315 lines
13 KiB
Markdown
315 lines
13 KiB
Markdown
# 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)
|
|
- `appendices()`, `paymentSchedule()`, `scheduleItems()` (HasManyThrough)
|
|
- `payments()`, `paymentFines()`
|
|
|
|
**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)
|
|
- Table có filter theo phương thức và ngày thu
|
|
|
|
---
|
|
|
|
## 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)
|
|
|
|
### `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
|
|
|
|
### 5.2. Đang dở / Cần tiếp tục
|
|
- [ ] **ContractForm:** `payment_template_id` đang `dehydrated(false)` - chưa tự động tạo lịch khi tạo hợp đồng mới từ form (hiện chỉ có trong CreateContract page sau khi submit)
|
|
- [ ] **PaymentsTable:** Chưa có cột trạng thái đối soát (so sánh với schedule_item amount)
|
|
- [ ] **Module Chiết khấu (Discounts):** Chưa có engine tính toán tự động dựa trên `discount_details`
|
|
- [ ] **PaymentFine:** Model đã có nhưng chưa có Resource/Form
|
|
- [ ] **Appendix & Settlement:** Chưa có Filament Resources
|
|
- [ ] **Báo cáo:** Chưa có Dashboard thống kê
|
|
- [ ] **Tự động hóa lịch trình cho 139 HĐ:** Cần command hoặc action để generate schedule hàng loạt
|
|
|
|
### 5.3. Vấn đề kỹ thuật cần xử lý
|
|
- [ ] `payment_template_id` trong ContractForm cần hook `afterCreate` hoặc đổi thành dehydrated + xử lý trong CreateContract
|
|
- [ ] PaymentsTable nên hiển thị `scheduleItem.type` và trạng thái đối soát
|
|
- [ ] ContractTable có thể thêm cột `paid_amount` / `remaining_amount` (đã có trong Resource nhưng chưa commit staged)
|
|
- [ ] Cần kiểm tra logic `updateOrCreate` trong ImportContractsComplex với nhiều khách hàng cùng 1 hợp đồng
|
|
|
|
---
|
|
|
|
## 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 ĐÃ THAY ĐỔI (Git Status)
|
|
|
|
### Staged (Sẵn sàng commit)
|
|
- `HQLAND_PROJECT_BLUEPRINT.md`
|
|
- `analyze_contracts.php`, `analyze_excel.php`, `analyze_khachhang.php`
|
|
- `app/Console/Commands/ImportContractsComplex.php`
|
|
- `app/Console/Commands/ImportCustomersExcel.php`
|
|
- `app/Console/Commands/ImportProductsExcel.php`
|
|
- `app/Filament/Resources/Contracts/Schemas/ContractForm.php`
|
|
- `app/Filament/Resources/Contracts/Tables/ContractsTable.php`
|
|
- `app/Filament/Resources/Customers/CustomerResource.php`
|
|
- `app/Filament/Resources/Customers/Schemas/CustomerForm.php`
|
|
- `app/Filament/Resources/Customers/Tables/CustomersTable.php`
|
|
- `app/Filament/Resources/Products/Schemas/ProductForm.php`
|
|
- `app/Models/Contract.php`
|
|
- `app/Models/Customer.php`
|
|
- `composer.json`, `composer.lock`
|
|
- `database/migrations/2026_04_23_081206_update_customers_table_for_real_estate.php`
|
|
- `database/migrations/2026_04_23_094837_expand_contracts_table_for_finance.php`
|
|
- `tests/Feature/ContractFinanceFlowTest.php`
|
|
- `tests/Feature/ProductResourceTest.php`
|
|
|
|
### Unstaged (Đang chỉnh sửa, chưa xong)
|
|
- `.gitignore`
|
|
- `analyze_contracts.php`
|
|
- `app/Filament/Resources/Contracts/ContractResource.php` (thêm action Tạo lịch TT)
|
|
- `app/Filament/Resources/Contracts/Pages/CreateContract.php` (refactor dùng Service)
|
|
- `app/Filament/Resources/Contracts/Schemas/ContractForm.php`
|
|
- `app/Filament/Resources/Projects/ProjectResource.php` (refactor sang Schemas)
|
|
- `app/Filament/Resources/Projects/Schemas/ProjectForm.php`
|
|
- `app/Models/Contract.php` (booted logic tài chính)
|
|
- `app/Providers/AppServiceProvider.php` (đăng ký PaymentObserver)
|
|
- `composer.json` (xóa script tạo SQLite)
|
|
- `config/database.php` (default về pgsql)
|
|
- `database/factories/CustomerFactory.php`
|
|
- `phpunit.xml` (cấu hình PostgreSQL testing)
|
|
|
|
### Untracked (File mới chưa add)
|
|
- `app/Filament/Resources/Payments/` (PaymentResource, Form, Table, Pages)
|
|
- `app/Observers/PaymentObserver.php`
|
|
- `app/Services/ContractScheduleService.php`
|
|
|
|
---
|
|
|
|
*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.*
|