End-to-end procurement project tracking from initiation through closure -- phases, milestones, risk management, team allocation, budget integration, and formal closure workflows.
The Project Management module in ProKure provides a structured framework for tracking procurement projects from initiation through closure. It integrates with CRM leads, budget planning, and vendor management to deliver full lifecycle visibility across all procurement activities.
Master project table -- core project information, status, budget, and CRM linkage
Sequential project phases with gate review controls and completion tracking
Key milestones with type classification and overdue detection
Risk register with probability-impact scoring and mitigation tracking
Team assignment with role-based allocation and lifecycle management
Formal closure records with checklist, lessons learned, and approval workflow
Projects follow a five-stage lifecycle. Each stage maps to specific table interactions and status transitions.
┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐
│ CREATION │---->│ PLANNING │---->│ EXECUTION │---->│ MONITORING│---->│ CLOSURE │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘
v v v v v
projects phases milestones risks closures
(INSERT) team_members risks, work budget chk (INSERT)
PLANNING PLANNING ACTIVE ACTIVE/ON_HOLD COMPLETED/CANCELLED
| Stage | Status | Tables Affected | Key Actions |
|---|---|---|---|
| Creation | PLANNING | proj.projects | Record created, code auto-generated, manager assigned |
| Planning | PLANNING | project_phases, project_team_members | Phases defined, team allocated, milestones planned |
| Execution | ACTIVE | project_milestones, project_risks | Work begins, milestones tracked, risks logged |
| Monitoring | ACTIVE / ON_HOLD | project_risks, project_milestones | Progress reviews, risk reassessment, budget checks |
| Closure | COMPLETED / CANCELLED | project_closures | Checklist completion, lessons learned, approval |
Projects are divided into sequential phases. Each phase must pass a gate review before the next phase can begin.
PLANNED ----> IN_PROGRESS ----> GATE_REVIEW ----> COMPLETED
|
| (Rejected)
v
IN_PROGRESS (Rework required)
-- Phase status and gate review readiness SELECT pp.phase_name, pp.phase_number, pp.completion_pct, pp.gate_review_status, CASE WHEN pp.completion_pct = 100 AND pp.gate_review_status = 'APPROVED' THEN 'Ready for next phase' WHEN pp.completion_pct = 100 THEN 'Awaiting gate review' ELSE 'In progress' END AS phase_readiness FROM proj.project_phases pp WHERE pp.project_id = @project_id ORDER BY pp.phase_number;
UPCOMING ----(date passes)----> OVERDUE
|
| (actual_date set)
v
COMPLETED Note: CANCELLED can be set from any state
-- Overdue milestone detection (scheduled job) UPDATE proj.project_milestones SET status = 'OVERDUE' WHERE status = 'UPCOMING' AND planned_date < NOW() AND actual_date IS NULL; -- Notify project managers of overdue milestones SELECT p.name, pm.milestone_name, pm.milestone_type, pm.planned_date, NOW() - pm.planned_date AS days_overdue, u.email AS manager_email FROM proj.project_milestones pm JOIN proj.projects p ON p.id = pm.project_id JOIN users u ON u.id = p.manager_id WHERE pm.status = 'OVERDUE';
The risk register uses a probability-impact matrix to score and prioritize project risks. Each risk is assigned an owner, response strategy, and mitigation plan.
-- Risk score = Probability x Impact (range: 1 to 25) risk_score = probability * impact -- 1-4 = Low (green) | 5-9 = Medium (yellow) | 10-16 = High (orange) | 17-25 = Critical (red)
5x5 Risk Matrix Impact: 1(VLow) 2(Low) 3(Med) 4(High) 5(VHigh) Probability: 5 (Very High) 5 10 15 20 25 4 (High) 4 8 12 16 20 3 (Medium) 3 6 9 12 15 2 (Low) 2 4 6 8 10 1 (Very Low) 1 2 3 4 5
| Strategy | Description | When to Apply |
|---|---|---|
| AVOID | Eliminate risk by changing project scope or approach | Critical risks with viable alternatives |
| MITIGATE | Reduce probability or impact through preventive action | High risks where full avoidance is not feasible |
| TRANSFER | Shift risk ownership to a third party (insurance, vendor) | Financial or contractual risks |
| ACCEPT | Acknowledge risk without active mitigation | Low-scoring risks or unavoidable conditions |
OPEN ---(risk event occurs)---> MATERIALIZED ---(mitigation applied)---> MITIGATED ---> CLOSED
| ^
+---(resolved directly)---------------------------------------------------------------------+
-- Active high-priority risks requiring review SELECT r.risk_title, r.risk_category, r.probability, r.impact, r.risk_score, r.response_strategy, u.full_name AS risk_owner, r.review_date FROM proj.project_risks r JOIN users u ON u.id = r.risk_owner WHERE r.project_id = @project_id AND r.status = 'OPEN' AND r.risk_score >= 10 ORDER BY r.risk_score DESC;
Project budgets are linked to planning.budgets for commitment tracking and utilization alerting.
-- Budget utilization check (BR-PRJ-003: Alert at 80%) SELECT p.code, p.name, p.budget_amount, b.committed_amount, b.spent_amount, ROUND((b.spent_amount / NULLIF(p.budget_amount, 0)) * 100, 2) AS utilization_pct, CASE WHEN b.spent_amount >= p.budget_amount * 0.80 THEN 'ALERT: 80% threshold breached' WHEN b.spent_amount >= p.budget_amount * 0.60 THEN 'WARNING: Approaching threshold' ELSE 'Normal' END AS budget_status FROM proj.projects p JOIN planning.budgets b ON b.project_id = p.id WHERE p.status = 'ACTIVE' AND p.is_deleted = false;
The crm_lead_id column in proj.projects enables end-to-end traceability from CRM lead conversion to project delivery.
CRM Module Project Module ┌─────────────────┐ Lead Conversion ┌─────────────────────┐ │ crm.leads │------(Screen 124)----->│ proj.projects │ │ lead_id │ │ crm_lead_id = FK │ │ customer_name │ │ Inherits: │ │ deal_value │ │ - customer_id │ │ status = WON │ │ - budget_amount │ └─────────────────┘ └─────────────────────┘
-- Trace project back to originating CRM lead SELECT p.code, p.name, p.status, l.lead_code, l.customer_name, l.deal_value AS original_deal_value, p.budget_amount AS project_budget FROM proj.projects p JOIN crm.leads l ON l.id = p.crm_lead_id WHERE p.crm_lead_id IS NOT NULL;
| Role | Permissions | Typical Allocation |
|---|---|---|
| MANAGER | Full project control, team management, closure initiation | 50-100% |
| LEAD | Phase management, milestone updates, risk logging | 40-80% |
| MEMBER | Task execution, milestone completion, time logging | 20-60% |
| OBSERVER | Read-only access to project dashboards and reports | 5-10% |
-- Detect over-allocated users (total allocation > 100% across active projects) SELECT u.id, u.full_name, SUM(tm.allocation_pct) AS total_allocation, COUNT(tm.project_id) AS project_count, CASE WHEN SUM(tm.allocation_pct) > 100 THEN 'OVER-ALLOCATED' ELSE 'OK' END AS status FROM proj.project_team_members tm JOIN users u ON u.id = tm.user_id JOIN proj.projects p ON p.id = tm.project_id WHERE tm.is_active = true AND p.status IN ('PLANNING', 'ACTIVE') GROUP BY u.id, u.full_name HAVING SUM(tm.allocation_pct) > 100 ORDER BY total_allocation DESC;
DRAFT ----(submit)----> PENDING_APPROVAL ----(approve)----> APPROVED
|
| (reject)
v
REJECTED ----(revise)----> DRAFT
Closure Types: COMPLETED | CANCELLED | SUSPENDED
-- Example checklist_items JSONB content { "items": [ { "key": "deliverables_accepted", "label": "All deliverables accepted by customer", "checked": true }, { "key": "invoices_settled", "label": "All invoices settled", "checked": true }, { "key": "contracts_closed", "label": "Vendor contracts formally closed", "checked": false }, { "key": "docs_archived", "label": "Project documents archived", "checked": true }, { "key": "team_released", "label": "Team members released from allocation", "checked": false }, { "key": "lessons_documented", "label": "Lessons learned documented", "checked": true } ] } -- Pending deliverables check before closure approval (BR-PRJ-004) SELECT pm.milestone_name, pm.milestone_type, pm.status FROM proj.project_milestones pm WHERE pm.project_id = @project_id AND pm.status IN ('UPCOMING', 'OVERDUE'); -- If rows returned AND closure_type != 'CANCELLED', block closure
| Rule ID | Rule Description | Enforcement | Tables |
|---|---|---|---|
| BR-PRJ-001 | Project code is auto-generated and immutable after creation | Database trigger prevents UPDATE on code column | proj.projects |
| BR-PRJ-002 | Only project manager or admin can add/remove team members | Application-level RBAC check on INSERT/DELETE | proj.project_team_members |
| BR-PRJ-003 | Budget utilization alert triggered at 80% of budget_amount | Scheduled job + notification service | proj.projects, planning.budgets |
| BR-PRJ-004 | Cannot close project with pending milestones unless closure_type = CANCELLED | Application-level validation on closure approval | proj.project_closures, proj.project_milestones |
-- BR-PRJ-001: Trigger to prevent project code modification CREATE OR REPLACE FUNCTION proj.prevent_code_update() RETURNS TRIGGER AS $$ BEGIN IF OLD.code IS DISTINCT FROM NEW.code THEN RAISE EXCEPTION 'Project code is immutable and cannot be modified'; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trg_prevent_project_code_update BEFORE UPDATE ON proj.projects FOR EACH ROW EXECUTE FUNCTION proj.prevent_code_update(); -- BR-PRJ-004: Closure validation function CREATE OR REPLACE FUNCTION proj.validate_closure( p_project_id INT, p_closure_type VARCHAR ) RETURNS BOOLEAN AS $$ DECLARE v_pending_count INT; BEGIN IF p_closure_type = 'CANCELLED' THEN RETURN true; END IF; SELECT COUNT(*) INTO v_pending_count FROM proj.project_milestones WHERE project_id = p_project_id AND status IN ('UPCOMING', 'OVERDUE'); RETURN v_pending_count = 0; END; $$ LANGUAGE plpgsql;
ProKure Database Documentation - Project Management Logic v1.0
Part of the ProKure Procurement Management System