- 引入 alibabacloud/dysmsapi-20170525 依赖,集成阿里云短信服务 - 将短信验证码从6位改为4位,优化用户体验 - 添加聚水潭商品按时间范围同步功能,支持分页拉取 - 增强Cron任务异常处理,添加错误日志记录 - 修复系统附件服务中图片路径处理逻辑 - 更新阿里云SDK相关组件至最新版本 - 添加think-trace调试扩展,便于问题排查 - 优化跨域中间件,使用str_contains替代strpos
147 lines
6.3 KiB
PHP
147 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace app\haichao\sync;
|
|
|
|
use app\haichao\HaichaoJstServices;
|
|
use app\jobs\product\ProductSyncErp;
|
|
use app\services\product\product\StoreProductServices;
|
|
use app\services\product\sku\StoreProductAttrServices;
|
|
use app\services\product\sku\StoreProductAttrValueServices;
|
|
use app\services\store\SystemStoreServices;
|
|
use crmeb\exceptions\AdminException;
|
|
use think\facade\Log;
|
|
use Exception;
|
|
|
|
class JstStorkSync extends HaichaoJstServices
|
|
{
|
|
public function syncStorkFromInneropenErp(): void
|
|
{
|
|
$startAt = microtime(true);
|
|
/** @var StoreProductAttrValueServices $storeProductAttrValueServices */
|
|
$storeProductAttrValueServices = app()->make(StoreProductAttrValueServices::class);
|
|
Log::info('jst.stork.sync.start');
|
|
$codes = [];
|
|
$spuIds = [];
|
|
$codeIdMap = [];
|
|
$codeProductIdMap = [];
|
|
foreach ($storeProductAttrValueServices->getList(['is_del' => 0]) as $item) {
|
|
$code = (string)($item['code'] ?? '');
|
|
if ($code !== '') {
|
|
$codes[] = $code;
|
|
$id = (int)($item['id'] ?? 0);
|
|
if ($id > 0) {
|
|
$codeIdMap[$code] = $id;
|
|
}
|
|
$productId = (int)($item['product_id'] ?? 0);
|
|
if ($productId > 0) {
|
|
$spuIds[$productId] = 1;
|
|
$codeProductIdMap[$code] = $productId;
|
|
}
|
|
}
|
|
}
|
|
$codes = array_values(array_unique($codes));
|
|
Log::info('jst.stork.sync.request_stats ' . json_encode([
|
|
'spu_count' => count($spuIds),
|
|
'sku_count' => count($codes),
|
|
], JSON_UNESCAPED_UNICODE));
|
|
|
|
$pullStats = [];
|
|
$productStockMap = [];
|
|
foreach ($this->getInneropenStockAndDetailList($codes, $pullStats) as $product) {
|
|
$productStockMap[(string)$product['item_code']] = (int)$product['stock'];
|
|
}
|
|
$respSpuIds = [];
|
|
foreach (array_keys($productStockMap) as $code) {
|
|
if (isset($codeProductIdMap[$code])) {
|
|
$respSpuIds[$codeProductIdMap[$code]] = 1;
|
|
}
|
|
}
|
|
Log::info('jst.stork.sync.response_stats ' . json_encode([
|
|
'spu_count' => count($respSpuIds),
|
|
'sku_count' => count($productStockMap),
|
|
'api_call_count' => (int)($pullStats['api_call_count'] ?? 0),
|
|
'api_resp_row_count' => (int)($pullStats['api_resp_row_count'] ?? 0),
|
|
], JSON_UNESCAPED_UNICODE));
|
|
|
|
$updatedSkuCount = 0;
|
|
$notFoundSkuCount = 0;
|
|
foreach ($productStockMap as $code => $stock) {
|
|
$id = (int)($codeIdMap[$code] ?? 0);
|
|
if ($id < 1) {
|
|
$notFoundSkuCount++;
|
|
continue;
|
|
}
|
|
$storeProductAttrValueServices->update($id, [
|
|
'stock' => $stock,
|
|
'sum_stock' => $stock
|
|
]);
|
|
$updatedSkuCount++;
|
|
}
|
|
Log::info('jst.stork.sync.finish ' . json_encode([
|
|
'requested_spu_count' => count($spuIds),
|
|
'requested_sku_count' => count($codes),
|
|
'response_spu_count' => count($respSpuIds),
|
|
'response_sku_count' => count($productStockMap),
|
|
'update_sku_count' => $updatedSkuCount,
|
|
'not_found_sku_count' => $notFoundSkuCount,
|
|
'duration_ms' => (int)round((microtime(true) - $startAt) * 1000),
|
|
], JSON_UNESCAPED_UNICODE));
|
|
}
|
|
|
|
public function syncStockFromErp(array $ids): bool
|
|
{
|
|
try {
|
|
/** @var StoreProductServices $storeProductServices */
|
|
$storeProductServices = app()->make(StoreProductServices::class);
|
|
/** @var StoreProductAttrValueServices $storeProductAttrValueServices */
|
|
$storeProductAttrValueServices = app()->make(StoreProductAttrValueServices::class);
|
|
$list = $storeProductAttrValueServices->getSkuArray(['product_id' => $ids, 'type' => 0], 'code', 'id');
|
|
$values = array_filter(array_values($list));
|
|
if (empty($values)) {
|
|
throw new AdminException('没有符合同步库存的商品');
|
|
}
|
|
$skuData = $skuMap = [];
|
|
$basic = 20;
|
|
$num = count($values);
|
|
$rate = ceil($num / $basic);
|
|
for ($i = 0; $i < $rate; $i++) {
|
|
$code = array_slice($values, $i * $basic, $basic);
|
|
$codeStr = implode(',', $code);
|
|
$result = $this->getStork($codeStr)['data'];
|
|
if (!empty($result['inventorys'])) {
|
|
foreach ($result['inventorys'] as $inventory) {
|
|
$skuMap[$inventory['sku_id']] = $inventory['qty'] - $inventory['order_lock'];
|
|
}
|
|
}
|
|
}
|
|
if (!empty($skuMap)) {
|
|
foreach ($skuMap as $key => $item) {
|
|
if ($id = array_search($key, $list)) {
|
|
$skuData[] = ['id' => $id, 'stock' => $item, 'sum_stock' => $item];
|
|
}
|
|
}
|
|
}
|
|
$storeProductServices->transaction(function () use ($ids, $skuData, $storeProductAttrValueServices, $storeProductServices) {
|
|
$storeProductAttrValueServices->saveAll($skuData);
|
|
$productData = $storeProductAttrValueServices->getProductStockByValues($ids);
|
|
$storeProductServices->saveAll($productData);
|
|
});
|
|
/** @var SystemStoreServices $systemStoreServices */
|
|
$systemStoreServices = app()->make(SystemStoreServices::class);
|
|
$systemStoreList = $systemStoreServices->getErpStore([['erp_shop_id', '>', 0]]);
|
|
if (!empty($systemStoreList)) {
|
|
foreach ($systemStoreList as $store) {
|
|
ProductSyncErp::dispatchDo('syncBranchProductStock', [$ids[0], $skuMap, $store['id']]);
|
|
}
|
|
}
|
|
$storeProductServices->cacheTag()->clear();
|
|
/** @var StoreProductAttrServices $attrService */
|
|
$attrService = app()->make(StoreProductAttrServices::class);
|
|
$attrService->cacheTag()->clear();
|
|
} catch (Exception $e) {
|
|
Log::error('jst.stork.sync.error ' . $e->getMessage());
|
|
}
|
|
return true;
|
|
}
|
|
}
|