Files
minicrm/tests/Feature/ImportCskhTest.php

128 lines
4.0 KiB
PHP

<?php
use App\Models\Contract;
use App\Models\Customer;
use App\Models\Feedback;
use App\Models\FeedbackChannel;
use App\Models\FeedbackInteraction;
use App\Models\Handover;
use App\Models\Product;
use App\Models\ProductService;
use App\Models\User;
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
beforeEach(function () {
// Seed a default user since the importer associates interactions with the first user
User::factory()->create([
'name' => 'Default Agent',
'email' => 'agent@test.com',
]);
// Create a default FeedbackChannel (ID 1) which is required by the importer
FeedbackChannel::create([
'name' => 'Email',
'slug' => 'email',
'icon' => 'heroicon-o-envelope',
'color' => '#3b82f6'
]);
});
test('cskh import command processes rows correctly in dry run and active modes', function () {
// Create temporary CSV file inside the project directory so WSL has easy access
$csvPath = base_path('tests/Feature/cskh_test.csv');
// Headers: Mã căn hộ, Họ tên KH, BÀN GIÀO CĂN HỘ, TÌNH TRẠNG, HỢP ĐỒNG THUÊ, HĐ HỢP TÁC KINH DOANH, TỰ DOANH, Phí QL, Lịch Sử khách hàng
$headers = [
'Mã căn hộ',
'Họ tên KH',
'BÀN GIÀO CĂN HỘ',
'TÌNH TRẠNG',
'HỢP ĐỒNG THUÊ',
'HĐ HỢP TÁC KINH DOANH',
'TỰ DOANH',
'Phí QL',
'Lịch Sử khách hàng'
];
$row1 = [
'A1-101',
'Nguyen Van A',
'{"date":"2026-01-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"}',
'Đã bàn giao căn hộ cho KH',
'Số HĐ: HĐ-001, Giá: 10M, Thời hạn: 1 năm',
'',
'',
'Đã thu phí QL tháng 1',
"KH báo hỏng bóng đèn\nKỹ thuật đã sửa xong"
];
$row2 = [
'A1-102',
'Tran Thi B',
'',
'',
'',
'HĐ hợp tác BCC-123',
'Doanh nghiệp B',
'',
'Khách hàng thắc mắc hóa đơn tiền nước'
];
$fp = fopen($csvPath, 'w');
// Write UTF-8 BOM for Excel support
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($fp, $headers);
fputcsv($fp, $row1);
fputcsv($fp, $row2);
fclose($fp);
// 1. Dry run execution
$this->artisan('app:import-cskh', [
'file_path' => $csvPath,
'--dry-run' => true
])
->expectsOutputToContain('Total rows in file: 2')
->expectsOutputToContain('New Products')
->assertExitCode(0);
// Verify no records created in dry-run
expect(Product::count())->toBe(0);
expect(Customer::count())->toBe(0);
expect(Contract::count())->toBe(0);
expect(Handover::count())->toBe(0);
expect(ProductService::count())->toBe(0);
expect(Feedback::count())->toBe(0);
// 2. Active run execution
$this->artisan('app:import-cskh', [
'file_path' => $csvPath
])
->expectsOutputToContain('Total rows in file: 2')
->assertExitCode(0);
// Verify records created
expect(Product::count())->toBe(2);
expect(Customer::count())->toBe(2);
expect(Contract::count())->toBe(2); // 1 Lease (row1) and 1 BCC (row2)
expect(Handover::count())->toBe(1); // row1 has handover, row2 doesn't
expect(ProductService::count())->toBe(1); // row2 has Self-Business
expect(Feedback::count())->toBe(2); // both have feedback logs
expect(FeedbackInteraction::count())->toBe(3); // row1 has 2 lines, row2 has 1 line
// Verify relationships and fields
$productA = Product::where('name', 'A1-101')->first();
expect($productA)->not->toBeNull();
$handover = Handover::where('product_id', $productA->id)->first();
expect($handover)->not->toBeNull();
expect($handover->handover_date)->toBe('2026-01-01');
$contract = Contract::where('product_id', $productA->id)->first();
expect($contract)->not->toBeNull();
expect($contract->type)->toBe('lease'); // type is a string 'lease'
// Clean up temporary file
@unlink($csvPath);
});