From 364d5333d77453c5dbb63f263619a62985d35a1c Mon Sep 17 00:00:00 2001 From: panchengyong Date: Mon, 6 Apr 2026 02:40:01 +0800 Subject: [PATCH] =?UTF-8?q?fix(hjf):=20=E4=BF=9D=E5=8D=95=E5=95=86?= =?UTF-8?q?=E5=93=81=E5=A4=9A=E4=BB=BD=E8=B4=AD=E4=B9=B0=E5=88=86=E6=B6=A6?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E5=85=A8=E9=93=BE=E8=B7=AF=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 公排入队:按件数拆分为 N 条独立记录,每条单份金额,逐条触发退款检测 - 周期佣金:位次统计改为按报单商品总件数(cart_num 之和),而非订单数 - 分销等级任务:type 6/7 订单数统计改为按 cart_num 累计保单商品份数 - 推荐返佣与积分奖励:验证 cart_num 倍乘逻辑正确 Made-with: Cursor --- docs/fsgx-issues-0402-1.md | 9 ++- pro_v3.5.1/app/jobs/hjf/HjfOrderPayJob.php | 70 +++++++++++-------- .../services/agent/AgentLevelTaskServices.php | 38 ++++++++-- .../order/StoreOrderCreateServices.php | 18 ++++- 4 files changed, 93 insertions(+), 42 deletions(-) diff --git a/docs/fsgx-issues-0402-1.md b/docs/fsgx-issues-0402-1.md index da948da8..96532a83 100644 --- a/docs/fsgx-issues-0402-1.md +++ b/docs/fsgx-issues-0402-1.md @@ -1,4 +1,11 @@ # 测试问题 ## 提现页面,pages/users/user_cash/index -- 选择支付宝提现,点击“立即提现”提交后跳转到pages/users/user_spread_money/index?type=1 \ No newline at end of file +- **已修复**选择支付宝提现,点击“立即提现”提交后跳转到pages/users/user_spread_money/index?type=1 + +## 保单商品一次购买多份下的分润计算 +- **已修复**推荐返佣按照一次购买多单的分润计算,如购买5份,则返佣5份,而不是1份。 +- **已修复**积分奖励同上 +- **已修复**分销等级任务中订单数统计改为按购买保单商品份数计算,如购买5份保单商品,则订单数统计为5份,而不是1份。 +- **已修复**公排入队按件数拆分为 N 条独立记录(PRD §3.1.2),每条单份金额,逐条触发退款检测 +- **已修复**周期佣金位次统计改为按报单商品总件数(而非订单数),确保跨订单轮巡位次连续 \ No newline at end of file diff --git a/pro_v3.5.1/app/jobs/hjf/HjfOrderPayJob.php b/pro_v3.5.1/app/jobs/hjf/HjfOrderPayJob.php index a2ff5801..f794d74a 100644 --- a/pro_v3.5.1/app/jobs/hjf/HjfOrderPayJob.php +++ b/pro_v3.5.1/app/jobs/hjf/HjfOrderPayJob.php @@ -34,11 +34,44 @@ class HjfOrderPayJob extends BaseJobs public function doJob(int $uid, string $orderId, float $amount = 3600.00): bool { + // 先查订单与购物车,计算报单商品总件数(公排入队 + 积分奖励共用) + $orderRow = Db::name('store_order') + ->where('order_id', $orderId) + ->where('is_queue_goods', 1) + ->field('id,uid,is_queue_goods') + ->find(); + + $queueQty = 1; + if ($orderRow) { + try { + $cartRows = Db::name('store_order_cart_info') + ->where('oid', (int)$orderRow['id']) + ->column('cart_info'); + $qtySum = 0; + foreach ($cartRows as $row) { + $item = is_string($row) ? json_decode($row, true) : $row; + if (!empty($item['productInfo']['is_queue_goods'])) { + $qtySum += (int)($item['cart_num'] ?? 1); + } + } + if ($qtySum > 0) { + $queueQty = $qtySum; + } + } catch (\Throwable $qe) { + Log::warning("[HjfOrderPay] 计算报单商品数量异常,使用默认值1: " . $qe->getMessage()); + } + } + + // PRD §3.1.2:一次购买多份时,拆分为多个独立记录分别进入公排池 + $unitAmount = $queueQty > 1 ? round($amount / $queueQty, 2) : $amount; try { /** @var QueuePoolServices $queueServices */ $queueServices = app()->make(QueuePoolServices::class); - $queueServices->enqueue($uid, $orderId, $amount); - Log::info("[HjfOrderPay] 公排入队成功 uid={$uid} orderId={$orderId}"); + for ($i = 0; $i < $queueQty; $i++) { + $subOrderId = $queueQty > 1 ? $orderId . '-' . ($i + 1) : $orderId; + $queueServices->enqueue($uid, $subOrderId, $unitAmount); + } + Log::info("[HjfOrderPay] 公排入队成功 uid={$uid} orderId={$orderId} qty={$queueQty} unitAmount={$unitAmount}"); } catch (ValidateException $e) { Log::warning("[HjfOrderPay] 入队被锁,延迟重试 uid={$uid} orderId={$orderId}: " . $e->getMessage()); static::dispatchSece(5, [$uid, $orderId, $amount]); @@ -77,40 +110,15 @@ class HjfOrderPayJob extends BaseJobs } // 等级升级完成后发放积分奖励(确保使用升级后的 agent_level) - try { - $orderRow = Db::name('store_order') - ->where('order_id', $orderId) - ->where('is_queue_goods', 1) - ->field('id,uid,is_queue_goods') - ->find(); - if ($orderRow) { - // fsgx B3:计算订单中报单商品的总数量,积分按数量倍乘 - $queueQty = 1; - try { - $cartRows = Db::name('store_order_cart_info') - ->where('oid', (int)$orderRow['id']) - ->column('cart_info'); - $qtySum = 0; - foreach ($cartRows as $row) { - $item = is_string($row) ? json_decode($row, true) : $row; - if (!empty($item['productInfo']['is_queue_goods'])) { - $qtySum += (int)($item['cart_num'] ?? 1); - } - } - if ($qtySum > 0) { - $queueQty = $qtySum; - } - } catch (\Throwable $qe) { - Log::warning("[HjfOrderPay] 计算报单商品数量异常,使用默认值1: " . $qe->getMessage()); - } - + if ($orderRow) { + try { /** @var PointsRewardServices $pointsService */ $pointsService = app()->make(PointsRewardServices::class); $pointsService->reward($uid, $orderId, (int)$orderRow['id'], $preUpgradeLevels, $queueQty); Log::info("[HjfOrderPay] 积分奖励发放完成 uid={$uid} orderId={$orderId} qty={$queueQty}"); + } catch (\Throwable $e) { + Log::error("[HjfOrderPay] 积分奖励发放失败 uid={$uid} orderId={$orderId}: " . $e->getMessage()); } - } catch (\Throwable $e) { - Log::error("[HjfOrderPay] 积分奖励发放失败 uid={$uid} orderId={$orderId}: " . $e->getMessage()); } return true; diff --git a/pro_v3.5.1/app/services/agent/AgentLevelTaskServices.php b/pro_v3.5.1/app/services/agent/AgentLevelTaskServices.php index 94044b04..b27a53f5 100644 --- a/pro_v3.5.1/app/services/agent/AgentLevelTaskServices.php +++ b/pro_v3.5.1/app/services/agent/AgentLevelTaskServices.php @@ -423,7 +423,31 @@ class AgentLevelTaskServices extends BaseServices } /** - * 统计直推下级的报单订单数(type=6 任务) + * 根据订单 ID 列表,统计其中报单商品的总件数(cart_num 之和) + * + * 一笔订单购买 N 份报单商品时 cart_num=N,本方法返回所有订单的 N 之和, + * 而非订单行数。与 HjfOrderPayJob / StoreOrderCreateServices 中的 B3/B6 逻辑一致。 + */ + private function sumQueueGoodsQty(array $orderIds): int + { + if (empty($orderIds)) { + return 0; + } + $cartRows = Db::name('store_order_cart_info') + ->whereIn('oid', $orderIds) + ->column('cart_info'); + $total = 0; + foreach ($cartRows as $row) { + $item = is_string($row) ? json_decode($row, true) : $row; + if (!empty($item['productInfo']['is_queue_goods'])) { + $total += (int)($item['cart_num'] ?? 1); + } + } + return $total; + } + + /** + * 统计直推下级的报单商品总份数(type=6 任务) * * @param int $uid 用户 ID * @return int @@ -437,14 +461,14 @@ class AgentLevelTaskServices extends BaseServices if (empty($directUids)) { return 0; } - // fsgx B5:补充 refund_status 检查,与其他任务类型保持一致,排除已全额退款订单 - return (int)Db::name('store_order') + $orderIds = Db::name('store_order') ->whereIn('uid', $directUids) ->where('is_queue_goods', 1) ->where('paid', 1) ->where('is_del', 0) ->whereIn('refund_status', [0, 3]) - ->count(); + ->column('id'); + return $this->sumQueueGoodsQty($orderIds); } /** @@ -492,14 +516,14 @@ class AgentLevelTaskServices extends BaseServices if ($childGrade >= 2) { continue; } - // fsgx B5:补充 refund_status 检查,排除已全额退款订单 - $total += (int)Db::name('store_order') + $childOrderIds = Db::name('store_order') ->where('uid', $child['uid']) ->where('is_queue_goods', 1) ->where('paid', 1) ->where('is_del', 0) ->whereIn('refund_status', [0, 3]) - ->count(); + ->column('id'); + $total += $this->sumQueueGoodsQty($childOrderIds); $total += $this->recursiveUmbrellaCount((int)$child['uid'], $remainDepth - 1); } return $total; diff --git a/pro_v3.5.1/app/services/order/StoreOrderCreateServices.php b/pro_v3.5.1/app/services/order/StoreOrderCreateServices.php index 369684dd..417fa503 100644 --- a/pro_v3.5.1/app/services/order/StoreOrderCreateServices.php +++ b/pro_v3.5.1/app/services/order/StoreOrderCreateServices.php @@ -1028,13 +1028,25 @@ class StoreOrderCreateServices extends BaseServices return '0'; } - // fsgx B6:统计推荐人已完成的报单订单数,作为起始位次基准 - $completedCount = (int)\think\facade\Db::name('store_order') + // fsgx B6:统计推荐人已完成的报单商品总件数(非订单数),作为起始位次基准 + $completedOrderIds = \think\facade\Db::name('store_order') ->where('spread_uid', $spread_uid) ->where('is_queue_goods', 1) ->where('paid', 1) ->where('is_del', 0) - ->count(); + ->column('id'); + $completedCount = 0; + if ($completedOrderIds) { + $completedCartRows = \think\facade\Db::name('store_order_cart_info') + ->whereIn('oid', $completedOrderIds) + ->column('cart_info'); + foreach ($completedCartRows as $ccRow) { + $ccItem = is_string($ccRow) ? json_decode($ccRow, true) : $ccRow; + if (!empty($ccItem['productInfo']['is_queue_goods'])) { + $completedCount += (int)($ccItem['cart_num'] ?? 1); + } + } + } // fsgx B-2B:逐件轮巡,每件商品取下一个位次的佣金比例后累加 $total = '0';