修正进销存报表商品编码匹配 #222
@ -317,11 +317,19 @@ class ThirdPartyWarehouseStorageMirrorRepository
|
||||
->where('generation', $inventoryGeneration)
|
||||
->where('qty', '!=', 0)
|
||||
->whereNotNull('sku_code')->where('sku_code', '!=', '')
|
||||
->select(['wms_co_id', 'wh_id', 'sku_code', 'captured_at'])
|
||||
->select(['wms_co_id', 'wh_id', 'sku_code as inventory_sku_code', 'captured_at'])
|
||||
->selectRaw('qty AS snapshot_qty');
|
||||
$candidates = $this->connection->query()->fromSub($inventoryDimensions, 'pairs')
|
||||
->select(['pairs.wms_co_id', 'pairs.sku_code', 'pairs.wh_id']);
|
||||
$this->containsFilter($candidates, 'pairs.sku_code', $filters['product_code'] ?? '');
|
||||
->joinSub($latestProducts, 'latest_product', 'latest_product.sku_id', '=', 'pairs.inventory_sku_code')
|
||||
->join(self::PRODUCT_TABLE . ' as s', function ($join): void {
|
||||
$join->on('s.sku_id', '=', 'latest_product.sku_id')
|
||||
->on('s.autoid', '=', 'latest_product.autoid');
|
||||
})
|
||||
->select([
|
||||
'pairs.wms_co_id', 'pairs.wh_id', 'pairs.inventory_sku_code',
|
||||
's.sku_id as sku_code', 's.category',
|
||||
]);
|
||||
$this->containsFilter($candidates, 's.sku_id', $filters['product_code'] ?? '');
|
||||
$warehouseFilter = trim((string) ($filters['warehouse_provider'] ?? ''));
|
||||
if ($warehouseFilter !== '') {
|
||||
$warehouseIds = $this->connection->query()->fromSub(
|
||||
@ -336,17 +344,12 @@ class ThirdPartyWarehouseStorageMirrorRepository
|
||||
}
|
||||
$categoryFilter = trim((string) ($filters['category'] ?? ''));
|
||||
if ($categoryFilter !== '') {
|
||||
$categorySkus = $this->connection->table(self::PRODUCT_TABLE)
|
||||
->where('sku_type', 'normal')
|
||||
->whereNotNull('sku_id')->where('sku_id', '!=', '')
|
||||
->select('sku_id')->distinct();
|
||||
$this->containsFilter($categorySkus, 'category', $categoryFilter);
|
||||
$candidates->whereIn('pairs.sku_code', $categorySkus);
|
||||
$this->containsFilter($candidates, 's.category', $categoryFilter);
|
||||
}
|
||||
|
||||
$total = $includeTotal ? (clone $candidates)->count() : 0;
|
||||
$pagePairs = (clone $candidates)
|
||||
->orderBy('pairs.wms_co_id')->orderBy('pairs.wh_id')->orderBy('pairs.sku_code')
|
||||
->orderBy('pairs.wms_co_id')->orderBy('pairs.wh_id')->orderBy('s.sku_id')
|
||||
->forPage($page, $perPage);
|
||||
$pairRows = (clone $pagePairs)->get();
|
||||
if ($pairRows->isEmpty()) {
|
||||
@ -359,24 +362,25 @@ class ThirdPartyWarehouseStorageMirrorRepository
|
||||
}
|
||||
|
||||
$dimensionedPagePairs = $this->connection->query()->fromSub($pagePairs, 'pairs')
|
||||
->leftJoinSub($latestProducts, 'latest_product', 'latest_product.sku_id', '=', 'pairs.sku_code')
|
||||
->leftJoin(self::PRODUCT_TABLE . ' as s', function ($join): void {
|
||||
$join->on('s.sku_id', '=', 'latest_product.sku_id')
|
||||
->on('s.autoid', '=', 'latest_product.autoid');
|
||||
})
|
||||
->leftJoinSub($latestWarehouses, 'latest_warehouse', 'latest_warehouse.wms_co_id', '=', 'pairs.wms_co_id')
|
||||
->leftJoin(self::WAREHOUSE_TABLE . ' as w', function ($join): void {
|
||||
$join->on('w.wms_co_id', '=', 'latest_warehouse.wms_co_id')
|
||||
->on('w.Id', '=', 'latest_warehouse.Id');
|
||||
})
|
||||
->select(['pairs.wms_co_id', 'pairs.wh_id', 'pairs.sku_code', 's.category', 'w.name as warehouse_name']);
|
||||
->select([
|
||||
'pairs.wms_co_id', 'pairs.wh_id', 'pairs.inventory_sku_code',
|
||||
'pairs.sku_code', 'pairs.category', 'w.name as warehouse_name',
|
||||
]);
|
||||
$anchors = $this->connection->query()->fromSub($dimensionedPagePairs, 'pairs')
|
||||
->leftJoinSub(clone $inventoryDimensions, 'inventory', function ($join): void {
|
||||
$join->on('inventory.wms_co_id', '=', 'pairs.wms_co_id')
|
||||
->on('inventory.sku_code', '=', 'pairs.sku_code')
|
||||
->on('inventory.inventory_sku_code', '=', 'pairs.inventory_sku_code')
|
||||
->on('inventory.wh_id', '=', 'pairs.wh_id');
|
||||
})
|
||||
->select(['pairs.wms_co_id', 'pairs.wh_id', 'pairs.sku_code', 'pairs.category', 'pairs.warehouse_name'])
|
||||
->select([
|
||||
'pairs.wms_co_id', 'pairs.wh_id', 'pairs.inventory_sku_code',
|
||||
'pairs.sku_code', 'pairs.category', 'pairs.warehouse_name',
|
||||
])
|
||||
->selectRaw('COALESCE(inventory.snapshot_qty, 0) AS snapshot_qty')
|
||||
->selectRaw('COALESCE(inventory.captured_at, ?) AS snapshot_at', [$anchorAt]);
|
||||
|
||||
@ -384,9 +388,9 @@ class ThirdPartyWarehouseStorageMirrorRepository
|
||||
->where('h.occurred_at', '>=', $rangeStart)
|
||||
->where('h.occurred_at', '<', $rangeEnd)
|
||||
->whereIn('h.wms_co_id', $pairRows->pluck('wms_co_id')->unique()->values()->all())
|
||||
->whereIn('i.sku_code', $pairRows->pluck('sku_code')->unique()->values()->all())
|
||||
->whereIn('i.sku_code', $pairRows->pluck('inventory_sku_code')->unique()->values()->all())
|
||||
->select([
|
||||
'h.wms_co_id', 'h.io_type', 'h.occurred_at', 'i.sku_code',
|
||||
'h.wms_co_id', 'h.io_type', 'h.occurred_at', 'i.sku_code as inventory_sku_code',
|
||||
'i.qty as movement_qty', 'i.qty_type as movement_qty_type',
|
||||
])
|
||||
->selectRaw('COALESCE(NULLIF(h.wh_id, 0), 1) AS wh_id');
|
||||
@ -404,10 +408,11 @@ class ThirdPartyWarehouseStorageMirrorRepository
|
||||
->leftJoinSub($movements, 'mv', function ($join): void {
|
||||
$join->on('mv.wms_co_id', '=', 'a.wms_co_id')
|
||||
->on('mv.wh_id', '=', 'a.wh_id')
|
||||
->on('mv.sku_code', '=', 'a.sku_code');
|
||||
->on('mv.inventory_sku_code', '=', 'a.inventory_sku_code');
|
||||
})
|
||||
->groupBy([
|
||||
'a.wms_co_id', 'a.wh_id', 'a.sku_code', 'a.category', 'a.warehouse_name',
|
||||
'a.wms_co_id', 'a.wh_id', 'a.inventory_sku_code', 'a.sku_code',
|
||||
'a.category', 'a.warehouse_name',
|
||||
'a.snapshot_qty', 'a.snapshot_at',
|
||||
])
|
||||
->select(['a.wms_co_id', 'a.wh_id', 'a.sku_code', 'a.category', 'a.warehouse_name'])
|
||||
|
||||
@ -280,11 +280,12 @@ class ThirdPartyWarehouseStorageMirrorRepositoryTest extends TestCase
|
||||
$this->assertSame(-20.0, (float) $result['data'][0]->sales_out);
|
||||
}
|
||||
|
||||
public function test_inventory_report_excludes_zero_only_dirty_product_codes(): void
|
||||
public function test_inventory_report_uses_only_product_codes_matched_to_the_operations_replica_catalog(): void
|
||||
{
|
||||
$this->markReady();
|
||||
$this->insertProduct('SKU-STOCK');
|
||||
$this->insertInventory('SKU-STOCK', 2, '2026-09-01 00:00:00');
|
||||
$this->insertInventory('【商品描述不是商品编码】', 0, '2026-09-01 00:00:00');
|
||||
$this->insertInventory('LEGACY-CODE-NOT-IN-CATALOG', 7, '2026-09-01 00:00:00');
|
||||
|
||||
$result = $this->repository->paginateMonthlyInventoryReport([
|
||||
'month' => '2026-08',
|
||||
@ -296,7 +297,7 @@ class ThirdPartyWarehouseStorageMirrorRepositoryTest extends TestCase
|
||||
|
||||
$this->assertSame(1, $result['total']);
|
||||
$this->assertSame(['SKU-STOCK'], $codes);
|
||||
$this->assertNotContains('【商品描述不是商品编码】', $codes);
|
||||
$this->assertNotContains('LEGACY-CODE-NOT-IN-CATALOG', $codes);
|
||||
}
|
||||
|
||||
public function test_third_party_page_remains_ready_when_only_the_all_warehouse_dimension_is_missing(): void
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user