# PMS Phase 1 — Task Cards (Task Manager Spec)

> **WBS index:** [docs/project-management/wbs/00-master-wbs.md](../project-management/wbs/00-master-wbs.md)  
> **সব table-এর schema এক জায়গায়:** [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)  
> নিচের cards task manager-এ paste করার জন্য। Column নিয়ে সন্দেহ হলে উপরের schema ফাইল দেখো।

**Project:** ERPFlow  
**Module:** Project Management System (PMS)  
**Source of truth (business):** [Project Management System — Business SRS.md](./Project%20Management%20System%20%E2%80%94%20Business%20SRS.md)  
**Commission (Phase 2 only):** `PMS_Commission_Implementation_Plan.pdf` · also [Commissioning SRS](./Commissioning%20Management%20System%20%E2%80%94%20SRS%20%26%20Dynamic%20Rule%20Matrix.md)  
**Team & lanes (Phase 1 assignment):**

| Lane | Owner | Ownership |
| --- | --- | --- |
| **A** | **Ashraful** | Spine BE — Project → Contract → Share → Earning shell |
| **B** | **Munna** | Team BE — Service teams, membership, contract assignment, Act As |
| **C** | **Sharif** | Masters/Config BE — Types, Services, Divisions, Commission rules shell, seeders, some reports |
| **D** | **Bablu** | FE + Permissions — all UI screens, nav shell, permission seed |

**Shared:** PMS-0.1 (Ashraful leads) · **PMS-SCHEMA-1** (Ashraful leads; Munna/Sharif review) · PMS-QA-1 (all four) · PMS-COMM-EPIC (not started)

---


## How to use this file

Each card below is paste-ready for the internal task manager. Field layout matches the Employee Personal Info sample.

### API Contract tasks (read this)

**API Contract** = short written freeze of endpoints (URL, request, response, errors, permissions) **before/while** BE & FE code.

- Owner writes the contract (often same lane as BE).
- **Bablu** builds UI against the contract (mock OK).
- **BE** implements the same contract.
- FE does **not** wait for full BE merge to *start* (SOFT sync before release).

Full explanation: [docs/project-management/wbs/what-is-api-contract.md](../project-management/wbs/what-is-api-contract.md)  
**Sample request/response:** প্রতিটা **FE** (+ `PMS-API-*`) card-এর ভিতরেই আছে। Backup copy: [11-api.md](../project-management/wbs/11-api.md)।


**Already delivered — do not open duplicate cards:**

| Table / feature             | Status                                         |
| --------------------------- | ---------------------------------------------- |
| `project_categories`        | Exists                                         |
| `office_expense_rules`      | Exists (Phase 2 commission base)               |
| `provident_fund_role_rules` | Exists (Phase 2)                               |
| `ProjectController`         | Stub only — real Project API is **PMS-2.1-BE** |

**Phase 1 boundary:** Client → Project → Service → Contract → Team → Assignment (Act As) → Team/BD/PD Share → Commission **Rule shell** → Earning **Record shell** → Reports.  
**Out of Phase 1:** full commission calculation engine, payment-cleared auto distribution, Fixed Team Allocation engine, PF maturity calc, EPS, commission approval/payment workflow.

**Parallel start (nobody idle):**

| Person | Lane | Week-1 start |
| --- | --- | --- |
| **Ashraful** | A | আগে `PMS-0.1`, তারপর **SCHEMA-1** (সব column একসাথে ঠিক), তারপর API-0 → 2.1-BE |
| **Munna** | B | SCHEMA-1-এ team table review; Sharif-এর `1.2-BE` এর পর scaffold |
| **Sharif** | C | SCHEMA-1 masters/`clients` review; তারপর 1.1-BE + 1.2-BE |
| **Bablu** | D | `0.2` + `0.1-FE` — SCHEMA-এর জন্য wait করতে হবে না |

**Global DoD (every BE card):** Service Repository pattern, Form Request, API Resource, `company_id` tenant scope, permission middleware, try/catch in controller, feature tests (happy + validation + IDOR).  
**Global DoD (every FE card):** list/form states, permission gating, API error mapping, loading/empty/error states, follow existing ERP UI patterns.

---

## Index

> **API Contract** = endpoint/request/response freeze so FE & BE work in parallel. See [what-is-api-contract.md](../project-management/wbs/what-is-api-contract.md).

| View Order | Serial | Title | Assignee | Lane | Hours | Depends |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | PMS-0.1 | Domain ERD & Ownership Lock | Ashraful (lead) | Shared | 4 | — |
| 2 | PMS-SCHEMA-1 | Full Phase 1 Database Schema (all tables) | Ashraful (lead) | Shared | 6 | PMS-0.1 |
| 3 | PMS-API-0 | API Envelope & Error Contract | Ashraful | A | 2 | PMS-0.1 |
| 4 | PMS-0.2 | PMS Permissions & Actions Seed | Bablu | D | 4 | PMS-0.1 |
| 5 | PMS-0.1-FE | Project Module Nav & Route Shell | Bablu | D | 3 | PMS-0.2 |
| 6 | PMS-API-1.1 | Project Types API Contract | Sharif | C | 1 | PMS-API-0 |
| 7 | PMS-1.1-BE | Project Types — Backend | Sharif | C | 5 | PMS-SCHEMA-1 |
| 8 | PMS-1.1-FE | Project Types — Frontend | Bablu | D | 3 | PMS-API-1.1, PMS-0.1-FE |
| 9 | PMS-1.0-BE | Project Categories — Verify & Wire | Sharif | C | 2 | PMS-SCHEMA-1 |
| 10 | PMS-1.0-FE | Project Categories — FE Verify/Wire | Bablu | D | 2 | PMS-1.0-BE, PMS-0.1-FE |
| 11 | PMS-API-1.2 | Service Master API Contract | Sharif | C | 1 | PMS-API-0 |
| 12 | PMS-1.2-BE | Service Master — Backend | Sharif | C | 6 | PMS-SCHEMA-1 |
| 13 | PMS-1.2-FE | Service Master — Frontend | Bablu | D | 4 | PMS-API-1.2, PMS-0.1-FE |
| 14 | PMS-API-1.3 | Team Divisions & Roles API Contract | Sharif | C | 1 | PMS-API-0 |
| 15 | PMS-1.3-BE | Team Divisions & Contract Roles — Backend | Sharif | C | 5 | PMS-SCHEMA-1 |
| 16 | PMS-1.3-FE | Team Divisions & Roles — Frontend | Bablu | D | 3 | PMS-API-1.3 |
| 17 | PMS-1.4a-BE | Commission Types Master/Enum — Backend | Sharif | C | 3 | PMS-SCHEMA-1 |
| 18 | PMS-1.4a-FE | Commission Types — Frontend | Bablu | D | 2 | PMS-1.4a-BE |
| 19 | PMS-API-1.4 | Commission Rules Shell API Contract | Sharif | C | 1 | PMS-API-0 |
| 20 | PMS-1.4-BE | Commission Rules Shell — Backend | Sharif | C | 6 | PMS-SCHEMA-1, PMS-1.3-BE, PMS-1.4a-BE |
| 21 | PMS-1.4-FE | Commission Rules Shell — Frontend | Bablu | D | 5 | PMS-API-1.4 |
| 22 | PMS-1.5-BE | Client Module Integration Point | Sharif | C | 3 | PMS-SCHEMA-1 |
| 23 | PMS-API-2.1 | Projects API Contract | Ashraful | A | 1.5 | PMS-API-0 |
| 24 | PMS-2.1-BE | Project CRUD — Backend | Ashraful | A | 8 | PMS-SCHEMA-1, PMS-1.1-BE, PMS-1.0-BE |
| 25 | PMS-2.1-FE | Project List/Form — Frontend | Bablu | D | 6 | PMS-API-2.1, PMS-0.1-FE |
| 26 | PMS-API-2.2 | Project Service Links API Contract | Ashraful | A | 1 | PMS-API-2.1, PMS-API-1.2 |
| 27 | PMS-2.2-BE | Project Service Links — Backend | Ashraful | A | 6 | PMS-SCHEMA-1, PMS-2.1-BE, PMS-1.2-BE |
| 28 | PMS-2.2-FE | Project Services Tab — Frontend | Bablu | D | 4 | PMS-API-2.2, PMS-2.1-FE |
| 29 | PMS-API-3.1 | Service Teams & Membership API Contract | Munna | B | 1.5 | PMS-API-0, PMS-API-1.2 |
| 30 | PMS-3.1-BE | Service Teams — Backend | Munna | B | 5 | PMS-SCHEMA-1, PMS-1.2-BE, PMS-1.3-BE |
| 31 | PMS-3.2-BE | Service Team Membership — Backend | Munna | B | 6 | PMS-SCHEMA-1, PMS-3.1-BE |
| 32 | PMS-3.1-FE | Service Teams & Members — Frontend | Bablu | D | 6 | PMS-API-3.1 |
| 33 | PMS-API-2.3 | Contracts API Contract | Ashraful | A | 2 | PMS-API-2.2 |
| 34 | PMS-2.3-BE | Contract CRUD — Backend | Ashraful | A | 10 | PMS-SCHEMA-1, PMS-2.2-BE |
| 35 | PMS-2.3-FE | Contract List/Form — Frontend | Bablu | D | 8 | PMS-API-2.3 |
| 36 | PMS-2.4-BE | Contract Status Transitions — Backend | Ashraful | A | 5 | PMS-SCHEMA-1, PMS-2.3-BE |
| 37 | PMS-2.4-FE | Contract Status Actions — Frontend | Bablu | D | 3 | PMS-2.4-BE, PMS-2.3-FE |
| 38 | PMS-API-2.5 | Commission Share API Contract | Ashraful | A | 1.5 | PMS-API-2.3 |
| 39 | PMS-2.5-BE | Contract Commission Share — Backend | Ashraful | A | 8 | PMS-SCHEMA-1, PMS-2.3-BE |
| 40 | PMS-2.5-FE | Contract Commission Share — Frontend | Bablu | D | 5 | PMS-API-2.5, PMS-2.3-FE |
| 41 | PMS-2.6-BE | Contract Attachments — Backend | Ashraful | A | 4 | PMS-SCHEMA-1, PMS-2.3-BE |
| 42 | PMS-2.6-FE | Contract Attachments — Frontend | Bablu | D | 3 | PMS-2.6-BE, PMS-2.3-FE |
| 43 | PMS-API-3.3 | Assignment & Act-As API Contract | Munna | B | 2 | PMS-API-2.3, PMS-API-3.1 |
| 44 | PMS-3.3-BE | Contract Team Assignment & Act As — Backend | Munna | B | 10 | PMS-SCHEMA-1, PMS-2.3-BE, PMS-3.2-BE |
| 45 | PMS-3.3-FE | Contract Assignment — Frontend | Bablu | D | 8 | PMS-API-3.3, PMS-2.3-FE |
| 46 | PMS-3.4-BE | Assignment Validation Matrix — Backend | Munna | B | 5 | PMS-3.3-BE |
| 47 | PMS-3.5-BE | Assignment History / Unassign — Backend | Munna | B | 5 | PMS-SCHEMA-1, PMS-3.3-BE |
| 48 | PMS-4.1-BE | PMS Demo Seeder | Sharif | C | 4 | Wave 2 BE |
| 49 | PMS-5.1-BE | Commission Earning Records Shell — Backend | Ashraful | A | 6 | PMS-SCHEMA-1, PMS-1.4-BE, PMS-2.5-BE |
| 50 | PMS-5.1-FE | Commission Earnings Shell — Frontend | Bablu | D | 4 | PMS-5.1-BE |
| 51 | PMS-5.2-BE | Payment Cleared Integration Hook | Ashraful | A | 3 | PMS-5.1-BE |
| 52 | PMS-5.3-BE | Employee-wise Assignment Report API | Munna | B | 4 | PMS-3.3-BE |
| 53 | PMS-5.3-FE | Assignment Report — Frontend | Bablu | D | 3 | PMS-5.3-BE |
| 54 | PMS-5.4-BE | Contract/Service Team Report API | Munna | B | 4 | PMS-3.3-BE |
| 55 | PMS-5.4-FE | Team Reports — Frontend | Bablu | D | 3 | PMS-5.4-BE |
| 56 | PMS-5.7-BE | Project-wise Team Report API | Munna | B | 3 | PMS-3.3-BE |
| 57 | PMS-5.7-FE | Project-wise Team Report — Frontend | Bablu | D | 2 | PMS-5.7-BE |
| 58 | PMS-5.5-BE | Active/Expired Contracts Report API | Sharif | C | 3 | PMS-2.4-BE |
| 59 | PMS-5.5-FE | Contract Status Report — Frontend | Bablu | D | 3 | PMS-5.5-BE |
| 60 | PMS-5.6-BE | Contract Commission Share Summary API | Sharif | C | 4 | PMS-2.5-BE |
| 61 | PMS-5.6-FE | Commission Share Summary — Frontend | Bablu | D | 3 | PMS-5.6-BE |
| 62 | PMS-5.8-BE | BD/PD Commission Earnings Report API (shell) | Ashraful | A | 4 | PMS-5.1-BE |
| 63 | PMS-5.8-FE | BD/PD Commission Earnings Report — Frontend | Bablu | D | 3 | PMS-5.8-BE |
| 64 | PMS-DOC-1 | Phase 1 Module Documentation | Sharif | C | 3 | PMS-QA-1 soft |
| 65 | PMS-QA-1 | E2E SRS Scenario (ABC Digital Growth) | All (Ashraful leads) | Shared | 6 | Wave 3 |
| 66 | PMS-COMM-EPIC | Phase 2 Full Commission Engine | — | — | 0 | PMS-QA-1 |

### Hours by person (approx)

| Person | Hours (approx) |
| --- | --- |
| Ashraful | ~78 (incl. SCHEMA-1 lead) |
| Munna | ~50 (+ SCHEMA-1 review) |
| Sharif | ~48 (+ SCHEMA-1 review) |
| Bablu | ~90 |
| Shared QA | 6 |

> আগে **PMS-SCHEMA-1** দিয়ে column গুলো ঠিক করে নাও — তারপর migration। Bablu-র কাজ বেশি; API contract থাকলে সে BE-এর জন্য বসে থাকবে না।

**Phase 1 total (approx):** ~272 hours (৪ জনে parallel করলে calendar অনেক কম)


---

# WAVE 0 — Foundation

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
PMS Domain ERD & Table Ownership Lock  
Branch Name  
feature-pms-domain-erd-ownership  
View Order  
1  
Assignee  
Ashraful (lead)  
Description

Task Serial  
PMS-0.1 — Domain ERD & Ownership Lock

User Story  
আমি tech lead হিসেবে চাই: কোন table আছে, কে owner — একটা ছবি/ম্যাট্রিক্সে সবাই একমত হোক। যাতে চারজন parallel কাজ করতে পারে, আর একই জিনিস দুইবার না বানায়।

Related Table Schema  
এই card-এ শুধু **কোন table আছে + কার**। Column detail নেই — সেটা **PMS-SCHEMA-1**।  
Planned: `clients`, `project_types`, `pms_services`, `team_divisions`, `pms_contract_role_maps` (opt), `commission_rules`, `projects`, `project_service_links`, `service_teams`, `service_team_members`, `contracts`, `contract_status_histories` (opt), `contract_commission_shares`, `contract_attachments`, `contract_team_assignments`, `contract_members`, `contract_member_histories` (opt), `commission_earning_records`  
Reuse: `companies`, `users`/`employees`, `designations`, `project_categories`

