From 18c28c4f1a639b9c11cff311d3822a8069b310a3 Mon Sep 17 00:00:00 2001 From: limeng <1131177064@qq.com> Date: Thu, 15 Oct 2026 16:56:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BF=AB=E9=80=92=E8=B5=84=E6=96=99?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=E5=90=88=E5=90=8C=E7=94=B2=E4=B9=99=E6=96=B9?= =?UTF-8?q?=E5=B9=B6=E8=81=94=E5=8A=A8=E5=8D=8F=E8=AE=AE=E7=AD=BE=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Business/Pages.php | 23 +++++++++++- docs/上游业务镜像清单.md | 2 +- .../CourierInformationMirrorRepository.php | 36 ++++++++++++++++++- .../agreement-signing.blade.php | 25 +++++++++++++ .../courier-information.blade.php | 6 ++-- .../Business/AgreementSigningPageTest.php | 8 ++++- .../Business/CourierInformationPageTest.php | 26 ++++++++++++++ ...CourierInformationMirrorRepositoryTest.php | 35 +++++++++++++++++- 8 files changed, 154 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/Business/Pages.php b/app/Http/Controllers/Business/Pages.php index 438930de..7543fed6 100644 --- a/app/Http/Controllers/Business/Pages.php +++ b/app/Http/Controllers/Business/Pages.php @@ -2257,6 +2257,7 @@ class Pages extends Controller $receiptStats = null; $agreementCourierNames = $this->agreementCourierNames($page['slug'] ?? null); $agreementCourierAccounts = $this->agreementCourierAccounts($page['slug'] ?? null, $agreementCourierNames); + $agreementCourierContractParties = $this->agreementCourierContractParties($page['slug'] ?? null, $agreementCourierNames); $agreementSupplierOptions = $this->agreementSupplierOptions($page['slug'] ?? null); // 内部流转报表读取共享业务镜像中由工作簿导入的数据集,不走上游只读查询。 @@ -2335,6 +2336,7 @@ class Pages extends Controller 'agreementSubjects' => $this->agreementSubjects($page['slug']), 'agreementCourierNames' => $agreementCourierNames, 'agreementCourierAccounts' => $agreementCourierAccounts, + 'agreementCourierContractParties' => $agreementCourierContractParties, 'agreementSupplierOptions' => $agreementSupplierOptions, 'agreementQuoteVersions' => $this->agreementQuoteVersions($page['slug']), 'inventoryWarehouseMappings' => $inventoryWarehouseMappings, @@ -2396,6 +2398,7 @@ class Pages extends Controller 'agreementSubjects' => $this->agreementSubjects($page['slug'] ?? null), 'agreementCourierNames' => $agreementCourierNames, 'agreementCourierAccounts' => $agreementCourierAccounts, + 'agreementCourierContractParties' => $agreementCourierContractParties, 'agreementSupplierOptions' => $agreementSupplierOptions, 'agreementQuoteVersions' => $this->agreementQuoteVersions($page['slug'] ?? null), 'inventoryWarehouseMappings' => $inventoryWarehouseMappings, @@ -2854,6 +2857,22 @@ class Pages extends Controller return $accounts; } + /** @return array */ + protected function agreementCourierContractParties(?string $page, Collection $courierNames): array + { + if ($page !== 'agreement-signing') { + return []; + } + + try { + return $this->courierInformation->contractPartiesByName($courierNames->values()->all()); + } catch (Throwable $exception) { + report($exception); + + return []; + } + } + protected function agreementTasks(?string $page): Collection|\Illuminate\Contracts\Pagination\LengthAwarePaginator { if ($page !== 'agreement-signing') { @@ -6483,7 +6502,7 @@ class Pages extends Controller fputcsv($csv, [ 'ID', '快递公司代码', '快递公司名称', '外部编码', '杉橙快递代码', '运费打款方式', '是否启用', '可达服务', '是否快运', '自动寻号', '配货单号寻号', '数量拆单', '重量0寻号', - '停运时间', '合同开始时间', '合同结束时间', '联系人', '联系电话', '自定义1', '自定义2', '扣款方式', + '停运时间', '合同主体', '合同开始时间', '合同结束时间', '签订公司', '联系人', '联系电话', '自定义1', '自定义2', '扣款方式', '体积0寻号', '手工单号', '解密', '电子签章经办人', '最后修改', '入驻单号', '入驻状态', '入驻主体', ...array_map(static fn (string $field): string => \App\Models\Business\CourierOnboarding::PROFILE_FIELDS[$field][0], \App\Business\CourierProfileData::APPENDED_PROFILE_FIELDS), @@ -6524,8 +6543,10 @@ class Pages extends Controller $bool($row->skucountsplitsgn ?? null), $bool($row->weight0sgn ?? null), $date($row->stopdate ?? null), + $this->csvText($row->tradebody ?? null), $date($row->tradebtime ?? null), $date($row->tradeetime ?? null), + $this->csvText($row->signcom ?? null), $this->csvText($row->linker ?? null), $this->csvText($row->linkmobile ?? null), $this->csvText($row->undefined1 ?? null), diff --git a/docs/上游业务镜像清单.md b/docs/上游业务镜像清单.md index 587ff703..09ed3ee6 100644 --- a/docs/上游业务镜像清单.md +++ b/docs/上游业务镜像清单.md @@ -76,7 +76,7 @@ | 库存与货款对账 | `dbo.pm_boardInventoryDetail_snapshot`、`dbo.fys_supplierGoods_sttlement_purchase`、`dbo.fys_supplierGoods_sttlement_sale`、`dbo.pm_purchaseIn` | | 采购单价 | `dbo.jst_purchase`、`dbo.jst_purchaseItem`(受控字段联表镜像,不复制其他采购业务字段) | | 工作平台采购价格 | `dbo.pm_priceAdjustment`(`Id` 稳定键;按 `skuCode` 匹配 `jst_sku.sku_id`,页面取当前已生效的最新 `purchasePrice` / `effectTime`) | -| 快递资料 | `dbo.wp_express`、`dbo.wp_express_expNet`、`dbo.wp_express_account`、`dbo.wp_express_extension` | +| 快递资料 | `dbo.wp_express`、`dbo.wp_express_expNet`、`dbo.wp_express_account`、`dbo.wp_express_extension`。`wp_express.tradebody` 为合作合同乙方(合同主体),`signcom` 为甲方(签订公司),主资料列表与导出读取这两个原始镜像字段。协议签署选择快递后按确切名称带入唯一乙方主体,缺失或同名主体冲突时保留空值并提示核对,不以快递简称替代,也不改写已签归档合同。 | | 聚水潭小额打款工单 | `dbo.jst_workOrderInfo`(稳定键 `Id`、增量字段 `updateTime`)与 `dbo.jst_small_payment_order_map`(稳定键 `woNo`、增量字段 `updated_at`) | | 拼多多货款账户账单 | `dbo.jst_originalBillInfo`(固定 `channel = PinduoduoImport`,镜像 `js_jst_pdd_receiving_bill_rows`) | | 得物完整账户账单 | 聚胜算平台原始账单(新)XLSX(受控导入 `dewu_settlement_bill_rows`;保留得物、退货退款订单、扣减其他费用明细) | diff --git a/modules/EcommerceFinance/Repositories/CourierInformationMirrorRepository.php b/modules/EcommerceFinance/Repositories/CourierInformationMirrorRepository.php index 9549b98a..9eb5b19f 100644 --- a/modules/EcommerceFinance/Repositories/CourierInformationMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/CourierInformationMirrorRepository.php @@ -309,6 +309,40 @@ class CourierInformationMirrorRepository ->all(); } + /** + * 工作平台合同主体为乙方、签订公司为甲方;同名但主体不唯一时不猜选。 + * + * @param list $expnames + * @return array + */ + public function contractPartiesByName(array $expnames): array + { + if (! $this->ready() || $expnames === []) { + return []; + } + + return $this->connection->table($this->dataset()->targetTable()) + ->select(['expname', 'tradebody', 'signcom']) + ->whereIn('expname', $expnames) + ->where(static fn (Builder $query) => $query->whereNull('is_delete')->orWhere('is_delete', '<>', 1)) + ->get() + ->groupBy(static fn ($row): string => trim((string) $row->expname)) + ->map(static function ($rows): array { + $subjects = static fn (string $field) => $rows->pluck($field) + ->map(static fn ($value): string => trim((string) $value)) + ->filter(static fn (string $value): bool => $value !== '') + ->unique()->values(); + $partyB = $subjects('tradebody'); + $partyA = $subjects('signcom'); + + return [ + 'party_b' => $partyB->count() === 1 ? $partyB->first() : '', + 'party_a' => $partyA->count() === 1 ? $partyA->first() : '', + 'ambiguous' => $partyB->count() > 1, + ]; + })->all(); + } + /** * 快递资料操作日志。 * @return array{data:list,total:int} @@ -366,7 +400,7 @@ class CourierInformationMirrorRepository $query = $this->connection->table($this->dataset()->targetTable())->select([ 'Id', 'expcode', 'expname', 'outcode', 'scexpcode', 'status', 'paymethod', 'addvalidsgn', 'kuaiyunsgn', 'autonosgn', 'packnosgn', 'skucountsplitsgn', - 'weight0sgn', 'stopdate', 'tradebtime', 'tradeetime', 'signcom', 'signmode', + 'weight0sgn', 'stopdate', 'tradebody', 'tradebtime', 'tradeetime', 'signcom', 'signmode', 'linker', 'linkmobile', 'paytype', 'undefined1', 'undefined2', 'undefined3', 'volume0sgn', 'handnosgn', 'decryptsgn', 'pj1sgn', 'undefinedtype', 'undefined4', 'undefined5', 'dzqzjbr', 'guid', 'is_delete', 'exp_properties', diff --git a/resources/views/business/pages/courier-payables/agreement-signing.blade.php b/resources/views/business/pages/courier-payables/agreement-signing.blade.php index 8830b2d3..b7ebe95c 100644 --- a/resources/views/business/pages/courier-payables/agreement-signing.blade.php +++ b/resources/views/business/pages/courier-payables/agreement-signing.blade.php @@ -3,6 +3,7 @@ @php($agreementSubjects = $agreementSubjects ?? collect()) @php($agreementCourierNames = collect($agreementCourierNames ?? [])) @php($agreementCourierAccounts = $agreementCourierAccounts ?? []) +@php($agreementCourierContractParties = $agreementCourierContractParties ?? []) @php($agreementSupplierOptions = $agreementSupplierOptions ?? []) @php($supplierContractTemplates = \App\Support\SupplierCooperationTemplates::TEMPLATES) @php($supplierContractRequestKey = (string) \Illuminate\Support\Str::uuid()) @@ -1618,6 +1619,7 @@ +
@@ -2346,6 +2348,9 @@ return { value: option.value, account: option.dataset.esignAccount || '' }; }) : []; var originalCourierOptions = courierOptions; + var courierContractParties = @json($agreementCourierContractParties); + var courierContractPartiesHelp = root.querySelector('[data-courier-contract-parties]'); + var selectedContractCourier = ''; var selectedSupplierId = ''; var visibleCourierIndexes = []; var activeCourierIndex = -1; @@ -2852,6 +2857,8 @@ var supplier = type === 'supplier'; if (type !== currentPartnerType) { closeCourierOptions(); + selectedContractCourier = ''; + courierContractPartiesHelp.hidden = true; courierSelect.value = ''; courierSearch.value = ''; esignAccountInput.value = ''; @@ -2957,6 +2964,23 @@ refreshPreview(); } + function syncCourierContractParties() { + var name = currentPartnerType === 'courier' ? courierSelect.value : ''; + var parties = Object.prototype.hasOwnProperty.call(courierContractParties, name) ? courierContractParties[name] : null; + var partyB = parties && !parties.ambiguous ? parties.party_b : ''; + if (selectedContractCourier !== name) { + selectedContractCourier = name; + var partyBInput = form.querySelector('[name="cooperation_party_b_name"]'); + if (partyBInput && currentPartnerType === 'courier') partyBInput.value = partyB; + } + courierContractPartiesHelp.hidden = name === ''; + if (name !== '') { + courierContractPartiesHelp.textContent = parties && parties.ambiguous + ? '同名快递对应多个合同主体,未自动填入乙方,请核对快递资料后手工填写。' + : '合同主体(乙方):' + (partyB || '未维护,请手工填写') + ';签订公司(甲方):' + (parties && parties.party_a || '未维护或不唯一,请核对') + '。乙方可按本次合同修改,甲方请核对我方签署主体。'; + } + } + function syncEsignAccount() { if (!courierSelect || !esignAccountInput) { return; @@ -2983,6 +3007,7 @@ } else { selectedSupplierId = ''; } + syncCourierContractParties(); if (account !== '') { esignAccountInput.value = account; diff --git a/resources/views/business/pages/courier-payables/courier-information.blade.php b/resources/views/business/pages/courier-payables/courier-information.blade.php index b9646822..76d5cff8 100644 --- a/resources/views/business/pages/courier-payables/courier-information.blade.php +++ b/resources/views/business/pages/courier-payables/courier-information.blade.php @@ -504,7 +504,7 @@ ID快递公司代码快递公司名称外部编码杉橙快递代码运费打款方式 是否启用可达服务是否快运自动寻号配货单号寻号数量拆单重量0寻号 - 停运时间合同开始时间合同结束时间联系人联系电话自定义1自定义2扣款方式 + 停运时间合同主体合同开始时间合同结束时间签订公司联系人联系电话自定义1自定义2扣款方式 体积0寻号手工单号解密电子签章经办人最后修改 入驻单号入驻状态ERP 开通入驻主体@foreach (\App\Business\CourierProfileData::APPENDED_PROFILE_FIELDS as $profileField){{ \App\Models\Business\CourierOnboarding::PROFILE_FIELDS[$profileField][0] }}@endforeach 证照生效报价 @@ -541,8 +541,10 @@ {{ $onlyOnboarding ? '-' : $bool($row->skucountsplitsgn ?? null) }} {{ $onlyOnboarding ? '-' : $bool($row->weight0sgn ?? null) }} {{ $date($row->stopdate ?? null) }} + {{ filled($row->tradebody ?? null) ? $row->tradebody : '-' }} {{ $date($row->tradebtime ?? null) }} {{ $date($row->tradeetime ?? null) }} + {{ filled($row->signcom ?? null) ? $row->signcom : '-' }} {{ $row->linker ?? '-' }} {{ $row->linkmobile ?? '-' }} {{ $row->undefined1 ?? '-' }} @@ -556,7 +558,7 @@ @include('business.pages.courier-payables.partials.courier-onboarding-cells', ['info' => $row->_info ?? null, 'platformName' => $row->expname ?? null, 'platformCode' => $row->expcode ?? null]) @empty - {{ $courierError ? '数据暂时不可用。' : '当前筛选条件下没有快递资料。' }} + {{ $courierError ? '数据暂时不可用。' : '当前筛选条件下没有快递资料。' }} @endforelse diff --git a/tests/Feature/Business/AgreementSigningPageTest.php b/tests/Feature/Business/AgreementSigningPageTest.php index b09f8ef4..4fe9bc94 100644 --- a/tests/Feature/Business/AgreementSigningPageTest.php +++ b/tests/Feature/Business/AgreementSigningPageTest.php @@ -154,9 +154,12 @@ class AgreementSigningPageTest extends FeatureTestCase ->once() ->with(['顺丰', '韵达']) ->andReturn(['顺丰' => '13800000001']); + $courierInformation->shouldReceive('contractPartiesByName')->once()->with(['顺丰', '韵达'])->andReturn([ + '顺丰' => ['party_b' => '乙方顺丰物流有限公司', 'party_a' => '甲方商贸有限公司', 'ambiguous' => false], + ]); $this->app->instance(CourierInformationMirrorRepository::class, $courierInformation); - $this->loginAs() + $response = $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'courier-payables', 'page' => 'agreement-signing', @@ -167,7 +170,10 @@ class AgreementSigningPageTest extends FeatureTestCase ->assertSee('data-courier-select required', false) ->assertSee('', false) ->assertSee('', false) + ->assertSee('data-courier-contract-parties', false) ->assertDontSee('