@@ -7,6 +7,7 @@ namespace App\Command;
|
||||
use App\Model\Product;
|
||||
use App\Model\ProductAmountRecord;
|
||||
use App\Model\ProductPlatformAmount;
|
||||
use App\Utils\Log;
|
||||
use Extend\Prescription\Prescription;
|
||||
use Hyperf\Command\Command as HyperfCommand;
|
||||
use Hyperf\Command\Annotation\Command;
|
||||
@@ -30,127 +31,188 @@ class getProductStockCommand extends HyperfCommand
|
||||
$this->setDescription('获取处方平台商品库存数据');
|
||||
}
|
||||
|
||||
protected function logInfo(string $message): void
|
||||
{
|
||||
$this->line(date('Y-m-d H:i:s') . ' [INFO] ' . $message);
|
||||
Log::getInstance('getProductStockCommand')->info($message);
|
||||
}
|
||||
|
||||
protected function logWarn(string $message): void
|
||||
{
|
||||
$this->warn(date('Y-m-d H:i:s') . ' [WARN] ' . $message);
|
||||
Log::getInstance('getProductStockCommand')->warning($message);
|
||||
}
|
||||
|
||||
protected function logError(string $message): void
|
||||
{
|
||||
$this->error(date('Y-m-d H:i:s') . ' [ERROR] ' . $message);
|
||||
Log::getInstance('getProductStockCommand')->error($message);
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$this->line("商品库存更新开始");
|
||||
$startTime = microtime(true);
|
||||
$this->logInfo("================== [getProductStockCommand] 商品库存更新开始 ==================");
|
||||
|
||||
$stats = [
|
||||
'total' => 0,
|
||||
'success' => 0,
|
||||
'stock_changed' => 0,
|
||||
'stock_unchanged' => 0,
|
||||
'skipped' => 0,
|
||||
'failed' => 0,
|
||||
];
|
||||
|
||||
try {
|
||||
// 获取商品
|
||||
$pageSize = 20;
|
||||
$params = array();
|
||||
$params['product_status'] = 1;
|
||||
$product = Product::getPage($params,['*'],1,10);
|
||||
if (empty($product['data'])){
|
||||
$this->line("商品库存更新成功,无可更新库存商品");
|
||||
$product = Product::getPage($params, ['*'], 1, $pageSize);
|
||||
if (empty($product['data'])) {
|
||||
$this->logInfo("当前无可更新库存的在架商品,任务结束");
|
||||
return;
|
||||
}
|
||||
|
||||
$totalCount = (int)($product['total'] ?? count($product['data']));
|
||||
$lastPage = (int)($product['last_page'] ?? 1);
|
||||
$this->logInfo("在架商品总数: {$totalCount} 件,共 {$lastPage} 页,每页批次: {$pageSize} 件");
|
||||
|
||||
$prescription = new Prescription();
|
||||
|
||||
foreach ($product['data'] as $item){
|
||||
if (!empty($item['product_pharmacy_code'])){
|
||||
for ($page = 1; $page <= $lastPage; $page++) {
|
||||
if ($page > 1) {
|
||||
$product = Product::getPage($params, ['*'], $page, $pageSize);
|
||||
if (empty($product['data'])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->logInfo(">>> 正在处理第 {$page}/{$lastPage} 页商品库存 (当前页 " . count($product['data']) . " 件)...");
|
||||
|
||||
foreach ($product['data'] as $item) {
|
||||
$stats['total']++;
|
||||
|
||||
if (empty($item['product_pharmacy_code'])) {
|
||||
$this->logWarn("【跳过】商品 [{$item['product_name']}] (ID: {$item['product_id']}) 未配置第三方药品编码(product_pharmacy_code)");
|
||||
$stats['skipped']++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$pharmacy_code = $item['pharmacy_code'] ?? '';
|
||||
$result = $prescription->getProdStock($item['product_pharmacy_code'], $pharmacy_code);
|
||||
$this->handleData($item['product_platform_id'],$item['product_platform_code'],$result[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($product['last_page'] > 1){
|
||||
for ($i = 2; $i <= $product['last_page']; $i++) {
|
||||
// 获取商品
|
||||
$params = array();
|
||||
$params['product_status'] = 1;
|
||||
$product = Product::getPage($params,['*'],$i,10);
|
||||
if (empty($product['data'])){
|
||||
$this->line("商品库存更新成功,无可更新库存商品");
|
||||
return;
|
||||
}
|
||||
|
||||
$prescription = new Prescription();
|
||||
|
||||
foreach ($product['data'] as $item){
|
||||
if (!empty($item['product_pharmacy_code'])){
|
||||
$pharmacy_code = $item['pharmacy_code'] ?? '';
|
||||
$result = $prescription->getProdStock($item['product_pharmacy_code'], $pharmacy_code);
|
||||
$this->handleData($item['product_platform_id'],$item['product_platform_code'],$result[0]);
|
||||
try {
|
||||
$result = $prescription->getProdStock($item['product_pharmacy_code'], $pharmacy_code);
|
||||
if (empty($result) || !isset($result[0])) {
|
||||
$this->logWarn("【库存响应空】商品 [{$item['product_name']}] 药房 [{$pharmacy_code}] 平台未返回库存数据");
|
||||
$stats['failed']++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$res = $this->handleData($item, $result[0], $stats);
|
||||
if ($res) {
|
||||
$stats['success']++;
|
||||
} else {
|
||||
$stats['failed']++;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$this->logError("【查询库存失败】商品 [{$item['product_name']}] (药店编码: {$item['product_pharmacy_code']}, 药房: {$pharmacy_code}) 异常: " . $e->getMessage());
|
||||
$stats['failed']++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->line("商品库存更新失败:" . $e->getMessage());
|
||||
} catch (\Throwable $e) {
|
||||
$this->logError("商品库存更新全局异常:" . $e->getMessage());
|
||||
}
|
||||
|
||||
$this->line("商品库存更新成功");
|
||||
$duration = round(microtime(true) - $startTime, 2);
|
||||
$this->logInfo("================== [getProductStockCommand] 商品库存更新完成 ==================");
|
||||
$this->logInfo("总耗时: {$duration}s | 检查总数: {$stats['total']} | 成功: {$stats['success']} (变动: {$stats['stock_changed']}, 未变: {$stats['stock_unchanged']}) | 跳过: {$stats['skipped']} | 失败: {$stats['failed']}");
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库
|
||||
* @param string $product_platform_id
|
||||
* @param string $product_platform_code
|
||||
* @param Product|array $item
|
||||
* @param array $resultData
|
||||
* @param array $stats
|
||||
* @return bool
|
||||
*/
|
||||
public function handleData(string $product_platform_id,string $product_platform_code,array $resultData): bool
|
||||
public function handleData(Product|array $item, array $resultData, array &$stats = []): bool
|
||||
{
|
||||
if (empty($resultData['quantity'])){
|
||||
$resultData['quantity'] = 0;
|
||||
}
|
||||
$quantity = (int)($resultData['quantity'] ?? 0);
|
||||
$product_platform_id = (string)$item['product_platform_id'];
|
||||
$product_platform_code = (string)$item['product_platform_code'];
|
||||
$product_name = (string)($item['product_name'] ?? '');
|
||||
$pharmacy_code = (string)($item['pharmacy_code'] ?? '');
|
||||
|
||||
try {
|
||||
Db::beginTransaction();
|
||||
|
||||
// 当前库存数量
|
||||
$stock = 0;
|
||||
|
||||
$params = array();
|
||||
$params['product_platform_id'] = $product_platform_id;
|
||||
$params['product_platform_code'] = $product_platform_code;
|
||||
$product_platform_amount = ProductPlatformAmount::getSharedLockOne($params);
|
||||
if (empty($product_platform_amount)){
|
||||
|
||||
$old_stock = 0;
|
||||
if (empty($product_platform_amount)) {
|
||||
// 无库存数据,新增
|
||||
$data = array();
|
||||
$data['product_platform_id'] = $product_platform_id;
|
||||
$data['product_platform_code'] = $product_platform_code;
|
||||
$data['stock'] = $resultData['quantity'];
|
||||
$data['stock'] = $quantity;
|
||||
$product_platform_amount = ProductPlatformAmount::addProductPlatformAmount($data);
|
||||
if (empty($product_platform_amount)){
|
||||
if (empty($product_platform_amount)) {
|
||||
Db::rollBack();
|
||||
$this->line("商品库存更新失败,无法新增库存数据" . json_encode($data, JSON_UNESCAPED_UNICODE));
|
||||
$this->logError("商品 [{$product_name}] 新增库存数据失败: " . json_encode($data, JSON_UNESCAPED_UNICODE));
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
$stock = $product_platform_amount['stock'];
|
||||
$this->logInfo("【初始化库存】商品 [{$product_name}] 药房 [{$pharmacy_code}] 初始库存: {$quantity}");
|
||||
$stats['stock_changed']++;
|
||||
} else {
|
||||
$old_stock = (int)$product_platform_amount['stock'];
|
||||
|
||||
// 存在库存数据,修改
|
||||
$data = array();
|
||||
$data['stock'] = $resultData['quantity'];
|
||||
$data['stock'] = $quantity;
|
||||
|
||||
$params = array();
|
||||
$params['amount_id'] = $product_platform_amount['amount_id'];
|
||||
ProductPlatformAmount::edit($params,$data);
|
||||
ProductPlatformAmount::edit($params, $data);
|
||||
|
||||
if ($old_stock !== $quantity) {
|
||||
$diff = $quantity - $old_stock;
|
||||
$diffStr = ($diff > 0 ? "+{$diff}" : "{$diff}");
|
||||
$this->logInfo("【库存变动】商品 [{$product_name}] 药房 [{$pharmacy_code}] 原库存: {$old_stock} -> 最新库存: {$quantity} (变动: {$diffStr})");
|
||||
$stats['stock_changed']++;
|
||||
} else {
|
||||
$this->logInfo("【库存无变化】商品 [{$product_name}] 药房 [{$pharmacy_code}] 当前库存: {$quantity}");
|
||||
$stats['stock_unchanged']++;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取商品数据
|
||||
$params = array();
|
||||
$params['product_platform_id'] = $product_platform_id;
|
||||
$product = Product::getOne($params);
|
||||
if (!empty($product)){
|
||||
// 增加库存记录
|
||||
$data = array();
|
||||
$data['product_id'] = $product['product_id'];
|
||||
$data['change_quantity'] = $resultData['quantity'] - $stock; // 库存变动的数量 变动的库存-原库存
|
||||
$data['quantity'] = $resultData['quantity']; // 变动后库存数量
|
||||
$data['change_time'] = date('Y-m-d H:i:s',time());
|
||||
$data['remark'] = "库存同步";
|
||||
$product_amount_record = ProductAmountRecord::addProductAmountRecord($data);
|
||||
if (empty($product_amount_record)){
|
||||
Db::rollBack();
|
||||
$this->line("商品库存更新失败,增加库存记录失败" . json_encode($data, JSON_UNESCAPED_UNICODE));
|
||||
// 增加库存记录(仅在库存发生变动或首次初始化时记录)
|
||||
if ($old_stock !== $quantity || empty($product_platform_amount)) {
|
||||
$params = array();
|
||||
$params['product_platform_id'] = $product_platform_id;
|
||||
$product = Product::getOne($params);
|
||||
if (!empty($product)) {
|
||||
$data = array();
|
||||
$data['product_id'] = $product['product_id'];
|
||||
$data['change_quantity'] = $quantity - $old_stock;
|
||||
$data['quantity'] = $quantity;
|
||||
$data['change_time'] = date('Y-m-d H:i:s', time());
|
||||
$data['remark'] = "处方平台库存定时同步";
|
||||
$product_amount_record = ProductAmountRecord::addProductAmountRecord($data);
|
||||
if (empty($product_amount_record)) {
|
||||
Db::rollBack();
|
||||
$this->logError("商品 [{$product_name}] 增加库存流水记录失败: " . json_encode($data, JSON_UNESCAPED_UNICODE));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollBack();
|
||||
$this->line("商品库存更新失败:" . $e->getMessage());
|
||||
$this->logError("商品 [{$product_name}] 更新库存事务异常: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user