Schema Based Business Rules

- একটা table = একজন lane owner।
- Team Member ≠ Contract Member।
- Act As = contract-এর `designation_id` (+ `is_act_as`); আলাদা ActAs master table নেই।
- PM মানে Member of Project — Project Manager না।
- Commission Rule ≠ Earning Record।
- Column লিস্ট এই card-এর কাজ না → **PMS-SCHEMA-1**।

Task Scope  
ERD (diagram + markdown) লেখো। Ownership matrix publish করো। `project.*` permission naming ঠিক করো। Phase 2 commission engine যে Phase 1 card-এ নেই — স্পষ্ট করে দাও। তারপর SCHEMA-1-এ হাত তুলে দাও।

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Full Phase 1 Database Schema — All Tables  
Branch Name  
feature-pms-phase1-database-schema  
View Order  
2  
Assignee  
Ashraful (lead) · Munna + Sharif review  
Description

Task Serial  
PMS-SCHEMA-1 — Full Phase 1 Database Schema (all tables)

User Story  
Team হিসেবে চাই: Phase 1-এর সব table-এর **DDL** এই card-এই থাকুক। কেউ নিজের মতো করে column বানিয়ে conflict করবে না।

Related Table Schema  
সব table-এর draft DDL নিচে। Same copy: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md)।  
Migration lane BE card-এ হবে — column এই DDL মিলিয়ে।

```sql
-- ============================================================
-- PMS Phase 1 — Full DDL (MySQL / MariaDB draft)
-- Task: PMS-SCHEMA-1
-- Note: existing platform tables (companies, users, employees,
--       designations) reuse only — not recreated here.
-- ============================================================

-- ------------------------------------------------------------
-- EXISTING (verify only — do not recreate) — PMS-1.0-BE
-- ------------------------------------------------------------
-- project_categories (already migrated)
/*
CREATE TABLE project_categories (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  name VARCHAR(255) NOT NULL,
  parent_id BIGINT UNSIGNED NULL,
  status ENUM('active','inactive') NOT NULL DEFAULT 'active',
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY project_categories_company_parent_name_unique (company_id, parent_id, name),
  KEY project_categories_company_status_index (company_id, status),
  CONSTRAINT project_categories_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT project_categories_parent_id_foreign FOREIGN KEY (parent_id) REFERENCES project_categories (id) ON DELETE RESTRICT,
  CONSTRAINT project_categories_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT project_categories_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);
*/

-- ------------------------------------------------------------
-- 1. clients — Sharif / PMS-1.5-BE (create if Client module missing)
-- ------------------------------------------------------------
CREATE TABLE clients (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  name VARCHAR(200) NOT NULL,
  code VARCHAR(50) NULL,
  email VARCHAR(150) NULL,
  phone VARCHAR(50) NULL,
  address TEXT NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'active', -- active|inactive
  notes TEXT NULL,
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY clients_company_name_unique (company_id, name),
  KEY clients_company_status_index (company_id, status),
  CONSTRAINT clients_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT clients_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT clients_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 2. project_types — Sharif / PMS-1.1-BE
-- ------------------------------------------------------------
CREATE TABLE project_types (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  name VARCHAR(150) NOT NULL,
  code VARCHAR(50) NULL,
  description TEXT NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'active', -- active|inactive
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY project_types_company_name_unique (company_id, name),
  KEY project_types_company_status_index (company_id, status),
  CONSTRAINT project_types_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT project_types_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT project_types_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 3. pms_services — Sharif / PMS-1.2-BE
-- ------------------------------------------------------------
CREATE TABLE pms_services (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  name VARCHAR(150) NOT NULL,
  code VARCHAR(50) NULL,
  description TEXT NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'active', -- active|inactive
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY pms_services_company_name_unique (company_id, name),
  KEY pms_services_company_status_index (company_id, status),
  CONSTRAINT pms_services_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT pms_services_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT pms_services_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 4. team_divisions — Sharif / PMS-1.3-BE
-- ------------------------------------------------------------
CREATE TABLE team_divisions (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  code VARCHAR(20) NOT NULL, -- BD|PD
  name VARCHAR(100) NOT NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY team_divisions_company_code_unique (company_id, code),
  CONSTRAINT team_divisions_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT team_divisions_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT team_divisions_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 5. pms_contract_role_maps (OPTIONAL) — Sharif / PMS-1.3-BE
-- ------------------------------------------------------------
CREATE TABLE pms_contract_role_maps (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  designation_id BIGINT UNSIGNED NOT NULL,
  division_code VARCHAR(10) NOT NULL, -- BD|PD
  label_override VARCHAR(100) NULL,
  sort_order INT NOT NULL DEFAULT 0,
  is_act_as_allowed TINYINT(1) NOT NULL DEFAULT 1,
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY pms_contract_role_maps_unique (company_id, designation_id, division_code),
  CONSTRAINT pms_contract_role_maps_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT pms_contract_role_maps_designation_id_foreign FOREIGN KEY (designation_id) REFERENCES designations (id) ON DELETE RESTRICT,
  CONSTRAINT pms_contract_role_maps_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT pms_contract_role_maps_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 6. commission_types — Phase 1: NO separate table (enum on rules)
-- Values: one_time | recurring | monthly | contract_based | milestone_based
-- Optional read-only API lists these values (PMS-1.4a-BE)
-- ------------------------------------------------------------

-- ------------------------------------------------------------
-- 7. commission_rules — Sharif / PMS-1.4-BE
-- ------------------------------------------------------------
CREATE TABLE commission_rules (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  name VARCHAR(150) NOT NULL,
  commission_type VARCHAR(40) NOT NULL, -- see §6 values
  calculation_base VARCHAR(40) NOT NULL, -- contract_value|team_pool|bd_pool|pd_pool
  percentage DECIMAL(8,4) NULL,
  fixed_amount DECIMAL(15,2) NULL,
  frequency VARCHAR(30) NULL,
  duration_value INT NULL,
  duration_type VARCHAR(30) NULL, -- months|lifetime|…
  team_division VARCHAR(10) NULL, -- BD|PD
  role_designation_id BIGINT UNSIGNED NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  effective_from DATE NULL,
  effective_to DATE NULL,
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  KEY commission_rules_company_status_index (company_id, status),
  KEY commission_rules_company_division_index (company_id, team_division),
  CONSTRAINT commission_rules_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT commission_rules_role_designation_id_foreign FOREIGN KEY (role_designation_id) REFERENCES designations (id) ON DELETE SET NULL,
  CONSTRAINT commission_rules_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT commission_rules_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);
-- App rule: active row → exactly one of percentage / fixed_amount

-- ------------------------------------------------------------
-- 8. projects — Ashraful / PMS-2.1-BE
-- ------------------------------------------------------------
CREATE TABLE projects (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  client_id BIGINT UNSIGNED NOT NULL,
  name VARCHAR(200) NOT NULL,
  project_type_id BIGINT UNSIGNED NULL,
  project_category_id BIGINT UNSIGNED NULL,
  description TEXT NULL,
  start_date DATE NULL,
  expected_end_date DATE NULL,
  status VARCHAR(30) NOT NULL DEFAULT 'draft', -- draft|active|on_hold|completed|cancelled
  owner_user_id BIGINT UNSIGNED NULL,
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  KEY projects_company_status_index (company_id, status),
  KEY projects_company_client_index (company_id, client_id),
  KEY projects_company_type_index (company_id, project_type_id),
  KEY projects_company_category_index (company_id, project_category_id),
  CONSTRAINT projects_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT projects_client_id_foreign FOREIGN KEY (client_id) REFERENCES clients (id) ON DELETE RESTRICT,
  CONSTRAINT projects_project_type_id_foreign FOREIGN KEY (project_type_id) REFERENCES project_types (id) ON DELETE SET NULL,
  CONSTRAINT projects_project_category_id_foreign FOREIGN KEY (project_category_id) REFERENCES project_categories (id) ON DELETE SET NULL,
  CONSTRAINT projects_owner_user_id_foreign FOREIGN KEY (owner_user_id) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT projects_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT projects_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 9. project_service_links — Ashraful / PMS-2.2-BE
-- ------------------------------------------------------------
CREATE TABLE project_service_links (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  project_id BIGINT UNSIGNED NOT NULL,
  service_id BIGINT UNSIGNED NOT NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'active', -- active|inactive
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY project_service_links_project_service_unique (project_id, service_id),
  KEY project_service_links_company_project_index (company_id, project_id),
  CONSTRAINT project_service_links_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT project_service_links_project_id_foreign FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE,
  CONSTRAINT project_service_links_service_id_foreign FOREIGN KEY (service_id) REFERENCES pms_services (id) ON DELETE RESTRICT,
  CONSTRAINT project_service_links_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT project_service_links_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 10. service_teams — Munna / PMS-3.1-BE
-- ------------------------------------------------------------
CREATE TABLE service_teams (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  service_id BIGINT UNSIGNED NOT NULL,
  name VARCHAR(150) NOT NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY service_teams_company_service_name_unique (company_id, service_id, name),
  KEY service_teams_company_service_index (company_id, service_id),
  CONSTRAINT service_teams_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT service_teams_service_id_foreign FOREIGN KEY (service_id) REFERENCES pms_services (id) ON DELETE RESTRICT,
  CONSTRAINT service_teams_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT service_teams_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 11. service_team_members (permanent) — Munna / PMS-3.2-BE
-- No designation_id / is_act_as here
-- ------------------------------------------------------------
CREATE TABLE service_team_members (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  team_id BIGINT UNSIGNED NOT NULL,
  employee_id BIGINT UNSIGNED NOT NULL, -- default employees.id (lock in review)
  division VARCHAR(10) NOT NULL, -- BD|PD
  status VARCHAR(20) NOT NULL DEFAULT 'active', -- active|inactive
  joined_at DATE NULL,
  left_at DATE NULL,
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  KEY service_team_members_company_team_index (company_id, team_id),
  KEY service_team_members_company_employee_index (company_id, employee_id),
  CONSTRAINT service_team_members_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT service_team_members_team_id_foreign FOREIGN KEY (team_id) REFERENCES service_teams (id) ON DELETE CASCADE,
  CONSTRAINT service_team_members_employee_id_foreign FOREIGN KEY (employee_id) REFERENCES employees (id) ON DELETE RESTRICT,
  CONSTRAINT service_team_members_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT service_team_members_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);
-- App rule: one active row per (team_id, employee_id)

-- ------------------------------------------------------------
-- 12. contracts — Ashraful / PMS-2.3-BE
-- ------------------------------------------------------------
CREATE TABLE contracts (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  contract_number VARCHAR(50) NOT NULL,
  project_id BIGINT UNSIGNED NOT NULL,
  project_service_link_id BIGINT UNSIGNED NOT NULL,
  client_id BIGINT UNSIGNED NOT NULL, -- must equal projects.client_id
  start_date DATE NULL,
  end_date DATE NULL,
  contract_value DECIMAL(15,2) NOT NULL DEFAULT 0.00,
  currency VARCHAR(10) NOT NULL DEFAULT 'USD',
  allocated_hours DECIMAL(10,2) NULL,
  billing_type VARCHAR(50) NULL,
  payment_terms VARCHAR(100) NULL,
  renewal_type VARCHAR(50) NULL,
  status VARCHAR(30) NOT NULL DEFAULT 'draft',
  -- draft|pending_approval|active|expired|completed|cancelled|terminated|renewed
  notes TEXT NULL,
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  UNIQUE KEY contracts_company_number_unique (company_id, contract_number),
  KEY contracts_company_status_index (company_id, status),
  KEY contracts_company_project_index (company_id, project_id),
  KEY contracts_project_service_link_index (project_service_link_id),
  CONSTRAINT contracts_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT contracts_project_id_foreign FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE RESTRICT,
  CONSTRAINT contracts_project_service_link_id_foreign FOREIGN KEY (project_service_link_id) REFERENCES project_service_links (id) ON DELETE RESTRICT,
  CONSTRAINT contracts_client_id_foreign FOREIGN KEY (client_id) REFERENCES clients (id) ON DELETE RESTRICT,
  CONSTRAINT contracts_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT contracts_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 13. contract_status_histories (OPTIONAL) — Ashraful / PMS-2.4-BE
-- ------------------------------------------------------------
CREATE TABLE contract_status_histories (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  contract_id BIGINT UNSIGNED NOT NULL,
  from_status VARCHAR(30) NULL,
  to_status VARCHAR(30) NOT NULL,
  changed_by BIGINT UNSIGNED NULL,
  note TEXT NULL,
  created_at TIMESTAMP NULL,
  KEY contract_status_histories_company_contract_index (company_id, contract_id),
  CONSTRAINT contract_status_histories_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT contract_status_histories_contract_id_foreign FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
  CONSTRAINT contract_status_histories_changed_by_foreign FOREIGN KEY (changed_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 14. contract_commission_shares — Ashraful / PMS-2.5-BE
-- ------------------------------------------------------------
CREATE TABLE contract_commission_shares (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  contract_id BIGINT UNSIGNED NOT NULL,
  team_share_percent DECIMAL(8,4) NOT NULL, -- % of contract_value
  bd_share_percent DECIMAL(8,4) NOT NULL, -- % of team_pool
  pd_share_percent DECIMAL(8,4) NOT NULL, -- % of team_pool
  team_pool_amount DECIMAL(15,2) NOT NULL, -- snapshot
  bd_pool_amount DECIMAL(15,2) NOT NULL,
  pd_pool_amount DECIMAL(15,2) NOT NULL,
  currency VARCHAR(10) NOT NULL,
  effective_from DATE NOT NULL,
  effective_to DATE NULL,
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  KEY contract_commission_shares_company_contract_index (company_id, contract_id),
  KEY contract_commission_shares_contract_effective_index (contract_id, effective_from),
  CONSTRAINT contract_commission_shares_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT contract_commission_shares_contract_id_foreign FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
  CONSTRAINT contract_commission_shares_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT contract_commission_shares_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);
-- App rule: bd_share_percent + pd_share_percent = 100

-- ------------------------------------------------------------
-- 15. contract_attachments — Ashraful / PMS-2.6-BE
-- ------------------------------------------------------------
CREATE TABLE contract_attachments (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  contract_id BIGINT UNSIGNED NOT NULL,
  file_path VARCHAR(255) NOT NULL,
  original_name VARCHAR(255) NOT NULL,
  mime VARCHAR(100) NULL,
  size BIGINT UNSIGNED NULL,
  uploaded_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  KEY contract_attachments_company_contract_index (company_id, contract_id),
  CONSTRAINT contract_attachments_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT contract_attachments_contract_id_foreign FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
  CONSTRAINT contract_attachments_uploaded_by_foreign FOREIGN KEY (uploaded_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 16. contract_team_assignments — Munna / PMS-3.3-BE
-- ------------------------------------------------------------
CREATE TABLE contract_team_assignments (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  contract_id BIGINT UNSIGNED NOT NULL,
  team_id BIGINT UNSIGNED NULL,
  division VARCHAR(10) NOT NULL, -- BD|PD
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  KEY contract_team_assignments_company_contract_division_index (company_id, contract_id, division),
  CONSTRAINT contract_team_assignments_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT contract_team_assignments_contract_id_foreign FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
  CONSTRAINT contract_team_assignments_team_id_foreign FOREIGN KEY (team_id) REFERENCES service_teams (id) ON DELETE SET NULL,
  CONSTRAINT contract_team_assignments_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT contract_team_assignments_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 17. contract_members (role + Act As) — Munna / PMS-3.3-BE
-- ------------------------------------------------------------
CREATE TABLE contract_members (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  contract_id BIGINT UNSIGNED NOT NULL,
  assignment_id BIGINT UNSIGNED NULL,
  employee_id BIGINT UNSIGNED NOT NULL,
  division VARCHAR(10) NOT NULL, -- BD|PD
  designation_id BIGINT UNSIGNED NOT NULL, -- contract role / Act As role
  is_act_as TINYINT(1) NOT NULL DEFAULT 0,
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  assigned_at TIMESTAMP NULL,
  unassigned_at TIMESTAMP NULL,
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  KEY contract_members_company_contract_index (company_id, contract_id),
  KEY contract_members_company_employee_index (company_id, employee_id),
  CONSTRAINT contract_members_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT contract_members_contract_id_foreign FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
  CONSTRAINT contract_members_assignment_id_foreign FOREIGN KEY (assignment_id) REFERENCES contract_team_assignments (id) ON DELETE SET NULL,
  CONSTRAINT contract_members_employee_id_foreign FOREIGN KEY (employee_id) REFERENCES employees (id) ON DELETE RESTRICT,
  CONSTRAINT contract_members_designation_id_foreign FOREIGN KEY (designation_id) REFERENCES designations (id) ON DELETE RESTRICT,
  CONSTRAINT contract_members_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT contract_members_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 18. contract_member_histories (OPTIONAL) — Munna / PMS-3.5-BE
-- ------------------------------------------------------------
CREATE TABLE contract_member_histories (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  contract_member_id BIGINT UNSIGNED NOT NULL,
  action VARCHAR(30) NOT NULL, -- assigned|unassigned|role_changed
  payload JSON NULL,
  acted_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  CONSTRAINT contract_member_histories_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT contract_member_histories_contract_member_id_foreign FOREIGN KEY (contract_member_id) REFERENCES contract_members (id) ON DELETE CASCADE,
  CONSTRAINT contract_member_histories_acted_by_foreign FOREIGN KEY (acted_by) REFERENCES users (id) ON DELETE SET NULL
);

-- ------------------------------------------------------------
-- 19. commission_earning_records (SHELL only) — Ashraful / PMS-5.1-BE
-- ------------------------------------------------------------
CREATE TABLE commission_earning_records (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  company_id BIGINT UNSIGNED NOT NULL,
  contract_id BIGINT UNSIGNED NOT NULL,
  employee_id BIGINT UNSIGNED NOT NULL,
  designation_id BIGINT UNSIGNED NULL,
  division VARCHAR(10) NULL, -- BD|PD
  rule_id BIGINT UNSIGNED NULL,
  calculation_base_type VARCHAR(40) NOT NULL,
  base_amount DECIMAL(15,2) NOT NULL,
  percentage DECIMAL(8,4) NULL,
  fixed_amount DECIMAL(15,2) NULL,
  earning_amount DECIMAL(15,2) NOT NULL,
  period_start DATE NULL,
  period_end DATE NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'draft', -- draft|finalized|cancelled
  finalized_at TIMESTAMP NULL,
  meta JSON NULL, -- frozen inputs snapshot
  created_by BIGINT UNSIGNED NULL,
  updated_by BIGINT UNSIGNED NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL,
  KEY commission_earning_records_company_contract_index (company_id, contract_id),
  KEY commission_earning_records_company_employee_index (company_id, employee_id),
  KEY commission_earning_records_company_status_index (company_id, status),
  CONSTRAINT commission_earning_records_company_id_foreign FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE,
  CONSTRAINT commission_earning_records_contract_id_foreign FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE RESTRICT,
  CONSTRAINT commission_earning_records_employee_id_foreign FOREIGN KEY (employee_id) REFERENCES employees (id) ON DELETE RESTRICT,
  CONSTRAINT commission_earning_records_designation_id_foreign FOREIGN KEY (designation_id) REFERENCES designations (id) ON DELETE SET NULL,
  CONSTRAINT commission_earning_records_rule_id_foreign FOREIGN KEY (rule_id) REFERENCES commission_rules (id) ON DELETE SET NULL,
  CONSTRAINT commission_earning_records_created_by_foreign FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT commission_earning_records_updated_by_foreign FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL
);
```

