# Task D.4 Implementation Summary ## Completed - extended `crm_enquiries` with official won/lost lifecycle fields - added `crm_enquiry_attachments` for purchase order files - seeded `crm_lost_reason` master data - added permissions: - `crm.enquiry.mark_won` - `crm.enquiry.mark_lost` - `crm.enquiry.reopen` - added outcome service operations for: - mark won - mark lost - reopen lost opportunity - added API routes for outcome transitions and PO attachment upload/view/download - added enquiry detail outcome card with: - open / won / lost state - PO data - lost data - closed by / closed date - mark won / mark lost / reopen actions - PO attachment upload and retrieval - removed quotation-status-driven mutation of enquiry pipeline outcome - migrated dashboard summary/funnel/sales won revenue to enquiry outcome helpers - added reporting helpers: - `getWonRevenue()` - `getLostRevenue()` - `getLostByReason()` - `getLostByCompetitor()` - `getWinRate()` ## Verification - `npm exec tsc --noEmit` ## Notes - marketing users still receive outcome state, but PO amount is redacted server-side unless commercial pricing visibility exists - PO attachment endpoints are also restricted to commercial-data viewers - revenue analytics cards still use existing quotation-attribution views for top-party ranking, but won/lost headline KPI and sales won revenue now follow the D.4 lifecycle rule