'decimal:2', 'fee' => 'decimal:2', 'net_amount' => 'decimal:2', 'refunded_amount' => 'decimal:2', 'gateway_response' => 'array', 'paid_at' => 'datetime', ]; // Relationships public function workspace(): BelongsTo { return $this->belongsTo(Workspace::class); } public function invoice(): BelongsTo { return $this->belongsTo(Invoice::class); } public function refunds(): HasMany { return $this->hasMany(Refund::class); } // Status helpers public function isPending(): bool { return $this->status === 'pending'; } public function isProcessing(): bool { return $this->status === 'processing'; } public function isSucceeded(): bool { return $this->status === 'succeeded'; } public function isFailed(): bool { return $this->status === 'failed'; } public function isRefunded(): bool { return $this->status === 'refunded'; } public function isPartiallyRefunded(): bool { return $this->status === 'partially_refunded'; } public function canRefund(): bool { return $this->isSucceeded() || $this->isPartiallyRefunded(); } public function isFullyRefunded(): bool { return $this->refunded_amount >= $this->amount; } public function getRefundableAmount(): float { return $this->amount - $this->refunded_amount; } // Actions public function markAsSucceeded(): void { $this->update(['status' => 'succeeded']); } public function markAsFailed(?string $reason = null): void { $this->update([ 'status' => 'failed', 'failure_reason' => $reason, ]); } public function recordRefund(float $amount): void { $newRefundedAmount = $this->refunded_amount + $amount; $status = $newRefundedAmount >= $this->amount ? 'refunded' : 'partially_refunded'; $this->update([ 'refunded_amount' => $newRefundedAmount, 'status' => $status, ]); } // Scopes public function scopeSucceeded($query) { return $query->where('status', 'succeeded'); } public function scopeForWorkspace($query, int $workspaceId) { return $query->where('workspace_id', $workspaceId); } public function scopeForGateway($query, string $gateway) { return $query->where('gateway', $gateway); } }