Files
alla-allaos-fullstack/docs/implementation/technical-debt.md
phaichayon 04a886ea26 task-j1
2026-06-17 16:04:19 +07:00

348 lines
11 KiB
Markdown

# Technical Debt
## After Task D
### Database foreign keys
Customer, contact, and enquiry relationships are still enforced mainly in application logic.
Future:
- add FK constraints after the CRM schema settles
- review cascade behavior before enabling hard relational enforcement
### Date input UX
Several forms still use plain `YYYY-MM-DD` text/date inputs.
Future:
- move to a shared date picker pattern
- standardize timezone handling for CRM forms
### Related enquiry pagination
Customer detail can show related enquiries, but that view still has no dedicated pagination strategy.
Future:
- add paging once real data volume grows
### Follow-up activity timeline
Activity history still relies heavily on audit payloads instead of a curated domain timeline.
Future:
- build a combined activity view/service for CRM interactions
## After Task D.1
### Enquiry Own / Assigned Scope
Current:
sales role ยังอ่าน enquiry ในระดับ organization scope
Future:
เพิ่ม server-side policy:
- sales เห็นเฉพาะ enquiry ที่ตัวเองสร้าง
- หรือ enquiry ที่ assigned ให้ตัวเอง
- sales_manager เห็นทั้งทีม
Priority:
High
### Legacy Business Role Backfill
Current:
ระบบ runtime ใช้ CRM businessRole แล้ว แต่ DB เก่าอาจยังมี role จาก IT-CENTER
Future:
ทำ one-time migration/backfill script สำหรับ memberships.businessRole
Priority:
Medium
## After Task E
### Mixed tax rollup
Quotation items support per-line tax input, but summary calculation still assumes a header-centric tax model.
Future:
- support mixed-tax aggregation from actual item rows
- align document totals and reporting with per-line tax logic
### Attachment storage abstraction
Quotation attachments started as metadata-only and approved PDFs now write to local disk, but there is still no real storage abstraction.
Future:
- introduce a provider abstraction
- support upload/download lifecycle consistently across manual attachments and generated artifacts
- define migration strategy for existing local/public paths
### Revision snapshot coverage
Revision copy currently focuses on quotation header, items, customers, and topics.
Future:
- decide whether follow-ups and attachments belong in revision snapshots
- define immutable vs mutable child-data behavior across revisions
### CRM foreign keys
Core CRM tables still depend on organization-scoped validation in service code.
Future:
- add FK constraints after schema churn slows down
- review delete and soft-delete interactions first
## After Task F
### Permission sync for existing memberships
New permissions are defined in code, but old membership rows may still hold stale permission arrays.
Future:
- add a permission sync/backfill command
- provide admin tooling for role and permission maintenance
### Approval workflow configuration UI
Approval workflows are seeded and usable, but still not configurable from the dashboard.
Future:
- build workflow setup screens
- add step editing and role mapping management
### Approval notifications
Approval flow has no queue-backed notification channel yet.
Future:
- add notification jobs
- support reminders and escalation policy
## After Task G
### Document mapping editor
Template mappings are seeded and readable, but not manageable from UI.
Future:
- add mapping CRUD for admins
- support table column editing
- add draft/publish template workflow
### Product-specific template resolution
Quotation document template resolution still defaults to a coarse product selection strategy.
Future:
- define clearer rules for crane, dock door, solar, and service-specific templates
## After Task H / H.1
### Font compatibility fallback
PDF generation now uses vendored Cordia TTF files from `public/fonts`, which fixed the TTC runtime issue, but generator-side fallback normalization still remains as a safety net.
Future:
- keep validating Thai text metrics against designer output
- remove fallback normalization only after render parity is proven stable
### Local filesystem storage
Approved PDFs currently persist under `public/generated/quotations/<organizationId>/`.
Future:
- replace local public storage for production with object storage
- add signed/private delivery where required
- define backup and cleanup expectations
### Approved artifact immutability
Approved PDF persistence exists, but the lifecycle is not immutable by policy yet.
Future:
- define whether regeneration is allowed after approval
- version approved artifacts explicitly if regeneration must remain possible
- document which snapshot fields are contractual records
### Post-approval automation
Approved PDF generation is still manual by design.
Future:
- add a non-blocking auto-generation hook after final approval
- move heavy generation/retry behavior to a background job when needed
### PDF pipeline test coverage
Task H.1 added dev fixture and HTTP verification scripts, but there is still no CI-backed E2E coverage for the PDF pipeline.
Future:
- promote fixture verification into automated test coverage
- add regression checks for template mappings, storage persistence, and permission enforcement
## After Task I
### Storage provider production rollout
Task I introduced a storage provider abstraction with local and S3/MinIO-compatible implementations, but the production rollout still depends on environment configuration and infrastructure ownership outside the app.
Future:
- validate real bucket policies, credentials rotation, and environment separation
- add operational runbooks for provider misconfiguration and storage outage handling
- add smoke checks for startup-time storage provider health
### Legacy approved PDF migration
Task I keeps compatibility for legacy `public/generated/...` approved PDFs, but those legacy files are still outside the new artifact source-of-truth model.
Future:
- add a one-time migration script from legacy local paths into `crm_document_artifacts`
- backfill `approvedArtifactId` where possible
- remove legacy compatibility once migration is complete and verified
### Artifact lifecycle policy depth
Approved artifacts are now immutable-first and locked after generation, but void/regeneration policy is still service-level rather than a full operator workflow.
Future:
- add explicit admin tooling for artifact void and replacement flows
- define whether artifact voiding also clears or supersedes quotation-facing references automatically
- document retention expectations for voided objects in object storage
### Secure artifact delivery model
Approved-PDF viewing now goes through secure server routes and storage-backed reads, but signed-url/offload behavior is not yet used.
Future:
- decide when direct signed URLs are acceptable versus mandatory server streaming
- add response caching strategy for large artifact downloads
- evaluate optional download-audit sampling if volume grows
## After Task J.0
### Missing lifecycle timestamps for KPI precision
Task J.0 freezes KPI rules around `pipelineStage`, but the schema still lacks explicit lifecycle timestamps for stage conversion and closure events.
Future:
- add `convertedToOpportunityAt` for precise lead-to-opportunity timing
- add `closedWonAt` for won-date reporting
- add `closedLostAt` for lost-date reporting
- backfill reporting logic to prefer explicit lifecycle timestamps over inference when available
### Lost reason analytics
Closed-lost semantics are frozen, but there is still no structured `lostReason` field for dashboard grouping and sales analysis.
Future:
- add `lostReason` to the CRM enquiry lifecycle model
- define a controlled vocabulary or master-option category for loss analysis
- expose lost-reason reporting only after the field is reliably captured
### Default customer party role behavior
Customer party definitions are frozen, but there is still no `defaultPartyRole` behavior to help normalize customer selection and reduce operator ambiguity.
Future:
- decide whether customers should carry a suggested default project-party role
- add `defaultPartyRole` only if it improves data-entry quality without creating hidden automation
- keep dashboard logic independent from this field until the model is formally introduced
## After Task D.2.1
### Unified project-party reporting projection
Revenue attribution is now frozen, but the schema still stores enquiry and quotation parties in separate tables rather than a dedicated reporting projection.
Future:
- add a unified reporting view or materialized projection if dashboard/report queries become heavy
- keep quotation-party precedence and enquiry fallback centralized in one service until that projection exists
- avoid duplicating attribution logic in dashboard-specific code
### Historical party snapshot fidelity
Current revenue attribution uses live project-party relationships with quotation-first fallback behavior, but it does not yet provide effective-dated historical party snapshots for reporting.
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