feat: Ensure order totals are non-negative, improve voucher deduction validation, and add pessimistic locking for stock updates.
This commit is contained in:
parent
4b1566c1a2
commit
2978d34e9e
@ -109,7 +109,7 @@ public function store(): array
|
|||||||
$discount = $voucherDiscount + $manualDiscount;
|
$discount = $voucherDiscount + $manualDiscount;
|
||||||
|
|
||||||
// Calculate total (subtotal - manual discount - voucher discount)
|
// Calculate total (subtotal - manual discount - voucher discount)
|
||||||
$total = $afterManual - $voucherDiscount;
|
$total = max(0, $afterManual - $voucherDiscount);
|
||||||
|
|
||||||
$pointsEarned = (int) floor($total / 5000);
|
$pointsEarned = (int) floor($total / 5000);
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ public function store(): array
|
|||||||
// Deduct item stock from the outlet inventory
|
// Deduct item stock from the outlet inventory
|
||||||
$result = $this->decreaseOutletStock($order->outlet, $item);
|
$result = $this->decreaseOutletStock($order->outlet, $item);
|
||||||
|
|
||||||
if ($result && ! $result['status']) {
|
if (! $result['status']) {
|
||||||
throw new \Exception($result['message']);
|
throw new \Exception($result['message']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,27 +161,35 @@ public function store(): array
|
|||||||
|
|
||||||
// Deduct voucher quantity
|
// Deduct voucher quantity
|
||||||
if ($this->voucher_id) {
|
if ($this->voucher_id) {
|
||||||
|
if (! $member) {
|
||||||
|
throw new \Exception('Data member tidak valid.');
|
||||||
|
}
|
||||||
|
|
||||||
$userVoucher = DB::table('user_voucher')
|
$userVoucher = DB::table('user_voucher')
|
||||||
->where('user_id', $member->id)
|
->where('user_id', $member->id)
|
||||||
->where('voucher_id', $this->voucher_id)
|
->where('voucher_id', $this->voucher_id)
|
||||||
->lockForUpdate()
|
->lockForUpdate()
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($userVoucher) {
|
if (! $userVoucher) {
|
||||||
if (! $userVoucher->quantity) {
|
throw new \Exception('Member tidak memiliki voucher ini.');
|
||||||
return;
|
}
|
||||||
} elseif ($userVoucher->quantity > 1) {
|
|
||||||
DB::table('user_voucher')
|
if ($userVoucher->quantity < 1) {
|
||||||
->where('id', $userVoucher->id)
|
throw new \Exception('Voucher sudah habis terpakai.');
|
||||||
->update([
|
}
|
||||||
'quantity' => $userVoucher->quantity - 1,
|
|
||||||
'updated_at' => now(),
|
if ($userVoucher->quantity > 1) {
|
||||||
]);
|
DB::table('user_voucher')
|
||||||
} else {
|
->where('id', $userVoucher->id)
|
||||||
DB::table('user_voucher')
|
->update([
|
||||||
->where('id', $userVoucher->id)
|
'quantity' => $userVoucher->quantity - 1,
|
||||||
->delete();
|
'updated_at' => now(),
|
||||||
}
|
]);
|
||||||
|
} else {
|
||||||
|
DB::table('user_voucher')
|
||||||
|
->where('id', $userVoucher->id)
|
||||||
|
->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,8 @@ public function getSubTotal(): int
|
|||||||
|
|
||||||
public function getTotal(): int
|
public function getTotal(): int
|
||||||
{
|
{
|
||||||
return $this->items->sum(fn ($item) => $item->unit_price * $item->quantity - parseRupiahToInt($this->form->discount) - $this->voucherDiscount);
|
$subtotal = $this->items->sum(fn ($item) => $item->unit_price * $item->quantity);
|
||||||
|
|
||||||
|
return max(0, $subtotal - parseRupiahToInt($this->form->discount) - $this->voucherDiscount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,11 @@ public function increaseOutletStock($outlet, $item): void
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$existing = $outlet->{$relation}()->withPivot('stock')->where("{$relation}.id", $item->orderable_id)->first();
|
$existing = $outlet->{$relation}()
|
||||||
|
->withPivot('stock')
|
||||||
|
->where("{$relation}.id", $item->orderable_id)
|
||||||
|
->lockForUpdate()
|
||||||
|
->first();
|
||||||
|
|
||||||
if ($existing) {
|
if ($existing) {
|
||||||
$currentStock = $existing->pivot->stock ?? 0;
|
$currentStock = $existing->pivot->stock ?? 0;
|
||||||
@ -112,5 +116,7 @@ public function decreaseOutletStock($outlet, $item)
|
|||||||
'purchase_id' => $item->purchase_id ?? null,
|
'purchase_id' => $item->purchase_id ?? null,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return ['status' => true];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user