Quản lý Hợp đồng - Contract Management
1. Tổng quan
1.1. Mục đích
Module quản lý hợp đồng là nền tảng của toàn bộ hệ thống, đảm bảo:
- Mọi hoạt động đều xuất phát từ hợp đồng hợp lệ
- Ngân sách và KPI được khóa chặt theo điều khoản hợp đồng
- Nghiệm thu và thanh toán theo đúng milestone đã thỏa thuận
- Tracking lời/lỗ theo từng scope của hợp đồng
1.2. Cấu trúc 3 tầng
Contract (Master) - Hợp đồng tổng thể
└── Scope - Gói dịch vụ độc lập
└── Milestone - Nghiệm thu và thanh toán
2. Contract (Hợp đồng tổng)
2.1. Chức năng chính
Contract chỉ quản lý:
- Pháp lý: Thông tin hợp đồng, khách hàng, thời gian
- Tài chính tổng: Giá trị tổng, margin mục tiêu
- Trạng thái: Draft, Active, Completed, Cancelled
Contract KHÔNG quản lý chi tiết:
- Ngân sách cụ thể cho từng kênh
- KPI chi tiết
- Payment schedule → Những thứ này thuộc về Scope
2.2. Use Cases
UC-CNT-01: Tạo hợp đồng mới
Actor: Kế toán
Precondition:
- User có quyền tạo contract
- Đã có thông tin khách hàng
Main Flow:
- Kế toán nhập thông tin contract:
- Contract code (unique)
- Client
- Start date & End date
- Total value
- Margin target
- Currency
- Hệ thống validate:
- Contract code chưa tồn tại
- End date > Start date
- Total value > 0
- Hệ thống tạo contract với status = "draft"
- Hệ thống log audit trail
Postcondition:
- Contract được tạo với status "draft"
- Sẵn sàng để tạo Scope
UC-CNT-02: Kích hoạt hợp đồng
Actor: Kế toán / PM
Precondition:
- Contract đang ở status "draft"
- Contract đã có ít nhất 1 Scope
- Mỗi Scope đã có Payment Milestone
Main Flow:
- User click "Activate Contract"
- Hệ thống validate:
- Có ít nhất 1 scope
- Mỗi scope có ít nhất 1 milestone
- Tổng scope.revenue <= contract.total_value
- Hệ thống chuyển status = "active"
- Hệ thống gửi notification cho team
Postcondition:
- Contract status = "active"
- Các scope con có thể bắt đầu thực thi
UC-CNT-03: Xem chi tiết hợp đồng
Actor: Tất cả roles
Main Flow:
- User chọn contract từ danh sách
- Hệ thống hiển thị:
- Thông tin contract
- Danh sách scope
- Tổng hợp tài chính:
- Total value
- Total revenue (sum of scope.revenue)
- Total cost (sum of scope.cost)
- Actual profit
- Profit margin %
- Timeline và status
UC-CNT-04: Sửa hợp đồng
Actor: Kế toán
Precondition:
- Contract status = "draft" hoặc "active"
- User có quyền edit
Main Flow:
- User sửa thông tin contract (trừ contract_code)
- Hệ thống validate business rules
- Nếu đang active và thay đổi total_value:
- Hệ thống check: total_value >= sum(scope.revenue)
- Hệ thống save và log audit trail
Exception Flow:
- Nếu total_value < sum(scope.revenue) → error message
UC-CNT-05: Đóng hợp đồng (Complete)
Actor: Director / Kế toán
Precondition:
- Contract status = "active"
- Tất cả scope đã completed
- Tất cả milestone đã paid
Main Flow:
- User click "Complete Contract"
- Hệ thống validate:
- Tất cả scope.status = "completed"
- Tất cả milestone.status = "paid"
- Hệ thống tính final P&L
- Hệ thống chuyển status = "completed"
- Hệ thống archive contract
Postcondition:
- Contract status = "completed"
- Không thể edit nữa (read-only)
3. Scope (Gói dịch vụ)
3.1. Tại sao cần Scope?
Vấn đề: Một hợp đồng digital marketing thường bao gồm nhiều kênh và dịch vụ:
- Facebook Ads
- TikTok Ads
- Website
- SEO
- Hosting
Mỗi kênh có:
- Ngân sách riêng
- KPI riêng
- Thời gian riêng
- Nghiệm thu riêng
- Dòng tiền riêng (TikTok xong trước thì thu tiền trước, không cần chờ Facebook)
Giải pháp: Chia hợp đồng thành nhiều Scope, mỗi scope là một đơn vị:
- Tính ngân sách
- Tính KPI
- Nghiệm thu
- Thu tiền
- Tính lời/lỗ
3.2. Các loại Scope
| Service Type | Channel Examples | KPI Type | Pricing Model |
|---|---|---|---|
| ads | FB, TikTok, Google | Leads, Sales, Traffic | CPA, CPL, CPC, CPM |
| web | Website | Deliverable | Fixed price, Milestone |
| app | Mobile App | Deliverable | Fixed price, Milestone |
| seo | Organic Search | Rankings, Traffic | Monthly retainer |
| hosting | Infrastructure | Uptime | Monthly fee |
| kol | Influencer | Views, Engagement | Per post, CPV |
| branding | Video, Design | Deliverable | Fixed price |
| outsource | Any | Custom | Varies |
3.3. Attributes linh hoạt
Mỗi scope type có thể có attributes riêng (JSON field):
Ads Scope Attributes
{
"target_audience": "Office workers 25-45",
"region": "HCM, HN",
"product": "Kewpie Sesame",
"campaign_type": "Always-on",
"break_even_cpl": 16000
}
Web Scope Attributes
{
"platform": "Next.js",
"cms": "MongoREST",
"language": "VN, EN",
"hosting": "Cloudflare",
"delivery": "Source + Deploy",
"responsive": true
}
App Scope Attributes
{
"platforms": ["iOS", "Android"],
"framework": "React Native",
"features": ["Push notification", "Payment", "Map"],
"app_store": true,
"google_play": true
}
3.4. Use Cases cho Scope
UC-SCP-01: Tạo Scope mới
Actor: Kế toán / PM
Precondition:
- Contract đã tồn tại
- User có quyền tạo scope
Main Flow:
- User chọn contract và click "Add Scope"
- User nhập thông tin scope:
- Scope code (unique trong contract)
- Service type
- Channel
- Name & Description
- Budget / Revenue
- KPI type & target
- Pricing model
- Start/End date
- Attributes (optional)
- Hệ thống validate:
- Scope code unique trong contract
- Revenue > 0
- Start/End date trong khoảng contract date
- Sum(all scope.revenue) <= contract.total_value
- Hệ thống tạo scope với status = "pending"
Postcondition:
- Scope được tạo
- Sẵn sàng để tạo Campaign Plan (nếu là ads) hoặc Milestone
UC-SCP-02: Phân bổ ngân sách cho Scope Ads
Actor: PM
Precondition:
- Scope.service_type = "ads"
- Scope.status = "pending" hoặc "active"
Main Flow:
- PM click "Allocate Budget"
- PM nhập hoặc import (Excel/CSV):
- Campaign code
- Budget allocated
- KPI target
- Start/End date
- Hệ thống validate:
- Sum(campaign.budget) <= scope.budget
- Sum(campaign.kpi) >= scope.kpi_target
- Expected margin >= scope.margin_target
- Hệ thống tạo các Campaign Plan
- Hệ thống cập nhật scope.status = "active"
Postcondition:
- Campaign Plans được tạo
- Scope ready để execute
UC-SCP-03: Tạo Milestone cho Scope
Actor: Kế toán
Precondition:
- Scope đã tồn tại
- User có quyền tạo milestone
Main Flow:
- User chọn scope và click "Add Milestone"
- User nhập thông tin milestone:
- Name (Phase 1, Phase 2...)
- Due date
- Amount
- KPI required (cho ads scope)
- Deliverable (cho project scope)
- Acceptance criteria
- Hệ thống validate:
- Sum(milestone.amount) <= scope.revenue
- Due date <= scope.end_date
- Hệ thống tạo milestone với status = "pending"
Postcondition:
- Milestone được tạo
- Tracking được kích hoạt
UC-SCP-04: Xem tình trạng Scope
Actor: Tất cả roles
Main Flow:
-
User chọn scope
-
Hệ thống hiển thị dashboard:
Cho Ads Scope:
- Budget allocated vs Spend to date
- Budget remaining
- Budget utilization %
- KPI target vs KPI achieved
- KPI remaining
- KPI completion %
- Real-time profit/loss
- Margin realized vs target
Cho Project Scope:
- Project timeline
- Deliverables checklist
- Vendor assignments
- Cost breakdown
- Profit/loss
Common:
- Milestone progress
- Payment status
- Alerts & warnings
UC-SCP-05: Cảnh báo vượt ngân sách
Actor: System (auto)
Trigger: Spend >= 95% budget
Main Flow:
- Hệ thống phát hiện scope spend >= 95% budget
- Hệ thống tạo alert:
- Type: "budget_warning"
- Severity: "high"
- Message: "Scope {name} đã dùng {%} ngân sách"
- Hệ thống gửi notification:
- Email to PM
- Slack/Teams notification
- In-app alert
- Hệ thống highlight scope trong dashboard
Postcondition:
- PM được thông báo
- Có thể điều chỉnh kế hoạch
UC-SCP-06: Tự động dừng khi hết ngân sách
Actor: System (auto)
Trigger: Spend >= 100% budget
Main Flow:
- Hệ thống phát hiện scope spend >= 100%
- Nếu có API integration:
- Hệ thống gọi API pause tất cả campaign
- Hệ thống cập nhật scope.status = "paused"
- Hệ thống tạo critical alert
- Hệ thống gửi notification khẩn cấp
Postcondition:
- Campaigns bị pause
- Scope status = "paused"
- PM và Director được thông báo
Manual Override:
- Director có thể approve tăng budget
- Khi được approve, scope được active lại
4. Scope Lifecycle
4.1. State Diagram
pending → active → (paused ⇄ active) → completed
↓ ↑
cancelled ← ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
4.2. State Transitions
| From | To | Trigger | Condition |
|---|---|---|---|
| pending | active | User activates | Có campaign plan hoặc milestone |
| active | paused | Budget limit reached | Spend >= 100% |
| active | paused | Manual pause | User action |
| paused | active | Manual resume | Director approval |
| active | completed | Scope finished | All milestones completed |
| * | cancelled | Contract cancelled | User action |
5. Multi-Channel Contract Example
5.1. Hợp đồng Kewpie 2026
Contract:
- Code: KWP2026
- Client: Kewpie Vietnam
- Total value: 2,400,000,000 VND
- Duration: 2026-01-01 to 2026-12-31
- Margin target: 20%
Scopes:
| Scope Code | Service | Budget | KPI Target | Revenue |
|---|---|---|---|---|
| FB01 | Facebook Ads | 800M | 50,000 leads | 1,000M |
| TT01 | TikTok Ads | 400M | 10M views | 500M |
| WEB01 | Landing Page | - | 1 website | 50M |
| HOST01 | Hosting 12 months | - | 99.9% uptime | 12M |
Payment Schedule:
FB01:
- Phase 1 (Q1): 15,000 leads → 300M
- Phase 2 (Q2): 20,000 leads → 400M
- Phase 3 (Q3): 15,000 leads → 300M
TT01:
- Phase 1 (H1): 5M views → 250M
- Phase 2 (H2): 5M views → 250M
WEB01:
- Design approved → 25M
- Go-live → 25M
HOST01:
- Monthly: 1M/month
Lợi ích của mô hình này:
- TikTok hoàn thành sớm (tháng 6) → Thu tiền sớm → Có cashflow chạy tiếp FB
- Website delay không ảnh hưởng cashflow của Ads
- Hosting thu đều hàng tháng → Ổn định dòng tiền
6. Business Rules
6.1. Contract Level
- Contract code phải unique trong hệ thống
- End date phải sau Start date
- Total value > 0
- Margin target >= 0 và <= 100
- Không thể xóa contract khi có scope active
6.2. Scope Level
- Scope code phải unique trong mỗi contract
- Tổng scope.revenue <= contract.total_value
- Scope.start_date >= contract.start_date
- Scope.end_date <= contract.end_date
- Không thể xóa scope khi có campaign plan hoặc milestone
6.3. Milestone Level
- Tổng milestone.amount = scope.revenue (±5% tolerance)
- Milestone.due_date <= scope.end_date
- Không thể xóa milestone khi status = "invoiced" hoặc "paid"
7. Reporting
7.1. Contract Dashboard
- Tổng số contract: Active / Completed / Cancelled
- Total contract value: By status
- Revenue forecast: By month
- Profit margin: Realized vs Target
- At-risk contracts: Margin < target
7.2. Scope Dashboard
- Scope by service type: Ads / Web / App / Others
- Scope by status: Active / Paused / Completed
- Budget utilization: By scope
- KPI achievement: By scope
- Top performing scopes: By profit margin
- Under-performing scopes: By KPI gap
8. Integration Points
8.1. CRM Integration
- Import client data from CRM
- Sync contract status back to CRM
- Link contract to CRM opportunity
8.2. Accounting System
- Export invoice data
- Sync payment status
- Generate P&L report
8.3. Project Management Tools
- Link scope to project (for web/app)
- Sync milestone status
- Update deliverable progress
9. Security & Permissions
9.1. Role-Based Access Control
| Action | Accountant | PM | Ads Team | Finance | Director |
|---|---|---|---|---|---|
| Create Contract | ✓ | - | - | - | ✓ |
| Edit Contract | ✓ | - | - | - | ✓ |
| Delete Contract | - | - | - | - | ✓ |
| Create Scope | ✓ | ✓ | - | - | ✓ |
| Edit Scope | ✓ | ✓ (owner) | - | - | ✓ |
| View Financial | ✓ | ✓ (own) | - | ✓ | ✓ |
| Create Milestone | ✓ | - | - | - | ✓ |
| View All Contracts | ✓ | - | - | ✓ | ✓ |
9.2. Audit Trail
Tất cả thay đổi quan trọng phải log:
- Who: User ID
- What: Action (create/update/delete)
- When: Timestamp
- Old value & New value
- IP address
10. Validation & Error Handling
10.1. Input Validation
- Contract code: Alphanumeric, max 20 chars
- Total value: Positive number, max 15 digits
- Dates: Valid date format, logical order
- Email: Valid email format
10.2. Error Messages
| Error Code | Message | Resolution |
|---|---|---|
| CNT-001 | Contract code already exists | Use different code |
| CNT-002 | Total value must be positive | Enter valid amount |
| CNT-003 | End date must be after start date | Adjust dates |
| SCP-001 | Total scope revenue exceeds contract value | Reduce scope revenue or increase contract value |
| SCP-002 | Scope dates outside contract period | Adjust scope dates |
| MLS-001 | Total milestone amount doesn't match scope revenue | Adjust milestone amounts |
11. Best Practices
11.1. Contract Setup
- Tạo contract trước
- Tạo tất cả scope cho contract
- Tạo milestone cho mỗi scope
- Review tổng thể trước khi activate
- Activate contract
11.2. Naming Convention
- Contract code:
{Client-Code}{Year}(VD: KWP2026) - Scope code:
{Channel}{Number}(VD: FB01, WEB01) - Milestone name:
Phase {N}hoặc{Month} {Year}
11.3. Documentation
- Lưu file hợp đồng PDF vào
contract_file_url - Ghi rõ notes cho các điều khoản đặc biệt
- Document acceptance criteria cho milestone