Schema Based Business Rules

- এই task column ঠিক করে — migration merge করে না। Migration এখনও প্রত্যেক lane-এর BE card।
- এক table = এক owner (matrix schema doc-এ)।
- Client নিয়ে সিদ্ধান্ত স্পষ্ট করতে হবে: existing module map, নাকি নতুন `clients` CRUD।
- `employee_id` কোথায় যাবে ঠিক করতে হবে (`employees` নাকি `users`)।
- Commission type Phase 1-এ enum/string — আলাদা master table লাগবে না।
- Optional table রাখব নাকি বাদ — আগেই ঠিক করো। পরে চুপিচুপি যোগ করা যাবে না; doc আপডেট লাগবে।

Task Scope  
এই card-এর DDL ফাইনাল করো (Munna = team/assignment, Sharif = masters + clients)। PR-এ team “OK”। Column বদলালে এই card + `phase1-database-schema.md` একসাথে আপডেট। Schema ছাড়া আলাদা column নিয়ে migration merge বন্ধ।

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
PMS Permissions & Actions Seed  
Branch Name  
feature-pms-permissions-actions-seed  
View Order  
4  
Assignee  
Bablu  
Description

Task Serial  
PMS-0.2 — Permissions & Actions Seed

User Story  
As an admin, I want PMS permissions seeded so that every API and screen can be gated consistently.

Related Table Schema  
Existing platform permission/action tables (project convention — do not invent a parallel ACL).  
Permission keys (minimum):  
`project.types-view|create|update|delete`  
`project.services-view|create|update|delete`  
`project.projects-view|create|update|delete|manage`  
`project.contracts-view|create|update|delete|manage`  
`project.teams-view|create|update|delete`  
`project.assignments-view|manage`  
`project.shares-view|manage`  
`project.commission-rules-view|manage`  
`project.earnings-view|manage`  
`project.reports-view`  
(Align exact naming with PMS-0.1 and existing `project.categories-*` style.)

Schema Based Business Rules

- Seed must be idempotent.
- Missing permission → 403; unauthenticated → 401.
- Controllers use permission middleware, not hardcoded role names.

Task Scope  
Add/seed permissions and wire into actions config if the repo uses it. Document keys in PR. Smoke-test at least one endpoint for 401/403.

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project Module Nav & Route Shell — Frontend  
Branch Name  
feature-pms-module-nav-route-shell-frontend  
View Order  
5  
Assignee  
Bablu  
Description

Task Serial  
PMS-0.1-FE — Module Nav & Route Shell

User Story  
As a user with project permissions, I want a Project section in the app navigation so that upcoming PMS screens have a consistent home.

Related Table Schema  
N/A (frontend shell). Consumes permission keys from PMS-0.2.

API Request / Response  
এই card-এ business CRUD API নেই (nav shell)। Permission keys seed থেকে আসবে।

```http
GET /api/v1/... (existing me/permissions — project convention)
```

UI শুধু `project.*` permission দেখে menu show/hide করবে।

Schema Based Business Rules

- Menu items appear only when the user has at least one related view permission.
- Placeholder routes show empty states, not broken 404s for registered paths.

Task Scope  
Add Project sidebar section, route placeholders, FE API client folder structure following existing modules. No business CRUD yet.

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

# WAVE 1 — Masters + Project Core

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project Types — Backend  
Branch Name  
feature-pms-project-types-backend  
View Order  
7  
Assignee  
Sharif  
Description

Task Serial  
PMS-1.1-BE — Project Types Backend

User Story  
As an admin, I want configurable Project Types so that each project can be classified by engagement/business model (Retainer, Fixed, Dedicated Team, etc.).

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `project_types`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK → companies.id  
name — VARCHAR(150) REQUIRED  
code — VARCHAR(50) NULL  
description — TEXT NULL  
status — VARCHAR(20) REQUIRED DEFAULT 'active' — values: active, inactive  
created_by — BIGINT UNSIGNED NULL FK → users.id  
updated_by — BIGINT UNSIGNED NULL FK → users.id  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Indexes / constraints  
UNIQUE(company_id, name)  
INDEX(company_id, status)

Schema Based Business Rules

- Name unique per company.
- Cross-company access by id is forbidden (IDOR → 404/403).
- Inactive types remain readable for historical projects; new attachments may require active (document chosen rule in PR).
- Soft-delete optional; if hard delete, block when referenced by `projects`.

Task Scope  
Migration, model, enum/status, repository + interface, service + interface, form requests, resource, API CRUD (`index/show/store/update/destroy` + optional `active`), feature tests, provider bindings, routes under `/api/v1/project/...`.

Estimate Hours  
5.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project Types — Frontend  
Branch Name  
feature-pms-project-types-frontend  
View Order  
8  
Assignee  
Bablu  
Description

Task Serial  
PMS-1.1-FE — Project Types Frontend

User Story  
As an admin, I want a UI to manage Project Types so that configuration does not require database access.

Related Table Schema  
Consumes `project_types` API from PMS-1.1-BE.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-1.1`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/types`  
**Permission:** `project.types-view|create|update|delete`

### POST create — request

