'integer', 'effective_date' => 'date', 'end_date' => 'date', 'is_retrospective' => 'boolean', 'submitted_at' => 'datetime', 'approved_at' => 'datetime', 'quote_payload' => 'array', ]; public function items(): HasMany { return $this->hasMany(CourierQuoteChangeItem::class, 'quote_change_id')->orderBy('position'); } public function events(): HasMany { return $this->hasMany(CourierQuoteChangeEvent::class, 'quote_change_id')->orderBy('created_at'); } public function version(): HasOne { return $this->hasOne(CourierQuoteVersion::class, 'source_change_id'); } public function stockEntry(): HasOne { return $this->hasOne(CourierStockQuoteEntry::class, 'source_change_id'); } /** 按完整报价结构提交的变价(快递入驻后的后台变价 / 重新报价)。 */ /** 执行期间文字,如「2026-10-12 至 2026-10-15(临时)」或「2026-10-01 起」。 */ public function periodLabel(): string { return $this->end_date !== null ? $this->effective_date?->toDateString() . ' 至 ' . $this->end_date->toDateString() . '(临时)' : $this->effective_date?->toDateString() . ' 起'; } public function hasQuotePayload(): bool { return is_array($this->quote_payload) && $this->quote_payload !== []; } public function isStockQuote(): bool { return $this->change_type === '存量报价' && is_numeric(data_get($this->quote_payload, 'stock_quote_entry_id')); } public function isEditable(): bool { return in_array($this->status, [self::STATUS_DRAFT, self::STATUS_RETURNED], true); } public function isRetrospective(): bool { return (bool) $this->is_retrospective; } public function recalculationStatusLabel(): string { return match ($this->recalculation_status) { self::RECALCULATION_NOT_REQUIRED => '无需追溯', self::RECALCULATION_PENDING => '待追溯核算', self::RECALCULATION_BLOCKED => '核算受阻', default => $this->recalculation_status, }; } public function statusLabel(): string { return match ($this->status) { self::STATUS_DRAFT => '草稿', self::STATUS_PENDING_REVIEW => '待审核', self::STATUS_RETURNED => '已退回', self::STATUS_APPROVED => '已审核', default => $this->status, }; } }