update DOC
This commit is contained in:
@@ -10,8 +10,8 @@
|
||||
| Mục | Giá trị |
|
||||
|------|--------|
|
||||
| Framework | Laravel 13.6.0 |
|
||||
| Admin Panel | Filament 5.6.1 |
|
||||
| Auth/RBAC | Spatie laravel-permission (3 roles: admin, manager, staff) |
|
||||
| Panels | Filament 5.6.1 — 2 panels: `/admin` (đầy đủ) + `/support` (rút gọn) |
|
||||
| Auth/RBAC | Spatie laravel-permission (3 roles: admin, manager, staff, 29 permissions) |
|
||||
| Database | SQLite (`database/database.sqlite`) |
|
||||
| Testing | Pest PHP |
|
||||
| PHP | 8.3 |
|
||||
@@ -32,6 +32,9 @@
|
||||
app/
|
||||
├── Filament/
|
||||
│ ├── Resources/
|
||||
│ │ ├── ActivityLogs/ # NEW: Audit trail (read-only)
|
||||
│ │ │ ├── ActivityLogResource.php
|
||||
│ │ │ └── Pages/ListActivityLogs.php
|
||||
│ │ ├── Customers/
|
||||
│ │ │ ├── CustomerResource.php
|
||||
│ │ │ ├── Pages/
|
||||
@@ -56,7 +59,7 @@ app/
|
||||
│ │ │ │ └── FeedbackForm.php
|
||||
│ │ │ └── Tables/
|
||||
│ │ │ └── FeedbackTable.php
|
||||
│ │ ├── Contracts/ # NEW
|
||||
│ │ ├── Contracts/
|
||||
│ │ │ ├── ContractResource.php
|
||||
│ │ │ ├── Pages/
|
||||
│ │ │ │ ├── CreateContract.php
|
||||
@@ -86,32 +89,32 @@ app/
|
||||
│ │ │ │ └── FeedbackTagForm.php
|
||||
│ │ │ └── Tables/
|
||||
│ │ │ └── FeedbackTagsTable.php
|
||||
│ │ └── Products/
|
||||
│ │ ├── ProductResource.php
|
||||
│ │ ├── Pages/
|
||||
│ │ │ ├── CreateProduct.php
|
||||
│ │ │ ├── EditProduct.php
|
||||
│ │ │ └── ListProducts.php
|
||||
│ │ ├── RelationManagers/
|
||||
│ │ │ ├── ContractsRelationManager.php # NEW
|
||||
│ │ │ ├── HandoversRelationManager.php # NEW
|
||||
│ │ │ └── ProductServicesRelationManager.php # NEW
|
||||
│ │ ├── Schemas/
|
||||
│ │ │ └── ProductForm.php
|
||||
│ │ └── Tables/
|
||||
│ │ └── ProductsTable.php
|
||||
│ │ └── Users/ # NEW
|
||||
│ │ ├── UserResource.php # Admin-only user management
|
||||
│ │ ├── Pages/
|
||||
│ │ │ ├── CreateUser.php
|
||||
│ │ │ ├── EditUser.php
|
||||
│ │ │ └── ListUsers.php # Tabs: All/Admin/Manager/Staff
|
||||
│ │ ├── Schemas/
|
||||
│ │ │ └── UserForm.php # name, email, password, role (dynamic)
|
||||
│ │ └── Tables/
|
||||
│ │ └── UsersTable.php # name, email, role badge
|
||||
│ │ └── Roles/ # NEW
|
||||
│ │ ├── RoleResource.php # Admin-only role management
|
||||
│ │ ├── Products/
|
||||
│ │ │ ├── ProductResource.php
|
||||
│ │ │ ├── Pages/
|
||||
│ │ │ │ ├── CreateProduct.php
|
||||
│ │ │ │ ├── EditProduct.php
|
||||
│ │ │ │ └── ListProducts.php
|
||||
│ │ │ ├── RelationManagers/
|
||||
│ │ │ │ ├── ContractsRelationManager.php
|
||||
│ │ │ │ ├── HandoversRelationManager.php
|
||||
│ │ │ │ └── ProductServicesRelationManager.php
|
||||
│ │ │ ├── Schemas/
|
||||
│ │ │ │ └── ProductForm.php
|
||||
│ │ │ └── Tables/
|
||||
│ │ │ └── ProductsTable.php
|
||||
│ │ ├── Users/ # Admin-only user management
|
||||
│ │ │ ├── UserResource.php
|
||||
│ │ │ ├── Pages/
|
||||
│ │ │ │ ├── CreateUser.php
|
||||
│ │ │ │ ├── EditUser.php
|
||||
│ │ │ │ └── ListUsers.php # Tabs: All/Admin/Manager/Staff
|
||||
│ │ │ ├── Schemas/
|
||||
│ │ │ │ └── UserForm.php # name, email, password, role (dynamic)
|
||||
│ │ │ └── Tables/
|
||||
│ │ │ └── UsersTable.php # name, email, role badge
|
||||
│ │ └── Roles/ # Admin-only role management
|
||||
│ │ ├── RoleResource.php
|
||||
│ │ ├── Pages/
|
||||
│ │ │ ├── CreateRole.php
|
||||
│ │ │ ├── EditRole.php
|
||||
@@ -124,20 +127,23 @@ app/
|
||||
│ ├── AvgProcessingTimeWidget.php # 4 stats: resolved count, avg time, pending, escalated
|
||||
│ ├── HandlerPerformanceWidget.php # bar chart: avg time per handler
|
||||
│ └── ResolvedTicketsWidget.php # table: resolved tickets awaiting closure
|
||||
├── Console/ # NEW
|
||||
├── Console/
|
||||
│ └── Commands/
|
||||
│ ├── ImportCskh.php # app:import-cskh command
|
||||
│ └── ExportBackup.php # app:export-backup command (JSON backup)
|
||||
├── Enums/ # NEW
|
||||
├── Enums/
|
||||
│ ├── ContractType.php # SALE/LEASE/BCC
|
||||
│ ├── ContractStatus.php # ACTIVE/EXPIRED/LIQUIDATED
|
||||
│ ├── HandoverStatus.php # NOT_READY/READY/SCHEDULED/HANDED_OVER
|
||||
│ └── ServiceType.php # MANAGEMENT_FEE/GRATITUDE/SELF_BUSINESS
|
||||
├── Http/
|
||||
│ └── Controllers/
|
||||
│ └── Controller.php
|
||||
│ ├── Controllers/
|
||||
│ │ └── Controller.php
|
||||
│ └── Middleware/
|
||||
│ └── HandleUploadErrors.php
|
||||
├── Models/
|
||||
│ ├── Contract.php # NEW
|
||||
│ ├── ActivityLog.php # NEW: Audit trail (user_id, action, description, metadata)
|
||||
│ ├── Contract.php
|
||||
│ ├── Customer.php
|
||||
│ ├── CustomerProduct.php # pivot model (customer_product table)
|
||||
│ ├── Department.php
|
||||
@@ -146,27 +152,32 @@ app/
|
||||
│ ├── FeedbackChannel.php
|
||||
│ ├── FeedbackInteraction.php
|
||||
│ ├── FeedbackTag.php
|
||||
│ ├── Handover.php # NEW
|
||||
│ ├── Handover.php
|
||||
│ ├── Product.php
|
||||
│ ├── ProductService.php # NEW
|
||||
│ ├── ProductService.php
|
||||
│ ├── TicketTransferLog.php
|
||||
│ └── User.php
|
||||
├── Notifications/
|
||||
│ ├── TicketClosed.php
|
||||
│ └── TicketTransferred.php
|
||||
├── Policies/
|
||||
│ ├── ContractPolicy.php # NEW
|
||||
│ ├── ActivityLogPolicy.php # NEW: Admin-only
|
||||
│ ├── ContractPolicy.php
|
||||
│ ├── CustomerPolicy.php
|
||||
│ ├── FeedbackChannelPolicy.php
|
||||
│ ├── FeedbackPolicy.php
|
||||
│ └── ProductPolicy.php
|
||||
│ ├── ProductPolicy.php
|
||||
│ ├── RolePolicy.php
|
||||
│ └── UserPolicy.php
|
||||
├── Providers/
|
||||
│ ├── AppServiceProvider.php
|
||||
│ └── Filament/
|
||||
│ └── AdminPanelProvider.php
|
||||
│ ├── AdminPanelProvider.php # Panel đầy đủ (/admin)
|
||||
│ └── SupportPanelProvider.php # Panel rút gọn (/support)
|
||||
├── Rules/
|
||||
│ └── RequireProofOfResolution.php
|
||||
└── Services/
|
||||
├── ActivityLogger.php # NEW: static log() cho audit trail
|
||||
├── ClosingService.php
|
||||
├── FileService.php
|
||||
└── TransferService.php
|
||||
@@ -174,8 +185,37 @@ app/
|
||||
|
||||
---
|
||||
|
||||
## Dual Panel Architecture
|
||||
|
||||
### Admin Panel (`/admin`) — `AdminPanelProvider.php`
|
||||
Đầy đủ tất cả modules:
|
||||
- Resources: Feedback, Customer, Product, Contract, FeedbackChannel, FeedbackTag, User, Role, ActivityLog
|
||||
- Widgets: ResolvedTicketsWidget, AvgProcessingTimeWidget, HandlerPerformanceWidget
|
||||
- User/Role management (admin-only)
|
||||
|
||||
### Support Panel (`/support`) — `SupportPanelProvider.php`
|
||||
Rút gọn, tập trung feedback:
|
||||
- Resources: Feedback, Customer, Product, FeedbackChannel, FeedbackTag, ActivityLog
|
||||
- Widgets: ResolvedTicketsWidget, AvgProcessingTimeWidget, HandlerPerformanceWidget
|
||||
|
||||
---
|
||||
|
||||
## Models — Chi tiết
|
||||
|
||||
### ActivityLog (`activity_logs`) — NEW
|
||||
| Cột | Kiểu |
|
||||
|-----|------|
|
||||
| id | bigint PK |
|
||||
| user_id | FK->users nullable |
|
||||
| action | string (import/export/transfer/close/create/update/delete) |
|
||||
| description | text |
|
||||
| subject_type | string nullable |
|
||||
| subject_id | bigint nullable |
|
||||
| metadata | json nullable |
|
||||
| created_at | timestamp |
|
||||
|
||||
Relationships: `user()` BelongsTo
|
||||
|
||||
### Product (`products`)
|
||||
| Cột | Kiểu |
|
||||
|-----|------|
|
||||
@@ -186,7 +226,7 @@ app/
|
||||
|
||||
Relationships: `customers()` BelongsToMany (pivot: customer_product, withPivot: purchase_date), `contracts()` HasMany, `handovers()` HasMany, `productServices()` HasMany
|
||||
|
||||
### ProductService (`product_services`) — NEW
|
||||
### ProductService (`product_services`)
|
||||
| Cột | Kiểu |
|
||||
|-----|------|
|
||||
| id | bigint PK |
|
||||
@@ -198,7 +238,7 @@ Relationships: `customers()` BelongsToMany (pivot: customer_product, withPivot:
|
||||
|
||||
Relationships: `product()` BelongsTo
|
||||
|
||||
### Handover (`handovers`) — NEW
|
||||
### Handover (`handovers`)
|
||||
| Cột | Kiểu |
|
||||
|-----|------|
|
||||
| id | bigint PK |
|
||||
@@ -210,7 +250,7 @@ Relationships: `product()` BelongsTo
|
||||
|
||||
Relationships: `product()` BelongsTo, `customer()` BelongsTo
|
||||
|
||||
### Contract (`contracts`) — NEW
|
||||
### Contract (`contracts`)
|
||||
| Cột | Kiểu |
|
||||
|-----|------|
|
||||
| id | bigint PK |
|
||||
@@ -266,7 +306,7 @@ Relationships: `manager()` BelongsTo User, `feedbacks()` HasMany, `transferLogsF
|
||||
| password | string |
|
||||
| role | string (admin/manager/staff) |
|
||||
|
||||
Uses Spatie `HasRoles`. Relationships: `assignedFeedbacks()` HasMany Feedback.
|
||||
Uses Spatie `HasRoles`. Relationships: `assignedFeedbacks()` HasMany Feedback, `activityLogs()` HasMany.
|
||||
|
||||
### Feedback (`feedback`)
|
||||
| Cột | Kiểu |
|
||||
@@ -323,6 +363,7 @@ Relationships: `feedback()`, `interaction()`, `user()`. Scopes: `byCollection()`
|
||||
| name | string |
|
||||
| slug | string unique |
|
||||
| icon | string nullable |
|
||||
| color | string nullable |
|
||||
| is_active | boolean default true |
|
||||
|
||||
Relationships: `feedbacks()` HasMany
|
||||
@@ -353,27 +394,31 @@ Relationships: `feedback()`, `fromDepartment()`, `toDepartment()`, `sender()`
|
||||
|
||||
## Services — Tóm tắt
|
||||
|
||||
### ActivityLogger (`app/Services/ActivityLogger.php`) — NEW
|
||||
- `ActivityLogger::log(action, description, subject?, metadata?, userId?)`: Static method. Tạo ActivityLog record cho audit trail. Dùng trong Import/Export/Transfer/Close/Create/Update/Delete.
|
||||
|
||||
### TransferService (`app/Services/TransferService.php`)
|
||||
- `transfer(Feedback, Department, reason, User, ?int $newHandlerId)`: Tạo TicketTransferLog, cập nhật current_department_id + assigned_to, gửi TicketTransferred notification cho manager đích.
|
||||
- Validate reason không được rỗng (ValidationException).
|
||||
|
||||
### FileService (`app/Services/FileService.php`)
|
||||
- `upload()`: Validate (jpg/png/pdf/mp4/mov, ≤20MB), store vào public disk, tạo FeedbackAttachment record.
|
||||
- `getTemporaryUrl()` / `getPreviewUrl()`: Signed URL cho private file.
|
||||
- `getByCollection()` / `hasCollection()`: Query collection-based attachments.
|
||||
|
||||
### ClosingService (`app/Services/ClosingService.php`)
|
||||
- `close(Feedback, User)`: 4 guard: status ≠ closed, staff → 403, manager chỉ đóng ticket phòng mình, phải có proof_of_resolution attachment (FileService::hasCollection). Gửi TicketClosed notification.
|
||||
- `resolve(Feedback, User)`: Đánh dấu resolved (không role gate).
|
||||
|
||||
### FileService (`app/Services/FileService.php`)
|
||||
- `upload()`: Validate (jpg/png/pdf/mp4/mov, ≤20MB), store vào private local disk (`feedback-attachments/`), tạo FeedbackAttachment record.
|
||||
- `getTemporaryUrl()` / `getPreviewUrl()`: Signed URL cho private file.
|
||||
- `getByCollection()` / `hasCollection()`: Query collection-based attachments.
|
||||
|
||||
---
|
||||
|
||||
## Policies — Tóm tắt
|
||||
|
||||
> **Note:** Policies now use Spatie `hasPermissionTo()` instead of `hasRole()` for granular permission control.
|
||||
> **Note:** Policies use Spatie `hasPermissionTo()` instead of `hasRole()` for granular permission control.
|
||||
|
||||
| Policy | viewAny/view | create | update | delete | restore/forceDelete |
|
||||
|--------|-------------|--------|--------|--------|---------------------|
|
||||
| ActivityLogPolicy | admin only | — | — | — | — |
|
||||
| ContractPolicy | view-contract | create-contract | update-contract | delete-contract | admin only |
|
||||
| FeedbackPolicy | view-feedback | create-feedback | update-feedback | delete-feedback | admin only |
|
||||
| ProductPolicy | view-product | create-product | update-product | delete-product | admin only |
|
||||
@@ -386,6 +431,7 @@ Relationships: `feedback()`, `fromDepartment()`, `toDepartment()`, `sender()`
|
||||
|
||||
## Filament Navigation Structure
|
||||
|
||||
### Admin Panel (`/admin`)
|
||||
```
|
||||
Dashboard (AccountWidget + 3 custom widgets)
|
||||
├── Customer Care (group)
|
||||
@@ -394,8 +440,24 @@ Dashboard (AccountWidget + 3 custom widgets)
|
||||
├── Products (heroicon-o-building-storefront, sort=1)
|
||||
├── Customers (heroicon-o-user-group, sort=2)
|
||||
├── Channels (heroicon-o-inbox-stack, sort=3)
|
||||
├── Contracts (heroicon-o-document-text, sort=4) # NEW
|
||||
└── Tags (heroicon-o-tag, default sort)
|
||||
├── Contracts (heroicon-o-document-text, sort=4)
|
||||
├── Tags (heroicon-o-tag, default sort)
|
||||
├── Activity Logs (heroicon-o-clock, sort=7) — admin only
|
||||
├── Users (heroicon-o-users, sort=5) — admin only
|
||||
└── Roles (heroicon-o-shield-check, sort=6) — admin only
|
||||
```
|
||||
|
||||
### Support Panel (`/support`)
|
||||
```
|
||||
Dashboard (3 custom widgets)
|
||||
├── Customer Care (group)
|
||||
│ └── Feedbacks
|
||||
└── Management (group)
|
||||
├── Products
|
||||
├── Customers
|
||||
├── Channels
|
||||
├── Tags
|
||||
└── Activity Logs
|
||||
```
|
||||
|
||||
---
|
||||
@@ -407,7 +469,7 @@ Dashboard (AccountWidget + 3 custom widgets)
|
||||
|
||||
---
|
||||
|
||||
## Database Migration files (23 files)
|
||||
## Database Migration files (25 files)
|
||||
|
||||
| # | File | Tables |
|
||||
|---|------|--------|
|
||||
@@ -430,17 +492,19 @@ Dashboard (AccountWidget + 3 custom widgets)
|
||||
| 17 | `2026_04_27_083000_add_collection_to_feedback_attachments_table` | (modify feedback_attachments) add uuid, disk, collection |
|
||||
| 18 | `2026_04_27_140000_fix_attachment_disk_default` | (modify feedback_attachments) fix disk default private→local |
|
||||
| 19 | `2026_04_27_150000_create_notifications_table` | notifications |
|
||||
| 20 | `2026_05_01_000000_create_contracts_table` | **(NEW)** contracts |
|
||||
| 21 | `2026_05_01_000001_add_contract_id_to_feedback_table` | **(NEW)** add contract_id FK to feedback |
|
||||
| 22 | `2026_05_01_000002_create_handovers_table` | **(NEW)** handovers |
|
||||
| 23 | `2026_05_01_000003_create_product_services_table` | **(NEW)** product_services |
|
||||
| 20 | `2026_05_01_000000_create_contracts_table` | contracts |
|
||||
| 21 | `2026_05_01_000001_add_contract_id_to_feedback_table` | (modify feedback) add contract_id FK |
|
||||
| 22 | `2026_05_01_000002_create_handovers_table` | handovers |
|
||||
| 23 | `2026_05_01_000003_create_product_services_table` | product_services |
|
||||
| 24 | `2026_05_01_000004_add_color_to_feedback_channels_table` | (modify feedback_channels) add color |
|
||||
| 25 | `2026_05_09_104519_create_activity_logs_table` | activity_logs |
|
||||
|
||||
---
|
||||
|
||||
## Seeder (AfterSalesSeeder + PermissionSeeder) — Data mẫu
|
||||
|
||||
- 3 users (admin, manager, staff) + Spatie roles
|
||||
- **29 granular permissions** (PermissionSeeder) — NEW
|
||||
- **29 granular permissions** (PermissionSeeder)
|
||||
- Feedback: view/create/update/delete, add-interaction, close-ticket, transfer-department
|
||||
- Products/Customers/Contracts/Channels/Tags: view/create/update/delete each
|
||||
- Dashboard: view-dashboard-widgets, export-data
|
||||
@@ -459,12 +523,9 @@ Dashboard (AccountWidget + 3 custom widgets)
|
||||
- 1 ticket_transfer_log
|
||||
- 3 feedback_attachments (2 proof_of_resolution, 1 customer_evidence)
|
||||
|
||||
---|---
|
||||
| 22 | `2026_05_01_000003_create_product_services_table` | **(NEW)** product_services |
|
||||
|
||||
---
|
||||
|
||||
## Data Import (`app:import-cskh`) — NEW
|
||||
## Data Import (`app:import-cskh`)
|
||||
|
||||
Command: `php artisan app:import-cskh {file_path}`
|
||||
- Sử dụng `spatie/simple-excel` với Lazy Collection (chống OOM)
|
||||
@@ -493,12 +554,13 @@ Tổng: 8 tests, 21 assertions.
|
||||
|
||||
1. **Form components:** `Filament\Forms\Components\*` (Select, TextInput, Textarea, Toggle, FileUpload, RichEditor)
|
||||
2. **Schema/layout:** `Filament\Schemas\Components\*` (Section, Schema)
|
||||
3. **Service access:** `App::make(FileService::class)` hoặc inject constructor
|
||||
3. **Service access:** `App::make(FileService::class)` hoặc inject constructor. `ActivityLogger::log()` là static.
|
||||
4. **Role check:** `$user->hasRole('admin')` / `$user->hasRole(['admin', 'manager'])`
|
||||
5. **Dynamic form field:** dùng `$get` function injection, KHÔNG dùng `$component->getLivewire()->data`
|
||||
6. **FileUpload với dehydrated(false):** File được Filament lưu trước, chỉ cần tạo FeedbackAttachment record trong after()/afterSave() — KHÔNG re-upload qua FileService
|
||||
7. **Private disk:** files lưu ở `storage/app/private/feedback-attachments/`, truy cập qua signed URL từ FileService
|
||||
7. **Private disk:** files lưu ở `storage/app/private/feedback-attachments/`, truy cập qua signed URL từ FileService. Luôn dùng `disk('public')` cho FileUpload.
|
||||
8. **Navigation group icons:** Filament 5 báo lỗi nếu cả navigation group VÀ child items đều có icons
|
||||
9. **Dual Panel:** Cả 2 panel share models, services, policies, database, translations
|
||||
|
||||
---
|
||||
|
||||
@@ -506,9 +568,10 @@ Tổng: 8 tests, 21 assertions.
|
||||
|
||||
| File | Nội dung |
|
||||
|------|----------|
|
||||
| `AGENTS.md` | Hướng dẫn cho AI Agent: cách chạy, cấu trúc, workflow, RBAC, gotchas |
|
||||
| `PROGRESS.md` | Lịch sử tiến độ hoàn thành (8 giai đoạn + bug fix) |
|
||||
| `ai_instructions/AI_01_*.md` | Business Logic & Policies (hợp đồng snapshot, transfer policy, handover) |
|
||||
| `ai_instructions/AI_02_*.md` | Database Schema Upgrade (contracts, handovers, product_services) |
|
||||
| `ai_instructions/AI_03_*.md` | Data Import Pipeline (spatie/simple-excel, lazy collection) |
|
||||
| `TASKS_ROADMAP.md` | Roadmap: việc đã làm, đang làm, sẽ làm |
|
||||
| `AGENTS.md` | Hướng dẫn cho AI Agent: cách chạy, cấu trúc, workflow, RBAC, gotchas, patterns |
|
||||
| `TASKS_ROADMAP.md` | Roadmap + lịch sử tiến độ hoàn thành |
|
||||
| `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 (tham khảo nếu cần) |
|
||||
|
||||
Reference in New Issue
Block a user