- 新增配置表 business_supplier_bookkeeping_configs(+ 操作日志表),迁移时导入财务提供的 209 家存量配置 - 记账方式:正常记账 / 仅代发仓发错货记账 / 不记账,支持生效期;配置页支持新增、编辑、删除恢复、Excel 导入导出 - 扣款判定:厂家记账按供应商配置,仅正常记账扣款;仓库记账仅订单发货仓库为代发仓且二级原因含“仓库发错货”时作为厂家扣款项,其余不扣 - 未配置/生效期外显示待配置,多供应商判定不一致显示待确认,均不计入扣款金额 - 明细页新增厂家扣款判定筛选、扣款工单数与扣款金额指标、导出列 涉及:数据库迁移(新建配置表并写入存量配置)、金额汇总展示;不涉及上游写入和权限模型。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JouFR6TJ7vGscRJanYScEo
101 lines
4.5 KiB
PHP
101 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Business;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use Illuminate\Validation\Rule as ValidationRule;
|
|
use Modules\EcommerceFinance\Services\SupplierBookkeepingConfigImporter;
|
|
use Modules\EcommerceFinance\Services\SupplierBookkeepingConfigStore;
|
|
use Modules\EcommerceFinance\Services\SupplierBookkeepingDeductionRule as Rule;
|
|
use Modules\EcommerceFinance\View\SupplierBookkeepingConfigPageData;
|
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
|
|
|
class SupplierBookkeepingConfigs extends Controller
|
|
{
|
|
public function __construct(private readonly SupplierBookkeepingConfigStore $store) {}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
$this->store->save($this->validated($request), $this->actor());
|
|
|
|
return $this->back('厂家记账配置已新增,厂家记账明细按新配置重新判定。');
|
|
}
|
|
|
|
public function update(Request $request, int $configId)
|
|
{
|
|
$this->store->save($this->validated($request), $this->actor(), $configId);
|
|
|
|
return $this->back('厂家记账配置已更新,厂家记账明细按新配置重新判定。');
|
|
}
|
|
|
|
public function destroy(int $configId)
|
|
{
|
|
$this->store->changeDeleted($configId, true, $this->actor());
|
|
|
|
return $this->back('配置已删除,该供应商的厂家记账将显示为“待配置”。');
|
|
}
|
|
|
|
public function restore(int $configId)
|
|
{
|
|
$this->store->changeDeleted($configId, false, $this->actor());
|
|
|
|
return $this->back('厂家记账配置已恢复。');
|
|
}
|
|
|
|
public function import(Request $request, SupplierBookkeepingConfigImporter $importer)
|
|
{
|
|
$request->validate(['file' => ['required', 'file', 'mimes:xlsx', 'max:10240']]);
|
|
$path = $request->file('file')->getRealPath();
|
|
$result = $this->store->import($importer->read($path), $this->actor(), hash_file('sha256', $path));
|
|
|
|
return $this->back("导入完成:新增{$result['added']}条,更新{$result['updated']}条,未变化{$result['skipped']}条。");
|
|
}
|
|
|
|
public function export(SupplierBookkeepingConfigPageData $data)
|
|
{
|
|
$rows = $this->store->filtered($data->filters())->get();
|
|
$book = new Spreadsheet();
|
|
$sheet = $book->getActiveSheet();
|
|
$sheet->setTitle('厂家记账配置');
|
|
$sheet->fromArray([['供应商', '记账方式', '生效开始日期', '生效结束日期', '原始说明', '创建人', '更新时间', '删除状态']]);
|
|
foreach ($rows as $index => $row) {
|
|
$values = [$row->supplier_name, Rule::MODES[$row->mode] ?? $row->mode, $row->effective_from, $row->effective_to, $row->source_text, $row->creator, $row->updated_at, $row->deleted_at ? '已删除' : '正常'];
|
|
foreach ($values as $column => $value) {
|
|
$sheet->setCellValueExplicit([$column + 1, $index + 2], (string) $value, DataType::TYPE_STRING);
|
|
}
|
|
}
|
|
foreach (['A' => 24, 'B' => 20, 'C' => 14, 'D' => 14, 'E' => 44, 'F' => 16, 'G' => 20, 'H' => 10] as $column => $width) {
|
|
$sheet->getColumnDimension($column)->setWidth($width);
|
|
}
|
|
$sheet->freezePane('A2');
|
|
|
|
return response()->streamDownload(function () use ($book): void {
|
|
try { (new Xlsx($book))->save('php://output'); } finally { $book->disconnectWorksheets(); }
|
|
}, '厂家记账配置.xlsx', ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
|
|
}
|
|
|
|
private function validated(Request $request): array
|
|
{
|
|
return $request->validate([
|
|
'supplier_name' => ['required', 'string', 'max:191'],
|
|
'mode' => ['required', ValidationRule::in(array_keys(Rule::MODES))],
|
|
'effective_from' => ['nullable', 'date_format:Y-m-d'],
|
|
'effective_to' => ['nullable', 'date_format:Y-m-d', 'after_or_equal:effective_from'],
|
|
'source_text' => ['nullable', 'string', 'max:255'],
|
|
], [], ['supplier_name' => '供应商', 'mode' => '记账方式', 'effective_from' => '生效开始日期', 'effective_to' => '生效结束日期', 'source_text' => '备注']);
|
|
}
|
|
|
|
private function actor(): string
|
|
{
|
|
return mb_substr((string) user()->name, 0, 191);
|
|
}
|
|
|
|
private function back(string $message)
|
|
{
|
|
return redirect()->route('business.pages.show', ['section' => 'supplier-payables', 'page' => 'manufacturer-bookkeeping', 'bk_view' => 'config'])->with('bookkeeping_config_message', $message);
|
|
}
|
|
}
|