diff --git a/docs/implementation/task-j-crm-dashboard-kpi.md b/docs/implementation/task-j-crm-dashboard-kpi.md new file mode 100644 index 0000000..decbde4 --- /dev/null +++ b/docs/implementation/task-j-crm-dashboard-kpi.md @@ -0,0 +1,74 @@ +# Task J: CRM Dashboard KPI and Sales Analytics + +## Files added + +- `src/features/crm/dashboard/api/types.ts` +- `src/features/crm/dashboard/api/service.ts` +- `src/features/crm/dashboard/api/queries.ts` +- `src/features/crm/dashboard/server/service.ts` +- `src/features/crm/dashboard/components/crm-dashboard.tsx` +- `src/features/crm/dashboard/components/dashboard-filters.tsx` +- `src/features/crm/dashboard/components/dashboard-summary-cards.tsx` +- `src/features/crm/dashboard/components/dashboard-funnel.tsx` +- `src/features/crm/dashboard/components/dashboard-revenue-cards.tsx` +- `src/features/crm/dashboard/components/dashboard-sales-ranking.tsx` +- `src/features/crm/dashboard/components/dashboard-followups.tsx` +- `src/features/crm/dashboard/components/dashboard-approval-metrics.tsx` +- `src/features/crm/dashboard/components/dashboard-hot-projects.tsx` +- `src/app/api/crm/dashboard/route.ts` +- `src/app/api/crm/dashboard/export/route.ts` + +## Files modified + +- `src/app/dashboard/crm/page.tsx` +- `src/config/nav-config.ts` +- `src/lib/auth/rbac.ts` +- `src/lib/searchparams.ts` +- `docs/implementation/technical-debt.md` + +## KPI widgets added + +- Replaced the CRM placeholder route with a production dashboard at `/dashboard/crm`. +- Added summary cards for lead, opportunity, quotation, and revenue metrics. +- Added a funnel widget for lead -> opportunity -> quotation -> pending approval -> approved -> closed won. +- Added a hot-project widget based on real enquiry data. + +## Revenue analytics added + +- Added top end-customer, billing-customer, contractor, and consultant revenue tables. +- Reused the Task D.2.1 reporting helpers so revenue attribution follows the frozen governance rules. +- Added export support for revenue analytics through the dashboard export route. + +## Sales ranking added + +- Added a production sales ranking table using enquiry assignment and quotation salesman ownership rules. +- Added CSV export for sales ranking. + +## Approval and follow-up analytics added + +- Added approval KPI cards and a `My Pending Approvals` table. +- Added follow-up KPI cards and an `Upcoming Follow Ups` table from enquiry and quotation follow-up sources. + +## Export and permissions added + +- Added `crm.dashboard.read`. +- Added `crm.dashboard.export`. +- Added audit logging for `crm_dashboard_export` with `export_csv` and `export_excel`. +- Added sidebar navigation for the CRM dashboard. + +## Remaining risks + +- `closed_won` is not yet a first-class enquiry lifecycle field, so the dashboard currently uses quotation status `accepted` as the practical won-stage proxy. +- follow-up completion is inferred from `outcome` presence because the follow-up model still has no explicit completion flag. +- the global `Project Party Role` filter currently influences revenue analytics and exports, but the rest of the dashboard still depends mainly on enquiry and quotation core filters. +- sales users currently read organization-wide dashboard data; own-scope filtering is still future work. + +## Task K readiness + +- the CRM dashboard now uses real production data +- KPI widgets are live +- revenue analytics is reusable +- sales ranking is exportable +- approval and follow-up analytics exist +- export and audit hooks are in place +- the app is ready for Task K report-center expansion diff --git a/docs/implementation/task-j1-crm-admin-configuration-center.md b/docs/implementation/task-j1-crm-admin-configuration-center.md new file mode 100644 index 0000000..7680c39 --- /dev/null +++ b/docs/implementation/task-j1-crm-admin-configuration-center.md @@ -0,0 +1,85 @@ +# Task J.1: CRM Admin Configuration Center + +## Files Added + +- `src/app/api/crm/settings/**` +- `src/app/dashboard/crm/settings/approval-workflows/page.tsx` +- `src/features/foundation/approval/components/approval-workflow-settings.tsx` +- `src/features/foundation/document-sequence/client-service.ts` +- `src/features/foundation/document-sequence/components/document-sequence-settings.tsx` +- `src/features/foundation/document-sequence/mutations.ts` +- `src/features/foundation/document-sequence/queries.ts` +- `src/features/foundation/document-template/mutations.ts` +- `docs/implementation/task-j1-crm-admin-configuration-center.md` + +## Files Modified + +- `src/config/nav-config.ts` +- `src/lib/auth/rbac.ts` +- `src/app/dashboard/crm/settings/document-sequences/page.tsx` +- `src/features/foundation/approval/{mutations,queries,server/service,service,types}.ts` +- `src/features/foundation/document-sequence/{service,types}.ts` +- `src/features/foundation/document-template/{components/template-settings,mutations,server/service,service,types}.ts` + +## What Was Added + +- CRM Settings menu now includes `Approval Workflows` and uses CRM-specific permission checks for `Document Sequences`. +- `/dashboard/crm/settings/templates` now supports: + - create/edit template metadata + - create/edit template versions with JSON schema textarea + - create/edit/delete template mappings + - table-column mapping input for `table` data type +- `/dashboard/crm/settings/approval-workflows` now supports: + - create/edit/delete workflows + - manage sequential workflow steps + - role-based step definitions using CRM business roles +- `/dashboard/crm/settings/document-sequences` now supports: + - create/edit/delete sequences + - reset sequence counters + - preview next code from stored sequence state + +## API Routes Added + +- `/api/crm/settings/document-templates/**` +- `/api/crm/settings/approval-workflows/**` +- `/api/crm/settings/document-sequences/**` + +## Permissions Added + +- `crm.approval.workflow.read` +- `crm.approval.workflow.create` +- `crm.approval.workflow.update` +- `crm.approval.workflow.delete` +- `crm.document_sequence.read` +- `crm.document_sequence.create` +- `crm.document_sequence.update` +- `crm.document_sequence.reset` + +## Audit Coverage + +- `crm_document_template_version` +- `crm_document_template_mapping` +- `crm_approval_workflow` +- `crm_approval_step` +- `crm_document_sequence` + +## Verification + +- `npx tsc --noEmit` passed on June 17, 2026. +- `npm run lint` still fails because of pre-existing repo lint errors outside Task J.1 scope, including: + - `src/components/ui/input-group.tsx` + - `src/features/chat/components/message-composer.tsx` + - `src/components/forms/demo-form.tsx` + +## Remaining Risks + +- Template settings UI is functional but not yet a polished table-first admin experience. +- Document template version activation currently supports state updates, but the page focuses on version edit/create over dedicated activate/deactivate action buttons. +- Sequence reset UI currently resets to `0`; custom reset value can be added later if the product needs it. +- Approval step management currently replaces the full ordered step list in one save flow rather than exposing per-row move controls. + +## Task K Readiness + +- CRM settings foundations are now exposed through organization-scoped admin routes. +- Query invalidation is wired for template, workflow, and sequence mutations. +- The configuration center is ready for KPI/report consumers to reference the same settings data in later tasks. diff --git a/docs/implementation/technical-debt.md b/docs/implementation/technical-debt.md index 73d9145..19efa5b 100644 --- a/docs/implementation/technical-debt.md +++ b/docs/implementation/technical-debt.md @@ -297,3 +297,51 @@ Future: - decide whether approved quotation snapshots or another immutable reporting snapshot should become the historical source of truth - define how reporting should behave if project parties change after quotation approval or after a won/lost outcome - add backfill or reconciliation tooling if historical party drift becomes a business issue + +## After Task J + +### Closed-won lifecycle fidelity + +Task J ships a live CRM dashboard, but the current schema still lacks a first-class enquiry `closed_won` lifecycle field and dedicated close timestamps. + +Current: + +- dashboard won-stage metrics currently use quotation status `accepted` as the practical proxy for `closed_won` + +Future: + +- add explicit enquiry lifecycle support for `closed_won` +- add `closedWonAt` to support precise won-date analytics +- remove dashboard proxy logic once the lifecycle model is formalized + +### Follow-up completion semantics + +Task J adds follow-up analytics, but the follow-up model still has no explicit completion flag. + +Current: + +- dashboard `Completed` follow-up metrics infer completion from `outcome` presence + +Future: + +- add an explicit completion state or activity outcome model for follow-ups +- separate scheduled, completed, cancelled, and skipped follow-up reporting cleanly + +### Dashboard own-scope policy + +Task J introduces `crm.dashboard.read`, but sales users still view organization-wide KPI data for now. + +Future: + +- add own-scope dashboard filtering for sales roles +- define whether mixed-role users see own, team, or organization scope by default +- keep exports aligned with the same scope policy once enforced + +### Global project-party filter coverage + +Task J adds a global `Project Party Role` filter in the dashboard UI, but the strongest enforcement today is in revenue analytics and export sections. + +Future: + +- decide which non-revenue widgets should fully honor project-party role filtering +- add a unified filtered reporting projection if cross-widget party-role filtering becomes a hard requirement diff --git a/plans/task-j.1.md b/plans/task-j.1.md new file mode 100644 index 0000000..69f5d0c --- /dev/null +++ b/plans/task-j.1.md @@ -0,0 +1,419 @@ +# Task J.1: CRM Admin Configuration Center + +## Goal + +สร้างหน้า Admin Configuration สำหรับจัดการ configuration สำคัญของ CRM ที่ปัจจุบันมี foundation แล้ว แต่ยังจัดการผ่าน UI ไม่สมบูรณ์ + +ครอบคลุม: + +1. Document Templates +2. Approval Workflows +3. Document Sequences + +ยังไม่ทำ: + +* Template drag/drop designer เต็มรูปแบบ +* PDF visual designer +* Advanced conditional approval +* Report builder + +--- + +# Must Read + +```txt +Layout.md +AGENTS.md +.agents/skills/kiranism-shadcn-dashboard + +src/features/foundation/document-template/** +src/features/foundation/approval/** +src/features/foundation/document-sequence/** +src/features/foundation/master-options/** +src/features/foundation/storage/** +src/db/schema.ts + +docs/adr/0009-approved-document-storage-lifecycle.md +docs/adr/0010-revenue-attribution-governance.md +docs/implementation/technical-debt.md +``` + +--- + +# Scope 1: Admin Settings Navigation + +Under: + +```txt +/dashboard/crm/settings +``` + +Add/complete pages: + +```txt +/dashboard/crm/settings/templates +/dashboard/crm/settings/approval-workflows +/dashboard/crm/settings/document-sequences +``` + +Use existing: + +```txt +PageContainer +DataTable +Sheet/Dialog +Bento/Settings cards +``` + +No new design system. + +--- + +# Scope 2: Document Template Management + +Current state: + +* template schema exists +* template versions exist +* template mappings exist +* default pdfme template seed exists +* template settings page is mostly listing/read-focused + +Need UI: + +## Template List + +Show: + +```txt +Template Name +Document Type +Product Type +File Type +Default +Active +Latest Version +Mapping Count +Actions +``` + +Actions: + +```txt +Create Template +Edit Template Metadata +Activate/Deactivate +Set Default +View Versions +``` + +## Template Version Management + +For each template: + +```txt +Version +Active +File Path +Schema JSON +Preview Image URL +Created By +Created At +``` + +Actions: + +```txt +Create Version +View Version +Activate Version +Deactivate Version +``` + +## Template Mapping Management + +Add basic CRUD UI for mappings: + +```txt +placeholderKey +sourcePath +dataType +defaultValue +formatMask +sortOrder +``` + +For table mapping: + +```txt +columnName +sourceField +columnLetter +sortOrder +formatMask +``` + +Rules: + +* role: admin only +* audit template mutations +* no drag/drop designer yet +* JSON textarea is acceptable for schemaJson in this task +* validate schemaJson is valid JSON + +Permissions: + +```txt +crm.document_template.read +crm.document_template.create +crm.document_template.update +crm.document_template.delete +``` + +--- + +# Scope 3: Approval Workflow Management + +Current state: + +* approval schema exists +* seeded quotation standard workflow exists +* approval engine works +* no workflow management UI + +Need UI: + +## Workflow List + +Show: + +```txt +Workflow Code +Workflow Name +Entity Type +Active +Step Count +Actions +``` + +Actions: + +```txt +Create Workflow +Edit Workflow +Activate/Deactivate +Manage Steps +``` + +## Workflow Step Management + +For each workflow: + +```txt +Step Number +Role Code +Role Name +Required +``` + +Actions: + +```txt +Add Step +Edit Step +Remove Step +Reorder Steps +``` + +Rules: + +* sequential approval only +* no parallel approval +* no conditional approval +* no delegation +* no escalation +* roleCode must match CRM businessRole or permission strategy +* do not break existing quotation approval flow + +Permissions: + +```txt +crm.approval.workflow.read +crm.approval.workflow.create +crm.approval.workflow.update +crm.approval.workflow.delete +``` + +Audit: + +```txt +crm_approval_workflow +crm_approval_step +``` + +--- + +# Scope 4: Document Sequence Management + +Current state: + +* document sequence service exists +* seed exists +* generate/preview works +* admin UI incomplete + +Need UI: + +## Sequence List + +Show: + +```txt +Document Type +Prefix +Period +Branch +Current Number +Padding Length +Next Preview +Updated At +Actions +``` + +Actions: + +```txt +Create Sequence +Edit Sequence +Preview Next Code +Reset Current Number +Deactivate/Delete if supported +``` + +Rules: + +* reset requires confirmation +* changing prefix should not rewrite old document codes +* preview must not increment +* generation remains server-only +* organization scoped +* branch optional or from crm_branch options + +Permissions: + +```txt +crm.document_sequence.read +crm.document_sequence.create +crm.document_sequence.update +crm.document_sequence.reset +``` + +Audit: + +```txt +crm_document_sequence +``` + +--- + +# Scope 5: Route Handlers + +Add or complete APIs: + +```txt +/api/crm/settings/document-templates/** +/api/crm/settings/approval-workflows/** +/api/crm/settings/document-sequences/** +``` + +หรือถ้ามี route เดิมแล้ว ให้ reuse และเติม missing mutation + +All APIs must: + +```txt +requireOrganizationAccess +requirePermission +filter by organizationId +audit mutations +return user-safe errors +``` + +--- + +# Scope 6: Mutation Freshness Rule + +All CRUD pages must follow project hotfix rule: + +```txt +mutation success +↓ +invalidate list query +↓ +invalidate detail query if relevant +↓ +refresh table/detail immediately +``` + +No stale config table after save. + +--- + +# Scope 7: Safety Constraints + +Do NOT implement: + +```txt +visual template designer +drag/drop pdf designer +advanced approval engine +parallel approval +conditional workflow +notification +report builder +dashboard changes +``` + +--- + +# Output + +1. Files Added +2. Files Modified +3. Template Config UI Added +4. Approval Workflow UI Added +5. Document Sequence UI Added +6. API Routes Added +7. Permissions Added +8. Audit Integration +9. Remaining Risks +10. Task K Readiness + +--- + +# Definition of Done + +✔ Admin can manage template metadata + +✔ Admin can manage template versions + +✔ Admin can manage template mappings + +✔ Admin can manage approval workflows + +✔ Admin can manage approval steps + +✔ Admin can manage document sequences + +✔ Preview next document code works + +✔ All mutations refresh table data + +✔ All settings routes are organization scoped + +✔ Permission guard works + +✔ Audit works + +✔ No drag/drop designer + +✔ No advanced approval logic diff --git a/plans/task-j.md b/plans/task-j.md index e69de29..14c3d22 100644 --- a/plans/task-j.md +++ b/plans/task-j.md @@ -0,0 +1,540 @@ +# Task J: CRM Dashboard KPI & Sales Analytics + +## Background + +Task J.0 KPI Definition Freeze completed. + +Task D.2.1 Revenue Attribution and Party Governance completed. + +Dashboard implementation MUST follow: + +```txt +Lead Definition +Opportunity Definition +Revenue Attribution Rules +Project Party Reporting Rules +``` + +No dashboard logic may redefine KPI formulas. + +--- + +# Must Read + +```txt +Layout.md + +.agents/skills/kiranism-shadcn-dashboard + +docs/adr/0010-revenue-attribution-governance.md + +docs/implementation/technical-debt.md + +src/features/crm/reporting/server/** +src/features/crm/customers/** +src/features/crm/enquiries/** +src/features/crm/quotations/** +src/features/foundation/approval/** +src/features/foundation/document-artifact/** +src/db/schema.ts +``` + +--- + +# Goal + +Replace CRM placeholder dashboard with a production KPI dashboard powered by real CRM data. + +Route: + +```txt +/ dashboard / crm +``` + +No mock data allowed. + +--- + +# Scope J1: Dashboard Foundation + +Create: + +```txt +src/features/crm/dashboard/** +``` + +Recommended structure: + +```txt +api/ + types.ts + service.ts + queries.ts + +server/ + service.ts + +components/ + dashboard-summary-cards.tsx + dashboard-funnel.tsx + dashboard-sales-ranking.tsx + dashboard-followups.tsx + dashboard-approval-metrics.tsx + dashboard-revenue-cards.tsx + dashboard-hot-projects.tsx +``` + +Use: + +```txt +Server Components First +React Query +PageContainer +Bento Grid Layout +``` + +Follow: + +```txt +Layout.md +kiranism-shadcn-dashboard +``` + +--- + +# Scope J2: Executive Summary Cards + +Cards: + +## Lead + +```txt +Lead Count +New Leads +Unassigned Leads +Lead Aging Average +``` + +Formula: + +```txt +pipelineStage = lead +``` + +--- + +## Opportunity + +```txt +Opportunity Count +Open Opportunities +Hot Opportunities +Opportunity Value +``` + +Formula: + +```txt +pipelineStage = opportunity +``` + +Source: + +```txt +crm_enquiries.estimatedValue +``` + +--- + +## Quotation + +```txt +Draft Quotations +Pending Approval +Approved Quotations +Sent Quotations +``` + +--- + +## Revenue + +```txt +Quotation Value +Won Value +Lost Value +``` + +Use frozen revenue rules. + +--- + +# Scope J3: Sales Pipeline Funnel + +Create funnel widget: + +```txt +Lead +↓ +Opportunity +↓ +Quotation +↓ +Pending Approval +↓ +Approved +↓ +Closed Won +``` + +Display: + +```txt +Count +Value +Conversion % +``` + +Formulas must follow Task J.0. + +--- + +# Scope J4: Revenue Analytics + +Use: + +```txt +src/features/crm/reporting/server/** +``` + +Cards: + +```txt +Top End Customers +Top Billing Customers +Top Contractors +Top Consultants +``` + +Metrics: + +```txt +Revenue +Quotation Count +Won Revenue +``` + +Revenue Attribution: + +```txt +End Customer +Fallback Billing Customer +``` + +must follow ADR. + +--- + +# Scope J5: Sales Ranking + +Create table: + +Columns: + +```txt +Sales Person +Lead Count +Opportunity Count +Quotation Count +Approved Quotations +Won Revenue +Conversion Rate +``` + +Ownership: + +```txt +Lead / Opportunity +→ assignedToUserId + +Quotation +→ salesmanId +``` + +Use KPI Freeze definitions. + +--- + +# Scope J6: Follow-up Dashboard + +Source: + +```txt +crm_enquiry_followups +crm_quotation_followups +``` + +Cards: + +```txt +Due Today +Due This Week +Overdue +Completed +``` + +Table: + +```txt +Upcoming Follow Ups +``` + +Display: + +```txt +Date +Customer +Opportunity +Assigned Sales +``` + +--- + +# Scope J7: Approval Analytics + +Source: + +```txt +approval module +``` + +Cards: + +```txt +Pending Approvals +Approved Today +Rejected Today +Returned Today +``` + +Metrics: + +```txt +Average Approval Time +``` + +Table: + +```txt +My Pending Approvals +``` + +--- + +# Scope J8: Hot Projects + +Source: + +```txt +crm_enquiries.isHotProject +crm_quotations.isHotProject +``` + +Widget: + +```txt +Top Hot Opportunities +``` + +Display: + +```txt +Project +Customer +Value +Assigned Sales +Probability +``` + +--- + +# Scope J9: Global Filters + +Add filters: + +```txt +Date Range +Branch +Sales Person +Project Party Role +Product Type +``` + +Use: + +```txt +nuqs +``` + +Rules: + +```txt +organization scoped +server query aware +``` + +--- + +# Scope J10: Permissions + +Add: + +```txt +crm.dashboard.read +crm.dashboard.export +``` + +Rules: + +```txt +super_admin +organization_admin +sales_manager +``` + +full access + +sales: + +```txt +own scope only (future-ready) +``` + +For now: + +```txt +organization scope allowed +``` + +Document as technical debt. + +--- + +# Scope J11: Export + +Support: + +```txt +CSV +Excel +``` + +Exports: + +```txt +Sales Ranking +Revenue Analytics +Pipeline Funnel +``` + +Use current export patterns. + +Do NOT generate PDF dashboards. + +--- + +# Scope J12: Performance Rules + +Required: + +```txt +Aggregate queries +Server-side calculations +No N+1 queries +Pagination for tables +Reusable KPI service layer +``` + +Dashboard should remain fast with: + +```txt +100k+ +quotations +enquiries +customers +``` + +--- + +# Scope J13: Audit + +Audit: + +```txt +crm_dashboard_export +``` + +Actions: + +```txt +export_csv +export_excel +``` + +Reading dashboard does not require audit. + +--- + +# Explicit Non-Scope + +Do NOT implement: + +```txt +AI Forecasting +Predictive Sales +Power BI +Data Warehouse +Notification Center +Report Builder +``` + +--- + +# Output + +1. Files Added +2. Files Modified +3. KPI Widgets Added +4. Revenue Analytics Added +5. Sales Ranking Added +6. Approval Analytics Added +7. Export Added +8. Permissions Added +9. Remaining Risks +10. Task K Readiness + +--- + +# Definition of Done + +✔ Dashboard uses real data + +✔ KPI summary cards complete + +✔ Revenue analytics complete + +✔ Sales ranking complete + +✔ Approval analytics complete + +✔ Follow-up analytics complete + +✔ Pipeline funnel complete + +✔ Filters working + +✔ Export working + +✔ No mock data + +✔ Ready for Task K Report Center diff --git a/src/app/api/crm/dashboard/export/route.ts b/src/app/api/crm/dashboard/export/route.ts new file mode 100644 index 0000000..dfe6ebd --- /dev/null +++ b/src/app/api/crm/dashboard/export/route.ts @@ -0,0 +1,131 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { auditAction } from '@/features/foundation/audit-log/service'; +import { getCrmDashboardData } from '@/features/crm/dashboard/server/service'; +import { PERMISSIONS } from '@/lib/auth/rbac'; +import { AuthError, requireOrganizationAccess } from '@/lib/auth/session'; + +function escapeCsv(value: string | number | null | undefined) { + const text = value === null || value === undefined ? '' : String(value); + return `"${text.replaceAll('"', '""')}"`; +} + +function buildCsv(rows: string[][]) { + return rows.map((row) => row.map((cell) => escapeCsv(cell)).join(',')).join('\n'); +} + +function buildExcelTable(rows: string[][]) { + const body = rows + .map( + (row, rowIndex) => + `
+ {JSON.stringify(version.schemaJson, null, 2)}
+
+