CaiWuXiTong/modules/EcommerceFinance/Repositories/SupplierAccessoryFreightRepository.php

47 lines
2.7 KiB
PHP

<?php
namespace Modules\EcommerceFinance\Repositories;
use Modules\EcommerceFinance\Services\AccessoryReshipMatcher;
use Modules\EcommerceFinance\Services\BusinessMirrorDatasetRegistry;
use Modules\EcommerceFinance\Services\SupplierAccessoryFreightMatcher;
use RuntimeException;
/** 只读现有共享镜像,不使用发货行的历史供应商字段代替商品资料。 */
class SupplierAccessoryFreightRepository
{
public function __construct(
private readonly ShippingOrderRepository $shipping,
private readonly BusinessMirrorDatasetRegistry $datasets,
private readonly GenericBusinessMirrorRepository $mirror,
private readonly SupplierAccessoryFreightMatcher $matcher,
) {}
public function rows(string $month): \Generator
{
$productDataset = $this->datasets->get(ProductCatalogMirrorRepository::DATASET_KEY);
$supplierDataset = $this->datasets->get(SupplierManagementMirrorRepository::DATASET);
if (!$this->mirror->ready($productDataset) || !$this->mirror->ready($supplierDataset)) {
throw new RuntimeException('商品或供应商资料尚未完成首次同步');
}
$db = $this->mirror->connection();
// 供应商档案数量较小,一次读取,批量商品查询避免逐单访问数据库。
$suppliers = $db->table($supplierDataset->targetTable())->get(['scmname', 'linkerprovience'])
->groupBy(static fn ($row) => trim((string) $row->scmname))
->map(static fn ($group) => $group->map(static fn ($row) => (array) $row)->all());
$start = \Carbon\Carbon::createFromFormat('!Y-m', $month);
foreach ($this->shipping->accessoryFreightBatches($start->format('Y-m-d'), $start->copy()->addMonth()->format('Y-m-d')) as $batch) {
$barcodes = array_values(array_unique(array_filter(array_map(static fn ($row) => AccessoryReshipMatcher::barcode((string) ($row['barcode'] ?? '')), $batch), static fn ($value) => $value !== '')));
$products = $db->table($productDataset->targetTable())->where('sku_type', 'normal')->whereIn('sku_id', $barcodes)
->get(['sku_id', 'name', 'supplier_name'])->groupBy(static fn ($row) => trim((string) $row->sku_id))
->map(static fn ($group) => $group->map(static fn ($row) => (array) $row)->all());
foreach ($batch as $row) {
$barcode = AccessoryReshipMatcher::barcode((string) ($row['barcode'] ?? ''));
$candidates = $products->get($barcode, []);
$supplierName = trim((string) ($candidates[0]['supplier_name'] ?? ''));
yield $this->matcher->match($row, $candidates, $suppliers->get($supplierName, []));
}
}
}
}