feat: nạp tiền thủ công mã 30 phút, gia hạn trừ số dư, đồng bộ domain từ Plesk
- Nạp tiền: mã thanh toán sống 30 phút (ManualDepositDraft), khôi phục/huỷ mã, lệnh dọn mã hết hạn; total_pending chỉ tính giao dịch đã nộp chứng từ, admin duyệt/từ chối/xoá giao dịch - Gia hạn dịch vụ: phát hành invoice gia hạn trên order gốc và trừ số dư ngay - Đồng bộ domain từ Plesk theo server, ServiceOrderRecorder tạo order/invoice cho dịch vụ admin dựng - Danh sách dịch vụ trả field theo loại (service_plan, dns_records_count), đếm dịch vụ theo loại Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
10af41c5cf
commit
c5115b52dd
@@ -12,6 +12,7 @@ use App\Models\Log;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Transaction;
|
||||
use App\Services\ActivityLogger;
|
||||
use App\Support\ManualDepositDraft;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -77,28 +78,17 @@ class ManualDepositController extends Controller
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Huỷ transaction prepare cũ (chưa có proof) nếu còn tồn tại
|
||||
$old = Transaction::where('customer_id', $user->id)
|
||||
->where('type', 'manual')
|
||||
->where('status', TransactionStatus::PENDING->value)
|
||||
->whereNull('proof_image')
|
||||
->latest()
|
||||
->first();
|
||||
|
||||
if ($old) {
|
||||
DB::transaction(function () use ($old, $user) {
|
||||
$user->total_pending = max(0, $user->total_pending - $old->amount);
|
||||
$user->save();
|
||||
$old->forceDelete();
|
||||
});
|
||||
}
|
||||
ManualDepositDraft::query()
|
||||
->where('customer_id', $user->id)
|
||||
->get()
|
||||
->each(fn (Transaction $draft) => ManualDepositDraft::discard($draft));
|
||||
|
||||
$uuid = Str::uuid()->toString();
|
||||
$publicCode = Transaction::newPublicCode('MAN');
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
Transaction::create([
|
||||
$draft = Transaction::create([
|
||||
'uuid' => $uuid,
|
||||
'public_code' => $publicCode,
|
||||
'trans' => 'MAN' . time(),
|
||||
@@ -108,9 +98,6 @@ class ManualDepositController extends Controller
|
||||
'status' => TransactionStatus::PENDING->value,
|
||||
]);
|
||||
|
||||
$user->total_pending += $request->amount;
|
||||
$user->save();
|
||||
|
||||
DB::commit();
|
||||
} catch (\Exception) {
|
||||
DB::rollBack();
|
||||
@@ -126,13 +113,43 @@ class ManualDepositController extends Controller
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => [
|
||||
'uuid' => $uuid,
|
||||
'public_code' => $publicCode,
|
||||
],
|
||||
'data' => $this->draftPayload($draft),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /v1/transaction/manual-deposit/{uuid}
|
||||
*/
|
||||
public function show(Request $request, string $uuid): JsonResponse
|
||||
{
|
||||
$draft = ManualDepositDraft::query()
|
||||
->where('uuid', $uuid)
|
||||
->where('customer_id', $request->user()->id)
|
||||
->first();
|
||||
|
||||
if (! $draft) {
|
||||
return response()->json(['error' => true, 'message' => 'Mã thanh toán không tồn tại'], 404);
|
||||
}
|
||||
|
||||
if (ManualDepositDraft::isExpired($draft)) {
|
||||
ManualDepositDraft::discard($draft);
|
||||
|
||||
return response()->json(['error' => true, 'message' => 'Mã thanh toán đã hết hạn, vui lòng tạo mã mới'], 410);
|
||||
}
|
||||
|
||||
return response()->json(['error' => false, 'data' => $this->draftPayload($draft)]);
|
||||
}
|
||||
|
||||
private function draftPayload(Transaction $draft): array
|
||||
{
|
||||
return [
|
||||
'uuid' => $draft->uuid,
|
||||
'public_code' => $draft->public_code,
|
||||
'amount' => (int) $draft->amount,
|
||||
'expires_at' => ManualDepositDraft::expiresAt($draft)->toISOString(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE /v1/transaction/manual-deposit/{uuid}/cancel
|
||||
* Huỷ transaction đang prepare (chưa có proof, chưa submit).
|
||||
@@ -142,21 +159,15 @@ class ManualDepositController extends Controller
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
$transaction = Transaction::where('uuid', $uuid)
|
||||
$transaction = ManualDepositDraft::query()
|
||||
->where('uuid', $uuid)
|
||||
->where('customer_id', $user->id)
|
||||
->where('type', 'manual')
|
||||
->where('status', TransactionStatus::PENDING->value)
|
||||
->whereNull('proof_image')
|
||||
->firstOrFail();
|
||||
|
||||
$amount = $transaction->amount;
|
||||
$publicCode = $transaction->public_code;
|
||||
|
||||
DB::transaction(function () use ($transaction, $user) {
|
||||
$user->total_pending = max(0, $user->total_pending - $transaction->amount);
|
||||
$user->save();
|
||||
$transaction->forceDelete();
|
||||
});
|
||||
ManualDepositDraft::discard($transaction);
|
||||
|
||||
$this->activityLogger->log(
|
||||
event: 'deposit_cancel',
|
||||
@@ -194,22 +205,30 @@ class ManualDepositController extends Controller
|
||||
], 422);
|
||||
}
|
||||
|
||||
$transaction = Transaction::where('uuid', $request->uuid)
|
||||
->where('customer_id', $user->id)
|
||||
->where('type', 'manual')
|
||||
->where('status', TransactionStatus::PENDING->value)
|
||||
->whereNull('proof_image')
|
||||
->first();
|
||||
$transaction = DB::transaction(function () use ($request, $user) {
|
||||
$draft = ManualDepositDraft::query()
|
||||
->where('uuid', $request->uuid)
|
||||
->where('customer_id', $user->id)
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
if (! $draft || ManualDepositDraft::isExpired($draft)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$draft->update(['proof_image' => $request->proof_image]);
|
||||
$user->newQuery()->whereKey($user->getKey())->increment('total_pending', $draft->amount);
|
||||
|
||||
return $draft;
|
||||
});
|
||||
|
||||
if (!$transaction) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Giao dịch không hợp lệ hoặc đã được xử lý',
|
||||
'message' => 'Mã thanh toán đã hết hạn hoặc đã được xử lý, vui lòng tạo mã mới',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$transaction->update(['proof_image' => $request->proof_image]);
|
||||
|
||||
try {
|
||||
(new Telegram())->SendManualDepositPendingApproval($user, $transaction);
|
||||
$this->sendManualDepositAdminEmail($user, $transaction, $request);
|
||||
|
||||
Reference in New Issue
Block a user