actingAs(User::factory()->create()); }); it('can create a contract and automatically generate a payment schedule from template', function () { // 1. Chuẩn bị dữ liệu mẫu $project = Project::factory()->create(['code' => 'TEST-PROJ', 'name' => 'Dự án Kiểm thử']); $product = Product::factory()->create([ 'project_id' => $project->id, 'code' => 'STH03.TEST', 'total_price' => 1000000000, // 1 tỷ ]); $customer = Customer::factory()->create(['full_name' => 'Khách Hàng Test']); // 2. Tạo Mẫu thanh toán (3 đợt: 30% - 30% - 40%) $template = PaymentTemplate::create([ 'project_id' => $project->id, 'name' => 'Mẫu thanh toán 30-30-40', 'is_default' => true, ]); // Đợt 1: 30% ngay khi ký (0 ngày sau signing) PaymentScheduleItem::create([ 'template_id' => $template->id, 'installment_no' => 1, 'percentage' => 30, 'days_after_signing' => 0, 'type' => 'QSDD', ]); // Đợt 2: 30% sau 30 ngày kể từ đợt trước PaymentScheduleItem::create([ 'template_id' => $template->id, 'installment_no' => 2, 'percentage' => 30, 'days_after_previous' => 30, 'type' => 'MONG', ]); // 3. Thực hiện tạo Hợp đồng qua Livewire Page $signingDate = Carbon::now(); livewire(Pages\CreateContract::class) ->set('data.product_id', $product->id) ->set('data.contract_number', 'HD-TEST-UUID') ->set('data.contract_type', 'HĐMB') ->set('data.signing_date', $signingDate->format('Y-m-d')) ->set('data.total_value', 1000000000) ->set('data.payment_template_id', $template->id) ->set('data.customers', [$customer->id]) ->call('create') ->assertHasNoFormErrors(); // 4. KIỂM TRA KẾT QUẢ TRONG DATABASE // A. Hợp đồng phải tồn tại $contract = Contract::where('contract_number', 'HD-TEST-UUID')->first(); expect($contract)->not->toBeNull(); expect($contract->id)->toBeUuid(); // B. Kiểm tra bảng trung gian contract_customers $this->assertDatabaseHas('contract_customers', [ 'contract_id' => $contract->id, 'customer_id' => $customer->id, ]); // C. Kiểm tra Lịch trình thanh toán $schedule = PaymentSchedule::where('contract_id', $contract->id)->first(); expect($schedule)->not->toBeNull(); // D. Kiểm tra các đợt thanh toán con $scheduleItems = PaymentScheduleItem::where('schedule_id', $schedule->id) ->orderBy('installment_no') ->get(); expect($scheduleItems)->toHaveCount(2); expect((float)$scheduleItems[0]->amount)->toBe(300000000.0); });