# HQLAND - TRẠNG THÁI CODEBASE & LỘ TRÌNH PHÁT TRIỂN > File này được tạo để lưu trữ ngữ cảnh dự án cho các phiên làm việc sau. > **Cập nhật:** 24/04/2026 > **Dự án:** HQLand - Hệ thống quản lý Bất động sản > **Stack:** Laravel 13 + Filament v5.5 (Schemas Architecture) + PostgreSQL + UUID --- ## 1. THÔNG TIN KẾT NỐI DATABASE (CRITICAL) ### Database Chính (Production Data) - **Connection:** pgsql - **Host:** pgsql (trong Docker), 127.0.0.1 (từ Host machine) - **Port:** 5432 - **Database:** laravel - **Username:** sail - **Password:** password - **Dữ liệu hiện có:** 120 khách hàng, 45 sản phẩm, 139 hợp đồng ### Database Thử Nghiệm - **Database:** laravel_testing (đã tạo) - **Cách chạy test:** `DB_HOST=127.0.0.1 ./vendor/bin/pest` - **Cách chạy artisan:** `DB_HOST=127.0.0.1 php artisan tinker` ### Quy tắc VÀNG - **TUYỆT ĐỐI KHÔNG** dùng `migrate:fresh` trên database chính. - Tài khoản admin: `admin@phuongtc.com` / `1Qazxsw2@!321` - Dữ liệu Excel đã import là tài sản quý - không xóa. --- ## 2. KIẾN TRÚC KỸ THUẬT ### Tech Stack | Thành phần | Phiên bản / Công nghệ | |------------|----------------------| | Framework | Laravel 13.x | | PHP | 8.3 | | Admin Panel | Filament v5.5 | | Kiến trúc UI | **Schemas Architecture** (Tách Form/Table ra khỏi Resource) | | Database | PostgreSQL | | Khóa chính | UUID (100% các bảng) | | Excel | PhpSpreadsheet 5.7 | | Testing | Pest PHP 4.6 | ### Quy chuẩn Code 1. **LUÔN** dùng `Schemas` class. **KHÔNG** định nghĩa inline trong Resource. 2. `Grid` và `Section` nằm trong `Filament\Schemas\Components`. 3. Khi render HTML động trong Form, dùng **Inline Styles** thay vì Tailwind class. 4. Mọi trường JSONB trong Model phải khai báo trong `$casts = ['field' => 'array']`. 5. Naming database: **snake_case** cho mọi bảng và cột. --- ## 3. CẤU TRÚC MODULE HIỆN TẠI ### 3.1. Warehouse (Kho hàng) **Models:** `Project`, `Product` **Project:** - `code`, `name`, `type`, `address` - `payment_template_id` (relationship với PaymentTemplate) **Product:** - `code`, `project_id`, `product_type` (LAND | APARTMENT) - `area`, `price_per_unit`, `total_price` - `qsdd_value`, `foundation_temp_value`, `contract_temp_value` - `infrastructure_status` (JSONB) - `custom_data` (JSONB): block, building_density, legal_status_raw - `status` **Filament Resources:** - `ProjectResource` → `ProjectForm` (Schemas) - `ProductResource` --- ### 3.2. CRM (Khách hàng) **Model:** `Customer` **Cấu trúc:** - `type`: INDIVIDUAL | COMPANY - `full_name`, `cmnd_cccd`, `tax_code`, `title` - `phone`, `secondary_phones` (JSONB) - `email`, `dob` - `permanent_address`, `contact_address` (lưu cứng, không JSON) - `id_issue_date`, `id_issue_place` - `representative_id` (self-referencing, cho công ty) **Quan hệ:** - `representedCompanies()`: Công ty mà khách hàng đại diện - `representative()`: Ngườ đại diện của công ty - `contracts()`: belongsToMany qua `contract_customers` **Filament Resources:** - `CustomerResource` → `CustomerForm` + `CustomersTable` (Schemas) - Form hỗ trợ chuyển đổi INDIVIDUAL/COMPANY động (live) - Copy địa chỉ thường trú → liên hệ (suffixAction) --- ### 3.3. Contracts (Hợp đồng & Tài chính) **Model:** `Contract` **Cấu trúc:** - `contract_number`, `contract_type` (HĐMB | HĐGV | HĐDC) - `product_id`, `status` - `signing_date`, `sale_date`, `hql_confirmation_date` - `land_value`, `foundation_value`, `total_value`, `total_value_with_foundation` - `paid_amount`, `remaining_amount`, `excess_amount` - `discount_details` (JSONB) - `brokerage_name`, `stored_contract_count`, `filing_note` - `transfer_order`: 0 = chủ hiện tại, 1 = F0, 2+ = F1, F2... **Logic tự động trong Model (booted):** - `total_value` = `land_value` + `foundation_value` (nếu có giá trị) - Fallback: lấy từ `product.total_price` khi tạo mới - `remaining_amount` = `total_value` - `paid_amount` **Quan hệ:** - `product()`, `customers()` (belongsToMany qua contract_customers) - `paymentTemplate()` (belongsTo PaymentTemplate) - `appendices()`, `paymentSchedule()`, `scheduleItems()` (HasManyThrough) - `payments()`, `paymentFines()` **Accessor:** - `final_value`: Giá trị sau chiết khấu (tính từ `DiscountEngine`) **Filament Resources:** - `ContractResource` → `ContractForm` + `ContractsTable` - Action "Tạo lịch TT" trong Table (gọi `ContractScheduleService`) - Form có tính toán live: land_value + foundation_value = total_value - Hiển thị discount_details dạng grid inline style --- ### 3.4. Finance (Tài chính & Thu tiền) **Models:** `PaymentTemplate`, `PaymentSchedule`, `PaymentScheduleItem`, `Payment`, `PaymentFine` **PaymentTemplate:** - `project_id`, `name`, `is_default` - `items()`: các đợt thanh toán mẫu **PaymentSchedule:** - `contract_id`, `template_id` - `items()`: các đợt thanh toán thực tế **PaymentScheduleItem:** - `schedule_id` (hoặc `template_id` - dùng chung bảng) - `installment_no`, `type` (PaymentType enum), `percentage`, `amount`, `due_date` - `days_after_signing`, `days_after_previous` **Payment:** - `contract_id`, `schedule_item_id`, `amount`, `paid_date` - `method`, `receipt_number`, `metadata` (JSONB) **PaymentObserver (TỰ ĐỘNG):** - Khi tạo/sửa/xóa Payment: 1. Tính lại `contract.paid_amount` = SUM(payments) 2. Tính lại `remaining_amount` và `excess_amount` 3. Nếu có `excess_amount` > 0: **Tự động khấu trừ** vào đợt thanh toán tiếp theo chưa đủ tiền (tạo Payment auto) **Filament Resources:** - `PaymentResource` → `PaymentForm` + `PaymentsTable` - Form chọn Contract → chọn Đợt thanh toán (cascade) - Validation số tiền không vượt quá công nợ đợt / công nợ HĐ - Table có filter theo phương thức và ngày thu - Cột đối soát: Đủ / Thiếu / Thừa (tính tổng payments của đợt) - Cột còn thiếu tiền theo đợt - `PaymentFineResource` → Quản lý tiền phạt chậm thanh toán - `AppendixResource` → Quản lý phụ lục hợp đồng - `SettlementResource` → Quản lý quyết toán & sổ đỏ --- ## 4. CÁC COMMAND IMPORT DỮ LIỆU ### `import:products-excel {file=sanpham.xlsx}` - Import sản phẩm vào dự án "Hà Quang 1" - Tự động parse hạ tầng từ chuỗi "Key: Value - Key2: Value2" - Tạo custom_data (block, building_density...) ### `import:customers-excel {file=khachhang.xlsx}` - Import khách hàng cá nhân - Tách nhiều số điện thoại (dấu phẩy, gạch chéo, xuống dòng) - Parse ngày tháng Excel (số serial hoặc chuỗi) - Tự động tạo mẫu Công ty + Ngườ đại diện (Công ty TNHH BĐS Thịnh Vượng) ### `contracts:generate-schedules {--force}` - Tự động tạo lịch thanh toán cho các hợp đồng chưa có lịch - Ưu tiên `contract.payment_template_id`, fallback lấy từ `product.project.paymentTemplate` - Option `--force` để tạo lại lịch cho HĐ đã có schedule ### `import:contracts-complex {hopdong=hopdong.xlsx} {hdkh=Hd_kh.xlsx}` - Logic "Bắc cầu" 2 file: 1. `hopdong.xlsx`: Dữ liệu tài chính (theo Số HĐMB) 2. `Hd_kh.xlsx`: Liên kết Khách hàng - Lô đất - Thứ tự chuyển nhượng - Tìm mapping giữa mã lô và số HĐMB (str_contains) - Tạo/cập nhật Contract + liên kết pivot `contract_customers` ### Các file Excel quan trọng (KHÔNG ĐƯỢC XÓA) - `hopdong.xlsx` - Dữ liệu hợp đồng tài chính - `Hd_kh.xlsx` - Liên kết hợp đồng-khách hàng - `khachhang.xlsx` - Danh sách khách hàng - `sanpham.xlsx` - Danh sách sản phẩm/lô đất --- ## 5. TÌNH TRẠNG CÁC PHẦN ĐÃ LÀM / ĐANG DỞ ### 5.1. Đã hoàn thành - [x] Kiến trúc Schemas cho tất cả Resources - [x] Import Customers, Products, Contracts từ Excel - [x] Mở rộng bảng customers (type, representative, addresses...) - [x] Mở rộng bảng contracts (land_value, foundation_value, discount_details...) - [x] ContractScheduleService - Tạo lịch thanh toán từ template - [x] PaymentObserver - Tự động tính toán tài chính + khấu trừ dư - [x] PaymentResource (Form + Table) - [x] Test: ContractFinanceFlowTest (PASS) - [x] Cấu hình PHPUnit dùng PostgreSQL testing database - [x] **Fix ContractForm:** `payment_template_id` đã lưu vào DB, tự động tạo lịch khi tạo HĐ mới - [x] **PaymentForm validation:** Không cho phép thu quá công nợ đợt / HĐ - [x] **PaymentsTable:** Thêm cột Loại đợt, Trạng thái đối soát, Còn thiếu - [x] **Command generate schedule hàng loạt:** `php artisan contracts:generate-schedules` - [x] **PaymentFine Resource:** Form + Table đầy đủ - [x] **Appendix Resource:** Form + Table đầy đủ - [x] **Settlement Resource:** Form + Table đầy đủ - [x] **Discount Engine:** Tính toán tự động chiết khấu + hiển thị `final_value` trong ContractForm ### 5.2. Đang dở / Cần tiếp tục - [x] **Dashboard thống kê:** Đã tạo `ContractStatsOverview` + `UpcomingPaymentsTable` - [ ] **Notification:** Cảnh báo đợt thanh toán sắp đến hạn (chưa có hệ thống notification) ### 5.3. Vấn đề kỹ thuật ĐÃ XỬ LÝ - [x] ContractTable đã thêm cột `paid_amount` / `remaining_amount`, chuyển sang dùng `ContractsTable` Schemas - [x] Logic `syncWithoutDetaching` trong ImportContractsComplex đảm bảo nhiều KH cùng 1 HĐ không bị ghi đè - [x] Fix N+1 query ở `PaymentScheduleItem::getPaidAmountAttribute()` (dùng `relationLoaded`) - [x] Fix PaymentForm validation khi edit (`instanceof Payment` thay vì truthy check) - [x] Fix ContractForm `final_value_display` hiển thị được cả khi create (dùng `$get` state) --- ## 6. LỘ TRÌNH PHÁT TRIỂN TIẾP THEO (ĐỀ XUẤT) ### Giai đoạn 1: Hoàn thiện Core Finance (Ưu tiên CAO) 1. **Fix ContractForm:** Cho phép chọn template và tự động tạo lịch thanh toán ngay khi tạo hợp đồng 2. **Hoàn thiện PaymentForm:** Thêm validation số tiền không vượt quá công nợ đợt 3. **Cập nhật PaymentsTable:** Thêm cột "Đợt TT", "Trạng thái đối soát", "Còn thiếu" 4. **Command generate schedule hàng loạt:** `php artisan contracts:generate-schedules` cho 139 hợp đồng đã import ### Giai đoạn 2: Module Bổ sung (Ưu tiên TRUNG BÌNH) 5. **PaymentFine Resource:** Quản lý tiền phạt chậm thanh toán 6. **Appendix Resource:** Quản lý phụ lục hợp đồng 7. **Settlement Resource:** Quản lý thanh lý hợp đồng 8. **Discount Engine:** Tính toán tự động chiết khấu từ `discount_details` vào giá trị hợp đồng ### Giai đoạn 3: Báo cáo & Tối ưu (Ưu tiên THẤP) 9. **Dashboard Tài chính:** Tổng doanh thu, dòng tiền dự kiến, công nợ phải thu 10. **Báo cáo theo Dự án:** Thống kê bán hàng, thanh toán theo từng dự án 11. **Export Excel:** Xuất báo cáo công nợ khách hàng 12. **Notification:** Cảnh báo đợt thanh toán sắp đến hạn --- ## 7. CÂU LỆNH THƯỜNG DÙNG ```bash # Chạy test DB_HOST=127.0.0.1 ./vendor/bin/pest # Chạy test cụ thể DB_HOST=127.0.0.1 ./vendor/bin/pest --filter="ContractFinanceFlowTest" # Import dữ liệu db:host=127.0.0.1 php artisan import:products-excel db:host=127.0.0.1 php artisan import:customers-excel db:host=127.0.0.1 php artisan import:contracts-complex # Tinker DB_HOST=127.0.0.1 php artisan tinker # Migrate (KHÔNG dùng fresh!) DB_HOST=127.0.0.1 php artisan migrate ``` --- ## 8. DANH SÁCH FILE MỚI / THAY ĐỔI TRONG PHIÊN NÀY ### Migrations mới - `database/migrations/2026_04_24_083000_add_payment_template_id_to_contracts.php` ### Services mới - `app/Services/DiscountEngine.php` - Tính toán chiết khấu - `app/Console/Commands/GenerateContractSchedules.php` - Command tạo lịch hàng loạt ### Filament Resources mới - `app/Filament/Resources/PaymentFines/` (Resource + Form + Table + Pages) - `app/Filament/Resources/Appendices/` (Resource + Form + Table + Pages) - `app/Filament/Resources/Settlements/` (Resource + Form + Table + Pages) ### Widgets mới - `app/Filament/Widgets/ContractStatsOverview.php` - Dashboard tổng quan tài chính - `app/Filament/Widgets/UpcomingPaymentsTable.php` - Danh sách đợt TT sắp đến hạn ### Models sửa đổi - `app/Models/Contract.php` - Thêm `paymentTemplate()`, accessor `final_value` - `app/Models/PaymentScheduleItem.php` - Thêm accessor `paid_amount`, `remaining_amount` - `app/Models/User.php` - Thêm `FilamentUser` interface để user có quyền truy cập panel ### Forms/Tables sửa đổi - `app/Filament/Resources/Contracts/ContractResource.php` - Fix action `EditAction` namespace (`Filament\Actions\EditAction`) - `app/Filament/Resources/Contracts/Schemas/ContractForm.php` - Fix `payment_template_id`, thêm `final_value_display` - `app/Filament/Resources/Contracts/Pages/CreateContract.php` - Refactor dùng `$contract->payment_template_id` - `app/Filament/Resources/Payments/Schemas/PaymentForm.php` - Thêm validation amount + helper text công nợ - `app/Filament/Resources/Payments/Tables/PaymentsTable.php` - Thêm cột Loại đợt, Đối soát, Còn thiếu - `app/Filament/Resources/Payments/PaymentResource.php` - Thêm eager load `scheduleItem.payments` ### Config/Provider sửa đổi - `app/Providers/Filament/AdminPanelProvider.php` - Đăng ký widgets mới - `phpunit.xml` - Cấu hình PostgreSQL testing (DB_HOST, DB_DATABASE, etc.) - `config/database.php` - Default `pgsql` - `composer.json` - Xóa script tạo SQLite --- ## 9. FILE HỖ TRỢ CHUYỂN MÁY - `NEXT_SESSION.md` - Checklist và hướng dẫn nhanh cho phiên làm việc tiếp theo - `COMMIT_GUIDE.md` - Hướng dẫn commit toàn bộ thay đổi chưa commit --- *File này cần được cập nhật mỗi khi có thay đổi lớn trong kiến trúc hoặc lộ trình phát triển.*