13 KiB
13 KiB
TASKS_ROADMAP.md — AfterSales CRM
Mục đích: Theo dõi tất cả các công việc: đã hoàn thành, đang làm, sẽ làm. Cập nhật: Mỗi khi hoàn thành hoặc thêm task mới.
Trạng thái hiện tại
- SOP Phase 1-8: 100% hoàn thành
- AI Instructions Core: 85% (6/7, còn auto-suggest transfer)
- V2 Restructure: 100% hoàn thành (Contract category, bỏ pivot, đại diện)
- Test: Pest 8/8 tests (21 assertions) pass
- Data import: 3658 rows từ
ai_instructions/CSKH.xlsximported successfully - Dual Panel: Admin (đầy đủ) + Support (rút gọn, tập trung feedback)
✅ ĐÃ HOÀN THÀNH
Giai đoạn 1: Mở rộng CSDL
- Bảng
departments(id, name, manager_id → users) - Bổ sung
feedback: current_department_id, is_escalated - Bảng
ticket_transfer_logs(feedback_id, from/to department, sender, reason) - Nâng cấp
feedback_attachments: uuid, disk, collection - Cài Spatie laravel-permission
Giai đoạn 2: Services & Logic
FileService: upload, validation (jpg/png/pdf/mp4/mov ≤20MB), collection query, temporary URLTransferService: transfer department + reason required + notificationClosingService: role-gated close + proof_of_resolution check- Policies dùng Spatie
hasRole() - Custom Rule
RequireProofOfResolution
Giai đoạn 3: Notifications
TicketTransferred(Database + Mail)TicketClosed(Database + Mail)
Giai đoạn 4: Filament UI
TransferDepartmentAction trên Edit Feedback (modal: department + reason + attachment)CloseTicketAction (visible: admin/manager, status ≠ closed, requires confirmation)- InteractionsRelationManager: role-aware status options (staff: no "closed"), department field
- FeedbackForm: current_department_id, is_escalated, attachment_collection
Giai đoạn 5: Dashboard Widgets
ResolvedTicketsWidget: bảng ticket resolved chờ đóng (manager lọc theo phòng quản lý)AvgProcessingTimeWidget: 4 stats (resolved count, avg time, pending, escalated)HandlerPerformanceWidget: bar chart thời gian xử lý trung bình theo nhân viên
Giai đoạn 6: Testing
- Pest cài đặt + 8 test scenarios
ClosingPermissionTest: 4 tests (staff 403, no evidence 422, with evidence OK, cross-department 403)TransferFlowTest: 2 tests (success + missing reason)
Giai đoạn 7: Seeder
- 4 departments (CSKH, Kỹ thuật, Kế toán, Pháp lý)
- 1 ticket_transfer_log mẫu
- 3 feedback_attachments (2 proof_of_resolution, 1 customer_evidence)
Giai đoạn 8: Polish & Bug Fix
- Dashboard widget filter Manager theo department
- Migration disk default fix (private → local)
- File upload pattern fix
- Department + Escalated columns trên FeedbackTable + Department filter
- Validation proof_of_resolution khi close từ form
- Manager chỉ đóng ticket phòng mình
- View Attachments trong Interaction History (temporary signed URL)
- Docker deployment (Dockerfile, docker-compose, entrypoint)
- Migration notifications table
Giai đoạn 9: Granular Permissions + Export Backup + User/Role Management
- PermissionSeeder: 29 granular permissions (view/create/update/delete per module + close-ticket, transfer-department, export-data)
- Role → Permission mapping: admin (all), manager (no delete/export), staff (view + limited write)
- Policies updated to
hasPermissionTo()(5 policies) - ExportBackup command:
app:export-backup(JSON, per-table, chunk 500, manifest.json) - UserResource: admin-only CRUD users + assign role
- RoleResource: admin-only CRUD roles + assign permissions via CheckboxList
- UserPolicy + RolePolicy (admin-only access)
A: Module Hợp đồng (Contract)
- Migration
contracts: product_id, customer_id, type (sale/lease/bcc), dates, status, signed_status - Enum
ContractType(SALE/LEASE/BCC) +ContractStatus(ACTIVE/EXPIRED/LIQUIDATED) - Model
Contract: relationships product(), customer(), feedbacks() - Filament Resource
Contracts(CRUD) +ContractPolicy - RelationManager
ContractsRelationManagertrên ProductResource - Model
Productthêmcontracts()HasMany - Seeder: 5 contracts mẫu
B: Cơ chế Snapshot Hợp đồng
- Migration thêm
contract_id(FK->contracts, nullable) vào bảngfeedback - Model
Feedback: thêmcontract_idfillable +contract()BelongsTo - FeedbackForm: auto-select active contract khi chọn sản phẩm, cho phép chọn lại thủ công
- FeedbackTable: cột "Contract" hiển thị loại HĐ dạng badge
- Seeder: gán contract_id cho 5 feedback mẫu
C: Module Bàn giao (Handover)
- Migration
handovers: product_id, customer_id, handover_date, status, remark - Enum
HandoverStatus(NOT_READY/READY/SCHEDULED/HANDED_OVER) - Model
Handover: relationships product(), customer() - RelationManager
HandoversRelationManagertrên ProductResource - Model
Productthêmhandovers()HasMany - Seeder: 5 handovers mẫu
D: Module Dịch vụ phụ trợ (ProductService)
- Migration
product_services: product_id, service_type, status, actual_collection_date, remark - Enum
ServiceType(MANAGEMENT_FEE/GRATITUDE/SELF_BUSINESS) - Model
ProductService: relationship product() - RelationManager
ProductServicesRelationManagertrên ProductResource - Model
ProductthêmproductServices()HasMany - Seeder: 5 services mẫu
E: Enhancement ProductResource
- ProductResource có 3 tabs: Contracts + Handovers + Services (via getRelations())
G: Data Import Pipeline
- Cài
spatie/simple-excel(Lazy Collection, chống OOM) - Command
app:import-cskh {file_path} --dry-runvới ProgressBar, chunk 100 rows - Pipeline per row: Product/Customer firstOrCreate → customer_product pivot → Contract → Handover → Service → Feedback + Interactions
- Xử lý DateTimeImmutable object từ Excel, skip header/meta rows
- Test thành công: 3658 rows → 3299 products, 2089 customers, 2637 contracts, 2077 handovers, 159 services, 71 feedbacks, 226 interactions
Internationalization (i18n) — Vietnamese + English
- Config:
APP_LOCALE=vi,APP_FALLBACK_LOCALE=en - Created
lang/en/andlang/vi/with 3 files each:app.php,feedback.php,enums.php - ~120 translation keys: navigation, labels, status, widgets, services, notifications, enums
- All Resources: override
getPluralLabel()+getNavigationGroup()with__()calls - All Form fields: explicit
->label(__('key')) - All Table columns: explicit
->label(__('key')) - All RelationManagers:
$titleuses translation key - All Widgets:
getHeading()/getDescription()return translated strings - Enums:
ContractType,ContractStatus,HandoverStatus,ServiceTypeuse__()inlabel() - Filament vendor: 57 Vietnamese translation files auto-activated
UI Polish & Bug Fixes
- File upload: Fixed
disk('local')→disk('public')across all components - File upload: Added
exists()check before getting metadata - File upload: Fixed
dehydrated(false)issue — use property to store paths - Tailwind CSS: Added ~200 utility classes to
public/css/filament-custom.css - SVG icons: Use inline
width/heightattributes instead of Tailwind classes - GlobalSearch: Customized for all Resources with multi-field search
- RelationManager titles: Override
getTitle()for proper translation - Enum refactoring: Added
color()method, staticoptions(), developer comments - Documentation: Created
docs/I18N_GUIDE.mdanddocs/ENUM_GUIDE.md
Support Panel (Dual Panel)
SupportPanelProvider: panel thứ 2 tại path/support, rút gọn chỉ tập trung feedback- Resources trong Support: Feedback, Customer, Product, FeedbackChannel, FeedbackTag, ActivityLog
- Widgets: ResolvedTicketsWidget, AvgProcessingTimeWidget, HandlerPerformanceWidget
V2: Contract Restructure — Category + Representative + Bỏ Pivot
- Migration: thêm
category(ownership/business),representative_*vào contracts, xóacustomer_product - Enum:
ContractCategory(ownership, business) + cập nhậtContractType(deposit, purchase, transfer, rental, self_business, bcc) - Model: Contract (+category, +representative), Customer (ownedProducts qua contracts), Feedback (-customer_product_id)
- Xóa
CustomerProductmodel/pivot - Validation: ràng buộc 1 active/category/product (CreateContract/EditContract)
- FeedbackForm: filter mới (Customer → Product qua Contract ownership + đại diện), case-insensitive search
- ContractForm: select category → dynamic type options, representative form section
- FeedbackTable:
contract.product.namethaycustomerProduct.product.name - Seeder: 6 contracts V2 (ownership+business, có representative), feedback no customer_product_id
- ImportCskh: cập nhật pipeline, không còn customer_product
- i18n: vi/en cho category, type mới, representative, validation
- Tests: 8/8 pass (21 assertions)
ActivityLog — Audit Trail
- Migration
activity_logs: user_id, action, description, subject_type/id, metadata - Model
ActivityLog+ ServiceActivityLogger(static log method) - Filament Resource
ActivityLogResource(read-only, list view with filters) - Policy
ActivityLogPolicy(admin-only) - Translation keys:
resource_activity_logs,action_*,details,system
🔴 CHƯA LÀM
F: Tự động gợi ý transfer (optional, nice-to-have)
- Hiển thị badge gợi ý: "Ticket BCC → khuyến nghị chuyển Pháp lý"
- Logic detect contract type → suggest department
📋 Ưu tiên phát triển
| Ưu tiên | Task | Phụ thuộc |
|---|---|---|
| 1 | F: Tự động gợi ý transfer (nice-to-have) | A |
📊 Tiến độ tổng quan
SOP Phase 1-9: ████████████████████████ 100% (Hoàn thành)
AI Instructions Core: ███████████████████████░ 85% (6/7 — Còn: auto-suggest transfer)
Support Panel: ████████████████████████ 100% (Hoàn thành)
ActivityLog: ████████████████████████ 100% (Hoàn thành)
i18n (vi/en): ████████████████████████ 100% (Hoàn thành)
Data Import: ████████████████████████ 100% (3658 rows imported)
Tests: ████████████████████████ 100% (8 tests, 21 assertions)
Cách chạy Local Dev
cd /home/phuongtc/vibecode/minicrm
php artisan migrate:fresh --seed
php artisan serve
# Admin panel: http://localhost:8000/admin
# Support panel: http://localhost:8000/support
php artisan test # 8 tests (21 assertions)
Data Import
php artisan app:import-cskh ai_instructions/CSKH.xlsx --dry-run # phân tích
php artisan app:import-cskh ai_instructions/CSKH.xlsx # import thật
Export Backup
php artisan app:export-backup
php artisan app:export-backup --path=/custom/path --pretty
php artisan app:export-backup --tables=feedback,customers,products
Tài khoản test (seeded)
| Role | Password | |
|---|---|---|
| Admin | admin@minicrm.local | password |
| Manager | manager@minicrm.local | password |
| Staff | staff@minicrm.local | password |
Tech Stack
- PHP 8.3, Laravel 13.6.0, Filament 5.6.1
- Database: SQLite (
database/database.sqlite) - Composer:
/home/phuongtc/composer - Spatie: laravel-permission (RBAC)
- Testing: Pest PHP
File hướng dẫn cho AI Agent
| File | Nội dung |
|---|---|
AGENTS.md |
Hướng dẫn toàn diện: chạy, cấu trúc, workflow, RBAC, gotchas, patterns |
CODEBASE_SNAPSHOT.md |
Snapshot cấu trúc codebase (đọc thay vì scan code) |
TASKS_ROADMAP.md |
File này — roadmap + tiến độ |
docs/I18N_GUIDE.md |
Hướng dẫn đa ngôn ngữ chi tiết |
docs/ENUM_GUIDE.md |
Hướng dẫn thêm Enum mới |
UI_DESIGN_BRIEF.md |
Thiết kế UI chi tiết (horizontal top bar) |
webappUI/aftersales_crm_core/DESIGN.md |
Design tokens (colors, typography, spacing) |
luutru/ |
Archive các file đã lỗi thời (AI_01-03 specs, SOP_des, PROGRESS cũ...) |