MexUserSellItemMatchCommand.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <?php
  2. namespace App\Module\Mex\Commands;
  3. use App\Module\Mex\Services\MexMatchService;
  4. use Illuminate\Support\Facades\Log;
  5. use UCore\Command\Command;
  6. /**
  7. * 用户卖出物品撮合计划任务
  8. *
  9. * 定时执行用户卖出物品撮合任务,处理待撮合的用户卖出物品订单
  10. * php artisan mex:user-sell-item-match
  11. */
  12. class MexUserSellItemMatchCommand extends Command
  13. {
  14. /**
  15. * 命令签名
  16. *
  17. * @var string
  18. */
  19. protected $signature = 'mex:user-sell-item-match
  20. {--item= : 指定商品ID,不指定则处理所有商品}
  21. {--batch=100 : 批处理大小,默认100}
  22. {--dry-run : 试运行模式,不执行实际撮合}';
  23. /**
  24. * 命令描述
  25. *
  26. * @var string
  27. */
  28. protected $description = '执行用户卖出物品撮合任务';
  29. /**
  30. * 执行命令
  31. *
  32. * @return int
  33. */
  34. public function handleRun(): int
  35. {
  36. $startTime = microtime(true);
  37. $this->info('开始执行用户卖出物品撮合任务...');
  38. // 获取命令参数
  39. $itemId = $this->option('item') ? (int)$this->option('item') : null;
  40. $batchSize = (int)$this->option('batch');
  41. $dryRun = $this->option('dry-run');
  42. if ($dryRun) {
  43. $this->warn('试运行模式:不会执行实际的撮合操作');
  44. return $this->handleDryRun($itemId, $batchSize);
  45. }
  46. try {
  47. // 显示撮合前统计
  48. $this->showPreMatchStats();
  49. // 执行用户卖出物品撮合
  50. $result = MexMatchService::executeUserSellItemMatch($itemId, $batchSize);
  51. // 显示撮合结果
  52. $this->showMatchResult($result);
  53. // 显示撮合后统计
  54. $this->showPostMatchStats();
  55. $endTime = microtime(true);
  56. $totalTime = round(($endTime - $startTime) * 1000, 2);
  57. $this->info("用户卖出物品撮合任务执行完成,总耗时: {$totalTime}ms");
  58. return $result['success'] ? Command::SUCCESS : Command::FAILURE;
  59. } catch (\Exception $e) {
  60. $this->error('用户卖出物品撮合任务执行失败: ' . $e->getMessage());
  61. Log::error('MexUserSellItemMatchCommand执行失败', [
  62. 'error' => $e->getMessage(),
  63. 'trace' => $e->getTraceAsString(),
  64. ]);
  65. return Command::FAILURE;
  66. }
  67. }
  68. /**
  69. * 处理试运行模式
  70. *
  71. * @param int|null $itemId
  72. * @param int $batchSize
  73. * @return int
  74. */
  75. private function handleDryRun(?int $itemId, int $batchSize): int
  76. {
  77. $this->info('=== 用户卖出物品撮合试运行模式 ===');
  78. // 显示当前统计
  79. $stats = MexMatchService::getUserSellItemMatchStats();
  80. $this->table([
  81. '待撮合用户卖出物品订单数',
  82. '涉及商品数',
  83. '待撮合数量',
  84. '待撮合金额'
  85. ], [[
  86. $stats['pending_orders'],
  87. $stats['pending_items'],
  88. $stats['pending_quantity'],
  89. $stats['pending_amount']
  90. ]]);
  91. if ($itemId) {
  92. $this->info("指定处理商品ID: {$itemId}");
  93. $conditionCheck = MexMatchService::checkUserSellItemMatchConditions($itemId);
  94. if ($conditionCheck['can_match']) {
  95. $this->info("✓ 商品 {$itemId} 满足用户卖出物品撮合条件");
  96. $this->info(" - 待撮合订单: {$conditionCheck['pending_orders']} 个");
  97. } else {
  98. $this->warn("✗ 商品 {$itemId} 不满足用户卖出物品撮合条件: {$conditionCheck['message']}");
  99. }
  100. } else {
  101. $this->info('将处理所有符合条件的商品');
  102. }
  103. $this->info("批处理大小: {$batchSize}");
  104. $this->info('试运行完成,未执行实际撮合操作');
  105. return Command::SUCCESS;
  106. }
  107. /**
  108. * 显示撮合前统计
  109. */
  110. private function showPreMatchStats(): void
  111. {
  112. $this->info('=== 用户卖出物品撮合前统计 ===');
  113. $stats = MexMatchService::getUserSellItemMatchStats();
  114. $this->table([
  115. '待撮合用户卖出物品订单数',
  116. '涉及商品数',
  117. '待撮合数量',
  118. '待撮合金额'
  119. ], [[
  120. $stats['pending_orders'],
  121. $stats['pending_items'],
  122. $stats['pending_quantity'],
  123. $stats['pending_amount']
  124. ]]);
  125. }
  126. /**
  127. * 显示撮合结果
  128. *
  129. * @param array $result
  130. */
  131. private function showMatchResult(array $result): void
  132. {
  133. $this->info('=== 用户卖出物品撮合结果 ===');
  134. if ($result['success']) {
  135. $this->info("✓ 撮合成功");
  136. $this->info(" - 处理商品: " . count($result['processed_items']) . " 个");
  137. $this->info(" - 撮合订单: {$result['total_matched']} 个");
  138. $this->info(" - 成交金额: {$result['total_amount']}");
  139. $this->info(" - 执行时间: {$result['execution_time_ms']}ms");
  140. if (!empty($result['processed_items'])) {
  141. $this->info(" - 处理的商品ID: " . implode(', ', $result['processed_items']));
  142. }
  143. if (!empty($result['errors'])) {
  144. $this->warn('部分商品处理出现错误:');
  145. foreach ($result['errors'] as $error) {
  146. $this->warn(" - {$error}");
  147. }
  148. }
  149. } else {
  150. $this->error("✗ 撮合失败: {$result['message']}");
  151. }
  152. }
  153. /**
  154. * 显示撮合后统计
  155. */
  156. private function showPostMatchStats(): void
  157. {
  158. $this->info('=== 用户卖出物品撮合后统计 ===');
  159. $stats = MexMatchService::getUserSellItemMatchStats();
  160. $this->table([
  161. '剩余待撮合订单',
  162. '今日撮合订单',
  163. '今日成交数量',
  164. '今日成交金额'
  165. ], [[
  166. $stats['pending_orders'],
  167. $stats['today_matched'],
  168. $stats['today_quantity'],
  169. $stats['today_amount']
  170. ]]);
  171. }
  172. }