update email template
This commit is contained in:
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Api\Admin\Transaction;
|
||||
use App\Enums\TransactionStatus;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Mail\Customer\ManualDepositStatus;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Notification;
|
||||
use App\Models\Log;
|
||||
use App\Models\Transaction;
|
||||
@@ -85,11 +86,55 @@ class AdminTransactionController extends Controller
|
||||
|
||||
public function approve(string $uuid): JsonResponse
|
||||
{
|
||||
$transaction = Transaction::with('customer')
|
||||
->where('uuid', $uuid)
|
||||
->where('type', 'manual')
|
||||
->where('status', TransactionStatus::PENDING->value)
|
||||
->first();
|
||||
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 = Transaction::where('uuid', $uuid)
|
||||
->where('type', 'manual')
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
if (!$transaction || (int) $transaction->status !== TransactionStatus::PENDING->value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$transaction->update(['status' => TransactionStatus::COMPLETED->value]);
|
||||
|
||||
$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);
|
||||
$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)',
|
||||
'customer_id' => $customer->id,
|
||||
]);
|
||||
|
||||
Notification::notifyCustomer($customer, [
|
||||
'type' => 'deposit_success',
|
||||
'title' => 'Nạp tiền thành công',
|
||||
'body' => 'Giao dịch ' . $transaction->public_code . ' đã được duyệt.',
|
||||
'link' => '/lich-su-giao-dich/' . $transaction->id,
|
||||
'data' => [
|
||||
'transaction_uuid' => $transaction->uuid,
|
||||
'amount' => $transaction->amount,
|
||||
'public_code' => $transaction->public_code,
|
||||
],
|
||||
]);
|
||||
|
||||
return $transaction->setRelation('customer', $customer);
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
FacadesLog::error('AdminTransactionController::approve error: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Có lỗi xảy ra, vui lòng thử lại',
|
||||
], 500);
|
||||
}
|
||||
|
||||
if (!$transaction) {
|
||||
return response()->json([
|
||||
@@ -98,65 +143,28 @@ class AdminTransactionController extends Controller
|
||||
], 404);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
$customer = $transaction->customer;
|
||||
|
||||
try {
|
||||
$transaction->update(['status' => TransactionStatus::COMPLETED->value]);
|
||||
|
||||
$customer = $transaction->customer;
|
||||
$customer->total += $transaction->amount;
|
||||
$customer->credit += (int) floor($transaction->amount / 100);
|
||||
$customer->total_pending = max(0, $customer->total_pending - $transaction->amount);
|
||||
$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)',
|
||||
Mail::to($customer->email)->send(new ManualDepositStatus([
|
||||
'customer_id' => $customer->id,
|
||||
'customer_email' => $customer->email,
|
||||
'customer_name' => $customer->fullname,
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'amount' => $transaction->amount,
|
||||
'status_label' => 'Đã duyệt',
|
||||
'status_color' => '#15803d',
|
||||
'status_bg' => '#f0fdf4',
|
||||
'subject' => 'Yêu cầu nạp tiền đã được duyệt - ' . $transaction->public_code,
|
||||
'status_message' => 'Yêu cầu nạp tiền của bạn đã được duyệt. Số tiền đã được cộng vào tài khoản và có thể sử dụng ngay.',
|
||||
'deposit_date' => $transaction->created_at?->format('d/m/Y H:i:s') ?? now()->format('d/m/Y H:i:s'),
|
||||
'processed_date' => now()->format('d/m/Y H:i:s'),
|
||||
]));
|
||||
} catch (\Throwable $e) {
|
||||
FacadesLog::error('Không thể gửi email duyệt nạp tiền thủ công: ' . $e->getMessage(), [
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'customer_email' => $customer->email,
|
||||
]);
|
||||
|
||||
Notification::notifyCustomer($customer, [
|
||||
'type' => 'deposit_success',
|
||||
'title' => 'Nạp tiền thành công',
|
||||
'body' => 'Giao dịch ' . $transaction->public_code . ' đã được duyệt.',
|
||||
'link' => '/lich-su-giao-dich/' . $transaction->id,
|
||||
'data' => [
|
||||
'transaction_uuid' => $transaction->uuid,
|
||||
'amount' => $transaction->amount,
|
||||
'public_code' => $transaction->public_code,
|
||||
],
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
try {
|
||||
Mail::to($customer->email)->send(new ManualDepositStatus([
|
||||
'customer_id' => $customer->id,
|
||||
'customer_email' => $customer->email,
|
||||
'customer_name' => $customer->fullname,
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'amount' => $transaction->amount,
|
||||
'status_label' => 'Đã duyệt',
|
||||
'status_color' => '#15803d',
|
||||
'status_bg' => '#f0fdf4',
|
||||
'subject' => 'Yêu cầu nạp tiền đã được duyệt - ' . $transaction->public_code,
|
||||
'status_message' => 'Yêu cầu nạp tiền của bạn đã được duyệt. Số tiền đã được cộng vào tài khoản và có thể sử dụng ngay.',
|
||||
'deposit_date' => $transaction->created_at?->format('d/m/Y H:i:s') ?? now()->format('d/m/Y H:i:s'),
|
||||
'processed_date' => now()->format('d/m/Y H:i:s'),
|
||||
]));
|
||||
} catch (\Throwable $e) {
|
||||
FacadesLog::error('Không thể gửi email duyệt nạp tiền thủ công: ' . $e->getMessage(), [
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'customer_email' => $customer->email,
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
FacadesLog::error('AdminTransactionController::approve error: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Có lỗi xảy ra, vui lòng thử lại',
|
||||
], 500);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
@@ -167,11 +175,41 @@ class AdminTransactionController extends Controller
|
||||
|
||||
public function reject(string $uuid): JsonResponse
|
||||
{
|
||||
$transaction = Transaction::with('customer')
|
||||
->where('uuid', $uuid)
|
||||
->where('type', 'manual')
|
||||
->where('status', TransactionStatus::PENDING->value)
|
||||
->first();
|
||||
try {
|
||||
// Same lock-then-verify-status pattern as approve() — prevents a duplicate
|
||||
// reject (or reject-after-approve) race from double-adjusting total_pending.
|
||||
$transaction = DB::transaction(function () use ($uuid) {
|
||||
$transaction = Transaction::where('uuid', $uuid)
|
||||
->where('type', 'manual')
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
if (!$transaction || (int) $transaction->status !== TransactionStatus::PENDING->value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$transaction->update(['status' => TransactionStatus::FAILED->value]);
|
||||
|
||||
$customer = Customer::where('id', $transaction->customer_id)->lockForUpdate()->first();
|
||||
$customer->total_pending = max(0, $customer->total_pending - $transaction->amount);
|
||||
$customer->save();
|
||||
|
||||
Log::create([
|
||||
'agent' => 'admin',
|
||||
'client_ip' => request()->ip(),
|
||||
'description' => 'Admin từ chối nạp tiền thủ công: ' . number_format($transaction->amount) . ' VNĐ',
|
||||
'customer_id' => $customer->id,
|
||||
]);
|
||||
|
||||
return $transaction->setRelation('customer', $customer);
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
FacadesLog::error('AdminTransactionController::reject error: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Có lỗi xảy ra, vui lòng thử lại',
|
||||
], 500);
|
||||
}
|
||||
|
||||
if (!$transaction) {
|
||||
return response()->json([
|
||||
@@ -180,51 +218,28 @@ class AdminTransactionController extends Controller
|
||||
], 404);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
$customer = $transaction->customer;
|
||||
|
||||
try {
|
||||
$transaction->update(['status' => TransactionStatus::FAILED->value]);
|
||||
|
||||
$customer = $transaction->customer;
|
||||
$customer->total_pending = max(0, $customer->total_pending - $transaction->amount);
|
||||
$customer->save();
|
||||
|
||||
Log::create([
|
||||
'agent' => 'admin',
|
||||
'client_ip' => request()->ip(),
|
||||
'description' => 'Admin từ chối nạp tiền thủ công: ' . number_format($transaction->amount) . ' VNĐ',
|
||||
Mail::to($customer->email)->send(new ManualDepositStatus([
|
||||
'customer_id' => $customer->id,
|
||||
'customer_email' => $customer->email,
|
||||
'customer_name' => $customer->fullname,
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'amount' => $transaction->amount,
|
||||
'status_label' => 'Không phù hợp',
|
||||
'status_color' => '#b91c1c',
|
||||
'status_bg' => '#fef2f2',
|
||||
'subject' => 'Yêu cầu nạp tiền không phù hợp - ' . $transaction->public_code,
|
||||
'status_message' => 'Yêu cầu nạp tiền của bạn chưa phù hợp để được duyệt. Vui lòng kiểm tra lại chứng từ hoặc liên hệ bộ phận hỗ trợ để được hướng dẫn thêm.',
|
||||
'deposit_date' => $transaction->created_at?->format('d/m/Y H:i:s') ?? now()->format('d/m/Y H:i:s'),
|
||||
'processed_date' => now()->format('d/m/Y H:i:s'),
|
||||
]));
|
||||
} catch (\Throwable $e) {
|
||||
FacadesLog::error('Không thể gửi email từ chối nạp tiền thủ công: ' . $e->getMessage(), [
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'customer_email' => $customer->email,
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
try {
|
||||
Mail::to($customer->email)->send(new ManualDepositStatus([
|
||||
'customer_id' => $customer->id,
|
||||
'customer_email' => $customer->email,
|
||||
'customer_name' => $customer->fullname,
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'amount' => $transaction->amount,
|
||||
'status_label' => 'Không phù hợp',
|
||||
'status_color' => '#b91c1c',
|
||||
'status_bg' => '#fef2f2',
|
||||
'subject' => 'Yêu cầu nạp tiền không phù hợp - ' . $transaction->public_code,
|
||||
'status_message' => 'Yêu cầu nạp tiền của bạn chưa phù hợp để được duyệt. Vui lòng kiểm tra lại chứng từ hoặc liên hệ bộ phận hỗ trợ để được hướng dẫn thêm.',
|
||||
'deposit_date' => $transaction->created_at?->format('d/m/Y H:i:s') ?? now()->format('d/m/Y H:i:s'),
|
||||
'processed_date' => now()->format('d/m/Y H:i:s'),
|
||||
]));
|
||||
} catch (\Throwable $e) {
|
||||
FacadesLog::error('Không thể gửi email từ chối nạp tiền thủ công: ' . $e->getMessage(), [
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'customer_email' => $customer->email,
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
FacadesLog::error('AdminTransactionController::reject error: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Có lỗi xảy ra, vui lòng thử lại',
|
||||
], 500);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
|
||||
Reference in New Issue
Block a user