*/ use HasFactory; use SoftDeletes; public const STATUS_ISSUED = 'issued'; public const STATUS_REDEEMED = 'redeemed'; public const STATUS_REFUNDED = 'refunded'; public const STATUS_EXPIRED = 'expired'; protected $fillable = [ 'code', 'amount', 'currency', 'status', 'purchaser_email', 'recipient_email', 'recipient_name', 'message', 'paddle_transaction_id', 'paddle_checkout_id', 'paddle_price_id', 'coupon_id', 'expires_at', 'redeemed_at', 'refunded_at', 'recipient_delivery_scheduled_at', 'recipient_delivery_sent_at', 'metadata', ]; protected $casts = [ 'amount' => 'decimal:2', 'expires_at' => 'datetime', 'redeemed_at' => 'datetime', 'refunded_at' => 'datetime', 'recipient_delivery_scheduled_at' => 'datetime', 'recipient_delivery_sent_at' => 'datetime', 'metadata' => 'array', ]; protected static function booted(): void { static::saving(function (self $voucher): void { if ($voucher->code) { $voucher->code = Str::upper($voucher->code); } if ($voucher->currency) { $voucher->currency = Str::upper($voucher->currency); } }); } public function coupon(): BelongsTo { return $this->belongsTo(Coupon::class); } public function isRedeemed(): bool { return $this->status === self::STATUS_REDEEMED; } public function isRefunded(): bool { return $this->status === self::STATUS_REFUNDED; } public function isExpired(): bool { return $this->status === self::STATUS_EXPIRED || ($this->expires_at && $this->expires_at->isPast()); } public function canBeRedeemed(): bool { return ! $this->isRedeemed() && ! $this->isRefunded() && ! $this->isExpired(); } public function canBeRefunded(): bool { return ! $this->isRedeemed() && ! $this->isRefunded(); } }