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
+36 -40
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);
HookManager::call('order.before_open', $order);
DB::transaction(function () use ($order, $plan) {
if ($order->refund_amount) { if ($order->refund_amount) {
$this->user->balance = $this->user->balance + $order->refund_amount; $this->user->balance += $order->refund_amount;
}
try {
DB::beginTransaction();
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(); });
$eventId = match ((int) $order->type) {
Order::STATUS_PROCESSING => admin_setting('new_order_event_id', 0),
Order::TYPE_RENEWAL => admin_setting('renew_order_event_id', 0),
Order::TYPE_UPGRADE => admin_setting('change_order_event_id', 0),
default => 0,
};
if ($eventId) {
$this->openEvent($eventId);
}
HookManager::call('order.after_open', $order); HookManager::call('order.after_open', $order);
} catch (\Exception $e) {
DB::rollBack();
Log::error($e);
throw new ApiException('开通失败');
}
} }
@@ -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();
} }
} }