Files
portal-api/tests/Feature/Payment/AdminManualDepositActionsTest.php
baodev0andClaude Opus 5.5 c5115b52dd 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>
2026-10-11 23:07:51 +07:00

94 lines
3.8 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Payment;
use App\Enums\TransactionStatus;
use App\Http\Controllers\Api\Admin\Transaction\AdminTransactionController;
use App\Models\Customer;
use App\Models\Transaction;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Str;
use Tests\TestCase;
class AdminManualDepositActionsTest extends TestCase
{
use RefreshDatabase;
private function deposit(Customer $customer, int $amount, ?string $proof, TransactionStatus $status = TransactionStatus::PENDING): Transaction
{
return Transaction::create([
'uuid' => (string) Str::uuid(),
'trans' => 'MANTEST' . Str::random(6),
'amount' => $amount,
'customer_id' => $customer->id,
'type' => 'manual',
'status' => $status->value,
'proof_image' => $proof,
]);
}
public function test_draft_without_proof_can_be_rejected_and_approved_without_touching_pending(): void
{
Mail::fake();
$customer = Customer::factory()->create(['total' => 0, 'total_pending' => 300_000]);
$controller = app(AdminTransactionController::class);
$rejected = $this->deposit($customer, 5_000_000, null);
$this->assertSame(200, $controller->reject($rejected->uuid)->getStatusCode());
$this->assertSame(TransactionStatus::FAILED->value, (int) $rejected->fresh()->status);
$approved = $this->deposit($customer, 1_000_000, null);
$this->assertSame(200, $controller->approve(new Request(), $approved->uuid)->getStatusCode());
$customer->refresh();
$this->assertSame(300_000, (int) $customer->total_pending);
$this->assertSame(1_000_000, (int) $customer->total);
}
public function test_signed_proof_image_url_serves_the_file(): void
{
Storage::fake('local');
$customer = Customer::factory()->create();
$path = UploadedFile::fake()->image('proof.png')->store('deposit-proofs/' . $customer->id, 'local');
$transaction = $this->deposit($customer, 300_000, $path);
$this->get($transaction->proof_image_urls[0])->assertOk();
$this->get(strtok($transaction->proof_image_urls[0], '?'))->assertForbidden();
}
public function test_deleting_submitted_pending_deposit_releases_pending_amount(): void
{
$customer = Customer::factory()->create(['total' => 0, 'total_pending' => 300_000]);
$transaction = $this->deposit($customer, 300_000, 'deposit-proofs/a.jpg');
$response = app(AdminTransactionController::class)->destroy($transaction->uuid);
$this->assertSame(200, $response->getStatusCode());
$this->assertSoftDeleted($transaction);
$this->assertSame(0, (int) $customer->fresh()->total_pending);
}
public function test_deleting_draft_or_completed_deposit_keeps_balances(): void
{
$customer = Customer::factory()->create(['total' => 2_000_000, 'total_pending' => 300_000]);
$controller = app(AdminTransactionController::class);
$draft = $this->deposit($customer, 500_000, null);
$completed = $this->deposit($customer, 2_000_000, 'deposit-proofs/b.jpg', TransactionStatus::COMPLETED);
$this->assertSame(200, $controller->destroy($draft->uuid)->getStatusCode());
$this->assertSame(200, $controller->destroy($completed->uuid)->getStatusCode());
$this->assertSame(404, $controller->destroy($completed->uuid)->getStatusCode());
$customer->refresh();
$this->assertSame(300_000, (int) $customer->total_pending);
$this->assertSame(2_000_000, (int) $customer->total);
}
}