AdjustmentStatus::class, 'category' => AdjustmentCategory::class, 'type' => AdjustmentType::class, 'recoverable' => 'boolean', 'rate' => RateCast::class, 'computation' => AdjustmentComputation::class, 'scope' => AdjustmentScope::class, 'start_date' => 'datetime', 'end_date' => 'datetime', 'paused_at' => 'datetime', 'paused_until' => 'datetime', 'archived_at' => 'datetime', ]; public function account(): BelongsTo { return $this->belongsTo(Account::class, 'account_id'); } public function offerings(): MorphToMany { return $this->morphedByMany(Offering::class, 'adjustmentable', 'adjustmentables'); } public function isSalesTax(): bool { return $this->category->isTax() && $this->type->isSales(); } public function isNonRecoverablePurchaseTax(): bool { return $this->category->isTax() && $this->type->isPurchase() && $this->recoverable === false; } public function isRecoverablePurchaseTax(): bool { return $this->category->isTax() && $this->type->isPurchase() && $this->recoverable === true; } public function isSalesDiscount(): bool { return $this->category->isDiscount() && $this->type->isSales(); } public function isPurchaseDiscount(): bool { return $this->category->isDiscount() && $this->type->isPurchase(); } public function canBePaused(): bool { return $this->status === AdjustmentStatus::Active; } public function canBeResumed(): bool { return $this->status === AdjustmentStatus::Paused; } public function canBeArchived(): bool { return $this->status !== AdjustmentStatus::Archived; } public function calculateNaturalStatus(): AdjustmentStatus { if ($this->start_date?->isFuture()) { return AdjustmentStatus::Upcoming; } if ($this->end_date?->isPast()) { return AdjustmentStatus::Expired; } return AdjustmentStatus::Active; } public function pause(?string $reason = null, ?\DateTime $untilDate = null): bool { if (! $this->canBePaused()) { return false; } return $this->update([ 'paused_at' => now(), 'paused_until' => $untilDate, 'status' => AdjustmentStatus::Paused, 'status_reason' => $reason, ]); } public function resume(): bool { if (! $this->canBeResumed()) { return false; } return $this->update([ 'paused_at' => null, 'paused_until' => null, 'status_reason' => null, 'status' => $this->calculateNaturalStatus(), ]); } public function archive(?string $reason = null): bool { if (! $this->canBeArchived()) { return false; } return $this->update([ 'status' => AdjustmentStatus::Archived, 'status_reason' => $reason, ]); } public function shouldAutoResume(): bool { return $this->status === AdjustmentStatus::Paused && $this->paused_until !== null && $this->paused_until->isPast(); } public function refreshStatus(): bool { // Don't automatically change archived or paused status if ($this->status === AdjustmentStatus::Archived || ($this->status === AdjustmentStatus::Paused && ! $this->shouldAutoResume())) { return false; } // Check if a paused adjustment should be auto-resumed if ($this->shouldAutoResume()) { return $this->resume(); } // Calculate natural status based on dates $naturalStatus = $this->calculateNaturalStatus(); // Only update if the status would change if ($this->status !== $naturalStatus) { return $this->update([ 'status' => $naturalStatus, ]); } return false; } protected static function newFactory(): Factory { return AdjustmentFactory::new(); } }