CaiWuXiTong/app/Models/Business/CourierQuoteChange.php
limeng 9a25db91cc feat(报价管理): 存量报价整本批量录入及签署原图归档 (#346)
保留各家工作表报价原文、公式、独立执行日期及签署原件;审核后按执行日期管理版本。33项测试、336项断言通过。生产业务迁移已获明确授权,服务器私有备份已完成并逐条校验。
2026-10-16 14:56:44 +08:00

109 lines
3.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Models\Business;
use App\Abstracts\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
class CourierQuoteChange extends Model
{
public const STATUS_DRAFT = 'draft';
public const STATUS_PENDING_REVIEW = 'pending_review';
public const STATUS_RETURNED = 'returned';
public const STATUS_APPROVED = 'approved';
public const RECALCULATION_NOT_REQUIRED = 'not_required';
public const RECALCULATION_PENDING = 'pending';
public const RECALCULATION_BLOCKED = 'blocked';
protected $table = 'business_courier_quote_changes';
protected $fillable = [
'company_id', 'number', 'source_quote_id', 'source_sheet_name', 'carrier_name', 'quote_type',
'change_type', 'status', 'effective_date', 'end_date', 'is_retrospective', 'recalculation_status',
'recalculation_note', 'summary', 'created_by', 'submitted_by', 'submitted_at', 'approved_by',
'approved_at', 'new_quote_version_id', 'quote_payload', 'proposed_values_json',
];
protected $casts = [
'company_id' => '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,
};
}
}