Files
minicrm/PROGRESS.md
phuongtc efa97b6c71
Some checks failed
Tests / PHP 8.3 (push) Has been cancelled
Tests / PHP 8.4 (push) Has been cancelled
Tests / PHP 8.5 (push) Has been cancelled
them log, chinh upload
2026-05-09 11:00:59 +00:00

10 KiB

AfterSales CRM - Tiến độ

Trạng thái: Hoàn thành SOP + 6/7 AI Instructions (85%)

Đã test: Tất cả routes HTTP 200, Pest 8/8 tests (21 assertions) pass ✓ Tham chiếu: SOP_des.md — Bản đặc tả hệ thống After-Sale CRM Data import: php artisan app:import-cskh ai_instructions/CSKH.xlsx — 3658 rows imported successfully

Công nghệ

  • Laravel 13.6.0 + Filament 5.6.1 + SQLite
  • PHP 8.3
  • Spatie laravel-permission (RBAC)
  • Pest PHP (testing)

Tài khoản test

Role Email Password
admin admin@minicrm.local password
manager manager@minicrm.local password
staff staff@minicrm.local password

ĐÃ 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 URL
  • TransferService: transfer department + reason required + notification
  • ClosingService: role-gated close + proof_of_resolution check
  • Policies cập nhật dùng Spatie hasRole()
  • Custom Rule RequireProofOfResolution

Giai đoạn 3: Notifications

  • TicketTransferred (Database + Mail)
  • TicketClosed (Database + Mail)

Giai đoạn 4: Filament UI

  • TransferDepartment Action trên Edit Feedback (modal: department + reason + attachment)
  • CloseTicket Action (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)

Giai đoạn 6: Testing

  • Pest cài đặt + 6 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

  • AGENTS.md cập nhật đầy đủ

Bug Fix

  • Dashboard widget lọc Manager dùng Department::where('manager_id') thay vì auth()->id()
  • Migration default disk privatelocal
  • File upload trong Interaction/Create/Edit dùng lưu thẳng FeedbackAttachment, không tạo UploadedFile giả

PM (Improvements)

  • FeedbackTable: thêm cột Department, Escalated icon, Department filter
  • EditFeedback: validation proof_of_resolution khi đổi status sang closed từ form

PASS 3 — Hoàn thiện SOP

  • HandlerPerformanceWidget: biểu đồ bar chart thời gian xử lý trung bình theo từng nhân viên
  • Department_Head: Manager chỉ đóng được ticket phòng mình quản lý (kèm test)
  • Temporary URL tích hợp vào UI: nút "View Attachments" trong Interaction History với download link
  • Cho phép upload attachment trong status_change interaction
  • Docker sẵn sàng production: Dockerfile, docker-compose, entrypoint
  • Migration notifications table

AI Instructions — Phase 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 ContractsRelationManager trên ProductResource
  • Model Product thêm contracts() HasMany
  • Seeder: 5 contracts mẫu

AI Instructions — Phase B: Snapshot Hợp đồng

  • Migration thêm contract_id FK nullable vào feedback
  • Model Feedback: thêm contract_id fillable + 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

AI Instructions — Phase 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 HandoversRelationManager trên ProductResource
  • Model Product thêm handovers() HasMany
  • Seeder: 5 handovers mẫu

AI Instructions — Phase D: Module Dịch vụ (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 ProductServicesRelationManager trên ProductResource
  • Model Product thêm productServices() HasMany
  • Seeder: 5 services mẫu

AI Instructions — Phase E: Enhancement ProductResource

  • ProductResource có 3 tabs: Contracts + Handovers + Services

AI Instructions — Phase G: Data Import Pipeline

  • Cài spatie/simple-excel (Lazy Collection, chống OOM)
  • Command app:import-cskh {file_path} --dry-run với ProgressBar
  • Pipeline: Product/Customer firstOrCreate → customer_product pivot → Contract → Handover → Service → Feedback + Interactions
  • Xử lý DateTimeImmutable object từ Excel, skip meta rows
  • Đã test thành công với CSKH.xlsx: 3658 rows → 3299 products, 2089 customers, 2637 contracts, 2077 handovers, 159 services, 71 feedbacks, 226 interactions

Còn lại (Optional)

  • Auto-suggest chuyển phòng ban dựa trên loại hợp đồng (Ticket BCC → gợi ý Pháp lý)

Granular Permissions + Export Backup + User/Role Management

  • PermissionSeeder: 29 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 use hasPermissionTo() instead of hasRole()
  • Widgets/Filament updated to use permission-based checks
  • ExportBackup command: app:export-backup (JSON, per-table, chunk 500, manifest.json)
  • UserResource: admin can create/edit/delete users + assign roles
  • RoleResource: admin can create/edit/delete roles + assign permissions
  • UserPolicy + RolePolicy (admin-only)
  • Tests updated: 8 tests, 21 assertions pass

Internationalization (i18n) — Vietnamese + English

  • Config: APP_LOCALE=vi, APP_FALLBACK_LOCALE=en in .env
  • Created lang/en/ and lang/vi/ with 3 files each: app.php, feedback.php, enums.php
  • ~120 translation keys covering: navigation, labels, status, widgets, services, notifications, enums
  • All Resources: override getPluralLabel() + getNavigationGroup() with __() calls
  • All Form fields: explicit ->label(__('key')) on TextInput, Select, Textarea, etc.
  • All Table columns: explicit ->label(__('key')) on TextColumn, IconColumn
  • All RelationManagers: $title property uses translation key
  • All Widgets: getHeading()/getDescription() methods return translated strings
  • Enums: ContractType, ContractStatus, HandoverStatus, ServiceType use __() in label()
  • Services/Notifications: all user-facing strings use translation keys
  • Blade views: all hardcoded strings replaced with __() calls
  • Filament vendor translations (57 Vietnamese files) auto-activated for UI chrome
  • Tests: 8/8 pass (21 assertions)

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 filament-custom.css
  • SVG icons: Use inline width/height attributes instead of Tailwind classes
  • GlobalSearch: Customized for all 6 Resources with multi-field search
  • RelationManager titles: Override getTitle() for proper translation
  • Enum refactoring: Added color() method, static options(), developer comments
  • Documentation: Created docs/I18N_GUIDE.md and docs/ENUM_GUIDE.md

Database Schema (final — 23 migrations)

products              customers            customer_product (pivot)
feedback_channels     feedback             feedback_interactions
feedback_attachments  feedback_tags        feedback_feedback_tag (pivot)
users                 departments          ticket_transfer_logs
permissions           roles                model_has_roles (spatie)
notifications         sessions             cache
contracts             handovers            product_services

Data Import

# Dry-run (phân tích trước, an toàn)
php artisan app:import-cskh ai_instructions/CSKH.xlsx --dry-run

# Import thật
php artisan app:import-cskh ai_instructions/CSKH.xlsx

Local Dev

cd /home/phuongtc/vibecode/minicrm
php artisan migrate:fresh --seed
php artisan serve
# Mở http://localhost:8000/admin
php artisan test  # 8 tests (21 assertions)

Hướng dẫn cho AI Agent khác

  • CODEBASE_SNAPSHOT.md — Toàn bộ cấu trúc codebase (đọc thay vì scan code)
  • TASKS_ROADMAP.md — Roadmap: đã làm, đang làm, sẽ làm
  • AGENTS.md — Hướng dẫn chạy, workflow, RBAC, gotchas
  • 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