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() { $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, $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(); 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'] ?? ''; 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 (\Throwable $e) { $this->logError("商品库存更新全局异常:" . $e->getMessage()); } $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 Product|array $item * @param array $resultData * @param array $stats * @return bool */ public function handleData(Product|array $item, array $resultData, array &$stats = []): bool { $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(); $params = array(); $params['product_platform_id'] = $product_platform_id; $params['product_platform_code'] = $product_platform_code; $product_platform_amount = ProductPlatformAmount::getSharedLockOne($params); $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'] = $quantity; $product_platform_amount = ProductPlatformAmount::addProductPlatformAmount($data); if (empty($product_platform_amount)) { Db::rollBack(); $this->logError("商品 [{$product_name}] 新增库存数据失败: " . json_encode($data, JSON_UNESCAPED_UNICODE)); return false; } $this->logInfo("【初始化库存】商品 [{$product_name}] 药房 [{$pharmacy_code}] 初始库存: {$quantity}"); $stats['stock_changed']++; } else { $old_stock = (int)$product_platform_amount['stock']; // 存在库存数据,修改 $data = array(); $data['stock'] = $quantity; $params = array(); $params['amount_id'] = $product_platform_amount['amount_id']; 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']++; } } // 增加库存记录(仅在库存发生变动或首次初始化时记录) 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->logError("商品 [{$product_name}] 更新库存事务异常: " . $e->getMessage()); return false; } return true; } }