feat: consider remaining traffic in surplus calculation when resetting traffic on plan change

This commit is contained in:
xboard
2025-07-17 12:13:03 +08:00
parent 4a7eef8ad6
commit 10ff5d7b27
+37 -41
View File
@@ -88,63 +88,55 @@ class OrderService
}); });
} }
public function open() public function open(): void
{ {
$order = $this->order; $order = $this->order;
HookManager::call('order.before_open', $order);
$this->user = User::find($order->user_id); $this->user = User::find($order->user_id);
$plan = Plan::find($order->plan_id); $plan = Plan::find($order->plan_id);
if ($order->refund_amount) { HookManager::call('order.before_open', $order);
$this->user->balance = $this->user->balance + $order->refund_amount;
} DB::transaction(function () use ($order, $plan) {
try { if ($order->refund_amount) {
DB::beginTransaction(); $this->user->balance += $order->refund_amount;
if ($order->surplus_order_ids) {
Order::whereIn('id', $order->surplus_order_ids)->update([
'status' => Order::STATUS_DISCOUNTED
]);
}
switch ((string) $order->period) {
case Plan::PERIOD_ONETIME:
$this->buyByOneTime($plan);
break;
case Plan::PERIOD_RESET_TRAFFIC:
app(TrafficResetService::class)->performReset($this->user, TrafficResetLog::SOURCE_ORDER);
break;
default:
$this->buyByPeriod($order, $plan);
} }
switch ((int) $order->type) { if ($order->surplus_order_ids) {
case Order::STATUS_PROCESSING: Order::whereIn('id', $order->surplus_order_ids)
$this->openEvent(admin_setting('new_order_event_id', 0)); ->update(['status' => Order::STATUS_DISCOUNTED]);
break;
case Order::TYPE_RENEWAL:
$this->openEvent(admin_setting('renew_order_event_id', 0));
break;
case Order::TYPE_UPGRADE:
$this->openEvent(admin_setting('change_order_event_id', 0));
break;
} }
match ((string) $order->period) {
Plan::PERIOD_ONETIME => $this->buyByOneTime($plan),
Plan::PERIOD_RESET_TRAFFIC => app(TrafficResetService::class)->performReset($this->user, TrafficResetLog::SOURCE_ORDER),
default => $this->buyByPeriod($order, $plan),
};
$this->setSpeedLimit($plan->speed_limit); $this->setSpeedLimit($plan->speed_limit);
$this->setDeviceLimit($plan->device_limit); $this->setDeviceLimit($plan->device_limit);
if (!$this->user->save()) { if (!$this->user->save()) {
throw new \Exception('用户信息保存失败'); throw new \RuntimeException('用户信息保存失败');
} }
$order->status = Order::STATUS_COMPLETED; $order->status = Order::STATUS_COMPLETED;
if (!$order->save()) { if (!$order->save()) {
throw new \Exception('订单信息保存失败'); throw new \RuntimeException('订单信息保存失败');
} }
DB::commit(); });
HookManager::call('order.after_open', $order);
} catch (\Exception $e) { $eventId = match ((int) $order->type) {
DB::rollBack(); Order::STATUS_PROCESSING => admin_setting('new_order_event_id', 0),
Log::error($e); Order::TYPE_RENEWAL => admin_setting('renew_order_event_id', 0),
throw new ApiException('开通失败'); Order::TYPE_UPGRADE => admin_setting('change_order_event_id', 0),
default => 0,
};
if ($eventId) {
$this->openEvent($eventId);
} }
HookManager::call('order.after_open', $order);
} }
@@ -274,9 +266,13 @@ class OrderService
$remainTraffic = max(0, $totalTraffic - $usedTraffic); $remainTraffic = max(0, $totalTraffic - $usedTraffic);
$trafficRatio = $totalTraffic > 0 ? $remainTraffic / $totalTraffic : 0; $trafficRatio = $totalTraffic > 0 ? $remainTraffic / $totalTraffic : 0;
$minRatio = min($cycleRatio, $trafficRatio); $ratio = $cycleRatio;
if (admin_setting('change_order_event_id', 0) == 1) {
$ratio = min($cycleRatio, $trafficRatio);
}
$order->surplus_amount = (int) max(0, $orderAmountSum * $minRatio);
$order->surplus_amount = (int) max(0, $orderAmountSum * $ratio);
$order->surplus_order_ids = $orders->pluck('id')->all(); $order->surplus_order_ids = $orders->pluck('id')->all();
} }
} }