Compare commits
1 Commits
main
...
fix/shippi
| Author | SHA1 | Date | |
|---|---|---|---|
| c1be417d3f |
@ -135,6 +135,12 @@ class ShippingReplicaSynchronizer
|
||||
|
||||
/** @var array<string,string> 最近一次 loadViewItems 的 io_id => 视图店铺名(发货明细缺店铺时兜底) */
|
||||
private array $ioShop = [];
|
||||
|
||||
/** @var array<string,string> 最近一次 loadViewItems 的 io_id => 视图快递名称 expressName(工作平台显示的快递名称) */
|
||||
private array $ioExpress = [];
|
||||
|
||||
/** @var array<string,string> 最近一次 loadViewItems 的 io_id => 视图发货仓 wareHoursName(工作平台显示的仓库) */
|
||||
private array $ioWare = [];
|
||||
/** @var array<string,array{l_id:mixed,send_date:mixed,status:?string,online:bool}> 已查询订单元数据缓存 o_id=>字段 */
|
||||
private array $orderMetadata = [];
|
||||
|
||||
@ -489,6 +495,7 @@ class ShippingReplicaSynchronizer
|
||||
?? $this->ts($r['send_time'] ?? null) ?? $this->ts($r['jo_send'] ?? null);
|
||||
$pkg = $this->pkgFromExpress($r, $tracking, $shipTime);
|
||||
$pkg = $this->withOutboundCarrier($io, $r, $pkg, $pkgId);
|
||||
$pkg = $this->withViewCarrier($io, $pkg, $pkgId);
|
||||
$pkg['platform'] = $this->platformOf($io, $pkg['platform']);
|
||||
$pkg = $this->withViewAddr($io, $pkg);
|
||||
$total += $this->emitPackage($pkgId, $pkg, $items, $skus, $freight, $so, $tracking, $now);
|
||||
@ -705,6 +712,7 @@ class ShippingReplicaSynchronizer
|
||||
$pkg['platform'] = $this->platformOf($io, $pkg['platform']);
|
||||
$pkg = $this->withViewAddr($io, $pkg);
|
||||
$pkgId = self::AUTOSHIP_OFFSET + (int) $oid;
|
||||
$pkg = $this->withViewCarrier($io, $pkg, $pkgId);
|
||||
$total += $this->emitPackage($pkgId, $pkg, $items, $skus, $freight, $so, $tracking, $now, true);
|
||||
}
|
||||
unset($rows, $byOid, $bySo, $dws, $skus, $freight);
|
||||
@ -900,8 +908,11 @@ class ShippingReplicaSynchronizer
|
||||
}
|
||||
$pkg = $this->pkgFromOutbound($r, $tracking !== '' ? $tracking : null, $this->ts($r['io_date'] ?? null), $h, $so);
|
||||
$pkg = $this->withViewAddr($io, $pkg);
|
||||
$pkg = $this->withViewCarrier($io, $pkg, self::OUTBOUND_OFFSET + (int) $io);
|
||||
if (trim((string) ($pkg['express_name1'] ?? '')) === self::NO_LOGISTICS) {
|
||||
if (empty($this->ioWare[$io])) {
|
||||
$pkg['warehouse_name'] = self::NO_LOGISTICS_WAREHOUSE;
|
||||
}
|
||||
$virtualEmitted++;
|
||||
}
|
||||
$total += $this->emitPackage(self::OUTBOUND_OFFSET + (int) $io, $pkg, $viewItems[$io], $skus, $freight, $so, $tracking !== '' ? $tracking : null, $now, true);
|
||||
@ -1030,7 +1041,7 @@ class ShippingReplicaSynchronizer
|
||||
private function loadViewHeads(array $ioIds): array
|
||||
{
|
||||
$out = [];
|
||||
foreach (array_chunk(array_values(array_unique(array_filter($ioIds))), 800) as $chunk) {
|
||||
foreach (array_chunk(array_values(array_unique(array_filter($ioIds))), 300) as $chunk) {
|
||||
if ($chunk === []) {
|
||||
continue;
|
||||
}
|
||||
@ -1260,6 +1271,26 @@ class ShippingReplicaSynchronizer
|
||||
return $pkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作平台的快递名称/仓库即发货数据视图的 expressName / wareHoursName(抽样 14/14 一致):
|
||||
* 视图有值时以视图为准;视图无该出库单时保留出库单/发货明细推断的值。
|
||||
*/
|
||||
private function withViewCarrier(string $io, array $pkg, int $pkgId): array
|
||||
{
|
||||
if ($io === '') {
|
||||
return $pkg;
|
||||
}
|
||||
if (! empty($this->ioExpress[$io])) {
|
||||
$pkg['express_name1'] = $this->ioExpress[$io];
|
||||
}
|
||||
if (! empty($this->ioWare[$io])) {
|
||||
$pkg['warehouse_name'] = $this->ioWare[$io];
|
||||
unset($this->pendingWarehouse[$pkgId]);
|
||||
}
|
||||
|
||||
return $pkg;
|
||||
}
|
||||
|
||||
private function wmsName(string $wms): ?string
|
||||
{
|
||||
if (empty($this->wmsNames[$wms])) {
|
||||
@ -1723,12 +1754,15 @@ class ShippingReplicaSynchronizer
|
||||
$this->ioSite = [];
|
||||
$this->ioAddr = [];
|
||||
$this->ioShop = [];
|
||||
foreach (array_chunk(array_values(array_unique(array_filter($ioIds))), 800) as $chunk) {
|
||||
$this->ioExpress = [];
|
||||
$this->ioWare = [];
|
||||
// 发货数据视图是计算视图,IN 列表过长时副本库容易超时:按 300 个出库单一批
|
||||
foreach (array_chunk(array_values(array_unique(array_filter($ioIds))), 300) as $chunk) {
|
||||
if ($chunk === []) {
|
||||
continue;
|
||||
}
|
||||
$ph = implode(',', array_fill(0, count($chunk), '?'));
|
||||
$sql = 'SELECT io_id, sku_ids, qty, type, sku_name, shop_i_id, wareHoursName, l, w, h, volume, weight, supplier_name, shop_site, shop_name, receiver_state, receiver_city, receiver_district FROM '
|
||||
$sql = 'SELECT io_id, sku_ids, qty, type, sku_name, shop_i_id, wareHoursName, expressName, l, w, h, volume, weight, supplier_name, shop_site, shop_name, receiver_state, receiver_city, receiver_district FROM '
|
||||
. self::VIEW . " WHERE io_id IN ({$ph})";
|
||||
foreach ($this->selectWithReconnect($sql, $chunk) as $r) {
|
||||
$io = (string) ($r['io_id'] ?? '');
|
||||
@ -1738,6 +1772,12 @@ class ShippingReplicaSynchronizer
|
||||
if ($io !== '' && ! isset($this->ioShop[$io]) && trim((string) ($r['shop_name'] ?? '')) !== '') {
|
||||
$this->ioShop[$io] = trim((string) $r['shop_name']);
|
||||
}
|
||||
if ($io !== '' && ! isset($this->ioExpress[$io]) && trim((string) ($r['expressName'] ?? '')) !== '') {
|
||||
$this->ioExpress[$io] = trim((string) $r['expressName']);
|
||||
}
|
||||
if ($io !== '' && ! isset($this->ioWare[$io]) && trim((string) ($r['wareHoursName'] ?? '')) !== '') {
|
||||
$this->ioWare[$io] = trim((string) $r['wareHoursName']);
|
||||
}
|
||||
if ($io !== '') {
|
||||
foreach (['st' => 'receiver_state', 'ci' => 'receiver_city', 'di' => 'receiver_district'] as $ak => $ac) {
|
||||
$av = trim((string) ($r[$ac] ?? ''));
|
||||
|
||||
@ -1271,6 +1271,50 @@ class ShippingReplicaSynchronizerTest extends TestCase
|
||||
$this->assertSame(1, $skipped->getValue($sync));
|
||||
}
|
||||
|
||||
public function test_view_express_and_warehouse_override_inferred_carrier_like_the_work_platform(): void
|
||||
{
|
||||
$chunks = [];
|
||||
$upstream = $this->createMock(UpstreamReadOnlyQuery::class);
|
||||
$upstream->method('select')->willReturnCallback(function (string $sql, array $bindings) use (&$chunks): array {
|
||||
$this->assertStringContainsString('expressName', $sql);
|
||||
$chunks[] = count($bindings);
|
||||
|
||||
return [
|
||||
['io_id' => '12', 'sku_ids' => 'a', 'qty' => 1, 'type' => 0, 'volume' => null, 'expressName' => '常州德邦', 'wareHoursName' => '工厂-河南千优代发仓'],
|
||||
['io_id' => '12', 'sku_ids' => 'b', 'qty' => 1, 'type' => 0, 'volume' => null, 'expressName' => '', 'wareHoursName' => ''],
|
||||
['io_id' => '41', 'sku_ids' => 'c', 'qty' => 1, 'type' => 0, 'volume' => null, 'expressName' => '无需物流', 'wareHoursName' => '简尚-自动发货仓'],
|
||||
];
|
||||
});
|
||||
$factory = $this->createMock(UpstreamReadOnlyQueryFactory::class);
|
||||
$factory->method('forSource')->willReturn($upstream);
|
||||
$sync = new ShippingReplicaSynchronizer($factory);
|
||||
$load = new \ReflectionMethod($sync, 'loadViewItems');
|
||||
$load->setAccessible(true);
|
||||
$load->invoke($sync, array_merge(['12', '41', '99'], array_map('strval', range(1000, 1400))));
|
||||
$this->assertSame([300, 104], $chunks); // 视图按 300 个出库单一批
|
||||
|
||||
$pending = new \ReflectionProperty($sync, 'pendingWarehouse');
|
||||
$pending->setAccessible(true);
|
||||
$pending->setValue($sync, [1 => '14138566', 2 => '15170678']);
|
||||
$carrier = new \ReflectionMethod($sync, 'withViewCarrier');
|
||||
$carrier->setAccessible(true);
|
||||
|
||||
// 视图有值:快递名称、仓库按视图(工作平台口径),不再按发货主体回填
|
||||
$pkg = $carrier->invoke($sync, '12', ['express_name1' => '崔桥顺丰干配', 'warehouse_name' => '工厂-河北浩浦代发仓'], 1);
|
||||
$this->assertSame('常州德邦', $pkg['express_name1']);
|
||||
$this->assertSame('工厂-河南千优代发仓', $pkg['warehouse_name']);
|
||||
$this->assertArrayNotHasKey(1, $pending->getValue($sync));
|
||||
|
||||
$none = $carrier->invoke($sync, '41', ['express_name1' => '无需物流', 'warehouse_name' => '工厂-山东恒思代发仓'], 4);
|
||||
$this->assertSame('简尚-自动发货仓', $none['warehouse_name']);
|
||||
|
||||
// 视图没有该出库单:保留出库单/发货明细推断值和待回填仓库
|
||||
$keep = $carrier->invoke($sync, '99', ['express_name1' => '外采快递', 'warehouse_name' => '常州简尚家居有限公司'], 2);
|
||||
$this->assertSame('外采快递', $keep['express_name1']);
|
||||
$this->assertSame('常州简尚家居有限公司', $keep['warehouse_name']);
|
||||
$this->assertSame('15170678', $pending->getValue($sync)[2]);
|
||||
}
|
||||
|
||||
private function setScanBatchLimit(ShippingReplicaSynchronizer $synchronizer, string $property, int $limit): void
|
||||
{
|
||||
$reflection = new \ReflectionProperty($synchronizer, $property);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user