This commit is contained in:
baodev0
2026-09-23 15:17:18 +07:00
parent cd38c5d6d0
commit 82a71244ca
107 changed files with 3332 additions and 3306 deletions
@@ -57,6 +57,10 @@ class AdminTransactionController extends Controller
'public_code' => $t->public_code,
'trans' => $t->trans,
'amount' => $t->amount,
// Số thực nhận trên sao kê; null = chưa duyệt. Chênh với `amount` chính là
// phần khách chuyển thiếu/dư so với số đã khai.
'received_amount' => $t->received_amount === null ? null : (int) $t->received_amount,
'note' => $t->note,
'type' => $t->type,
'status' => $t->status,
'status_label' => TransactionStatus::from((int) $t->status)->label(),
@@ -84,12 +88,19 @@ class AdminTransactionController extends Controller
]);
}
public function approve(string $uuid): JsonResponse
public function approve(Request $request, string $uuid): JsonResponse
{
// Số tiền THỰC NHẬN trên sao kê. Bỏ trống = tin số khách khai (hành vi cũ), nhưng
// khi khách chuyển thiếu thì admin nhập đúng số đã về để số dư không bị cộng khống.
$validated = $request->validate([
'received_amount' => 'nullable|integer|min:0',
'note' => 'nullable|string|max:1000',
]);
try {
// Lock the transaction (and customer) row for the whole read-check-write so two
// admins approving the same transaction concurrently cannot both credit the customer.
$transaction = DB::transaction(function () use ($uuid) {
$transaction = DB::transaction(function () use ($uuid, $validated) {
$transaction = Transaction::where('uuid', $uuid)
->where('type', 'manual')
->lockForUpdate()
@@ -99,18 +110,47 @@ class AdminTransactionController extends Controller
return null;
}
$transaction->update(['status' => TransactionStatus::COMPLETED->value]);
$declared = (int) $transaction->amount;
$received = $validated['received_amount'] ?? $declared;
$shortfall = $declared - $received;
$note = trim(implode(' ', array_filter([
$transaction->note,
$validated['note'] ?? null,
$shortfall !== 0
? sprintf(
'[Lệch %s VNĐ: khai %s, thực nhận %s]',
number_format(abs($shortfall)),
number_format($declared),
number_format($received),
)
: null,
])));
$transaction->update([
'status' => TransactionStatus::COMPLETED->value,
'received_amount' => $received,
'note' => $note !== '' ? $note : null,
]);
$customer = Customer::where('id', $transaction->customer_id)->lockForUpdate()->first();
$customer->total += $transaction->amount;
$customer->credit += (int) floor($transaction->amount / 100);
$customer->total_pending = max(0, $customer->total_pending - $transaction->amount);
$creditEarned = Customer::creditFor($received);
$customer->total += $received;
$customer->credit += $creditEarned;
// Trừ pending theo số khách khai — đó chính là số đã được giữ chỗ lúc tạo yêu cầu.
$customer->total_pending = max(0, $customer->total_pending - $declared);
$customer->save();
Log::create([
'agent' => 'admin',
'client_ip' => request()->ip(),
'description' => 'Admin duyệt nạp tiền thủ công: ' . number_format($transaction->amount) . ' VNĐ (+' . floor($transaction->amount / 100) . ' credit)',
'description' => sprintf(
'Admin duyệt nạp tiền thủ công: thực nhận %s VNĐ (khai %s VNĐ) (+%d credit)%s',
number_format($received),
number_format($declared),
$creditEarned,
$shortfall > 0 ? ' — THIẾU ' . number_format($shortfall) . ' VNĐ' : '',
),
'customer_id' => $customer->id,
]);
@@ -121,7 +161,7 @@ class AdminTransactionController extends Controller
'link' => '/lich-su-giao-dich/' . $transaction->id,
'data' => [
'transaction_uuid' => $transaction->uuid,
'amount' => $transaction->amount,
'amount' => $received,
'public_code' => $transaction->public_code,
],
]);
@@ -151,7 +191,7 @@ class AdminTransactionController extends Controller
'customer_email' => $customer->email,
'customer_name' => $customer->fullname,
'transaction_code' => $transaction->public_code,
'amount' => $transaction->amount,
'amount' => $transaction->received_amount ?? $transaction->amount,
'status_label' => 'Đã duyệt',
'status_color' => '#15803d',
'status_bg' => '#f0fdf4',