'integer', 'source_variant_id' => 'integer', 'source_purchase_id' => 'integer', 'starts_at' => 'datetime', 'expires_at' => 'datetime', 'used_at' => 'datetime', 'scanner_user_id' => 'integer', 'user_id' => 'integer', ]; } /** @return BelongsTo */ public function tenant(): BelongsTo { return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo'); } /** @return BelongsTo */ public function user(): BelongsTo { return $this->belongsTo(User::class); } /** @return BelongsTo */ public function scannerUser(): BelongsTo { return $this->belongsTo(User::class, 'scanner_user_id'); } /** @return BelongsTo */ public function sourcePurchase(): BelongsTo { return $this->belongsTo(Purchase::class, 'source_purchase_id'); } /** @return BelongsTo */ public function sourceCatalogItem(): BelongsTo { return $this->belongsTo(CatalogItem::class, 'source_catalog_item_id'); } /** @return BelongsTo */ public function sourceVariant(): BelongsTo { return $this->belongsTo(Variant::class, 'source_variant_id'); } public function isValid(): bool { $now = now(); $startsAt = $this->getEffectiveStartsAt(); $expiresAt = $this->getEffectiveExpiresAt(); return $this->used_at === null && ($startsAt === null || $startsAt->lessThanOrEqualTo($now)) && ($expiresAt === null || $expiresAt->greaterThan($now)); } public function getIsValidAttribute(): bool { return $this->isValid(); } public function getIsExpiredAttribute(): bool { $expiresAt = $this->getEffectiveExpiresAt(); return $this->used_at === null && $expiresAt !== null && $expiresAt->lessThanOrEqualTo(now()); } public function getIsUsedAttribute(): bool { return $this->used_at !== null; } public function getEffectiveStartsAt(): ?CarbonInterface { return $this->sourceVariant?->getMinimumUseDate() ?? $this->starts_at; } public function getEffectiveExpiresAt(): ?CarbonInterface { return $this->sourceVariant?->getMaximumUseDate() ?? $this->expires_at; } }