```json
{
  "name": "Retainer Project",
  "code": "RETAINER",
  "description": "Monthly retainer engagement",
  "status": "active"
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Project type created successfully",
  "data": {
    "id": 1,
    "company_id": 1,
    "name": "Retainer Project",
    "code": "RETAINER",
    "description": "Monthly retainer engagement",
    "status": "active",
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### GET index — response `200` (paginated `data[]` same object shape)

### GET active — response `200` (dropdown)

```json
{
  "success": true,
  "message": "Active project types fetched successfully",
  "data": [
    { "id": 1, "name": "Retainer Project", "code": "RETAINER" }
  ]
}
```

---

Schema Based Business Rules

- Permission-gated actions (view vs manage).
- Show API validation messages for duplicate name / required fields.
- Status toggle must call update API, not local-only state.

Task Scope  
List + create/edit drawer or page. Loading, empty, error states. Nav under Project › Configuration › Types. Integrate with PMS-0.1-FE shell.

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Service Master — Backend  
Branch Name  
feature-pms-service-master-backend  
View Order  
12  
Assignee  
Sharif  
Description

Task Serial  
PMS-1.2-BE — Service Master Backend

User Story  
As an admin, I want a Service Master (SEO, Digital Marketing, Web Development, …) so that projects attach predefined services instead of free-text labels.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `pms_services`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK → companies.id  
name — VARCHAR(150) REQUIRED  
code — VARCHAR(50) NULL  
description — TEXT NULL  
status — VARCHAR(20) REQUIRED DEFAULT 'active' — active, inactive  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Indexes / constraints  
UNIQUE(company_id, name)  
INDEX(company_id, status)

Schema Based Business Rules

- Unique name per company.
- Active-only listing endpoint for dropdowns.
- Cannot delete (or must block) if referenced by `project_service_links` or `service_teams`.
- Tenant isolation mandatory.

Task Scope  
Full CRUD stack (same layering as PMS-1.1-BE). Feature tests for CRUD, uniqueness, IDOR, active filter.

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Service Master — Frontend  
Branch Name  
feature-pms-service-master-frontend  
View Order  
13  
Assignee  
Bablu  
Description

Task Serial  
PMS-1.2-FE — Service Master Frontend

User Story  
As an admin, I want to manage company services from the UI so that later project and team screens can pick from a clean master list.

Related Table Schema  
Consumes `pms_services` API.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-1.2`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/services`  
**Permission:** `project.services-*`

### POST create — request

```json
{
  "name": "Digital Marketing",
  "code": "DM",
  "description": null,
  "status": "active"
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Service created successfully",
  "data": {
    "id": 10,
    "company_id": 1,
    "name": "Digital Marketing",
    "code": "DM",
    "description": null,
    "status": "active",
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### GET active — response `200`

```json
{
  "success": true,
  "message": "Active services fetched successfully",
  "data": [
    { "id": 9, "name": "SEO", "code": "SEO" },
    { "id": 10, "name": "Digital Marketing", "code": "DM" }
  ]
}
```

---

Schema Based Business Rules

- Permission gating.
- Inactive services visually distinct; still visible in admin list.
- Destroy/disable errors from API must surface when service is in use.

Task Scope  
List/create/edit/status UI. Nav Project › Services. Reuse shared DataTable/form patterns.

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Team Divisions & Contract Roles — Backend  
Branch Name  
feature-pms-team-divisions-roles-backend  
View Order  
15  
Assignee  
Sharif  
Description

Task Serial  
PMS-1.3-BE — Team Divisions & Contract Roles Backend

User Story  
As an admin, I want BD/PD divisions and a clear contract-role model so that assignments and Act As use consistent designations.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `team_divisions`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
code — VARCHAR(20) REQUIRED — BD, PD  
name — VARCHAR(100) REQUIRED  
status — VARCHAR(20) DEFAULT 'active'  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
UNIQUE(company_id, code)

Contract roles: **reuse existing `designations` table** (no new ActAs master).  
Optional mapping (only if product needs explicit PMS role catalog):  
Table: `pms_contract_role_maps`  
Columns  
id, company_id, designation_id, division_code (BD|PD), label_override NULL, sort_order, is_act_as_allowed BOOL DEFAULT true, status, timestamps  
UNIQUE(company_id, designation_id, division_code)

Schema Based Business Rules

- BD and PD are the only primary divisions in Phase 1.
- Act As must not create a parallel role taxonomy.
- Document in code/PR: PM = Member of Project (delivery contributor), not Project Manager.
- Seed default BD/PD per company (idempotent).

Task Scope  
Division CRUD or seed-only + read API. Confirm designation reuse. Seed/map recommended roles: Sales Person, Closer, Manager, Regional Manager, PM (Member of Project). Tests for scope + uniqueness.

Estimate Hours  
5.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Team Divisions & Roles — Frontend  
Branch Name  
feature-pms-team-divisions-roles-frontend  
View Order  
16  
Assignee  
Bablu  
Description

Task Serial  
PMS-1.3-FE — Team Divisions & Roles Frontend

User Story  
As an admin, I want to view BD/PD divisions and available contract roles so that assignment screens use the same vocabulary.

Related Table Schema  
Consumes `team_divisions` (+ designations / `pms_contract_role_maps` if present).

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-1.3`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Bases:**  
- `/api/v1/project/team-divisions`  
- `/api/v1/project/contract-roles` (designations mapped for PMS; may proxy existing designations)

### GET team-divisions — response `200`

```json
{
  "success": true,
  "message": "Team divisions fetched successfully",
  "data": [
    { "id": 1, "code": "BD", "name": "Business Development", "status": "active" },
    { "id": 2, "code": "PD", "name": "Product Development", "status": "active" }
  ]
}
```

### GET contract-roles — response `200`

```json
{
  "success": true,
  "message": "Contract roles fetched successfully",
  "data": [
    {
      "designation_id": 101,
      "name": "Sales Person",
      "division_code": "BD",
      "is_act_as_allowed": true
    },
    {
      "designation_id": 102,
      "name": "Closer",
      "division_code": "BD",
      "is_act_as_allowed": true
    },
    {
      "designation_id": 201,
      "name": "PM",
      "label": "Member of Project",
      "division_code": "PD",
      "is_act_as_allowed": true
    }
  ]
}
```

> **PM** in `name`/`label` means **Member of Project**, not Project Manager.

---

Schema Based Business Rules

- UI help text must state PM = Member of Project.
- Read-only is acceptable if backend is seed-only.

Task Scope  
Simple configuration/reference screen under Project › Configuration. Wire dropdown data sources for later assignment FE.

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Commission Rules Shell — Backend  
Branch Name  
feature-pms-commission-rules-shell-backend  
View Order  
20  
Assignee  
Sharif  
Description

Task Serial  
PMS-1.4-BE — Commission Rules Shell Backend

User Story  
As an admin, I want to store configurable commission rules so that future calculation can use data instead of hard-coded percentages.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `commission_rules`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
name — VARCHAR(150) REQUIRED  
commission_type — VARCHAR(40) REQUIRED — one_time, recurring, monthly, contract_based, milestone_based  
calculation_base — VARCHAR(40) REQUIRED — contract_value, team_pool, bd_pool, pd_pool  
percentage — DECIMAL(8,4) NULL  
fixed_amount — DECIMAL(15,2) NULL  
frequency — VARCHAR(30) NULL  
duration_value — INT NULL  
duration_type — VARCHAR(30) NULL — months, lifetime, etc.  
team_division — VARCHAR(10) NULL — BD, PD  
role_designation_id — BIGINT UNSIGNED NULL FK → designations.id  
status — VARCHAR(20) DEFAULT 'active'  
effective_from — DATE NULL  
effective_to — DATE NULL  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Indexes  
INDEX(company_id, status), INDEX(company_id, team_division)

Schema Based Business Rules

- Exactly one of percentage or fixed_amount should be set (validate).
- effective_to must be null or >= effective_from.
- **No earning generation in this card.**
- Changing a rule must not rewrite historical `commission_earning_records` (enforced later in PMS-5.1-BE).

Task Scope  
CRUD API + validation + tests. Explicit comment/README note: calculation engine is Phase 2.

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Commission Rules Shell — Frontend  
Branch Name  
feature-pms-commission-rules-shell-frontend  
View Order  
21  
Assignee  
Bablu  
Description

Task Serial  
PMS-1.4-FE — Commission Rules Shell Frontend

User Story  
As an admin, I want a UI to configure commission rules without implying that payroll/commission has already been calculated.

Related Table Schema  
Consumes `commission_rules` API.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-1.4`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/commission-rules`  
**Note:** No `POST .../calculate` endpoint in Phase 1.

### POST create — request

```json
{
  "name": "BD Sales One-Time 10% of BD Pool",
  "commission_type": "one_time",
  "calculation_base": "bd_pool",
  "percentage": 10.0,
  "fixed_amount": null,
  "frequency": null,
  "duration_value": null,
  "duration_type": null,
  "team_division": "BD",
  "role_designation_id": 101,
  "status": "active",
  "effective_from": "2026-01-01",
  "effective_to": null
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Commission rule created successfully",
  "data": {
    "id": 5,
    "company_id": 1,
    "name": "BD Sales One-Time 10% of BD Pool",
    "commission_type": "one_time",
    "calculation_base": "bd_pool",
    "percentage": "10.0000",
    "fixed_amount": null,
    "team_division": "BD",
    "role_designation_id": 101,
    "status": "active",
    "effective_from": "2026-01-01",
    "effective_to": null,
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

---

Schema Based Business Rules

- UI must label this as configuration only.
- No Calculate / Generate Commission primary action.
- percentage vs fixed_amount mutual exclusivity mirrored in form UX.

Task Scope  
List + create/edit form for rule fields. Permission gated. Empty/error states.

Estimate Hours  
5.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Client Module Integration Point  
Branch Name  
feature-pms-client-integration-point  
View Order  
22  
Assignee  
Sharif  
Description

Task Serial  
PMS-1.5-BE — Client Module Integration

User Story  
Project/Contract-এ Client লাগবে। আলাদা `pms_clients` বানিয়ে duplicate করতে চাই না — existing Client থাকলে সেটাই use করব; না থাকলে SCHEMA মতো বানাব।

Related Table Schema  
`clients` column: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)।

দুটোর একটা সিদ্ধান্ত নাও:
1. **Client module আছে** — ওইটাতে map করো; `pms_clients` বানাবেন না।
2. **নেই** — SCHEMA অনুযায়ী `clients` CRUD এই card-এই করতে হবে (scope বাড়বে)।

Schema Based Business Rules

- `projects.client_id` আর `contracts.client_id` একই client domain।
- Contract-এর client = Project-এর client।
- ভুল / অন্য company-র client_id → 422/404।
- SCHEMA-এ নেই এমন column নিজে থেকে যোগ করো না — দরকার হলে আগে schema doc আপডেট।

Task Scope  
Client module আছে কিনা দেখো। না থাকলে SCHEMA মতো `clients` বানাও। Dropdown API দাও। Project/Contract validation company scope-এ বাঁধো। PR-এ লিখে রাখো কী map করলে। Full CRUD লাগলে hour বাড়তে পারে — review-এ বলো।

Estimate Hours  
3.00 (Client নতুন হলে বাড়তে পারে)  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project CRUD — Backend  
Branch Name  
feature-pms-project-crud-backend  
View Order  
24  
Assignee  
Ashraful  
Description

Task Serial  
PMS-2.1-BE — Project CRUD Backend

User Story  
As a project owner, I want to create and manage Projects linked to Client, Project Type, and Project Category so that each client engagement is tracked centrally.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `projects`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK → companies.id  
client_id — BIGINT UNSIGNED FK → clients.id (existing)  
name — VARCHAR(200) REQUIRED  
project_type_id — BIGINT UNSIGNED NULL FK → project_types.id  
project_category_id — BIGINT UNSIGNED NULL FK → project_categories.id  
description — TEXT NULL  
start_date — DATE NULL  
expected_end_date — DATE NULL  
status — VARCHAR(30) REQUIRED DEFAULT 'draft' — draft, active, on_hold, completed, cancelled  
owner_user_id — BIGINT UNSIGNED NULL FK → users.id  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Indexes  
INDEX(company_id, status)  
INDEX(company_id, client_id)  
INDEX(company_id, project_type_id)  
INDEX(company_id, project_category_id)

Schema Based Business Rules

- BR-01: one client may have many projects.
- Type/category/client must belong to same company.
- expected_end_date must be null or >= start_date when both set.
- Replace stub `ProjectController` blade responses with real JSON API.
- IDOR across companies blocked.

Task Scope  
Migration + full Service Repository API. List filters: status, client_id, type, category, search name. Feature tests. Bind routes already sketched under `/api/v1/project/projects`.

Estimate Hours  
8.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project List/Form — Frontend  
Branch Name  
feature-pms-project-list-form-frontend  
View Order  
25  
Assignee  
Bablu  
Description

Task Serial  
PMS-2.1-FE — Project List/Form Frontend

User Story  
As a user, I want Project list and create/edit screens so that I can manage engagements without API tools.

Related Table Schema  
Consumes `projects` API; dropdowns from clients, project_types, project_categories.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-2.1`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/projects`  
**Permission:** `project.projects-*`

### POST create — request

```json
{
  "client_id": 55,
  "name": "ABC Digital Growth",
  "project_type_id": 1,
  "project_category_id": 3,
  "description": "Digital growth engagement",
  "start_date": "2026-01-01",
  "expected_end_date": "2026-12-31",
  "status": "draft",
  "owner_user_id": 12
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Project created successfully",
  "data": {
    "id": 100,
    "company_id": 1,
    "client_id": 55,
    "client": { "id": 55, "name": "ABC Corporation" },
    "name": "ABC Digital Growth",
    "project_type_id": 1,
    "project_type": { "id": 1, "name": "Retainer Project" },
    "project_category_id": 3,
    "project_category": { "id": 3, "name": "Digital Marketing" },
    "description": "Digital growth engagement",
    "start_date": "2026-01-01",
    "expected_end_date": "2026-12-31",
    "status": "draft",
    "owner_user_id": 12,
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### GET index query

`?status=active&client_id=55&search=ABC&page=1`

---

Schema Based Business Rules

- Status values match backend enum.
- Permission gating for create/update.
- Client/type/category required rules follow API.

Task Scope  
List with filters, create/edit form, detail shell (tabs placeholder for Services/Contracts). Loading/empty/error states.

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project Service Links — Backend  
Branch Name  
feature-pms-project-service-links-backend  
View Order  
27  
Assignee  
Ashraful  
Description

Task Serial  
PMS-2.2-BE — Project Service Links Backend

User Story  
As a user, I want to attach one or more Services under a Project so that contracts can be created per service.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `project_service_links`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
project_id — BIGINT UNSIGNED FK → projects.id  
service_id — BIGINT UNSIGNED FK → pms_services.id  
status — VARCHAR(20) DEFAULT 'active' — active, inactive  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Constraints  
UNIQUE(project_id, service_id)  
INDEX(company_id, project_id)

Schema Based Business Rules

- BR-02: multiple services per project.
- Project and service must share company_id.
- Duplicate attach → 422.
- Detach/delete blocked if an active/non-cancelled contract references the link (preferred) — document if soft-inactive allowed instead.
- Prefer attaching only active services.

Task Scope  
Nested routes under project (attach/list/detach/update status). Feature tests including duplicate and IDOR.

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project Services Tab — Frontend  
Branch Name  
feature-pms-project-services-tab-frontend  
View Order  
28  
Assignee  
Bablu  
Description

Task Serial  
PMS-2.2-FE — Project Services Tab Frontend

User Story  
As a user, I want a Services tab on the Project detail page so that I can attach and remove services visually.

Related Table Schema  
Consumes `project_service_links` + active `pms_services`.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-2.2`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/projects/{projectId}/services`

### POST attach — request

```json
{
  "service_id": 10,
  "status": "active"
}
```

### POST attach — response `201`

```json
{
  "success": true,
  "message": "Service attached to project successfully",
  "data": {
    "id": 501,
    "project_id": 100,
    "service_id": 10,
    "service": { "id": 10, "name": "Digital Marketing", "code": "DM" },
    "status": "active",
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### Duplicate attach — response `422`

```json
{
  "success": false,
  "message": "Validation failed.",
  "errors": {
    "service_id": ["This service is already attached to the project."]
  }
}
```

---

Schema Based Business Rules

- Dropdown only shows services not already attached (or shows attached as disabled).
- API in-use errors shown when remove is blocked.

Task Scope  
Tab UI on project detail. Add/remove flows. Empty state when no services.

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Service Teams — Backend  
Branch Name  
feature-pms-service-teams-backend  
View Order  
30  
Assignee  
Munna  
Description

Task Serial  
PMS-3.1-BE — Service Teams Backend

User Story  
As an admin, I want service-based Teams so that each service (e.g. SEO Team) has a permanent/general team distinct from contract assignments.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `service_teams`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
service_id — BIGINT UNSIGNED FK → pms_services.id  
name — VARCHAR(150) REQUIRED  
status — VARCHAR(20) DEFAULT 'active'  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Constraints  
UNIQUE(company_id, service_id, name)  
INDEX(company_id, service_id)

Schema Based Business Rules

- Team ≠ Contract Team (permanent structure only).
- Team belongs to exactly one service.
- Company scope + IDOR protection.
- Delete/block rules when members or contract assignments exist.

Task Scope  
CRUD API, list by service, tests. PR note stating Team vs Contract Team principle.

Estimate Hours  
5.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Service Team Membership — Backend  
Branch Name  
feature-pms-service-team-membership-backend  
View Order  
31  
Assignee  
Munna  
Description

Task Serial  
PMS-3.2-BE — Service Team Membership Backend

User Story  
As an admin, I want permanent team membership with BD/PD division so that an employee’s home team is tracked separately from contract roles.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `service_team_members`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
team_id — BIGINT UNSIGNED FK → service_teams.id  
employee_id — BIGINT UNSIGNED FK → employees.id (or users.id — follow ERP employee pattern; lock in PMS-0.1)  
division — VARCHAR(10) REQUIRED — BD, PD  
status — VARCHAR(20) DEFAULT 'active' — active, inactive  
joined_at — DATE NULL  
left_at — DATE NULL  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Constraints  
INDEX(company_id, team_id)  
INDEX(company_id, employee_id)  
UNIQUE active membership: enforce in service (e.g. one active row per team_id+employee_id)

Schema Based Business Rules

- Membership does not set contract role / Act As.
- Employee may be permanent member without any contract assignment.
- left_at must be null or >= joined_at.
- Employee must belong to same company.

Task Scope  
Add/remove/list members APIs. Validation + feature tests. Do not write to `contract_members` from this card.

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Service Teams & Members — Frontend  
Branch Name  
feature-pms-service-teams-members-frontend  
View Order  
32  
Assignee  
Bablu  
Description

Task Serial  
PMS-3.1-FE — Service Teams & Members Frontend

User Story  
As an admin, I want UI to manage service teams and permanent BD/PD members so that staffing of home teams is visible.

Related Table Schema  
Consumes `service_teams`, `service_team_members`.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-3.1`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Bases:**  
- `/api/v1/project/service-teams`  
- `/api/v1/project/service-teams/{teamId}/members`

### POST team — request

```json
{
  "service_id": 10,
  "name": "Digital Marketing Team",
  "status": "active"
}
```

### POST team — response `201`

```json
{
  "success": true,
  "message": "Service team created successfully",
  "data": {
    "id": 20,
    "service_id": 10,
    "service": { "id": 10, "name": "Digital Marketing" },
    "name": "Digital Marketing Team",
    "status": "active"
  }
}
```

### POST member (permanent) — request

```json
{
  "employee_id": 77,
  "division": "BD",
  "joined_at": "2026-01-15"
}
```

### POST member — response `201`

```json
{
  "success": true,
  "message": "Team member added successfully",
  "data": {
    "id": 300,
    "team_id": 20,
    "employee_id": 77,
    "employee": { "id": 77, "name": "Rahim" },
    "division": "BD",
    "status": "active",
    "joined_at": "2026-01-15",
    "left_at": null
  }
}
```

> Permanent membership has **no** `designation_id` / `is_act_as`.

---

Schema Based Business Rules

- UI copy must say this is permanent team membership, not contract assignment.
- Division BD/PD required on add.

Task Scope  
Team list by service, member management UI, permission gating, empty/error states.

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

# WAVE 2 — Contract, Share, Assignment

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract CRUD — Backend  
Branch Name  
feature-pms-contract-crud-backend  
View Order  
34  
Assignee  
Ashraful  
Description

Task Serial  
PMS-2.3-BE — Contract CRUD Backend

User Story  
As a commercial user, I want Contracts per project service with value, dates, and status so that service delivery has a commercial agreement record.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `contracts`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
contract_number — VARCHAR(50) REQUIRED  
project_id — BIGINT UNSIGNED FK → projects.id  
project_service_link_id — BIGINT UNSIGNED FK → project_service_links.id  
client_id — BIGINT UNSIGNED FK → clients.id  
start_date — DATE NULL  
end_date — DATE NULL  
contract_value — DECIMAL(15,2) REQUIRED DEFAULT 0  
currency — VARCHAR(10) REQUIRED DEFAULT 'USD'  
allocated_hours — DECIMAL(10,2) NULL  
billing_type — VARCHAR(50) NULL  
payment_terms — VARCHAR(100) NULL  
renewal_type — VARCHAR(50) NULL  
status — VARCHAR(30) REQUIRED DEFAULT 'draft' — draft, pending_approval, active, expired, completed, cancelled, terminated, renewed  
commission_eligible — BOOLEAN DEFAULT true  
notes — TEXT NULL  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Constraints  
UNIQUE(company_id, contract_number)  
INDEX(company_id, status)  
INDEX(company_id, project_id)  
INDEX(project_service_link_id)

Schema Based Business Rules

- BR-03: multiple contracts per service allowed if business permits (Phase 1: allow unless unique active constraint is later added).
- project_service_link must belong to project_id.
- client_id must equal project.client_id.
- end_date null or >= start_date.
- contract_value >= 0.
- Default status draft.

Task Scope  
Full CRUD + filters (project, service, status, date range). Number: manual or generator — document choice. Feature tests for consistency validations and IDOR.

Estimate Hours  
10.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract List/Form — Frontend  
Branch Name  
feature-pms-contract-list-form-frontend  
View Order  
35  
Assignee  
Bablu  
Description

Task Serial  
PMS-2.3-FE — Contract List/Form Frontend

User Story  
As a user, I want to create and manage contracts from the UI with project→service cascade selection.

Related Table Schema  
Consumes `contracts` API; cascade from projects + project_service_links.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-2.3`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/contracts`

### POST create — request

```json
{
  "contract_number": "DM-2026-001",
  "project_id": 100,
  "project_service_link_id": 501,
  "start_date": "2026-02-01",
  "end_date": "2026-04-30",
  "contract_value": 100.0,
  "currency": "USD",
  "allocated_hours": 40,
  "billing_type": "retainer",
  "payment_terms": "Net 15",
  "renewal_type": "manual",
  "status": "draft",
  "notes": null
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Contract created successfully",
  "data": {
    "id": 900,
    "company_id": 1,
    "contract_number": "DM-2026-001",
    "project_id": 100,
    "project_service_link_id": 501,
    "client_id": 55,
    "client": { "id": 55, "name": "ABC Corporation" },
    "service": { "id": 10, "name": "Digital Marketing" },
    "start_date": "2026-02-01",
    "end_date": "2026-04-30",
    "contract_value": "100.00",
    "currency": "USD",
    "allocated_hours": "40.00",
    "billing_type": "retainer",
    "payment_terms": "Net 15",
    "renewal_type": "manual",
    "status": "draft",
    "notes": null,
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### Status transition (optional dedicated endpoint)

`POST /api/v1/project/contracts/{id}/status`

```json
{ "status": "active", "note": "Approved by commercial" }
```

---

Schema Based Business Rules

- Service dropdown only lists services attached to selected project.
- Client read-only from project.
- Status displayed; illegal edits rely on API errors until PMS-2.4-BE UI hooks exist.

Task Scope  
List, create/edit, detail page with placeholders for Assignment and Share tabs. Permission gating.

Estimate Hours  
8.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Status Transitions — Backend  
Branch Name  
feature-pms-contract-status-transitions-backend  
View Order  
36  
Assignee  
Ashraful  
Description

Task Serial  
PMS-2.4-BE — Contract Status Transitions Backend

User Story  
As a user, I want controlled contract status transitions so that illegal jumps (e.g. Cancelled → Active) cannot corrupt commercial state.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)।  
Uses `contracts.status`.  
Optional Table: `contract_status_histories` (columns in SCHEMA-1 §13)  
Summary: id, company_id, contract_id, from_status, to_status, changed_by, note, created_at

Schema Based Business Rules

- Define allow-matrix in service (document in PR).
- Activating requires minimum fields: contract_value, start_date, valid project_service_link.
- Illegal transition → 409/422.
- Prefer appending history rows; never rewrite past history.

Task Scope  
Transition endpoint or constrained update path. History write. Unit/feature tests for allow/deny matrix.

Estimate Hours  
5.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Commission Share (Team/BD/PD Pools) — Backend  
Branch Name  
feature-pms-contract-commission-share-backend  
View Order  
39  
Assignee  
Ashraful  
Description

Task Serial  
PMS-2.5-BE — Contract Commission Share Backend

User Story  
As a commercial user, I want Team Pool and BD/PD share configured with an explicit calculation base so that commission later has an unambiguous pool.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `contract_commission_shares`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
contract_id — BIGINT UNSIGNED FK → contracts.id  
team_share_percent — DECIMAL(8,4) REQUIRED — percent of contract_value  
bd_share_percent — DECIMAL(8,4) REQUIRED — percent of team_pool  
pd_share_percent — DECIMAL(8,4) REQUIRED — percent of team_pool  
team_pool_amount — DECIMAL(15,2) REQUIRED — snapshot  
bd_pool_amount — DECIMAL(15,2) REQUIRED — snapshot  
pd_pool_amount — DECIMAL(15,2) REQUIRED — snapshot  
currency — VARCHAR(10) REQUIRED  
effective_from — DATE REQUIRED  
effective_to — DATE NULL  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Indexes  
INDEX(company_id, contract_id)  
INDEX(contract_id, effective_from)

Schema Based Business Rules

- BR-09/BR-10/BR-14: Contract Value → Team Share % → Team Pool → BD% + PD% → BD/PD pools.
- bd_share_percent + pd_share_percent must equal 100 (±0.0001).
- Server computes pool amounts; client preview must not be sole source of truth.
- BR-15 spirit: changing shares creates a new effective row (or closes prior row); do not mutate historical snapshots used by finalized earnings.
- Example fixture: contract_value 100, team 30%, BD 40%, PD 60% → team_pool 30, bd 12, pd 18.

Task Scope  
Set/get/list share versions for a contract. Calculation in service layer. Unit tests for math + validation. Feature tests for persistence and non-destructive updates.

Estimate Hours  
8.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Commission Share — Frontend  
Branch Name  
feature-pms-contract-commission-share-frontend  
View Order  
40  
Assignee  
Bablu  
Description

Task Serial  
PMS-2.5-FE — Contract Commission Share Frontend

User Story  
As a user, I want to configure and preview Team/BD/PD pools on a contract so that commercial splits are visible before commission rules run.

Related Table Schema  
Consumes `contract_commission_shares` API.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-2.5`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/contracts/{contractId}/commission-shares`

### PUT/POST set — request

```json
{
  "team_share_percent": 30.0,
  "bd_share_percent": 40.0,
  "pd_share_percent": 60.0,
  "effective_from": "2026-02-01"
}
```

### Response `200` / `201` (server computes pools from contract_value)

```json
{
  "success": true,
  "message": "Commission share saved successfully",
  "data": {
    "id": 70,
    "contract_id": 900,
    "calculation_base": "contract_value",
    "contract_value": "100.00",
    "team_share_percent": "30.0000",
    "bd_share_percent": "40.0000",
    "pd_share_percent": "60.0000",
    "team_pool_amount": "30.00",
    "bd_pool_amount": "12.00",
    "pd_pool_amount": "18.00",
    "currency": "USD",
    "effective_from": "2026-02-01",
    "effective_to": null
  }
}
```

### BD+PD ≠ 100 — response `422`

```json
{
  "success": false,
  "message": "Validation failed.",
  "errors": {
    "bd_share_percent": ["BD share percent plus PD share percent must equal 100."]
  }
}
```

---

Schema Based Business Rules

- Show Contract Value, Team Pool, BD Pool, PD Pool.
- Block submit when BD+PD ≠ 100 (client-side) and still handle API 422.
- Display effective dating if multiple versions exist.

Task Scope  
Share form on contract detail. Preview numbers. Save/reload. Permission gating.

Estimate Hours  
5.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Attachments — Backend  
Branch Name  
feature-pms-contract-attachments-backend  
View Order  
41  
Assignee  
Ashraful  
Description

Task Serial  
PMS-2.6-BE — Contract Attachments Backend

User Story  
As a user, I want to attach agreement documents to a contract so that commercial files live with the contract record.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `contract_attachments`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
contract_id — BIGINT UNSIGNED FK → contracts.id  
file_path — VARCHAR(255) REQUIRED  
original_name — VARCHAR(255) REQUIRED  
mime — VARCHAR(100) NULL  
size — BIGINT UNSIGNED NULL  
uploaded_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
INDEX(company_id, contract_id)

Schema Based Business Rules

- Follow existing ERP file storage / virus/size policies.
- Allowed mime types documented (PDF, DOC, DOCX, images as agreed).
- Delete authorized for uploader or manage permission.
- Tenant-scoped paths; no cross-company file access.

Task Scope  
Upload, list, delete endpoints using existing storage patterns. Feature tests for authz and company scope.

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Team Assignment & Act As — Backend  
Branch Name  
feature-pms-contract-assignment-act-as-backend  
View Order  
44  
Assignee  
Munna  
Description

Task Serial  
PMS-3.3-BE — Contract Team Assignment & Act As Backend

User Story  
As an operations user, I want to assign selected BD/PD members to a contract with roles including Act As so that permanent team membership stays unchanged while contract responsibility is recorded.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `contract_team_assignments`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
contract_id — BIGINT UNSIGNED FK → contracts.id  
team_id — BIGINT UNSIGNED NULL FK → service_teams.id  
division — VARCHAR(10) REQUIRED — BD, PD  
status — VARCHAR(20) DEFAULT 'active'  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
INDEX(company_id, contract_id, division)

Table: `contract_members`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
contract_id — BIGINT UNSIGNED FK → contracts.id  
assignment_id — BIGINT UNSIGNED NULL FK → contract_team_assignments.id  
employee_id — BIGINT UNSIGNED FK  
division — VARCHAR(10) REQUIRED — BD, PD  
designation_id — BIGINT UNSIGNED REQUIRED FK → designations.id  
is_act_as — BOOLEAN DEFAULT false  
status — VARCHAR(20) DEFAULT 'active'  
assigned_at — TIMESTAMP NULL  
unassigned_at — TIMESTAMP NULL  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
INDEX(company_id, contract_id)  
INDEX(company_id, employee_id)

Schema Based Business Rules

- BR-06/07/08: permanent membership unchanged; Act As allowed; selected members (not forced whole team).
- Same employee may be on multiple contracts with different roles.
- Employee from SEO team may Act As Sales on Digital Marketing contract (`is_act_as=true`).
- Official designation on employee profile does not change.
- Assigning does not require the employee to be permanent member of the contract’s service team (Act As path).
- Duplicate active assignment rules: document (e.g. one active row per contract+employee+division or per role).

Task Scope  
Assign/list/update/unassign APIs. Feature test for Rahim-style Act As scenario from SRS §15/§27. IDOR tests.

Estimate Hours  
10.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Assignment — Frontend  
Branch Name  
feature-pms-contract-assignment-frontend  
View Order  
45  
Assignee  
Bablu  
Description

Task Serial  
PMS-3.3-FE — Contract Assignment Frontend

User Story  
As a user, I want a Contract Assignment UI for BD/PD members and Act As roles so that staffing a contract is operationally clear.

Related Table Schema  
Consumes `contract_team_assignments`, `contract_members`; employee search; designations.

API Request / Response  
নিচে sample — আলাদা ফাইল খোলার দরকার নেই (source: `PMS-API-3.3`)।

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/contracts/{contractId}/members`

### POST assign — request

```json
{
  "employee_id": 77,
  "division": "BD",
  "designation_id": 101,
  "is_act_as": true,
  "team_id": 20
}
```

### POST assign — response `201`

```json
{
  "success": true,
  "message": "Contract member assigned successfully",
  "data": {
    "id": 800,
    "contract_id": 900,
    "employee_id": 77,
    "employee": { "id": 77, "name": "Rahim" },
    "division": "BD",
    "designation_id": 101,
    "designation": { "id": 101, "name": "Sales Person" },
    "is_act_as": true,
    "permanent_team": {
      "id": 15,
      "name": "SEO Team",
      "service": { "id": 9, "name": "SEO" }
    },
    "status": "active",
    "assigned_at": "2026-02-01T10:00:00+00:00",
    "unassigned_at": null
  }
}
```

### Business meaning of this sample

Rahim’s **permanent** team remains SEO. On DM contract he is **Act As** Sales Person. Official HR designation is unchanged.

---

Schema Based Business Rules

- Clear visual distinction: permanent team vs contract role.
- Act As indicated when employee’s home service team ≠ contract service.
- Roles include Sales Person, Closer, Manager, Regional Manager, PM (Member of Project) with helper text.

Task Scope  
Assignment tab on contract detail. Add/remove members, role select, division tabs/sections. Permission gating.

Estimate Hours  
8.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Assignment Validation Matrix — Backend  
Branch Name  
feature-pms-assignment-validation-matrix-backend  
View Order  
46  
Assignee  
Munna  
Description

Task Serial  
PMS-3.4-BE — Assignment Validation Matrix Backend

User Story  
As a system, I want centralized assignment validations so that invalid contract staffing is rejected consistently.

Related Table Schema  
Reads/writes `contract_members`, reads `contracts`, `service_team_members`, employees.

Schema Based Business Rules

- Cannot assign to cancelled/terminated contracts (unless explicitly allowed — default deny).
- Inactive employees cannot be newly assigned.
- designation_id required and must exist in company/allowed map.
- Clear 422 messages for each failure mode.

Task Scope  
Extract/strengthen validation service used by PMS-3.3-BE. Unit tests covering validation matrix. No schema change required unless gaps found.

Estimate Hours  
5.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Assignment History / Unassign — Backend  
Branch Name  
feature-pms-assignment-history-backend  
View Order  
47  
Assignee  
Munna  
Description

Task Serial  
PMS-3.5-BE — Assignment History Backend

User Story  
As an auditor, I want assignment changes preserved historically so that past contract staffing remains reconstructable.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)।  
Primary: `contract_members.unassigned_at` / status.  
Optional Table: `contract_member_histories` (SCHEMA-1 §18)  
Summary: id, company_id, contract_member_id, action, payload JSON, acted_by, created_at

Schema Based Business Rules

- Unassign sets unassigned_at / inactive; do not hard-delete historical rows.
- Re-assign creates a new row rather than erasing prior history.
- BR-15 aligned: history is append-only.

Task Scope  
Unassign API behavior + tests proving history retained. Optional history table if product wants explicit audit log.

Estimate Hours  
5.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
PMS Demo Seeder  
Branch Name  
feature-pms-demo-seeder  
View Order  
48  
Assignee  
Sharif  
Description

Task Serial  
PMS-4.1-BE — Demo Seeder

User Story  
As a developer/QA, I want idempotent demo data for the SRS ABC scenario so that local environments can exercise the full hierarchy quickly.

Related Table Schema  
Seeder data SCHEMA মতো হতে হবে: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md)।  
Tables: project_types, pms_services, team_divisions, service_teams, service_team_members, projects, project_service_links, contracts (SEO + DM), contract_members (incl. Act As), contract_commission_shares ($100 example).

Schema Based Business Rules

- Idempotent (second run does not duplicate).
- No production secrets.
- Demo names clearly marked (e.g. ABC Corporation / ABC Digital Growth).

Task Scope  
Module seeder + hook from ProjectDatabaseSeeder. Document how to run. Optional artisan flag for demo-only.

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

# WAVE 3 — Earning Shell, Reports, QA

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Commission Earning Records Shell — Backend  
Branch Name  
feature-pms-commission-earning-records-shell-backend  
View Order  
49  
Assignee  
Ashraful  
Description

Task Serial  
PMS-5.1-BE — Commission Earning Records Shell Backend

User Story  
As a system, I want earning records stored separately from commission rules so that historical earnings are never overwritten when rules change.

Related Table Schema  
Column গুলো এখান থেকে নাও: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md) (`PMS-SCHEMA-1`)। Migration ওই doc মিলিয়ে লিখো।
সংক্ষেপে:
Table: `commission_earning_records`  
Columns  
id — BIGINT UNSIGNED PK  
company_id — BIGINT UNSIGNED FK  
contract_id — BIGINT UNSIGNED FK → contracts.id  
employee_id — BIGINT UNSIGNED FK  
designation_id — BIGINT UNSIGNED NULL  
division — VARCHAR(10) NULL — BD, PD  
rule_id — BIGINT UNSIGNED NULL FK → commission_rules.id  
calculation_base_type — VARCHAR(40) REQUIRED  
base_amount — DECIMAL(15,2) REQUIRED  
percentage — DECIMAL(8,4) NULL  
fixed_amount — DECIMAL(15,2) NULL  
earning_amount — DECIMAL(15,2) REQUIRED  
period_start — DATE NULL  
period_end — DATE NULL  
status — VARCHAR(20) DEFAULT 'draft' — draft, finalized, cancelled  
finalized_at — TIMESTAMP NULL  
meta — JSON NULL — frozen inputs snapshot  
created_by — BIGINT UNSIGNED NULL  
updated_by — BIGINT UNSIGNED NULL  
created_at — TIMESTAMP  
updated_at — TIMESTAMP  
Indexes  
INDEX(company_id, contract_id)  
INDEX(company_id, employee_id)  
INDEX(company_id, status)

Schema Based Business Rules

- BR-15: finalized rows immutable w.r.t. rule updates.
- Updating `commission_rules` must not change existing earning_amount.
- Phase 1 may allow manual/admin draft create + finalize; **no full engine**.
- meta should snapshot base amounts/percentages used.

Task Scope  
Migration + list/show/create-draft/finalize(cancel) APIs. Test: create earning, change rule, assert earning unchanged. Explicit Phase 2 boundary in PR.

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Payment Cleared Integration Hook  
Branch Name  
feature-pms-payment-cleared-integration-hook  
View Order  
51  
Assignee  
Ashraful  
Description

Task Serial  
PMS-5.2-BE — Payment Cleared Integration Hook

User Story  
As a developer, I want a payment-cleared integration contract so that future commission calculation starts only after client payment is cleared—not on project create or invoice draft.

Related Table Schema  
N/A new payment tables. Define event/interface payload referencing existing payment flow fields, e.g.:  
project_id, contract_id (nullable if project-level), payment_reference, payment_date, payment_status, payment_amount / applicable_net_base, company_id

Schema Based Business Rules

- Commission processing must not duplicate payment implementation.
- Trigger only when status is received/cleared (name per payment module).
- Listener in Phase 1 may be no-op or log-only; must not fake full distribution.

Task Scope  
PHP interface and/or domain event + documented payload. Optional no-op listener. Integration note linking Implementation Plan Phase 9.

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Employee-wise Assignment Report API  
Branch Name  
feature-pms-employee-assignment-report-backend  
View Order  
52  
Assignee  
Munna  
Description

Task Serial  
PMS-5.3-BE — Employee Assignment Report Backend

User Story  
As a manager, I want an employee-wise assignment report so that I can see permanent teams and contract roles (including Act As) in one place.

Related Table Schema  
Reads: `service_team_members`, `contract_members`, `contracts`, `projects`, `pms_services`, designations.

Schema Based Business Rules

- Permanent vs contract assignment clearly separated in response shape.
- Company scoped.
- Filters: employee_id, status, date (as-of optional).

Task Scope  
Report endpoint + resource. Feature test with Act As fixture.

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract/Service Team Report API  
Branch Name  
feature-pms-contract-service-team-report-backend  
View Order  
54  
Assignee  
Munna  
Description

Task Serial  
PMS-5.4-BE — Contract/Service Team Report Backend

User Story  
As a manager, I want contract-wise and service-wise team reports so that staffing per commercial unit is visible.

Related Table Schema  
Reads: `contracts`, `contract_members`, `service_teams`, `service_team_members`, `project_service_links`.

Schema Based Business Rules

- Contract-wise: members + roles + division.
- Service-wise: permanent team + optional active contract assignments summary.
- Tenant safe.

Task Scope  
One or two report endpoints. Tests for both groupings.

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Active/Expired Contracts Report API  
Branch Name  
feature-pms-active-expired-contracts-report-backend  
View Order  
58  
Assignee  
Sharif  
Description

Task Serial  
PMS-5.5-BE — Active/Expired Contracts Report Backend

User Story  
As a manager, I want active and expired contract lists so that commercial portfolio health is visible.

Related Table Schema  
Reads: `contracts` (+ projects/clients for display fields).

Schema Based Business Rules

- Document whether “expired” is status=expired and/or end_date < today.
- Prefer: status drives reporting; optional job later to auto-flip status (out of this card unless trivial).

Task Scope  
Filtered report API. Tests for active vs expired datasets.

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Commission Share Summary API  
Branch Name  
feature-pms-contract-commission-share-summary-backend  
View Order  
60  
Assignee  
Sharif  
Description

Task Serial  
PMS-5.6-BE — Contract Team Share Summary Backend

User Story  
As a manager, I want contract commission and team share summaries so that pool distribution is reviewable without opening each contract.

Related Table Schema  
Reads: `contracts`, `contract_commission_shares` (current effective row).

Schema Based Business Rules

- Numbers must match share service ($100 → $30 → $12/$18 fixture).
- Filters: project_id, date range, status.
- Explicit base fields in response.

Task Scope  
Summary list/detail endpoint. Feature tests with known math.

Estimate Hours  
4.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Assignment Report — Frontend  
Branch Name  
feature-pms-assignment-report-frontend  
View Order  
53  
Assignee  
Bablu  
Description

Task Serial  
PMS-5.3-FE — Assignment Report Frontend

User Story  
As a manager, I want an assignment report screen so that employee permanent vs contract roles are auditable from the UI.

Related Table Schema  
Consumes PMS-5.3-BE API.

API Request / Response  
Base: `GET /api/v1/project/reports/employee-assignments`

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### GET — query

`?employee_id=77&project_id=100`

### GET — response `200`

```json
{
  "success": true,
  "message": "Assignment report fetched successfully",
  "data": [
    {
      "employee_id": 77,
      "employee_name": "Rahim",
      "permanent_memberships": [
        { "team": "SEO Team", "division": "PD", "service": "SEO" }
      ],
      "contract_assignments": [
        {
          "contract_number": "DM-2026-001",
          "division": "BD",
          "role": "Sales Person",
          "is_act_as": true
        }
      ]
    }
  ]
}
```

Schema Based Business Rules

- Show Act As badge/flag.
- Permission: project.reports-view (or equivalent).

Task Scope  
Report page with filters, table, empty/error states. Nav under Project › Reports.

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Team Reports — Frontend  
Branch Name  
feature-pms-team-reports-frontend  
View Order  
55  
Assignee  
Bablu  
Description

Task Serial  
PMS-5.4-FE — Team Reports Frontend

User Story  
As a manager, I want contract-wise and service-wise team report screens.

Related Table Schema  
Consumes PMS-5.4-BE API.

API Request / Response  
Base: `GET /api/v1/project/reports/contract-teams` · `GET /api/v1/project/reports/service-teams`

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### Contract-wise — response `200`

```json
{
  "success": true,
  "message": "Contract team report fetched successfully",
  "data": [
    {
      "contract_id": 900,
      "contract_number": "DM-2026-001",
      "service": "Digital Marketing",
      "members": [
        { "employee_name": "Rahim", "division": "BD", "role": "Sales Person", "is_act_as": true }
      ]
    }
  ]
}
```

### Service-wise — response `200`

```json
{
  "success": true,
  "message": "Service team report fetched successfully",
  "data": [
    {
      "service_id": 10,
      "service_name": "Digital Marketing",
      "teams": [
        {
          "team_id": 20,
          "team_name": "Digital Marketing Team",
          "members": [
            { "employee_name": "Karim", "division": "PD", "status": "active" }
          ]
        }
      ]
    }
  ]
}
```

Schema Based Business Rules

- Toggle or tabs for contract-wise vs service-wise.
- Permission gated.

Task Scope  
Report UI + filters. Match ERP report page patterns.

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Status Report — Frontend  
Branch Name  
feature-pms-contract-status-report-frontend  
View Order  
59  
Assignee  
Bablu  
Description

Task Serial  
PMS-5.5-FE — Contract Status Report Frontend

User Story  
As a manager, I want active/expired contract report UI.

Related Table Schema  
Consumes PMS-5.5-BE API.

API Request / Response  
Base: `GET /api/v1/project/reports/contracts-by-status`

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### GET — query

`?status=active,expired&page=1`

### GET — response `200`

```json
{
  "success": true,
  "message": "Contract status report fetched successfully",
  "data": [
    {
      "id": 900,
      "contract_number": "DM-2026-001",
      "project_name": "ABC Digital Growth",
      "client_name": "ABC Corporation",
      "status": "active",
      "start_date": "2026-02-01",
      "end_date": "2026-04-30",
      "contract_value": "100.00",
      "currency": "USD"
    }
  ],
  "meta": { "current_page": 1, "per_page": 15, "total": 1, "last_page": 1 }
}
```

Schema Based Business Rules

- Clear status filters.
- Link through to contract detail when permitted.

Task Scope  
Report page. Empty/error/loading states.

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Commission Share Summary — Frontend  
Branch Name  
feature-pms-commission-share-summary-frontend  
View Order  
61  
Assignee  
Bablu  
Description

Task Serial  
PMS-5.6-FE — Team Share Summary Frontend

User Story  
As a manager, I want a commission/share summary screen showing contract value and Team/BD/PD pools.

Related Table Schema  
Consumes PMS-5.6-BE API.

API Request / Response  
Base: `GET /api/v1/project/reports/commission-share-summary`

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### GET — query

`?project_id=100&from=2026-01-01&to=2026-12-31`

### GET — response `200`

```json
{
  "success": true,
  "message": "Commission share summary fetched successfully",
  "data": [
    {
      "contract_id": 900,
      "contract_number": "DM-2026-001",
      "contract_value": "100.00",
      "team_share_percent": "30.0000",
      "team_pool_amount": "30.00",
      "bd_share_percent": "40.0000",
      "bd_pool_amount": "12.00",
      "pd_share_percent": "60.0000",
      "pd_pool_amount": "18.00",
      "currency": "USD",
      "effective_from": "2026-02-01"
    }
  ]
}
```

Schema Based Business Rules

- Display explicit bases (contract value → pools).
- Permission gated.

Task Scope  
Summary table/page with filters. Optional export later (not required Phase 1).

Estimate Hours  
3.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
QA  
Title  
E2E SRS Scenario — ABC Digital Growth  
Branch Name  
feature-pms-qa-e2e-abc-digital-growth  
View Order  
65  
Assignee  
All (Ashraful leads)  
Description

Task Serial  
PMS-QA-1 — E2E SRS Scenario

User Story  
As QA, I want one end-to-end path proving the SRS example so that Act As and pool math are verified before Phase 2 commission work starts.

Related Table Schema  
All Phase 1 tables (prefer seeder from PMS-4.1-BE).

Schema Based Business Rules  
Scenario must prove:

1. Client ABC → Project ABC Digital Growth
2. Services SEO + Digital Marketing with contracts
3. Rahim permanent team = SEO; on DM contract Act As Sales Person
4. DM contract value 100; team share 30%; BD 40%; PD 60% → pools 30 / 12 / 18
5. Permanent membership unchanged after Act As assignment
6. Rule change does not alter finalized earning (if any created in shell)

Task Scope  
Automated feature test and/or written QA script with steps + expected results. Block Phase 2 epic until this passes.

Estimate Hours  
6.00  
Status

- QA Status
- QA Comment
-

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Epic  
Title  
Phase 2 — Commission Engine Epic (Parent Only)  
Branch Name  
n/a  
View Order  
66  
Assignee  
—  
Description

Task Serial  
PMS-COMM-EPIC — Phase 2 Commission Engine

User Story  
As finance, I want a full commission engine (BD/PD distribution, office expense base, fixed team allocation, PF/EPS, payment-triggered calculation) so that earnings are generated from cleared payments using approved business formulas.

Related Table Schema  
Extends Phase 1 plus existing:  
`office_expense_rules`  
`provident_fund_role_rules`  
Plus Implementation Plan tables such as project team distribution, commission schedule/summary, PF summaries (to be broken into child cards later).

Schema Based Business Rules

- Starts only after payment cleared.
- Exact BD/Closer/Sales/Act As/PM formulas must be signed off before child cards.
- Historical earnings remain immutable.
- Reuse existing PMS/ERP structures; no duplicate payment module.

Task Scope  
Parent epic only. Do not implement inside Phase 1. Break into child cards after PMS-QA-1 passes and commissioning business rules document is approved.

Estimate Hours  
0.00  
Status  
Blocked (Phase 1)  
QA Status

- QA Comment
-

---



---

# APPENDIX — SRS gap fill + API Contract paste cards

> Added so **every SRS §31 Phase-1 capability** and **every WBS leaf** has an assignable task card.

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
PMS API Envelope & Error Contract  
Branch Name  
docs-pms-api-envelope-contract  
View Order  
3  
Assignee  
Ashraful  
Description  

Task Serial  
PMS-API-0 — API Envelope & Error Contract  

User Story  
As a developer, I want a frozen API envelope and error contract so that backend and frontend can implement PMS endpoints consistently in parallel.

Related Table Schema  
N/A (documentation contract)

API Request / Response  
Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### Success (single resource)

```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "success": true,
  "message": "Operation successful",
  "data": {}
}
```

### Success (created)

```http
HTTP/1.1 201 Created
```

```json
{
  "success": true,
  "message": "Created successfully",
  "data": {
    "id": 1
  }
}
```

### Success (paginated list)

```json
{
  "success": true,
  "message": "Operation successful",
  "data": [],
  "meta": {
    "current_page": 1,
    "per_page": 15,
    "total": 0,
    "last_page": 1
  },
  "links": {
    "first": "https://api.example/api/v1/project/...?page=1",
    "last": "https://api.example/api/v1/project/...?page=1",
    "prev": null,
    "next": null
  }
}
```

### Validation error

```http
HTTP/1.1 422 Unprocessable Entity
```

```json
{
  "success": false,
  "message": "Validation failed.",
  "errors": {
    "name": ["The name field is required."]
  }
}
```

### Unauthorized / Forbidden

```json
{
  "success": false,
  "message": "Unauthenticated.",
  "errors": {}
}
```

```json
{
  "success": false,
  "message": "This action is unauthorized.",
  "errors": {}
}
```

---

Schema Based Business Rules  
- Use existing ERPFlow success/error response shapes.  
- 401 unauthenticated, 403 missing permission, 404/403 for IDOR, 422 validation, 409 state conflict where applicable.  
- Permission prefix `project.*`.

Task Scope  
Publish contract section in `docs/project-management/wbs/11-api.md`: envelope, pagination, status codes, permission naming, example OK/error payloads. No feature endpoints yet.

Estimate Hours  
2.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Project Types API Contract  
Branch Name  
docs-pms-api-project-types-contract  
View Order  
6  
Assignee  
Sharif  
Description  

Task Serial  
PMS-API-1.1 — Project Types API Contract  

User Story  
As FE/BE developers, we want the Project Types API locked so UI and implementation can proceed without waiting on each other.

Related Table Schema  
Documents contract for table `project_types` (see PMS-1.1-BE).

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/types`  
**Permission:** `project.types-view|create|update|delete`

### POST create — request

```json
{
  "name": "Retainer Project",
  "code": "RETAINER",
  "description": "Monthly retainer engagement",
  "status": "active"
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Project type created successfully",
  "data": {
    "id": 1,
    "company_id": 1,
    "name": "Retainer Project",
    "code": "RETAINER",
    "description": "Monthly retainer engagement",
    "status": "active",
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### GET index — response `200` (paginated `data[]` same object shape)

### GET active — response `200` (dropdown)

```json
{
  "success": true,
  "message": "Active project types fetched successfully",
  "data": [
    { "id": 1, "name": "Retainer Project", "code": "RETAINER" }
  ]
}
```

---

Schema Based Business Rules  
- Unique name per company.  
- Active list endpoint for dropdowns.

Task Scope  
Document CRUD + active endpoints, payloads, errors, permissions, examples in `11-api.md`.

Estimate Hours  
1.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project Categories — Verify & Wire (Existing)  
Branch Name  
feature-pms-project-categories-verify-wire  
View Order  
9  
Assignee  
Sharif  
Description  

Task Serial  
PMS-1.0-BE — Project Categories Verify & Wire  

User Story  
As a project user, I want existing Project Categories available to Projects so that SRS master “Project Categories” is complete in the Project module.

Related Table Schema  
`project_categories` — [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md)। আগে থেকেই আছে; column মিল আছে কিনা দেখো। দরকার না হলে আবার বানাবেন না।

Schema Based Business Rules  
- Category must belong to same company as project.  
- Do not recreate category CRUD if already complete — verify API + permissions + Project FK wiring.

Task Scope  
Audit existing Category API/tests/permissions. Fix gaps only. Ensure Project FormRequest/service can resolve `project_category_id`. Document “already delivered + verified” in PR.

Estimate Hours  
2.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project Categories — FE Verify/Wire  
Branch Name  
feature-pms-project-categories-fe-verify  
View Order  
10  
Assignee  
Bablu  
Description  

Task Serial  
PMS-1.0-FE — Project Categories FE Verify/Wire  

User Story  
As an admin, I want Category UI/dropdowns working with Projects so category selection is usable end-to-end.

Related Table Schema  
Consumes existing categories API.

API Request / Response  
Base: `/api/v1/project/categories` (existing — path BE verify)

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### GET list — response `200`

```json
{
  "success": true,
  "message": "Categories fetched successfully",
  "data": [
    { "id": 3, "name": "Digital Marketing", "parent_id": null, "status": "active" },
    { "id": 4, "name": "SEO", "parent_id": 3, "status": "active" }
  ],
  "meta": { "current_page": 1, "per_page": 15, "total": 2, "last_page": 1 }
}
```

### GET active (dropdown) — response `200`

```json
{
  "success": true,
  "message": "Active categories fetched successfully",
  "data": [
    { "id": 3, "name": "Digital Marketing" },
    { "id": 4, "name": "SEO" }
  ]
}
```


Schema Based Business Rules  
- Permission gated.  
- Project form category dropdown uses active categories.

Task Scope  
Verify category admin screen if present; wire Project form category dropdown; fix gaps only.

Estimate Hours  
2.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Service Master API Contract  
Branch Name  
docs-pms-api-service-master-contract  
View Order  
11  
Assignee  
Sharif  
Description  

Task Serial  
PMS-API-1.2 — Service Master API Contract  

User Story  
As FE/BE developers, we want Service Master API locked for parallel work.

Related Table Schema  
`pms_services` (see PMS-1.2-BE)

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/services`  
**Permission:** `project.services-*`

### POST create — request

```json
{
  "name": "Digital Marketing",
  "code": "DM",
  "description": null,
  "status": "active"
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Service created successfully",
  "data": {
    "id": 10,
    "company_id": 1,
    "name": "Digital Marketing",
    "code": "DM",
    "description": null,
    "status": "active",
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### GET active — response `200`

```json
{
  "success": true,
  "message": "Active services fetched successfully",
  "data": [
    { "id": 9, "name": "SEO", "code": "SEO" },
    { "id": 10, "name": "Digital Marketing", "code": "DM" }
  ]
}
```

---

Schema Based Business Rules  
- Unique name/company; active dropdown list.

Task Scope  
Document endpoints/payloads/errors/permissions/examples in `11-api.md`.

Estimate Hours  
1.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Team Divisions & Roles API Contract  
Branch Name  
docs-pms-api-team-divisions-roles-contract  
View Order  
14  
Assignee  
Sharif  
Description  

Task Serial  
PMS-API-1.3 — Team Divisions & Roles API Contract  

User Story  
As FE/BE developers, we want BD/PD divisions and role reference APIs locked.

Related Table Schema  
`team_divisions`; designations reuse; optional `pms_contract_role_maps`

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Bases:**  
- `/api/v1/project/team-divisions`  
- `/api/v1/project/contract-roles` (designations mapped for PMS; may proxy existing designations)

### GET team-divisions — response `200`

```json
{
  "success": true,
  "message": "Team divisions fetched successfully",
  "data": [
    { "id": 1, "code": "BD", "name": "Business Development", "status": "active" },
    { "id": 2, "code": "PD", "name": "Product Development", "status": "active" }
  ]
}
```

### GET contract-roles — response `200`

```json
{
  "success": true,
  "message": "Contract roles fetched successfully",
  "data": [
    {
      "designation_id": 101,
      "name": "Sales Person",
      "division_code": "BD",
      "is_act_as_allowed": true
    },
    {
      "designation_id": 102,
      "name": "Closer",
      "division_code": "BD",
      "is_act_as_allowed": true
    },
    {
      "designation_id": 201,
      "name": "PM",
      "label": "Member of Project",
      "division_code": "PD",
      "is_act_as_allowed": true
    }
  ]
}
```

> **PM** in `name`/`label` means **Member of Project**, not Project Manager.

---

Schema Based Business Rules  
- PM label = Member of Project in docs/examples.  
- No separate ActAs master.

Task Scope  
Document list/seed/read contracts in `11-api.md`.

Estimate Hours  
1.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Commission Types Master/Enum — Backend  
Branch Name  
feature-pms-commission-types-backend  
View Order  
17  
Assignee  
Sharif  
Description  

Task Serial  
PMS-1.4a-BE — Commission Types Backend  

User Story  
As an admin, I want Commission Types available as master/enum (One Time, Recurring, Monthly, Contract Based, Milestone Based) so SRS master management is complete before rules.

Related Table Schema  
সিদ্ধান্ত SCHEMA doc §6-এ: [phase1-database-schema.md](../project-management/wbs/phase1-database-schema.md)।  
Phase 1-এ মূলত `commission_rules.commission_type`-এ enum/string। Dropdown লাগলে read-only `/commission-types`। CRUD master শুধু product জোর করলে।  
Values: one_time | recurring | monthly | contract_based | milestone_based.

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/projects/{projectId}/services`

### POST attach — request

```json
{
  "service_id": 10,
  "status": "active"
}
```

### POST attach — response `201`

```json
{
  "success": true,
  "message": "Service attached to project successfully",
  "data": {
    "id": 501,
    "project_id": 100,
    "service_id": 10,
    "service": { "id": 10, "name": "Digital Marketing", "code": "DM" },
    "status": "active",
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### Duplicate attach — response `422`

```json
{
  "success": false,
  "message": "Validation failed.",
  "errors": {
    "service_id": ["This service is already attached to the project."]
  }
}
```

---

Schema Based Business Rules  
- SRS §23 initial types required.  
- Do not implement calculation.

Task Scope  
Implement enum endpoint or CRUD master; seed defaults; tests; wire into PMS-1.4-BE validation.

Estimate Hours  
3.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Commission Types — Frontend  
Branch Name  
feature-pms-commission-types-frontend  
View Order  
18  
Assignee  
Bablu  
Description  

Task Serial  
PMS-1.4a-FE — Commission Types Frontend  

User Story  
As an admin, I want to see/select Commission Types when configuring rules.

Related Table Schema  
Consumes commission-types API.

API Request / Response  
Base: `/api/v1/project/commission-types` (read-only enum list Phase 1)

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### GET list — response `200`

```json
{
  "success": true,
  "message": "Commission types fetched successfully",
  "data": [
    { "code": "one_time", "name": "One Time" },
    { "code": "recurring", "name": "Recurring" },
    { "code": "monthly", "name": "Monthly" },
    { "code": "contract_based", "name": "Contract Based" },
    { "code": "milestone_based", "name": "Milestone Based" }
  ]
}
```

Schema Based Business Rules  
- Types used as dropdown on Commission Rules form.

Task Scope  
If CRUD master: simple list UI. If enum: dropdown only on rules form (may merge visually with 1.4-FE).

Estimate Hours  
2.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Commission Rules Shell API Contract  
Branch Name  
docs-pms-api-commission-rules-contract  
View Order  
19  
Assignee  
Sharif  
Description  

Task Serial  
PMS-API-1.4 — Commission Rules Shell API Contract  

User Story  
As FE/BE developers, we want commission rule CRUD contract locked with **no calculate endpoint**.

Related Table Schema  
`commission_rules`

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/commission-rules`  
**Note:** No `POST .../calculate` endpoint in Phase 1.

### POST create — request

```json
{
  "name": "BD Sales One-Time 10% of BD Pool",
  "commission_type": "one_time",
  "calculation_base": "bd_pool",
  "percentage": 10.0,
  "fixed_amount": null,
  "frequency": null,
  "duration_value": null,
  "duration_type": null,
  "team_division": "BD",
  "role_designation_id": 101,
  "status": "active",
  "effective_from": "2026-01-01",
  "effective_to": null
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Commission rule created successfully",
  "data": {
    "id": 5,
    "company_id": 1,
    "name": "BD Sales One-Time 10% of BD Pool",
    "commission_type": "one_time",
    "calculation_base": "bd_pool",
    "percentage": "10.0000",
    "fixed_amount": null,
    "team_division": "BD",
    "role_designation_id": 101,
    "status": "active",
    "effective_from": "2026-01-01",
    "effective_to": null,
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

---

Schema Based Business Rules  
- Shell only — no earning generation endpoints.

Task Scope  
Document CRUD contract in `11-api.md`; explicitly forbid Generate/Calculate.

Estimate Hours  
1.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Projects API Contract  
Branch Name  
docs-pms-api-projects-contract  
View Order  
23  
Assignee  
Ashraful  
Description  

Task Serial  
PMS-API-2.1 — Projects API Contract  

User Story  
As FE/BE developers, we want Projects API locked including status enum and FK rules.

Related Table Schema  
`projects`

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/projects`  
**Permission:** `project.projects-*`

### POST create — request

```json
{
  "client_id": 55,
  "name": "ABC Digital Growth",
  "project_type_id": 1,
  "project_category_id": 3,
  "description": "Digital growth engagement",
  "start_date": "2026-01-01",
  "expected_end_date": "2026-12-31",
  "status": "draft",
  "owner_user_id": 12
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Project created successfully",
  "data": {
    "id": 100,
    "company_id": 1,
    "client_id": 55,
    "client": { "id": 55, "name": "ABC Corporation" },
    "name": "ABC Digital Growth",
    "project_type_id": 1,
    "project_type": { "id": 1, "name": "Retainer Project" },
    "project_category_id": 3,
    "project_category": { "id": 3, "name": "Digital Marketing" },
    "description": "Digital growth engagement",
    "start_date": "2026-01-01",
    "expected_end_date": "2026-12-31",
    "status": "draft",
    "owner_user_id": 12,
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### GET index query

`?status=active&client_id=55&search=ABC&page=1`

---

Schema Based Business Rules  
- BR-01; same-company client/type/category.

Task Scope  
Document CRUD/filters/status in `11-api.md`.

Estimate Hours  
1.50  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Project Service Links API Contract  
Branch Name  
docs-pms-api-project-services-contract  
View Order  
26  
Assignee  
Ashraful  
Description  

Task Serial  
PMS-API-2.2 — Project Service Links API Contract  

User Story  
As FE/BE developers, we want attach/detach service contract locked (BR-02).

Related Table Schema  
`project_service_links`

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/projects/{projectId}/services`

### POST attach — request

```json
{
  "service_id": 10,
  "status": "active"
}
```

### POST attach — response `201`

```json
{
  "success": true,
  "message": "Service attached to project successfully",
  "data": {
    "id": 501,
    "project_id": 100,
    "service_id": 10,
    "service": { "id": 10, "name": "Digital Marketing", "code": "DM" },
    "status": "active",
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### Duplicate attach — response `422`

```json
{
  "success": false,
  "message": "Validation failed.",
  "errors": {
    "service_id": ["This service is already attached to the project."]
  }
}
```

---

Schema Based Business Rules  
- Unique (project, service).

Task Scope  
Document nested project service endpoints in `11-api.md`.

Estimate Hours  
1.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Service Teams & Membership API Contract  
Branch Name  
docs-pms-api-service-teams-contract  
View Order  
29  
Assignee  
Munna  
Description  

Task Serial  
PMS-API-3.1 — Service Teams & Membership API Contract  

User Story  
As FE/BE developers, we want permanent team/membership APIs locked and clearly separated from contract assignment.

Related Table Schema  
`service_teams`, `service_team_members`

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Bases:**  
- `/api/v1/project/service-teams`  
- `/api/v1/project/service-teams/{teamId}/members`

### POST team — request

```json
{
  "service_id": 10,
  "name": "Digital Marketing Team",
  "status": "active"
}
```

### POST team — response `201`

```json
{
  "success": true,
  "message": "Service team created successfully",
  "data": {
    "id": 20,
    "service_id": 10,
    "service": { "id": 10, "name": "Digital Marketing" },
    "name": "Digital Marketing Team",
    "status": "active"
  }
}
```

### POST member (permanent) — request

```json
{
  "employee_id": 77,
  "division": "BD",
  "joined_at": "2026-01-15"
}
```

### POST member — response `201`

```json
{
  "success": true,
  "message": "Team member added successfully",
  "data": {
    "id": 300,
    "team_id": 20,
    "employee_id": 77,
    "employee": { "id": 77, "name": "Rahim" },
    "division": "BD",
    "status": "active",
    "joined_at": "2026-01-15",
    "left_at": null
  }
}
```

> Permanent membership has **no** `designation_id` / `is_act_as`.

---

Schema Based Business Rules  
- Membership has no designation_id / Act-As.  
- Team ≠ Contract Team.

Task Scope  
Document team + member endpoints in `11-api.md` with permanent-membership wording.

Estimate Hours  
1.50  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Contracts API Contract  
Branch Name  
docs-pms-api-contracts-contract  
View Order  
33  
Assignee  
Ashraful  
Description  

Task Serial  
PMS-API-2.3 — Contracts API Contract  

User Story  
As FE/BE developers, we want Contracts API locked for parallel UI/backend work.

Related Table Schema  
`contracts`

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/contracts`

### POST create — request

```json
{
  "contract_number": "DM-2026-001",
  "project_id": 100,
  "project_service_link_id": 501,
  "start_date": "2026-02-01",
  "end_date": "2026-04-30",
  "contract_value": 100.0,
  "currency": "USD",
  "allocated_hours": 40,
  "billing_type": "retainer",
  "payment_terms": "Net 15",
  "renewal_type": "manual",
  "status": "draft",
  "notes": null
}
```

### POST create — response `201`

```json
{
  "success": true,
  "message": "Contract created successfully",
  "data": {
    "id": 900,
    "company_id": 1,
    "contract_number": "DM-2026-001",
    "project_id": 100,
    "project_service_link_id": 501,
    "client_id": 55,
    "client": { "id": 55, "name": "ABC Corporation" },
    "service": { "id": 10, "name": "Digital Marketing" },
    "start_date": "2026-02-01",
    "end_date": "2026-04-30",
    "contract_value": "100.00",
    "currency": "USD",
    "allocated_hours": "40.00",
    "billing_type": "retainer",
    "payment_terms": "Net 15",
    "renewal_type": "manual",
    "status": "draft",
    "notes": null,
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### Status transition (optional dedicated endpoint)

`POST /api/v1/project/contracts/{id}/status`

```json
{ "status": "active", "note": "Approved by commercial" }
```

---

Schema Based Business Rules  
- Client must match project client; service link under project.

Task Scope  
Document CRUD, filters, status field, commercial fields in `11-api.md`.

Estimate Hours  
2.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Status Actions — Frontend  
Branch Name  
feature-pms-contract-status-actions-frontend  
View Order  
37  
Assignee  
Bablu  
Description  

Task Serial  
PMS-2.4-FE — Contract Status Actions Frontend  

User Story  
As a user, I want to perform allowed contract status transitions from the UI so operational status matches backend rules.

Related Table Schema  
Consumes contract status transition API from PMS-2.4-BE.

API Request / Response  
Base: `POST /api/v1/project/contracts/{id}/status`

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### POST status — request

```json
{ "status": "active", "note": "Approved by commercial" }
```

### POST status — response `200`

```json
{
  "success": true,
  "message": "Contract status updated successfully",
  "data": {
    "id": 900,
    "contract_number": "DM-2026-001",
    "status": "active",
    "from_status": "draft",
    "note": "Approved by commercial"
  }
}
```

### Illegal transition — response `409` / `422`

```json
{
  "success": false,
  "message": "Invalid status transition.",
  "errors": {
    "status": ["Cannot move from cancelled to active."]
  }
}
```

Schema Based Business Rules  
- Illegal transitions show API errors.  
- Activate disabled until required fields present (if API returns readiness).

Task Scope  
Status action buttons/menu on contract detail; confirmation; error mapping.

Estimate Hours  
3.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Commission Share API Contract  
Branch Name  
docs-pms-api-commission-share-contract  
View Order  
38  
Assignee  
Ashraful  
Description  

Task Serial  
PMS-API-2.5 — Commission Share API Contract  

User Story  
As FE/BE developers, we want Team/BD/PD share API locked with explicit calculation bases.

Related Table Schema  
`contract_commission_shares`

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/contracts/{contractId}/commission-shares`

### PUT/POST set — request

```json
{
  "team_share_percent": 30.0,
  "bd_share_percent": 40.0,
  "pd_share_percent": 60.0,
  "effective_from": "2026-02-01"
}
```

### Response `200` / `201` (server computes pools from contract_value)

```json
{
  "success": true,
  "message": "Commission share saved successfully",
  "data": {
    "id": 70,
    "contract_id": 900,
    "calculation_base": "contract_value",
    "contract_value": "100.00",
    "team_share_percent": "30.0000",
    "bd_share_percent": "40.0000",
    "pd_share_percent": "60.0000",
    "team_pool_amount": "30.00",
    "bd_pool_amount": "12.00",
    "pd_pool_amount": "18.00",
    "currency": "USD",
    "effective_from": "2026-02-01",
    "effective_to": null
  }
}
```

### BD+PD ≠ 100 — response `422`

```json
{
  "success": false,
  "message": "Validation failed.",
  "errors": {
    "bd_share_percent": ["BD share percent plus PD share percent must equal 100."]
  }
}
```

---

Schema Based Business Rules  
- BR-09/10/14; BD%+PD%=100; example 100→30→12/18.

Task Scope  
Document set/get/list share versions in `11-api.md`.

Estimate Hours  
1.50  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Contract Attachments — Frontend  
Branch Name  
feature-pms-contract-attachments-frontend  
View Order  
42  
Assignee  
Bablu  
Description  

Task Serial  
PMS-2.6-FE — Contract Attachments Frontend  

User Story  
As a user, I want to upload/list/delete contract agreement files from the UI.

Related Table Schema  
Consumes `contract_attachments` API.

API Request / Response  
Base: `/api/v1/project/contracts/{contractId}/attachments`  
Upload: `multipart/form-data` field `file`

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### POST upload — response `201`

```json
{
  "success": true,
  "message": "Attachment uploaded successfully",
  "data": {
    "id": 11,
    "contract_id": 900,
    "original_name": "sow.pdf",
    "mime": "application/pdf",
    "size": 245760,
    "file_path": "contracts/900/sow.pdf",
    "uploaded_by": 12,
    "created_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### GET list — response `200`

```json
{
  "success": true,
  "message": "Attachments fetched successfully",
  "data": [
    {
      "id": 11,
      "original_name": "sow.pdf",
      "mime": "application/pdf",
      "size": 245760,
      "created_at": "2026-09-14T10:00:00+00:00"
    }
  ]
}
```

### DELETE — response `200`

```json
{
  "success": true,
  "message": "Attachment deleted successfully",
  "data": null
}
```

Schema Based Business Rules  
- Respect type/size errors from API.  
- Permission gated.

Task Scope  
Attachments panel on contract detail.

Estimate Hours  
3.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Spike  
Title  
Assignment & Act-As API Contract  
Branch Name  
docs-pms-api-assignment-act-as-contract  
View Order  
43  
Assignee  
Munna  
Description  

Task Serial  
PMS-API-3.3 — Assignment & Act-As API Contract  

User Story  
As FE/BE developers, we want contract assignment/Act-As API locked so UI can show permanent vs contract role clearly.

Related Table Schema  
`contract_team_assignments`, `contract_members`

API Request / Response  
এই contract-এর sample (FE/BE একই shape):

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

**Base:** `/api/v1/project/contracts/{contractId}/members`

### POST assign — request

```json
{
  "employee_id": 77,
  "division": "BD",
  "designation_id": 101,
  "is_act_as": true,
  "team_id": 20
}
```

### POST assign — response `201`

```json
{
  "success": true,
  "message": "Contract member assigned successfully",
  "data": {
    "id": 800,
    "contract_id": 900,
    "employee_id": 77,
    "employee": { "id": 77, "name": "Rahim" },
    "division": "BD",
    "designation_id": 101,
    "designation": { "id": 101, "name": "Sales Person" },
    "is_act_as": true,
    "permanent_team": {
      "id": 15,
      "name": "SEO Team",
      "service": { "id": 9, "name": "SEO" }
    },
    "status": "active",
    "assigned_at": "2026-02-01T10:00:00+00:00",
    "unassigned_at": null
  }
}
```

### Business meaning of this sample

Rahim’s **permanent** team remains SEO. On DM contract he is **Act As** Sales Person. Official HR designation is unchanged.

---

Schema Based Business Rules  
- BR-06/07/08; Act-As does not change permanent membership; PM = Member of Project.

Task Scope  
Document assign/list/unassign payloads including `is_act_as` and `designation_id` in `11-api.md`.

Estimate Hours  
2.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Commission Earnings Shell — Frontend  
Branch Name  
feature-pms-commission-earnings-shell-frontend  
View Order  
50  
Assignee  
Bablu  
Description  

Task Serial  
PMS-5.1-FE — Commission Earnings Shell Frontend  

User Story  
As an admin, I want to view (and if allowed create draft/finalize) earning shell records without implying full commission engine exists.

Related Table Schema  
Consumes `commission_earning_records` API.

API Request / Response  
Base: `/api/v1/project/commission-earnings` (shell — Phase 1-এ Calculate button নেই)

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### GET list — query

`?contract_id=900&status=draft&page=1`

### GET list — response `200`

```json
{
  "success": true,
  "message": "Commission earnings fetched successfully",
  "data": [
    {
      "id": 1,
      "contract_id": 900,
      "employee_id": 77,
      "employee": { "id": 77, "name": "Rahim" },
      "division": "BD",
      "designation": { "id": 101, "name": "Sales Person" },
      "calculation_base_type": "bd_pool",
      "base_amount": "12.00",
      "percentage": "10.0000",
      "earning_amount": "1.20",
      "status": "draft",
      "period_start": null,
      "period_end": null
    }
  ],
  "meta": { "current_page": 1, "per_page": 15, "total": 1, "last_page": 1 }
}
```

Schema Based Business Rules  
- Label UI as shell/records only.  
- No “Run Commission Engine” action.

Task Scope  
List/detail (+ draft create if API supports); permission gated.

Estimate Hours  
4.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project-wise Team Report API  
Branch Name  
feature-pms-project-wise-team-report-backend  
View Order  
56  
Assignee  
Munna  
Description  

Task Serial  
PMS-5.7-BE — Project-wise Team Report Backend  

User Story  
As a manager, I want a project-wise team report so SRS reporting “Project-wise Team” is covered.

Related Table Schema  
Reads projects, contracts, contract_members, service teams as needed.

Schema Based Business Rules  
- Company scoped.  
- Distinguish permanent vs contract where shown.

Task Scope  
Report endpoint grouped by project; tests.

Estimate Hours  
3.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
Project-wise Team Report — Frontend  
Branch Name  
feature-pms-project-wise-team-report-frontend  
View Order  
57  
Assignee  
Bablu  
Description  

Task Serial  
PMS-5.7-FE — Project-wise Team Report Frontend  

User Story  
As a manager, I want a project-wise team report screen.

Related Table Schema  
Consumes PMS-5.7-BE.

API Request / Response  
Base: `GET /api/v1/project/reports/project-teams`

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### GET — query

`?project_id=100`

### GET — response `200`

```json
{
  "success": true,
  "message": "Project team report fetched successfully",
  "data": {
    "project_id": 100,
    "project_name": "ABC Digital Growth",
    "services": [
      {
        "service_id": 10,
        "service_name": "Digital Marketing",
        "contracts": [
          {
            "contract_number": "DM-2026-001",
            "members": [
              { "employee_name": "Rahim", "division": "BD", "role": "Sales Person", "is_act_as": true }
            ]
          }
        ]
      }
    ]
  }
}
```

Schema Based Business Rules  
- Permission: reports-view.

Task Scope  
Report page with filters.

Estimate Hours  
2.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
BD/PD Commission Earnings Report API (Shell)  
Branch Name  
feature-pms-bd-pd-commission-earnings-report-backend  
View Order  
62  
Assignee  
Ashraful  
Description  

Task Serial  
PMS-5.8-BE — BD/PD Commission Earnings Report Backend  

User Story  
As a manager, I want BD/PD commission earning reports from **stored earning shell records** so SRS reporting items are covered without implementing the full calculation engine.

Related Table Schema  
Reads `commission_earning_records` (shell). Does **not** calculate new commissions.

Schema Based Business Rules  
- Phase 1: report = read/aggregate existing earning rows by division BD/PD.  
- Full auto-calculation remains Phase 2 (`PMS-COMM-EPIC`).

Task Scope  
Report endpoints for BD commission and PD commission views; filters; tests with seeded earnings.

Estimate Hours  
4.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Feature  
Title  
BD/PD Commission Earnings Report — Frontend  
Branch Name  
feature-pms-bd-pd-commission-earnings-report-frontend  
View Order  
63  
Assignee  
Bablu  
Description  

Task Serial  
PMS-5.8-FE — BD/PD Commission Earnings Report Frontend  

User Story  
As a manager, I want BD/PD commission earning report screens fed by shell records.

Related Table Schema  
Consumes PMS-5.8-BE.

API Request / Response  
Base: `GET /api/v1/project/reports/bd-pd-commission-earnings` (shell)

Headers (সব call-এ):
`Authorization: Bearer <token>`
`X-Company-Id: <company_id>`
`Accept: application/json`
`Content-Type: application/json` (POST/PUT)

Envelope: `{ success, message, data }` · list-এ `meta`/`links` থাকতে পারে · error-এ `errors`।

### GET — query

`?division=BD&from=2026-01-01&to=2026-03-31`

### GET — response `200`

```json
{
  "success": true,
  "message": "BD/PD commission earnings report fetched successfully",
  "data": [
    {
      "employee_id": 77,
      "employee_name": "Rahim",
      "division": "BD",
      "earning_amount_total": "1.20",
      "currency": "USD",
      "records_count": 1,
      "status_breakdown": { "draft": 1, "finalized": 0 }
    }
  ]
}
```

Schema Based Business Rules  
- UI clarifies these are recorded earnings, not live engine output.

Task Scope  
Two tabs or pages: BD / PD; filters; empty states.

Estimate Hours  
3.00  
Status  
-  
QA Status  
-  
QA Comment  
-  

---

Project  
ERPFlow  
Module  
Project Management System  
Type  
Docs  
Title  
Phase 1 Module Documentation  
Branch Name  
docs-pms-phase1-module-documentation  
View Order  
64  
Assignee  
Sharif  
Description  

Task Serial  
PMS-DOC-1 — Phase 1 Module Documentation  

User Story  
As a developer/QA, I want Phase 1 PMS module docs (how to run, permissions, main flows) so onboarding and SRS traceability are clear.

Related Table Schema  
N/A

Schema Based Business Rules  
- Document Act-As vs permanent membership.  
- Document Phase 1 vs Phase 2 commission boundary.

Task Scope  
Short module README under docs/projects or Modules/Project; link WBS + task cards; no deploy production runbook required unless known.

Estimate Hours  
3.00  
Status  
-  
QA Status  
-  
QA Comment  
-  


## Lane ownership quick reference

| Lane | Owner | Owns tables |
| --- | --- | --- |
| **A** | **Ashraful** | `projects`, `project_service_links`, `contracts`, `contract_status_histories`, `contract_commission_shares`, `contract_attachments`, `commission_earning_records` |
| **B** | **Munna** | `service_teams`, `service_team_members`, `contract_team_assignments`, `contract_members` (+ history) |
| **C** | **Sharif** | `project_types`, `pms_services`, `team_divisions`, `pms_contract_role_maps` (optional), `commission_rules` |
| **D** | **Bablu** | All FE cards, permissions seed (PMS-0.2), nav shell |

**Rule:** একই টেবিল দুই জনে ছুঁও না। FE শুধু Bablu — Ashraful/Munna/Sharif BE merge করলে Bablu unlock করে।

---

## Suggested Week-1 board

1. **Ashraful** আগে **PMS-0.1**, তারপর **PMS-SCHEMA-1** শেষ করে — Munna/Sharif নিজের table-এর column দেখে OK দেয়।
2. Same day:
   - **Sharif:** `1.1-BE` + `1.2-BE`
   - **Ashraful:** scaffold `2.1-BE` (type FK nullable until Sharif merges)
   - **Munna:** prepare `3.1-BE` scaffold; hard-start after `1.2-BE`
   - **Bablu:** `0.2` + `0.1-FE`
3. As each BE merges, **Bablu** picks matching FE — spine (Ashraful) never waits on FE.
