> /tmp/alibaba_today_import.log 2>&1
*
* 分润设置(写死):
* - extension_type: 1(开启分润)
* - concession_pri: 售价 × 15%(商家让利金额)
* - extension_one: 15(SKU级分润比例)
* - plate_mer_profit: 0(平台商户利润)
* - commission: 保持原样(不修改)
*
* 原价计算规则(根据SKU售价阶梯加价):
* 1-20元 => 固定加5元
* 21-50元 => 固定加20元
* 51-120元 => 固定加40元
* 121-200元 => 固定加45元
* 201-300元 => 固定加50元
*/
class AlibabaTodayImport extends Command
{
protected function configure()
{
$this->setName('alibaba:today-import')
->setDescription('从alibaba_import_goods获取今日创建的商品,调用importStore接口正式入库')
->addOption('mer_id', null, \think\console\input\Option::VALUE_OPTIONAL, '商户ID', '3447')
->addOption('date', null, \think\console\input\Option::VALUE_OPTIONAL, '指定日期 (Y-m-d),默认今天', '')
->addOption('batch', null, \think\console\input\Option::VALUE_OPTIONAL, '每批处理数量', '50')
->addOption('skip', null, \think\console\input\Option::VALUE_OPTIONAL, '跳过前N条(断点续传)', '0');
}
protected function execute(Input $input, Output $output)
{
// 解除时间限制
set_time_limit(0);
$output->writeln('========================================');
$output->writeln(' 1688今日商品自动入库 开始');
$output->writeln('========================================');
// 1. 解析参数
$merId = (int)$input->getOption('mer_id');
$date = $input->getOption('date');
$batch = (int)$input->getOption('batch');
$skip = (int)$input->getOption('skip');
if ($batch < 1) $batch = 50;
if ($skip < 0) $skip = 0;
if (empty($date)) {
$date = date('Y-m-d');
}
// ============================================================
// 分润配置(写死)
// ============================================================
$profitConfig = [
'extension_type' => 1, // 1=开启分润
'concession_rate' => 0.15, // 商家让利比例15%(concession_pri = 售价 × 15%)
'extension_one' => 15, // SKU级分润比例15%
];
$output->writeln("商户ID: {$merId}");
$output->writeln("查询日期: {$date}");
$output->writeln("每批数量: {$batch}");
$output->writeln("跳过前N条: {$skip}");
$output->writeln('分润设置:');
$output->writeln(" extension_type: {$profitConfig['extension_type']} (开启分润)");
$output->writeln(" concession_rate: {$profitConfig['concession_rate']} (售价×{$profitConfig['concession_rate']})");
$output->writeln(" extension_one: {$profitConfig['extension_one']}%");
// 2. 查询今日创建的 alibaba_import_goods 记录(只查ID,不查全字段,节省内存)
$todayStart = $date . ' 00:00:00';
$todayEnd = $date . ' 23:59:59';
$output->write('正在查询今日待入库商品... ');
$allIds = Db::name('alibaba_import_goods')
->where('status', 1)
->where('create_time', '>=', $todayStart)
->where('create_time', '<=', $todayEnd)
->order('id', 'ASC')
->column('id');
$total = count($allIds);
$output->writeln("共 {$total} 条");
if ($total === 0) {
$output->writeln("{$date} 没有需要入库的商品");
$output->writeln('========================================');
$output->writeln(' 1688今日商品自动入库 结束 (无商品)');
$output->writeln('========================================');
return;
}
// 3. 应用 skip 跳过已处理的
if ($skip > 0) {
$allIds = array_slice($allIds, $skip);
$output->writeln("跳过前 {$skip} 条,剩余 " . count($allIds) . " 条");
}
// 4. 分批处理
/** @var ProductService $productService */
$productService = app()->make(ProductService::class);
$chunks = array_chunk($allIds, $batch);
$totalChunks = count($chunks);
$output->writeln("共分 {$totalChunks} 批执行");
$output->writeln('');
$globalSuccess = 0;
$globalFail = 0;
$globalProfitSet = 0;
$startTime = time();
foreach ($chunks as $chunkIndex => $idBatch) {
$batchStartTime = time();
$batchNum = $chunkIndex + 1;
$processedCount = $skip + ($chunkIndex * $batch) + 1;
$output->writeln("--- 第 {$batchNum}/{$totalChunks} 批 (已处理 {$processedCount}/{$total}) ---");
foreach ($idBatch as $importId) {
$output->write(" [{$processedCount}/{$total}] import_goods_id={$importId} ... ");
try {
// 4a. 调用原始入库方法
$result = $productService->importToStoreProduct($importId, $merId);
if ($result['code'] === 200) {
$productId = $result['product_id'];
$globalSuccess++;
// 4b. 根据SKU售价阶梯计算原价(ot_price)
try {
// 获取所有SKU的售价(用 unique 字段唯一标识每个SKU)
$skuValues = Db::name('store_product_attr_value')
->where('product_id', $productId)
->field('unique, price')
->select()
->toArray();
$skuPrices = [];
$skuOtPrices = [];
foreach ($skuValues as $sku) {
$salePrice = (float)$sku['price'];
$skuPrices[] = $salePrice;
// 根据售价区间计算原价
$otPrice = self::calcOtPrice($salePrice);
$skuOtPrices[] = $otPrice;
// 通过 unique 字段更新当前SKU的 ot_price
Db::name('store_product_attr_value')
->where('unique', $sku['unique'])
->update(['ot_price' => $otPrice]);
}
// 更新 store_product 表的 price(最低售价)和 ot_price(最高原价)
$minPrice = !empty($skuPrices) ? min($skuPrices) : 0;
$maxOtPrice = !empty($skuOtPrices) ? max($skuOtPrices) : 0;
Db::name('store_product')
->where('product_id', $productId)
->update([
'price' => $minPrice,
'ot_price' => $maxOtPrice,
]);
$output->write("[原价已计算] ");
} catch (\Throwable $priceE) {
$output->write("[原价计算失败: {$priceE->getMessage()}] ");
}
// 4c. 设置分润(写死15%)
try {
// 获取商品最低售价
$storeProduct = Db::name('store_product')
->where('product_id', $productId)
->field('price')
->find();
$salePrice = $storeProduct ? (float)$storeProduct['price'] : 0;
// 计算 concession_pri = 售价 × 15%,使用 bc 函数保留两位小数
$concessionPri = '0.00';
if ($salePrice > 0) {
$concessionPri = bcmul((string)$salePrice, (string)$profitConfig['concession_rate'], 2);
}
// 更新 store_product 表的分润字段(commission保持原样不修改)
Db::name('store_product')
->where('product_id', $productId)
->update([
'extension_type' => $profitConfig['extension_type'],
'concession_pri' => $concessionPri,
]);
// 更新 store_product_attr_value 表的 SKU 分润比例
Db::name('store_product_attr_value')
->where('product_id', $productId)
->update([
'extension_one' => $profitConfig['extension_one'],
]);
$globalProfitSet++;
$output->write("[分润15%已设置] ");
} catch (\Throwable $profitE) {
$output->write("[分润设置失败: {$profitE->getMessage()}] ");
}
$output->writeln("成功 => product_id={$productId}");
} else {
$globalFail++;
$output->writeln("跳过: {$result['msg']}");
}
} catch (\Throwable $e) {
$globalFail++;
$output->writeln("异常: {$e->getMessage()}");
}
$processedCount++;
}
// 每批结束后输出当前进度和耗时
$batchElapsed = time() - $batchStartTime;
$totalElapsed = time() - $startTime;
$output->writeln(" 本批耗时: {$batchElapsed}s | 累计耗时: {$totalElapsed}s | 累计成功: {$globalSuccess} | 累计失败: {$globalFail} | 分润设置: {$globalProfitSet}");
$output->writeln('');
// 每批之间短暂休眠,避免数据库压力过大
if ($chunkIndex < $totalChunks - 1) {
$output->writeln(" 等待 1 秒后继续下一批...");
sleep(1);
}
}
// 5. 输出汇总结果
$totalElapsed = time() - $startTime;
$output->writeln('');
$output->writeln('========================================');
$output->writeln(' 入库完成');
$output->writeln('========================================');
$output->writeln("总耗时: {$totalElapsed}s");
$output->writeln("总处理: {$total} 条");
$output->writeln("成功: {$globalSuccess} 条");
$output->writeln("失败: {$globalFail} 条");
$output->writeln("已设置分润15%: {$globalProfitSet} 条");
if ($globalFail > 0) {
$output->writeln('');
$output->writeln('提示: 失败的商品可以查看 alibaba 日志通道获取详细信息');
$output->writeln(" 重跑时可加 --skip={$skip} 跳过已处理的商品");
}
$output->writeln('========================================');
$output->writeln(' 1688今日商品自动入库 结束');
$output->writeln('========================================');
}
/**
* 根据售价计算原价(阶梯加价)
*
* @param float $salePrice SKU售价
* @return float 计算后的原价
*/
protected static function calcOtPrice(float $salePrice): float
{
if ($salePrice <= 0) {
return 0;
}
if ($salePrice >= 1 && $salePrice <= 20) {
return $salePrice + 5;
} elseif ($salePrice >= 21 && $salePrice <= 50) {
return $salePrice + 20;
} elseif ($salePrice >= 51 && $salePrice <= 120) {
return $salePrice + 40;
} elseif ($salePrice >= 121 && $salePrice <= 200) {
return $salePrice + 45;
} else {
// 201元以上(含201-300及超过300),统一加50元
return $salePrice + 50;
}
}
}