task-fix
This commit is contained in:
305
plans/task-fixcrm.md
Normal file
305
plans/task-fixcrm.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# Task Fix: CRM Dashboard Opportunity Rename Compatibility
|
||||
|
||||
## Objective
|
||||
|
||||
Fix CRM Dashboard API/runtime errors after the force rename from Enquiry to Opportunity.
|
||||
|
||||
The current issue appears when the CRM dashboard query returns `500 Internal Server Error`, causing TanStack Query hydration to reject:
|
||||
|
||||
```txt
|
||||
["crm-dashboard", {...}]
|
||||
```
|
||||
|
||||
This task aligns dashboard, reports, query keys, imports, SQL, DTOs, and permissions with the new Opportunity domain.
|
||||
|
||||
---
|
||||
|
||||
## Error Context
|
||||
|
||||
Observed error:
|
||||
|
||||
```txt
|
||||
A query that was dehydrated as pending ended up rejecting.
|
||||
[["crm-dashboard", {...}]]: Error: API error: 500 Internal Server Error
|
||||
```
|
||||
|
||||
Likely root cause:
|
||||
|
||||
```txt
|
||||
Dashboard API still references old Enquiry domain after D.5.5.1 rename.
|
||||
```
|
||||
|
||||
Examples of stale references:
|
||||
|
||||
```txt
|
||||
crm_enquiries
|
||||
crmEnquiries
|
||||
enquiryId
|
||||
Enquiry
|
||||
enquiry-aging
|
||||
crm.enquiry.*
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Mandatory Review
|
||||
|
||||
Review:
|
||||
|
||||
```txt
|
||||
src/features/crm/dashboard/**
|
||||
src/app/api/crm/dashboard/**
|
||||
src/app/dashboard/crm/**
|
||||
src/app/api/crm/reports/**
|
||||
src/app/dashboard/crm/reports/**
|
||||
src/features/crm/reports/**
|
||||
src/db/schema.ts
|
||||
src/features/crm/opportunities/**
|
||||
src/config/nav-config.ts
|
||||
src/db/seeds/foundation.seed.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scope 1: Identify Stale References
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
rg "crmEnquir|crm_enquir|enquiry|Enquiry|enquiryId|crm\.enquiry|/crm/enquiries" src/features/crm/dashboard src/app/api/crm/dashboard src/app/dashboard/crm src/features/crm/reports src/app/api/crm/reports src/app/dashboard/crm/reports
|
||||
```
|
||||
|
||||
Expected action:
|
||||
|
||||
* Replace active application references with Opportunity terminology.
|
||||
* Historical docs can remain unchanged.
|
||||
* No active dashboard/report runtime code should depend on Enquiry naming.
|
||||
|
||||
---
|
||||
|
||||
## Scope 2: Dashboard API Fix
|
||||
|
||||
Update dashboard API/service to use:
|
||||
|
||||
```txt
|
||||
crmOpportunities
|
||||
crm_opportunities
|
||||
opportunityId
|
||||
crm.opportunity.*
|
||||
```
|
||||
|
||||
instead of:
|
||||
|
||||
```txt
|
||||
crmEnquiries
|
||||
crm_enquiries
|
||||
enquiryId
|
||||
crm.enquiry.*
|
||||
```
|
||||
|
||||
Ensure all dashboard metrics still return successfully.
|
||||
|
||||
Required dashboard response areas to verify:
|
||||
|
||||
```txt
|
||||
summary cards
|
||||
pipeline counts
|
||||
sales ranking
|
||||
follow-up due / overdue
|
||||
hot projects
|
||||
quotation summary
|
||||
won / lost summary
|
||||
project party filters
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scope 3: SQL / Drizzle Query Fix
|
||||
|
||||
Fix all raw SQL and Drizzle queries that reference old table/column names.
|
||||
|
||||
Replace:
|
||||
|
||||
```txt
|
||||
crm_enquiries
|
||||
crm_enquiry_followups
|
||||
crm_enquiry_customers
|
||||
enquiry_id
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```txt
|
||||
crm_opportunities
|
||||
crm_opportunity_followups
|
||||
crm_opportunity_customers
|
||||
opportunity_id
|
||||
```
|
||||
|
||||
If any remaining DB column intentionally keeps legacy naming, document it and map it at service boundary only.
|
||||
|
||||
---
|
||||
|
||||
## Scope 4: Dashboard DTO / Mapper Fix
|
||||
|
||||
Update dashboard DTOs, mappers, and labels.
|
||||
|
||||
Rename:
|
||||
|
||||
```txt
|
||||
enquiryCount
|
||||
enquiryPipeline
|
||||
enquiryValue
|
||||
enquiryAging
|
||||
```
|
||||
|
||||
to:
|
||||
|
||||
```txt
|
||||
opportunityCount
|
||||
opportunityPipeline
|
||||
opportunityValue
|
||||
opportunityAging
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* API response should use Opportunity naming.
|
||||
* UI labels should use Opportunity naming.
|
||||
* Do not expose Enquiry naming in active CRM dashboard.
|
||||
|
||||
---
|
||||
|
||||
## Scope 5: Report Route Compatibility
|
||||
|
||||
Verify renamed routes:
|
||||
|
||||
```txt
|
||||
/api/crm/reports/opportunity-aging
|
||||
/dashboard/crm/reports/opportunity-aging
|
||||
```
|
||||
|
||||
Remove or replace active references to:
|
||||
|
||||
```txt
|
||||
/api/crm/reports/enquiry-aging
|
||||
/dashboard/crm/reports/enquiry-aging
|
||||
```
|
||||
|
||||
Update nav config if needed.
|
||||
|
||||
---
|
||||
|
||||
## Scope 6: Permissions
|
||||
|
||||
Replace dashboard/report permission checks:
|
||||
|
||||
```txt
|
||||
crm.enquiry.*
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```txt
|
||||
crm.opportunity.*
|
||||
```
|
||||
|
||||
Verify seed/config contains the required permissions:
|
||||
|
||||
```txt
|
||||
crm.opportunity.read
|
||||
crm.opportunity.create
|
||||
crm.opportunity.update
|
||||
crm.opportunity.delete
|
||||
crm.opportunity.assign
|
||||
crm.opportunity.followup.create
|
||||
crm.opportunity.followup.update
|
||||
crm.opportunity.followup.delete
|
||||
crm.opportunity.lifecycle.update
|
||||
crm.opportunity.lifecycle.reopen
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scope 7: Error Handling Improvement
|
||||
|
||||
Prevent dashboard SSR hydration from failing hard when API returns an error.
|
||||
|
||||
Improve dashboard query behavior:
|
||||
|
||||
* Server prefetch should catch API failure and return a safe empty dashboard model, or
|
||||
* Client component should render an error state instead of causing hydration failure.
|
||||
|
||||
Do not hide backend errors in development logs.
|
||||
|
||||
Recommended:
|
||||
|
||||
```txt
|
||||
dashboard API logs detailed server error
|
||||
dashboard UI shows recoverable error message
|
||||
query fallback uses empty dashboard model only when safe
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scope 8: Verification
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm exec tsc --noEmit
|
||||
npm run build
|
||||
```
|
||||
|
||||
Search validation:
|
||||
|
||||
```bash
|
||||
rg "crmEnquir|crm_enquir|enquiry|Enquiry|enquiryId|crm\.enquiry|/crm/enquiries" src
|
||||
```
|
||||
|
||||
Allowed only if:
|
||||
|
||||
```txt
|
||||
historical docs
|
||||
comments explicitly marked legacy
|
||||
migration history
|
||||
```
|
||||
|
||||
Manual verification:
|
||||
|
||||
```txt
|
||||
Open CRM Dashboard
|
||||
Dashboard API returns 200
|
||||
No TanStack hydration rejection
|
||||
Opportunity counts render
|
||||
Quotation counts render
|
||||
Won/Lost summary renders
|
||||
Sales ranking renders
|
||||
Follow-up widgets render
|
||||
Hot project widgets render
|
||||
Opportunity aging report opens
|
||||
Navigation links use opportunity routes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Task is complete when:
|
||||
|
||||
* CRM Dashboard no longer returns 500
|
||||
* Dashboard no longer references active Enquiry domain
|
||||
* Reports use Opportunity naming
|
||||
* Permissions use `crm.opportunity.*`
|
||||
* API response and UI labels use Opportunity terminology
|
||||
* TanStack hydration error is gone
|
||||
* `npm exec tsc --noEmit` passes
|
||||
* `npm run build` passes
|
||||
|
||||
Result:
|
||||
|
||||
```txt
|
||||
Dashboard Opportunity Rename Compatibility = Fixed
|
||||
CRM Dashboard Runtime = Restored
|
||||
Ready to continue Approval + Notification roadmap
|
||||
```
|
||||
Reference in New Issue
Block a user