feat: 添加阿里云短信服务支持并优化验证码逻辑
- 引入 alibabacloud/dysmsapi-20170525 依赖,集成阿里云短信服务 - 将短信验证码从6位改为4位,优化用户体验 - 添加聚水潭商品按时间范围同步功能,支持分页拉取 - 增强Cron任务异常处理,添加错误日志记录 - 修复系统附件服务中图片路径处理逻辑 - 更新阿里云SDK相关组件至最新版本 - 添加think-trace调试扩展,便于问题排查 - 优化跨域中间件,使用str_contains替代strpos
This commit is contained in:
@@ -8,6 +8,7 @@ use app\services\product\sku\StoreProductAttrValueServices;
|
||||
use app\haichao\HaichaoJstServices;
|
||||
use crmeb\basic\BaseJobs;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\erp\Erp as erpServices;
|
||||
use crmeb\traits\QueueTrait;
|
||||
use think\facade\Log;
|
||||
|
||||
@@ -42,7 +43,7 @@ class ProductSyncErp extends BaseJobs
|
||||
}
|
||||
foreach ($attrs as $item) {
|
||||
if ($item['pic'] && strstr($item['pic'], 'http') === false) {
|
||||
$siteUrl = sys_config('site_url');
|
||||
$siteUrl = app()->make(\crmeb\services\SystemConfigService::class)->get('site_url');
|
||||
$item['pic'] = $siteUrl . $item['pic'];
|
||||
}
|
||||
|
||||
@@ -119,10 +120,18 @@ class ProductSyncErp extends BaseJobs
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function productFromErp($spuArr, int $supplierId = 0)
|
||||
public function productFromErp($spuArr, int $supplierId = 0, string $traceId = '')
|
||||
{
|
||||
$stats = [
|
||||
'trace_id' => $traceId,
|
||||
'fetched' => 0,
|
||||
'created' => 0,
|
||||
'updated' => 0,
|
||||
'skipped' => 0,
|
||||
'failed' => 0,
|
||||
];
|
||||
try {
|
||||
Log::info('admin.manual.jst.product.sync.request', ['spu' => $spuArr]);
|
||||
Log::info('admin.manual.jst.product.sync.request', ['trace_id' => $traceId, 'spu' => $spuArr, 'supplier_id' => $supplierId]);
|
||||
$result = app()->make(HaichaoJstServices::class)->getProductListKuan($spuArr);
|
||||
$resultPreview = null;
|
||||
try {
|
||||
@@ -130,6 +139,7 @@ class ProductSyncErp extends BaseJobs
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
Log::info('admin.manual.jst.product.sync.api_result', [
|
||||
'trace_id' => $traceId,
|
||||
'spu' => $spuArr,
|
||||
'page_index' => $result['page_index'] ?? null,
|
||||
'page_count' => $result['page_count'] ?? null,
|
||||
@@ -137,178 +147,29 @@ class ProductSyncErp extends BaseJobs
|
||||
'result_preview' => $resultPreview,
|
||||
]);
|
||||
$productList = $result['datas'] ?? [];
|
||||
$productInfo = [];
|
||||
$stats['fetched'] = is_array($productList) ? count($productList) : 0;
|
||||
$stats = $this->mergeStats($stats, $this->processProductList($productList, $supplierId, $traceId, [
|
||||
'mode' => 'spu',
|
||||
'spu' => $spuArr,
|
||||
]));
|
||||
|
||||
/** @var StoreProductServices $productServices */
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
/** @var StoreProductAttrServices $productAttrServices */
|
||||
$productAttrServices = app()->make(StoreProductAttrServices::class);
|
||||
|
||||
Log::info('admin.manual.jst.product.sync.response', [
|
||||
'spu' => $spuArr,
|
||||
'datas_count' => is_array($productList) ? count($productList) : 0
|
||||
]);
|
||||
$relationSupplierId = $supplierId > 0 ? $supplierId : 0;
|
||||
foreach ($productList as $item) {
|
||||
Log::info('admin.manual.jst.product.sync.item', [
|
||||
'spu' => $spuArr,
|
||||
'i_id' => $item['i_id'] ?? '',
|
||||
'name' => $item['name'] ?? '',
|
||||
'sku_count' => isset($item['skus']) && is_array($item['skus']) ? count($item['skus']) : 0
|
||||
]);
|
||||
$skuRows = isset($item['skus']) && is_array($item['skus']) ? $item['skus'] : [];
|
||||
$salePrice = floatval($item['s_price'] ?? 0);
|
||||
if ($salePrice <= 0 && $skuRows) {
|
||||
$skuSalePrices = [];
|
||||
foreach ($skuRows as $skuRow) {
|
||||
if (isset($skuRow['sale_price']) && is_numeric($skuRow['sale_price'])) {
|
||||
$skuSalePrices[] = floatval($skuRow['sale_price']);
|
||||
}
|
||||
}
|
||||
if ($skuSalePrices) {
|
||||
$salePrice = min($skuSalePrices);
|
||||
}
|
||||
}
|
||||
$marketPrice = floatval($item['market_price'] ?? 0);
|
||||
if ($marketPrice <= 0 && $skuRows) {
|
||||
$skuMarketPrices = [];
|
||||
foreach ($skuRows as $skuRow) {
|
||||
if (isset($skuRow['market_price']) && is_numeric($skuRow['market_price'])) {
|
||||
$skuMarketPrices[] = floatval($skuRow['market_price']);
|
||||
}
|
||||
}
|
||||
if ($skuMarketPrices) {
|
||||
$marketPrice = max($skuMarketPrices);
|
||||
}
|
||||
}
|
||||
$costPrice = floatval($item['c_price'] ?? ($item['cost_price'] ?? 0));
|
||||
if ($costPrice <= 0 && $skuRows) {
|
||||
$skuCostPrices = [];
|
||||
foreach ($skuRows as $skuRow) {
|
||||
if (isset($skuRow['cost_price']) && is_numeric($skuRow['cost_price'])) {
|
||||
$skuCostPrices[] = floatval($skuRow['cost_price']);
|
||||
}
|
||||
}
|
||||
if ($skuCostPrices) {
|
||||
$costPrice = max($skuCostPrices);
|
||||
}
|
||||
}
|
||||
$pic = (string)($item['pic'] ?? ($skuRows[0]['pic'] ?? ''));
|
||||
$name = (string)($item['name'] ?? ($skuRows[0]['name'] ?? ''));
|
||||
$productInfo = [
|
||||
'image' => $pic,
|
||||
'slider_image' => json_encode([$pic]),
|
||||
'store_name' => $name,
|
||||
'store_info' => $name,
|
||||
'cate_id' => 0,
|
||||
'price' => $salePrice,
|
||||
'ot_price' => $marketPrice,
|
||||
'delivery_type' => '1,2,3',
|
||||
'freight' => 1,
|
||||
'is_show' => 0,
|
||||
'add_time' => time(),
|
||||
'cost' => $costPrice,
|
||||
'ficti' => 0,
|
||||
'spec_type' => 1,
|
||||
'code' => $item['i_id'],
|
||||
'type' => $relationSupplierId ? 2 : 0,
|
||||
'relation_id' => $relationSupplierId,
|
||||
];
|
||||
$detail = $details = $value = [];
|
||||
$usedSpecValues = [];
|
||||
foreach ($skuRows as $skuIndex => $items) {
|
||||
$specValue = trim((string)($items['properties_value'] ?? ''));
|
||||
if ($specValue === '') {
|
||||
$specValue = trim((string)($items['name'] ?? ''));
|
||||
}
|
||||
if ($specValue === '') {
|
||||
$specValue = '规格' . ($skuIndex + 1);
|
||||
}
|
||||
if (isset($usedSpecValues[$specValue])) {
|
||||
$specValue = $specValue . '-' . ($skuIndex + 1);
|
||||
}
|
||||
$usedSpecValues[$specValue] = 1;
|
||||
$detail[] = $specValue;
|
||||
$details[] = [
|
||||
'name' => $specValue,
|
||||
'select' => false
|
||||
];
|
||||
$skuCost = floatval($items['cost_price'] ?? $costPrice);
|
||||
$skuSettle = $relationSupplierId ? $skuCost : 0.0;
|
||||
$value[] = [
|
||||
'bar_code' => '',
|
||||
'brokerage' => 0,
|
||||
'brokerage_two' => 0,
|
||||
'code' => (string)($items['sku_id'] ?? ''),
|
||||
'settle_price' => $skuSettle,
|
||||
'cost' => $skuCost,
|
||||
'detail' => ['规格' => $specValue],
|
||||
'ot_price' => floatval($items['market_price'] ?? $marketPrice),
|
||||
'pic' => (string)$items['pic'],
|
||||
'price' => floatval($items['sale_price'] ?? $salePrice),
|
||||
'select' => true,
|
||||
'value1' => $specValue,
|
||||
'values' => $specValue,
|
||||
'vip_price' => 0,
|
||||
'volume' => 0,
|
||||
'weight' => 0,
|
||||
'stock' => 0,
|
||||
];
|
||||
}
|
||||
if (!$value) {
|
||||
$specValue = '默认';
|
||||
$detail[] = $specValue;
|
||||
$details[] = [
|
||||
'name' => $specValue,
|
||||
'select' => false
|
||||
];
|
||||
$defCost = floatval($item['c_price'] ?? 0);
|
||||
$defSettle = $relationSupplierId ? $defCost : 0.0;
|
||||
$value[] = [
|
||||
'bar_code' => '',
|
||||
'brokerage' => 0,
|
||||
'brokerage_two' => 0,
|
||||
'code' => (string)($item['i_id'] ?? ''),
|
||||
'settle_price' => $defSettle,
|
||||
'cost' => $defCost,
|
||||
'detail' => ['规格' => $specValue],
|
||||
'ot_price' => floatval($item['market_price'] ?? 0),
|
||||
'pic' => (string)($item['pic'] ?? ''),
|
||||
'price' => floatval($item['s_price'] ?? 0),
|
||||
'select' => true,
|
||||
'value1' => $specValue,
|
||||
'values' => $specValue,
|
||||
'vip_price' => 0,
|
||||
'volume' => 0,
|
||||
'weight' => 0,
|
||||
'stock' => 0,
|
||||
];
|
||||
}
|
||||
$pid = $productServices->value(['code' => $item['i_id']], 'id');
|
||||
$existed = !!$pid;
|
||||
if (!$pid) {
|
||||
$pid = $productServices->ErpProductSave($productInfo);
|
||||
}
|
||||
$attr = [[
|
||||
'value' => '规格',
|
||||
'detail' => $detail,
|
||||
'details' => $details,
|
||||
]];
|
||||
|
||||
$skuList = $productAttrServices->validateProductAttr($attr, $value, $pid, 0, 0, 0);
|
||||
$productAttrServices->saveProductAttr($skuList, $pid);
|
||||
Log::info('admin.manual.jst.product.sync.save', [
|
||||
'spu' => $spuArr,
|
||||
'product_id' => $pid,
|
||||
'existed' => $existed,
|
||||
'sku_saved_count' => isset($skuList['value']) && is_array($skuList['value']) ? count($skuList['value']) : 0
|
||||
]);
|
||||
}
|
||||
|
||||
//清除数据缓存
|
||||
$productServices->cacheTag()->clear();
|
||||
$productAttrServices->cacheTag()->clear();
|
||||
Log::info('admin.manual.jst.product.sync.finish', ['spu' => $spuArr, 'count' => count($productList)]);
|
||||
Log::info('admin.manual.jst.product.sync.finish', [
|
||||
'trace_id' => $traceId,
|
||||
'spu' => $spuArr,
|
||||
'count' => is_array($productList) ? count($productList) : 0,
|
||||
'created' => $stats['created'],
|
||||
'updated' => $stats['updated'],
|
||||
'skipped' => $stats['skipped'],
|
||||
'failed' => $stats['failed'],
|
||||
]);
|
||||
|
||||
return $stats;
|
||||
} catch (\Exception $e) {
|
||||
|
||||
response_log_write([
|
||||
@@ -316,11 +177,433 @@ class ProductSyncErp extends BaseJobs
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine()
|
||||
]);
|
||||
Log::error('admin.manual.jst.product.sync.error', ['spu' => $spuArr, 'message' => $e->getMessage()]);
|
||||
Log::error('admin.manual.jst.product.sync.error', ['trace_id' => $traceId, 'spu' => $spuArr, 'message' => $e->getMessage()]);
|
||||
$stats['failed']++;
|
||||
return $stats;
|
||||
}
|
||||
}
|
||||
|
||||
private function mergeStats(array $base, array $delta): array
|
||||
{
|
||||
foreach (['fetched', 'created', 'updated', 'skipped', 'failed'] as $key) {
|
||||
$base[$key] = (int)($base[$key] ?? 0) + (int)($delta[$key] ?? 0);
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
|
||||
return true;
|
||||
private function processProductList($productList, int $supplierId, string $traceId, array $context = []): array
|
||||
{
|
||||
$stats = [
|
||||
'fetched' => 0,
|
||||
'created' => 0,
|
||||
'updated' => 0,
|
||||
'skipped' => 0,
|
||||
'failed' => 0,
|
||||
];
|
||||
if (!is_array($productList)) {
|
||||
return $stats;
|
||||
}
|
||||
$stats['fetched'] = count($productList);
|
||||
$seenCodes = [];
|
||||
foreach ($productList as $item) {
|
||||
if (!is_array($item)) {
|
||||
$stats['skipped']++;
|
||||
continue;
|
||||
}
|
||||
$code = (string)($item['i_id'] ?? '');
|
||||
if ($code === '') {
|
||||
$stats['skipped']++;
|
||||
continue;
|
||||
}
|
||||
if (isset($seenCodes[$code])) {
|
||||
$stats['skipped']++;
|
||||
continue;
|
||||
}
|
||||
$seenCodes[$code] = 1;
|
||||
try {
|
||||
$save = $this->saveProductFromErpData($item, $supplierId);
|
||||
if (!empty($save['created'])) {
|
||||
$stats['created']++;
|
||||
} else {
|
||||
$stats['updated']++;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$stats['failed']++;
|
||||
Log::error('admin.manual.jst.product.sync.item.error', [
|
||||
'trace_id' => $traceId,
|
||||
'i_id' => $code,
|
||||
'message' => $e->getMessage(),
|
||||
'context' => $context,
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按时间范围同步商品
|
||||
* @param string $startTime
|
||||
* @param string $endTime
|
||||
* @param int $supplierId
|
||||
* @return bool
|
||||
*/
|
||||
public function syncProductByTime(string $startTime, string $endTime, int $supplierId = 0, string $traceId = '', string $mode = 'dispatch')
|
||||
{
|
||||
$startTs = strtotime($startTime);
|
||||
$endTs = strtotime($endTime);
|
||||
if ($startTs && $endTs) {
|
||||
$maxSeconds = 7 * 86400;
|
||||
if (($endTs - $startTs) > $maxSeconds) {
|
||||
Log::warning('admin.manual.jst.product.sync_by_time.range_too_large', [
|
||||
'trace_id' => $traceId,
|
||||
'start_time' => $startTime,
|
||||
'end_time' => $endTime,
|
||||
'range_seconds' => $endTs - $startTs,
|
||||
'max_seconds' => $maxSeconds,
|
||||
'supplier_id' => $supplierId,
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'error' => '时间范围不能超过7天',
|
||||
'trace_id' => $traceId,
|
||||
];
|
||||
}
|
||||
}
|
||||
try {
|
||||
$stats = [
|
||||
'ok' => true,
|
||||
'mode' => $mode,
|
||||
'trace_id' => $traceId,
|
||||
'start_time' => $startTime,
|
||||
'end_time' => $endTime,
|
||||
'page_count' => 1,
|
||||
'pages_processed' => 0,
|
||||
'fetched' => 0,
|
||||
'created' => 0,
|
||||
'updated' => 0,
|
||||
'skipped' => 0,
|
||||
'failed' => 0,
|
||||
];
|
||||
Log::info('admin.manual.jst.product.sync_by_time.start', [
|
||||
'trace_id' => $traceId,
|
||||
'start_time' => $startTime,
|
||||
'end_time' => $endTime,
|
||||
'supplier_id' => $supplierId
|
||||
]);
|
||||
$jstService = app()->make(HaichaoJstServices::class);
|
||||
$result = $jstService->getProductListByTime($startTime, $endTime, 1, 50);
|
||||
$pageCount = $result['page_count'] ?? 1;
|
||||
$stats['page_count'] = (int)$pageCount;
|
||||
Log::info('admin.manual.jst.product.sync_by_time.api_result', [
|
||||
'trace_id' => $traceId,
|
||||
'page' => 1,
|
||||
'page_count' => $pageCount,
|
||||
'datas_count' => isset($result['datas']) && is_array($result['datas']) ? count($result['datas']) : 0,
|
||||
]);
|
||||
|
||||
$pageStats = $this->processProductList($result['datas'] ?? [], $supplierId, $traceId, [
|
||||
'mode' => 'time',
|
||||
'page' => 1,
|
||||
]);
|
||||
$stats = $this->mergeStats($stats, $pageStats);
|
||||
$stats['pages_processed']++;
|
||||
|
||||
if ($pageCount > 1) {
|
||||
if ($mode === 'sync') {
|
||||
for ($i = 2; $i <= $pageCount; $i++) {
|
||||
$pageResult = $jstService->getProductListByTime($startTime, $endTime, $i, 50);
|
||||
$productList = $pageResult['datas'] ?? [];
|
||||
$resultPreview = null;
|
||||
try {
|
||||
$resultPreview = mb_substr(json_encode($pageResult, JSON_UNESCAPED_UNICODE), 0, 2000);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
Log::info('admin.manual.jst.product.sync_page.api_result', [
|
||||
'trace_id' => $traceId,
|
||||
'page' => $i,
|
||||
'page_count' => $pageResult['page_count'] ?? null,
|
||||
'datas_count' => is_array($productList) ? count($productList) : 0,
|
||||
'result_preview' => $resultPreview,
|
||||
]);
|
||||
$stats = $this->mergeStats($stats, $this->processProductList($productList, $supplierId, $traceId, [
|
||||
'mode' => 'time',
|
||||
'page' => $i,
|
||||
]));
|
||||
$stats['pages_processed']++;
|
||||
}
|
||||
} else {
|
||||
for ($i = 2; $i <= $pageCount; $i++) {
|
||||
self::dispatchDo('syncProductPage', [$startTime, $endTime, $i, $supplierId, $traceId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @var StoreProductServices $productServices */
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
/** @var StoreProductAttrServices $productAttrServices */
|
||||
$productAttrServices = app()->make(StoreProductAttrServices::class);
|
||||
$productServices->cacheTag()->clear();
|
||||
$productAttrServices->cacheTag()->clear();
|
||||
Log::info('admin.manual.jst.product.sync_by_time.finish', [
|
||||
'trace_id' => $traceId,
|
||||
'start_time' => $startTime,
|
||||
'end_time' => $endTime,
|
||||
'supplier_id' => $supplierId,
|
||||
'page_count' => $stats['page_count'],
|
||||
'pages_processed' => $stats['pages_processed'],
|
||||
'fetched' => $stats['fetched'],
|
||||
'created' => $stats['created'],
|
||||
'updated' => $stats['updated'],
|
||||
'skipped' => $stats['skipped'],
|
||||
'failed' => $stats['failed'],
|
||||
]);
|
||||
return $stats;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('admin.manual.jst.product.sync_by_time.error', [
|
||||
'trace_id' => $traceId,
|
||||
'message' => $e->getMessage(),
|
||||
'start_time' => $startTime,
|
||||
'end_time' => $endTime
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'trace_id' => $traceId,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步特定页码的商品
|
||||
* @param string $startTime
|
||||
* @param string $endTime
|
||||
* @param int $pageIndex
|
||||
* @param int $supplierId
|
||||
* @return bool
|
||||
*/
|
||||
public function syncProductPage(string $startTime, string $endTime, int $pageIndex, int $supplierId = 0, string $traceId = '')
|
||||
{
|
||||
try {
|
||||
Log::info('admin.manual.jst.product.sync_page.start', [
|
||||
'trace_id' => $traceId,
|
||||
'page' => $pageIndex,
|
||||
'start_time' => $startTime,
|
||||
'end_time' => $endTime
|
||||
]);
|
||||
$jstService = app()->make(HaichaoJstServices::class);
|
||||
$result = $jstService->getProductListByTime($startTime, $endTime, $pageIndex, 50);
|
||||
$productList = $result['datas'] ?? [];
|
||||
$resultPreview = null;
|
||||
try {
|
||||
$resultPreview = mb_substr(json_encode($result, JSON_UNESCAPED_UNICODE), 0, 2000);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
Log::info('admin.manual.jst.product.sync_page.api_result', [
|
||||
'trace_id' => $traceId,
|
||||
'page' => $pageIndex,
|
||||
'page_count' => $result['page_count'] ?? null,
|
||||
'datas_count' => is_array($productList) ? count($productList) : 0,
|
||||
'result_preview' => $resultPreview,
|
||||
]);
|
||||
|
||||
$stats = $this->processProductList($productList, $supplierId, $traceId, [
|
||||
'mode' => 'time',
|
||||
'page' => $pageIndex,
|
||||
]);
|
||||
|
||||
/** @var StoreProductServices $productServices */
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
/** @var StoreProductAttrServices $productAttrServices */
|
||||
$productAttrServices = app()->make(StoreProductAttrServices::class);
|
||||
$productServices->cacheTag()->clear();
|
||||
$productAttrServices->cacheTag()->clear();
|
||||
|
||||
Log::info('admin.manual.jst.product.sync_page.finish', [
|
||||
'trace_id' => $traceId,
|
||||
'page' => $pageIndex,
|
||||
'count' => is_array($productList) ? count($productList) : 0,
|
||||
'created' => $stats['created'] ?? 0,
|
||||
'updated' => $stats['updated'] ?? 0,
|
||||
'skipped' => $stats['skipped'] ?? 0,
|
||||
'failed' => $stats['failed'] ?? 0,
|
||||
]);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('admin.manual.jst.product.sync_page.error', [
|
||||
'trace_id' => $traceId,
|
||||
'page' => $pageIndex,
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存从ERP获取的商品数据
|
||||
* @param array $item
|
||||
* @param int $supplierId
|
||||
*/
|
||||
private function saveProductFromErpData(array $item, int $supplierId = 0): array
|
||||
{
|
||||
/** @var StoreProductServices $productServices */
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
/** @var StoreProductAttrServices $productAttrServices */
|
||||
$productAttrServices = app()->make(StoreProductAttrServices::class);
|
||||
|
||||
$relationSupplierId = $supplierId > 0 ? $supplierId : 0;
|
||||
Log::info('admin.manual.jst.product.sync.item.process', [
|
||||
'i_id' => $item['i_id'] ?? '',
|
||||
'name' => $item['name'] ?? '',
|
||||
'sku_count' => isset($item['skus']) && is_array($item['skus']) ? count($item['skus']) : 0
|
||||
]);
|
||||
$skuRows = isset($item['skus']) && is_array($item['skus']) ? $item['skus'] : [];
|
||||
$salePrice = floatval($item['s_price'] ?? 0);
|
||||
if ($salePrice <= 0 && $skuRows) {
|
||||
$skuSalePrices = [];
|
||||
foreach ($skuRows as $skuRow) {
|
||||
if (isset($skuRow['sale_price']) && is_numeric($skuRow['sale_price'])) {
|
||||
$skuSalePrices[] = floatval($skuRow['sale_price']);
|
||||
}
|
||||
}
|
||||
if ($skuSalePrices) {
|
||||
$salePrice = min($skuSalePrices);
|
||||
}
|
||||
}
|
||||
$marketPrice = floatval($item['market_price'] ?? 0);
|
||||
if ($marketPrice <= 0 && $skuRows) {
|
||||
$skuMarketPrices = [];
|
||||
foreach ($skuRows as $skuRow) {
|
||||
if (isset($skuRow['market_price']) && is_numeric($skuRow['market_price'])) {
|
||||
$skuMarketPrices[] = floatval($skuRow['market_price']);
|
||||
}
|
||||
}
|
||||
if ($skuMarketPrices) {
|
||||
$marketPrice = max($skuMarketPrices);
|
||||
}
|
||||
}
|
||||
$costPrice = floatval($item['c_price'] ?? ($item['cost_price'] ?? 0));
|
||||
if ($costPrice <= 0 && $skuRows) {
|
||||
$skuCostPrices = [];
|
||||
foreach ($skuRows as $skuRow) {
|
||||
if (isset($skuRow['cost_price']) && is_numeric($skuRow['cost_price'])) {
|
||||
$skuCostPrices[] = floatval($skuRow['cost_price']);
|
||||
}
|
||||
}
|
||||
if ($skuCostPrices) {
|
||||
$costPrice = max($skuCostPrices);
|
||||
}
|
||||
}
|
||||
$pic = (string)($item['pic'] ?? ($skuRows[0]['pic'] ?? ''));
|
||||
$name = (string)($item['name'] ?? ($skuRows[0]['name'] ?? ''));
|
||||
$productInfo = [
|
||||
'image' => $pic,
|
||||
'slider_image' => json_encode([$pic]),
|
||||
'store_name' => $name,
|
||||
'store_info' => $name,
|
||||
'cate_id' => 0,
|
||||
'price' => $salePrice,
|
||||
'ot_price' => $marketPrice,
|
||||
'delivery_type' => '1,2,3',
|
||||
'freight' => 1,
|
||||
'is_show' => 0,
|
||||
'add_time' => time(),
|
||||
'cost' => $costPrice,
|
||||
'ficti' => 0,
|
||||
'spec_type' => 1,
|
||||
'code' => $item['i_id'],
|
||||
'type' => $relationSupplierId ? 2 : 0,
|
||||
'relation_id' => $relationSupplierId,
|
||||
];
|
||||
$detail = $details = $value = [];
|
||||
$usedSpecValues = [];
|
||||
foreach ($skuRows as $skuIndex => $items) {
|
||||
$specValue = trim((string)($items['properties_value'] ?? ''));
|
||||
if ($specValue === '') {
|
||||
$specValue = trim((string)($items['name'] ?? ''));
|
||||
}
|
||||
if ($specValue === '') {
|
||||
$specValue = '规格' . ($skuIndex + 1);
|
||||
}
|
||||
if (isset($usedSpecValues[$specValue])) {
|
||||
$specValue = $specValue . '-' . ($skuIndex + 1);
|
||||
}
|
||||
$usedSpecValues[$specValue] = 1;
|
||||
$detail[] = $specValue;
|
||||
$details[] = [
|
||||
'name' => $specValue,
|
||||
'select' => false
|
||||
];
|
||||
$skuCost = floatval($items['cost_price'] ?? $costPrice);
|
||||
$skuSettle = $relationSupplierId ? $skuCost : 0.0;
|
||||
$value[] = [
|
||||
'bar_code' => '',
|
||||
'brokerage' => 0,
|
||||
'brokerage_two' => 0,
|
||||
'code' => (string)($items['sku_id'] ?? ''),
|
||||
'settle_price' => $skuSettle,
|
||||
'cost' => $skuCost,
|
||||
'detail' => ['规格' => $specValue],
|
||||
'ot_price' => floatval($items['market_price'] ?? $marketPrice),
|
||||
'pic' => (string)$items['pic'],
|
||||
'price' => floatval($items['sale_price'] ?? $salePrice),
|
||||
'select' => true,
|
||||
'value1' => $specValue,
|
||||
'values' => $specValue,
|
||||
'vip_price' => 0,
|
||||
'volume' => 0,
|
||||
'weight' => 0,
|
||||
'stock' => 0,
|
||||
];
|
||||
}
|
||||
if (!$value) {
|
||||
$specValue = '默认';
|
||||
$detail[] = $specValue;
|
||||
$details[] = [
|
||||
'name' => $specValue,
|
||||
'select' => false
|
||||
];
|
||||
$defCost = floatval($item['c_price'] ?? 0);
|
||||
$defSettle = $relationSupplierId ? $defCost : 0.0;
|
||||
$value[] = [
|
||||
'bar_code' => '',
|
||||
'brokerage' => 0,
|
||||
'brokerage_two' => 0,
|
||||
'code' => (string)($item['i_id'] ?? ''),
|
||||
'settle_price' => $defSettle,
|
||||
'cost' => $defCost,
|
||||
'detail' => ['规格' => $specValue],
|
||||
'ot_price' => floatval($item['market_price'] ?? 0),
|
||||
'pic' => (string)($item['pic'] ?? ''),
|
||||
'price' => floatval($item['s_price'] ?? 0),
|
||||
'select' => true,
|
||||
'value1' => $specValue,
|
||||
'values' => $specValue,
|
||||
'vip_price' => 0,
|
||||
'volume' => 0,
|
||||
'weight' => 0,
|
||||
'stock' => 0,
|
||||
];
|
||||
}
|
||||
$pid = $productServices->value(['code' => $item['i_id']], 'id');
|
||||
$existed = !!$pid;
|
||||
if (!$pid) {
|
||||
$pid = $productServices->ErpProductSave($productInfo);
|
||||
}
|
||||
$productServices->ensureSpu((int)$pid);
|
||||
$attr = [[
|
||||
'value' => '规格',
|
||||
'detail' => $detail,
|
||||
'details' => $details,
|
||||
]];
|
||||
|
||||
$skuList = $productAttrServices->validateProductAttr($attr, $value, $pid, 0, 0, 0);
|
||||
$productAttrServices->saveProductAttr($skuList, $pid);
|
||||
Log::info('admin.manual.jst.product.sync.save', [
|
||||
'product_id' => $pid,
|
||||
'existed' => $existed,
|
||||
'sku_saved_count' => isset($skuList['value']) && is_array($skuList['value']) ? count($skuList['value']) : 0
|
||||
]);
|
||||
return ['created' => !$existed, 'product_id' => $pid, 'existed' => $existed];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -412,7 +695,7 @@ class ProductSyncErp extends BaseJobs
|
||||
}
|
||||
|
||||
// 更新平台商品库存
|
||||
$defaultShopId = (int)sys_config('jst_default_shopid');
|
||||
$defaultShopId = (int)app()->make(\crmeb\services\SystemConfigService::class)->get('jst_default_shopid');
|
||||
if ($defaultShopId == $erpShopId) {
|
||||
$this->updateStoreProductValueStock($data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user