## 任务占用与边界 - 任务名称:附加费类型字典自维护 - 实际开发者:zhoushengchen - 目标结果:在快递附加费报价维护页支持附加费类型的新增、启用/停用;新增报价仅可选择启用类型,历史报价保留原类型。 - 预计修改路径:附加费类型 Repository、Model、Controller、报价 Repository/Controller、页面、管理路由、类型表迁移和专项测试。 - 将写入的公共契约:business.courier-surcharge.types.store、business.courier-surcharge.types.status、business_courier_surcharge_types。 - 仅复用、不修改的公共契约:business.pages.show、business.courier-surcharge.store。 - 明确不修改的范围:上游数据库、业务镜像、七牛、生产配置和无关页面。 ## 开工碰撞检查 - [x] 已检查最新 main 和所有远程任务分支 - [x] 已运行 scripts/codex-task-preflight.ps1 - [x] 未发现与其他远程任务的实际写入重叠 ## 实际改动 - 新增附加费类型字典及公司范围隔离。 - 新增类型管理弹窗、创建接口、启用/停用接口。 - 报价表单和后端校验动态读取启用类型;筛选仍可查看全部类型。 - 默认初始化原有 11 种类型,并增加“进仓费”。 - 增加幂等增量迁移,补齐已执行建表迁移环境中的“进仓费”。 ## 验证证据 - tests/Feature/Business/CourierSurchargePageTest.php:6 个用例、60 个断言通过。 - 相关 PHP 文件语法检查通过。 - business.courier-surcharge 路由共 5 条,路由检查通过。 - git diff --check 通过。 - 本地共享系统库现状:类型表已存在,当前公司有 11 个旧类型;增量迁移待执行。 ## 风险检查 - 未提交 .env、密码、Token、私钥、真实财务数据、生产日志或构建产物。 - 前端遵循 DESIGN.md 的 VIP 黑金令牌。 - 数据库影响:仅新增类型表(若环境尚未建表)或幂等补充“进仓费”,不删除、不覆盖已有类型。 - 回滚:类型字典不做物理删除;迁移 down 保持空操作以保护业务引用。 - 已获得本次“合并 PR 并执行类型表迁移”的明确授权;迁移目标为本机当前连接的团队系统数据库,不涉及生产部署。 ## 合并前复查 - [x] 已重新 fetch 远程引用并再次运行碰撞检查 - [x] 已逐文件审核 origin/main...任务分支完整 diff - [ ] PR 创建后移除 WIP 并执行 Squash merge - [ ] 合并后验证 main、执行迁移并验证页面 Reviewed-on: http://git.1080p.hk/WuYongJie/CaiWuXiTong/pulls/98
89 lines
3.4 KiB
PHP
89 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Business;
|
|
|
|
use App\Business\CourierSurchargeQuoteRepository;
|
|
use App\Models\Business\CourierSurchargeQuote;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
|
|
class CourierSurchargeQuotes extends Controller
|
|
{
|
|
public function __construct(private readonly CourierSurchargeQuoteRepository $quotes)
|
|
{
|
|
$this->middleware('auth');
|
|
$this->middleware('company.identify');
|
|
$this->middleware('business.page:courier-payables,courier-surcharge');
|
|
}
|
|
|
|
public function store(Request $request): RedirectResponse
|
|
{
|
|
abort_unless($this->quotes->ready(), 503, '附加费报价数据表尚未完成迁移,请联系管理员。');
|
|
|
|
$this->quotes->create($this->validated($request), (int) user_id());
|
|
|
|
return $this->redirect()->with('success', '报价规则已新增并保存。');
|
|
}
|
|
|
|
public function update(Request $request, CourierSurchargeQuote $quote): RedirectResponse
|
|
{
|
|
$this->ensureCompany($quote);
|
|
abort_unless($this->quotes->ready(), 503, '附加费报价数据表尚未完成迁移,请联系管理员。');
|
|
|
|
$this->quotes->update($quote, $this->validated($request), (int) user_id());
|
|
|
|
return $this->redirect()->with('success', '报价规则已更新并保存。');
|
|
}
|
|
|
|
public function setStatus(Request $request, CourierSurchargeQuote $quote): RedirectResponse
|
|
{
|
|
$this->ensureCompany($quote);
|
|
abort_unless($this->quotes->ready(), 503, '附加费报价数据表尚未完成迁移,请联系管理员。');
|
|
|
|
$status = $request->validate([
|
|
'status' => ['required', 'in:' . CourierSurchargeQuote::STATUS_ACTIVE . ',' . CourierSurchargeQuote::STATUS_INACTIVE],
|
|
])['status'];
|
|
$this->quotes->setStatus($quote, $status, (int) user_id());
|
|
|
|
return $this->redirect()->with('success', '报价规则状态已更新。');
|
|
}
|
|
|
|
/** @return array<string,mixed> */
|
|
private function validated(Request $request): array
|
|
{
|
|
$data = $request->validate([
|
|
'courier' => ['required', 'string', 'max:191'],
|
|
'scope' => ['required', 'in:' . implode(',', CourierSurchargeQuoteRepository::SCOPES)],
|
|
'reconciler' => ['required', 'string', 'max:100'],
|
|
'types' => ['required', 'array', 'min:1', 'max:50'],
|
|
'types.*' => ['string', 'in:' . implode(',', $this->quotes->activeTypeNames())],
|
|
'mode' => ['required', 'in:' . implode(',', CourierSurchargeQuoteRepository::MODES)],
|
|
'standard' => ['required', 'string', 'max:2000'],
|
|
'condition' => ['required', 'string', 'max:2000'],
|
|
'effective_at' => ['required', 'date_format:Y-m-d'],
|
|
'remark' => ['nullable', 'string', 'max:2000'],
|
|
]);
|
|
|
|
$data['courier'] = trim($data['courier']);
|
|
$data['reconciler'] = trim($data['reconciler']);
|
|
$data['types'] = array_values(array_unique($data['types']));
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function ensureCompany(CourierSurchargeQuote $quote): void
|
|
{
|
|
abort_unless((int) $quote->company_id === (int) company_id(), 404, '报价规则不存在。');
|
|
}
|
|
|
|
private function redirect(): RedirectResponse
|
|
{
|
|
return redirect()->route('business.pages.show', [
|
|
'company_id' => company_id() ?: 1,
|
|
'section' => 'courier-payables',
|
|
'page' => 'courier-surcharge',
|
|
]);
|
|
}
|
|
}
|