Services/Helpers sind entfernt, API/Frontend angepasst, Tests auf Paddle umgestellt. Außerdem wurde die CSP gestrafft und Stripe‑Texte in den Abandoned‑Checkout‑Mails ersetzt.
128 lines
3.2 KiB
PHP
128 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
class CheckoutSession extends Model
|
|
{
|
|
use HasFactory;
|
|
use HasUuids;
|
|
use SoftDeletes;
|
|
|
|
public const STATUS_DRAFT = 'draft';
|
|
|
|
public const STATUS_AWAITING_METHOD = 'awaiting_payment_method';
|
|
|
|
public const STATUS_REQUIRES_CUSTOMER_ACTION = 'requires_customer_action';
|
|
|
|
public const STATUS_PROCESSING = 'processing';
|
|
|
|
public const STATUS_COMPLETED = 'completed';
|
|
|
|
public const STATUS_FAILED = 'failed';
|
|
|
|
public const STATUS_CANCELLED = 'cancelled';
|
|
|
|
public const PROVIDER_NONE = 'none';
|
|
|
|
public const PROVIDER_PADDLE = 'paddle';
|
|
|
|
public const PROVIDER_FREE = 'free';
|
|
|
|
/**
|
|
* The attributes that aren't mass assignable.
|
|
*/
|
|
protected $guarded = [];
|
|
|
|
/**
|
|
* Indicates if the IDs are auto-incrementing.
|
|
*/
|
|
public $incrementing = false;
|
|
|
|
/**
|
|
* The data type of the primary key.
|
|
*/
|
|
protected $keyType = 'string';
|
|
|
|
/**
|
|
* The attributes that should be cast.
|
|
*/
|
|
protected $casts = [
|
|
'package_snapshot' => 'array',
|
|
'status_history' => 'array',
|
|
'provider_metadata' => 'array',
|
|
'coupon_snapshot' => 'array',
|
|
'discount_breakdown' => 'array',
|
|
'expires_at' => 'datetime',
|
|
'completed_at' => 'datetime',
|
|
'accepted_terms_at' => 'datetime',
|
|
'accepted_privacy_at' => 'datetime',
|
|
'accepted_withdrawal_notice_at' => 'datetime',
|
|
'digital_content_waiver_at' => 'datetime',
|
|
'amount_subtotal' => 'decimal:2',
|
|
'amount_total' => 'decimal:2',
|
|
'amount_discount' => 'decimal:2',
|
|
];
|
|
|
|
/**
|
|
* Default attributes.
|
|
*/
|
|
protected $attributes = [
|
|
'status_history' => '[]',
|
|
'package_snapshot' => '[]',
|
|
'provider_metadata' => '[]',
|
|
'coupon_snapshot' => '[]',
|
|
'discount_breakdown' => '[]',
|
|
];
|
|
|
|
public function user(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class);
|
|
}
|
|
|
|
public function tenant(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Tenant::class);
|
|
}
|
|
|
|
public function package(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Package::class)->withTrashed();
|
|
}
|
|
|
|
public function coupon(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Coupon::class);
|
|
}
|
|
|
|
public function scopeActive($query)
|
|
{
|
|
return $query->whereNotIn('status', [
|
|
self::STATUS_COMPLETED,
|
|
self::STATUS_CANCELLED,
|
|
])->where(function ($inner) {
|
|
$inner->whereNull('expires_at')->orWhere('expires_at', '>', now());
|
|
});
|
|
}
|
|
|
|
public function scopeByProviderId($query, string $providerField, string $value)
|
|
{
|
|
return $query->where($providerField, $value);
|
|
}
|
|
|
|
public function isExpired(): bool
|
|
{
|
|
return (bool) $this->expires_at && $this->expires_at->isPast();
|
|
}
|
|
|
|
public function requiresCustomerAction(): bool
|
|
{
|
|
return $this->status === self::STATUS_REQUIRES_CUSTOMER_ACTION;
|
|
}
|
|
}
|