feat: subscriptions
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\BillingProductPurpose;
|
||||
use App\Enums\CreditProductType;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUlids;
|
||||
@@ -18,6 +19,7 @@ class CreditProduct extends Model
|
||||
'name',
|
||||
'description',
|
||||
'type',
|
||||
'purpose',
|
||||
'credits',
|
||||
'amount',
|
||||
'currency',
|
||||
@@ -51,6 +53,7 @@ class CreditProduct extends Model
|
||||
{
|
||||
return [
|
||||
'type' => CreditProductType::class,
|
||||
'purpose' => BillingProductPurpose::class,
|
||||
'credits' => 'integer',
|
||||
'amount' => 'integer',
|
||||
'is_active' => 'boolean',
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\IdentityVerificationStatus;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUlids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class IdentityVerificationRequest extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\IdentityVerificationRequestFactory> */
|
||||
use HasFactory, HasUlids;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'status',
|
||||
'document_disk',
|
||||
'document_path',
|
||||
'document_mime_type',
|
||||
'document_size',
|
||||
'submitted_at',
|
||||
'reviewed_at',
|
||||
'reviewed_by',
|
||||
'rejection_reason',
|
||||
'document_deleted_at',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'document_disk',
|
||||
'document_path',
|
||||
];
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function reviewer(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'reviewed_by');
|
||||
}
|
||||
|
||||
public function hasDocument(): bool
|
||||
{
|
||||
return filled($this->document_path) && $this->document_deleted_at === null;
|
||||
}
|
||||
|
||||
public function temporaryDocumentUrl(): ?string
|
||||
{
|
||||
if (! $this->hasDocument()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Storage::disk($this->document_disk)->temporaryUrl(
|
||||
$this->document_path,
|
||||
now()->addMinutes((int) config('billing.identity_verification.temporary_url_minutes', 5)),
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'status' => IdentityVerificationStatus::class,
|
||||
'submitted_at' => 'datetime',
|
||||
'reviewed_at' => 'datetime',
|
||||
'document_deleted_at' => 'datetime',
|
||||
'document_size' => 'integer',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,8 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
|
||||
'height',
|
||||
'bio',
|
||||
'account_verified_at',
|
||||
'certification_purchased_at',
|
||||
'trial_ends_at',
|
||||
'daily_calorie_goal',
|
||||
'daily_protein_goal',
|
||||
'daily_carbs_goal',
|
||||
@@ -82,6 +84,7 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'account_verified_at' => 'datetime',
|
||||
'certification_purchased_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'daily_calorie_goal' => 'integer',
|
||||
'daily_protein_goal' => 'float',
|
||||
@@ -129,6 +132,11 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
|
||||
return $this->hasMany(PaymentTransaction::class);
|
||||
}
|
||||
|
||||
public function identityVerificationRequest(): HasOne
|
||||
{
|
||||
return $this->hasOne(IdentityVerificationRequest::class);
|
||||
}
|
||||
|
||||
public function workouts(): HasMany
|
||||
{
|
||||
return $this->hasMany(WorkoutSessions::class);
|
||||
@@ -188,6 +196,25 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
|
||||
return $this->suspended_at !== null;
|
||||
}
|
||||
|
||||
public function canAnalyzeMeals(): bool
|
||||
{
|
||||
return $this->subscribed('default') || $this->onGenericTrial();
|
||||
}
|
||||
|
||||
public function analysisAccessLevel(): string
|
||||
{
|
||||
if ($this->subscribed('default')) {
|
||||
return 'subscribed';
|
||||
}
|
||||
|
||||
return $this->onGenericTrial() ? 'trial' : 'free';
|
||||
}
|
||||
|
||||
public function hasPurchasedCertification(): bool
|
||||
{
|
||||
return $this->certification_purchased_at !== null;
|
||||
}
|
||||
|
||||
public function routeNotificationForExpoPush(): array
|
||||
{
|
||||
return $this->deviceTokens()
|
||||
|
||||
Reference in New Issue
Block a user