保留各家工作表报价原文、公式、独立执行日期及签署原件;审核后按执行日期管理版本。33项测试、336项断言通过。生产业务迁移已获明确授权,服务器私有备份已完成并逐条校验。
109 lines
3.6 KiB
PHP
109 lines
3.6 KiB
PHP
<?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,
|
||
};
|
||
}
|
||
}
|