'integer', 'effective_date' => 'date', 'end_date' => 'date', 'voided_at' => 'datetime', 'billing_structure' => 'array', 'billing_rows' => 'array', ]; /** 短期(临时)变价:有结束日期,到期后回到原来的长期报价。 */ public function isTemporary(): bool { return $this->end_date !== null && !$this->change?->isStockQuote(); } /** 某一天是否在这一版的执行期间内(开始 ≤ 日期 ≤ 结束;长期版本没有结束)。 */ public function coversDate(\DateTimeInterface $date): bool { $day = \Illuminate\Support\Carbon::instance($date)->startOfDay(); return $this->effective_date !== null && $this->effective_date->lte($day) && ($this->end_date === null || $this->end_date->gte($day)); } /** 执行期间文字,如「2026-10-12 至 2026-10-15(临时)」或「2026-10-01 起」。 */ public function periodLabel(): string { if ($this->effective_date === null) { return '-'; } return $this->end_date !== null ? $this->effective_date->toDateString() . ' 至 ' . $this->end_date->toDateString() . ($this->isTemporary() ? '(临时)' : '') : $this->effective_date->toDateString() . ' 起'; } /** 是否已有可用于运费核算的结构化计费规则。 */ public function hasBillingRules(): bool { $mode = $this->billing_structure['mode'] ?? null; return is_string($mode) && $mode !== 'other' && is_array($this->billing_rows) && $this->billing_rows !== []; } public function isVoided(): bool { return $this->status === self::STATUS_VOIDED; } /** 存量报价审核后按执行日期生效,不以补签或历史签署资料为前置条件。 */ public function isApprovedStockQuote(): bool { return $this->status === self::STATUS_APPROVED && $this->change?->status === CourierQuoteChange::STATUS_APPROVED && $this->change->isStockQuote(); } public function signatureLabel(): string { return $this->isApprovedStockQuote() && !in_array($this->signature_status, ['历史签署资料已归档', '已签署并归档'], true) ? '存量报价,审核生效(无需签章)' : (string) $this->signature_status; } public function change(): BelongsTo { return $this->belongsTo(CourierQuoteChange::class, 'source_change_id'); } public function signature(): HasOne { return $this->hasOne(CourierQuoteSignature::class, 'quote_version_id'); } }