@fayz-ai/plugin-fiscal-br 0.9.4 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/connectors/plugnotas.ts","../src/migrations/index.ts","../src/data/registries.ts","../src/lib/nfe-xml.ts","../src/data/inbox.ts","../src/views/PullByKeyDialog.tsx","../src/views/InboundNotesView.tsx","../src/views/NoteAttachmentsCard.tsx","../src/types.ts","../src/views/NoteReconcileView.tsx","../src/views/InboundNotesPage.tsx","../src/views/UnitFiscalWidgets.tsx","../src/data/issued.ts","../src/lib/issued-note.ts","../src/views/InvoiceNotesButton.tsx","../src/lib/financial-provider.ts","../src/views/GapScreens.tsx","../src/views/inventoryView.tsx","../src/index.ts"],"names":["digits","useState","useEffect","jsx","jsxs","Button","Loader2","KeyRound","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","money","formatCurrency","day","useRef","useCallback","Card","ImageIcon","FileText","Trash2","UploadCloud","accepted","useMemo","reavaliar","rodape","Fragment","ModalHeader","ModalTitle","ModalBody","ModalFooter","FileCode2","Hint","RefreshCw","Input","Modal","ModalContent","sb","getSupabaseClientOptional","getActiveTenantId","React","adminNavigateTo","Skeleton","Field","Check","X","NOTE_COLUMNS","TooltipProvider","Tooltip","TooltipTrigger","TooltipContent","ModalDescription","toast","Badge","ChevronDown","AlertTriangle","document","describeError"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA6jB/B,IAAM,0DAAA,GAA6D,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAqMnE,IAAM,+CAAA,GAAkD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA2WxD,IAAM,0CAAA,GAA6C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAkPnD,IAAM,8CAAA,GAAiD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAwBvD,IAAM,2CAAA,GAA8C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA+MpD,IAAM,yCAAA,GAA4C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAoBlD,IAAM,oDAAA,GAAuD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAiC7D,IAAM,yDAAA,GAA4D,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AA4NlE,IAAM,gEAAA,GAAmE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAsiBzE,IAAM,gEAAA,GAAmE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAkOzE,IAAM,8CAAA,GAAiD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAmFvD,IAAM,oDAAA,GAAuD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA,CAAA;AA8J7D,IAAM,oDAAA,GAAuD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AA0J7D,IAAM,kDAAA,GAAqD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAsH7D,IAAM,+CAAA,GAAkD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","file":"index.js","sourcesContent":["import type React from 'react'\nimport {\n connectionSettings,\n connectionStatus,\n createConnectionStore,\n settingsStatus,\n type ConnectionConfig,\n type ConnectorDefinition,\n type ConnectorField,\n type ConnectorSetting,\n} from '@fayz-ai/core'\nimport type { PlugNotasConnectorClient, PlugNotasEnvironment, PlugNotasSetupState } from '../types'\n\nexport const PLUGNOTAS_CONNECTOR_ID = 'plugnotas'\n\nconst PLUGNOTAS_MARK = \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%230F766E'/%3E%3Cpath d='M10 7h12v18l-2-1.5-2 1.5-2-1.5-2 1.5-2-1.5-2 1.5V7Z' fill='white'/%3E%3Cpath d='M13 12h6M13 16h6M13 20h4' stroke='%230F766E' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E\"\n\nexport const PLUGNOTAS_FIELDS = [\n {\n key: 'emitterCnpj',\n label: 'CNPJ do emitente',\n type: 'text',\n placeholder: '00.000.000/0000-00',\n },\n] as const satisfies readonly ConnectorField[]\n\nexport const PLUGNOTAS_SETTINGS = [{\n key: 'environment',\n label: 'Ambiente fiscal',\n description: 'Sandbox simula o emissor. Homologação envia para a SEFAZ sem valor fiscal.',\n type: 'select',\n options: [\n { value: 'sandbox', label: 'Sandbox simulado' },\n { value: 'homologation', label: 'Homologação SEFAZ' },\n ],\n requiredToOperate: true,\n defaultValue: 'sandbox',\n}] as const satisfies readonly ConnectorSetting[]\n\nconst INTERNAL_SETTINGS = [\n 'certificateReady',\n 'cscReady',\n 'providerEmitterId',\n 'certificateExpiresAt',\n 'certificateFingerprint',\n // Non-secret operational data written by the host's server-side setup flow.\n // Declaring these keys keeps the shared connection store authoritative while\n // credentials (API key, A1 bytes/password, CSC) remain outside public JSON.\n 'stateRegistration',\n 'corporateName',\n 'tradeName',\n 'email',\n 'taxRegime',\n 'address',\n 'series',\n 'paymentMethod',\n]\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction digits(value: string): string {\n return value.replace(/\\D/g, '')\n}\n\nexport function isValidCnpj(value: string): boolean {\n const normalized = digits(value)\n if (!/^\\d{14}$/.test(normalized) || /^(\\d)\\1{13}$/.test(normalized)) return false\n const digit = (base: string, weights: number[]) => {\n const sum = weights.reduce((total, weight, index) => total + Number(base[index]) * weight, 0)\n const remainder = sum % 11\n return remainder < 2 ? 0 : 11 - remainder\n }\n const first = digit(normalized.slice(0, 12), [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2])\n const second = digit(`${normalized.slice(0, 12)}${first}`, [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2])\n return normalized.endsWith(`${first}${second}`)\n}\n\nfunction environment(value: unknown): PlugNotasEnvironment {\n if (value === undefined || value === null || value === '' || value === 'sandbox') return 'sandbox'\n if (value === 'homologation') return value\n throw new Error('Produção não está disponível neste conector preview.')\n}\n\nfunction store() {\n return createConnectionStore(PLUGNOTAS_CONNECTOR_ID, {\n fields: [...PLUGNOTAS_FIELDS],\n settings: [...PLUGNOTAS_SETTINGS],\n settingsKeys: INTERNAL_SETTINGS,\n })\n}\n\nfunction deriveStatus(connection: ConnectionConfig | null) {\n if (!connection?.active) return { connected: false }\n const readiness = settingsStatus([...PLUGNOTAS_SETTINGS], connection)\n const certificateReady = connection.settings.certificateReady === true\n const cscReady = connection.settings.cscReady === true\n const expiry = typeof connection.settings.certificateExpiresAt === 'string'\n ? Date.parse(connection.settings.certificateExpiresAt)\n : Number.NaN\n const daysUntilExpiry = Number.isFinite(expiry) ? Math.ceil((expiry - Date.now()) / DAY_MS) : null\n const expired = daysUntilExpiry !== null && daysUntilExpiry <= 0\n const expiringSoon = daysUntilExpiry !== null && daysUntilExpiry > 0 && daysUntilExpiry <= 30\n const missingSettings = [...new Set([\n ...(readiness.missingSettings ?? []),\n ...(!certificateReady || expired ? ['certificate'] : []),\n ...(!cscReady ? ['csc'] : []),\n ])]\n\n return {\n connected: true,\n needsSetup: missingSettings.length > 0,\n ...(missingSettings.length ? { missingSettings } : {}),\n detail: expired\n ? 'Certificado A1 vencido'\n : !certificateReady\n ? 'Envie o certificado A1 do emitente.'\n : !cscReady\n ? 'Confirme o CSC e o ID Token do emitente.'\n : connection.settings.environment === 'homologation'\n ? 'Emitente pronto em homologação'\n : 'Emitente pronto no sandbox',\n ...(expiringSoon\n ? { issues: [`O certificado A1 vence em ${daysUntilExpiry} dia${daysUntilExpiry === 1 ? '' : 's'}.`] }\n : {}),\n plane: 'sync' as const,\n }\n}\n\nexport interface CreatePlugNotasConnectorOptions {\n client?: PlugNotasConnectorClient\n SetupPanel?: React.ComponentType\n}\n\nexport function createPlugNotasConnector(options: CreatePlugNotasConnectorOptions = {}): ConnectorDefinition {\n const connectionStore = store()\n return {\n id: PLUGNOTAS_CONNECTOR_ID,\n // PlugBank and PlugNotas are different products from the same vendor. The\n // directory key names the product, otherwise one silently replaces the\n // other in the generated connector map.\n catalogSlug: 'plugnotas',\n hostPluginId: 'financial',\n name: 'PlugNotas · NFC-e',\n description: 'Emita NFC-e pela TecnoSpeed sem expor certificado, senha ou API key no navegador.',\n icon: 'ReceiptText',\n logoUrl: PLUGNOTAS_MARK,\n authKind: 'api-key',\n category: 'erp',\n direction: 'outbound',\n planes: ['sync'],\n docsUrl: 'https://docs.plugnotas.com.br/',\n fields: [...PLUGNOTAS_FIELDS],\n settings: [...PLUGNOTAS_SETTINGS],\n permissions: [{\n kind: 'data',\n resource: 'fiscal-document',\n actions: ['read', 'write'],\n reason: 'Enviar a NFC-e e reconciliar situação, chave de acesso e artefatos no Financeiro.',\n sensitive: true,\n }],\n invokedAt: [{\n key: 'financial.nfce.issue',\n label: 'Quando um operador confirma a emissão da NFC-e de um pedido concluído',\n plane: 'sync',\n trigger: 'manual',\n touches: ['fiscal-document'],\n }],\n howItSyncs: [\n 'A emissão cria primeiro um comando durável e só depois chama o provedor.',\n 'Webhook e recuperação consultiva convergem o mesmo comando, sem reenviar no escuro.',\n ],\n ...connectionStatus(PLUGNOTAS_CONNECTOR_ID, deriveStatus, { store }),\n ...connectionSettings(connectionStore),\n async testConnection(values) {\n const emitterCnpj = digits(values.emitterCnpj ?? '')\n if (!isValidCnpj(emitterCnpj)) return { ok: false, message: 'Informe um CNPJ válido.' }\n let selected: PlugNotasEnvironment\n try {\n selected = environment(values.environment)\n } catch (error) {\n return { ok: false, message: error instanceof Error ? error.message : 'Ambiente inválido.' }\n }\n return options.client?.testEmitter\n ? options.client.testEmitter({ emitterCnpj, environment: selected })\n : { ok: true }\n },\n async saveConnection(values) {\n const emitterCnpj = digits(values.emitterCnpj ?? '')\n if (!isValidCnpj(emitterCnpj)) throw new Error('Informe um CNPJ válido.')\n await connectionStore.save({\n active: true,\n displayName: `Emitente ${emitterCnpj.slice(-6)}`,\n providerAccountKey: emitterCnpj,\n settings: {\n emitterCnpj,\n environment: environment(values.environment),\n certificateReady: false,\n cscReady: false,\n },\n })\n },\n ...(options.client?.disconnectEmitter\n ? { disconnect: () => options.client!.disconnectEmitter!() }\n : {}),\n disconnectNote: 'As notas existentes permanecem no Financeiro; somente novas emissões são interrompidas.',\n ExtraPanel: options.SetupPanel,\n }\n}\n\n/** Persist only server-confirmed readiness and non-secret certificate metadata. */\nexport async function markPlugNotasEmitterReady(input: PlugNotasSetupState): Promise<void> {\n const emitterCnpj = digits(input.emitterCnpj)\n if (!isValidCnpj(emitterCnpj)) throw new Error('Informe um CNPJ válido.')\n await store().save({\n active: true,\n providerAccountKey: emitterCnpj,\n settings: {\n emitterCnpj,\n environment: environment(input.environment),\n certificateReady: input.certificateReady,\n cscReady: input.cscReady,\n providerEmitterId: input.providerEmitterId,\n certificateExpiresAt: input.certificateExpiresAt,\n certificateFingerprint: input.certificateFingerprint,\n },\n })\n}\n","// AUTO-GENERATED from 000_baseline.sql, 001_preserve_terminal_results_and_recover_leases.sql, 002_a_nota_que_chega_tem_onde_esperar.sql, 003_a_caixa_de_entrada_atravessa.sql, 004_o_grupo_fiscal_do_v1_repete_nome.sql, 005_a_nota_emitida_e_um_documento.sql, 006_o_grupo_fiscal_ganha_o_rail.sql, 007_a_rls_do_documento_passa_a_ser_legivel.sql, 008_a_nota_recebida_guarda_a_decisao_de_entrada.sql, 009_aceitar_a_nota_escreve_estoque_e_titulo_de_uma_vez.sql, 010_a_data_de_emissao_e_instante_e_a_competencia_e_dia.sql, 011_o_imposto_do_produto_e_do_fiscal.sql, 012_quem_e_o_produto_se_pergunta_ao_indice.sql, 013_a_sugestao_sobrevive_a_fechar_a_janela.sql, 014_a_descricao_da_nota_tem_lixo_no_meio.sql, 015_o_movimento_diz_que_veio_da_nota.sql, 016_a_nota_guarda_o_proprio_xml.sql, 017_quem_emite_e_o_cnpj_nao_a_loja.sql, 018_a_nota_do_v1_alcanca_a_conta.sql, 019_a_nota_emitida_se_cancela_pelo_v2.sql, 020_a_nota_acha_o_fornecedor_pelo_cnpj.sql, 021_uso_e_consumo_entra_no_estoque.sql, 022_a_nota_do_v1_traz_o_xml.sql, 023_a_nota_aceita_sem_linhas_recebe_as_linhas.sql, 024_a_nota_nao_aponta_para_conta_que_sumiu.sql, 025_a_conta_da_nota_fecha_com_o_total.sql, 026_o_recebimento_parado_diz_por_que.sql, 027_a_nota_com_conta_e_sem_estoque_termina_no_v2.sql, 028_a_linha_de_estoque_tem_unidade.sql, 029_the_service_writes_the_intake_health.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_000_BASELINE = `-- Fiscal Brasil / PlugNotas baseline.\n--\n-- This addon does not create a second fiscal ledger. \\`plg_financial_nfe\\`\n-- remains the authoritative document owned by plugin-financial. The tables\n-- below describe delivery to an external issuer: durable commands, attempts,\n-- webhooks and emitter ownership.\n--\n-- The file is additive and idempotent because the current restaurant pool is\n-- live. Applying it is deliberately outside this draft PR.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_nfce_jobs (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n -- Logical reference to plugin-financial's fiscal ledger. Cross-plugin\n -- physical foreign keys are intentionally forbidden: installation and\n -- removal of this addon must never rewrite another plugin's schema.\n nota_id uuid NOT NULL,\n order_id uuid NOT NULL REFERENCES public.orders(id) ON DELETE RESTRICT,\n connection_id uuid NOT NULL REFERENCES public.connections(id) ON DELETE RESTRICT,\n operation text NOT NULL CHECK (operation IN ('issue', 'cancel')),\n status text NOT NULL DEFAULT 'queued'\n CHECK (status IN ('queued', 'running', 'waiting', 'succeeded', 'failed', 'manual_review')),\n idempotency_key text NOT NULL,\n provider_document_id text,\n integration_id text,\n request_snapshot jsonb NOT NULL DEFAULT '{}'::jsonb,\n provider_response jsonb NOT NULL DEFAULT '{}'::jsonb,\n attempts integer NOT NULL DEFAULT 0 CHECK (attempts >= 0),\n next_attempt_at timestamptz,\n locked_until timestamptz,\n last_error text,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE (tenant_id, idempotency_key)\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_nfce_jobs_recovery_idx\n ON public.plg_fiscalbr_nfce_jobs (status, next_attempt_at, locked_until)\n WHERE status IN ('queued', 'waiting');\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_nfce_events (\n id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n nota_id uuid NOT NULL,\n job_id uuid REFERENCES public.plg_fiscalbr_nfce_jobs(id) ON DELETE SET NULL,\n event_type text NOT NULL,\n payload jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now()\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_nfce_events_document_idx\n ON public.plg_fiscalbr_nfce_events (tenant_id, nota_id, created_at DESC);\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_webhook_receipts (\n id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,\n provider text NOT NULL DEFAULT 'plugnotas',\n provider_event_id text NOT NULL,\n tenant_id uuid REFERENCES public.tenants(id) ON DELETE SET NULL,\n nota_id uuid,\n payload_sha256 text NOT NULL,\n received_at timestamptz NOT NULL DEFAULT now(),\n processed_at timestamptz,\n processing_error text,\n UNIQUE (provider, provider_event_id)\n);\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_emitter_ownership (\n emitter_cnpj text PRIMARY KEY CHECK (emitter_cnpj ~ '^[0-9]{14}$'),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n connection_id uuid NOT NULL REFERENCES public.connections(id) ON DELETE CASCADE,\n environment text NOT NULL CHECK (environment IN ('sandbox', 'homologation')),\n provider_emitter_id text,\n certificate_expires_at timestamptz,\n certificate_fingerprint text,\n csc_ready boolean NOT NULL DEFAULT false,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE (tenant_id, connection_id)\n);\n\nALTER TABLE public.plg_fiscalbr_nfce_jobs ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_nfce_events ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_webhook_receipts ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_emitter_ownership ENABLE ROW LEVEL SECURITY;\n\nDROP POLICY IF EXISTS plg_fiscalbr_nfce_jobs_read ON public.plg_fiscalbr_nfce_jobs;\nCREATE POLICY plg_fiscalbr_nfce_jobs_read ON public.plg_fiscalbr_nfce_jobs\n FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL))\n );\n\nDROP POLICY IF EXISTS plg_fiscalbr_nfce_events_read ON public.plg_fiscalbr_nfce_events;\nCREATE POLICY plg_fiscalbr_nfce_events_read ON public.plg_fiscalbr_nfce_events\n FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL))\n );\n\nDROP POLICY IF EXISTS plg_fiscalbr_emitter_ownership_read ON public.plg_fiscalbr_emitter_ownership;\nCREATE POLICY plg_fiscalbr_emitter_ownership_read ON public.plg_fiscalbr_emitter_ownership\n FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL))\n );\n\nREVOKE ALL ON public.plg_fiscalbr_nfce_jobs FROM anon, authenticated;\nREVOKE ALL ON public.plg_fiscalbr_nfce_events FROM anon, authenticated;\nREVOKE ALL ON public.plg_fiscalbr_webhook_receipts FROM anon, authenticated;\nREVOKE ALL ON public.plg_fiscalbr_emitter_ownership FROM anon, authenticated;\nGRANT SELECT ON public.plg_fiscalbr_nfce_jobs TO authenticated;\nGRANT SELECT ON public.plg_fiscalbr_nfce_events TO authenticated;\nGRANT SELECT ON public.plg_fiscalbr_emitter_ownership TO authenticated;\nGRANT ALL ON public.plg_fiscalbr_nfce_jobs TO service_role;\nGRANT ALL ON public.plg_fiscalbr_nfce_events TO service_role;\nGRANT ALL ON public.plg_fiscalbr_webhook_receipts TO service_role;\nGRANT ALL ON public.plg_fiscalbr_emitter_ownership TO service_role;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_register_emitter(\n p_tenant_id uuid,\n p_connection_id uuid,\n p_emitter_cnpj text,\n p_environment text,\n p_provider_emitter_id text DEFAULT NULL,\n p_certificate_expires_at timestamptz DEFAULT NULL,\n p_certificate_fingerprint text DEFAULT NULL,\n p_csc_ready boolean DEFAULT false\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_cnpj text := regexp_replace(coalesce(p_emitter_cnpj, ''), '[^0-9]', '', 'g');\nBEGIN\n IF v_cnpj !~ '^[0-9]{14}$' THEN\n RAISE EXCEPTION 'plugnotas_register_emitter: invalid CNPJ' USING ERRCODE = '22023';\n END IF;\n IF p_environment NOT IN ('sandbox', 'homologation') THEN\n RAISE EXCEPTION 'plugnotas_register_emitter: production is not enabled' USING ERRCODE = '22023';\n END IF;\n IF NOT EXISTS (\n SELECT 1 FROM public.connections c\n WHERE c.id = p_connection_id\n AND c.tenant_id = p_tenant_id\n AND c.connector_id = 'plugnotas'\n AND c.active\n ) THEN\n RAISE EXCEPTION 'plugnotas_register_emitter: active connection not found' USING ERRCODE = 'P0002';\n END IF;\n\n INSERT INTO public.plg_fiscalbr_emitter_ownership\n (emitter_cnpj, tenant_id, connection_id, environment, provider_emitter_id,\n certificate_expires_at, certificate_fingerprint, csc_ready, updated_at)\n VALUES\n (v_cnpj, p_tenant_id, p_connection_id, p_environment, p_provider_emitter_id,\n p_certificate_expires_at, p_certificate_fingerprint, p_csc_ready, now())\n ON CONFLICT (emitter_cnpj) DO UPDATE SET\n tenant_id = EXCLUDED.tenant_id,\n connection_id = EXCLUDED.connection_id,\n environment = EXCLUDED.environment,\n provider_emitter_id = EXCLUDED.provider_emitter_id,\n certificate_expires_at = EXCLUDED.certificate_expires_at,\n certificate_fingerprint = EXCLUDED.certificate_fingerprint,\n csc_ready = EXCLUDED.csc_ready,\n updated_at = now()\n WHERE public.plg_fiscalbr_emitter_ownership.tenant_id = EXCLUDED.tenant_id;\n\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_register_emitter: CNPJ belongs to another tenant' USING ERRCODE = '23505';\n END IF;\n\n UPDATE public.connections\n SET provider_account_key = v_cnpj,\n settings = settings || jsonb_build_object(\n 'environment', p_environment,\n 'certificateReady', p_certificate_expires_at IS NOT NULL,\n 'certificateExpiresAt', p_certificate_expires_at,\n 'certificateFingerprint', p_certificate_fingerprint,\n 'providerEmitterId', p_provider_emitter_id,\n 'cscReady', p_csc_ready\n ),\n status = CASE WHEN p_certificate_expires_at IS NOT NULL AND p_csc_ready THEN 'connected' ELSE 'pending' END,\n updated_at = now()\n WHERE id = p_connection_id AND tenant_id = p_tenant_id;\n\n RETURN jsonb_build_object('emitterCnpj', v_cnpj, 'environment', p_environment);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_disconnect_emitter(\n p_tenant_id uuid,\n p_connection_id uuid\n) RETURNS void\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n DELETE FROM public.plg_fiscalbr_emitter_ownership\n WHERE tenant_id = p_tenant_id AND connection_id = p_connection_id;\n UPDATE public.connections\n SET active = false, status = 'revoked', settings = '{}'::jsonb,\n provider_state = '{}'::jsonb, updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = p_connection_id AND connector_id = 'plugnotas';\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_create_nfce_draft_for_order(\n p_tenant_id uuid,\n p_order_id uuid\n) RETURNS uuid\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_order public.orders%ROWTYPE;\n v_nota_id uuid;\nBEGIN\n -- Serialize draft creation per tenant/order without adding a column or\n -- index to the financial plugin's table. The order itself remains the\n -- stable idempotency boundary for one NFC-e draft.\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || p_order_id::text, 0));\n\n SELECT * INTO v_order FROM public.orders\n WHERE tenant_id = p_tenant_id AND id = p_order_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_create_nfce_draft_for_order: order not found' USING ERRCODE = 'P0002';\n END IF;\n IF v_order.status NOT IN ('completed', 'paid', 'invoiced') THEN\n RAISE EXCEPTION 'plugnotas_create_nfce_draft_for_order: order is not closed' USING ERRCODE = '23514';\n END IF;\n IF NOT EXISTS (SELECT 1 FROM public.items i WHERE i.tenant_id = p_tenant_id AND i.order_id = p_order_id) THEN\n RAISE EXCEPTION 'plugnotas_create_nfce_draft_for_order: order has no items' USING ERRCODE = '23514';\n END IF;\n\n SELECT n.id INTO v_nota_id FROM public.plg_financial_nfe n\n WHERE n.tenant_id = p_tenant_id AND n.order_id = p_order_id AND n.model = 'nfce'\n ORDER BY n.created_at DESC LIMIT 1;\n IF v_nota_id IS NOT NULL THEN RETURN v_nota_id; END IF;\n\n INSERT INTO public.plg_financial_nfe\n (tenant_id, unit_id, model, status, order_id, contact_id, total_amount,\n emissor, metadata)\n VALUES\n (p_tenant_id, v_order.unit_id, 'nfce', 'draft', p_order_id, v_order.party_id,\n coalesce(v_order.total, 0), 'plugnotas',\n jsonb_build_object('source', 'order', 'orderKind', v_order.kind, 'orderChannel', v_order.channel))\n RETURNING id INTO v_nota_id;\n RETURN v_nota_id;\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_prepare_nfce(\n p_tenant_id uuid,\n p_nota_id uuid,\n p_connection_id uuid,\n p_idempotency_key text\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_nota public.plg_financial_nfe%ROWTYPE;\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_snapshot jsonb;\nBEGIN\n SELECT * INTO v_nota FROM public.plg_financial_nfe\n WHERE tenant_id = p_tenant_id AND id = p_nota_id FOR UPDATE;\n IF NOT FOUND OR v_nota.model <> 'nfce' OR v_nota.order_id IS NULL THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce: order-backed NFC-e not found' USING ERRCODE = 'P0002';\n END IF;\n IF v_nota.status NOT IN ('draft', 'error', 'processing') THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce: invalid document status %', v_nota.status USING ERRCODE = '23514';\n END IF;\n IF NOT EXISTS (\n SELECT 1 FROM public.plg_fiscalbr_emitter_ownership e\n WHERE e.tenant_id = p_tenant_id AND e.connection_id = p_connection_id\n AND e.csc_ready AND e.certificate_expires_at > now()\n ) THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce: emitter is not ready' USING ERRCODE = '23514';\n END IF;\n\n SELECT jsonb_build_object(\n 'nota', to_jsonb(v_nota),\n 'order', to_jsonb(o),\n 'items', coalesce((\n SELECT jsonb_agg(to_jsonb(i) ORDER BY i.sort_order, i.id)\n FROM public.items i\n WHERE i.tenant_id = p_tenant_id AND i.order_id = v_nota.order_id\n ), '[]'::jsonb),\n -- Product tax metadata must be frozen in the same transaction as the order\n -- lines. Looking products up in the Edge Function would let a retry emit\n -- with NCM/CFOP changed after the operator confirmed the document.\n 'products', coalesce((\n SELECT jsonb_agg(to_jsonb(p) ORDER BY p.id)\n FROM public.products p\n WHERE p.tenant_id = p_tenant_id\n AND p.id IN (\n SELECT i.product_id FROM public.items i\n WHERE i.tenant_id = p_tenant_id\n AND i.order_id = v_nota.order_id\n AND i.product_id IS NOT NULL\n )\n ), '[]'::jsonb)\n ) INTO v_snapshot\n FROM public.orders o\n WHERE o.tenant_id = p_tenant_id AND o.id = v_nota.order_id;\n\n IF jsonb_array_length(v_snapshot->'items') = 0 THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce: order has no items' USING ERRCODE = '23514';\n END IF;\n\n INSERT INTO public.plg_fiscalbr_nfce_jobs\n (tenant_id, nota_id, order_id, connection_id, operation, status,\n idempotency_key, request_snapshot, next_attempt_at, updated_at)\n VALUES\n (p_tenant_id, p_nota_id, v_nota.order_id, p_connection_id, 'issue', 'queued',\n p_idempotency_key, v_snapshot, now(), now())\n ON CONFLICT (tenant_id, idempotency_key) DO UPDATE\n SET updated_at = now()\n RETURNING * INTO v_job;\n\n UPDATE public.plg_financial_nfe\n SET status = 'processing', error_message = NULL,\n metadata = metadata || jsonb_build_object('plugnotas', jsonb_build_object(\n 'jobId', v_job.id, 'jobStatus', v_job.status, 'operation', 'issue'\n )), updated_at = now()\n WHERE id = p_nota_id AND tenant_id = p_tenant_id;\n\n INSERT INTO public.plg_fiscalbr_nfce_events (tenant_id, nota_id, job_id, event_type, payload)\n VALUES (p_tenant_id, p_nota_id, v_job.id, 'issue.queued', '{}'::jsonb);\n RETURN jsonb_build_object('jobId', v_job.id, 'snapshot', v_job.request_snapshot, 'replayed', v_job.attempts > 0);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_prepare_nfce_cancel(\n p_tenant_id uuid,\n p_nota_id uuid,\n p_connection_id uuid,\n p_reason text\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_nota public.plg_financial_nfe%ROWTYPE;\n v_job_id uuid;\n v_reason text := btrim(coalesce(p_reason, ''));\nBEGIN\n IF char_length(v_reason) NOT BETWEEN 15 AND 255 THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce_cancel: reason must contain 15 to 255 characters' USING ERRCODE = '22023';\n END IF;\n SELECT * INTO v_nota FROM public.plg_financial_nfe\n WHERE tenant_id = p_tenant_id AND id = p_nota_id FOR UPDATE;\n IF NOT FOUND OR v_nota.status <> 'issued' OR v_nota.access_key IS NULL THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce_cancel: authorized NFC-e not found' USING ERRCODE = '23514';\n END IF;\n\n INSERT INTO public.plg_fiscalbr_nfce_jobs\n (tenant_id, nota_id, order_id, connection_id, operation, status,\n idempotency_key, provider_document_id, integration_id,\n request_snapshot, next_attempt_at)\n VALUES\n (p_tenant_id, p_nota_id, v_nota.order_id, p_connection_id, 'cancel', 'queued',\n 'nfce-cancel:' || p_nota_id::text,\n v_nota.metadata #>> '{plugnotas,providerDocumentId}',\n v_nota.metadata #>> '{plugnotas,integrationId}',\n jsonb_build_object('reason', v_reason), now())\n ON CONFLICT (tenant_id, idempotency_key) DO UPDATE SET\n provider_document_id = coalesce(\n public.plg_fiscalbr_nfce_jobs.provider_document_id,\n EXCLUDED.provider_document_id\n ),\n integration_id = coalesce(\n public.plg_fiscalbr_nfce_jobs.integration_id,\n EXCLUDED.integration_id\n ),\n updated_at = now()\n RETURNING id INTO v_job_id;\n\n UPDATE public.plg_financial_nfe\n SET metadata = metadata || jsonb_build_object('plugnotas', jsonb_build_object(\n 'jobId', v_job_id, 'jobStatus', 'queued', 'operation', 'cancel', 'cancellationPending', true\n )), updated_at = now()\n WHERE id = p_nota_id AND tenant_id = p_tenant_id;\n RETURN jsonb_build_object('jobId', v_job_id, 'reason', v_reason);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_record_nfce_attempt(\n p_tenant_id uuid,\n p_job_id uuid,\n p_status text,\n p_provider_response jsonb DEFAULT '{}'::jsonb,\n p_error text DEFAULT NULL,\n p_next_attempt_at timestamptz DEFAULT NULL\n) RETURNS void\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n IF p_status NOT IN ('running', 'waiting', 'failed', 'manual_review') THEN\n RAISE EXCEPTION 'plugnotas_record_nfce_attempt: invalid status' USING ERRCODE = '22023';\n END IF;\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = p_status,\n -- One provider dispatch is one attempt. Moving that same attempt from\n -- running to waiting/failed must not count it a second time.\n attempts = attempts + CASE WHEN p_status = 'running' THEN 1 ELSE 0 END,\n provider_response = coalesce(p_provider_response, '{}'::jsonb),\n last_error = p_error, next_attempt_at = p_next_attempt_at,\n locked_until = NULL, updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = p_job_id;\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_apply_nfce_result(\n p_tenant_id uuid,\n p_job_id uuid,\n p_status text,\n p_provider_document_id text DEFAULT NULL,\n p_integration_id text DEFAULT NULL,\n p_number text DEFAULT NULL,\n p_series text DEFAULT NULL,\n p_access_key text DEFAULT NULL,\n p_message text DEFAULT NULL,\n p_provider_response jsonb DEFAULT '{}'::jsonb\n) RETURNS uuid\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_document_status text;\nBEGIN\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE tenant_id = p_tenant_id AND id = p_job_id FOR UPDATE;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: job not found' USING ERRCODE = 'P0002';\n END IF;\n IF p_status NOT IN ('processing', 'issued', 'cancelled', 'error') THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: invalid status' USING ERRCODE = '22023';\n END IF;\n\n v_document_status := CASE\n WHEN v_job.operation = 'cancel' AND p_status = 'processing' THEN 'issued'\n ELSE p_status\n END;\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = CASE\n WHEN p_status IN ('issued', 'cancelled') THEN 'succeeded'\n WHEN p_status = 'error' THEN 'failed'\n ELSE 'waiting'\n END,\n provider_document_id = coalesce(p_provider_document_id, provider_document_id),\n integration_id = coalesce(p_integration_id, integration_id),\n provider_response = coalesce(p_provider_response, '{}'::jsonb),\n last_error = CASE WHEN p_status = 'error' THEN p_message ELSE NULL END,\n next_attempt_at = CASE WHEN p_status = 'processing' THEN now() + interval '2 minutes' ELSE NULL END,\n locked_until = NULL, updated_at = now()\n WHERE id = p_job_id;\n\n UPDATE public.plg_financial_nfe\n SET status = v_document_status,\n number = coalesce(p_number, number),\n series = coalesce(p_series, series),\n access_key = coalesce(p_access_key, access_key),\n issued_at = CASE WHEN p_status = 'issued' THEN coalesce(issued_at, now()) ELSE issued_at END,\n error_message = CASE WHEN p_status = 'error' THEN p_message ELSE NULL END,\n metadata = metadata || jsonb_build_object('plugnotas', jsonb_strip_nulls(jsonb_build_object(\n 'jobId', p_job_id,\n 'jobStatus', CASE WHEN p_status IN ('issued', 'cancelled') THEN 'succeeded' WHEN p_status = 'error' THEN 'failed' ELSE 'waiting' END,\n 'operation', v_job.operation,\n 'providerDocumentId', coalesce(p_provider_document_id, v_job.provider_document_id),\n 'integrationId', coalesce(p_integration_id, v_job.integration_id),\n 'cancellationPending', v_job.operation = 'cancel' AND p_status = 'processing'\n ))),\n updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = v_job.nota_id;\n\n INSERT INTO public.plg_fiscalbr_nfce_events (tenant_id, nota_id, job_id, event_type, payload)\n VALUES (p_tenant_id, v_job.nota_id, p_job_id, v_job.operation || '.' || p_status,\n coalesce(p_provider_response, '{}'::jsonb));\n RETURN v_job.nota_id;\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_apply_nfce_webhook(\n p_provider_event_id text,\n p_payload_sha256 text,\n p_provider_document_id text,\n p_status text,\n p_integration_id text DEFAULT NULL,\n p_number text DEFAULT NULL,\n p_series text DEFAULT NULL,\n p_access_key text DEFAULT NULL,\n p_message text DEFAULT NULL,\n p_payload jsonb DEFAULT '{}'::jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_receipt_id bigint;\nBEGIN\n INSERT INTO public.plg_fiscalbr_webhook_receipts\n (provider_event_id, payload_sha256)\n VALUES (p_provider_event_id, p_payload_sha256)\n ON CONFLICT (provider, provider_event_id) DO NOTHING\n RETURNING id INTO v_receipt_id;\n IF v_receipt_id IS NULL THEN RETURN jsonb_build_object('duplicate', true); END IF;\n\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE provider_document_id = p_provider_document_id\n ORDER BY created_at DESC LIMIT 1;\n IF NOT FOUND THEN\n UPDATE public.plg_fiscalbr_webhook_receipts\n SET processed_at = now(), processing_error = 'job_not_found'\n WHERE id = v_receipt_id;\n RETURN jsonb_build_object('duplicate', false, 'matched', false);\n END IF;\n\n UPDATE public.plg_fiscalbr_webhook_receipts\n SET tenant_id = v_job.tenant_id, nota_id = v_job.nota_id, processed_at = now()\n WHERE id = v_receipt_id;\n PERFORM public.plugnotas_apply_nfce_result(\n v_job.tenant_id, v_job.id, p_status, p_provider_document_id,\n coalesce(p_integration_id, v_job.integration_id), p_number, p_series,\n p_access_key, p_message, p_payload\n );\n RETURN jsonb_build_object('duplicate', false, 'matched', true, 'jobId', v_job.id);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_get_artifact_locator(\n p_tenant_id uuid,\n p_nota_id uuid\n) RETURNS jsonb\nLANGUAGE sql SECURITY DEFINER SET search_path = '' STABLE AS $$\n SELECT jsonb_build_object(\n 'notaId', n.id,\n 'status', n.status,\n 'providerDocumentId', n.metadata #>> '{plugnotas,providerDocumentId}',\n 'integrationId', n.metadata #>> '{plugnotas,integrationId}'\n )\n FROM public.plg_financial_nfe n\n WHERE n.tenant_id = p_tenant_id AND n.id = p_nota_id\n AND n.status IN ('issued', 'cancelled');\n$$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_claim_nfce_recovery(\n p_limit integer DEFAULT 20\n) RETURNS SETOF public.plg_fiscalbr_nfce_jobs\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n RETURN QUERY\n WITH candidates AS (\n SELECT j.id FROM public.plg_fiscalbr_nfce_jobs j\n WHERE j.status IN ('queued', 'waiting')\n AND coalesce(j.next_attempt_at, j.created_at) <= now()\n AND coalesce(j.locked_until, '-infinity'::timestamptz) < now()\n ORDER BY coalesce(j.next_attempt_at, j.created_at), j.created_at\n FOR UPDATE SKIP LOCKED\n LIMIT greatest(1, least(coalesce(p_limit, 20), 100))\n )\n UPDATE public.plg_fiscalbr_nfce_jobs j\n SET status = 'running', locked_until = now() + interval '2 minutes', updated_at = now()\n FROM candidates c WHERE j.id = c.id\n RETURNING j.*;\nEND $$;\n\nREVOKE ALL ON FUNCTION public.plugnotas_register_emitter(uuid, uuid, text, text, text, timestamptz, text, boolean) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_disconnect_emitter(uuid, uuid) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_create_nfce_draft_for_order(uuid, uuid) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_prepare_nfce(uuid, uuid, uuid, text) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_prepare_nfce_cancel(uuid, uuid, uuid, text) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_record_nfce_attempt(uuid, uuid, text, jsonb, text, timestamptz) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_apply_nfce_result(uuid, uuid, text, text, text, text, text, text, text, jsonb) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_apply_nfce_webhook(text, text, text, text, text, text, text, text, text, jsonb) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_get_artifact_locator(uuid, uuid) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_claim_nfce_recovery(integer) FROM PUBLIC, anon, authenticated;\n\nGRANT EXECUTE ON FUNCTION public.plugnotas_register_emitter(uuid, uuid, text, text, text, timestamptz, text, boolean) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_disconnect_emitter(uuid, uuid) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_create_nfce_draft_for_order(uuid, uuid) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_prepare_nfce(uuid, uuid, uuid, text) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_prepare_nfce_cancel(uuid, uuid, uuid, text) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_record_nfce_attempt(uuid, uuid, text, jsonb, text, timestamptz) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_apply_nfce_result(uuid, uuid, text, text, text, text, text, text, text, jsonb) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_apply_nfce_webhook(text, text, text, text, text, text, text, text, text, jsonb) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_get_artifact_locator(uuid, uuid) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_claim_nfce_recovery(integer) TO service_role;\n`\n\nexport const MIGRATION_001_PRESERVE_TERMINAL_RESULTS_AND_RECOVER_LEASES = `-- Incremental recovery fix. Preserve 000_baseline.sql and its recorded checksum.\n-- Only existing fiscal functions change; no parallel ledger/schema or backfill.\n-- CREATE OR REPLACE retains the service-role-only ACL from the baseline.\n\nCREATE OR REPLACE FUNCTION public.plugnotas_record_nfce_attempt(\n p_tenant_id uuid,\n p_job_id uuid,\n p_status text,\n p_provider_response jsonb DEFAULT '{}'::jsonb,\n p_error text DEFAULT NULL,\n p_next_attempt_at timestamptz DEFAULT NULL\n) RETURNS void\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n IF p_status NOT IN ('running', 'waiting', 'failed', 'manual_review') THEN\n RAISE EXCEPTION 'plugnotas_record_nfce_attempt: invalid status' USING ERRCODE = '22023';\n END IF;\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = p_status,\n -- One provider dispatch is one attempt. Moving that same attempt from\n -- running to waiting/failed must not count it a second time.\n attempts = attempts + CASE WHEN p_status = 'running' THEN 1 ELSE 0 END,\n provider_response = coalesce(p_provider_response, '{}'::jsonb),\n last_error = p_error, next_attempt_at = p_next_attempt_at,\n locked_until = CASE WHEN p_status = 'running'\n THEN greatest(coalesce(locked_until, now()), now() + interval '2 minutes') ELSE NULL END,\n updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = p_job_id AND status <> 'succeeded';\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_apply_nfce_result(\n p_tenant_id uuid,\n p_job_id uuid,\n p_status text,\n p_provider_document_id text DEFAULT NULL,\n p_integration_id text DEFAULT NULL,\n p_number text DEFAULT NULL,\n p_series text DEFAULT NULL,\n p_access_key text DEFAULT NULL,\n p_message text DEFAULT NULL,\n p_provider_response jsonb DEFAULT '{}'::jsonb\n) RETURNS uuid\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_document_status text;\n v_existing_status text;\n v_job_status text;\nBEGIN\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE tenant_id = p_tenant_id AND id = p_job_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: job not found' USING ERRCODE = 'P0002';\n END IF;\n IF p_status NOT IN ('processing', 'issued', 'cancelled', 'error') THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: invalid status' USING ERRCODE = '22023';\n END IF;\n\n -- Match prepare/cancel's lock order: document, then job.\n SELECT status INTO v_existing_status FROM public.plg_financial_nfe\n WHERE tenant_id = p_tenant_id AND id = v_job.nota_id FOR UPDATE;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: document not found' USING ERRCODE = 'P0002';\n END IF;\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE tenant_id = p_tenant_id AND id = p_job_id FOR UPDATE;\n\n -- Late polling must not regress a concluded document or an active cancellation.\n IF v_existing_status = 'cancelled'\n OR (v_job.operation = 'issue' AND v_existing_status = 'issued' AND p_status <> 'cancelled')\n OR (v_job.status = 'succeeded' AND p_status IN ('processing', 'error')) THEN\n -- Old/interrupted jobs may still be running after the document concluded.\n -- Settle their lease too, otherwise recovery would claim them forever.\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = 'succeeded', locked_until = NULL, next_attempt_at = NULL, updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = p_job_id;\n RETURN v_job.nota_id;\n END IF;\n\n v_job_status := CASE\n WHEN p_status = 'cancelled' OR (v_job.operation = 'issue' AND p_status = 'issued') THEN 'succeeded'\n WHEN p_status = 'error' THEN 'failed'\n ELSE 'waiting' END;\n v_document_status := CASE\n WHEN v_job.operation = 'cancel' AND p_status <> 'cancelled' THEN v_existing_status\n ELSE p_status\n END;\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = v_job_status,\n provider_document_id = coalesce(p_provider_document_id, provider_document_id),\n integration_id = coalesce(p_integration_id, integration_id),\n provider_response = coalesce(p_provider_response, '{}'::jsonb),\n last_error = CASE WHEN p_status = 'error' THEN p_message ELSE NULL END,\n next_attempt_at = CASE WHEN v_job_status = 'waiting' THEN now() + interval '2 minutes' ELSE NULL END,\n locked_until = NULL, updated_at = now()\n WHERE id = p_job_id;\n\n UPDATE public.plg_financial_nfe\n SET status = v_document_status,\n number = coalesce(p_number, number),\n series = coalesce(p_series, series),\n access_key = coalesce(p_access_key, access_key),\n issued_at = CASE WHEN p_status = 'issued' THEN coalesce(issued_at, now()) ELSE issued_at END,\n error_message = CASE WHEN v_document_status = 'error' THEN p_message ELSE NULL END,\n metadata = metadata || jsonb_build_object('plugnotas', jsonb_strip_nulls(jsonb_build_object(\n 'jobId', p_job_id,\n 'jobStatus', v_job_status,\n 'operation', v_job.operation,\n 'providerDocumentId', coalesce(p_provider_document_id, v_job.provider_document_id),\n 'integrationId', coalesce(p_integration_id, v_job.integration_id),\n 'cancellationPending', v_job.operation = 'cancel' AND v_job_status = 'waiting'\n ))),\n updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = v_job.nota_id;\n\n INSERT INTO public.plg_fiscalbr_nfce_events (tenant_id, nota_id, job_id, event_type, payload)\n VALUES (p_tenant_id, v_job.nota_id, p_job_id, v_job.operation || '.' || p_status,\n coalesce(p_provider_response, '{}'::jsonb));\n RETURN v_job.nota_id;\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_apply_nfce_webhook(\n p_provider_event_id text,\n p_payload_sha256 text,\n p_provider_document_id text,\n p_status text,\n p_integration_id text DEFAULT NULL,\n p_number text DEFAULT NULL,\n p_series text DEFAULT NULL,\n p_access_key text DEFAULT NULL,\n p_message text DEFAULT NULL,\n p_payload jsonb DEFAULT '{}'::jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_receipt_id bigint;\n v_receipt public.plg_fiscalbr_webhook_receipts%ROWTYPE;\nBEGIN\n INSERT INTO public.plg_fiscalbr_webhook_receipts\n (provider_event_id, payload_sha256)\n VALUES (p_provider_event_id, p_payload_sha256)\n ON CONFLICT (provider, provider_event_id) DO NOTHING\n RETURNING id INTO v_receipt_id;\n SELECT * INTO v_receipt FROM public.plg_fiscalbr_webhook_receipts\n WHERE provider = 'plugnotas' AND provider_event_id = p_provider_event_id FOR UPDATE;\n v_receipt_id := v_receipt.id;\n IF v_receipt.payload_sha256 IS DISTINCT FROM p_payload_sha256 THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_webhook: conflicting event payload' USING ERRCODE = '22023';\n END IF;\n IF v_receipt.processed_at IS NOT NULL AND v_receipt.processing_error IS NULL THEN\n RETURN jsonb_build_object('duplicate', true, 'matched', true);\n END IF;\n\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE provider_document_id = p_provider_document_id\n ORDER BY created_at DESC LIMIT 1;\n IF NOT FOUND THEN\n UPDATE public.plg_fiscalbr_webhook_receipts\n SET processed_at = NULL, processing_error = 'job_not_found'\n WHERE id = v_receipt_id;\n RETURN jsonb_build_object('duplicate', false, 'matched', false);\n END IF;\n\n UPDATE public.plg_fiscalbr_webhook_receipts\n SET tenant_id = v_job.tenant_id, nota_id = v_job.nota_id, processed_at = now(), processing_error = NULL\n WHERE id = v_receipt_id;\n PERFORM public.plugnotas_apply_nfce_result(\n v_job.tenant_id, v_job.id, p_status, p_provider_document_id,\n coalesce(p_integration_id, v_job.integration_id), p_number, p_series,\n p_access_key, p_message, p_payload\n );\n RETURN jsonb_build_object('duplicate', false, 'matched', true, 'jobId', v_job.id);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_claim_nfce_recovery(\n p_limit integer DEFAULT 20\n) RETURNS SETOF public.plg_fiscalbr_nfce_jobs\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n RETURN QUERY\n WITH candidates AS (\n SELECT j.id FROM public.plg_fiscalbr_nfce_jobs j\n WHERE j.status IN ('queued', 'waiting', 'running')\n AND coalesce(j.next_attempt_at, j.created_at) <= now()\n AND coalesce(j.locked_until, '-infinity'::timestamptz) < now()\n ORDER BY coalesce(j.next_attempt_at, j.created_at), j.created_at\n FOR UPDATE SKIP LOCKED\n LIMIT greatest(1, least(coalesce(p_limit, 20), 100))\n )\n UPDATE public.plg_fiscalbr_nfce_jobs j\n SET status = 'running', locked_until = now() + interval '2 minutes', updated_at = now()\n FROM candidates c WHERE j.id = c.id\n RETURNING j.*;\nEND $$;\n`\n\nexport const MIGRATION_002_A_NOTA_QUE_CHEGA_TEM_ONDE_ESPERAR = `-- A nota que chega tem onde esperar.\n--\n-- O V1 recebe NF-e de fornecedor pela SEFAZ e guarda cada uma numa caixa de\n-- entrada antes de alguém decidir o que fazer com ela: manifestar, importar\n-- para o estoque, ou nada. Essa caixa não tinha destino no V2.\n--\n-- dfe_inbox 703 a nota recebida, com o XML inteiro\n-- dfe_inbox_items 3.215 o item da nota, com todo o tributo\n-- dfe_inbox_payments 739 a forma de pagamento declarada\n-- dfe_inbox_duplicatas 830 o vencimento da duplicata\n-- fiscal_groups 11 o grupo fiscal (CFOP, CST, alíquotas)\n--\n-- Os números somam os dois tenants: Espaço Facial e Pertinho do Céu. É o único\n-- domínio fiscal que os dois usam.\n--\n-- ── O XML é arquivo, e arquivo mora em public.documents ─────────────────────\n--\n-- \\`dfe_inbox.xml_content\\` é o XML inteiro numa coluna de texto, e\n-- \\`pdf_storage_path\\` aponta para o DANFE no storage do V1. Os dois são ARQUIVO,\n-- e o V2 já tem o arquétipo: \\`public.documents\\`, com kind, checksum, storage_*\n-- e a RLS de arquivo que uma coluna de texto nunca teria.\n--\n-- Então a extensão guarda um PONTEIRO — \\`document_id\\` — e os bytes vão para o\n-- arquétipo, pelo estágio de assets (\\`make mig-assets\\`), que é quem alcança\n-- object storage. Enquanto os bytes não chegam, \\`document_id\\` fica nulo e o\n-- caminho de origem fica em metadata: a linha é verdadeira nos dois momentos.\n--\n-- ── O tributo vem inteiro, e de propósito ───────────────────────────────────\n--\n-- 30 colunas de imposto por item (ICMS, ICMS-ST, PIS, COFINS, IPI, com base,\n-- alíquota e valor de cada). É muita coluna, e a tentação é jogar tudo num\n-- jsonb. Não: isto é documento fiscal recebido, e a pergunta que se faz dele é\n-- \"quanto de ICMS entrou neste mês\" — uma soma, sobre coluna, com índice. Um\n-- jsonb transformaria toda apuração numa varredura.\n--\n-- O que VAI para jsonb é o \\`raw_xml_item\\`, que já é jsonb na origem e existe\n-- para conferência, não para conta.\n--\n-- Idempotente.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_inbox_documents (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n unit_id uuid,\n -- O ponteiro para o arquétipo. Nulo enquanto os bytes não subiram — o\n -- caminho de origem fica em metadata até lá.\n document_id uuid,\n access_key text,\n nfe_number text,\n nfe_series text,\n nfe_model text,\n issue_date timestamp with time zone,\n received_at timestamp with time zone,\n status text DEFAULT 'received'::text NOT NULL,\n -- A manifestação do destinatário é outro eixo que o status: uma nota pode\n -- estar recebida e não manifestada, e é a manifestação que a SEFAZ cobra.\n manifestation_status text,\n manifested_at timestamp with time zone,\n manifestation_attempts integer DEFAULT 0 NOT NULL,\n manifestation_response jsonb,\n supplier_party_id uuid,\n supplier_cnpj text,\n supplier_name text,\n supplier_ie text,\n total_value numeric(14,2),\n total_products numeric(14,2),\n total_discount numeric(14,2),\n total_freight numeric(14,2),\n total_insurance numeric(14,2),\n total_other numeric(14,2),\n total_icms_base numeric(14,2),\n total_icms_value numeric(14,2),\n total_icms_st_base numeric(14,2),\n total_icms_st_value numeric(14,2),\n total_pis_value numeric(14,2),\n total_cofins_value numeric(14,2),\n total_ipi_value numeric(14,2),\n nfe_protocol text,\n nfe_authorized_at timestamp with time zone,\n carrier_name text,\n carrier_cnpj text,\n freight_mode_code text,\n additional_info text,\n reviewed_at timestamp with time zone,\n -- O que essa nota virou no estoque, quando virou. Nulo é nota recebida e\n -- não importada, que é a maioria.\n inventory_operation_id uuid,\n owner_id uuid,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE public.plg_fiscalbr_inbox_documents IS\n 'A NF-e de fornecedor recebida da SEFAZ, esperando manifestação ou importação. V1: dfe_inbox.';\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_documents.document_id IS\n 'V1: xml_content + pdf_storage_path. O XML e o DANFE são arquivo; os bytes moram em public.documents e aqui fica o ponteiro.';\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_inbox_items (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n inbox_document_id uuid NOT NULL,\n item_number integer,\n supplier_product_code text,\n ean_barcode text,\n ean_taxable text,\n description text,\n ncm text,\n cest text,\n cfop text,\n unit_commercial text,\n unit_taxable text,\n quantity_commercial numeric(18,4),\n quantity_taxable numeric(18,4),\n unit_price_commercial numeric(18,6),\n unit_price_taxable numeric(18,6),\n total_price numeric(14,2),\n discount numeric(14,2),\n freight numeric(14,2),\n insurance numeric(14,2),\n other_expenses numeric(14,2),\n icms_cst text, icms_csosn text, icms_origin text,\n icms_base numeric(14,2), icms_rate numeric(9,4), icms_value numeric(14,2),\n icms_st_base numeric(14,2), icms_st_value numeric(14,2),\n pis_cst text, pis_base numeric(14,2), pis_rate numeric(9,4), pis_value numeric(14,2),\n cofins_cst text, cofins_base numeric(14,2), cofins_rate numeric(9,4), cofins_value numeric(14,2),\n ipi_cst text, ipi_rate numeric(9,4), ipi_value numeric(14,2),\n -- O produto do V2 que esta linha da nota representa. \\`reconciled\\` é a\n -- decisão de quem conferiu; o id é o resultado dela.\n product_id uuid,\n reconciled boolean DEFAULT false NOT NULL,\n raw_xml_item jsonb,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE public.plg_fiscalbr_inbox_items IS\n 'O item da NF-e recebida, com o tributo em coluna — a apuração soma coluna, não varre jsonb. V1: dfe_inbox_items.';\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_inbox_payments (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n inbox_document_id uuid NOT NULL,\n payment_index integer,\n payment_indicator text,\n payment_type_code text,\n payment_type_label text,\n value numeric(14,2),\n change_given numeric(14,2),\n card_brand text,\n card_acquirer_cnpj text,\n card_auth_code text,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_inbox_duplicates (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n inbox_document_id uuid NOT NULL,\n duplicate_index integer,\n number text,\n due_date date,\n value numeric(14,2),\n -- O que essa duplicata virou no contas a pagar, se alguém a lançou.\n installment_id uuid,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE public.plg_fiscalbr_inbox_duplicates IS\n 'O vencimento declarado na NF-e recebida. Vira parcela do contas a pagar quando alguém lança a nota. V1: dfe_inbox_duplicatas.';\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_tax_groups (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n name text NOT NULL,\n cfop text,\n csosn text,\n cst text,\n icms_origin text,\n icms_rate numeric(9,4),\n icms_bc_mode text,\n pis_situation text,\n pis_rate numeric(9,4),\n cofins_situation text,\n cofins_rate numeric(9,4),\n -- A reforma tributária já está no cadastro do V1 e vem junto: deixar de\n -- fora obrigaria a recadastrar tudo no dia em que IBS/CBS valerem.\n ibs_cbs_situation text,\n ibs_cbs_classification text,\n base_calculation_mode text,\n benefit_code text,\n cest text,\n poverty_fund_rate numeric(9,4),\n is_active boolean DEFAULT true NOT NULL,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE public.plg_fiscalbr_tax_groups IS\n 'O grupo fiscal: CFOP, CST/CSOSN e alíquotas que o produto herda na emissão. V1: fiscal_groups. Traz IBS/CBS porque o cadastro do V1 já os tem.';\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- As chaves, os índices e a cerca\n-- ═══════════════════════════════════════════════════════════════════════════\n\nDO $$\nDECLARE t text;\nBEGIN\n FOREACH t IN ARRAY ARRAY['plg_fiscalbr_inbox_documents', 'plg_fiscalbr_inbox_items',\n 'plg_fiscalbr_inbox_payments', 'plg_fiscalbr_inbox_duplicates',\n 'plg_fiscalbr_tax_groups'] LOOP\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conrelid = ('public.' || t)::regclass AND contype = 'p') THEN\n EXECUTE format('ALTER TABLE ONLY public.%I ADD CONSTRAINT %I PRIMARY KEY (id)', t, t || '_pkey');\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = t || '_tenant_id_id_key') THEN\n EXECUTE format('ALTER TABLE ONLY public.%I ADD CONSTRAINT %I UNIQUE (tenant_id, id)', t, t || '_tenant_id_id_key');\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = t || '_tenant_fkey') THEN\n EXECUTE format('ALTER TABLE ONLY public.%I ADD CONSTRAINT %I FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE', t, t || '_tenant_fkey');\n END IF;\n END LOOP;\nEND $$;\n\nDO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_documents_unit_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_documents ADD CONSTRAINT plg_fiscalbr_inbox_documents_unit_fkey\n FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\n END IF;\n -- O arquivo pode ser apagado sem levar a nota junto: a nota fiscal existe\n -- mesmo sem o XML à mão, e é ela que a SEFAZ conhece.\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_documents_document_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_documents ADD CONSTRAINT plg_fiscalbr_inbox_documents_document_fkey\n FOREIGN KEY (document_id) REFERENCES public.documents(id) ON DELETE SET NULL;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_documents_supplier_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_documents ADD CONSTRAINT plg_fiscalbr_inbox_documents_supplier_fkey\n FOREIGN KEY (supplier_party_id) REFERENCES public.people(id) ON DELETE SET NULL;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_documents_operation_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_documents ADD CONSTRAINT plg_fiscalbr_inbox_documents_operation_fkey\n FOREIGN KEY (inventory_operation_id) REFERENCES public.plg_inventory_operations(id) ON DELETE SET NULL;\n END IF;\n\n -- Item, pagamento e duplicata não existem fora da nota: CASCADE.\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_document_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_items ADD CONSTRAINT plg_fiscalbr_inbox_items_document_fkey\n FOREIGN KEY (tenant_id, inbox_document_id) REFERENCES public.plg_fiscalbr_inbox_documents(tenant_id, id) ON DELETE CASCADE;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_product_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_items ADD CONSTRAINT plg_fiscalbr_inbox_items_product_fkey\n FOREIGN KEY (product_id) REFERENCES public.products(id) ON DELETE SET NULL;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_payments_document_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_payments ADD CONSTRAINT plg_fiscalbr_inbox_payments_document_fkey\n FOREIGN KEY (tenant_id, inbox_document_id) REFERENCES public.plg_fiscalbr_inbox_documents(tenant_id, id) ON DELETE CASCADE;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_duplicates_document_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_duplicates ADD CONSTRAINT plg_fiscalbr_inbox_duplicates_document_fkey\n FOREIGN KEY (tenant_id, inbox_document_id) REFERENCES public.plg_fiscalbr_inbox_documents(tenant_id, id) ON DELETE CASCADE;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_duplicates_installment_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_duplicates ADD CONSTRAINT plg_fiscalbr_inbox_duplicates_installment_fkey\n FOREIGN KEY (installment_id) REFERENCES public.plg_financial_invoice_installments(id) ON DELETE SET NULL;\n END IF;\nEND $$;\n\n-- A chave de acesso é única por casa: a mesma nota chegando duas vezes da SEFAZ\n-- é a mesma nota, e é isso que impede a importação em dobro.\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_inbox_documents_access_key_uidx\n ON public.plg_fiscalbr_inbox_documents USING btree (tenant_id, access_key)\n WHERE access_key IS NOT NULL;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_documents_pending_idx\n ON public.plg_fiscalbr_inbox_documents USING btree (tenant_id, unit_id, issue_date DESC)\n WHERE inventory_operation_id IS NULL;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_items_document_idx\n ON public.plg_fiscalbr_inbox_items USING btree (tenant_id, inbox_document_id);\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_items_product_idx\n ON public.plg_fiscalbr_inbox_items USING btree (tenant_id, product_id) WHERE product_id IS NOT NULL;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_payments_document_idx\n ON public.plg_fiscalbr_inbox_payments USING btree (tenant_id, inbox_document_id);\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_duplicates_document_idx\n ON public.plg_fiscalbr_inbox_duplicates USING btree (tenant_id, inbox_document_id);\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_tax_groups_name_uidx\n ON public.plg_fiscalbr_tax_groups USING btree (tenant_id, lower(name));\n\nDO $$\nDECLARE t text;\nBEGIN\n FOREACH t IN ARRAY ARRAY['plg_fiscalbr_inbox_documents', 'plg_fiscalbr_inbox_items',\n 'plg_fiscalbr_inbox_payments', 'plg_fiscalbr_inbox_duplicates',\n 'plg_fiscalbr_tax_groups'] LOOP\n EXECUTE format('DROP TRIGGER IF EXISTS %I ON public.%I', t || '_updated_at', t);\n EXECUTE format('CREATE TRIGGER %I BEFORE UPDATE ON public.%I FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at()', t || '_updated_at', t);\n END LOOP;\nEND $$;\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- Quem enxerga\n-- ═══════════════════════════════════════════════════════════════════════════\n--\n-- Nota fiscal é do FINANCEIRO, e a permissão é a que ele já usa. A caixa de\n-- entrada não tem unidade nos filhos — eles herdam a da nota —, então o escopo\n-- de unidade vale só no documento; o resto é do tenant, e é a CASCADE da FK que\n-- garante que ninguém veja filho de nota alheia.\n-- RLS, uma a uma e por extenso. O laço adiante já liga tudo isto — mas ele liga\n-- por \\`EXECUTE format(...)\\`, e o portão que revisa plugin lê o ARQUIVO, não o\n-- banco: para ele, tabela com tenant_id e sem um ENABLE literal é tabela\n-- aberta. Uma garantia que o revisor não consegue ler é uma garantia que\n-- ninguém confere.\nALTER TABLE public.plg_fiscalbr_inbox_documents ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_inbox_items ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_tax_groups ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_inbox_payments ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_inbox_duplicates ENABLE ROW LEVEL SECURITY;\n\nDO $$\nDECLARE\n t text;\n doc boolean;\nBEGIN\n FOREACH t IN ARRAY ARRAY['plg_fiscalbr_inbox_documents', 'plg_fiscalbr_inbox_items',\n 'plg_fiscalbr_inbox_payments', 'plg_fiscalbr_inbox_duplicates',\n 'plg_fiscalbr_tax_groups'] LOOP\n doc := t = 'plg_fiscalbr_inbox_documents';\n EXECUTE format('ALTER TABLE public.%I FORCE ROW LEVEL SECURITY', t);\n EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', t);\n EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE public.%I TO authenticated', t);\n EXECUTE format('GRANT ALL ON TABLE public.%I TO service_role', t);\n\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_authz_select', t);\n EXECUTE format($f$CREATE POLICY %I ON public.%I FOR SELECT TO authenticated USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (%s)\n AND (SELECT app.has_permission('financial.read', %s)))$f$,\n t || '_authz_select', t,\n CASE WHEN doc THEN format('unit_id IS NULL OR (SELECT app.has_unit(%I.unit_id))', t) ELSE 'true' END,\n CASE WHEN doc THEN format('%I.unit_id', t) ELSE 'NULL::uuid' END);\n\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_authz_write', t);\n EXECUTE format($f$CREATE POLICY %I ON public.%I FOR ALL TO authenticated USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.edit', %s)))\n WITH CHECK (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.edit', %s)))$f$,\n t || '_authz_write', t,\n CASE WHEN doc THEN format('%I.unit_id', t) ELSE 'NULL::uuid' END,\n CASE WHEN doc THEN format('%I.unit_id', t) ELSE 'NULL::uuid' END);\n END LOOP;\nEND $$;\n\nINSERT INTO public.scoped_resources (resource_table, unit_column, owner_column, shareable, default_visibility, label)\nVALUES ('plg_fiscalbr_inbox_documents', 'unit_id', 'owner_id', false, 'unit', 'Notas recebidas')\nON CONFLICT (resource_table) DO UPDATE\n SET unit_column = EXCLUDED.unit_column, default_visibility = EXCLUDED.default_visibility, label = EXCLUDED.label;\n`\n\nexport const MIGRATION_003_A_CAIXA_DE_ENTRADA_ATRAVESSA = `-- A caixa de entrada atravessa.\n--\n-- A 002 fez as cinco tabelas. Esta escreve o de-para. As cinco usam o writer\n-- genérico \\`by_shape\\` (spine 123): as colunas do destino foram desenhadas\n-- olhando a origem, então o que falta é dizer qual nome vira qual — não uma\n-- função de upsert por tabela.\n--\n-- ── O arquivo não vem por aqui ──────────────────────────────────────────────\n--\n-- \\`xml_content\\` guarda o XML inteiro e \\`pdf_storage_path\\` aponta para o DANFE.\n-- Os dois saem do de-para com \\`-\\`: arquivo atravessa pelo estágio de assets,\n-- que é quem alcança object storage, e vira linha de \\`public.documents\\`. O\n-- caminho de origem fica em metadata para o estágio achar.\n--\n-- ── O fornecedor fica para a costura ────────────────────────────────────────\n--\n-- \\`supplier_party_id\\` não é preenchido aqui. A origem guarda CNPJ e nome, não\n-- um id de contato, e casar CNPJ com \\`public.people\\` é uma decisão de\n-- identidade — a mesma que já pôs 438 clientes em quarentena. Fica nulo, com o\n-- CNPJ na coluna ao lado, e uma passada de costura resolve quando alguém\n-- decidir a regra.\n--\n-- Idempotente.\n\nSET LOCAL migration.allowlist_unlock = 'on';\n\nSELECT migration._allow(\n 'fiscal_groups', 'public.plg_fiscalbr_tax_groups', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_tax_groups'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'name', 'name',\n 'cfop', 'cfop',\n 'csosn', 'csosn',\n 'cst', 'cst',\n 'icms_origin', 'icms_origin',\n 'icms_rate', 'icms_rate',\n 'icms_modalidade_bc', 'icms_bc_mode',\n 'pis_situation', 'pis_situation',\n 'pis_rate', 'pis_rate',\n 'cofins_situation', 'cofins_situation',\n 'cofins_rate', 'cofins_rate',\n 'ibs_cbs_situation', 'ibs_cbs_situation',\n 'ibs_cbs_classification', 'ibs_cbs_classification',\n 'base_calculation_mode', 'base_calculation_mode',\n 'cbenef', 'benefit_code',\n 'cest', 'cest',\n 'poverty_fund_rate', 'poverty_fund_rate',\n 'active', 'is_active',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'O grupo fiscal: CFOP, CST/CSOSN e alíquotas que o produto herda na emissão. '\n 'IBS/CBS vêm junto porque o cadastro do V1 já os tem — deixar de fora '\n 'obrigaria a recadastrar tudo no dia em que a reforma valer.'\n);\n\nSELECT migration._allow(\n 'dfe_inbox', 'public.plg_fiscalbr_inbox_documents', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_inbox_documents'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'company_id', 'unit_id@companies',\n 'access_key', 'access_key',\n 'nfe_number', 'nfe_number',\n 'nfe_series', 'nfe_series',\n 'nfe_model', 'nfe_model',\n 'issue_date', 'issue_date',\n 'received_at', 'received_at',\n 'status', 'status',\n 'manifestation_status', 'manifestation_status',\n 'manifested_at', 'manifested_at',\n 'manifestation_attempts', 'manifestation_attempts',\n 'manifestation_response', 'manifestation_response',\n 'supplier_cnpj', 'supplier_cnpj',\n 'supplier_name', 'supplier_name',\n 'supplier_ie', 'supplier_ie',\n 'total_value', 'total_value',\n 'total_products', 'total_products',\n 'total_discount', 'total_discount',\n 'total_freight', 'total_freight',\n 'total_insurance', 'total_insurance',\n 'total_other', 'total_other',\n 'total_icms_base', 'total_icms_base',\n 'total_icms_value', 'total_icms_value',\n 'total_icms_st_base', 'total_icms_st_base',\n 'total_icms_st_value', 'total_icms_st_value',\n 'total_pis_value', 'total_pis_value',\n 'total_cofins_value', 'total_cofins_value',\n 'total_ipi_value', 'total_ipi_value',\n 'nfe_protocol', 'nfe_protocol') ||\n -- \\`jsonb_build_object\\` aceita no máximo 100 argumentos, e este de-para tem\n -- 59 pares. Dois objetos concatenados, e não uma tabela a menos.\n jsonb_build_object(\n 'nfe_authorized_at', 'nfe_authorized_at',\n 'carrier_name', 'carrier_name',\n 'carrier_cnpj', 'carrier_cnpj',\n 'freight_mode_code', 'freight_mode_code',\n 'additional_info', 'additional_info',\n 'reviewed_at', 'reviewed_at',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'reviewed_by', '-',\n 'xml_content', '-',\n 'pdf_storage_path', 'jsonb:fiscalbr.v1_pdf_path',\n 'pdf_fetched_at', 'jsonb:fiscalbr.v1_pdf_fetched_at',\n 'danfe_import_id', 'jsonb:fiscalbr.v1_danfe_import_ref',\n 'plugnotas_payload', 'jsonb:fiscalbr.v1_plugnotas_payload',\n 'plugnotas_received_at', 'jsonb:fiscalbr.v1_plugnotas_received_at',\n 'nfe_cnf', 'jsonb:fiscalbr.nfe.cnf',\n 'nfe_natureza_operacao', 'jsonb:fiscalbr.nfe.natureza_operacao',\n 'nfe_finalidade', 'jsonb:fiscalbr.nfe.finalidade',\n 'nfe_tipo_operacao', 'jsonb:fiscalbr.nfe.tipo_operacao',\n 'nfe_destination', 'jsonb:fiscalbr.nfe.destination',\n 'supplier_address', 'jsonb:fiscalbr.supplier.street',\n 'supplier_number', 'jsonb:fiscalbr.supplier.number',\n 'supplier_complement', 'jsonb:fiscalbr.supplier.complement',\n 'supplier_neighborhood', 'jsonb:fiscalbr.supplier.neighborhood',\n 'supplier_city', 'jsonb:fiscalbr.supplier.city',\n 'supplier_state', 'jsonb:fiscalbr.supplier.state',\n 'supplier_postal_code', 'jsonb:fiscalbr.supplier.postal_code',\n 'supplier_phone', 'jsonb:fiscalbr.supplier.phone',\n 'supplier_email', 'jsonb:fiscalbr.supplier.email',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'A NF-e de fornecedor recebida da SEFAZ. \\`xml_content\\` sai com \\`-\\`: arquivo '\n 'atravessa pelo estágio de assets e vira public.documents, e o caminho do '\n 'DANFE fica em metadata para o estágio achar. O endereço do fornecedor vai '\n 'para metadata porque o fornecedor é \\`public.people\\`, e duplicá-lo em coluna '\n 'daria duas respostas para \"onde ele fica\".'\n);\n\nSELECT migration._allow(\n 'dfe_inbox_items', 'public.plg_fiscalbr_inbox_items', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_inbox_items'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'dfe_inbox_id', 'inbox_document_id@dfe_inbox',\n 'item_number', 'item_number',\n 'product_code_supplier', 'supplier_product_code',\n 'ean_barcode', 'ean_barcode',\n 'ean_trib', 'ean_taxable',\n 'description', 'description',\n 'ncm', 'ncm',\n 'cest', 'cest',\n 'cfop', 'cfop',\n 'unit_commercial', 'unit_commercial',\n 'unit_taxable', 'unit_taxable',\n 'quantity_commercial', 'quantity_commercial',\n 'quantity_taxable', 'quantity_taxable',\n 'unit_price_commercial', 'unit_price_commercial',\n 'unit_price_taxable', 'unit_price_taxable',\n 'total_price', 'total_price',\n 'discount', 'discount',\n 'freight', 'freight',\n 'insurance', 'insurance',\n 'other_expenses', 'other_expenses',\n 'icms_cst', 'icms_cst',\n 'icms_csosn', 'icms_csosn',\n 'icms_origin', 'icms_origin',\n 'icms_base', 'icms_base',\n 'icms_rate', 'icms_rate',\n 'icms_value', 'icms_value',\n 'icms_st_base', 'icms_st_base',\n 'icms_st_value', 'icms_st_value',\n 'pis_cst', 'pis_cst',\n 'pis_base', 'pis_base',\n 'pis_rate', 'pis_rate',\n 'pis_value', 'pis_value',\n 'cofins_cst', 'cofins_cst',\n 'cofins_base', 'cofins_base',\n 'cofins_rate', 'cofins_rate',\n 'cofins_value', 'cofins_value',\n 'ipi_cst', 'ipi_cst',\n 'ipi_rate', 'ipi_rate',\n 'ipi_value', 'ipi_value',\n 'linked_product_id', 'product_id@products',\n 'reconciled', 'reconciled',\n 'raw_xml_item', 'raw_xml_item',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'O item da nota, com o tributo em COLUNA — a apuração soma coluna, não varre '\n 'jsonb. \\`raw_xml_item\\` é a exceção: já é jsonb na origem e serve para '\n 'conferência, não para conta.'\n);\n\nSELECT migration._allow(\n 'dfe_inbox_payments', 'public.plg_fiscalbr_inbox_payments', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_inbox_payments'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'dfe_inbox_id', 'inbox_document_id@dfe_inbox',\n 'payment_index', 'payment_index',\n 'indicador_pagamento', 'payment_indicator',\n 'tipo_pagamento_code', 'payment_type_code',\n 'tipo_pagamento_label', 'payment_type_label',\n 'value', 'value',\n 'troco', 'change_given',\n 'card_flag', 'card_brand',\n 'card_acquirer_cnpj', 'card_acquirer_cnpj',\n 'card_auth_code', 'card_auth_code',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'A forma de pagamento declarada na nota recebida.'\n);\n\nSELECT migration._allow(\n 'dfe_inbox_duplicatas', 'public.plg_fiscalbr_inbox_duplicates', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_inbox_duplicates'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'dfe_inbox_id', 'inbox_document_id@dfe_inbox',\n 'duplicata_index', 'duplicate_index',\n 'numero', 'number',\n 'vencimento', 'due_date',\n 'valor', 'value',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'O vencimento declarado na nota. Vira parcela do contas a pagar quando alguém '\n 'lança a nota — \\`installment_id\\` fica nulo até lá, porque a parcela é '\n 'decisão de quem lança, não da SEFAZ.'\n);\n\nDELETE FROM migration.excluded_tables\n WHERE source_table IN ('dfe_inbox', 'dfe_inbox_items', 'dfe_inbox_payments',\n 'dfe_inbox_duplicatas', 'fiscal_groups');\n\nRESET migration.allowlist_unlock;\n`\n\nexport const MIGRATION_004_O_GRUPO_FISCAL_DO_V1_REPETE_NOME = `-- O grupo fiscal do V1 repete nome.\n--\n-- A 002 criou índice ÚNICO em \\`(tenant_id, lower(name))\\`. O V1 tem, no tenant\n-- 8, \"Bebidas Alcoólicas\", \"Bebidas Não Alcoólicas\" e \"Vinhos e Espumantes\"\n-- DUAS vezes cada — grupos fiscais diferentes com o mesmo rótulo, e o V1\n-- permite. Três das onze linhas foram para a quarentena por uma regra que eu\n-- inventei, não que a origem tenha.\n--\n-- O índice vira comum: serve para buscar, não para proibir. Quem quiser proibir\n-- decide isso na tela, com o dado já dentro — e sabendo quais três são.\n--\n-- Esta correção nasceu dentro de \\`financial/083\\` e mudou de arquivo: o\n-- financeiro roda ANTES do fiscal_br na corrente, e um arquivo do financeiro\n-- que mexe numa tabela do fiscal_br falha do zero com\n-- \\`relation \"public.plg_fiscalbr_tax_groups\" does not exist\\`. Cada plugin mexe\n-- na tabela que é dele.\n--\n-- Idempotente.\n\nDROP INDEX IF EXISTS public.plg_fiscalbr_tax_groups_name_uidx;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_tax_groups_name_idx\n ON public.plg_fiscalbr_tax_groups USING btree (tenant_id, lower(name));\n`\n\nexport const MIGRATION_005_A_NOTA_EMITIDA_E_UM_DOCUMENTO = `-- A nota emitida é um DOCUMENTO, e o documento já tem arquétipo.\n--\n-- O V1 do Pertinho do Céu emitiu 496 notas (todas NFC-e: 440 concluídas, 51\n-- rejeitadas, 5 com erro) e nenhuma delas tem onde morar no V2. O que existe\n-- hoje aqui é a caixa de ENTRADA (\\`plg_fiscalbr_inbox_*\\`, a nota que chega do\n-- fornecedor) e o JOB de saída (\\`plg_fiscalbr_nfce_jobs\\`, a tentativa de\n-- emitir). Falta o resultado: a nota que a casa emitiu, com chave, protocolo e\n-- XML.\n--\n-- ── Por que pendurar em \\`public.documents\\` e não numa tabela solta ─────────\n--\n-- Porque a pergunta que o operador faz não é \"quais notas fiscais existem\",\n-- é \"o que foi emitido sobre ESTE pedido\". Hoje a resposta está espalhada:\n-- o anexo do título está em \\`documents\\`, o formulário está em \\`documents\\`, a\n-- foto do ponto está em \\`documents\\` — e a nota fiscal ficaria de fora, sendo\n-- o documento mais documento de todos.\n--\n-- \\`documents\\` é o arquétipo: \\`kind\\` diz a espécie, \\`subject_type\\`/\\`subject_id\\`\n-- dizem sobre o quê, e o plugin pendura o que só ele entende numa extensão 1:1\n-- pela chave — exatamente como \\`plg_forms_documents\\` já faz. Esta migração\n-- segue esse padrão, não inventa outro.\n--\n-- ── O que entra e o que NÃO entra ─────────────────────────────────────────\n--\n-- ENTRA o artefato legal e a trilha:\n-- xml_content 113 de 496 preenchidos, 618 kB no total (5,6 kB cada).\n-- É a prova da emissão e não se regenera. Fica.\n-- os quatro payloads 108 kB para as 496 notas inteiras. É a conversa com a\n-- SEFAZ, e é ela que explica as 51 rejeições.\n-- pdf_storage_path 84 de 496. Vira \\`documents.storage_path\\` com\n-- \\`storage_provider = 'v1-pending'\\`, a mesma convenção\n-- que \\`upsert_document\\` usa: o REGISTRO chegou, os bytes\n-- ainda não.\n--\n-- NÃO entra nada que o V2 já saiba responder por conta própria, e a emissão\n-- nova do V2 continua nascendo por \\`plg_fiscalbr_nfce_jobs\\` — este arquivo é o\n-- destino do resultado, não um segundo caminho de emissão.\n--\n-- ── Os dois ponteiros da nota do V1, que não são o mesmo ──────────────────\n--\n-- fiscal_documents.order_id 496 de 496 — a COMANDA (\\`table_orders\\`)\n-- fiscal_documents.invoice_id 118 de 496 — a VENDA (\\`invoices\\`)\n--\n-- Os dois chegam em \\`public.orders\\` no V2, e às vezes na MESMA linha (a\n-- comanda que virou nota adota a venda). Guardar os dois na mesma coluna\n-- perderia justamente a distinção: \\`order_id\\` na extensão é a comanda; a venda\n-- vai para \\`plg_fiscalbr_document_orders\\`, que é N:N porque uma nota pode\n-- juntar várias (511 vínculos para 496 notas).\n--\n-- Idempotente.\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 1. A espécie entra no vocabulário\n-- ═══════════════════════════════════════════════════════════════════════════\n-- \\`migration.upsert_document\\` RECUSA espécie que não esteja aqui, e faz certo:\n-- é o registro que impede \\`kind\\` de virar campo livre.\n\nINSERT INTO public.document_kinds (kind, plugin, description, statuses, status)\nVALUES ('fiscal_document', 'fiscal_br',\n 'A nota fiscal que a casa EMITIU (NFC-e, NF-e, NFS-e), com chave, protocolo e XML',\n ARRAY['draft','processing','authorized','rejected','error','cancelled','substituted'],\n 'declared')\nON CONFLICT (kind) DO UPDATE\n SET plugin = EXCLUDED.plugin,\n description = EXCLUDED.description,\n statuses = EXCLUDED.statuses,\n updated_at = now();\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 2. A extensão: o que só o fiscal entende\n-- ═══════════════════════════════════════════════════════════════════════════\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_documents (\n -- A chave É o documento. Não há id próprio: a nota e o documento são a mesma\n -- coisa vista de dois lugares, e um segundo id só criaria a chance de eles\n -- discordarem.\n document_id uuid PRIMARY KEY REFERENCES public.documents(id) ON DELETE CASCADE,\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n unit_id uuid,\n -- A comanda/pedido que originou a emissão.\n order_id uuid REFERENCES public.orders(id) ON DELETE SET NULL,\n model text NOT NULL,\n environment text,\n status text NOT NULL,\n series text,\n number text,\n -- 44 dígitos. Sem CHECK de formato: uma nota REJEITADA não tem chave, e uma\n -- chave que a SEFAZ devolveu torta é informação, não erro de digitação.\n access_key text,\n verification_code text,\n protocol text,\n provider text,\n provider_document_id text,\n provider_integration_id text,\n total_value numeric(14,2),\n iss_value numeric(14,2),\n recipient_snapshot jsonb,\n request_payload jsonb,\n response_payload jsonb,\n status_payload jsonb,\n rejection_payload jsonb,\n source_snapshot jsonb,\n -- O artefato legal. 5,6 kB por nota nas 113 que o têm; não se regenera.\n xml text,\n authorized_at timestamptz,\n last_polled_at timestamptz,\n emitted_by_user_id uuid,\n cancelled_at timestamptz,\n cancel_reason text,\n cancelled_by_user_id uuid,\n -- A cadeia de substituição. Auto-referência, então SET NULL: apagar a nota\n -- substituída não pode arrastar a que a substituiu.\n substitutes_document_id uuid REFERENCES public.plg_fiscalbr_documents(document_id) ON DELETE SET NULL,\n substituted_by_document_id uuid REFERENCES public.plg_fiscalbr_documents(document_id) ON DELETE SET NULL,\n observations text,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\n\nDO $$ BEGIN\n ALTER TABLE public.plg_fiscalbr_documents\n ADD CONSTRAINT plg_fiscalbr_documents_unit_fkey\n FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\nEXCEPTION WHEN duplicate_object THEN NULL; END $$;\n\n-- A chave de acesso é única POR INQUILINO e só quando existe: 56 das 496 notas\n-- do Pertinho não têm chave nenhuma (rejeitadas e com erro), e um UNIQUE\n-- comum as empilharia todas num conflito só.\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_documents_chave_idx\n ON public.plg_fiscalbr_documents (tenant_id, access_key) WHERE access_key IS NOT NULL;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_documents_order_idx\n ON public.plg_fiscalbr_documents (tenant_id, order_id);\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_documents_status_idx\n ON public.plg_fiscalbr_documents (tenant_id, unit_id, status, authorized_at DESC);\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 3. A trilha da emissão\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 1.886 eventos para 496 notas — quase quatro por nota. É aqui que a rejeição\n-- diz o motivo, e é o único lugar em que ela diz.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_document_events (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n unit_id uuid,\n document_id uuid NOT NULL REFERENCES public.plg_fiscalbr_documents(document_id) ON DELETE CASCADE,\n event_type text NOT NULL,\n status text,\n justification text,\n request_payload jsonb,\n response_payload jsonb,\n created_by_user_id uuid,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now()\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_document_events_doc_idx\n ON public.plg_fiscalbr_document_events (document_id, created_at DESC);\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 4. Quais vendas a nota cobre\n-- ═══════════════════════════════════════════════════════════════════════════\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_document_orders (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n document_id uuid NOT NULL REFERENCES public.plg_fiscalbr_documents(document_id) ON DELETE CASCADE,\n order_id uuid NOT NULL REFERENCES public.orders(id) ON DELETE CASCADE,\n created_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE (document_id, order_id)\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_document_orders_order_idx\n ON public.plg_fiscalbr_document_orders (tenant_id, order_id);\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 5. updated_at e a cerca\n-- ═══════════════════════════════════════════════════════════════════════════\n\nDO $$ BEGIN\n CREATE TRIGGER plg_fiscalbr_documents_updated_at BEFORE UPDATE\n ON public.plg_fiscalbr_documents FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at();\nEXCEPTION WHEN duplicate_object THEN NULL; END $$;\n\n-- \\`app.current_tenant_id()\\` e não \\`user_tenant_ids()\\`, pela razão que a 013 do\n-- plugin-tables teve de consertar em produção: a segunda devolve a UNIÃO das\n-- contas do chamador e mostraria a nota fiscal de um cliente para outro.\nDO $$\nDECLARE t text;\nBEGIN\n FOREACH t IN ARRAY ARRAY['plg_fiscalbr_documents','plg_fiscalbr_document_events',\n 'plg_fiscalbr_document_orders'] LOOP\n EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', t);\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_select', t);\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_insert', t);\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_update', t);\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_delete', t);\n EXECUTE format('CREATE POLICY %I ON public.%I FOR SELECT USING (tenant_id = (select app.current_tenant_id()))', t || '_select', t);\n EXECUTE format('CREATE POLICY %I ON public.%I FOR INSERT WITH CHECK (tenant_id = (select app.current_tenant_id()))', t || '_insert', t);\n EXECUTE format('CREATE POLICY %I ON public.%I FOR UPDATE USING (tenant_id = (select app.current_tenant_id()))', t || '_update', t);\n EXECUTE format('CREATE POLICY %I ON public.%I FOR DELETE USING (tenant_id = (select app.current_tenant_id()))', t || '_delete', t);\n EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON public.%I TO authenticated', t);\n END LOOP;\nEND $$;\n`\n\nexport const MIGRATION_006_O_GRUPO_FISCAL_GANHA_O_RAIL = `-- O grupo fiscal ganha observação e etiqueta.\n--\n-- A tabela existe desde a 002 e nunca teve TELA: o grupo fiscal de toda conta\n-- migrada estava no banco sem porta. Estas duas colunas são o que falta para\n-- ele ter o mesmo rail de todo cadastro do produto — e a etiqueta tem uso\n-- imediato aqui, porque «Simples», «monofásico» e «substituição tributária»\n-- são recortes que nenhum campo do grupo responde e que decidem qual grupo\n-- alguém procura.\n--\n-- Idempotente.\n\nALTER TABLE public.plg_fiscalbr_tax_groups\n ADD COLUMN IF NOT EXISTS notes text,\n ADD COLUMN IF NOT EXISTS tags text[] DEFAULT '{}'::text[],\n ADD COLUMN IF NOT EXISTS unit_id uuid;\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_tax_groups_tags_gin\n ON public.plg_fiscalbr_tax_groups USING gin (tags);\n`\n\nexport const MIGRATION_007_A_RLS_DO_DOCUMENTO_PASSA_A_SER_LEGIVEL = `-- ---------------------------------------------------------------------------\n-- 007_a_rls_do_documento_passa_a_ser_legivel.sql\n--\n-- MESMO caso da 036 do plugin-tables, e a mesma medição antes de escrever.\n--\n-- \\`check-plugin-review\\` reprovou estas tabelas com *«cria public.X com\n-- tenant_id e nunca liga row security»*. Fui ao banco: **todas têm RLS ligada,\n-- com políticas** — medido no cluster do Pertinho em 29-09:\n--\n-- plg_fiscalbr_documents ........ rls=t, 4 políticas\n-- plg_fiscalbr_document_events .. rls=t, 4\n-- plg_fiscalbr_document_orders .. rls=t, 4\n--\n-- Não há vazamento. O \\`ENABLE\\` dessas tabelas mora dentro de um\n-- \\`DO $$ … EXECUTE format(...)\\`, e o portão lê o ARQUIVO, não o banco — uma\n-- garantia que o revisor não consegue ler é uma garantia que ninguém confere.\n--\n-- As migrations que as criam JÁ FORAM APLICADAS; reescrevê-las trocaria o\n-- checksum, que é a deriva de ledger pela qual este repositório para o mundo.\n-- Então a legibilidade entra por arquivo NOVO — o portão pergunta ao SQL\n-- INTEIRO do plugin.\n--\n-- Ligar RLS já ligada é no-op: isto não muda comportamento, torna conferível o\n-- que já era verdade.\n--\n-- Idempotente e replay-safe.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_fiscalbr_documents ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_document_events ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_document_orders ENABLE ROW LEVEL SECURITY;\n`\n\nexport const MIGRATION_008_A_NOTA_RECEBIDA_GUARDA_A_DECISAO_DE_ENTRADA = `-- ---------------------------------------------------------------------------\n-- 008_a_nota_recebida_guarda_a_decisao_de_entrada.sql\n--\n-- A 002 trouxe a nota; esta guarda o que se DECIDE sobre ela.\n--\n-- O inbox do V2 já sabe tudo que o XML diz: fornecedor, item, NCM, CFOP, os 30\n-- campos de tributo. O que não tem onde morar é a decisão que o operador toma\n-- em cima da nota, e é ela que transforma documento em estoque e em dinheiro:\n--\n-- a qual PRODUTO esta linha corresponde (product_id, já existia)\n-- que TIPO de entrada ela é (entry_type)\n-- em que UNIDADE de estoque, com que FATOR (stock_unit_id, conversion_factor)\n-- em que PLANO DE CONTAS ela cai (chart_account_id)\n-- com que CUSTO o produto fica (cost_mode, unit_cost_new)\n--\n-- Sem essas colunas a tela de conciliação não tem onde salvar, e \"importar nota\n-- fiscal\" viraria um leitor de XML — que é exatamente o que o V2 tinha.\n--\n-- ── O vocabulário vem do V1 medido, não de um enum inventado ────────────────\n--\n-- \\`danfe_import_items.entry_type\\` no V1 de produção (29-09-2026), 3.402 linhas:\n--\n-- insumo 2.303 revenda 546 patrimonio 280\n-- despesa 262 servico 11 (null) 5\n--\n-- São cinco, e duas delas — \\`despesa\\` e \\`servico\\` — NÃO viram estoque. É por\n-- isso que o tipo é coluna da linha e não da nota: a mesma NF-e traz o insumo\n-- que entra no estoque e a taxa de entrega que só vira despesa.\n--\n-- \\`cost_mode\\` tem UM valor em 3.407 linhas: \\`novo\\`. A média ponderada existe na\n-- tela do V1 e ninguém nunca escolheu. Fica no CHECK por paridade — tirar a\n-- opção é decisão de produto, e o dado não autoriza ninguém a tomá-la por aqui.\n--\n-- ── Por que \\`stock_movement_id\\` na linha, e não só na nota ──────────────────\n--\n-- Uma nota pode virar estoque PARCIALMENTE: o V1 tem os status \\`partial\\` e\n-- \\`partial_stocked\\` justamente porque o operador concilia 1 de 6 itens hoje e o\n-- resto amanhã. Guardar o movimento só no cabeçalho responderia \"esta nota\n-- entrou?\" e nunca \"esta LINHA entrou?\" — e é a segunda pergunta que decide se\n-- aceitar de novo duplica saldo.\n--\n-- ── O de-para é o que faz a segunda nota ser rápida ─────────────────────────\n--\n-- \\`supplier_product_mappings\\` no V1: (CNPJ do fornecedor, código do produto no\n-- fornecedor) → produto, tipo, plano, unidade, fator. 66 linhas na Artorius, e é\n-- o que faz a nota seguinte do mesmo fornecedor chegar já vinculada. Sem ele,\n-- toda importação recomeça do zero e o ganho de importar XML desaparece.\n--\n-- A chave é (tenant, CNPJ, código) e NÃO inclui unidade: o de-para é\n-- conhecimento sobre o catálogo do fornecedor, não sobre uma loja.\n--\n-- Aditivo e idempotente. Nada aqui apaga, renomeia ou reescreve dado existente.\n-- ---------------------------------------------------------------------------\n\n-- ── A decisão, linha a linha ────────────────────────────────────────────────\n\nALTER TABLE public.plg_fiscalbr_inbox_items\n ADD COLUMN IF NOT EXISTS entry_type text,\n ADD COLUMN IF NOT EXISTS chart_account_id uuid,\n ADD COLUMN IF NOT EXISTS stock_unit_id uuid,\n -- A quantidade que entra no estoque, já convertida. Derivada\n -- (quantity_commercial × conversion_factor), mas GRAVADA: é o número que o\n -- operador viu na tela antes de aceitar, e recalcular depois com um fator que\n -- alguém editou daria outra resposta para a mesma entrada.\n ADD COLUMN IF NOT EXISTS stock_quantity numeric(18,4),\n ADD COLUMN IF NOT EXISTS conversion_factor numeric(14,4) NOT NULL DEFAULT 1,\n ADD COLUMN IF NOT EXISTS cost_mode text,\n ADD COLUMN IF NOT EXISTS unit_cost_new numeric(18,6),\n -- O movimento que ESTA linha produziu. Nulo = não entrou.\n ADD COLUMN IF NOT EXISTS stock_movement_id uuid,\n -- Divergência: chegou menos do que a nota diz. O V1 guarda quantidade, motivo\n -- e observação, e a nota continua válida — quem responde pela diferença é o\n -- fornecedor, não o estoque.\n ADD COLUMN IF NOT EXISTS shortage_quantity numeric(18,4),\n ADD COLUMN IF NOT EXISTS shortage_reason text,\n ADD COLUMN IF NOT EXISTS shortage_note text;\n\nDO $$\nBEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_entry_type_chk') THEN\n ALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_entry_type_chk\n CHECK (entry_type IS NULL OR entry_type IN ('insumo','revenda','patrimonio','despesa','servico'));\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_cost_mode_chk') THEN\n ALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_cost_mode_chk\n CHECK (cost_mode IS NULL OR cost_mode IN ('novo','media'));\n END IF;\n -- Um fator zero ou negativo não converte nada: transformaria a quantidade da\n -- nota em zero estoque sem ninguém acusar. É o defeito silencioso que o\n -- FLOW.md do V1 nomeia («fator de conversão errado é silencioso»), e aqui ele\n -- deixa de ser possível.\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_factor_chk') THEN\n ALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_factor_chk CHECK (conversion_factor > 0);\n END IF;\nEND $$;\n\n-- FK lógica para o plano de contas e a unidade: as duas são de OUTROS plugins\n-- (financial e inventory), e a 000 deste plugin já estabelece que FK física\n-- entre plugins é proibida — instalar ou remover um addon não reescreve o\n-- schema do vizinho. A integridade é verificada na RPC, que é quem escreve.\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.chart_account_id IS\n 'Logical reference to plg_financial_chart_of_accounts.id — validated by the accept RPC, not by a cross-plugin FK.';\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.stock_unit_id IS\n 'Logical reference to plg_inventory_measurement_units.id — validated by the accept RPC.';\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.stock_quantity IS\n 'quantity_commercial x conversion_factor, stored as shown on screen before accepting.';\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_items_pending_idx\n ON public.plg_fiscalbr_inbox_items (tenant_id, inbox_document_id)\n WHERE reconciled IS NOT TRUE;\n\n-- ── A decisão no cabeçalho da nota ──────────────────────────────────────────\n\nALTER TABLE public.plg_fiscalbr_inbox_documents\n -- «itens sem plano herdarão este» — o plano da nota é padrão com HERANÇA, não\n -- obrigação por item. A frase é do V1 e a coluna existe para ela.\n ADD COLUMN IF NOT EXISTS default_chart_account_id uuid,\n -- O título a pagar que esta nota gerou. Mesma ideia do inventory_operation_id\n -- que a 002 já trouxe para o estoque: a nota aponta para as duas travessias.\n ADD COLUMN IF NOT EXISTS invoice_id uuid,\n ADD COLUMN IF NOT EXISTS stocked_at timestamptz,\n -- A natureza da operação declarada na NF-e («REM BONIFICACAO NAO\n -- CONTRIBUINTE»). O bloco de situação fiscal da conciliação mostra isso, e\n -- sem a coluna a tela mostraria um campo vazio.\n ADD COLUMN IF NOT EXISTS nature_operation text,\n ADD COLUMN IF NOT EXISTS default_location_id uuid;\n\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_documents.invoice_id IS\n 'Logical reference to plg_financial_invoices.id created by fiscalbr_accept_inbox_document.';\n\n-- ── A parcela sabe como se paga ─────────────────────────────────────────────\n--\n-- A duplicata do XML traz número, vencimento e valor. O que o operador acrescenta\n-- na tela é COMO ela se paga — e o boleto que ele anexa carrega o código de\n-- barras, que é o que a automação do V1 lê para preencher a parcela.\n\nALTER TABLE public.plg_fiscalbr_inbox_duplicates\n ADD COLUMN IF NOT EXISTS payment_type text,\n ADD COLUMN IF NOT EXISTS barcode text,\n ADD COLUMN IF NOT EXISTS pix_key text,\n ADD COLUMN IF NOT EXISTS payment_method_id uuid;\n\n-- O vocabulário é o do V1, medido em \\`danfe_payments.payment_type\\` (1.069 linhas):\n-- boleto 660 · sem_pagamento 108 · outro 107 · dinheiro 65 ·\n-- duplicata_mercantil 45 · pix 35 · cartao_credito 35 · cartao_debito 9 ·\n-- credito_loja 4 · vale_presente 1\nDO $$\nBEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_duplicates_payment_type_chk') THEN\n ALTER TABLE public.plg_fiscalbr_inbox_duplicates\n ADD CONSTRAINT plg_fiscalbr_inbox_duplicates_payment_type_chk\n CHECK (payment_type IS NULL OR payment_type IN (\n 'boleto','pix','dinheiro','cartao_credito','cartao_debito',\n 'duplicata_mercantil','credito_loja','vale_presente','sem_pagamento','outro'));\n END IF;\nEND $$;\n\n-- ── O de-para fornecedor × produto ──────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_supplier_product_map (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n -- Só dígitos, normalizado na escrita: o XML traz o CNPJ cru e a tela do V1\n -- aceitava pontuação, então duas grafias do mesmo fornecedor viravam dois\n -- de-para e a segunda nota não achava o primeiro.\n supplier_cnpj text NOT NULL,\n supplier_product_code text NOT NULL,\n product_id uuid NOT NULL REFERENCES public.products(id) ON DELETE CASCADE,\n entry_type text,\n chart_account_id uuid,\n stock_unit_id uuid,\n conversion_factor numeric(14,4) NOT NULL DEFAULT 1,\n cost_mode text,\n -- Quantas vezes este de-para acertou. Serve para a tela mostrar de onde veio o\n -- vínculo («já usado 12 vezes») em vez de um produto que apareceu sozinho.\n hit_count integer NOT NULL DEFAULT 0,\n last_used_at timestamptz,\n owner_id uuid,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT plg_fiscalbr_supplier_product_map_factor_chk CHECK (conversion_factor > 0),\n CONSTRAINT plg_fiscalbr_supplier_product_map_entry_type_chk\n CHECK (entry_type IS NULL OR entry_type IN ('insumo','revenda','patrimonio','despesa','servico')),\n CONSTRAINT plg_fiscalbr_supplier_product_map_cost_mode_chk\n CHECK (cost_mode IS NULL OR cost_mode IN ('novo','media'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_supplier_product_map_uq\n ON public.plg_fiscalbr_supplier_product_map (tenant_id, supplier_cnpj, supplier_product_code);\n\nALTER TABLE public.plg_fiscalbr_supplier_product_map ENABLE ROW LEVEL SECURITY;\n\n-- Mesmas políticas das tabelas do inbox (002): o de-para é conhecimento do\n-- financeiro sobre o fornecedor, então lê com \\`financial.read\\` e escreve com\n-- \\`financial.edit\\`. Não tem unit_id — é catálogo do fornecedor, não da loja.\nDROP POLICY IF EXISTS plg_fiscalbr_supplier_product_map_authz_select ON public.plg_fiscalbr_supplier_product_map;\nCREATE POLICY plg_fiscalbr_supplier_product_map_authz_select\n ON public.plg_fiscalbr_supplier_product_map FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL::uuid)));\n\nDROP POLICY IF EXISTS plg_fiscalbr_supplier_product_map_authz_write ON public.plg_fiscalbr_supplier_product_map;\nCREATE POLICY plg_fiscalbr_supplier_product_map_authz_write\n ON public.plg_fiscalbr_supplier_product_map FOR ALL TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.edit', NULL::uuid)))\n WITH CHECK (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.edit', NULL::uuid)));\n\nCOMMENT ON TABLE public.plg_fiscalbr_supplier_product_map IS\n 'Supplier catalogue memory: (CNPJ, supplier product code) -> the entry decision, so the next note from the same supplier arrives already bound. Mirrors V1 supplier_product_mappings.';\n`\n\nexport const MIGRATION_009_ACEITAR_A_NOTA_ESCREVE_ESTOQUE_E_TITULO_DE_UMA_VEZ = `-- ---------------------------------------------------------------------------\n-- 009_aceitar_a_nota_escreve_estoque_e_titulo_de_uma_vez.sql\n--\n-- É o arquivo que fecha o porte: «Aceitar» na conciliação dá entrada no estoque\n-- E cria a conta a pagar, numa transação só.\n--\n-- Medido no V1 de produção (tenant 12 da Artorius, 29-09-2026): **72 de 72**\n-- movimentos de estoque nasceram com \\`danfe_import_item_id\\`. Nenhum foi digitado.\n-- Dar ao V2 uma tela de movimentação manual e chamar isso de paridade seria\n-- entregar a tela que eles nunca abriram.\n--\n-- ── Não reimplementa estoque nem título. CHAMA quem já faz ──────────────────\n--\n-- O V2 já tem as duas primitivas, e as duas já são idempotentes:\n--\n-- public.inventory_receive(location, lines, document, idempotency_key)\n-- public.financial_create_invoice(direction, total, counterparty, …, key)\n--\n-- Reescrever INSERT em \\`plg_inventory_stock_movements\\` aqui daria uma segunda\n-- resposta para «como entra estoque» — e a posição é derivada por gatilho, então\n-- a segunda resposta sairia com saldo certo e sem ninguém acusar. A entrada de\n-- nota é mais um CHAMADOR dessas portas, como a requisição e a contagem.\n--\n-- Idempotência vem de graça daí: a chave é derivada da chave de acesso da NF-e,\n-- que é única por documento fiscal no Brasil. Aceitar duas vezes devolve o mesmo\n-- resultado sem escrever de novo — o AC7 do plano.\n--\n-- ── O total do título é a soma das PARCELAS ────────────────────────────────\n--\n-- Regra herdada da \\`plugin-financial/084\\`, que mediu: em 6,3% das notas a soma\n-- das duplicatas não bate com o total da nota. \\`plg_financial_invoices\\` é\n-- imutável depois de emitido, então um título aberto com o total errado fica\n-- com saldo errado para sempre em toda tela que faz «total − pago».\n-- O total da nota continua legível no \\`metadata\\` e na caixa de entrada.\n--\n-- E a MESMA chave de idempotência da 084 (\\`danfe:<chave>\\`): uma nota que o porte\n-- histórico já transformou em título não pode ganhar um segundo aqui.\n--\n-- ── Despesa e serviço não viram estoque ────────────────────────────────────\n--\n-- \\`entry_type\\` decide por LINHA. A mesma NF-e traz o insumo que entra no estoque\n-- e a taxa de entrega que só vira despesa — e as duas precisam ir para o mesmo\n-- título a pagar. Por isso a lista de linhas do estoque é um FILTRO sobre os\n-- itens, não os itens.\n--\n-- Idempotente. Só cria função.\n-- ---------------------------------------------------------------------------\n\n-- ── Ajudantes ──────────────────────────────────────────────────────────────\n\n-- O XML traz o CNPJ cru e a tela aceita pontuação. Duas grafias do mesmo\n-- fornecedor viravam dois de-para no V1, e a segunda nota não achava o primeiro.\nCREATE OR REPLACE FUNCTION public.plg_fiscalbr_digits(p_value text)\nRETURNS text LANGUAGE sql IMMUTABLE SET search_path TO '' AS $$\n SELECT regexp_replace(coalesce(p_value, ''), '[^0-9]', '', 'g')\n$$;\n\n-- ── Receber a nota: o XML já lido vira linhas ──────────────────────────────\n--\n-- O XML é decomposto no NAVEGADOR e chega aqui como jsonb. Parsear NF-e em\n-- PL/pgSQL seria escrever um leitor de XML dentro do banco, sem teste unitário\n-- possível e sem a mensagem de erro que a tela precisa dar para um arquivo que\n-- não é uma nota.\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_stage_inbox_document(p_note jsonb)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_key text := btrim(coalesce(p_note->>'access_key', ''));\n v_cnpj text := public.plg_fiscalbr_digits(p_note->'supplier'->>'cnpj');\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_unit uuid := nullif(p_note->>'unit_id', '')::uuid;\n v_party uuid;\n v_item jsonb;\n v_map public.plg_fiscalbr_supplier_product_map%ROWTYPE;\n v_n integer := 0;\n v_matched integer := 0;\nBEGIN\n PERFORM public.plg_financial_require_permission('financial.create', v_unit);\n\n IF length(v_key) <> 44 THEN\n RAISE EXCEPTION 'fiscalbr: chave de acesso inválida (esperado 44 dígitos, veio %)', length(v_key)\n USING ERRCODE = '22023';\n END IF;\n\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND access_key = v_key;\n\n -- Nota já aceita não é reimportada: o XML é o mesmo documento fiscal, e\n -- reescrever os itens apagaria a decisão que virou estoque e título.\n IF FOUND AND (v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL) THEN\n RETURN jsonb_build_object(\n 'document_id', v_doc.id, 'access_key', v_key, 'already_accepted', true,\n 'invoice_id', v_doc.invoice_id, 'items', 0, 'matched', 0);\n END IF;\n\n -- O fornecedor é uma PESSOA, não um nome. A 094 do financial documenta o custo\n -- de não ter o ponteiro: praticamente todo título nascido de DANFE ficou sem\n -- contraparte. Casar por CNPJ acerta; casar por nome acertaria 137 de 554.\n IF v_cnpj <> '' THEN\n SELECT id INTO v_party FROM public.people\n WHERE tenant_id = v_tenant AND public.plg_fiscalbr_digits(document_number) = v_cnpj\n LIMIT 1;\n END IF;\n\n INSERT INTO public.plg_fiscalbr_inbox_documents (\n tenant_id, unit_id, access_key, nfe_number, nfe_series, nfe_model, issue_date,\n received_at, status, nature_operation, supplier_party_id, supplier_cnpj,\n supplier_name, supplier_ie, total_value, total_products, total_discount,\n total_freight, total_insurance, total_other, additional_info, metadata)\n VALUES (\n v_tenant, v_unit, v_key, p_note->>'nfe_number', p_note->>'nfe_series',\n coalesce(p_note->>'nfe_model', '55'), nullif(p_note->>'issue_date', '')::date,\n now(), 'pending', p_note->>'nature_operation', v_party, nullif(v_cnpj, ''),\n p_note->'supplier'->>'name', p_note->'supplier'->>'ie',\n (p_note->'totals'->>'total')::numeric, (p_note->'totals'->>'products')::numeric,\n (p_note->'totals'->>'discount')::numeric, (p_note->'totals'->>'freight')::numeric,\n (p_note->'totals'->>'insurance')::numeric, (p_note->'totals'->>'other')::numeric,\n p_note->>'additional_info',\n jsonb_build_object('source', coalesce(p_note->>'source', 'xml_upload')))\n -- O índice único da 002 é PARCIAL (\\`WHERE access_key IS NOT NULL\\`), e a\n -- inferência do ON CONFLICT só o alcança repetindo o predicado. Sem ele o\n -- INSERT levanta «no unique or exclusion constraint matching» — e levantaria\n -- na primeira reimportação, não na aplicação.\n ON CONFLICT (tenant_id, access_key) WHERE access_key IS NOT NULL DO UPDATE SET\n -- Reimportar o mesmo XML corrige o cabeçalho; a contraparte só é preenchida\n -- quando está vazia, para não desfazer uma costura feita à mão.\n nfe_number = EXCLUDED.nfe_number,\n nature_operation = coalesce(EXCLUDED.nature_operation, public.plg_fiscalbr_inbox_documents.nature_operation),\n supplier_party_id = coalesce(public.plg_fiscalbr_inbox_documents.supplier_party_id, EXCLUDED.supplier_party_id),\n supplier_name = EXCLUDED.supplier_name,\n total_value = EXCLUDED.total_value,\n updated_at = now()\n RETURNING * INTO v_doc;\n\n -- Os itens e as duplicatas são do DOCUMENTO, não do operador: vêm do XML e\n -- podem ser reescritos enquanto a nota não foi aceita.\n DELETE FROM public.plg_fiscalbr_inbox_items WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n DELETE FROM public.plg_fiscalbr_inbox_duplicates WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n DELETE FROM public.plg_fiscalbr_inbox_payments WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n FOR v_item IN SELECT * FROM jsonb_array_elements(coalesce(p_note->'items', '[]'::jsonb)) LOOP\n v_n := v_n + 1;\n\n -- O de-para: a segunda nota do mesmo fornecedor chega já vinculada. É o que\n -- faz importar XML valer a pena — sem ele toda nota recomeça do zero.\n SELECT * INTO v_map FROM public.plg_fiscalbr_supplier_product_map\n WHERE tenant_id = v_tenant AND supplier_cnpj = v_cnpj\n AND supplier_product_code = coalesce(v_item->>'supplier_product_code', '');\n IF FOUND THEN v_matched := v_matched + 1; END IF;\n\n INSERT INTO public.plg_fiscalbr_inbox_items (\n tenant_id, inbox_document_id, item_number, supplier_product_code, ean_barcode,\n description, ncm, cest, cfop, unit_commercial, quantity_commercial,\n unit_price_commercial, total_price, discount, freight, other_expenses,\n icms_cst, icms_csosn, icms_base, icms_rate, icms_value,\n pis_value, cofins_value, ipi_value, raw_xml_item,\n product_id, entry_type, chart_account_id, stock_unit_id, conversion_factor,\n cost_mode, reconciled, stock_quantity, unit_cost_new)\n VALUES (\n v_tenant, v_doc.id, coalesce((v_item->>'item_number')::int, v_n),\n v_item->>'supplier_product_code', v_item->>'ean_barcode',\n v_item->>'description', v_item->>'ncm', v_item->>'cest', v_item->>'cfop',\n v_item->>'unit', (v_item->>'quantity')::numeric,\n (v_item->>'unit_price')::numeric, (v_item->>'total')::numeric,\n (v_item->>'discount')::numeric, (v_item->>'freight')::numeric,\n (v_item->>'other')::numeric,\n v_item->>'icms_cst', v_item->>'icms_csosn', (v_item->>'icms_base')::numeric,\n (v_item->>'icms_rate')::numeric, (v_item->>'icms_value')::numeric,\n (v_item->>'pis_value')::numeric, (v_item->>'cofins_value')::numeric,\n (v_item->>'ipi_value')::numeric, v_item,\n v_map.product_id, v_map.entry_type, v_map.chart_account_id, v_map.stock_unit_id,\n coalesce(v_map.conversion_factor, 1), coalesce(v_map.cost_mode, 'novo'),\n v_map.product_id IS NOT NULL,\n -- A quantidade de estoque já sai calculada quando o de-para deu o fator: é\n -- o número que a tela mostra antes de aceitar.\n CASE WHEN v_map.product_id IS NOT NULL\n THEN (v_item->>'quantity')::numeric * coalesce(v_map.conversion_factor, 1) END,\n CASE WHEN v_map.product_id IS NOT NULL AND coalesce(v_map.conversion_factor, 1) > 0\n THEN (v_item->>'unit_price')::numeric / coalesce(v_map.conversion_factor, 1) END);\n END LOOP;\n\n INSERT INTO public.plg_fiscalbr_inbox_duplicates (\n tenant_id, inbox_document_id, duplicate_index, number, due_date, value, payment_type)\n SELECT v_tenant, v_doc.id, coalesce((d->>'index')::int, ord), d->>'number',\n nullif(d->>'due_date', '')::date, (d->>'value')::numeric,\n nullif(d->>'payment_type', '')\n FROM jsonb_array_elements(coalesce(p_note->'duplicates', '[]'::jsonb)) WITH ORDINALITY AS t(d, ord);\n\n INSERT INTO public.plg_fiscalbr_inbox_payments (\n tenant_id, inbox_document_id, payment_index, payment_indicator,\n payment_type_code, payment_type_label, value)\n SELECT v_tenant, v_doc.id, coalesce((p->>'index')::int, ord), p->>'indicator',\n p->>'code', p->>'label', (p->>'value')::numeric\n FROM jsonb_array_elements(coalesce(p_note->'payments', '[]'::jsonb)) WITH ORDINALITY AS t(p, ord);\n\n RETURN jsonb_build_object(\n 'document_id', v_doc.id, 'access_key', v_key, 'already_accepted', false,\n 'supplier_party_id', v_party, 'items', v_n, 'matched', v_matched);\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_stage_inbox_document(jsonb) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_stage_inbox_document(jsonb) TO authenticated;\n\n-- ── Salvar a conciliação sem aceitar ───────────────────────────────────────\n--\n-- Conciliar e estocar são duas coisas no V1 — daí as duas colunas na lista, e\n-- daí a fila de 55 notas conciliadas e não estocadas. Quem salva o vínculo não\n-- está mandando dar entrada.\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_save_inbox_decision(\n p_document_id uuid,\n p_items jsonb,\n p_default_chart_account_id uuid DEFAULT NULL,\n p_default_location_id uuid DEFAULT NULL,\n p_duplicates jsonb DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_row jsonb;\n v_done integer := 0;\n v_total integer;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.edit', v_doc.unit_id);\n\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RAISE EXCEPTION 'fiscalbr: nota % já foi aceita — a decisão não muda depois do estoque', p_document_id\n USING ERRCODE = '23514';\n END IF;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n default_chart_account_id = coalesce(p_default_chart_account_id, default_chart_account_id),\n default_location_id = coalesce(p_default_location_id, default_location_id),\n reviewed_at = now(), updated_at = now()\n WHERE id = v_doc.id;\n\n FOR v_row IN SELECT * FROM jsonb_array_elements(coalesce(p_items, '[]'::jsonb)) LOOP\n UPDATE public.plg_fiscalbr_inbox_items i SET\n product_id = nullif(v_row->>'product_id', '')::uuid,\n entry_type = nullif(v_row->>'entry_type', ''),\n chart_account_id = nullif(v_row->>'chart_account_id', '')::uuid,\n stock_unit_id = nullif(v_row->>'stock_unit_id', '')::uuid,\n conversion_factor = coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1),\n cost_mode = coalesce(nullif(v_row->>'cost_mode', ''), 'novo'),\n shortage_quantity = nullif(v_row->>'shortage_quantity', '')::numeric,\n shortage_reason = nullif(v_row->>'shortage_reason', ''),\n shortage_note = nullif(v_row->>'shortage_note', ''),\n -- Derivadas, gravadas: é o que o operador viu.\n stock_quantity = i.quantity_commercial * coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1)\n - coalesce(nullif(v_row->>'shortage_quantity', '')::numeric, 0),\n unit_cost_new = CASE WHEN coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1) > 0\n THEN i.unit_price_commercial / coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1) END,\n -- Uma linha está conciliada quando sabe o que é. Despesa e serviço não\n -- pedem produto: elas nunca vão virar estoque.\n reconciled = CASE\n WHEN nullif(v_row->>'entry_type', '') IN ('despesa','servico') THEN true\n ELSE nullif(v_row->>'product_id', '') IS NOT NULL\n END,\n updated_at = now()\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n AND i.id = (v_row->>'id')::uuid;\n v_done := v_done + 1;\n END LOOP;\n\n IF p_duplicates IS NOT NULL THEN\n DELETE FROM public.plg_fiscalbr_inbox_duplicates\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n INSERT INTO public.plg_fiscalbr_inbox_duplicates (\n tenant_id, inbox_document_id, duplicate_index, number, due_date, value,\n payment_type, barcode, pix_key, payment_method_id)\n SELECT v_tenant, v_doc.id, coalesce((d->>'index')::int, ord), d->>'number',\n nullif(d->>'due_date', '')::date, (d->>'value')::numeric,\n nullif(d->>'payment_type', ''), nullif(d->>'barcode', ''),\n nullif(d->>'pix_key', ''), nullif(d->>'payment_method_id', '')::uuid\n FROM jsonb_array_elements(p_duplicates) WITH ORDINALITY AS t(d, ord);\n END IF;\n\n SELECT count(*) INTO v_total FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET status = CASE\n WHEN (SELECT count(*) FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id AND reconciled) = v_total\n THEN 'accepted' ELSE 'partial' END\n WHERE id = v_doc.id;\n\n RETURN jsonb_build_object('document_id', v_doc.id, 'saved', v_done, 'items', v_total,\n 'reconciled', (SELECT count(*) FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id AND reconciled));\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_save_inbox_decision(uuid, jsonb, uuid, uuid, jsonb) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_save_inbox_decision(uuid, jsonb, uuid, uuid, jsonb) TO authenticated;\n\n-- ── Aceitar: estoque e título, de uma vez ──────────────────────────────────\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_accept_inbox_document(\n p_document_id uuid,\n p_location_id uuid DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_loc uuid;\n v_lines jsonb := '[]'::jsonb;\n v_insts jsonb := '[]'::jsonb;\n v_recv jsonb;\n v_inv jsonb;\n v_it record;\n v_no integer := 0;\n v_total numeric := 0;\n v_stock_n integer := 0;\n v_key text;\n v_invoice uuid;\n -- Posição na lista de linhas → id do item da nota. \\`line_no\\` do movimento\n -- indexa este array direto.\n v_item_ids uuid[] := '{}';\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.create', v_doc.unit_id);\n\n -- Já aceita devolve o que aceitou. Não é erro: é a segunda vez que o operador\n -- clicou, e o AC7 diz que isso não pode dobrar nada.\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RETURN jsonb_build_object('document_id', v_doc.id, 'already_accepted', true,\n 'invoice_id', v_doc.invoice_id, 'operation_id', v_doc.inventory_operation_id);\n END IF;\n\n v_loc := coalesce(p_location_id, v_doc.default_location_id);\n\n -- Toda linha tem de saber o que é. Aceitar uma nota com item sem tipo gravaria\n -- um título cujo rateio ninguém consegue explicar depois.\n IF EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id\n AND (entry_type IS NULL OR entry_type = '')) THEN\n RAISE EXCEPTION 'fiscalbr: há item sem tipo de registro — conciliar antes de aceitar'\n USING ERRCODE = '23514';\n END IF;\n\n -- As linhas que viram estoque. Despesa e serviço ficam fora daqui e entram só\n -- no título.\n FOR v_it IN\n SELECT * FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id\n AND entry_type IN ('insumo','revenda','patrimonio')\n ORDER BY item_number\n LOOP\n IF v_it.product_id IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: item % é % e não tem produto vinculado', v_it.item_number, v_it.entry_type\n USING ERRCODE = '23514';\n END IF;\n v_no := v_no + 1;\n -- A ordem desta lista É o \\`line_no\\` que o movimento vai carregar. Guardo o\n -- id da linha na mesma posição para devolver o movimento ao item sem\n -- reconsultar — e sem depender de casar por produto, que repete quando a\n -- mesma mercadoria vem em duas linhas da nota.\n v_item_ids := v_item_ids || v_it.id;\n v_lines := v_lines || jsonb_build_object(\n 'product_id', v_it.product_id,\n 'quantity', coalesce(v_it.stock_quantity, v_it.quantity_commercial * v_it.conversion_factor),\n 'unit_cost', coalesce(v_it.unit_cost_new, v_it.unit_price_commercial / v_it.conversion_factor),\n 'measurement_unit_id', v_it.stock_unit_id,\n 'notes', v_it.description);\n END LOOP;\n v_stock_n := v_no;\n\n IF v_stock_n > 0 THEN\n IF v_loc IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: a nota tem % linha(s) de estoque e nenhum local de estoque escolhido', v_stock_n\n USING ERRCODE = '22023';\n END IF;\n -- A chave de acesso é única por documento fiscal no Brasil: é a chave de\n -- idempotência natural, e é ela que faz o segundo clique não dobrar saldo.\n v_recv := public.inventory_receive(\n v_loc, v_lines,\n jsonb_build_object(\n 'supplier_id', v_doc.supplier_party_id,\n 'date', v_doc.issue_date,\n 'type', 'nfe',\n 'ref', 'NF-e ' || coalesce(v_doc.nfe_number, '?'),\n 'notes', 'Entrada via DANFE NF-e ' || coalesce(v_doc.nfe_number, '?')),\n 'nfe:' || v_doc.access_key);\n\n -- Cada movimento volta para a SUA linha. Guardar só no cabeçalho responderia\n -- «esta nota entrou?» e nunca «esta linha entrou?» — e é a segunda pergunta\n -- que a conciliação parcial faz.\n --\n -- \\`line_no\\` do movimento é a posição na lista que montei acima, e\n -- \\`v_item_ids\\` está na mesma ordem: um join, não uma varredura por posição.\n UPDATE public.plg_fiscalbr_inbox_items i\n SET stock_movement_id = m.movement_id, updated_at = now()\n FROM (\n SELECT v_item_ids[(mov->>'line_no')::int] AS item_id, (mov->>'id')::uuid AS movement_id\n FROM jsonb_array_elements(coalesce(v_recv->'movements', '[]'::jsonb)) AS t(mov)\n WHERE (mov->>'line_no') IS NOT NULL\n ) m\n WHERE i.tenant_id = v_tenant AND i.id = m.item_id;\n END IF;\n\n -- ── O título ─────────────────────────────────────────────────────────────\n -- Total = soma das PARCELAS (regra da financial/084). Nota sem duplicata vira\n -- uma parcela só, no vencimento que a nota declarar ou na emissão.\n SELECT coalesce(sum(value), 0),\n coalesce(jsonb_agg(jsonb_build_object(\n 'number', coalesce(duplicate_index, 1),\n 'due_date', coalesce(due_date, v_doc.issue_date, current_date),\n 'amount', round(value, 2),\n 'metadata', jsonb_strip_nulls(jsonb_build_object(\n 'barcode', barcode, 'pixKey', pix_key, 'paymentType', payment_type,\n 'danfeNumber', number))) ORDER BY duplicate_index), '[]'::jsonb)\n INTO v_total, v_insts\n FROM public.plg_fiscalbr_inbox_duplicates\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n IF jsonb_array_length(v_insts) = 0 THEN\n v_total := round(coalesce(v_doc.total_value, 0), 2);\n v_insts := jsonb_build_array(jsonb_build_object(\n 'number', 1, 'due_date', coalesce(v_doc.issue_date, current_date), 'amount', v_total));\n ELSE\n v_total := round(v_total, 2);\n END IF;\n\n -- A MESMA chave da 084: nota já transformada em título pelo porte histórico\n -- não ganha um segundo aqui.\n v_key := 'danfe:' || v_doc.access_key;\n\n v_inv := public.financial_create_invoice(\n 'payable', v_total, v_doc.supplier_party_id, NULL, v_doc.unit_id, v_insts,\n v_doc.issue_date,\n 'NF-e ' || coalesce(v_doc.nfe_number, '?') || ' · ' || coalesce(v_doc.supplier_name, 'fornecedor'),\n NULL,\n jsonb_build_object(\n 'source', 'danfe',\n 'danfe', jsonb_strip_nulls(jsonb_build_object(\n 'accessKey', v_doc.access_key, 'number', v_doc.nfe_number,\n 'series', v_doc.nfe_series, 'supplierName', v_doc.supplier_name,\n 'supplierCnpj', v_doc.supplier_cnpj,\n -- O total da NOTA continua legível, mesmo quando difere do total do\n -- título. É a diferença que a 084 mediu em 6,3% das notas.\n 'noteTotal', v_doc.total_value,\n 'inboxDocumentId', v_doc.id))),\n v_key);\n v_invoice := (v_inv->>'invoice_id')::uuid;\n\n -- As linhas do título: TODOS os itens, inclusive despesa e serviço. É o que\n -- responde «de que essa conta é feita».\n INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)\n SELECT v_tenant, v_invoice, i.description, i.quantity_commercial, i.unit_price_commercial,\n round(coalesce(i.total_price, 0), 2), i.item_number,\n jsonb_strip_nulls(jsonb_build_object(\n 'itemKind', i.entry_type, 'referenceId', i.product_id,\n 'chartAccountId', i.chart_account_id, 'ncm', i.ncm, 'cfop', i.cfop,\n 'supplierProductCode', i.supplier_product_code))\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n ORDER BY i.item_number\n ON CONFLICT DO NOTHING;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n invoice_id = v_invoice,\n inventory_operation_id = coalesce((v_recv->>'operation_id')::uuid, inventory_operation_id),\n stocked_at = CASE WHEN v_stock_n > 0 THEN now() ELSE stocked_at END,\n status = 'accepted', updated_at = now()\n WHERE id = v_doc.id;\n\n -- ── O de-para aprende ────────────────────────────────────────────────────\n -- A decisão desta nota é o que faz a próxima do mesmo fornecedor chegar\n -- pronta. Guardar isto é o que separa «importei XML» de «o sistema sabe o meu\n -- fornecedor».\n INSERT INTO public.plg_fiscalbr_supplier_product_map (\n tenant_id, supplier_cnpj, supplier_product_code, product_id, entry_type,\n chart_account_id, stock_unit_id, conversion_factor, cost_mode, hit_count, last_used_at)\n SELECT v_tenant, v_doc.supplier_cnpj, i.supplier_product_code, i.product_id,\n i.entry_type, coalesce(i.chart_account_id, v_doc.default_chart_account_id),\n i.stock_unit_id, i.conversion_factor, i.cost_mode, 1, now()\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n AND i.product_id IS NOT NULL\n AND coalesce(v_doc.supplier_cnpj, '') <> ''\n AND coalesce(i.supplier_product_code, '') <> ''\n ON CONFLICT (tenant_id, supplier_cnpj, supplier_product_code) DO UPDATE SET\n product_id = EXCLUDED.product_id,\n entry_type = EXCLUDED.entry_type,\n chart_account_id = coalesce(EXCLUDED.chart_account_id, public.plg_fiscalbr_supplier_product_map.chart_account_id),\n stock_unit_id = coalesce(EXCLUDED.stock_unit_id, public.plg_fiscalbr_supplier_product_map.stock_unit_id),\n conversion_factor = EXCLUDED.conversion_factor,\n cost_mode = EXCLUDED.cost_mode,\n hit_count = public.plg_fiscalbr_supplier_product_map.hit_count + 1,\n last_used_at = now(),\n updated_at = now();\n\n RETURN jsonb_build_object(\n 'document_id', v_doc.id, 'already_accepted', false,\n 'invoice_id', v_invoice, 'invoice_total', v_total,\n 'installments', jsonb_array_length(v_insts),\n 'operation_id', v_recv->>'operation_id',\n 'stock_lines', v_stock_n,\n 'movements', coalesce(v_recv->'movements', '[]'::jsonb));\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_accept_inbox_document(uuid, uuid) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_accept_inbox_document(uuid, uuid) TO authenticated;\n\n-- ── Rejeitar ───────────────────────────────────────────────────────────────\n-- O rodapé do diálogo do V1 tem dois botões, e o outro também precisa existir:\n-- recusar a nota é dizer que ela não vira nada aqui — sem apagar o documento,\n-- que é fiscal e tem de continuar legível.\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_reject_inbox_document(\n p_document_id uuid, p_reason text DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.edit', v_doc.unit_id);\n\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RAISE EXCEPTION 'fiscalbr: nota % já virou estoque ou título — recusar não desfaz', p_document_id\n USING ERRCODE = '23514';\n END IF;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n status = 'rejected',\n metadata = metadata || jsonb_strip_nulls(jsonb_build_object('rejectReason', p_reason)),\n reviewed_at = now(), updated_at = now()\n WHERE id = v_doc.id;\n\n RETURN jsonb_build_object('document_id', v_doc.id, 'status', 'rejected');\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_reject_inbox_document(uuid, text) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_reject_inbox_document(uuid, text) TO authenticated;\n`\n\nexport const MIGRATION_010_A_DATA_DE_EMISSAO_E_INSTANTE_E_A_COMPETENCIA_E_DIA = `-- ---------------------------------------------------------------------------\n-- 010_a_data_de_emissao_e_instante_e_a_competencia_e_dia.sql\n--\n-- A 009 não conseguia aceitar nota nenhuma. Descoberto no primeiro teste com\n-- usuário logado de verdade, que é onde ela ia ser usada:\n--\n-- POST rpc/fiscalbr_accept_inbox_document → 404\n-- function public.financial_create_invoice(unknown, numeric, uuid, unknown,\n-- uuid, jsonb, timestamp with time zone, text, unknown, jsonb, text)\n-- does not exist\n--\n-- \\`plg_fiscalbr_inbox_documents.issue_date\\` é **timestamptz** — a NF-e declara um\n-- INSTANTE (\\`dhEmi\\`, com fuso), e a 002 preservou isso. Eu escrevi a chamada\n-- supondo \\`date\\`, e \\`financial_create_invoice\\` pede \\`p_competence_date date\\`.\n--\n-- Nenhum teste pegou porque nenhum podia: o SQL aplica, a função compila (o corpo\n-- de PL/pgSQL não resolve assinatura em CREATE), e o erro só existe na chamada.\n-- Foi preciso um usuário logado percorrendo o caminho.\n--\n-- ── Duas correções, não uma ────────────────────────────────────────────────\n--\n-- 1. \\`issue_date::date\\` onde a competência é pedida. Instante é quando a nota foi\n-- emitida; competência é o DIA a que o título pertence, e o mês do título vem\n-- dela — um \\`timestamptz\\` viajando para lá levaria fuso para dentro de uma\n-- conta contábil.\n--\n-- 2. **Todo argumento tipado na chamada.** A chamada posicional passava \\`'payable'\\`\n-- e \\`NULL\\` sem tipo, e o Postgres tem de adivinhar entre as sobrecargas. Adivinhar\n-- certo hoje e errado quando alguém acrescentar uma sobrecarga é o defeito que\n-- volta meses depois sem ninguém mexer neste arquivo. Agora vai \\`::text\\`,\n-- \\`::uuid\\`, \\`::date\\` em tudo.\n--\n-- Idempotente: só substitui o corpo de uma função.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_accept_inbox_document(\n p_document_id uuid,\n p_location_id uuid DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_loc uuid;\n v_lines jsonb := '[]'::jsonb;\n v_insts jsonb := '[]'::jsonb;\n v_recv jsonb;\n v_inv jsonb;\n v_it record;\n v_no integer := 0;\n v_total numeric := 0;\n v_stock_n integer := 0;\n v_key text;\n v_invoice uuid;\n v_item_ids uuid[] := '{}';\n -- A competência: o DIA da emissão, não o instante.\n v_competence date;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.create', v_doc.unit_id);\n\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RETURN jsonb_build_object('document_id', v_doc.id, 'already_accepted', true,\n 'invoice_id', v_doc.invoice_id, 'operation_id', v_doc.inventory_operation_id);\n END IF;\n\n v_loc := coalesce(p_location_id, v_doc.default_location_id);\n v_competence := (v_doc.issue_date)::date;\n\n IF EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id\n AND (entry_type IS NULL OR entry_type = '')) THEN\n RAISE EXCEPTION 'fiscalbr: há item sem tipo de registro — conciliar antes de aceitar'\n USING ERRCODE = '23514';\n END IF;\n\n FOR v_it IN\n SELECT * FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id\n AND entry_type IN ('insumo','revenda','patrimonio')\n ORDER BY item_number\n LOOP\n IF v_it.product_id IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: item % é % e não tem produto vinculado', v_it.item_number, v_it.entry_type\n USING ERRCODE = '23514';\n END IF;\n v_no := v_no + 1;\n v_item_ids := v_item_ids || v_it.id;\n v_lines := v_lines || jsonb_build_object(\n 'product_id', v_it.product_id,\n 'quantity', coalesce(v_it.stock_quantity, v_it.quantity_commercial * v_it.conversion_factor),\n 'unit_cost', coalesce(v_it.unit_cost_new, v_it.unit_price_commercial / v_it.conversion_factor),\n 'measurement_unit_id', v_it.stock_unit_id,\n 'notes', v_it.description);\n END LOOP;\n v_stock_n := v_no;\n\n IF v_stock_n > 0 THEN\n IF v_loc IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: a nota tem % linha(s) de estoque e nenhum local de estoque escolhido', v_stock_n\n USING ERRCODE = '22023';\n END IF;\n v_recv := public.inventory_receive(\n v_loc::uuid,\n v_lines::jsonb,\n jsonb_build_object(\n 'supplier_id', v_doc.supplier_party_id,\n -- O documento do estoque também quer o DIA.\n 'date', v_competence,\n 'type', 'nfe',\n 'ref', 'NF-e ' || coalesce(v_doc.nfe_number, '?'),\n 'notes', 'Entrada via DANFE NF-e ' || coalesce(v_doc.nfe_number, '?')),\n ('nfe:' || v_doc.access_key)::text);\n\n UPDATE public.plg_fiscalbr_inbox_items i\n SET stock_movement_id = m.movement_id, updated_at = now()\n FROM (\n SELECT v_item_ids[(mov->>'line_no')::int] AS item_id, (mov->>'id')::uuid AS movement_id\n FROM jsonb_array_elements(coalesce(v_recv->'movements', '[]'::jsonb)) AS t(mov)\n WHERE (mov->>'line_no') IS NOT NULL\n ) m\n WHERE i.tenant_id = v_tenant AND i.id = m.item_id;\n END IF;\n\n SELECT coalesce(sum(value), 0),\n coalesce(jsonb_agg(jsonb_build_object(\n 'number', coalesce(duplicate_index, 1),\n 'due_date', coalesce(due_date, v_competence, current_date),\n 'amount', round(value, 2),\n 'metadata', jsonb_strip_nulls(jsonb_build_object(\n 'barcode', barcode, 'pixKey', pix_key, 'paymentType', payment_type,\n 'danfeNumber', number))) ORDER BY duplicate_index), '[]'::jsonb)\n INTO v_total, v_insts\n FROM public.plg_fiscalbr_inbox_duplicates\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n IF jsonb_array_length(v_insts) = 0 THEN\n v_total := round(coalesce(v_doc.total_value, 0), 2);\n v_insts := jsonb_build_array(jsonb_build_object(\n 'number', 1, 'due_date', coalesce(v_competence, current_date), 'amount', v_total));\n ELSE\n v_total := round(v_total, 2);\n END IF;\n\n v_key := 'danfe:' || v_doc.access_key;\n\n -- TODO argumento tipado. A chamada posicional sem tipo obrigava o Postgres a\n -- adivinhar entre sobrecargas, e foi assim que esta função nasceu quebrada.\n v_inv := public.financial_create_invoice(\n 'payable'::text,\n v_total::numeric,\n v_doc.supplier_party_id::uuid,\n NULL::uuid,\n v_doc.unit_id::uuid,\n v_insts::jsonb,\n v_competence::date,\n ('NF-e ' || coalesce(v_doc.nfe_number, '?') || ' · ' || coalesce(v_doc.supplier_name, 'fornecedor'))::text,\n NULL::text,\n jsonb_build_object(\n 'source', 'danfe',\n 'danfe', jsonb_strip_nulls(jsonb_build_object(\n 'accessKey', v_doc.access_key, 'number', v_doc.nfe_number,\n 'series', v_doc.nfe_series, 'supplierName', v_doc.supplier_name,\n 'supplierCnpj', v_doc.supplier_cnpj,\n 'noteTotal', v_doc.total_value,\n 'inboxDocumentId', v_doc.id)))::jsonb,\n v_key::text);\n v_invoice := (v_inv->>'invoice_id')::uuid;\n\n INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)\n SELECT v_tenant, v_invoice, i.description, i.quantity_commercial, i.unit_price_commercial,\n round(coalesce(i.total_price, 0), 2), i.item_number,\n jsonb_strip_nulls(jsonb_build_object(\n 'itemKind', i.entry_type, 'referenceId', i.product_id,\n 'chartAccountId', i.chart_account_id, 'ncm', i.ncm, 'cfop', i.cfop,\n 'supplierProductCode', i.supplier_product_code))\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n ORDER BY i.item_number\n ON CONFLICT DO NOTHING;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n invoice_id = v_invoice,\n inventory_operation_id = coalesce((v_recv->>'operation_id')::uuid, inventory_operation_id),\n stocked_at = CASE WHEN v_stock_n > 0 THEN now() ELSE stocked_at END,\n status = 'accepted', updated_at = now()\n WHERE id = v_doc.id;\n\n INSERT INTO public.plg_fiscalbr_supplier_product_map (\n tenant_id, supplier_cnpj, supplier_product_code, product_id, entry_type,\n chart_account_id, stock_unit_id, conversion_factor, cost_mode, hit_count, last_used_at)\n SELECT v_tenant, v_doc.supplier_cnpj, i.supplier_product_code, i.product_id,\n i.entry_type, coalesce(i.chart_account_id, v_doc.default_chart_account_id),\n i.stock_unit_id, i.conversion_factor, i.cost_mode, 1, now()\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n AND i.product_id IS NOT NULL\n AND coalesce(v_doc.supplier_cnpj, '') <> ''\n AND coalesce(i.supplier_product_code, '') <> ''\n ON CONFLICT (tenant_id, supplier_cnpj, supplier_product_code) DO UPDATE SET\n product_id = EXCLUDED.product_id,\n entry_type = EXCLUDED.entry_type,\n chart_account_id = coalesce(EXCLUDED.chart_account_id, public.plg_fiscalbr_supplier_product_map.chart_account_id),\n stock_unit_id = coalesce(EXCLUDED.stock_unit_id, public.plg_fiscalbr_supplier_product_map.stock_unit_id),\n conversion_factor = EXCLUDED.conversion_factor,\n cost_mode = EXCLUDED.cost_mode,\n hit_count = public.plg_fiscalbr_supplier_product_map.hit_count + 1,\n last_used_at = now(),\n updated_at = now();\n\n RETURN jsonb_build_object(\n 'document_id', v_doc.id, 'already_accepted', false,\n 'invoice_id', v_invoice, 'invoice_total', v_total,\n 'installments', jsonb_array_length(v_insts),\n 'operation_id', v_recv->>'operation_id',\n 'stock_lines', v_stock_n,\n 'movements', coalesce(v_recv->'movements', '[]'::jsonb));\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_accept_inbox_document(uuid, uuid) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_accept_inbox_document(uuid, uuid) TO authenticated;\n`\n\nexport const MIGRATION_011_O_IMPOSTO_DO_PRODUTO_E_DO_FISCAL = `-- O imposto do PRODUTO mora no fiscal, não no estoque.\n--\n-- No V1 as dezessete colunas de tributo (NCM, CFOP, CST, PIS, COFINS, CEST, FCP\n-- e os dois campos novos da reforma) ficam numa tabela do módulo de estoque,\n-- ao lado de quantidade mínima e temperatura de armazenamento. O salão que\n-- nunca emitiu uma nota carrega as dezessete do mesmo jeito.\n--\n-- Aqui elas ficam onde o assunto é: \\`plg_fiscalbr_tax_groups\\` já guarda a\n-- mesma lista para o GRUPO fiscal, e esta tabela é o que um produto tem de\n-- diferente do grupo dele. Produto sem nada de fiscal não tem linha nenhuma, e\n-- o estoque de quem não emite nota não muda de forma.\n--\n-- \\`tax_group_id\\` é a herança e as outras colunas são a exceção: NULL aqui quer\n-- dizer «vale o que o grupo diz», não «zero». Por isso nenhuma tem DEFAULT 0 —\n-- um zero gravado afirmaria alíquota zero e sobrescreveria o grupo em silêncio.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_product_tax_info (\n product_id uuid PRIMARY KEY REFERENCES public.products(id) ON DELETE CASCADE,\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n tax_group_id uuid REFERENCES public.plg_fiscalbr_tax_groups(id) ON DELETE SET NULL,\n\n -- Nomenclatura Comum do Mercosul: é do PRODUTO, nunca do grupo. É o campo que\n -- o V1 preenche mesmo quando nenhum outro está preenchido.\n ncm text,\n cest text,\n icms_origin text,\n icms_rate numeric(9,4),\n cfop text,\n cst text,\n pis_situation text,\n pis_rate numeric(9,4),\n cofins_situation text,\n cofins_rate numeric(9,4),\n base_calculation_mode text,\n benefit_code text,\n poverty_fund_rate numeric(9,4),\n\n -- Reforma tributária. Entram agora pelo mesmo motivo que entraram no grupo:\n -- deixar de fora obrigaria a recadastrar o catálogo inteiro no dia em que\n -- IBS e CBS valerem.\n ibs_cbs_situation text,\n ibs_cbs_classification text,\n\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_product_tax_info_tenant_idx\n ON public.plg_fiscalbr_product_tax_info (tenant_id);\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_product_tax_info_group_idx\n ON public.plg_fiscalbr_product_tax_info (tax_group_id);\n\nALTER TABLE public.plg_fiscalbr_product_tax_info ENABLE ROW LEVEL SECURITY;\n\n-- Quem lê e escreve é quem cuida do CADASTRO do produto, não quem emite a\n-- nota: a aba Fiscal do V1 vive dentro do formulário do produto, e exigir\n-- permissão de financeiro ali esconderia a seção do estoquista que digita o\n-- NCM da mercadoria que acabou de chegar.\nDROP POLICY IF EXISTS plg_fiscalbr_product_tax_info_authz_select ON public.plg_fiscalbr_product_tax_info;\nCREATE POLICY plg_fiscalbr_product_tax_info_authz_select\n ON public.plg_fiscalbr_product_tax_info FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('inventory.read', NULL::uuid)));\n\nDROP POLICY IF EXISTS plg_fiscalbr_product_tax_info_authz_write ON public.plg_fiscalbr_product_tax_info;\nCREATE POLICY plg_fiscalbr_product_tax_info_authz_write\n ON public.plg_fiscalbr_product_tax_info FOR ALL TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('inventory.edit', NULL::uuid)))\n WITH CHECK (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('inventory.edit', NULL::uuid)));\n\nGRANT ALL ON TABLE public.plg_fiscalbr_product_tax_info TO authenticated;\nGRANT ALL ON TABLE public.plg_fiscalbr_product_tax_info TO service_role;\n\nCOMMENT ON TABLE public.plg_fiscalbr_product_tax_info IS\n 'Tributos do produto — a exceção ao grupo fiscal. Espelha a aba Fiscal do cadastro de produto do V1 (product_fiscal_info). NULL herda do grupo.';\n`\n\nexport const MIGRATION_012_QUEM_E_O_PRODUTO_SE_PERGUNTA_AO_INDICE = `-- ---------------------------------------------------------------------------\n-- Quem é o produto desta linha da nota: pergunta-se ao índice, não ao modelo.\n-- ---------------------------------------------------------------------------\n-- A sugestão de IA da entrada de notas mandava o CATÁLOGO para o modelo. O V1\n-- mandava 400 produtos em todo turno (\\`.slice(0, 400)\\` sobre um \\`.limit(800)\\`\n-- sem \\`order by\\` — o corte era arbitrário, e acima de 400 produtos a function\n-- respondia «crie este produto» para produto cadastrado, sem aviso).\n--\n-- O custo disso é \\`catálogo × notas\\`. Num tenant de 171 produtos são ~3,5k\n-- tokens por nota; num distribuidor de 8.000 são ~160k e não cabe no turno. E a\n-- varredura de catálogo não é trabalho de modelo: é trabalho de índice.\n--\n-- Esta função é a pré-seleção, em TRÊS fases, e a primeira que acerta encerra a\n-- linha:\n--\n-- supplier_map o de-para do fornecedor. O que aquele CNPJ já ensinou não se\n-- pergunta de novo — e numa nota repetida isso resolve a nota\n-- inteira, então a IA nem roda.\n-- ean código de barras contra o cadastro. Igualdade, não palpite.\n-- text semelhança de texto, com os candidatos que sobraram.\n--\n-- \\`reason\\` é o que a tela usa para decidir: \\`supplier_map\\` e \\`ean\\` são VÍNCULO\n-- (liga sozinho), \\`text\\` é CANDIDATO (vai para o modelo desambiguar). Sem essa\n-- coluna a tela trataria um EAN exato como um chute de trigrama.\n--\n-- A fase de texto NÃO reimplementa busca: ela chama \\`public.global_search\\`, que\n-- já tem índice GIN de trigrama, \\`fayz_norm()\\` (tira acento, minúscula, colapsa\n-- pontuação) e a escada de pontuação da casa. Reescrever isso pior era o erro\n-- que o \\`ILIKE\\` da descrição fatiada em 24 caracteres já estava cometendo do\n-- lado do cliente — \\`name.ilike.%SACO PLASTICO 10X15 TRAN%\\` não casa acento,\n-- ordem de palavra nem abreviação, e o resultado mais comum era zero candidatos.\n--\n-- O RPC foi renomeado na 137 (\\`fayz_global_search\\` → \\`global_search\\`) e há pool\n-- em cada lado. Aqui se descobre o nome em tempo de execução, como o cliente já\n-- faz em \\`@fayz-ai/core/search\\`.\n--\n-- NÃO é SECURITY DEFINER. Roda como quem chamou, a RLS de \\`products\\` vale, e o\n-- tenant vem de \\`app.current_tenant_id()\\` — o cliente não passa tenant e por\n-- isso não pode passar o de outra conta.\n--\n-- \\`SET search_path\\` é explícito porque \\`similarity\\`/\\`word_similarity\\` moram em\n-- \\`extensions\\`: corpo com search_path vazio passa no DDL e estoura na primeira\n-- chamada.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_match_product_candidates(\n -- [{ \"ref\": \"<id do item>\", \"text\": \"SACO PLASTICO 10X15\", \"ean\": \"789…\", \"code\": \"ABC1\" }]\n p_queries jsonb,\n p_supplier_cnpj text DEFAULT NULL,\n p_per_query integer DEFAULT 8\n) RETURNS TABLE (\n ref text,\n product_id uuid,\n name text,\n sku text,\n unit text,\n cost numeric,\n score real,\n reason text\n)\nLANGUAGE plpgsql\nSTABLE\nSET search_path TO 'public', 'extensions', 'pg_temp'\nAS $fn$\nDECLARE\n v_tenant uuid := (SELECT app.current_tenant_id());\n v_cnpj text := public.fayz_digits(coalesce(p_supplier_cnpj, ''));\n v_barcodes boolean := to_regclass('public.plg_inventory_product_barcodes') IS NOT NULL;\n v_map boolean := to_regclass('public.plg_fiscalbr_supplier_product_map') IS NOT NULL;\n v_search text;\n v_q record;\n v_found uuid;\nBEGIN\n IF v_tenant IS NULL THEN RETURN; END IF;\n IF p_queries IS NULL OR jsonb_typeof(p_queries) <> 'array' THEN RETURN; END IF;\n p_per_query := least(greatest(coalesce(p_per_query, 8), 1), 50);\n\n v_search := CASE\n WHEN to_regprocedure('public.global_search(text,uuid,text[],integer,integer)') IS NOT NULL\n THEN 'public.global_search'\n WHEN to_regprocedure('public.fayz_global_search(text,uuid,text[],integer,integer)') IS NOT NULL\n THEN 'public.fayz_global_search'\n ELSE NULL\n END;\n\n FOR v_q IN\n SELECT e->>'ref' AS ref,\n coalesce(e->>'text', '') AS text,\n public.fayz_digits(coalesce(e->>'ean', '')) AS ean,\n nullif(btrim(coalesce(e->>'code', '')), '') AS code\n FROM jsonb_array_elements(p_queries) AS e\n WHERE e->>'ref' IS NOT NULL\n LOOP\n v_found := NULL;\n\n -- ① O de-para do fornecedor. Aprendizado da casa, e ele ganha de tudo.\n IF v_map AND v_cnpj <> '' AND v_q.code IS NOT NULL THEN\n SELECT p.id INTO v_found\n FROM public.plg_fiscalbr_supplier_product_map m\n JOIN public.products p ON p.id = m.product_id\n WHERE m.supplier_cnpj = v_cnpj\n AND m.supplier_product_code = v_q.code\n AND p.is_active\n ORDER BY m.hit_count DESC NULLS LAST, m.last_used_at DESC NULLS LAST\n LIMIT 1;\n\n IF v_found IS NOT NULL THEN\n RETURN QUERY\n SELECT v_q.ref, p.id, p.name, p.sku, p.unit, p.cost, 1.0::real, 'supplier_map'::text\n FROM public.products p WHERE p.id = v_found;\n CONTINUE;\n END IF;\n END IF;\n\n -- ② O código de barras. O produto guarda o principal em \\`metadata->>barcode\\`\n -- (no V1 era coluna) e os demais na tabela de códigos do estoque.\n IF length(v_q.ean) >= 8 THEN\n SELECT p.id INTO v_found\n FROM public.products p\n WHERE p.is_active\n AND (\n public.fayz_digits(coalesce(p.metadata->>'barcode', '')) = v_q.ean\n OR (v_barcodes AND EXISTS (\n SELECT 1 FROM public.plg_inventory_product_barcodes b\n WHERE b.product_id = p.id\n AND public.fayz_digits(coalesce(b.barcode, '')) = v_q.ean))\n )\n LIMIT 1;\n\n IF v_found IS NOT NULL THEN\n RETURN QUERY\n SELECT v_q.ref, p.id, p.name, p.sku, p.unit, p.cost, 1.0::real, 'ean'::text\n FROM public.products p WHERE p.id = v_found;\n CONTINUE;\n END IF;\n END IF;\n\n -- ③ Semelhança de texto, pela busca indexada que já existe.\n CONTINUE WHEN v_search IS NULL OR length(public.fayz_norm(v_q.text)) < 3;\n\n RETURN QUERY EXECUTE format($q$\n SELECT $4::text, p.id, p.name, p.sku, p.unit, p.cost, g.score, 'text'::text\n FROM %s($1, $2, ARRAY['product']::text[], $3, $3) g\n JOIN public.products p ON p.id = g.record_id::uuid\n WHERE p.is_active\n ORDER BY g.score DESC\n $q$, v_search)\n USING v_q.text, v_tenant, p_per_query, v_q.ref;\n END LOOP;\nEND\n$fn$;\n\nGRANT EXECUTE ON FUNCTION public.fiscalbr_match_product_candidates(jsonb, text, integer) TO authenticated;\n\nCOMMENT ON FUNCTION public.fiscalbr_match_product_candidates(jsonb, text, integer) IS\n 'Pré-seleção de produtos para a sugestão de IA da entrada de notas: de-para do fornecedor e EAN resolvem sozinhos (reason supplier_map/ean, vínculo direto); o resto volta como candidatos de texto (reason text) para o modelo desambiguar. Uma viagem para a nota inteira — substitui o despejo de 400 produtos do V1 e o ILIKE da descrição fatiada.';\n`\n\nexport const MIGRATION_013_A_SUGESTAO_SOBREVIVE_A_FECHAR_A_JANELA = `-- ---------------------------------------------------------------------------\n-- A sugestão sobrevive a fechar a janela — e diz QUEM escreveu no campo.\n-- ---------------------------------------------------------------------------\n-- A conciliação virou modal para a lista não ser desmontada. O efeito colateral\n-- é que o modal fecha com clique fora e com Esc, e a sugestão só existia em\n-- memória até alguém clicar em «Salvar conciliação»:\n--\n-- sugerir (30s de IA) → revisar 7 de 11 itens → clique fora → perdeu os 11\n--\n-- No V1 fechar não custava nada, porque a edge function já tinha gravado. Então\n-- a V2 grava também, logo depois da sugestão, pelo caminho que já existia\n-- (\\`fiscalbr_save_inbox_decision\\`, que não marca \\`reconciled\\`) — nenhum segundo\n-- caminho de escrita, nenhuma coluna \\`ai_*\\` paralela aos campos de verdade.\n--\n-- O que faltava era a MEMÓRIA DE AUTORIA. Depois de recarregar, a tela via um\n-- fator 22,056 e não sabia se foi a Laissa que digitou ou a máquina que chutou —\n-- e as duas coisas se conferem de maneiras diferentes.\n--\n-- O V1 guardava um booleano, \\`ai_suggested\\`. Aqui é texto, porque a V2 tem TRÊS\n-- autores de máquina e eles não merecem o mesmo selo:\n--\n-- supplier_map o de-para deste fornecedor. Igualdade, e aprendizado da casa.\n-- ean código de barras. Igualdade.\n-- ai semelhança julgada por modelo. É o único que se confere item\n-- a item, e \\`suggestion_confidence\\` diz o quanto.\n--\n-- NULL é a resposta mais importante: significa «uma pessoa escolheu isto». O\n-- cliente limpa a coluna em qualquer edição do campo, então o selo nunca mente\n-- sobre um valor que alguém corrigiu à mão.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_fiscalbr_inbox_items\n ADD COLUMN IF NOT EXISTS suggested_by text,\n ADD COLUMN IF NOT EXISTS suggestion_confidence numeric;\n\nDO $$\nBEGIN\n IF NOT EXISTS (\n SELECT 1 FROM pg_constraint\n WHERE conname = 'plg_fiscalbr_inbox_items_suggested_by_check'\n AND conrelid = 'public.plg_fiscalbr_inbox_items'::regclass\n ) THEN\n ALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_suggested_by_check\n CHECK (suggested_by IS NULL OR suggested_by IN ('ai', 'ean', 'supplier_map'));\n END IF;\nEND $$;\n\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.suggested_by IS\n 'Quem escreveu a decisão desta linha: ai (modelo, confira), ean / supplier_map (igualdade), NULL (uma pessoa). O cliente limpa em qualquer edição manual.';\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.suggestion_confidence IS\n '0..1, só para suggested_by = ai. Abaixo de 0,6 a tela marca a linha como «confira».';\n\n-- ── A gravação da decisão passa a carregar a autoria ───────────────────────\n-- Mesma assinatura, então é \\`CREATE OR REPLACE\\` e nenhum chamador muda. O corpo\n-- é o da 009 com duas linhas a mais: o resto fica palavra por palavra, porque\n-- esta função é o único caminho de escrita da decisão e reescrevê-la de memória\n-- é como se perde uma regra (a de \\`reconciled\\`, por exemplo).\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_save_inbox_decision(\n p_document_id uuid,\n p_items jsonb,\n p_default_chart_account_id uuid DEFAULT NULL,\n p_default_location_id uuid DEFAULT NULL,\n p_duplicates jsonb DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_row jsonb;\n v_done integer := 0;\n v_total integer;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.edit', v_doc.unit_id);\n\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RAISE EXCEPTION 'fiscalbr: nota % já foi aceita — a decisão não muda depois do estoque', p_document_id\n USING ERRCODE = '23514';\n END IF;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n default_chart_account_id = coalesce(p_default_chart_account_id, default_chart_account_id),\n default_location_id = coalesce(p_default_location_id, default_location_id),\n reviewed_at = now(), updated_at = now()\n WHERE id = v_doc.id;\n\n FOR v_row IN SELECT * FROM jsonb_array_elements(coalesce(p_items, '[]'::jsonb)) LOOP\n UPDATE public.plg_fiscalbr_inbox_items i SET\n product_id = nullif(v_row->>'product_id', '')::uuid,\n entry_type = nullif(v_row->>'entry_type', ''),\n chart_account_id = nullif(v_row->>'chart_account_id', '')::uuid,\n stock_unit_id = nullif(v_row->>'stock_unit_id', '')::uuid,\n conversion_factor = coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1),\n cost_mode = coalesce(nullif(v_row->>'cost_mode', ''), 'novo'),\n shortage_quantity = nullif(v_row->>'shortage_quantity', '')::numeric,\n shortage_reason = nullif(v_row->>'shortage_reason', ''),\n shortage_note = nullif(v_row->>'shortage_note', ''),\n -- Quem escreveu. Ausente na chave é NULL, que é «uma pessoa escolheu» — e é\n -- o que acontece em todo salvamento comum, sem a IA ter passado por aqui.\n suggested_by = nullif(v_row->>'suggested_by', ''),\n suggestion_confidence = nullif(v_row->>'suggestion_confidence', '')::numeric,\n -- Derivadas, gravadas: é o que o operador viu.\n stock_quantity = i.quantity_commercial * coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1)\n - coalesce(nullif(v_row->>'shortage_quantity', '')::numeric, 0),\n unit_cost_new = CASE WHEN coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1) > 0\n THEN i.unit_price_commercial / coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1) END,\n -- Uma linha está conciliada quando sabe o que é. Despesa e serviço não\n -- pedem produto: elas nunca vão virar estoque.\n reconciled = CASE\n WHEN nullif(v_row->>'entry_type', '') IN ('despesa','servico') THEN true\n ELSE nullif(v_row->>'product_id', '') IS NOT NULL\n END,\n updated_at = now()\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n AND i.id = (v_row->>'id')::uuid;\n v_done := v_done + 1;\n END LOOP;\n\n IF p_duplicates IS NOT NULL THEN\n DELETE FROM public.plg_fiscalbr_inbox_duplicates\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n INSERT INTO public.plg_fiscalbr_inbox_duplicates (\n tenant_id, inbox_document_id, duplicate_index, number, due_date, value,\n payment_type, barcode, pix_key, payment_method_id)\n SELECT v_tenant, v_doc.id, coalesce((d->>'index')::int, ord), d->>'number',\n nullif(d->>'due_date', '')::date, (d->>'value')::numeric,\n nullif(d->>'payment_type', ''), nullif(d->>'barcode', ''),\n nullif(d->>'pix_key', ''), nullif(d->>'payment_method_id', '')::uuid\n FROM jsonb_array_elements(p_duplicates) WITH ORDINALITY AS t(d, ord);\n END IF;\n\n SELECT count(*) INTO v_total FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET status = CASE\n WHEN (SELECT count(*) FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id AND reconciled) = v_total\n THEN 'accepted' ELSE 'partial' END\n WHERE id = v_doc.id;\n\n RETURN jsonb_build_object('document_id', v_doc.id, 'saved', v_done, 'items', v_total,\n 'reconciled', (SELECT count(*) FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id AND reconciled));\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_save_inbox_decision(uuid, jsonb, uuid, uuid, jsonb) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_save_inbox_decision(uuid, jsonb, uuid, uuid, jsonb) TO authenticated;\n`\n\nexport const MIGRATION_014_A_DESCRICAO_DA_NOTA_TEM_LIXO_NO_MEIO = `-- ---------------------------------------------------------------------------\n-- A descrição da nota tem lixo no meio, e um token de lixo matava a busca.\n-- ---------------------------------------------------------------------------\n-- Caso real, primeira nota de verdade: o item «20X35 AR VACUO» voltou SEM\n-- candidato, e o produto \\`EMBALAGEM VACUO 20X35\\` está cadastrado.\n--\n-- \\`public.global_search\\` exige que TODOS os tokens apareçam no haystack — é a\n-- regra certa para gente digitando («joão silva» não deve trazer todos os joãos)\n-- e é a regra errada para descrição de NF-e. Os tokens de \\`20X35 AR VACUO\\` são\n-- \\`20x35\\`, \\`ar\\`, \\`vacuo\\`; o produto é \\`embalagem vacuo 20x35\\`. Dois casam. \\`ar\\`\n-- não aparece em lugar nenhum, e o AND derruba a linha inteira.\n--\n-- A segunda fase (\\`word_similarity\\`) também não salva: ela compara a frase\n-- inteira contra o haystack, e com um terço da frase sendo ruído a semelhança\n-- fica abaixo do limiar.\n--\n-- Descrição de nota fiscal é assim por natureza: abreviada, em ordem própria, com\n-- sigla de unidade, micragem e palavra solta no meio. Então o que entra na busca\n-- deixa de ser a frase e passa a ser O QUE NELA DISTINGUE:\n--\n-- ① tokens de 3 letras ou mais. «ar», «kg», «un», «c/», «p/» saem. «20x35»\n-- e «vacuo» ficam — e são eles que identificam o produto.\n-- ② se mesmo assim não vier nada, UMA última tentativa com o token mais longo\n-- sozinho. É o recuo que acha «embalagem a vácuo 15 x 25» a partir de\n-- «VACUO», para a pessoa escolher entre poucos em vez de nenhum.\n--\n-- Não se mexe em \\`global_search\\`: lá a regra está certa para quem ela serve.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_match_product_candidates(\n p_queries jsonb,\n p_supplier_cnpj text DEFAULT NULL,\n p_per_query integer DEFAULT 8\n) RETURNS TABLE (\n ref text,\n product_id uuid,\n name text,\n sku text,\n unit text,\n cost numeric,\n score real,\n reason text\n)\nLANGUAGE plpgsql\nSTABLE\nSET search_path TO 'public', 'extensions', 'pg_temp'\nAS $fn$\nDECLARE\n v_tenant uuid := (SELECT app.current_tenant_id());\n v_cnpj text := public.fayz_digits(coalesce(p_supplier_cnpj, ''));\n v_barcodes boolean := to_regclass('public.plg_inventory_product_barcodes') IS NOT NULL;\n v_map boolean := to_regclass('public.plg_fiscalbr_supplier_product_map') IS NOT NULL;\n v_search text;\n v_q record;\n v_found uuid;\n v_tokens text[];\n v_strong text[];\n v_busca text;\n v_recuo text;\nBEGIN\n IF v_tenant IS NULL THEN RETURN; END IF;\n IF p_queries IS NULL OR jsonb_typeof(p_queries) <> 'array' THEN RETURN; END IF;\n p_per_query := least(greatest(coalesce(p_per_query, 8), 1), 50);\n\n v_search := CASE\n WHEN to_regprocedure('public.global_search(text,uuid,text[],integer,integer)') IS NOT NULL\n THEN 'public.global_search'\n WHEN to_regprocedure('public.fayz_global_search(text,uuid,text[],integer,integer)') IS NOT NULL\n THEN 'public.fayz_global_search'\n ELSE NULL\n END;\n\n FOR v_q IN\n SELECT e->>'ref' AS ref,\n coalesce(e->>'text', '') AS text,\n public.fayz_digits(coalesce(e->>'ean', '')) AS ean,\n nullif(btrim(coalesce(e->>'code', '')), '') AS code\n FROM jsonb_array_elements(p_queries) AS e\n WHERE e->>'ref' IS NOT NULL\n LOOP\n v_found := NULL;\n\n -- ① O de-para do fornecedor. Aprendizado da casa, e ele ganha de tudo.\n IF v_map AND v_cnpj <> '' AND v_q.code IS NOT NULL THEN\n SELECT p.id INTO v_found\n FROM public.plg_fiscalbr_supplier_product_map m\n JOIN public.products p ON p.id = m.product_id\n WHERE m.supplier_cnpj = v_cnpj\n AND m.supplier_product_code = v_q.code\n AND p.is_active\n ORDER BY m.hit_count DESC NULLS LAST, m.last_used_at DESC NULLS LAST\n LIMIT 1;\n\n IF v_found IS NOT NULL THEN\n RETURN QUERY\n SELECT v_q.ref, p.id, p.name, p.sku, p.unit, p.cost, 1.0::real, 'supplier_map'::text\n FROM public.products p WHERE p.id = v_found;\n CONTINUE;\n END IF;\n END IF;\n\n -- ② O código de barras. «SEM GTIN» é o que a NF-e escreve quando não há — e\n -- \\`fayz_digits\\` o reduz a vazio, então o teste de comprimento já o barra.\n IF length(v_q.ean) >= 8 THEN\n SELECT p.id INTO v_found\n FROM public.products p\n WHERE p.is_active\n AND (\n public.fayz_digits(coalesce(p.metadata->>'barcode', '')) = v_q.ean\n OR (v_barcodes AND EXISTS (\n SELECT 1 FROM public.plg_inventory_product_barcodes b\n WHERE b.product_id = p.id\n AND public.fayz_digits(coalesce(b.barcode, '')) = v_q.ean))\n )\n LIMIT 1;\n\n IF v_found IS NOT NULL THEN\n RETURN QUERY\n SELECT v_q.ref, p.id, p.name, p.sku, p.unit, p.cost, 1.0::real, 'ean'::text\n FROM public.products p WHERE p.id = v_found;\n CONTINUE;\n END IF;\n END IF;\n\n -- ③ Semelhança de texto, com o que DISTINGUE em vez da frase inteira.\n CONTINUE WHEN v_search IS NULL;\n\n v_tokens := array_remove(string_to_array(public.fayz_norm(v_q.text), ' '), '');\n SELECT array_agg(t ORDER BY length(t) DESC) INTO v_strong\n FROM unnest(v_tokens) t WHERE length(t) >= 3;\n\n v_busca := array_to_string(coalesce(v_strong, v_tokens), ' ');\n -- O recuo é o token mais longo sozinho: numa descrição de nota ele é quase\n -- sempre o nome da coisa, e os outros são medida, micragem ou conjunção.\n v_recuo := coalesce(v_strong[1], '');\n\n CONTINUE WHEN length(v_busca) < 3;\n\n RETURN QUERY EXECUTE format($q$\n WITH forte AS (\n SELECT g.record_id, g.score FROM %1$s($1, $2, ARRAY['product']::text[], $3, $3) g\n ),\n -- Só quando a busca forte não achou nada: um recuo que rodasse sempre\n -- encheria a lista de parecidos e empurraria o certo para fora do teto.\n fraco AS (\n SELECT g.record_id, g.score * 0.7 AS score\n FROM %1$s($4, $2, ARRAY['product']::text[], $3, $3) g\n WHERE $4 <> '' AND $4 <> $1 AND NOT EXISTS (SELECT 1 FROM forte)\n )\n SELECT $5::text, p.id, p.name, p.sku, p.unit, p.cost, g.score::real, 'text'::text\n FROM (SELECT * FROM forte UNION ALL SELECT * FROM fraco) g\n JOIN public.products p ON p.id = g.record_id::uuid\n WHERE p.is_active\n ORDER BY g.score DESC\n $q$, v_search)\n USING v_busca, v_tenant, p_per_query, v_recuo, v_q.ref;\n END LOOP;\nEND\n$fn$;\n\nGRANT EXECUTE ON FUNCTION public.fiscalbr_match_product_candidates(jsonb, text, integer) TO authenticated;\n\nCOMMENT ON FUNCTION public.fiscalbr_match_product_candidates(jsonb, text, integer) IS\n 'Pré-seleção de produtos para a sugestão de IA da entrada de notas: de-para do fornecedor e EAN resolvem sozinhos (reason supplier_map/ean); o resto volta como candidatos de texto. A busca usa os tokens de 3+ letras da descrição, não a frase — «20X35 AR VACUO» achava nada porque o AND de global_search exige o token «ar», que não existe em «embalagem vacuo 20x35».';\n`\n\nexport const MIGRATION_015_O_MOVIMENTO_DIZ_QUE_VEIO_DA_NOTA = `-- ---------------------------------------------------------------------------\n-- O movimento de estoque diz, por escrito, que veio desta nota.\n-- ---------------------------------------------------------------------------\n-- A aceitação já mandava a frase para \\`inventory_receive\\`, na chave \\`notes\\` do\n-- cabeçalho — e ela nunca chegava: lá dentro o \\`coalesce(v_ln.notes, …)\\` dá a vez\n-- à anotação DA LINHA, que aqui é sempre a descrição do item. A tela de\n-- Movimentações então escrevia «Sem motivo registrado» sobre a entrada mais\n-- rastreável que existe.\n--\n-- \\`inventory/021\\` abriu a chave \\`reason\\` no cabeçalho. Esta migration passa a\n-- usá-la, com a mesma frase que as linhas migradas do V1 carregam — para que a\n-- entrada de ontem e a de hoje se leiam igual no mesmo razão.\n--\n-- Só a chamada muda. O resto do corpo é o da 009, palavra por palavra: esta\n-- função escreve estoque e título na mesma transação, e reescrevê-la de memória\n-- é como se perde uma regra.\n-- ---------------------------------------------------------------------------\n\nDO $m$\nDECLARE\n v_def text;\n v_antes text := E' ''ref'', ''NF-e '' || coalesce(v_doc.nfe_number, ''?''),\\\\n ''notes'', ''Entrada via DANFE NF-e '' || coalesce(v_doc.nfe_number, ''?'')),';\n v_depois text := E' ''ref'', ''NF-e '' || coalesce(v_doc.nfe_number, ''?''),\\\\n ''notes'', ''Entrada via DANFE NF-e '' || coalesce(v_doc.nfe_number, ''?''),\\\\n ''reason'', ''Entrada via DANFE NF-e '' || coalesce(v_doc.nfe_number, ''?'')),';\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def\n FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n\n IF v_def IS NULL THEN\n RAISE NOTICE 'fiscalbr: accept ainda não existe neste pool — 009 roda antes e já traz o reason';\n RETURN;\n END IF;\n\n -- Já aplicada: sair sem tocar em nada é o que torna esta migration repetível.\n IF position('''reason'', ''Entrada via DANFE' in v_def) > 0 THEN RETURN; END IF;\n\n IF position(v_antes in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/015: o corpo de fiscalbr_accept_inbox_document não é o esperado — confira à mão em vez de deixar passar calado';\n END IF;\n\n EXECUTE replace(v_def, v_antes, v_depois);\nEND $m$;\n`\n\nexport const MIGRATION_016_A_NOTA_GUARDA_O_PROPRIO_XML = `-- ---------------------------------------------------------------------------\n-- A nota guarda o próprio XML, em vez de lê-lo e jogar fora.\n-- ---------------------------------------------------------------------------\n-- O V1 abre o XML e o DANFE direto da lista de notas. A V2 mostrava os dois\n-- botões desligados porque não tinha o arquivo: das 889 notas deste cluster,\n-- ZERO têm \\`document_id\\`, zero têm bytes em \\`documents\\`, zero têm nada no\n-- metadata.\n--\n-- E não é que o arquivo nunca tenha passado por aqui — ele passa INTEIRO pela\n-- mão do estágio: o navegador lê o \\`.xml\\` que a pessoa arrastou, o parser extrai\n-- itens, parcelas e totais, e os bytes são descartados no fim da função. A nota\n-- fiscal é documento com guarda legal de cinco anos, e a única cópia ficava na\n-- pasta de downloads de quem importou.\n--\n-- \\`xml_content text\\` é o mesmo nome e o mesmo tipo do \\`dfe_inbox.xml_content\\` do\n-- V1 — a ponte da 003 já citava essa coluna, e repetir o nome é o que faz uma\n-- futura migração de dados ser um \\`INSERT ... SELECT\\` em vez de um de-para.\n--\n-- Guardar no banco e não no bucket, de propósito: são 10–50 KB de texto por nota\n-- e são o ÚNICO conteúdo que torna a linha auditável. Storage é outro sistema,\n-- com outra vida útil e outra política de acesso, e um XML fiscal que vive em\n-- bucket é um XML que alguém apaga limpando bucket.\n--\n-- Isto NÃO preenche as 889 notas antigas: o que não foi guardado não se inventa.\n-- A tela desliga o botão por nota, não por feature.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_fiscalbr_inbox_documents\n ADD COLUMN IF NOT EXISTS xml_content text;\n\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_documents.xml_content IS\n 'O XML autorizado da NF-e, como chegou. Nulo nas notas importadas antes desta coluna existir — o que não foi guardado não se inventa.';\n\n-- ── O estágio passa a guardar o que já tinha em mão ────────────────────────\n-- Patch sobre o corpo que está no cluster, e não reescrita: esta função insere\n-- documento, itens, duplicatas e pagamentos numa transação só, e reescrevê-la de\n-- memória é como se perde uma regra.\n\nDO $m$\nDECLARE\n v_def text;\n v_cols_antes text := E' total_freight, total_insurance, total_other, additional_info, metadata)';\n v_cols_depois text := E' total_freight, total_insurance, total_other, additional_info, metadata, xml_content)';\n v_vals_antes text := E' jsonb_build_object(''source'', coalesce(p_note->>''source'', ''xml_upload'')))';\n v_vals_depois text := E' jsonb_build_object(''source'', coalesce(p_note->>''source'', ''xml_upload'')),' || E'\\\\n' ||\n E' nullif(p_note->>''xml'', ''''))';\n v_upd_antes text := E' total_value = EXCLUDED.total_value,';\n v_upd_depois text := E' total_value = EXCLUDED.total_value,' || E'\\\\n' ||\n E' -- Reimportar com o arquivo preenche o que faltava; reimportar sem ele' || E'\\\\n' ||\n E' -- não apaga o que já estava guardado.' || E'\\\\n' ||\n E' xml_content = coalesce(EXCLUDED.xml_content, public.plg_fiscalbr_inbox_documents.xml_content),';\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def\n FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_stage_inbox_document';\n\n IF v_def IS NULL THEN\n RAISE NOTICE 'fiscalbr/016: o estágio ainda não existe neste pool — a 009 roda antes';\n RETURN;\n END IF;\n\n -- Já aplicada: sair sem tocar em nada é o que torna esta migration repetível.\n IF position('xml_content' in v_def) > 0 THEN RETURN; END IF;\n\n IF position(v_cols_antes in v_def) = 0\n OR position(v_vals_antes in v_def) = 0\n OR position(v_upd_antes in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/016: o corpo de fiscalbr_stage_inbox_document não é o esperado — confira à mão em vez de deixar passar calado';\n END IF;\n\n v_def := replace(v_def, v_cols_antes, v_cols_depois);\n v_def := replace(v_def, v_vals_antes, v_vals_depois);\n v_def := replace(v_def, v_upd_antes, v_upd_depois);\n EXECUTE v_def;\nEND $m$;\n`\n\nexport const MIGRATION_017_QUEM_EMITE_E_O_CNPJ_NAO_A_LOJA = `-- Quem emite é o CNPJ, não a loja.\n--\n-- As abas \"Certificado\" e \"Emissão Fiscal\" do cadastro de empresa do V1\n-- guardam, em companies, como aquela pessoa jurídica emite NFS-e e NFC-e e se\n-- recebe DANFes da SEFAZ. No V2 a pessoa jurídica é\n-- public.company_legal_entities (base), e a filial chega nela por\n-- app.units.company_legal_entity_id (168). Esta tabela é uma linha por pessoa\n-- jurídica:\n--\n-- unidade → app.units.company_legal_entity_id → company_legal_entities.id\n-- → plg_fiscalbr_emitter_settings.legal_entity_id (UNIQUE)\n--\n-- Duas filiais com o mesmo CNPJ dividem a mesma configuração, como no V1.\n--\n-- O certificado A1 NÃO mora aqui. O .pfx e a senha vão direto ao provedor\n-- (PlugNotas) e o que fica é o recibo: id no provedor, titular e validade. O\n-- CSC da NFC-e é segredo — o navegador grava, mas não lê de volta: a coluna\n-- fica fora do GRANT SELECT e a tela vê só \\`nfce_csc_token_set\\`.\n--\n-- Plano aprovado em docs/port/empresa.schema.json. Idempotente.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_emitter_settings (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n legal_entity_id uuid NOT NULL,\n\n nfse_enabled boolean NOT NULL DEFAULT false,\n nfse_production boolean NOT NULL DEFAULT false,\n nfse_national boolean NOT NULL DEFAULT false,\n nfse_service_code_national text,\n nfse_service_code_municipal text,\n nfse_nbs_code text,\n nfse_cnae text,\n nfse_iss_rate numeric(5,2) CHECK (nfse_iss_rate IS NULL OR (nfse_iss_rate >= 0 AND nfse_iss_rate <= 100)),\n nfse_iss_taxation smallint,\n nfse_iss_exigibility smallint,\n nfse_ibscbs_cst text,\n nfse_ibscbs_classification text,\n nfse_simples_regime smallint,\n nfse_net_value boolean NOT NULL DEFAULT false,\n nfse_additional_info text,\n nfse_city_features jsonb,\n\n nfce_enabled boolean NOT NULL DEFAULT false,\n nfce_production boolean NOT NULL DEFAULT false,\n nfce_series integer CHECK (nfce_series IS NULL OR nfce_series > 0),\n nfce_csc_id text,\n nfce_csc_token text,\n nfce_csc_token_set boolean GENERATED ALWAYS AS (nfce_csc_token IS NOT NULL AND nfce_csc_token <> '') STORED,\n nfce_generic_item jsonb,\n\n nfe_enabled boolean NOT NULL DEFAULT false,\n\n certificate_provider_id text,\n certificate_cn text,\n certificate_expires_at timestamptz,\n certificate_uploaded_at timestamptz,\n\n dfe_sync_enabled boolean NOT NULL DEFAULT false,\n dfe_sync_cursor text,\n dfe_last_sync_at timestamptz,\n provider_synced_at timestamptz,\n\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE (tenant_id, id)\n);\n\nDO $$\nBEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_emitter_settings_legal_entity_fkey') THEN\n -- company_legal_entities é da base, não de outro plugin: a FK física é\n -- permitida (a regra do 000 proíbe FK entre PLUGINS).\n ALTER TABLE ONLY public.plg_fiscalbr_emitter_settings\n ADD CONSTRAINT plg_fiscalbr_emitter_settings_legal_entity_fkey\n FOREIGN KEY (legal_entity_id) REFERENCES public.company_legal_entities(id) ON DELETE CASCADE;\n END IF;\nEND $$;\n\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_emitter_settings_legal_entity_uidx\n ON public.plg_fiscalbr_emitter_settings USING btree (legal_entity_id);\n\nCOMMENT ON TABLE public.plg_fiscalbr_emitter_settings IS\n 'V1: companies (abas Certificado + Emissão Fiscal). Como uma pessoa jurídica emite NFS-e/NFC-e e recebe DANFes. Uma linha por CNPJ; a filial chega por app.units.company_legal_entity_id.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.legal_entity_id IS 'A chave que conecta: company_legal_entities.id. UNIQUE.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_production IS 'V1: companies.nfse_producao — false = homologação.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_national IS 'V1: companies.nfse_nacional — padrão nacional × municipal.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_service_code_national IS 'V1: companies.nfse_codigo_tributacao_nacional';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_service_code_municipal IS 'V1: companies.nfse_codigo_tributacao_municipio';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_nbs_code IS 'V1: companies.nfse_codigo_nbs';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_cnae IS 'V1: companies.nfse_cnae — CNAE do serviço, pode diferir do principal.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_iss_rate IS 'V1: companies.nfse_iss_aliquota (%)';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_iss_taxation IS 'V1: companies.nfse_iss_tipo_tributacao';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_iss_exigibility IS 'V1: companies.nfse_iss_exigibilidade';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_simples_regime IS 'V1: companies.nfse_regime_apuracao_sn — só para optante do Simples.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_net_value IS 'V1: companies.nfse_valor_liquido — emitir pelo valor líquido.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_city_features IS 'V1: companies.nfse_city_features — o que a prefeitura aceita, devolvido pelo provedor.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfce_csc_token IS 'V1: companies.nfce_csc_token — SEGREDO. Fora do GRANT SELECT de authenticated.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfce_generic_item IS 'V1: companies.nfce_item_generico — {ncm, cfop, csosn}.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.certificate_provider_id IS 'V1: companies.certificate_plugnotas_id — recibo; o .pfx não fica no banco.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.dfe_sync_enabled IS 'V1: companies.dfe_sync_enabled — receber DANFes automaticamente.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.dfe_sync_cursor IS 'V1: companies.dfe_sync_cursor — NSU onde a busca na SEFAZ parou.';\n\nALTER TABLE public.plg_fiscalbr_emitter_settings ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_emitter_settings FORCE ROW LEVEL SECURITY;\n\n-- O segredo fica fora do SELECT: grava-se, não se lê.\nREVOKE ALL ON TABLE public.plg_fiscalbr_emitter_settings FROM anon, authenticated;\nGRANT INSERT, UPDATE, DELETE ON TABLE public.plg_fiscalbr_emitter_settings TO authenticated;\nGRANT SELECT (\n id, tenant_id, legal_entity_id,\n nfse_enabled, nfse_production, nfse_national, nfse_service_code_national, nfse_service_code_municipal,\n nfse_nbs_code, nfse_cnae, nfse_iss_rate, nfse_iss_taxation, nfse_iss_exigibility, nfse_ibscbs_cst,\n nfse_ibscbs_classification, nfse_simples_regime, nfse_net_value, nfse_additional_info, nfse_city_features,\n nfce_enabled, nfce_production, nfce_series, nfce_csc_id, nfce_csc_token_set, nfce_generic_item,\n nfe_enabled, certificate_provider_id, certificate_cn, certificate_expires_at, certificate_uploaded_at,\n dfe_sync_enabled, dfe_sync_cursor, dfe_last_sync_at, provider_synced_at, created_at, updated_at\n) ON public.plg_fiscalbr_emitter_settings TO authenticated;\nGRANT ALL ON TABLE public.plg_fiscalbr_emitter_settings TO service_role;\n\nDROP POLICY IF EXISTS plg_fiscalbr_emitter_settings_authz_select ON public.plg_fiscalbr_emitter_settings;\nCREATE POLICY plg_fiscalbr_emitter_settings_authz_select ON public.plg_fiscalbr_emitter_settings\n FOR SELECT TO authenticated USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL::uuid)));\n\nDROP POLICY IF EXISTS plg_fiscalbr_emitter_settings_authz_write ON public.plg_fiscalbr_emitter_settings;\nCREATE POLICY plg_fiscalbr_emitter_settings_authz_write ON public.plg_fiscalbr_emitter_settings\n FOR ALL TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('settings.manage', NULL::uuid)))\n WITH CHECK (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('settings.manage', NULL::uuid))\n AND EXISTS (SELECT 1 FROM public.company_legal_entities le\n WHERE le.id = plg_fiscalbr_emitter_settings.legal_entity_id\n AND le.tenant_id = plg_fiscalbr_emitter_settings.tenant_id));\n`\n\nexport const MIGRATION_018_A_NOTA_DO_V1_ALCANCA_A_CONTA = `-- A nota que veio do V1 alcança a conta que a gerou.\n--\n-- A conta a receber pergunta \"que notas eu tenho?\" pelo pedido dela:\n-- plg_financial_invoices.order_id → plg_fiscalbr_document_orders → a nota.\n-- A importação só preencheu esse vínculo a partir da tabela N:N do V1\n-- (fiscal_document_invoice_sources). A NFS-e do V1 nunca usou essa tabela: ela\n-- aponta a conta por fiscal_documents.invoice_id, que chegou aqui apenas como\n-- metadata.v1.invoice_ref. Medido em 06-10-2026 no cluster do ChefControl: 488\n-- NFS-e e 122 NFC-e sem caminho até a conta.\n--\n-- A conta importada guarda o próprio id do V1 em\n-- metadata.migration.source_numeric_id, então o par se resolve sem adivinhar.\n-- Num pool sem dado do V1 isto não casa nada. Aditivo e idempotente.\n\nINSERT INTO public.plg_fiscalbr_document_orders (tenant_id, document_id, order_id)\nSELECT DISTINCT f.tenant_id, f.document_id, i.order_id\n FROM public.plg_fiscalbr_documents f\n JOIN public.plg_financial_invoices i\n ON i.tenant_id = f.tenant_id\n AND i.metadata -> 'migration' ->> 'source_table' = 'invoices'\n AND i.metadata -> 'migration' ->> 'source_numeric_id' = f.metadata -> 'v1' ->> 'invoice_ref'\n JOIN public.orders o ON o.id = i.order_id\n WHERE f.metadata -> 'v1' ->> 'invoice_ref' IS NOT NULL\nON CONFLICT (document_id, order_id) DO NOTHING;\n`\n\nexport const MIGRATION_019_A_NOTA_EMITIDA_SE_CANCELA_PELO_V2 = `-- A nota emitida se consulta e se cancela pelo V2.\n--\n-- Quem fala com a PlugNotas é a função \\`fiscalbr-plugnotas\\` (a chave só existe\n-- no servidor), mas ela roda com o JWT de quem clicou e não grava nada direto:\n-- pergunta aqui se a pessoa pode, e devolve o resultado aqui. Uma porta de\n-- leitura, uma de escrita, a permissão conferida nas duas.\n--\n-- consultar e baixar o PDF → financial.read na unidade da nota\n-- cancelar → financial.edit na unidade da nota\n--\n-- A espelho em \\`documents.status\\` anda junto: as duas tabelas são a mesma nota\n-- vista de dois lugares (005), e um status divergente entre elas é a nota\n-- dizendo duas coisas. Idempotente.\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_note_for_provider(p_document_id uuid, p_action text)\nRETURNS jsonb\nLANGUAGE plpgsql\nSTABLE SECURITY DEFINER\nSET search_path TO ''\nAS $$\nDECLARE\n v public.plg_fiscalbr_documents%ROWTYPE;\nBEGIN\n SELECT * INTO v FROM public.plg_fiscalbr_documents\n WHERE document_id = p_document_id AND tenant_id = app.current_tenant_id();\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscal: note not found' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission(\n CASE WHEN p_action = 'cancel' THEN 'financial.edit' ELSE 'financial.read' END, v.unit_id);\n RETURN jsonb_build_object(\n 'document_id', v.document_id, 'model', v.model, 'status', v.status,\n 'environment', v.environment, 'provider_document_id', v.provider_document_id,\n 'cancelled_at', v.cancelled_at, 'access_key', v.access_key, 'number', v.number);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_note_apply(\n p_document_id uuid,\n p_action text,\n p_patch jsonb,\n p_event jsonb DEFAULT NULL\n)\nRETURNS void\nLANGUAGE plpgsql\nSECURITY DEFINER\nSET search_path TO ''\nAS $$\nDECLARE\n v public.plg_fiscalbr_documents%ROWTYPE;\n v_status text := p_patch ->> 'status';\nBEGIN\n SELECT * INTO v FROM public.plg_fiscalbr_documents\n WHERE document_id = p_document_id AND tenant_id = app.current_tenant_id()\n FOR UPDATE;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscal: note not found' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission(\n CASE WHEN p_action = 'cancel' THEN 'financial.edit' ELSE 'financial.read' END, v.unit_id);\n IF v_status IS NOT NULL AND v_status NOT IN ('processing','authorized','rejected','error','cancelled','substituted') THEN\n RAISE EXCEPTION 'fiscal: unknown status %', v_status USING ERRCODE = '22023';\n END IF;\n\n -- Only what the provider answers; identity (model, unit, order) never moves.\n UPDATE public.plg_fiscalbr_documents SET\n status = COALESCE(v_status, status),\n number = COALESCE(p_patch ->> 'number', number),\n series = COALESCE(p_patch ->> 'series', series),\n access_key = COALESCE(p_patch ->> 'access_key', access_key),\n verification_code = COALESCE(p_patch ->> 'verification_code', verification_code),\n status_payload = COALESCE(p_patch -> 'status_payload', status_payload),\n rejection_payload = CASE WHEN p_patch ? 'rejection_payload' THEN p_patch -> 'rejection_payload' ELSE rejection_payload END,\n authorized_at = COALESCE((p_patch ->> 'authorized_at')::timestamptz, authorized_at),\n last_polled_at = CASE WHEN p_action = 'poll' THEN now() ELSE last_polled_at END,\n cancelled_at = CASE WHEN p_patch ? 'cancelled_at' THEN (p_patch ->> 'cancelled_at')::timestamptz ELSE cancelled_at END,\n cancel_reason = CASE WHEN p_patch ? 'cancel_reason' THEN p_patch ->> 'cancel_reason' ELSE cancel_reason END,\n cancelled_by_user_id = CASE WHEN p_action = 'cancel' THEN auth.uid()\n WHEN p_patch ? 'cancelled_at' AND p_patch -> 'cancelled_at' = 'null'::jsonb THEN NULL\n ELSE cancelled_by_user_id END\n WHERE document_id = p_document_id;\n\n IF v_status IS NOT NULL THEN\n UPDATE public.documents SET status = v_status WHERE id = p_document_id AND status IS DISTINCT FROM v_status;\n END IF;\n\n IF p_event IS NOT NULL THEN\n INSERT INTO public.plg_fiscalbr_document_events\n (tenant_id, unit_id, document_id, event_type, status, justification, response_payload, created_by_user_id)\n VALUES (v.tenant_id, v.unit_id, p_document_id, p_event ->> 'event_type', p_event ->> 'status',\n p_event ->> 'justification', p_event -> 'response_payload', auth.uid());\n END IF;\nEND $$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_note_for_provider(uuid, text) FROM PUBLIC, anon;\nREVOKE ALL ON FUNCTION public.fiscalbr_note_apply(uuid, text, jsonb, jsonb) FROM PUBLIC, anon;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_note_for_provider(uuid, text) TO authenticated;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_note_apply(uuid, text, jsonb, jsonb) TO authenticated;\n`\n\nexport const MIGRATION_020_A_NOTA_ACHA_O_FORNECEDOR_PELO_CNPJ = `-- A nota acha o fornecedor pelo CNPJ — e, se não achar, cadastra.\n--\n-- O estágio (009) só casava o CNPJ no momento do import. As notas que vieram\n-- do V1 atravessaram sem o vínculo (003 deixou para \"a costura\"), e um\n-- fornecedor cadastrado depois nunca era religado: 1029 notas com o fornecedor\n-- no cadastro e a tela dizendo \"não está no cadastro\", e o título aceito no V2\n-- nascendo sem contraparte (o traço em Contas a Pagar).\n--\n-- O V1 nunca pediu cadastro: ao aceitar, \\`resolveSupplierId\\` procura o\n-- fornecedor pelo CNPJ e, sem achar, cria com o nome e o CNPJ da nota. Esta\n-- função é esse gesto, com duas pontas:\n--\n-- p_create = false só casa (ao abrir a nota)\n-- p_create = true casa ou cria (antes de aceitar)\n--\n-- O título da nota, se já existe e está SEM contraparte, recebe a mesma pessoa.\n-- Nunca troca um vínculo gravado. Idempotente.\n\nCREATE OR REPLACE FUNCTION public.plg_fiscalbr_supplier_for_cnpj(p_tenant uuid, p_cnpj text)\nRETURNS uuid\nLANGUAGE sql\nSTABLE\nSET search_path TO ''\nAS $$\n SELECT p.id FROM public.people p\n WHERE p.tenant_id = p_tenant\n AND p_cnpj <> ''\n AND public.plg_fiscalbr_digits(p.document_number) = p_cnpj\n ORDER BY (p.kind = 'supplier') DESC, p.created_at\n LIMIT 1\n$$;\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_link_inbox_supplier(p_document_id uuid, p_create boolean DEFAULT false)\nRETURNS jsonb\nLANGUAGE plpgsql\nSECURITY DEFINER\nSET search_path TO ''\nAS $$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_cnpj text;\n v_party uuid;\n v_created boolean := false;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE id = p_document_id AND tenant_id = v_tenant;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscal: inbox note not found' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission(\n CASE WHEN p_create THEN 'financial.create' ELSE 'financial.read' END, v_doc.unit_id);\n\n v_party := v_doc.supplier_party_id;\n v_cnpj := public.plg_fiscalbr_digits(v_doc.supplier_cnpj);\n\n IF v_party IS NULL THEN\n v_party := public.plg_fiscalbr_supplier_for_cnpj(v_tenant, v_cnpj);\n END IF;\n\n -- Without a CNPJ there is nothing to match on; a name-only person would be a\n -- duplicate waiting to happen, so creation needs the document.\n IF v_party IS NULL AND p_create AND v_cnpj <> '' THEN\n INSERT INTO public.people (tenant_id, kind, name, document_number)\n VALUES (v_tenant, 'supplier', coalesce(nullif(trim(v_doc.supplier_name), ''), 'Fornecedor ' || v_cnpj), v_cnpj)\n RETURNING id INTO v_party;\n v_created := true;\n END IF;\n\n IF v_party IS NOT NULL AND v_doc.supplier_party_id IS NULL THEN\n UPDATE public.plg_fiscalbr_inbox_documents\n SET supplier_party_id = v_party\n WHERE id = v_doc.id AND supplier_party_id IS NULL;\n END IF;\n\n IF v_party IS NOT NULL AND v_doc.invoice_id IS NOT NULL THEN\n UPDATE public.plg_financial_invoices\n SET counterparty_person_id = v_party\n WHERE id = v_doc.invoice_id AND tenant_id = v_tenant AND counterparty_person_id IS NULL;\n END IF;\n\n RETURN jsonb_build_object('supplier_party_id', v_party, 'created', v_created);\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_link_inbox_supplier(uuid, boolean) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_link_inbox_supplier(uuid, boolean) TO authenticated;\n\n-- Backfill: match only, NULLs only. Nothing is created here — creating a person\n-- is the operator's gesture (accepting), not a migration's.\nWITH p AS (\n SELECT DISTINCT ON (tenant_id, dg) tenant_id, dg, id\n FROM (SELECT tenant_id, id, kind, created_at, public.plg_fiscalbr_digits(document_number) AS dg\n FROM public.people\n WHERE document_number IS NOT NULL) x\n WHERE length(dg) = 14\n ORDER BY tenant_id, dg, (kind = 'supplier') DESC, created_at\n)\nUPDATE public.plg_fiscalbr_inbox_documents d\n SET supplier_party_id = p.id\n FROM p\n WHERE d.supplier_party_id IS NULL\n AND p.tenant_id = d.tenant_id\n AND p.dg = public.plg_fiscalbr_digits(d.supplier_cnpj);\n\nUPDATE public.plg_financial_invoices i\n SET counterparty_person_id = d.supplier_party_id\n FROM public.plg_fiscalbr_inbox_documents d\n WHERE d.invoice_id = i.id\n AND d.tenant_id = i.tenant_id\n AND d.supplier_party_id IS NOT NULL\n AND i.counterparty_person_id IS NULL;\n`\n\nexport const MIGRATION_021_USO_E_CONSUMO_ENTRA_NO_ESTOQUE = `-- \"Materiais de Uso e Consumo\" vira um tipo de registro da nota recebida.\n--\n-- É o que a casa gasta sem vender nem transformar — luva, descartável, material\n-- de limpeza — e que ainda assim se conta no estoque. Entra no estoque como o\n-- insumo: precisa de produto vinculado e gera movimento ao aceitar.\n--\n-- Aditivo e idempotente. A função de aceite é REMENDADA, não reescrita (mesmo\n-- padrão da 015): copiar o corpo da 010 apagaria o \\`reason\\` que a 015 enxertou.\n\nALTER TABLE public.plg_fiscalbr_inbox_items\n DROP CONSTRAINT IF EXISTS plg_fiscalbr_inbox_items_entry_type_chk;\nALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_entry_type_chk\n CHECK (entry_type IS NULL OR entry_type IN ('insumo','revenda','patrimonio','uso_consumo','despesa','servico'));\n\nALTER TABLE public.plg_fiscalbr_supplier_product_map\n DROP CONSTRAINT IF EXISTS plg_fiscalbr_supplier_product_map_entry_type_chk;\nALTER TABLE public.plg_fiscalbr_supplier_product_map\n ADD CONSTRAINT plg_fiscalbr_supplier_product_map_entry_type_chk\n CHECK (entry_type IS NULL OR entry_type IN ('insumo','revenda','patrimonio','uso_consumo','despesa','servico'));\n\nDO $m$\nDECLARE\n v_def text;\n v_antes text := $q$entry_type IN ('insumo','revenda','patrimonio')$q$;\n v_depois text := $q$entry_type IN ('insumo','revenda','patrimonio','uso_consumo')$q$;\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def\n FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n\n IF v_def IS NULL THEN\n RAISE EXCEPTION 'fiscalbr/021: fiscalbr_accept_inbox_document não existe — aplicar 009/010 antes';\n END IF;\n\n IF position('uso_consumo' in v_def) > 0 THEN RETURN; END IF;\n\n IF position(v_antes in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/021: o corpo de fiscalbr_accept_inbox_document não é o esperado — confira à mão em vez de deixar passar calado';\n END IF;\n\n EXECUTE replace(v_def, v_antes, v_depois);\nEND\n$m$;\n`\n\nexport const MIGRATION_022_A_NOTA_DO_V1_TRAZ_O_XML = `-- ---------------------------------------------------------------------------\n-- The V1 bridge carries the note's XML.\n-- ---------------------------------------------------------------------------\n-- 003 dropped \\`xml_content\\` because, back then, V2 had no column for it (016\n-- added one). Without the file a note copied from the V1 cannot be downloaded,\n-- and a note the V1 never broke into lines arrives with zero items and no way\n-- to rebuild them. Only the mapping changes; rows already copied are not touched.\n-- ---------------------------------------------------------------------------\n\nUPDATE migration.allowlist\n SET columns = columns || jsonb_build_object('xml_content', 'xml_content')\n WHERE source_table = 'dfe_inbox'\n AND columns->>'xml_content' IS DISTINCT FROM 'xml_content';\n`\n\nexport const MIGRATION_023_A_NOTA_ACEITA_SEM_LINHAS_RECEBE_AS_LINHAS = `-- ---------------------------------------------------------------------------\n-- An accepted note that has no lines gets its lines, and nothing else.\n-- ---------------------------------------------------------------------------\n-- Notes copied from the V1 can carry a payable (or stock) and zero lines: the\n-- V1 never split their XML. Restaging is refused for them on purpose (it would\n-- rewrite the decision that became stock and payable), so they showed 0/0\n-- forever. This writes ONLY the missing lines, from the stored XML, and only\n-- while the note has none; the document, its payable and its instalments stay.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_fill_inbox_lines(p_document_id uuid, p_items jsonb)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_cnpj text;\n v_item jsonb;\n v_map public.plg_fiscalbr_supplier_product_map%ROWTYPE;\n v_n integer := 0;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id\n FOR UPDATE; -- two opens of the same note must not both see \"no lines\"\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota não encontrada' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.create', v_doc.unit_id);\n\n IF EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id) THEN\n RETURN jsonb_build_object('document_id', v_doc.id, 'items', 0, 'already_had_lines', true);\n END IF;\n\n v_cnpj := public.plg_fiscalbr_digits(v_doc.supplier_cnpj);\n\n FOR v_item IN SELECT * FROM jsonb_array_elements(coalesce(p_items, '[]'::jsonb)) LOOP\n v_n := v_n + 1;\n v_map := NULL;\n SELECT * INTO v_map FROM public.plg_fiscalbr_supplier_product_map\n WHERE tenant_id = v_tenant AND supplier_cnpj = v_cnpj\n AND supplier_product_code = coalesce(v_item->>'supplier_product_code', '');\n\n INSERT INTO public.plg_fiscalbr_inbox_items (\n tenant_id, inbox_document_id, item_number, supplier_product_code, ean_barcode,\n description, ncm, cest, cfop, unit_commercial, quantity_commercial,\n unit_price_commercial, total_price, discount, freight, other_expenses,\n icms_cst, icms_csosn, icms_base, icms_rate, icms_value,\n pis_value, cofins_value, ipi_value, raw_xml_item,\n product_id, entry_type, chart_account_id, stock_unit_id, conversion_factor,\n cost_mode, reconciled)\n VALUES (\n v_tenant, v_doc.id, coalesce((v_item->>'item_number')::int, v_n),\n v_item->>'supplier_product_code', v_item->>'ean_barcode',\n v_item->>'description', v_item->>'ncm', v_item->>'cest', v_item->>'cfop',\n v_item->>'unit', (v_item->>'quantity')::numeric,\n (v_item->>'unit_price')::numeric, (v_item->>'total')::numeric,\n (v_item->>'discount')::numeric, (v_item->>'freight')::numeric,\n (v_item->>'other')::numeric,\n v_item->>'icms_cst', v_item->>'icms_csosn', (v_item->>'icms_base')::numeric,\n (v_item->>'icms_rate')::numeric, (v_item->>'icms_value')::numeric,\n (v_item->>'pis_value')::numeric, (v_item->>'cofins_value')::numeric,\n (v_item->>'ipi_value')::numeric, v_item,\n v_map.product_id, v_map.entry_type, v_map.chart_account_id, v_map.stock_unit_id,\n coalesce(v_map.conversion_factor, 1), coalesce(v_map.cost_mode, 'novo'),\n v_map.product_id IS NOT NULL);\n END LOOP;\n\n RETURN jsonb_build_object('document_id', v_doc.id, 'items', v_n, 'already_had_lines', false);\nEND;\n$function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_fill_inbox_lines(uuid, jsonb) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_fill_inbox_lines(uuid, jsonb) TO authenticated;\n`\n\nexport const MIGRATION_024_A_NOTA_NAO_APONTA_PARA_CONTA_QUE_SUMIU = `-- ---------------------------------------------------------------------------\n-- A note never points at a payable (or stock movement) that no longer exists.\n-- ---------------------------------------------------------------------------\n-- invoice_id and stock_movement_id cross into other plugins, so they carry no\n-- foreign key. When a re-copy rebuilt a tenant's payables under new ids, the\n-- notes kept the old ones: the screen read \"already accepted\" and hid every\n-- action, while Contas a Pagar had nothing. This heals a note: a dead payable\n-- link is re-pointed to the live payable of the same NF-e when exactly one\n-- exists, otherwise cleared; a dead movement link is cleared, and the note\n-- stops counting as stocked only when that dead movement was all it had. A\n-- cleared note can be accepted again, which writes the payable and the stock.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.plg_fiscalbr_heal_note_links(p_tenant uuid, p_document_id uuid)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_invoice uuid;\n v_matches integer;\n v_dead_mv integer := 0;\n v_relinked boolean := false;\n v_released boolean := false;\n v_unstocked boolean := false;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = p_tenant AND id = p_document_id\n FOR UPDATE;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('document_id', p_document_id, 'changed', false);\n END IF;\n\n IF v_doc.invoice_id IS NOT NULL AND NOT EXISTS (\n SELECT 1 FROM public.plg_financial_invoices f WHERE f.id = v_doc.invoice_id) THEN\n -- Same NF-e: the key this plugin writes, or the V1 conciliation's text for the same supplier.\n SELECT count(*), min(f.id::text)::uuid INTO v_matches, v_invoice\n FROM public.plg_financial_invoices f\n WHERE f.tenant_id = p_tenant AND f.direction = 'payable' AND f.cancelled_at IS NULL\n AND (f.idempotency_key = 'danfe:' || v_doc.access_key\n OR (v_doc.supplier_party_id IS NOT NULL\n AND f.counterparty_person_id = v_doc.supplier_party_id\n AND f.description ~ ('NF-e 0*' || ltrim(v_doc.nfe_number, '0') || '(\\\\D|$)')))\n AND NOT EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_documents o\n WHERE o.tenant_id = p_tenant AND o.invoice_id = f.id AND o.id <> v_doc.id);\n IF v_matches = 1 THEN\n v_relinked := true;\n ELSE\n v_invoice := NULL;\n v_released := true;\n END IF;\n UPDATE public.plg_fiscalbr_inbox_documents SET invoice_id = v_invoice, updated_at = now()\n WHERE id = v_doc.id;\n END IF;\n\n UPDATE public.plg_fiscalbr_inbox_items i SET stock_movement_id = NULL, updated_at = now()\n WHERE i.tenant_id = p_tenant AND i.inbox_document_id = v_doc.id\n AND i.stock_movement_id IS NOT NULL\n AND NOT EXISTS (SELECT 1 FROM public.plg_inventory_stock_movements m WHERE m.id = i.stock_movement_id);\n GET DIAGNOSTICS v_dead_mv = ROW_COUNT;\n\n IF v_dead_mv > 0 AND v_doc.stocked_at IS NOT NULL\n AND v_doc.inventory_operation_id IS NULL\n AND NOT EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = p_tenant AND i.inbox_document_id = v_doc.id\n AND i.stock_movement_id IS NOT NULL) THEN\n UPDATE public.plg_fiscalbr_inbox_documents SET stocked_at = NULL, updated_at = now()\n WHERE id = v_doc.id;\n v_unstocked := true;\n END IF;\n\n RETURN jsonb_build_object('document_id', v_doc.id,\n 'changed', v_relinked OR v_released OR v_dead_mv > 0,\n 'relinked', v_relinked, 'released', v_released,\n 'dead_movements', v_dead_mv, 'unstocked', v_unstocked);\nEND;\n$function$;\n\nREVOKE ALL ON FUNCTION public.plg_fiscalbr_heal_note_links(uuid, uuid) FROM PUBLIC, anon, authenticated;\n\n-- The screen heals the note it opens, so a future re-copy cannot strand one again.\nCREATE OR REPLACE FUNCTION public.fiscalbr_heal_inbox_note(p_document_id uuid)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_unit uuid;\nBEGIN\n SELECT unit_id INTO v_unit FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota não encontrada' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.create', v_unit);\n RETURN public.plg_fiscalbr_heal_note_links(v_tenant, p_document_id);\nEND;\n$function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_heal_inbox_note(uuid) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_heal_inbox_note(uuid) TO authenticated;\n\n-- Heal what is already stranded.\nDO $backfill$\nDECLARE r record;\nBEGIN\n FOR r IN\n SELECT DISTINCT d.tenant_id, d.id\n FROM public.plg_fiscalbr_inbox_documents d\n LEFT JOIN public.plg_fiscalbr_inbox_items i\n ON i.tenant_id = d.tenant_id AND i.inbox_document_id = d.id\n WHERE (d.invoice_id IS NOT NULL\n AND NOT EXISTS (SELECT 1 FROM public.plg_financial_invoices f WHERE f.id = d.invoice_id))\n OR (i.stock_movement_id IS NOT NULL\n AND NOT EXISTS (SELECT 1 FROM public.plg_inventory_stock_movements m WHERE m.id = i.stock_movement_id))\n LOOP\n PERFORM public.plg_fiscalbr_heal_note_links(r.tenant_id, r.id);\n END LOOP;\nEND\n$backfill$;\n`\n\nexport const MIGRATION_025_A_CONTA_DA_NOTA_FECHA_COM_O_TOTAL = `-- ---------------------------------------------------------------------------\n-- The payable a note opens lists products as products, and adds up to its total.\n-- ---------------------------------------------------------------------------\n-- Two defects in the lines fiscalbr_accept_inbox_document wrote:\n-- 1. \\`itemKind\\` carried the fiscal entry type ('insumo', 'revenda'…), which the\n-- financial screens do not know, so a linked product showed as \"Insumo\"\n-- with no product. The kind is 'product' when the line has one; the entry\n-- type moves to \\`entryType\\`, and product/chart account go to their columns.\n-- 2. Only the product lines were written, so freight, insurance, other\n-- expenses, IPI, ICMS-ST and discount were in the total but in no line\n-- (NF-e 1430116: R$ 480,47 owed, R$ 478,47 listed). Each becomes a line,\n-- and whatever still differs from the instalments becomes one more.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.plg_fiscalbr_note_charge_lines(\n p_tenant uuid, p_document_id uuid, p_invoice_id uuid, p_total numeric)\nRETURNS integer LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_sum numeric;\n v_rest numeric;\n v_n integer := 0;\n v_c record;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = p_tenant AND id = p_document_id;\n IF NOT FOUND OR p_invoice_id IS NULL THEN RETURN 0; END IF;\n IF EXISTS (SELECT 1 FROM public.items\n WHERE tenant_id = p_tenant AND invoice_id = p_invoice_id\n AND metadata ? 'noteCharge') THEN\n RETURN 0;\n END IF;\n -- Only a payable that already lists the note's products: a V1 copy with no lines\n -- would get its whole total as one \"difference\" line.\n IF NOT EXISTS (SELECT 1 FROM public.items\n WHERE tenant_id = p_tenant AND invoice_id = p_invoice_id\n AND metadata ? 'cfop') THEN\n RETURN 0;\n END IF;\n\n FOR v_c IN\n SELECT * FROM (VALUES\n (1, 'freight', 'Frete', round(coalesce(v_doc.total_freight, 0), 2)),\n (2, 'insurance', 'Seguro', round(coalesce(v_doc.total_insurance, 0), 2)),\n (3, 'other', 'Outras despesas da nota', round(coalesce(v_doc.total_other, 0), 2)),\n (4, 'ipi', 'IPI', round(coalesce(v_doc.total_ipi_value, 0), 2)),\n (5, 'icms_st', 'ICMS-ST', round(coalesce(v_doc.total_icms_st_value, 0), 2)),\n (6, 'discount', 'Desconto da nota', -round(coalesce(v_doc.total_discount, 0), 2))\n ) AS c(ord, code, label, amount)\n WHERE amount <> 0\n ORDER BY ord\n LOOP\n INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)\n VALUES (p_tenant, p_invoice_id, v_c.label, 1, v_c.amount, v_c.amount, 1000 + v_c.ord,\n jsonb_build_object('itemKind', 'other', 'noteCharge', v_c.code));\n v_n := v_n + 1;\n END LOOP;\n\n SELECT coalesce(sum(total), 0) INTO v_sum FROM public.items\n WHERE tenant_id = p_tenant AND invoice_id = p_invoice_id AND cancelled_at IS NULL;\n v_rest := round(coalesce(p_total, 0) - v_sum, 2);\n IF v_rest <> 0 THEN\n INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)\n VALUES (p_tenant, p_invoice_id, 'Diferença entre a nota e as parcelas', 1, v_rest, v_rest, 1099,\n jsonb_build_object('itemKind', 'other', 'noteCharge', 'instalment_difference'));\n v_n := v_n + 1;\n END IF;\n RETURN v_n;\nEND;\n$function$;\n\nREVOKE ALL ON FUNCTION public.plg_fiscalbr_note_charge_lines(uuid, uuid, uuid, numeric) FROM PUBLIC, anon, authenticated;\n\nDO $m$\nDECLARE\n v_def text;\n v_start integer;\n v_end integer;\n v_marker text := 'INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)';\n v_close text := 'ON CONFLICT DO NOTHING;';\n v_new text := $q$INSERT INTO public.items (tenant_id, invoice_id, product_id, chart_account_id, name, quantity, unit_price, total, sort_order, metadata)\n SELECT v_tenant, v_invoice, i.product_id, coalesce(i.chart_account_id, v_doc.default_chart_account_id),\n i.description, i.quantity_commercial, i.unit_price_commercial,\n round(coalesce(i.total_price, 0), 2), i.item_number,\n jsonb_strip_nulls(jsonb_build_object(\n 'itemKind', CASE WHEN i.product_id IS NOT NULL THEN 'product' ELSE 'other' END,\n 'referenceId', i.product_id, 'entryType', i.entry_type,\n 'chartAccountId', coalesce(i.chart_account_id, v_doc.default_chart_account_id),\n 'ncm', i.ncm, 'cfop', i.cfop,\n 'supplierProductCode', i.supplier_product_code))\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n ORDER BY i.item_number\n ON CONFLICT DO NOTHING;\n PERFORM public.plg_fiscalbr_note_charge_lines(v_tenant, v_doc.id, v_invoice, v_total);$q$;\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def\n FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n IF v_def IS NULL THEN\n RAISE EXCEPTION 'fiscalbr/025: fiscalbr_accept_inbox_document does not exist';\n END IF;\n IF position('plg_fiscalbr_note_charge_lines' in v_def) > 0 THEN RETURN; END IF;\n\n v_start := position(v_marker in v_def);\n IF v_start = 0 THEN\n RAISE EXCEPTION 'fiscalbr/025: unexpected body of fiscalbr_accept_inbox_document — check by hand';\n END IF;\n v_end := v_start + position(v_close in substr(v_def, v_start)) - 1 + length(v_close);\n EXECUTE substr(v_def, 1, v_start - 1) || v_new || substr(v_def, v_end);\nEND\n$m$;\n\n-- The payables already opened by notes: same kind/product fix, and the missing charge lines.\nALTER TABLE public.items DISABLE TRIGGER items_invoice_line_immutable;\n\nUPDATE public.items it\n SET product_id = coalesce(it.product_id, (it.metadata->>'referenceId')::uuid),\n metadata = jsonb_set(it.metadata || jsonb_build_object('entryType', it.metadata->>'itemKind'),\n '{itemKind}', '\"product\"'::jsonb, true),\n updated_at = now()\n FROM public.plg_financial_invoices f\n WHERE f.id = it.invoice_id\n AND f.metadata ? 'danfe'\n AND it.metadata->>'itemKind' IN ('insumo','revenda','patrimonio','uso_consumo','despesa','servico')\n AND it.metadata->>'referenceId' IS NOT NULL\n AND EXISTS (SELECT 1 FROM public.products p WHERE p.id = (it.metadata->>'referenceId')::uuid);\n\nUPDATE public.items it\n SET metadata = jsonb_set(it.metadata || jsonb_build_object('entryType', it.metadata->>'itemKind'),\n '{itemKind}', '\"other\"'::jsonb, true),\n updated_at = now()\n FROM public.plg_financial_invoices f\n WHERE f.id = it.invoice_id\n AND f.metadata ? 'danfe'\n AND it.metadata->>'itemKind' IN ('insumo','revenda','patrimonio','uso_consumo','despesa','servico');\n\nALTER TABLE public.items ENABLE TRIGGER items_invoice_line_immutable;\n\nDO $backfill$\nDECLARE r record;\nBEGIN\n FOR r IN\n SELECT d.tenant_id, d.id, f.id AS invoice_id, f.total\n FROM public.plg_fiscalbr_inbox_documents d\n JOIN public.plg_financial_invoices f ON f.id = d.invoice_id AND f.tenant_id = d.tenant_id\n WHERE f.metadata ? 'danfe' AND f.cancelled_at IS NULL\n LOOP\n PERFORM public.plg_fiscalbr_note_charge_lines(r.tenant_id, r.id, r.invoice_id, r.total);\n END LOOP;\nEND\n$backfill$;\n`\n\nexport const MIGRATION_026_O_RECEBIMENTO_PARADO_DIZ_POR_QUE = `-- ---------------------------------------------------------------------------\n-- When notes stop arriving, the emitter row says why.\n-- ---------------------------------------------------------------------------\n-- The SEFAZ pull fails per CNPJ (expired A1 certificate, provider refusal) and\n-- the V1 records only the last failure (integration_sync_state.last_error). The\n-- V2 kept nothing, so a tenant could go two weeks without a note and no screen\n-- would say so. These two columns hold that last failure; the notes list warns\n-- from them and from a stale dfe_last_sync_at.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_fiscalbr_emitter_settings\n ADD COLUMN IF NOT EXISTS dfe_last_error text,\n ADD COLUMN IF NOT EXISTS dfe_last_error_at timestamptz;\n\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.dfe_last_error IS\n 'V1: integration_sync_state.last_error (source = dfe_inbox) — last failure pulling notes from SEFAZ; null when the last pull worked.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.dfe_last_error_at IS\n 'V1: integration_sync_state.last_synced_at when last_status = error.';\n\nGRANT SELECT (dfe_last_error, dfe_last_error_at) ON public.plg_fiscalbr_emitter_settings TO authenticated;\n`\n\nexport const MIGRATION_027_A_NOTA_COM_CONTA_E_SEM_ESTOQUE_TERMINA_NO_V2 = `-- ---------------------------------------------------------------------------\n-- A note that has its payable but never reached stock can be finished in V2.\n-- ---------------------------------------------------------------------------\n-- In the V1, saving the payment plan of a DANFE import opened the payable\n-- before anyone reconciled the lines; many imports stopped there. Copied over,\n-- those notes carry invoice_id and no stock, and both RPCs read invoice_id as\n-- \"accepted\": nothing could be reconciled and the goods never entered stock\n-- (Artorius 18, Espaço Facial 72, Pertinho 17 on 14/10/2026).\n--\n-- \"Settled\" is now: stocked, or a payable with no stock line left to receive.\n-- Saving decisions is allowed until then, and accepting a note that already has\n-- its payable receives the stock against it instead of opening a second one.\n-- ---------------------------------------------------------------------------\n\nDO $m$\nDECLARE\n v_def text;\n v_old text;\n v_new text;\n v_start integer;\n v_end integer;\n v_pending constant text := $q$NOT EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items x\n WHERE x.tenant_id = v_tenant AND x.inbox_document_id = v_doc.id\n AND x.stock_movement_id IS NULL\n AND (x.entry_type IS NULL OR x.entry_type = '' OR x.entry_type IN ('insumo','revenda','patrimonio','uso_consumo')))$q$;\nBEGIN\n -- 1. Saving decisions.\n SELECT pg_get_functiondef(p.oid) INTO v_def FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_save_inbox_decision';\n v_old := 'IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN';\n IF v_def IS NULL THEN RAISE EXCEPTION 'fiscalbr/027: fiscalbr_save_inbox_decision does not exist'; END IF;\n IF position(v_old in v_def) > 0 THEN\n v_def := replace(v_def, v_old, 'IF v_doc.stocked_at IS NOT NULL OR (v_doc.invoice_id IS NOT NULL AND ' || v_pending || ') THEN');\n -- v_tenant is that function's own variable name too.\n EXECUTE v_def;\n ELSIF position('x.stock_movement_id IS NULL' in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/027: unexpected body of fiscalbr_save_inbox_decision — check by hand';\n END IF;\n\n -- 2. Accepting.\n SELECT pg_get_functiondef(p.oid) INTO v_def FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n IF v_def IS NULL THEN RAISE EXCEPTION 'fiscalbr/027: fiscalbr_accept_inbox_document does not exist'; END IF;\n IF position('Half-done in the V1' in v_def) > 0 THEN RETURN; END IF;\n\n IF position(v_old in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/027: unexpected guard in fiscalbr_accept_inbox_document — check by hand';\n END IF;\n v_def := replace(v_def, v_old, 'IF v_doc.stocked_at IS NOT NULL OR (v_doc.invoice_id IS NOT NULL AND ' || v_pending || ') THEN');\n\n v_start := position(' SELECT coalesce(sum(value), 0),' in v_def);\n v_new := 'PERFORM public.plg_fiscalbr_note_charge_lines(v_tenant, v_doc.id, v_invoice, v_total);';\n v_end := position(v_new in v_def);\n IF v_start = 0 OR v_end = 0 OR v_end < v_start THEN\n RAISE EXCEPTION 'fiscalbr/027: unexpected payable block in fiscalbr_accept_inbox_document — check by hand';\n END IF;\n v_end := v_end + length(v_new);\n v_def := substr(v_def, 1, v_start - 1)\n || $q$ IF v_doc.invoice_id IS NOT NULL THEN\n -- Half-done in the V1: the payable exists; only the stock is missing.\n v_invoice := v_doc.invoice_id;\n SELECT total INTO v_total FROM public.plg_financial_invoices WHERE id = v_invoice;\n v_insts := '[]'::jsonb;\n ELSE\n$q$ || substr(v_def, v_start, v_end - v_start) || $q$\n END IF;$q$\n || substr(v_def, v_end);\n EXECUTE v_def;\nEND\n$m$;\n`\n\nexport const MIGRATION_028_A_LINHA_DE_ESTOQUE_TEM_UNIDADE = `-- ---------------------------------------------------------------------------\n-- A stock line enters with its unit.\n-- ---------------------------------------------------------------------------\n-- Accepting let a stock line through with no stock unit; the movement then\n-- carried a bare quantity that every screen reads as \"unidade\" (Artorius, NF-e\n-- 222879: 20 kg of copa lombo entered as 20 units). The screen now suggests the\n-- unit and refuses without one; this is the same rule where it cannot be\n-- skipped.\n-- ---------------------------------------------------------------------------\n\nDO $m$\nDECLARE\n v_def text;\n v_old constant text := $q$ IF v_it.product_id IS NULL THEN$q$;\n v_new constant text := $q$ IF v_it.stock_unit_id IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: item % entra no estoque sem unidade — escolha a unidade de estoque', v_it.item_number\n USING ERRCODE = '23514';\n END IF;\n IF v_it.product_id IS NULL THEN$q$;\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n IF v_def IS NULL THEN RAISE EXCEPTION 'fiscalbr/028: fiscalbr_accept_inbox_document does not exist'; END IF;\n IF position('entra no estoque sem unidade' in v_def) > 0 THEN RETURN; END IF;\n IF position(v_old in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/028: unexpected body of fiscalbr_accept_inbox_document — check by hand';\n END IF;\n EXECUTE replace(v_def, v_old, v_new);\nEND\n$m$;\n`\n\nexport const MIGRATION_029_THE_SERVICE_WRITES_THE_INTAKE_HEALTH = `-- ============================================================================\n-- 029_the_service_writes_the_intake_health — the DF-e pull moves to the\n-- integration service (ADR 0003 phase 2).\n--\n-- The pull reads a tenant's emitter rows AS the caller (RLS decides which), and\n-- then records each CNPJ's outcome in three health columns, even for a reader\n-- without settings.manage, so the notes list can say \"intake stopped\". The\n-- edge function did that with service_role; the service gets exactly those\n-- three columns, by row id, and nothing else on the table.\n--\n-- Guarded: the role is an operator step. Replay-safe.\n-- ============================================================================\n\nDO $$\nBEGIN\n IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'fayz_integration')\n AND to_regclass('public.plg_fiscalbr_emitter_settings') IS NOT NULL THEN\n GRANT SELECT (id) ON public.plg_fiscalbr_emitter_settings TO fayz_integration;\n GRANT UPDATE (dfe_last_sync_at, dfe_last_error, dfe_last_error_at) ON public.plg_fiscalbr_emitter_settings TO fayz_integration;\n DROP POLICY IF EXISTS plg_fiscalbr_emitter_settings_service_health ON public.plg_fiscalbr_emitter_settings;\n CREATE POLICY plg_fiscalbr_emitter_settings_service_health ON public.plg_fiscalbr_emitter_settings\n FOR UPDATE TO fayz_integration USING (true) WITH CHECK (true);\n DROP POLICY IF EXISTS plg_fiscalbr_emitter_settings_service_read ON public.plg_fiscalbr_emitter_settings;\n CREATE POLICY plg_fiscalbr_emitter_settings_service_read ON public.plg_fiscalbr_emitter_settings\n FOR SELECT TO fayz_integration USING (true);\n END IF;\nEND $$;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"000_baseline\", sql: MIGRATION_000_BASELINE },\n { id: \"001_preserve_terminal_results_and_recover_leases\", sql: MIGRATION_001_PRESERVE_TERMINAL_RESULTS_AND_RECOVER_LEASES },\n { id: \"002_a_nota_que_chega_tem_onde_esperar\", sql: MIGRATION_002_A_NOTA_QUE_CHEGA_TEM_ONDE_ESPERAR },\n { id: \"003_a_caixa_de_entrada_atravessa\", sql: MIGRATION_003_A_CAIXA_DE_ENTRADA_ATRAVESSA },\n { id: \"004_o_grupo_fiscal_do_v1_repete_nome\", sql: MIGRATION_004_O_GRUPO_FISCAL_DO_V1_REPETE_NOME },\n { id: \"005_a_nota_emitida_e_um_documento\", sql: MIGRATION_005_A_NOTA_EMITIDA_E_UM_DOCUMENTO },\n { id: \"006_o_grupo_fiscal_ganha_o_rail\", sql: MIGRATION_006_O_GRUPO_FISCAL_GANHA_O_RAIL },\n { id: \"007_a_rls_do_documento_passa_a_ser_legivel\", sql: MIGRATION_007_A_RLS_DO_DOCUMENTO_PASSA_A_SER_LEGIVEL },\n { id: \"008_a_nota_recebida_guarda_a_decisao_de_entrada\", sql: MIGRATION_008_A_NOTA_RECEBIDA_GUARDA_A_DECISAO_DE_ENTRADA },\n { id: \"009_aceitar_a_nota_escreve_estoque_e_titulo_de_uma_vez\", sql: MIGRATION_009_ACEITAR_A_NOTA_ESCREVE_ESTOQUE_E_TITULO_DE_UMA_VEZ },\n { id: \"010_a_data_de_emissao_e_instante_e_a_competencia_e_dia\", sql: MIGRATION_010_A_DATA_DE_EMISSAO_E_INSTANTE_E_A_COMPETENCIA_E_DIA },\n { id: \"011_o_imposto_do_produto_e_do_fiscal\", sql: MIGRATION_011_O_IMPOSTO_DO_PRODUTO_E_DO_FISCAL },\n { id: \"012_quem_e_o_produto_se_pergunta_ao_indice\", sql: MIGRATION_012_QUEM_E_O_PRODUTO_SE_PERGUNTA_AO_INDICE },\n { id: \"013_a_sugestao_sobrevive_a_fechar_a_janela\", sql: MIGRATION_013_A_SUGESTAO_SOBREVIVE_A_FECHAR_A_JANELA },\n { id: \"014_a_descricao_da_nota_tem_lixo_no_meio\", sql: MIGRATION_014_A_DESCRICAO_DA_NOTA_TEM_LIXO_NO_MEIO },\n { id: \"015_o_movimento_diz_que_veio_da_nota\", sql: MIGRATION_015_O_MOVIMENTO_DIZ_QUE_VEIO_DA_NOTA },\n { id: \"016_a_nota_guarda_o_proprio_xml\", sql: MIGRATION_016_A_NOTA_GUARDA_O_PROPRIO_XML },\n { id: \"017_quem_emite_e_o_cnpj_nao_a_loja\", sql: MIGRATION_017_QUEM_EMITE_E_O_CNPJ_NAO_A_LOJA },\n { id: \"018_a_nota_do_v1_alcanca_a_conta\", sql: MIGRATION_018_A_NOTA_DO_V1_ALCANCA_A_CONTA },\n { id: \"019_a_nota_emitida_se_cancela_pelo_v2\", sql: MIGRATION_019_A_NOTA_EMITIDA_SE_CANCELA_PELO_V2 },\n { id: \"020_a_nota_acha_o_fornecedor_pelo_cnpj\", sql: MIGRATION_020_A_NOTA_ACHA_O_FORNECEDOR_PELO_CNPJ },\n { id: \"021_uso_e_consumo_entra_no_estoque\", sql: MIGRATION_021_USO_E_CONSUMO_ENTRA_NO_ESTOQUE },\n { id: \"022_a_nota_do_v1_traz_o_xml\", sql: MIGRATION_022_A_NOTA_DO_V1_TRAZ_O_XML },\n { id: \"023_a_nota_aceita_sem_linhas_recebe_as_linhas\", sql: MIGRATION_023_A_NOTA_ACEITA_SEM_LINHAS_RECEBE_AS_LINHAS },\n { id: \"024_a_nota_nao_aponta_para_conta_que_sumiu\", sql: MIGRATION_024_A_NOTA_NAO_APONTA_PARA_CONTA_QUE_SUMIU },\n { id: \"025_a_conta_da_nota_fecha_com_o_total\", sql: MIGRATION_025_A_CONTA_DA_NOTA_FECHA_COM_O_TOTAL },\n { id: \"026_o_recebimento_parado_diz_por_que\", sql: MIGRATION_026_O_RECEBIMENTO_PARADO_DIZ_POR_QUE },\n { id: \"027_a_nota_com_conta_e_sem_estoque_termina_no_v2\", sql: MIGRATION_027_A_NOTA_COM_CONTA_E_SEM_ESTOQUE_TERMINA_NO_V2 },\n { id: \"028_a_linha_de_estoque_tem_unidade\", sql: MIGRATION_028_A_LINHA_DE_ESTOQUE_TEM_UNIDADE },\n { id: \"029_the_service_writes_the_intake_health\", sql: MIGRATION_029_THE_SERVICE_WRITES_THE_INTAKE_HEALTH },\n]\n","import type { EntityDef, PluginRegistryDef } from '@fayz-ai/core'\nimport { RECORD_GROUP, recordRailFields, activeFacet } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Grupos fiscais — a tributação que um produto herda.\n//\n// A tabela existe desde a 002 deste plugin e NUNCA teve tela: o grupo fiscal\n// de toda conta migrada estava no banco sem porta. Isto é a porta.\n//\n// O que ele responde é uma pergunta só, feita muitas vezes: com que imposto\n// este produto sai na nota. Agrupar é o ponto — sem grupo, CFOP, CST, origem e\n// três alíquotas seriam repetidos em cada produto, e mudar a regra de um\n// estado viraria uma edição em massa.\n//\n// A ordem dos campos segue a da nota: primeiro o que classifica a OPERAÇÃO\n// (CFOP), depois o ICMS, depois PIS/COFINS, e por último IBS/CBS — que é a\n// reforma tributária, e que já tem campo porque o V1 já tem.\n// ---------------------------------------------------------------------------\n\nconst taxGroupEntity: EntityDef = {\n name: 'Grupo fiscal',\n namePlural: 'Grupos fiscais',\n icon: 'ReceiptText',\n displayField: 'name',\n defaultSort: 'name',\n formColumns: 2,\n facets: [activeFacet({ active: 'Ativos', inactive: 'Inativos', all: 'Todos' })],\n fieldGroups: [\n {\n id: 'identity', label: 'Identificação', columns: 2,\n description: 'O nome é como a casa chama o grupo («Bebida alcoólica», «Serviço isento») — o resto é o que a nota exige.',\n },\n { id: 'icms', label: 'ICMS', columns: 3 },\n { id: 'pis_cofins', label: 'PIS e COFINS', columns: 2 },\n {\n id: 'ibs_cbs', label: 'IBS e CBS', columns: 2,\n description: 'A reforma tributária. Em branco enquanto não for exigido da sua operação.',\n },\n { ...RECORD_GROUP },\n ],\n fields: [\n { key: 'name', label: 'Nome', type: 'text', required: true, showInTable: true, searchable: true, group: 'identity', span: 2 },\n // O CFOP classifica a OPERAÇÃO (venda dentro do estado, fora, devolução) e\n // é o primeiro campo que o contador confere.\n { key: 'cfop', label: 'CFOP', type: 'text', showInTable: true, searchable: true, group: 'identity' },\n // CEST anda com a substituição tributária: só existe para quem está nela.\n { key: 'cest', label: 'CEST', type: 'text', showInTable: false, group: 'identity' },\n { key: 'benefitCode', label: 'Código de benefício', type: 'text', showInTable: false, group: 'identity' },\n\n // CST é do regime normal e CSOSN é do Simples — a casa usa UM dos dois, e\n // qual depende do regime dela, não deste grupo. Os dois ficam à vista de\n // propósito: esconder o que a conta não usa exigiria saber o regime aqui.\n { key: 'cst', label: 'CST', type: 'text', showInTable: true, group: 'icms' },\n { key: 'csosn', label: 'CSOSN (Simples)', type: 'text', showInTable: false, group: 'icms' },\n {\n key: 'icmsOrigin', label: 'Origem da mercadoria', type: 'select', showInTable: false, group: 'icms',\n options: [\n { value: '0', label: '0 — Nacional' },\n { value: '1', label: '1 — Estrangeira, importação direta' },\n { value: '2', label: '2 — Estrangeira, mercado interno' },\n { value: '3', label: '3 — Nacional, conteúdo de importação > 40%' },\n { value: '4', label: '4 — Nacional, processos produtivos básicos' },\n { value: '5', label: '5 — Nacional, conteúdo de importação ≤ 40%' },\n { value: '6', label: '6 — Estrangeira, sem similar nacional' },\n { value: '7', label: '7 — Estrangeira, mercado interno sem similar' },\n { value: '8', label: '8 — Nacional, conteúdo de importação > 70%' },\n ],\n },\n { key: 'icmsRate', label: 'Alíquota ICMS (%)', type: 'number', min: 0, max: 100, showInTable: true, group: 'icms' },\n { key: 'icmsBcMode', label: 'Modalidade da base', type: 'text', showInTable: false, group: 'icms' },\n { key: 'baseCalculationMode', label: 'Cálculo da base', type: 'text', showInTable: false, group: 'icms' },\n // O fundo de combate à pobreza é adicional ao ICMS em alguns estados.\n { key: 'povertyFundRate', label: 'Fundo de pobreza (%)', type: 'number', min: 0, max: 100, showInTable: false, group: 'icms' },\n\n { key: 'pisSituation', label: 'Situação PIS', type: 'text', showInTable: false, group: 'pis_cofins' },\n { key: 'pisRate', label: 'Alíquota PIS (%)', type: 'number', min: 0, max: 100, showInTable: false, group: 'pis_cofins' },\n { key: 'cofinsSituation', label: 'Situação COFINS', type: 'text', showInTable: false, group: 'pis_cofins' },\n { key: 'cofinsRate', label: 'Alíquota COFINS (%)', type: 'number', min: 0, max: 100, showInTable: false, group: 'pis_cofins' },\n\n { key: 'ibsCbsSituation', label: 'Situação IBS/CBS', type: 'text', showInTable: false, group: 'ibs_cbs' },\n { key: 'ibsCbsClassification', label: 'Classificação IBS/CBS', type: 'text', showInTable: false, group: 'ibs_cbs' },\n\n ...recordRailFields({ tagsTable: 'plg_fiscalbr_tax_groups', activeLabel: 'Ativo' }),\n ],\n data: {\n table: 'plg_fiscalbr_tax_groups',\n schema: 'public',\n tenantScoped: true,\n searchColumns: ['name', 'cfop'],\n },\n}\n\nexport const fiscalRegistries: PluginRegistryDef[] = [\n {\n id: 'taxGroups',\n icon: 'ReceiptText',\n entity: taxGroupEntity,\n description: 'A tributação que um produto herda: CFOP, ICMS, PIS/COFINS e, quando exigido, IBS/CBS.',\n agentHint: 'Regras de imposto que um produto herda — NÃO é a nota emitida nem o imposto de uma venda específica.',\n },\n]\n","// ---------------------------------------------------------------------------\n// nfe-xml — read a supplier NF-e (layout 4.00) into the shape the inbox wants.\n// ---------------------------------------------------------------------------\n// The XML is decomposed HERE, in TypeScript, and not in PL/pgSQL. Three reasons,\n// in order of how much each one cost when ignored elsewhere:\n//\n// 1. A parser with a unit test is a parser you can trust. The assertions in\n// nfe-xml.test.ts compare against what the V1 itself read out of the same\n// three documents, so drift is caught by the origin rather than by a number\n// someone typed into an expectation.\n// 2. A file that is not a nota has to produce a sentence the operator can act\n// on (\"this is an NFC-e, not a supplier note\"), and `RAISE EXCEPTION` from\n// a trigger deep in a transaction is not that sentence.\n// 3. The same reader runs in the browser, so the drop zone can show what it\n// found before anything is written.\n//\n// No XML dependency. The reader below is ~70 lines because NF-e is\n// machine-generated: no CDATA in the elements we read, no DTD, no mixed content.\n// Adding a parser to the dependency tree of every app that installs this plugin\n// to avoid those 70 lines is the worse trade.\n// ---------------------------------------------------------------------------\n\nexport interface NfeSupplier {\n cnpj: string\n name: string\n tradeName?: string\n ie?: string\n city?: string\n state?: string\n}\n\nexport interface NfeItem {\n itemNumber: number\n supplierProductCode: string\n eanBarcode?: string\n description: string\n ncm?: string\n cest?: string\n cfop?: string\n unit?: string\n quantity: number\n unitPrice: number\n total: number\n discount?: number\n freight?: number\n other?: number\n icmsCst?: string\n icmsCsosn?: string\n icmsOrigin?: string\n icmsBase?: number\n icmsRate?: number\n icmsValue?: number\n pisValue?: number\n cofinsValue?: number\n ipiValue?: number\n}\n\nexport interface NfeDuplicate {\n index: number\n number?: string\n dueDate?: string\n value: number\n}\n\nexport interface NfePayment {\n index: number\n indicator?: string\n code?: string\n label?: string\n value: number\n}\n\nexport interface NfeTotals {\n total: number\n products: number\n discount: number\n freight: number\n insurance: number\n other: number\n icmsBase?: number\n icmsValue?: number\n pisValue?: number\n cofinsValue?: number\n ipiValue?: number\n}\n\nexport interface ParsedNfe {\n accessKey: string\n nfeNumber: string\n nfeSeries: string\n nfeModel: string\n issueDate: string\n natureOperation?: string\n supplier: NfeSupplier\n totals: NfeTotals\n items: NfeItem[]\n duplicates: NfeDuplicate[]\n payments: NfePayment[]\n additionalInfo?: string\n protocol?: string\n authorizedAt?: string\n}\n\nexport class NfeParseError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'NfeParseError'\n }\n}\n\n// ── The reader ─────────────────────────────────────────────────────────────\n\ninterface XNode {\n name: string\n attrs: Record<string, string>\n children: XNode[]\n text: string\n}\n\nconst ENTITIES: Record<string, string> = {\n amp: '&', lt: '<', gt: '>', quot: '\"', apos: \"'\",\n}\n\nfunction decode(raw: string): string {\n return raw.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (whole, body: string) => {\n if (body.startsWith('#x') || body.startsWith('#X')) return String.fromCodePoint(parseInt(body.slice(2), 16))\n if (body.startsWith('#')) return String.fromCodePoint(parseInt(body.slice(1), 10))\n return ENTITIES[body] ?? whole\n })\n}\n\n// Namespace prefixes are dropped: the whole document lives in the portalfiscal\n// namespace and a supplier that emits `ns2:infNFe` is emitting the same note.\nconst bare = (name: string) => {\n const i = name.indexOf(':')\n return i < 0 ? name : name.slice(i + 1)\n}\n\nfunction parseXml(xml: string): XNode {\n // Declaration, comments and processing instructions carry nothing we read.\n const src = xml\n .replace(/<\\?[\\s\\S]*?\\?>/g, '')\n .replace(/<!--[\\s\\S]*?-->/g, '')\n .replace(/<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>/g, (_m, inner: string) => inner)\n .replace(/<!DOCTYPE[^>]*>/gi, '')\n\n const root: XNode = { name: '#root', attrs: {}, children: [], text: '' }\n const stack: XNode[] = [root]\n const tag = /<\\s*(\\/?)\\s*([A-Za-z_][\\w.:-]*)((?:\\s+[\\w.:-]+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'))*)\\s*(\\/?)\\s*>/g\n\n let cursor = 0\n let m: RegExpExecArray | null\n while ((m = tag.exec(src)) !== null) {\n const [whole, closing, rawName, rawAttrs, selfClosing] = m\n const top = stack[stack.length - 1]\n const between = src.slice(cursor, m.index)\n if (between.trim()) top.text += decode(between)\n cursor = m.index + whole.length\n\n if (closing) {\n if (stack.length > 1) stack.pop()\n continue\n }\n\n const attrs: Record<string, string> = {}\n const attrRe = /([\\w.:-]+)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/g\n let a: RegExpExecArray | null\n while ((a = attrRe.exec(rawAttrs ?? '')) !== null) {\n attrs[bare(a[1])] = decode(a[2] ?? a[3] ?? '')\n }\n\n const node: XNode = { name: bare(rawName), attrs, children: [], text: '' }\n top.children.push(node)\n if (!selfClosing) stack.push(node)\n }\n return root\n}\n\nconst kids = (node: XNode | undefined, name: string): XNode[] =>\n node ? node.children.filter((c) => c.name === name) : []\n\nconst kid = (node: XNode | undefined, name: string): XNode | undefined => kids(node, name)[0]\n\n/** Walk a dot path (`ide.nNF`). Returns undefined at the first missing step. */\nfunction at(node: XNode | undefined, path: string): XNode | undefined {\n let cur = node\n for (const step of path.split('.')) {\n cur = kid(cur, step)\n if (!cur) return undefined\n }\n return cur\n}\n\nconst str = (node: XNode | undefined, path?: string): string | undefined => {\n const target = path ? at(node, path) : node\n const value = target?.text.trim()\n return value ? value : undefined\n}\n\n// The NF-e writes decimals with a dot and no thousands separator, so Number is\n// enough — but a missing tag must come back as undefined, not 0: a freight that\n// was not declared is not a freight of zero, and the difference shows up in the\n// total the payable is opened with.\nconst num = (node: XNode | undefined, path?: string): number | undefined => {\n const value = str(node, path)\n if (value === undefined) return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nconst zero = (node: XNode | undefined, path?: string): number => num(node, path) ?? 0\n\n// ── tPag → the V1's own payment vocabulary ─────────────────────────────────\n//\n// Table from NF-e 4.00 layout, collapsed onto the ten values V1 actually stores\n// (measured in `danfe_payments.payment_type`). Anything unmapped becomes\n// `outro`, which is what the V1 does with 107 of its 1.069 rows.\nconst PAYMENT_BY_CODE: Record<string, string> = {\n '01': 'dinheiro',\n '02': 'outro', // cheque\n '03': 'cartao_credito',\n '04': 'cartao_debito',\n '05': 'credito_loja',\n '10': 'outro', // vale alimentação\n '11': 'outro', // vale refeição\n '12': 'vale_presente',\n '13': 'outro', // vale combustível\n '14': 'duplicata_mercantil',\n '15': 'boleto',\n '16': 'outro', // depósito bancário\n '17': 'pix',\n '18': 'outro', // transferência bancária\n '19': 'outro', // programa de fidelidade\n '90': 'sem_pagamento',\n '99': 'outro',\n}\n\nconst PAYMENT_LABEL: Record<string, string> = {\n dinheiro: 'Dinheiro',\n cartao_credito: 'Cartão de crédito',\n cartao_debito: 'Cartão de débito',\n credito_loja: 'Crédito na loja',\n vale_presente: 'Vale presente',\n duplicata_mercantil: 'Duplicata mercantil',\n boleto: 'Boleto',\n pix: 'PIX',\n sem_pagamento: 'Sem pagamento',\n outro: 'Outro',\n}\n\n/** The V1's payment vocabulary for an NF-e `tPag` code. */\nexport function paymentTypeFromCode(code: string | undefined): string {\n if (!code) return 'outro'\n return PAYMENT_BY_CODE[code.padStart(2, '0')] ?? 'outro'\n}\n\nexport function paymentLabel(type: string): string {\n return PAYMENT_LABEL[type] ?? 'Outro'\n}\n\nexport const onlyDigits = (value: string | undefined): string => (value ?? '').replace(/\\D+/g, '')\n\n// ── The note ───────────────────────────────────────────────────────────────\n\n/**\n * Read a supplier NF-e. Accepts both the standalone `<NFe>` and the\n * `<nfeProc>` envelope the SEFAZ returns (which is what PlugNotas delivers and\n * what the V1 has stored for all 80 of Artorius' notes).\n */\nexport function parseNfeXml(xml: string): ParsedNfe {\n if (!xml || !xml.trim()) throw new NfeParseError('O arquivo está vazio.')\n\n const root = parseXml(xml)\n const proc = kid(root, 'nfeProc')\n const nfe = kid(proc ?? root, 'NFe') ?? kid(root, 'NFe')\n const inf = kid(nfe, 'infNFe')\n\n if (!inf) {\n throw new NfeParseError(\n 'Este arquivo não é uma NF-e: não encontrei <infNFe>. Se veio do fornecedor, peça o XML da nota, não o DANFE em PDF.',\n )\n }\n\n // The access key lives in the Id attribute as \"NFe\" + 44 digits. It is the\n // identity of the document — every idempotency key downstream derives from it.\n const accessKey = onlyDigits(inf.attrs.Id ?? inf.attrs.id ?? '')\n if (accessKey.length !== 44) {\n throw new NfeParseError(\n `A chave de acesso tem ${accessKey.length} dígitos e deveria ter 44. O arquivo pode estar truncado.`,\n )\n }\n\n const ide = kid(inf, 'ide')\n const model = str(ide, 'mod') ?? '55'\n if (model !== '55') {\n // 65 is NFC-e — a note the shop ISSUES at the till, not one a supplier sends.\n // Letting it through would open a payable against the shop's own customer.\n throw new NfeParseError(\n `Este XML é modelo ${model}${model === '65' ? ' (NFC-e, nota de venda no balcão)' : ''}, e a entrada de notas recebe NF-e modelo 55 de fornecedor.`,\n )\n }\n\n const emit = kid(inf, 'emit')\n const ender = kid(emit, 'enderEmit')\n const total = at(inf, 'total.ICMSTot')\n const dhEmi = str(ide, 'dhEmi') ?? str(ide, 'dEmi') ?? ''\n\n const items: NfeItem[] = kids(inf, 'det').map((det, i) => {\n const prod = kid(det, 'prod')\n const imposto = kid(det, 'imposto')\n // ICMS carries exactly one child, and which one depends on the supplier's tax\n // regime: ICMS00/20/40/60/90 for the normal regime, ICMSSN101/102/… for\n // Simples Nacional. Reading \"the child, whichever it is\" costs one line and\n // survives a supplier changing regime; a list of names does not.\n const icms = kid(imposto, 'ICMS')?.children[0]\n const pis = kid(imposto, 'PIS')?.children[0]\n const cofins = kid(imposto, 'COFINS')?.children[0]\n const ipi = kid(kid(imposto, 'IPI'), 'IPITrib')\n\n return {\n itemNumber: Number(det.attrs.nItem ?? i + 1) || i + 1,\n supplierProductCode: str(prod, 'cProd') ?? '',\n eanBarcode: str(prod, 'cEAN'),\n description: str(prod, 'xProd') ?? '(sem descrição)',\n ncm: str(prod, 'NCM'),\n cest: str(prod, 'CEST'),\n cfop: str(prod, 'CFOP'),\n unit: str(prod, 'uCom'),\n quantity: zero(prod, 'qCom'),\n unitPrice: zero(prod, 'vUnCom'),\n total: zero(prod, 'vProd'),\n discount: num(prod, 'vDesc'),\n freight: num(prod, 'vFrete'),\n other: num(prod, 'vOutro'),\n icmsCst: str(icms, 'CST'),\n icmsCsosn: str(icms, 'CSOSN'),\n icmsOrigin: str(icms, 'orig'),\n icmsBase: num(icms, 'vBC'),\n icmsRate: num(icms, 'pICMS'),\n icmsValue: num(icms, 'vICMS'),\n pisValue: num(pis, 'vPIS'),\n cofinsValue: num(cofins, 'vCOFINS'),\n ipiValue: num(ipi, 'vIPI'),\n }\n })\n\n if (items.length === 0) {\n throw new NfeParseError('A nota não tem nenhum item — não há o que dar entrada.')\n }\n\n // `cobr > dup` is the instalment plan the supplier declared. It is the reason\n // importing the note replaces typing the bill: the vencimentos come from the\n // document. A note without `dup` is not an error — it is paid on sight, and\n // the accept RPC opens a single instalment for it.\n const cobr = kid(inf, 'cobr')\n const duplicates: NfeDuplicate[] = kids(cobr, 'dup').map((dup, i) => ({\n index: i + 1,\n number: str(dup, 'nDup'),\n dueDate: str(dup, 'dVenc'),\n value: zero(dup, 'vDup'),\n }))\n\n const payments: NfePayment[] = kids(kid(inf, 'pag'), 'detPag').map((det, i) => {\n const code = str(det, 'tPag')\n const type = paymentTypeFromCode(code)\n return {\n index: i + 1,\n indicator: str(det, 'indPag'),\n code,\n label: paymentLabel(type),\n value: zero(det, 'vPag'),\n }\n })\n\n const prot = at(proc, 'protNFe.infProt')\n\n return {\n accessKey,\n nfeNumber: str(ide, 'nNF') ?? '',\n nfeSeries: str(ide, 'serie') ?? '',\n nfeModel: model,\n // The layout writes an ISO instant with offset; the inbox stores a date.\n issueDate: dhEmi.slice(0, 10),\n natureOperation: str(ide, 'natOp'),\n supplier: {\n cnpj: onlyDigits(str(emit, 'CNPJ') ?? str(emit, 'CPF')),\n name: str(emit, 'xNome') ?? '',\n tradeName: str(emit, 'xFant'),\n ie: str(emit, 'IE'),\n city: str(ender, 'xMun'),\n state: str(ender, 'UF'),\n },\n totals: {\n total: zero(total, 'vNF'),\n products: zero(total, 'vProd'),\n discount: zero(total, 'vDesc'),\n freight: zero(total, 'vFrete'),\n insurance: zero(total, 'vSeg'),\n other: zero(total, 'vOutro'),\n icmsBase: num(total, 'vBC'),\n icmsValue: num(total, 'vICMS'),\n pisValue: num(total, 'vPIS'),\n cofinsValue: num(total, 'vCOFINS'),\n ipiValue: num(total, 'vIPI'),\n },\n items,\n duplicates,\n payments,\n additionalInfo: str(at(inf, 'infAdic'), 'infCpl'),\n protocol: str(prot, 'nProt'),\n authorizedAt: str(prot, 'dhRecbto'),\n }\n}\n\n// ── The payload the staging RPC wants ──────────────────────────────────────\n//\n// `fiscalbr_stage_inbox_document` takes snake_case jsonb, and the mapping lives\n// next to the parser so a renamed field breaks in one place instead of being\n// silently dropped into a column that stays null.\n\nexport function toStagePayload(\n note: ParsedNfe,\n options: { unitId?: string | null; source?: string; xml?: string } = {},\n) {\n return {\n // O ARQUIVO VIAJA JUNTO. Ele já está na mão aqui — o parser acabou de lê-lo —\n // e sem isto os bytes morriam no fim da função: nota fiscal tem guarda legal\n // de cinco anos e a única cópia ficava na pasta de downloads de quem importou.\n ...(options.xml ? { xml: options.xml } : {}),\n access_key: note.accessKey,\n nfe_number: note.nfeNumber,\n nfe_series: note.nfeSeries,\n nfe_model: note.nfeModel,\n issue_date: note.issueDate,\n nature_operation: note.natureOperation ?? null,\n additional_info: note.additionalInfo ?? null,\n unit_id: options.unitId ?? null,\n source: options.source ?? 'xml_upload',\n supplier: {\n cnpj: note.supplier.cnpj,\n name: note.supplier.name,\n ie: note.supplier.ie ?? null,\n },\n totals: {\n total: note.totals.total,\n products: note.totals.products,\n discount: note.totals.discount,\n freight: note.totals.freight,\n insurance: note.totals.insurance,\n other: note.totals.other,\n },\n items: note.items.map((i) => ({\n item_number: i.itemNumber,\n supplier_product_code: i.supplierProductCode,\n ean_barcode: i.eanBarcode ?? null,\n description: i.description,\n ncm: i.ncm ?? null,\n cest: i.cest ?? null,\n cfop: i.cfop ?? null,\n unit: i.unit ?? null,\n quantity: i.quantity,\n unit_price: i.unitPrice,\n total: i.total,\n discount: i.discount ?? null,\n freight: i.freight ?? null,\n other: i.other ?? null,\n icms_cst: i.icmsCst ?? null,\n icms_csosn: i.icmsCsosn ?? null,\n icms_base: i.icmsBase ?? null,\n icms_rate: i.icmsRate ?? null,\n icms_value: i.icmsValue ?? null,\n pis_value: i.pisValue ?? null,\n cofins_value: i.cofinsValue ?? null,\n ipi_value: i.ipiValue ?? null,\n })),\n // The instalment carries the payment form the note declared, so the\n // reconciliation dialog opens with `Boleto` already chosen instead of blank.\n duplicates: note.duplicates.map((d) => ({\n index: d.index,\n number: d.number ?? null,\n due_date: d.dueDate ?? null,\n value: d.value,\n payment_type: note.payments.length === 1 ? paymentTypeFromCode(note.payments[0].code) : null,\n })),\n payments: note.payments.map((p) => ({\n index: p.index,\n indicator: p.indicator ?? null,\n code: p.code ?? null,\n label: p.label ?? null,\n value: p.value,\n })),\n }\n}\n","// ---------------------------------------------------------------------------\n// inbox — the data layer of Entrada de Notas.\n// ---------------------------------------------------------------------------\n// Reads go through PostgREST so RLS answers; every WRITE goes through one of the\n// four RPCs of migration 009. That split is the whole safety property of this\n// screen: the browser never inserts a stock movement or a payable, it asks the\n// database to do both in one transaction with an idempotency key derived from\n// the NF-e access key.\n//\n// Nothing here parses XML. `../lib/nfe-xml` does that, is unit-tested against\n// three real notes, and hands this module the payload the staging RPC wants.\n// ---------------------------------------------------------------------------\nimport { getSupabaseClientOptional } from '@fayz-ai/core'\nimport { getActiveTenantId } from '@fayz-ai/admin'\nimport { parseNfeXml, toStagePayload, type ParsedNfe } from '../lib/nfe-xml'\nimport type {\n InboxNote, InboxNoteDetail, InboxItem, InboxInstalment,\n InboxStatusFilter, AcceptResult, StageResult, ProductOption,\n MeasurementUnitOption, ChartAccountOption, StockLocationOption,\n} from '../types'\n\nfunction sb() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not initialized')\n return supabase\n}\n\n// ── Leitura ────────────────────────────────────────────────────────────────\n\n// The two states the V1 list shows side by side, and they are NOT the same\n// question: `reconciled/total` counts items bound to a product, `stocked_at`\n// says the entry happened. 55 notes in the V1 were reconciled and never\n// stocked — a single \"status\" column would have hidden all 55.\nconst NOTE_COLUMNS = `\n id, access_key, nfe_number, nfe_series, issue_date, received_at, status,\n manifestation_status, manifested_at, manifestation_attempts,\n nature_operation, supplier_name, supplier_cnpj, supplier_party_id, xml_content,\n total_value, total_products, total_discount, total_freight,\n invoice_id, inventory_operation_id, stocked_at, reviewed_at,\n default_chart_account_id, default_location_id, unit_id, document_id, metadata,\n items:plg_fiscalbr_inbox_items(id, reconciled, entry_type),\n duplicates:plg_fiscalbr_inbox_duplicates(id, value)\n`\n\ninterface RawNote {\n items?: Array<{ id: string; reconciled: boolean | null; entry_type: string | null }>\n duplicates?: Array<{ id: string; value: number | string | null }>\n [key: string]: unknown\n}\n\nfunction rowToNote(row: RawNote): InboxNote {\n const items = row.items ?? []\n const duplicates = row.duplicates ?? []\n return {\n id: String(row.id),\n accessKey: String(row.access_key ?? ''),\n number: String(row.nfe_number ?? ''),\n series: String(row.nfe_series ?? ''),\n issueDate: (row.issue_date as string) ?? null,\n receivedAt: (row.received_at as string) ?? null,\n status: (row.status as string) ?? 'pending',\n manifestationStatus: (row.manifestation_status as string) ?? null,\n manifestedAt: (row.manifested_at as string) ?? null,\n manifestationAttempts: Number(row.manifestation_attempts ?? 0),\n natureOperation: (row.nature_operation as string) ?? null,\n supplierName: (row.supplier_name as string) ?? '',\n supplierCnpj: (row.supplier_cnpj as string) ?? null,\n supplierPartyId: (row.supplier_party_id as string) ?? null,\n total: Number(row.total_value ?? 0),\n itemCount: items.length,\n reconciledCount: items.filter((i) => i.reconciled).length,\n instalmentCount: duplicates.length,\n // The sum of instalments, because that is the total the payable is opened\n // with (financial/084) — showing the note total here would make the list and\n // Contas a Pagar disagree on 6,3% of notes.\n instalmentTotal: duplicates.reduce((acc, d) => acc + Number(d.value ?? 0), 0),\n invoiceId: (row.invoice_id as string) ?? null,\n operationId: (row.inventory_operation_id as string) ?? null,\n stockedAt: (row.stocked_at as string) ?? null,\n documentId: (row.document_id as string) ?? null,\n hasXml: Boolean(row.xml_content),\n unitId: (row.unit_id as string) ?? null,\n }\n}\n\nexport async function listInboxNotes(options: {\n filter?: InboxStatusFilter\n search?: string\n /** Narrows to one unit. Omitted = every unit the person reaches (RLS fences\n * the rest), which is what the V1 list did on \"Todas as unidades\". */\n unitId?: string\n /** Emission window, YYYY-MM-DD and inclusive. */\n from?: string\n to?: string\n limit?: number\n} = {}): Promise<InboxNote[]> {\n const { filter = 'all', search, unitId, from, to, limit = 200 } = options\n let query = sb().from('plg_fiscalbr_inbox_documents').select(NOTE_COLUMNS)\n\n if (unitId) query = query.eq('unit_id', unitId)\n // A nota sem data de emissão não some do recorte: ela ainda não foi lida do\n // XML, e esconder o que falta ler é esconder o trabalho.\n if (from) query = query.or(`issue_date.gte.${from},issue_date.is.null`)\n if (to) query = query.or(`issue_date.lte.${to},issue_date.is.null`)\n\n // `stocked` and `pending` are about the STOCK column, not about `status`:\n // \"pendente\" in the V1 list means the entry has not happened, whatever the\n // reconciliation says.\n if (filter === 'stocked') query = query.not('stocked_at', 'is', null)\n if (filter === 'pending') query = query.is('stocked_at', null)\n if (filter === 'rejected') query = query.eq('status', 'rejected')\n if (filter === 'manifest_error') query = query.eq('manifestation_status', 'erro')\n if (search?.trim()) {\n const term = search.trim()\n query = query.or(\n `supplier_name.ilike.%${term}%,nfe_number.ilike.%${term}%,access_key.ilike.%${term}%`,\n )\n }\n\n const { data, error } = await query\n .order('issue_date', { ascending: false, nullsFirst: false })\n .order('received_at', { ascending: false })\n .limit(limit)\n if (error) throw error\n return (data ?? []).map(rowToNote)\n}\n\nconst ITEM_COLUMNS = `\n id, item_number, supplier_product_code, ean_barcode, description, ncm, cest, cfop,\n unit_commercial, quantity_commercial, unit_price_commercial, total_price, discount,\n unit_taxable, quantity_taxable,\n icms_cst, icms_csosn, icms_base, icms_rate, icms_value, pis_value, cofins_value, ipi_value,\n product_id, entry_type, chart_account_id, stock_unit_id, stock_quantity,\n conversion_factor, cost_mode, unit_cost_new, reconciled, stock_movement_id,\n shortage_quantity, shortage_reason, shortage_note, suggested_by, suggestion_confidence\n`\n\nfunction rowToItem(row: Record<string, any>): InboxItem {\n const quantity = Number(row.quantity_commercial ?? 0)\n const factor = Number(row.conversion_factor ?? 1) || 1\n return {\n id: String(row.id),\n itemNumber: Number(row.item_number ?? 0),\n supplierProductCode: row.supplier_product_code ?? '',\n eanBarcode: row.ean_barcode ?? null,\n description: row.description ?? '',\n ncm: row.ncm ?? null,\n cest: row.cest ?? null,\n cfop: row.cfop ?? null,\n unit: row.unit_commercial ?? null,\n quantity,\n unitPrice: Number(row.unit_price_commercial ?? 0),\n total: Number(row.total_price ?? 0),\n unitTaxable: row.unit_taxable ?? null,\n quantityTaxable: row.quantity_taxable == null ? null : Number(row.quantity_taxable),\n discount: row.discount == null ? null : Number(row.discount),\n icmsCst: row.icms_cst ?? null,\n icmsCsosn: row.icms_csosn ?? null,\n icmsValue: row.icms_value == null ? null : Number(row.icms_value),\n productId: row.product_id ?? null,\n entryType: row.entry_type ?? null,\n chartAccountId: row.chart_account_id ?? null,\n stockUnitId: row.stock_unit_id ?? null,\n conversionFactor: factor,\n // Derived AND stored by the RPC. Reading the stored value keeps the screen\n // showing the number the operator accepted, and falls back to the product of\n // the two only while the decision has not been saved yet.\n stockQuantity: row.stock_quantity == null ? quantity * factor : Number(row.stock_quantity),\n costMode: row.cost_mode ?? 'novo',\n unitCostNew: row.unit_cost_new == null ? null : Number(row.unit_cost_new),\n reconciled: Boolean(row.reconciled),\n suggestedBy: row.suggested_by === 'ai' || row.suggested_by === 'ean' || row.suggested_by === 'supplier_map'\n ? row.suggested_by\n : null,\n suggestionConfidence: row.suggestion_confidence == null ? null : Number(row.suggestion_confidence),\n stockMovementId: row.stock_movement_id ?? null,\n shortageQuantity: row.shortage_quantity == null ? null : Number(row.shortage_quantity),\n shortageReason: row.shortage_reason ?? null,\n shortageNote: row.shortage_note ?? null,\n }\n}\n\nexport async function getInboxNote(id: string): Promise<InboxNoteDetail | null> {\n const { data, error } = await sb()\n .from('plg_fiscalbr_inbox_documents')\n .select(NOTE_COLUMNS)\n .eq('id', id)\n .maybeSingle()\n if (error) throw error\n if (!data) return null\n\n const [items, instalments, payments] = await Promise.all([\n sb().from('plg_fiscalbr_inbox_items').select(ITEM_COLUMNS)\n .eq('inbox_document_id', id).order('item_number'),\n sb().from('plg_fiscalbr_inbox_duplicates')\n .select('id, duplicate_index, number, due_date, value, payment_type, barcode, pix_key, payment_method_id')\n .eq('inbox_document_id', id).order('duplicate_index'),\n sb().from('plg_fiscalbr_inbox_payments')\n .select('id, payment_index, payment_type_code, payment_type_label, value')\n .eq('inbox_document_id', id).order('payment_index'),\n ])\n if (items.error) throw items.error\n if (instalments.error) throw instalments.error\n\n return {\n ...rowToNote(data as RawNote),\n natureOperation: (data as any).nature_operation ?? null,\n defaultChartAccountId: (data as any).default_chart_account_id ?? null,\n defaultLocationId: (data as any).default_location_id ?? null,\n items: (items.data ?? []).map(rowToItem),\n instalments: (instalments.data ?? []).map((d: any): InboxInstalment => ({\n id: String(d.id),\n index: Number(d.duplicate_index ?? 0),\n number: d.number ?? null,\n dueDate: d.due_date ?? null,\n amount: Number(d.value ?? 0),\n paymentType: d.payment_type ?? null,\n barcode: d.barcode ?? null,\n pixKey: d.pix_key ?? null,\n paymentMethodId: d.payment_method_id ?? null,\n })),\n declaredPayments: (payments.data ?? []).map((p: any) => ({\n index: Number(p.payment_index ?? 0),\n code: p.payment_type_code ?? null,\n label: p.payment_type_label ?? null,\n value: Number(p.value ?? 0),\n })),\n }\n}\n\n// ── Escrita: sempre por RPC ────────────────────────────────────────────────\n\n/**\n * Read one XML file and stage it. Returns what the parser found together with\n * how many items the de-para already bound, because that is the number the drop\n * zone reports: \"3 itens, 2 já vinculados\" is the difference between a screen\n * that remembers the supplier and one that does not.\n */\nexport async function stageNoteFromXml(\n xml: string,\n options: { unitId?: string | null } = {},\n): Promise<StageResult & { parsed: ParsedNfe }> {\n const parsed = parseNfeXml(xml)\n const { data, error } = await sb().rpc('fiscalbr_stage_inbox_document', {\n p_note: toStagePayload(parsed, { unitId: options.unitId ?? null, xml }),\n })\n if (error) throw error\n const res = (data ?? {}) as Record<string, unknown>\n return {\n documentId: String(res.document_id ?? ''),\n accessKey: String(res.access_key ?? parsed.accessKey),\n alreadyAccepted: Boolean(res.already_accepted),\n supplierPartyId: (res.supplier_party_id as string) ?? null,\n itemCount: Number(res.items ?? 0),\n matchedCount: Number(res.matched ?? 0),\n parsed,\n }\n}\n\n/**\n * Lines only, for a note that already became payable or stock but has none:\n * restaging is refused for those, so the stored XML fills the lines and nothing else.\n */\nexport async function fillInboxLines(documentId: string, xml: string): Promise<number> {\n const payload = toStagePayload(parseNfeXml(xml))\n const { data, error } = await sb().rpc('fiscalbr_fill_inbox_lines', {\n p_document_id: documentId,\n p_items: payload.items,\n })\n if (error) throw error\n return Number((data as Record<string, unknown> | null)?.items ?? 0)\n}\n\nexport interface HealResult {\n changed: boolean\n /** The payable it pointed at was gone and no live one matched: the note can be accepted again. */\n released: boolean\n}\n\n/** Re-points or clears a payable/movement link whose target was deleted. */\nexport async function healInboxNote(documentId: string): Promise<HealResult> {\n const { data, error } = await sb().rpc('fiscalbr_heal_inbox_note', { p_document_id: documentId })\n if (error) throw error\n const r = (data as Record<string, unknown> | null) ?? {}\n return { changed: Boolean(r.changed), released: Boolean(r.released) }\n}\n\nexport interface NotePayable {\n id: string\n number: string | null\n total: number\n cancelledAt: string | null\n}\n\n/** The payable an accepted note opened; null when it no longer exists. */\nexport async function getNotePayable(invoiceId: string): Promise<NotePayable | null> {\n const { data, error } = await sb().from('plg_financial_invoices')\n .select('id, number, total, cancelled_at').eq('id', invoiceId).maybeSingle()\n if (error) throw error\n if (!data) return null\n return { id: data.id, number: data.number ?? null, total: Number(data.total ?? 0), cancelledAt: data.cancelled_at ?? null }\n}\n\nexport interface PullCnpjOption { id: string; name: string; cnpj: string }\n\n/** Why a pull by key did not stage a note — each one has a different fix on screen. */\nexport class PullByKeyError extends Error {\n constructor(message: string, readonly code?: string, readonly options?: PullCnpjOption[]) {\n super(message)\n }\n}\n\nexport type PullByKeyResult =\n | ({ status: 'staged' } & StageResult & { parsed: ParsedNfe })\n | { status: 'pending'; message: string }\n\n/**\n * Ask the SEFAZ (via PlugNotas) for one note by its access key, then stage it\n * exactly like a dropped XML. Nothing here manifests the note.\n */\nexport async function pullNoteByKey(\n key: string,\n options: { legalEntityId?: string; unitId?: string | null } = {},\n): Promise<PullByKeyResult> {\n const { data, error } = await sb().functions.invoke('fiscalbr-dfe-pull', {\n body: { key: key.replace(/\\D/g, ''), legalEntityId: options.legalEntityId, tenantId: getActiveTenantId() ?? null },\n })\n if (error) {\n // The function's own message lives in the response body, not in `error.message`.\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* keep generic */ }\n throw new PullByKeyError(body?.error || error.message || 'Falha ao falar com a SEFAZ.', body?.code, body?.options)\n }\n if (data?.pending) return { status: 'pending', message: String(data.message ?? '') }\n if (!data?.xml) throw new PullByKeyError('A SEFAZ não devolveu o XML desta nota.')\n return { status: 'staged', ...(await stageNoteFromXml(String(data.xml), { unitId: options.unitId })) }\n}\n\n/** The DANFE of an inbound note, from the fiscal provider. Rejects with the provider's reason. */\nexport async function getInboxNotePdf(accessKey: string): Promise<Blob> {\n const { data, error } = await sb().functions.invoke('fiscalbr-dfe-pull', {\n body: { action: 'pdf', key: accessKey, tenantId: getActiveTenantId() ?? null },\n })\n if (error) {\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* keep generic */ }\n throw new PullByKeyError(body?.error || error.message || 'Falha ao buscar o DANFE.', body?.code)\n }\n if (!(data instanceof Blob)) throw new PullByKeyError('O serviço fiscal não devolveu um PDF.')\n return data\n}\n\nexport interface ItemDecisionInput {\n id: string\n productId?: string | null\n entryType?: string | null\n chartAccountId?: string | null\n stockUnitId?: string | null\n conversionFactor?: number\n costMode?: string | null\n /** Quem escreveu. `null`/ausente grava NULL, que é «uma pessoa escolheu». */\n suggestedBy?: 'ai' | 'ean' | 'supplier_map' | null\n suggestionConfidence?: number | null\n shortageQuantity?: number | null\n shortageReason?: string | null\n shortageNote?: string | null\n}\n\nexport interface InstalmentInput {\n index: number\n number?: string | null\n dueDate?: string | null\n amount: number\n paymentType?: string | null\n barcode?: string | null\n pixKey?: string | null\n paymentMethodId?: string | null\n}\n\nexport async function saveNoteDecision(input: {\n documentId: string\n items: ItemDecisionInput[]\n defaultChartAccountId?: string | null\n defaultLocationId?: string | null\n instalments?: InstalmentInput[] | null\n}): Promise<{ saved: number; items: number; reconciled: number }> {\n const { data, error } = await sb().rpc('fiscalbr_save_inbox_decision', {\n p_document_id: input.documentId,\n p_items: input.items.map((i) => ({\n id: i.id,\n product_id: i.productId ?? null,\n entry_type: i.entryType ?? null,\n chart_account_id: i.chartAccountId ?? null,\n stock_unit_id: i.stockUnitId ?? null,\n conversion_factor: i.conversionFactor ?? 1,\n cost_mode: i.costMode ?? 'novo',\n suggested_by: i.suggestedBy ?? null,\n suggestion_confidence: i.suggestionConfidence ?? null,\n shortage_quantity: i.shortageQuantity ?? null,\n shortage_reason: i.shortageReason ?? null,\n shortage_note: i.shortageNote ?? null,\n })),\n p_default_chart_account_id: input.defaultChartAccountId ?? null,\n p_default_location_id: input.defaultLocationId ?? null,\n p_duplicates: input.instalments\n ? input.instalments.map((d) => ({\n index: d.index,\n number: d.number ?? null,\n due_date: d.dueDate ?? null,\n value: d.amount,\n payment_type: d.paymentType ?? null,\n barcode: d.barcode ?? null,\n pix_key: d.pixKey ?? null,\n payment_method_id: d.paymentMethodId ?? null,\n }))\n : null,\n })\n if (error) throw error\n const res = (data ?? {}) as Record<string, unknown>\n return {\n saved: Number(res.saved ?? 0),\n items: Number(res.items ?? 0),\n reconciled: Number(res.reconciled ?? 0),\n }\n}\n\n/**\n * Accept: stock entry and payable, one transaction. `alreadyAccepted` coming\n * back true is not an error — it is the second click, and the RPC is idempotent\n * on the NF-e access key.\n */\n/**\n * Bind the note to its supplier by CNPJ. With `create`, a supplier missing from\n * the registry is created from the note's name and CNPJ — the V1 gesture.\n */\nexport async function linkInboxSupplier(documentId: string, create = false): Promise<{ supplierPartyId: string | null; created: boolean }> {\n const { data, error } = await sb().rpc('fiscalbr_link_inbox_supplier', { p_document_id: documentId, p_create: create })\n if (error) throw error\n const res = (data ?? {}) as Record<string, unknown>\n return { supplierPartyId: (res.supplier_party_id as string) ?? null, created: Boolean(res.created) }\n}\n\nexport async function acceptNote(documentId: string, locationId?: string | null): Promise<AcceptResult> {\n // The payable takes its counterparty from the note, so the supplier is bound\n // (or created) first — otherwise the title is born without one.\n await linkInboxSupplier(documentId, true).catch((e: { code?: string }) => {\n // A pool without migration 020 has no such function; accepting still works there.\n if (e?.code !== 'PGRST202' && e?.code !== '42883') throw e\n })\n const { data, error } = await sb().rpc('fiscalbr_accept_inbox_document', {\n p_document_id: documentId,\n p_location_id: locationId ?? null,\n })\n if (error) throw error\n const res = (data ?? {}) as Record<string, unknown>\n return {\n documentId: String(res.document_id ?? documentId),\n alreadyAccepted: Boolean(res.already_accepted),\n invoiceId: (res.invoice_id as string) ?? null,\n invoiceTotal: Number(res.invoice_total ?? 0),\n instalments: Number(res.installments ?? 0),\n operationId: (res.operation_id as string) ?? null,\n stockLines: Number(res.stock_lines ?? 0),\n }\n}\n\nexport async function rejectNote(documentId: string, reason?: string): Promise<void> {\n const { error } = await sb().rpc('fiscalbr_reject_inbox_document', {\n p_document_id: documentId,\n p_reason: reason ?? null,\n })\n if (error) throw error\n}\n\n// ── Os cadastros que a conciliação precisa ─────────────────────────────────\n\nexport async function searchProducts(term: string, limit = 20): Promise<ProductOption[]> {\n let query = sb().from('products')\n .select('id, name, sku, unit, cost, kind')\n .eq('is_active', true)\n .limit(limit)\n if (term.trim()) query = query.or(`name.ilike.%${term.trim()}%,sku.ilike.%${term.trim()}%`)\n const { data, error } = await query.order('name')\n if (error) throw error\n return (data ?? []).map((p: any) => ({\n id: String(p.id), name: p.name ?? '', sku: p.sku ?? null,\n unit: p.unit ?? null, cost: p.cost == null ? null : Number(p.cost), kind: p.kind ?? null,\n }))\n}\n\n/**\n * O XML autorizado desta nota, como ele chegou.\n *\n * Consulta à parte e não campo do detalhe: são 10–50 KB de texto por nota, e a\n * lista de uma conta grande carregaria megabytes que ninguém abriu. Desce quando\n * alguém clica em baixar.\n */\nexport async function getInboxNoteXml(id: string): Promise<string | null> {\n const { data, error } = await sb().from('plg_fiscalbr_inbox_documents')\n .select('xml_content').eq('id', id).maybeSingle()\n if (error) throw error\n return (data as { xml_content?: string } | null)?.xml_content ?? null\n}\n\n/**\n * Qual nota tem este número, quando ele é único na conta.\n *\n * É o caminho das linhas IMPORTADAS do V1: elas trazem «Entrada via DANFE NF-e\n * 10592» escrito no motivo e não trazem operação nenhuma — o importador copiou o\n * movimento e não o vínculo. Das 3.088 assim, as 3.088 acham a nota aqui.\n *\n * Exige UNICIDADE: número de NF-e repete entre fornecedores, e abrir a nota\n * errada é pior que não abrir nenhuma.\n */\nexport async function findInboxNoteByNumber(nfeNumber: string): Promise<string | null> {\n const n = (nfeNumber ?? '').replace(/\\D/g, '')\n if (!n) return null\n const { data, error } = await sb().from('plg_fiscalbr_inbox_documents')\n .select('id').eq('nfe_number', n).limit(2)\n if (error) throw error\n const linhas = (data ?? []) as Array<{ id: string }>\n return linhas.length === 1 ? linhas[0].id : null\n}\n\n/**\n * Qual nota originou esta operação de estoque.\n *\n * O movimento guarda `operation_id`; a nota guarda `inventory_operation_id`. É o\n * único elo entre o razão do estoque e o documento que o produziu, e é o que\n * permite à linha de Movimentações abrir a NF-e de onde ela veio.\n */\nexport async function findInboxNoteByOperation(operationId: string): Promise<string | null> {\n if (!operationId) return null\n const { data, error } = await sb().from('plg_fiscalbr_inbox_documents')\n .select('id').eq('inventory_operation_id', operationId).limit(1).maybeSingle()\n if (error) throw error\n return (data as { id?: string } | null)?.id ?? null\n}\n\n/** O que a edge function de sugestão devolve. */\nexport interface SuggestNoteItemsResult {\n /** Itens que o modelo deixou PRONTOS — com produto. */\n applied: number\n /** Itens em que ele só soube dizer o tipo: continuam «falta decidir». */\n typedOnly: number\n /** Itens que o índice ligou sozinho, sem modelo (EAN ou de-para). */\n bound: number\n boundByEan: number\n /** Nomes que o modelo propôs para o que não existe no catálogo. */\n newProductNames: string[]\n warnings: string[]\n}\n\n/**\n * Pede a sugestão ao servidor.\n *\n * É edge function e não turno de agente porque o broker de chat recusou a\n * pergunta («Message is too long») e, antes disso, porque um turno de chat tem\n * teto de rodadas, morre na navegação e persiste tudo no histórico de alguém.\n * Ver `functions/fiscalbr-suggest-note-items`.\n *\n * A FUNCTION GRAVA. Ela escreve pela mesma RPC do «Salvar conciliação» (que não\n * marca `reconciled`), então quem chama só precisa recarregar a nota — e a\n * sugestão sobrevive a fechar o modal, que era o buraco da versão anterior.\n *\n * O TENANT VAI NO CORPO, nunca em cabeçalho. É a regra que o console já aplica\n * (ver `isEdgeFunctionCall` em `@fayz-ai/admin/data/client`): a borda declara\n * uma lista fixa de `Access-Control-Allow-Headers`, e um cabeçalho fora da lista\n * faz o NAVEGADOR recusar o preflight e bloquear o POST antes de ele sair — não\n * sobra requisição no log, só um `OPTIONS` sozinho, e quem está usando lê «CORS».\n * Foi assim que vinte funções pararam de uma vez.\n *\n * Do outro lado a function põe `x-fayz-tenant` no PRÓPRIO cliente dela, porque é\n * o PostgREST que lê esse cabeçalho (`app.requested_tenant()`), e ali não há\n * preflight nenhum. Sem isso, quem tem mais de uma conta não tem tenant: o recuo\n * de `app._current_tenant_id_raw()` é «sua única conta», e com dez contas ele\n * devolve NULL — a nota existe, a RLS a esconde, e a tela diz 404.\n */\nexport async function suggestNoteItems(\n documentId: string,\n reevaluate = false,\n): Promise<SuggestNoteItemsResult> {\n const { data, error } = await sb().functions.invoke('fiscalbr-suggest-note-items', {\n body: { documentId, reevaluate, tenantId: getActiveTenantId() ?? null },\n })\n // A function responde `{ok:false,error}` com status 4xx/5xx; o cliente do\n // Supabase embrulha isso num FunctionsHttpError cujo `message` é genérico\n // («non-2xx status code»), então a mensagem útil mora no corpo.\n if (error) {\n const corpo = await (error as { context?: Response }).context?.json?.().catch(() => null)\n throw new Error((corpo as { error?: string } | null)?.error ?? error.message)\n }\n const res = (data ?? {}) as Record<string, unknown>\n if (res.ok === false) throw new Error(String(res.error ?? 'A sugestão falhou.'))\n return {\n applied: Number(res.applied ?? 0),\n typedOnly: Number(res.typedOnly ?? 0),\n bound: Number(res.bound ?? 0),\n boundByEan: Number(res.boundByEan ?? 0),\n newProductNames: Array.isArray(res.newProductNames)\n ? res.newProductNames.filter((n): n is string => typeof n === 'string')\n : [],\n warnings: Array.isArray(res.warnings)\n ? res.warnings.filter((w): w is string => typeof w === 'string')\n : [],\n }\n}\n\n/**\n * Os produtos JÁ VINCULADOS, pelo id.\n *\n * `plg_fiscalbr_inbox_items.product_id` guarda o id e mais nada, e o seletor de\n * produto precisa do NOME para mostrar o que está escolhido. Sem isto a linha\n * abria com o campo vazio sobre um produto vinculado — a tela dizia «conferido»\n * apontando para um campo em branco.\n */\nexport async function listProductsByIds(ids: string[]): Promise<ProductOption[]> {\n if (ids.length === 0) return []\n const { data, error } = await sb().from('products')\n .select('id, name, sku, unit, cost, kind')\n .in('id', ids)\n if (error) throw error\n return (data ?? []).map((p: any) => ({\n id: String(p.id), name: p.name ?? '', sku: p.sku ?? null,\n unit: p.unit ?? null, cost: p.cost == null ? null : Number(p.cost), kind: p.kind ?? null,\n }))\n}\n\nexport async function listMeasurementUnits(): Promise<MeasurementUnitOption[]> {\n const { data, error } = await sb().from('plg_inventory_measurement_units')\n .select('id, name, abbreviation, is_base').eq('is_active', true).order('name')\n if (error) throw error\n return (data ?? []).map((u: any) => ({\n id: String(u.id), name: u.name ?? '', abbreviation: u.abbreviation ?? '',\n isBase: Boolean(u.is_base),\n }))\n}\n\n/**\n * Leaf accounts only. `kind` never existed on this table: PostgREST answered 400\n * to the whole query and the caught error left the picker silently empty.\n */\nexport async function listChartAccounts(): Promise<ChartAccountOption[]> {\n const { data, error } = await sb().from('plg_financial_chart_of_accounts')\n .select('id, code, name, account_type, node_type, parent_id, is_active').order('code')\n if (error) throw error\n const rows = (data ?? []).filter((a: any) => a.is_active !== false)\n const parents = new Set(rows.map((a: any) => a.parent_id).filter(Boolean).map(String))\n return rows\n .filter((a: any) => a.node_type !== 'group' && !parents.has(String(a.id)))\n .map((a: any) => ({\n id: String(a.id), code: a.code ?? '', name: a.name ?? '', kind: a.account_type ?? null,\n }))\n}\n\nexport async function listStockLocations(): Promise<StockLocationOption[]> {\n const { data, error } = await sb().from('plg_inventory_stock_locations')\n .select('id, name, unit_id, is_active').order('name')\n if (error) throw error\n return (data ?? [])\n .filter((l: any) => l.is_active !== false)\n .map((l: any) => ({ id: String(l.id), name: l.name ?? '', unitId: l.unit_id ?? null }))\n}\n\n/**\n * What the supplier catalogue already remembers. The reconciliation screen shows\n * it next to a bound product so the operator can tell a de-para hit from a\n * product that appeared out of nowhere.\n */\nexport async function listSupplierMap(supplierCnpj: string): Promise<Array<{\n supplierProductCode: string; productId: string; hitCount: number; lastUsedAt: string | null\n}>> {\n if (!supplierCnpj) return []\n const { data, error } = await sb().from('plg_fiscalbr_supplier_product_map')\n .select('supplier_product_code, product_id, hit_count, last_used_at')\n .eq('supplier_cnpj', supplierCnpj)\n if (error) throw error\n return (data ?? []).map((m: any) => ({\n supplierProductCode: m.supplier_product_code ?? '',\n productId: String(m.product_id),\n hitCount: Number(m.hit_count ?? 0),\n lastUsedAt: m.last_used_at ?? null,\n }))\n}\n\n// ── Anexos: a casa é `public.documents`, como os do título ───────────────────\n\nexport interface NoteAttachment {\n id: string\n fileName: string\n fileSize?: number\n mimeType?: string\n /** Signed, short-lived. Absent when the bytes cannot be opened from here. */\n url?: string\n createdAt: string\n}\n\nconst NOTE_SUBJECT = 'fiscalbr_inbox_document'\nconst INVOICE_SUBJECT = 'financial_invoice'\n\n/**\n * The note's attachments and, once it has a payable, the payable's — one list,\n * because to the operator the boleto belongs to the purchase, not to a table.\n */\nexport async function listNoteAttachments(noteId: string, invoiceId?: string | null): Promise<NoteAttachment[]> {\n const subjects = [`and(subject_type.eq.${NOTE_SUBJECT},subject_id.eq.${noteId})`]\n if (invoiceId) subjects.push(`and(subject_type.eq.${INVOICE_SUBJECT},subject_id.eq.${invoiceId})`)\n const { data, error } = await sb().from('documents')\n .select('id, file_name, file_size, mime_type, storage_bucket, storage_path, created_at')\n .or(subjects.join(','))\n .eq('is_active', true)\n .order('created_at')\n if (error) throw error\n const rows = (data ?? []) as Array<Record<string, any>>\n // The bucket is private: the stored public URL answers 400, so sign on read.\n const signed = new Map<string, string>()\n const byBucket = new Map<string, string[]>()\n for (const r of rows) {\n if (!r.storage_bucket || !r.storage_path) continue\n byBucket.set(r.storage_bucket, [...(byBucket.get(r.storage_bucket) ?? []), r.storage_path])\n }\n for (const [bucket, paths] of byBucket) {\n const { data: urls } = await sb().storage.from(bucket).createSignedUrls(paths, 60 * 30)\n for (const u of urls ?? []) if (u.path && u.signedUrl) signed.set(u.path, u.signedUrl)\n }\n return rows.map((r) => ({\n id: r.id,\n fileName: r.file_name ?? 'Anexo',\n fileSize: r.file_size ?? undefined,\n mimeType: r.mime_type ?? undefined,\n url: signed.get(r.storage_path) ?? undefined,\n createdAt: r.created_at,\n }))\n}\n\n/** Attach to the payable when it exists, otherwise to the note (moved on accept). */\nexport async function addNoteAttachment(noteId: string, invoiceId: string | null | undefined, file: File): Promise<void> {\n const tenantId = getActiveTenantId()\n if (!tenantId) throw new Error('Conta sem empresa ativa')\n const subjectType = invoiceId ? INVOICE_SUBJECT : NOTE_SUBJECT\n const subjectId = invoiceId ?? noteId\n // The bucket policy only accepts paths under the tenant's own folder.\n const path = `${tenantId}/${subjectType}/${subjectId}/${Date.now()}_${file.name.replace(/[^\\w.\\-]+/g, '_')}`\n const { error: upErr } = await sb().storage.from('attachments').upload(path, file, { contentType: file.type || undefined })\n if (upErr) throw upErr\n const { error } = await sb().from('documents').insert({\n tenant_id: tenantId,\n kind: 'attachment',\n status: 'active',\n subject_type: subjectType,\n subject_id: subjectId,\n file_name: file.name,\n file_size: file.size,\n mime_type: file.type || null,\n storage_provider: 'supabase',\n storage_bucket: 'attachments',\n storage_path: path,\n })\n if (error) {\n await sb().storage.from('attachments').remove([path]).catch(() => {})\n throw error\n }\n}\n\nexport async function removeNoteAttachment(id: string): Promise<void> {\n const { error } = await sb().from('documents').update({ is_active: false }).eq('id', id)\n if (error) throw error\n}\n\n/** After accept the payable exists: what was attached to the note becomes its. */\nexport async function moveNoteAttachmentsToInvoice(noteId: string, invoiceId: string): Promise<void> {\n const { error } = await sb().from('documents')\n .update({ subject_type: INVOICE_SUBJECT, subject_id: invoiceId })\n .eq('subject_type', NOTE_SUBJECT)\n .eq('subject_id', noteId)\n if (error) throw error\n}\n\nexport interface PaymentCode {\n kind: 'barcode' | 'pix'\n code: string\n amount: number | null\n dueDate: string | null\n}\n\n/** Read a boleto barcode or a Pix code off an image/PDF — the V1 automation. */\nexport async function extractPaymentCode(file: File): Promise<PaymentCode | null> {\n const base64 = await new Promise<string>((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => { const r = String(reader.result); resolve(r.slice(r.indexOf(',') + 1)) }\n reader.onerror = () => reject(reader.error)\n reader.readAsDataURL(file)\n })\n const { data, error } = await sb().functions.invoke('fiscalbr-payment-extract', {\n body: { name: file.name, mime: file.type, base64 },\n })\n if (error) {\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* keep generic */ }\n throw new Error(body?.error || error.message || 'Falha ao ler o boleto.')\n }\n if (!data?.ok || data.kind === 'none' || !data.code) return null\n const code = String(data.code)\n if (data.kind === 'barcode') {\n const parsed = parseBoleto(code)\n return {\n kind: 'barcode',\n code: code.replace(/\\D/g, ''),\n amount: parsed?.amount ?? (typeof data.amount === 'number' ? data.amount : null),\n dueDate: parsed?.dueDate ?? (data.due_date ?? null),\n }\n }\n return { kind: 'pix', code, amount: typeof data.amount === 'number' ? data.amount : null, dueDate: data.due_date ?? null }\n}\n\n/**\n * Amount and due date straight from a bank boleto's digits, so the instalment\n * does not depend on the model reading the printed value right. Concessionária\n * slips (starting with 8) carry no due-date factor and fall back to the model.\n */\nexport function parseBoleto(raw: string): { amount: number | null; dueDate: string | null } | null {\n const d = raw.replace(/\\D/g, '')\n if (d.startsWith('8')) return null\n let barcode: string\n if (d.length === 44) barcode = d\n else if (d.length === 47) barcode = d.slice(0, 4) + d[32] + d.slice(33, 47) + d.slice(4, 9) + d.slice(10, 20) + d.slice(21, 31)\n else return null\n const factor = Number(barcode.slice(5, 9))\n const cents = Number(barcode.slice(9, 19))\n let dueDate: string | null = null\n if (factor > 0) {\n // FEBRABAN reset the factor at 1000 on 22/02/2025 (it hit 9999 the day before).\n const base = factor >= 1000 && Date.now() >= Date.UTC(2025, 1, 22)\n ? Date.UTC(2025, 1, 22) - 1000 * 86400000\n : Date.UTC(1997, 9, 7)\n dueDate = new Date(base + factor * 86400000).toISOString().slice(0, 10)\n }\n return { amount: cents > 0 ? cents / 100 : null, dueDate }\n}\n\nexport interface InboxIntakeHealth {\n /** CNPJs that should receive notes from SEFAZ and are not. */\n stalled: number\n /** Last time any of them received, for \"não chegam desde…\". */\n since: string | null\n /** When the A1 certificate expired, if that is the reason. */\n certificateExpiredAt: string | null\n /** The provider's own words, when the reason is something else. */\n error: string | null\n /** A unit of the affected CNPJ, whose tax settings take the new certificate. */\n unitId: string | null\n}\n\nconst STALE_AFTER_MS = 24 * 60 * 60 * 1000\n\n/** Parses \"Certificado vencido em: 02/10/2026 10:16:00\" from the provider's error. */\nfunction expiryFromError(error: string | null): string | null {\n const m = error?.match(/vencido em:?\\s*(\\d{2})\\/(\\d{2})\\/(\\d{4})/i)\n return m ? `${m[3]}-${m[2]}-${m[1]}` : null\n}\n\n/** Whether automatic intake from SEFAZ is working for this account, and why not. Null when it is. */\nexport async function getInboxIntakeHealth(): Promise<InboxIntakeHealth | null> {\n const { data, error } = await sb().from('plg_fiscalbr_emitter_settings')\n .select('legal_entity_id, dfe_sync_enabled, dfe_last_sync_at, dfe_last_error, certificate_expires_at')\n .eq('dfe_sync_enabled', true)\n if (error) throw error\n const now = Date.now()\n const stalled = (data ?? []).filter((r: any) => {\n const expired = r.certificate_expires_at && Date.parse(r.certificate_expires_at) < now\n const stale = !r.dfe_last_sync_at || now - Date.parse(r.dfe_last_sync_at) > STALE_AFTER_MS\n return expired || stale || Boolean(r.dfe_last_error)\n })\n if (stalled.length === 0) return null\n const since = stalled.map((r: any) => r.dfe_last_sync_at as string | null).filter(Boolean).sort()[0] ?? null\n const withError = stalled.find((r: any) => r.dfe_last_error)\n const certificateExpiredAt = stalled\n .map((r: any) => (r.certificate_expires_at && Date.parse(r.certificate_expires_at) < now\n ? (r.certificate_expires_at as string)\n : expiryFromError(r.dfe_last_error)))\n .find(Boolean) ?? null\n const target = stalled.find((r: any) => r.certificate_expires_at && Date.parse(r.certificate_expires_at) < now)\n ?? withError ?? stalled[0]\n const { data: unit } = await sb().from('v_unit_company_legal_entities')\n .select('unit_id').eq('company_legal_entity_id', target.legal_entity_id).limit(1).maybeSingle()\n return { stalled: stalled.length, since, certificateExpiredAt, error: withError?.dfe_last_error ?? null, unitId: unit?.unit_id ?? null }\n}\n\nexport interface SyncNewNotesResult {\n added: number\n /** Delivered by SEFAZ only as a summary (not manifested yet) or still being fetched. */\n waiting: number\n failed: number\n}\n\n/**\n * Brings in the notes SEFAZ delivered since the newest one here: the server lists\n * the access keys, and each missing one goes through `pullNoteByKey` — the same\n * path as «Puxar por chave», so nothing here bypasses its permissions.\n */\nexport async function syncNewNotes(max = 25): Promise<SyncNewNotesResult> {\n const { data: newest } = await sb().from('plg_fiscalbr_inbox_documents')\n .select('issue_date').order('issue_date', { ascending: false }).limit(1).maybeSingle()\n // Two days of overlap: SEFAZ indexes some notes a day after they are issued.\n const since = newest?.issue_date\n ? new Date(Date.parse(newest.issue_date) - 2 * 86_400_000).toISOString().slice(0, 10)\n : undefined\n const { data, error } = await sb().functions.invoke('fiscalbr-dfe-pull', {\n body: { action: 'list', since, tenantId: getActiveTenantId() ?? null },\n })\n if (error) {\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* generic below */ }\n throw new PullByKeyError(body?.error || error.message || 'Falha ao falar com a SEFAZ.', body?.code)\n }\n const listed = (data?.notes ?? []) as Array<{ key: string; legalEntityId: string }>\n if (listed.length === 0) return { added: 0, waiting: 0, failed: (data?.failures ?? []).length }\n\n const keys = [...new Set(listed.map((n) => n.key))]\n const { data: known } = await sb().from('plg_fiscalbr_inbox_documents').select('access_key').in('access_key', keys)\n const have = new Set((known ?? []).map((r: any) => r.access_key as string))\n const missing = listed.filter((n, i) => !have.has(n.key) && listed.findIndex((m) => m.key === n.key) === i).slice(0, max)\n\n const result: SyncNewNotesResult = { added: 0, waiting: 0, failed: (data?.failures ?? []).length }\n for (const n of missing) {\n try {\n const r = await pullNoteByKey(n.key, { legalEntityId: n.legalEntityId })\n if (r.status === 'staged') result.added++\n else result.waiting++\n } catch (e) {\n if (e instanceof PullByKeyError && (e.code === 'summary_only' || e.code === 'throttled')) result.waiting++\n else result.failed++\n }\n }\n return result\n}\n\n/** Each product's stock unit (inventory details), for prefilling the note's lines. */\nexport async function listProductStockUnits(productIds: string[]): Promise<Map<string, string>> {\n if (productIds.length === 0) return new Map()\n const { data, error } = await sb().from('plg_inventory_product_details')\n .select('product_id, measurement_unit_id').in('product_id', productIds).not('measurement_unit_id', 'is', null)\n if (error) throw error\n return new Map((data ?? []).map((r: any) => [String(r.product_id), String(r.measurement_unit_id)]))\n}\n","import React, { useEffect, useState } from 'react'\nimport { KeyRound, Loader2 } from 'lucide-react'\nimport {\n Button, Input, Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle,\n Select, SelectContent, SelectItem, SelectTrigger, SelectValue,\n} from '@fayz-ai/ui'\nimport { pullNoteByKey, PullByKeyError, type PullCnpjOption, type PullByKeyResult } from '../data/inbox'\n\nconst formatCnpj = (d: string) => `${d.slice(0, 2)}.${d.slice(2, 5)}.${d.slice(5, 8)}/${d.slice(8, 12)}-${d.slice(12)}`\n\n/** Groups of four, the way the key is printed on the DANFE, so a typo is findable by eye. */\nconst groupKey = (digits: string) => digits.replace(/(\\d{4})(?=\\d)/g, '$1 ')\n\nexport interface PullByKeyDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n unitId?: string | null\n /** Opens with this key already typed, for a note that is already on screen. */\n initialKey?: string\n /** Called after a note was staged, with what the parser found. */\n onPulled: (result: Extract<PullByKeyResult, { status: 'staged' }>) => void\n}\n\nexport function PullByKeyDialog({ open, onOpenChange, unitId, initialKey, onPulled }: PullByKeyDialogProps) {\n const [value, setValue] = useState('')\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n const [cnpjOptions, setCnpjOptions] = useState<PullCnpjOption[] | null>(null)\n const [legalEntityId, setLegalEntityId] = useState('')\n\n useEffect(() => {\n if (open) { if (initialKey) setValue(initialKey); return }\n setValue(''); setError(null); setNotice(null); setCnpjOptions(null); setLegalEntityId('')\n }, [open, initialKey])\n\n const digits = value.replace(/\\D/g, '').slice(0, 44)\n const needsCnpj = !!cnpjOptions && !legalEntityId\n const blocked = digits.length !== 44\n ? `Faltam ${44 - digits.length} dígitos`\n : needsCnpj ? 'Escolha o CNPJ' : null\n\n const pull = async () => {\n setBusy(true); setError(null); setNotice(null)\n try {\n const result = await pullNoteByKey(digits, { legalEntityId: legalEntityId || undefined, unitId })\n if (result.status === 'pending') { setNotice(result.message); return }\n onPulled(result)\n onOpenChange(false)\n } catch (e) {\n if (e instanceof PullByKeyError && e.code === 'choose_cnpj' && e.options?.length) {\n setCnpjOptions(e.options)\n setError(null)\n return\n }\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <Modal open={open} onOpenChange={(o) => { if (!busy) onOpenChange(o) }}>\n <ModalContent size=\"md\">\n <ModalHeader>\n <ModalTitle className=\"flex items-center gap-2\">\n <KeyRound className=\"h-5 w-5\" aria-hidden />\n Puxar NF-e por chave de acesso\n </ModalTitle>\n <ModalDescription>\n Para baixar uma nota que não veio na coleta automática (por exemplo, emitida antes de ligar o\n recebimento de DANFes). Cole a chave de acesso de 44 dígitos.\n </ModalDescription>\n </ModalHeader>\n <ModalBody className=\"space-y-3\">\n <Input\n value={groupKey(digits)}\n onChange={(e) => { setValue(e.target.value); setError(null); setNotice(null) }}\n onKeyDown={(e) => { if (e.key === 'Enter' && !blocked && !busy) void pull() }}\n placeholder=\"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000\"\n inputMode=\"numeric\"\n autoFocus\n className=\"font-mono tabular-nums\"\n aria-label=\"Chave de acesso\"\n data-testid=\"pull-by-key-input\"\n />\n <p className={`text-xs tabular-nums ${digits.length === 44 ? 'text-success-soft-foreground' : 'text-muted-foreground'}`}>\n {digits.length}/44 dígitos\n </p>\n\n {cnpjOptions && (\n <div className=\"space-y-1.5\">\n <p className=\"text-sm font-medium\">De qual CNPJ é esta nota?</p>\n <Select value={legalEntityId} onValueChange={setLegalEntityId}>\n <SelectTrigger><SelectValue placeholder=\"Escolha o CNPJ destinatário\" /></SelectTrigger>\n <SelectContent>\n {cnpjOptions.map((o) => (\n <SelectItem key={o.id} value={o.id}>{o.name} · {formatCnpj(o.cnpj)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n\n {error && <p className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\" role=\"alert\">{error}</p>}\n {notice && <p className=\"rounded-md bg-warning-soft px-3 py-2 text-sm text-warning-soft-foreground\" role=\"status\">{notice}</p>}\n\n <p className=\"text-xs text-muted-foreground\">\n Puxar não manifesta a nota na SEFAZ — a manifestação continua sendo feita no sistema antigo.\n </p>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={busy}>Cancelar</Button>\n <Button onClick={() => { void pull() }} disabled={busy || !!blocked} data-testid=\"pull-by-key-submit\">\n {busy ? <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" /> : <KeyRound className=\"mr-1.5 h-4 w-4\" />}\n {busy ? 'Buscando na SEFAZ…' : blocked ?? 'Puxar nota'}\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n )\n}\n","// ---------------------------------------------------------------------------\n// Manifesto de Notas — a lista das notas de compra, e a área onde o XML entra.\n// ---------------------------------------------------------------------------\n// Duas colunas de estado, e a diferença entre elas é o coração da tela:\n//\n// Conciliação quantos itens já sabem a que produto correspondem — 0/1, 1/1, 0/6\n// Estoque se a entrada aconteceu — Pendente / Estocado\n//\n// No V1 havia 55 notas conciliadas e nunca estocadas. Uma coluna de \"status\" só\n// teria escondido as 55, e a pergunta \"por que o estoque não mudou?\" não teria\n// resposta na tela.\n// ---------------------------------------------------------------------------\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Eye, FileCode2, FileDown, FileText, Inbox, KeyRound, ListChecks, Loader2, RefreshCw, Trash2, UploadCloud } from 'lucide-react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport {\n Button, Card, ChevronPager, DataTable, FilterPanel, FilterPanelField, PageHeaderActions, SearchField,\n RowActions, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Tooltip, TooltipContent,\n TooltipProvider, TooltipTrigger, useFilterDraft,\n} from '@fayz-ai/ui'\nimport { PageActions, adminNavigateTo, useUnitFilter } from '@fayz-ai/admin'\nimport { formatCurrency } from '@fayz-ai/core'\nimport { getInboxIntakeHealth, getInboxNotePdf, getInboxNoteXml, listInboxNotes, stageNoteFromXml, rejectNote, syncNewNotes, type InboxIntakeHealth } from '../data/inbox'\nimport type { InboxNote, InboxStatusFilter } from '../types'\nimport { PullByKeyDialog } from './PullByKeyDialog'\n\nconst money = (value: number) => formatCurrency(value || 0, 'BRL')\n\nconst day = (iso: string | null) => (iso ? iso.slice(0, 10).split('-').reverse().join('/') : '—')\n\nconst cnpj = (digits: string | null) => {\n const d = (digits ?? '').replace(/\\D/g, '')\n if (d.length !== 14) return digits ?? '—'\n return `${d.slice(0, 2)}.${d.slice(2, 5)}.${d.slice(5, 8)}/${d.slice(8, 12)}-${d.slice(12)}`\n}\n\n// Same box as SelectTrigger: the date filters sit beside it and must read as one row.\nconst CAMPO = 'h-9 w-full rounded-input border border-input bg-background px-3 text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2'\n\n/** O recorte, como ele vai para a consulta. */\ninterface Recorte {\n filter: InboxStatusFilter\n unitId: string\n from: string\n to: string\n}\n\nconst STATE_OPTIONS: Array<{ value: InboxStatusFilter; label: string }> = [\n { value: 'all', label: 'Todos' },\n { value: 'pending', label: 'Estoque pendente' },\n { value: 'stocked', label: 'Estocado' },\n { value: 'manifest_error', label: 'Manifestação com erro' },\n { value: 'rejected', label: 'Recusada' },\n]\n\nconst isoDay = (d: Date) => d.toISOString().slice(0, 10)\nconst SYNC_KEY = 'fiscalbr.inbox.lastSefazSync'\n\n/** O resultado de arrastar um lote: o que entrou, o que o de-para já resolveu, o que recusou. */\ninterface DropReport {\n ok: Array<{ file: string; number: string; items: number; matched: number; repeated: boolean }>\n failed: Array<{ file: string; message: string }>\n}\n\nexport interface InboundNotesViewProps {\n /** Abre a conciliação da nota. A rota é do host — esta tela não sabe navegar. */\n onOpenNote: (noteId: string) => void\n}\n\nexport function InboundNotesView({ onOpenNote }: InboundNotesViewProps) {\n const [notes, setNotes] = useState<InboxNote[]>([])\n const [loading, setLoading] = useState(true)\n const [search, setSearch] = useState('')\n const [busy, setBusy] = useState(false)\n const [report, setReport] = useState<DropReport | null>(null)\n const [dragging, setDragging] = useState(false)\n const [pullOpen, setPullOpen] = useState(false)\n const fileInput = useRef<HTMLInputElement>(null)\n\n // A unidade é o ALCANCE de quem olha: a lista abre na unidade em que a pessoa\n // está e só oferece as que ela alcança.\n const unidades = useUnitFilter({ scope: 'list' })\n\n // ── Rascunho e aplicado ─────────────────────────────────────────────────\n // O MESMO motor de recorte da conciliação bancária (FilterPanel): os campos\n // escrevem num rascunho e a lista só muda no «Buscar». Mexer em unidade,\n // estado e nas duas pontas do período seria quatro consultas no caminho, três\n // das quais ninguém pediu — e a terceira pode voltar depois da quarta e\n // pintar a tela com o recorte errado.\n const { draft, applied, patch, setDraft, dirty, apply, reset } = useFilterDraft<Recorte>({\n filter: 'all',\n unitId: unidades.value ?? '',\n // Sem período por padrão: o V1 abre em «Todos os registros», e uma janela\n // de 30 dias esconderia justamente a nota velha que nunca foi estocada.\n from: '',\n to: '',\n })\n\n // Trocar de unidade na casca re-ancora a lista, como no V1 quando a unidade\n // corrente mudava — e aplica na hora, porque uma lista presa ao recorte\n // anterior mostraria dados de outra unidade até alguém clicar em buscar.\n const ancora = unidades.value ?? ''\n const ancoraAnterior = useRef(ancora)\n useEffect(() => {\n if (ancoraAnterior.current === ancora) return\n ancoraAnterior.current = ancora\n setDraft((atual) => ({ ...atual, unitId: ancora }))\n apply()\n }, [ancora, setDraft, apply])\n const reload = useCallback(async () => {\n setLoading(true)\n try {\n setNotes(await listInboxNotes({\n filter: applied.filter,\n unitId: applied.unitId || undefined,\n from: applied.from || undefined,\n to: applied.to || undefined,\n // The list pages on screen; the default 200 would silently drop the rest.\n limit: 5000,\n }))\n } finally {\n setLoading(false)\n }\n }, [applied])\n\n useEffect(() => { void reload() }, [reload])\n\n const [intake, setIntake] = useState<InboxIntakeHealth | null>(null)\n const [syncing, setSyncing] = useState(false)\n const [syncNote, setSyncNote] = useState<string | null>(null)\n const refreshIntake = useCallback(() => { getInboxIntakeHealth().then(setIntake).catch(() => setIntake(null)) }, [])\n\n const syncNow = useCallback(async (quiet: boolean) => {\n setSyncing(true)\n if (!quiet) setSyncNote(null)\n try {\n const r = await syncNewNotes()\n try { localStorage.setItem(SYNC_KEY, String(Date.now())) } catch { /* private mode */ }\n if (r.added) void reload()\n const parts = [\n r.added ? `${r.added} ${r.added === 1 ? 'nota nova' : 'notas novas'}` : null,\n r.waiting ? `${r.waiting} ainda sem o XML completo na SEFAZ` : null,\n r.failed ? `${r.failed} com erro` : null,\n ].filter(Boolean)\n if (!quiet || parts.length) setSyncNote(parts.length ? `SEFAZ: ${parts.join(' · ')}.` : 'SEFAZ: nenhuma nota nova.')\n } catch (e) {\n if (!quiet) setSyncNote(e instanceof Error ? e.message : String(e))\n } finally {\n setSyncing(false)\n refreshIntake()\n }\n }, [reload, refreshIntake])\n\n // Opening the list is when someone wants to see what arrived; at most every 30 minutes.\n useEffect(() => {\n refreshIntake()\n let last = 0\n try { last = Number(localStorage.getItem(SYNC_KEY) ?? 0) } catch { /* private mode */ }\n if (Date.now() - last > 30 * 60_000) void syncNow(true)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // One file at a time, sequentially. The staging RPC is idempotent on the access\n // key, so a repeated file is not an error — but firing 20 of them in parallel\n // would race on the same de-para rows for the same supplier.\n const ingest = useCallback(async (files: File[]) => {\n const xmls = files.filter((f) => /\\.xml$/i.test(f.name))\n if (xmls.length === 0) {\n setReport({ ok: [], failed: [{ file: '—', message: 'Nenhum arquivo .xml no que foi solto.' }] })\n return\n }\n setBusy(true)\n const next: DropReport = { ok: [], failed: [] }\n for (const file of xmls) {\n try {\n const res = await stageNoteFromXml(await file.text())\n next.ok.push({\n file: file.name,\n number: res.parsed.nfeNumber,\n items: res.itemCount,\n matched: res.matchedCount,\n repeated: res.alreadyAccepted,\n })\n } catch (error) {\n next.failed.push({ file: file.name, message: error instanceof Error ? error.message : String(error) })\n }\n }\n setBusy(false)\n setReport(next)\n await reload()\n }, [reload])\n\n const [rowError, setRowError] = useState<string | null>(null)\n\n const downloadXml = useCallback(async (note: InboxNote) => {\n setRowError(null)\n try {\n const xml = await getInboxNoteXml(note.id)\n if (!xml) { setRowError(`O XML da nota ${note.number} não está guardado.`); return }\n const url = URL.createObjectURL(new Blob([xml], { type: 'application/xml' }))\n const a = document.createElement('a')\n a.href = url\n a.download = `${note.accessKey || note.number || 'nfe'}.xml`\n a.click()\n URL.revokeObjectURL(url)\n } catch (e) {\n setRowError(e instanceof Error ? e.message : String(e))\n }\n }, [])\n\n const openPdf = useCallback(async (note: InboxNote) => {\n setRowError(null)\n // Opened before the await: a tab opened after it is a popup the browser blocks.\n const tab = window.open('', '_blank')\n try {\n const pdf = await getInboxNotePdf(note.accessKey ?? '')\n if (tab) tab.location.href = URL.createObjectURL(pdf)\n } catch (e) {\n tab?.close()\n setRowError(e instanceof Error ? e.message : String(e))\n }\n }, [])\n\n const remove = useCallback(async (note: InboxNote) => {\n // Recusar, não apagar: a nota é documento fiscal e continua legível.\n await rejectNote(note.id, 'Recusada na lista de entrada')\n await reload()\n }, [reload])\n\n const activeCount = (applied.filter === 'all' ? 0 : 1)\n + (applied.unitId ? 1 : 0)\n + (applied.from || applied.to ? 1 : 0)\n\n const limpar = useCallback(() => {\n reset({ filter: 'all', unitId: ancora, from: '', to: '' })\n }, [reset, ancora])\n\n /** As duas pontas nunca ficam invertidas: mexer numa arrasta a outra. */\n const setFrom = (from: string) => patch({ from, to: draft.to && from > draft.to ? from : draft.to })\n const setTo = (to: string) => patch({ to, from: draft.from && to < draft.from ? to : draft.from })\n\n // Local search: the list already arrives whole, so a round trip per keystroke buys nothing.\n const query = search.trim().toLowerCase()\n const shown = useMemo(() => {\n if (!query) return notes\n // CNPJ, access key and date match on digits, so punctuation never matters.\n const digits = query.replace(/\\D/g, '')\n return notes.filter((note) => {\n if (`${note.number} ${note.series} ${note.supplierName}`.toLowerCase().includes(query)) return true\n if (digits.length < 2) return false\n if ((note.supplierCnpj ?? '').replace(/\\D/g, '').includes(digits)) return true\n if ((note.accessKey ?? '').includes(digits)) return true\n return day(note.issueDate).replace(/\\D/g, '').includes(digits)\n })\n }, [notes, query])\n\n const [page, setPage] = useState(1)\n useEffect(() => { setPage(1) }, [notes, query])\n const pageRows = useMemo(() => shown.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE), [shown, page])\n\n const columns = useMemo<ColumnDef<InboxNote, unknown>[]>(() => [\n {\n id: 'issueDate',\n header: 'Emissão',\n accessorFn: (note) => note.issueDate ?? '',\n cell: ({ row }) => <span className=\"tabular-nums text-muted-foreground\">{day(row.original.issueDate)}</span>,\n },\n {\n id: 'number',\n header: 'Nº',\n accessorFn: (note) => Number(note.number) || note.number,\n cell: ({ row }) => <span className=\"tabular-nums font-medium\">{row.original.number}</span>,\n },\n {\n id: 'supplier',\n header: 'Fornecedor',\n accessorFn: (note) => note.supplierName,\n meta: { truncate: true, mobile: 'title' },\n cell: ({ row }) => (\n <div>\n <p className=\"font-medium leading-tight\">{row.original.supplierName || '—'}</p>\n <p className=\"text-xs text-muted-foreground tabular-nums\">{cnpj(row.original.supplierCnpj)}</p>\n </div>\n ),\n },\n {\n id: 'reconciled',\n header: () => <span className=\"block text-center\">Conciliação</span>,\n accessorFn: (note) => (note.itemCount > 0 ? note.reconciledCount / note.itemCount : -1),\n cell: ({ row }) => (\n <div className=\"text-center\">\n <ReconcileBadge done={row.original.reconciledCount} total={row.original.itemCount} />\n </div>\n ),\n },\n {\n id: 'total',\n header: () => <span className=\"block text-right\">Valor</span>,\n accessorFn: (note) => note.total,\n cell: ({ row }) => {\n const note = row.original\n return (\n <div className=\"text-right tabular-nums\">\n {money(note.total)}\n {/* O título nasce com a soma das PARCELAS. Quando ela difere do\n total da nota, a tela mostra as duas — é a divergência que a\n conciliação passaria o mês procurando. */}\n {note.instalmentCount > 0 && Math.abs(note.instalmentTotal - note.total) > 0.01 && (\n <p className=\"text-[11px] text-warning-soft-foreground\">\n parcelas: {money(note.instalmentTotal)}\n </p>\n )}\n </div>\n )\n },\n },\n {\n id: 'stock',\n header: () => <span className=\"block text-center\">Estoque</span>,\n accessorFn: (note) => (note.stockedAt ? 2 : note.status === 'rejected' ? 0 : 1),\n cell: ({ row }) => (\n <div className=\"text-center\">\n <StockBadge stockedAt={row.original.stockedAt} status={row.original.status} />\n </div>\n ),\n },\n {\n id: 'actions',\n header: () => <span className=\"block text-right\">Ações</span>,\n enableSorting: false,\n cell: ({ row }) => {\n const note = row.original\n const done = !!note.stockedAt || note.status === 'rejected'\n return (\n // The row itself opens the note; the buttons must not fire it a second time.\n <div className=\"flex justify-end gap-1\" onClick={(e) => e.stopPropagation()}>\n <ActionIcon label={done ? 'Ver nota' : 'Conciliar'}>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n aria-label={done ? `Ver a nota ${note.number}` : `Conciliar a nota ${note.number}`}\n className={done ? '' : 'bg-foreground text-background hover:bg-foreground/85 hover:text-background'}\n onClick={() => onOpenNote(note.id)}\n >\n {done ? <Eye className=\"h-4 w-4\" /> : <ListChecks className=\"h-4 w-4\" />}\n </Button>\n </ActionIcon>\n <RowActions\n inlineLimit={0}\n actions={[\n { id: 'xml', label: 'Baixar XML', icon: FileCode2, onSelect: () => downloadXml(note) },\n { id: 'pdf', label: 'Abrir PDF', icon: FileText, onSelect: () => openPdf(note), hidden: !note.accessKey },\n {\n id: 'reject', label: 'Recusar nota', icon: Trash2, intent: 'danger',\n onSelect: () => remove(note), hidden: done || !!note.invoiceId,\n },\n ]}\n />\n </div>\n )\n },\n },\n ], [onOpenNote, remove, downloadXml, openPdf])\n\n // Empty-by-search and empty-by-no-notes have different fixes.\n const emptyMessage = query || activeCount > 0 ? (\n <div>\n <Inbox className=\"mx-auto h-8 w-8 text-muted-foreground\" aria-hidden />\n <p className=\"mt-2 text-sm font-medium\">Nenhuma nota encontrada</p>\n <p className=\"text-xs text-muted-foreground\">Tente outro número, fornecedor ou CNPJ.</p>\n </div>\n ) : (\n <div>\n <Inbox className=\"mx-auto h-8 w-8 text-muted-foreground\" aria-hidden />\n <p className=\"mt-2 text-sm font-medium\">Nenhuma nota de entrada</p>\n <p className=\"text-xs text-muted-foreground\">\n As notas chegam da SEFAZ sozinhas, ou você arrasta o XML aqui.\n </p>\n </div>\n )\n\n return (\n <div className=\"space-y-4\">\n <PageHeaderActions>\n <PageActions\n actions={[\n {\n // Picking an XML off a filesystem is a desk job.\n id: 'import-xml', label: 'Importar XML', icon: busy ? Loader2 : UploadCloud,\n intent: 'primary', creates: true, desktopOnly: true, disabled: busy,\n onSelect: () => fileInput.current?.click(),\n },\n {\n id: 'sync-sefaz', label: syncing ? 'Buscando na SEFAZ…' : 'Buscar notas novas', icon: syncing ? Loader2 : RefreshCw,\n disabled: syncing, testId: 'sync-sefaz', onSelect: () => { void syncNow(false) },\n },\n {\n id: 'pull-by-key', label: 'Puxar por chave', icon: KeyRound, creates: true,\n testId: 'pull-by-key', onSelect: () => setPullOpen(true),\n },\n ]}\n />\n </PageHeaderActions>\n\n {syncNote && <p className=\"text-xs text-muted-foreground\" data-testid=\"sync-note\">{syncNote}</p>}\n\n {intake && (\n <Card className=\"border-warning bg-warning-soft p-4\" data-testid=\"intake-stalled\">\n <p className=\"text-sm font-medium text-warning-soft-foreground\">\n {intake.certificateExpiredAt\n ? `As notas da SEFAZ não estão chegando: o certificado digital venceu em ${day(intake.certificateExpiredAt)}.`\n : `As notas da SEFAZ não estão chegando${intake.since ? ` desde ${day(intake.since)}` : ''}.`}\n </p>\n <p className=\"mt-1 text-xs text-warning-soft-foreground\">\n {intake.certificateExpiredAt\n ? 'Renove o certificado A1 do CNPJ e envie o arquivo novo. As notas que ficaram para trás chegam sozinhas depois disso.'\n : intake.error ?? 'A busca automática parou. Enquanto isso, dá para importar o XML ou puxar a nota pela chave.'}\n {intake.stalled > 1 ? ` (${intake.stalled} CNPJs afetados)` : ''}\n </p>\n {intake.unitId && (intake.certificateExpiredAt || intake.error) && (\n <Button size=\"sm\" variant=\"outline\" className=\"mt-3\" data-testid=\"intake-update-certificate\"\n onClick={() => adminNavigateTo(`/settings/locations/${intake.unitId}/fields:tax`)}>\n Atualizar certificado\n </Button>\n )}\n </Card>\n )}\n\n {/* A área de arrastar é a porta de entrada, e o texto é o do V1: a entrada\n nasce do XML, não da digitação. */}\n <Card\n className={`hidden border-dashed p-6 text-center transition-colors md:block ${dragging ? 'border-primary bg-primary/5' : ''}`}\n onDragOver={(e: React.DragEvent) => { e.preventDefault(); setDragging(true) }}\n onDragLeave={() => setDragging(false)}\n onDrop={(e: React.DragEvent) => {\n e.preventDefault()\n setDragging(false)\n void ingest(Array.from(e.dataTransfer.files))\n }}\n >\n <UploadCloud className=\"mx-auto h-8 w-8 text-muted-foreground\" aria-hidden />\n <p className=\"mt-2 text-sm font-medium\">Arraste arquivos XML aqui ou clique para selecionar</p>\n <p className=\"text-xs text-muted-foreground\">\n Suporta múltiplos arquivos XML de NF-e. O XML do fornecedor dá entrada no estoque e cria a conta a pagar.\n </p>\n <input\n ref={fileInput}\n type=\"file\"\n accept=\".xml,text/xml,application/xml\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n void ingest(Array.from(e.target.files ?? []))\n e.target.value = ''\n }}\n />\n </Card>\n\n <PullByKeyDialog\n open={pullOpen}\n onOpenChange={setPullOpen}\n unitId={applied.unitId || null}\n onPulled={(r) => {\n setReport({\n ok: [{ file: 'chave', number: r.parsed.nfeNumber, items: r.itemCount, matched: r.matchedCount, repeated: r.alreadyAccepted }],\n failed: [],\n })\n void reload()\n }}\n />\n\n {report && (\n <Card className=\"p-4 space-y-2\">\n {report.ok.map((r) => (\n <p key={r.file} className=\"text-sm\">\n <span className=\"font-medium\">NF-e {r.number}</span>{' '}\n <span className=\"text-muted-foreground\">\n {r.repeated\n ? '— já tinha sido aceita, nada mudou'\n // O número que diz se o de-para está trabalhando. Sem ele, o\n // operador não sabe se importar XML economizou algo.\n : `— ${r.items} ${r.items === 1 ? 'item' : 'itens'}, ${r.matched} já ${r.matched === 1 ? 'vinculado' : 'vinculados'}`}\n </span>\n </p>\n ))}\n {report.failed.map((r) => (\n <p key={r.file} className=\"text-sm text-destructive\">\n <span className=\"font-medium\">{r.file}</span> — {r.message}\n </p>\n ))}\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setReport(null)}>Fechar</Button>\n </Card>\n )}\n\n {/* ── O painel de filtros ──────────────────────────────────────────── */}\n {/* O MESMO FilterPanel da conciliação bancária: unidade, estado e as duas\n pontas do período definem O QUE se busca, e «Buscar» é que aplica.\n A BUSCA não entra aqui — ela é a barra da lista: quem digita está\n procurando UMA nota entre as que já estão na tela, não redefinindo a\n consulta. */}\n <FilterPanel\n title=\"Filtros\"\n dirty={dirty}\n onApply={apply}\n applyLabel=\"Buscar\"\n pendingTitle=\"Filtros não aplicados\"\n pendingHint=\"A lista ainda mostra o recorte anterior.\"\n onClear={activeCount > 0 ? limpar : undefined}\n clearLabel=\"Limpar\"\n busy={loading}\n >\n {unidades.visible && (\n <FilterPanelField label={unidades.label}>\n <Select\n value={draft.unitId || '__all__'}\n onValueChange={(v) => patch({ unitId: v === '__all__' ? '' : v })}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__all__\">{unidades.allLabel}</SelectItem>\n {unidades.options.map((u) => <SelectItem key={u.id} value={u.id}>{u.name}</SelectItem>)}\n </SelectContent>\n </Select>\n </FilterPanelField>\n )}\n\n <FilterPanelField label=\"Estado\">\n <Select value={draft.filter} onValueChange={(v) => patch({ filter: v as InboxStatusFilter })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {STATE_OPTIONS.map((o) => <SelectItem key={o.value} value={o.value}>{o.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </FilterPanelField>\n\n <FilterPanelField label=\"Emissão de\">\n <input type=\"date\" value={draft.from} max={isoDay(new Date())} onChange={(e) => setFrom(e.target.value)} className={CAMPO} />\n </FilterPanelField>\n <FilterPanelField label=\"Emissão até\">\n <input type=\"date\" value={draft.to} max={isoDay(new Date())} onChange={(e) => setTo(e.target.value)} className={CAMPO} />\n </FilterPanelField>\n </FilterPanel>\n\n {rowError && (\n <p className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\" role=\"alert\">{rowError}</p>\n )}\n\n {/* Search and table are one surface — they act on the same rows. `clip`, as\n in CrudListView: `hidden` makes a scroll box that swallows the sticky header. */}\n <Card style={{ overflow: 'clip' }}>\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2\">\n <div className=\"min-w-[10rem] flex-1\">\n <SearchField\n value={search}\n onChange={setSearch}\n placeholder=\"Buscar por número, fornecedor, CNPJ…\"\n data-testid=\"inbound-notes-search\"\n />\n </div>\n </div>\n <TooltipProvider delayDuration={200}>\n <DataTable\n variant=\"bare\"\n columns={columns}\n data={loading ? [] : pageRows}\n loading={loading}\n getRowId={(note) => note.id}\n onRowClick={(note) => onOpenNote(note.id)}\n emptyMessage={emptyMessage}\n mobileLayout=\"cards\"\n />\n </TooltipProvider>\n {!loading && shown.length > 0 && (\n <ChevronPager page={page} pageSize={PAGE_SIZE} total={shown.length} onPageChange={setPage} noun=\"notas\" />\n )}\n </Card>\n </div>\n )\n}\n\nconst PAGE_SIZE = 50\n\nfunction ActionIcon({ label, children }: { label: string; children: React.ReactElement }) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>{children}</TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n )\n}\n\nfunction ReconcileBadge({ done, total }: { done: number; total: number }) {\n const full = total > 0 && done === total\n return (\n <span\n className={`inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium tabular-nums ${\n full ? 'bg-success-soft text-success-soft-foreground' : 'bg-muted text-muted-foreground'\n }`}\n >\n {done}/{total}\n </span>\n )\n}\n\nfunction StockBadge({ stockedAt, status }: { stockedAt: string | null; status: string }) {\n if (status === 'rejected') {\n return <span className=\"inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground line-through\">Recusada</span>\n }\n return stockedAt ? (\n <span className=\"inline-flex items-center rounded-full bg-success-soft px-2 py-0.5 text-[11px] font-medium text-success-soft-foreground\">\n <FileDown className=\"mr-1 h-3 w-3\" aria-hidden />\n Estocado\n </span>\n ) : (\n <span className=\"inline-flex items-center rounded-full bg-warning-soft px-2 py-0.5 text-[11px] font-medium text-warning-soft-foreground\">\n Pendente\n </span>\n )\n}\n","import { formatCurrency } from '@fayz-ai/core'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\nimport { FileText, Image as ImageIcon, Loader2, Paperclip, ScanLine, Trash2, UploadCloud } from 'lucide-react'\nimport { Button, Card, Hint } from '@fayz-ai/ui'\nimport {\n addNoteAttachment, extractPaymentCode, listNoteAttachments, removeNoteAttachment,\n type InstalmentInput, type NoteAttachment, type PaymentCode,\n} from '../data/inbox'\n\nconst MAX_BYTES = 15 * 1024 * 1024\nconst money = (v: number) => formatCurrency(v || 0)\nconst day = (iso: string | null) => (iso ? iso.slice(0, 10).split('-').reverse().join('/') : '—')\nconst size = (b?: number) => (!b ? '' : b < 1024 * 1024 ? `${Math.max(1, Math.round(b / 1024))} KB` : `${(b / 1024 / 1024).toFixed(1)} MB`)\n\n/**\n * Put a read payment code on the instalment it belongs to: the empty one with\n * the same amount, else the first empty one, else a new instalment. Never\n * overwrites a code already there.\n */\nexport function applyPaymentCode(list: InstalmentInput[], code: PaymentCode): { next: InstalmentInput[]; index: number } {\n const field = code.kind === 'pix' ? 'pixKey' : 'barcode'\n const free = list.map((p, i) => ({ p, i })).filter(({ p }) => !p[field])\n const sameAmount = code.amount != null ? free.find(({ p }) => Math.abs((Number(p.amount) || 0) - code.amount!) < 0.01) : undefined\n const target = sameAmount ?? free[0]\n const patch = (p: InstalmentInput): InstalmentInput => ({\n ...p,\n [field]: code.code,\n paymentType: code.kind === 'pix' ? 'pix' : 'boleto',\n dueDate: p.dueDate || code.dueDate,\n amount: Number(p.amount) > 0 ? p.amount : (code.amount ?? 0),\n })\n if (target) return { next: list.map((p, i) => (i === target.i ? patch(p) : p)), index: target.i }\n const fresh = patch({ index: list.length, amount: 0 })\n return { next: [...list, fresh], index: list.length }\n}\n\nexport function NoteAttachmentsCard({ noteId, invoiceId, readOnly, instalments, onInstalments }: {\n noteId: string\n invoiceId?: string | null\n readOnly?: boolean\n instalments: InstalmentInput[]\n onInstalments: (next: InstalmentInput[]) => void\n}) {\n const input = useRef<HTMLInputElement>(null)\n const [items, setItems] = useState<NoteAttachment[] | null>(null)\n const [busy, setBusy] = useState<string | null>(null)\n const [over, setOver] = useState(false)\n const [confirming, setConfirming] = useState<string | null>(null)\n const [messages, setMessages] = useState<Array<{ tone: 'ok' | 'warn' | 'error'; text: string }>>([])\n // The latest instalments, so several files read in sequence each see the previous fill.\n const current = useRef(instalments)\n current.current = instalments\n\n const load = useCallback(async () => {\n try { setItems(await listNoteAttachments(noteId, invoiceId)) } catch { setItems([]) }\n }, [noteId, invoiceId])\n useEffect(() => { void load() }, [load])\n\n const upload = async (files: File[]) => {\n const out: typeof messages = []\n for (const file of files) {\n if (!(file.type.startsWith('image/') || file.type === 'application/pdf') || file.size > MAX_BYTES) {\n out.push({ tone: 'error', text: `${file.name}: envie imagem ou PDF de até 15 MB.` })\n continue\n }\n setBusy(`Anexando ${file.name}…`)\n try {\n await addNoteAttachment(noteId, invoiceId, file)\n } catch (e) {\n out.push({ tone: 'error', text: `${file.name}: ${e instanceof Error ? e.message : String(e)}` })\n continue\n }\n if (readOnly) continue\n setBusy(`Lendo ${file.name}…`)\n try {\n const code = await extractPaymentCode(file)\n if (!code) {\n out.push({ tone: 'warn', text: `${file.name}: anexado. Não achei código de boleto nem Pix nele.` })\n } else {\n const { next, index } = applyPaymentCode(current.current, code)\n current.current = next\n onInstalments(next)\n const p = next[index]\n out.push({\n tone: 'ok',\n text: `${code.kind === 'pix' ? 'Pix' : 'Boleto'} lido → parcela ${index + 1}: ${money(Number(p.amount) || 0)}, vence ${day(p.dueDate ?? null)}. Confira e salve.`,\n })\n }\n } catch (e) {\n out.push({ tone: 'warn', text: `${file.name}: anexado, mas não consegui ler o código (${e instanceof Error ? e.message : String(e)}).` })\n }\n }\n setBusy(null)\n setMessages(out)\n await load()\n }\n\n const remove = async (a: NoteAttachment) => {\n setBusy(`Removendo ${a.fileName}…`)\n try {\n await removeNoteAttachment(a.id)\n setMessages([{ tone: 'ok', text: `${a.fileName} removido.` }])\n } catch (e) {\n setMessages([{ tone: 'error', text: `${a.fileName}: ${e instanceof Error ? e.message : String(e)}` }])\n } finally {\n setBusy(null)\n await load()\n }\n }\n\n return (\n <Card className=\"p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <h3 className=\"text-sm font-semibold\">Anexos da conta</h3>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n Boleto, comprovante, foto da nota. Boleto e Pix anexados são lidos e preenchem a parcela.\n </p>\n </div>\n {items && items.length > 0 && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{items.length} {items.length === 1 ? 'anexo' : 'anexos'}</span>\n )}\n </div>\n\n {items === null ? (\n <div className=\"mt-3 h-10 animate-pulse rounded-md bg-muted\" />\n ) : items.length > 0 && (\n <ul className=\"mt-3 divide-y rounded-md border\">\n {items.map((a) => (\n <li key={a.id} className=\"flex items-center gap-2 px-3 py-2 text-sm\">\n {a.mimeType?.startsWith('image/')\n ? <ImageIcon className=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden />\n : <FileText className=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden />}\n {a.url\n ? <a href={a.url} target=\"_blank\" rel=\"noreferrer\" className=\"min-w-0 flex-1 truncate hover:underline\">{a.fileName}</a>\n : <span className=\"min-w-0 flex-1 truncate text-muted-foreground\">{a.fileName}</span>}\n {confirming === a.id ? (\n // Inline, not a dialog: this card already lives inside a modal.\n <span className=\"flex shrink-0 items-center gap-1\">\n <span className=\"text-xs text-muted-foreground\">Remover?</span>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => { setConfirming(null); void remove(a) }}>Remover</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setConfirming(null)}>Cancelar</Button>\n </span>\n ) : (\n <>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{size(a.fileSize)}</span>\n <Hint label=\"Remover anexo\">\n <Button variant=\"ghost\" size=\"icon\" aria-label={`Remover ${a.fileName}`} disabled={!!busy} onClick={() => setConfirming(a.id)}>\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </Hint>\n </>\n )}\n </li>\n ))}\n </ul>\n )}\n\n <div\n className={`mt-3 flex flex-col items-center gap-1 rounded-md border border-dashed px-4 py-5 text-center transition-colors ${over ? 'border-primary bg-primary/5' : 'border-input'}`}\n onDragOver={(e) => { e.preventDefault(); setOver(true) }}\n onDragLeave={() => setOver(false)}\n onDrop={(e) => { e.preventDefault(); setOver(false); void upload(Array.from(e.dataTransfer.files)) }}\n >\n {busy ? (\n <p className=\"flex items-center gap-2 text-sm text-muted-foreground\"><Loader2 className=\"h-4 w-4 animate-spin\" />{busy}</p>\n ) : (\n <>\n <UploadCloud className=\"h-6 w-6 text-muted-foreground\" aria-hidden />\n <p className=\"text-sm\">Arraste o boleto ou o comprovante aqui</p>\n <div className=\"mt-1 flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => input.current?.click()} data-testid=\"note-attach\">\n <Paperclip className=\"mr-1.5 h-4 w-4\" />\n Anexar arquivo\n </Button>\n </div>\n {!readOnly && (\n <p className=\"mt-1 flex items-center gap-1 text-[11px] text-muted-foreground\">\n <ScanLine className=\"h-3 w-3\" aria-hidden /> o código de barras e o Pix são lidos sozinhos\n </p>\n )}\n </>\n )}\n <input\n ref={input}\n type=\"file\"\n multiple\n accept=\"image/*,application/pdf\"\n className=\"hidden\"\n onChange={(e) => { void upload(Array.from(e.target.files ?? [])); e.target.value = '' }}\n />\n </div>\n\n {messages.length > 0 && (\n <ul className=\"mt-3 space-y-1\">\n {messages.map((m, i) => (\n <li\n key={i}\n className={`text-xs ${m.tone === 'ok' ? 'text-success-soft-foreground' : m.tone === 'warn' ? 'text-warning-soft-foreground' : 'text-destructive'}`}\n >\n {m.text}\n </li>\n ))}\n </ul>\n )}\n </Card>\n )\n}\n","/** The preview contract deliberately excludes production emission. */\nexport type PlugNotasEnvironment = 'sandbox' | 'homologation'\nexport type PlugNotasDocumentStatus = 'draft' | 'processing' | 'issued' | 'cancelled' | 'error'\n\nexport interface PlugNotasSetupState {\n emitterCnpj: string\n environment: PlugNotasEnvironment\n certificateReady: boolean\n cscReady: boolean\n providerEmitterId?: string\n certificateExpiresAt?: string\n certificateFingerprint?: string\n}\n\nexport interface PlugNotasDocumentResult {\n status: PlugNotasDocumentStatus\n providerDocumentId?: string\n integrationId?: string\n number?: string\n series?: string\n accessKey?: string\n message?: string\n}\n\nexport interface PlugNotasFiscalGateway {\n issue(input: { notaId: string; idempotencyKey: string }): Promise<PlugNotasDocumentResult>\n refresh(input: { notaId: string }): Promise<PlugNotasDocumentResult>\n cancel(input: { notaId: string; reason: string }): Promise<PlugNotasDocumentResult>\n artifact(input: {\n notaId: string\n kind: 'xml' | 'pdf' | 'cancellation_xml'\n }): Promise<{ url: string }>\n}\n\nexport interface PlugNotasConnectorClient {\n testEmitter?(input: {\n emitterCnpj: string\n environment: PlugNotasEnvironment\n }): Promise<{ ok: boolean; message?: string }>\n disconnectEmitter?(): Promise<void>\n}\n\nexport interface PlugNotasFinancialProviderOptions {\n base: import('@fayz-ai/financial/data/provider').FinancialDataProvider\n gateway: PlugNotasFiscalGateway\n}\n\n// ---------------------------------------------------------------------------\n// Entrada de Notas — a nota que o fornecedor emitiu contra o CNPJ da casa.\n// ---------------------------------------------------------------------------\n// Dois estados, e eles NÃO respondem à mesma pergunta. `reconciledCount/itemCount`\n// diz quantos itens já sabem a que produto correspondem; `stockedAt` diz se a\n// entrada aconteceu. No V1 havia 55 notas conciliadas e nunca estocadas — uma\n// coluna de \"status\" só teria escondido as 55.\n\n/** Os cinco tipos de registro do V1, medidos em 3.402 linhas de produção. */\nexport type InboxEntryType = 'insumo' | 'revenda' | 'patrimonio' | 'uso_consumo' | 'despesa' | 'servico'\n\n/** Despesa e serviço nunca viram estoque: viram só título a pagar. */\nexport const STOCK_BEARING_ENTRY_TYPES: readonly InboxEntryType[] = ['insumo', 'revenda', 'patrimonio', 'uso_consumo']\n\nexport const isStockBearing = (type: string | null | undefined): boolean =>\n STOCK_BEARING_ENTRY_TYPES.includes(type as InboxEntryType)\n\nexport type InboxCostMode = 'novo' | 'media'\n\nexport type InboxStatusFilter = 'all' | 'pending' | 'stocked' | 'rejected' | 'manifest_error'\n\nexport interface InboxNote {\n id: string\n accessKey: string\n number: string\n series: string\n issueDate: string | null\n receivedAt: string | null\n status: string\n manifestationStatus: string | null\n manifestedAt: string | null\n manifestationAttempts: number\n natureOperation: string | null\n supplierName: string\n supplierCnpj: string | null\n supplierPartyId: string | null\n /** O total declarado na NOTA. */\n total: number\n itemCount: number\n reconciledCount: number\n instalmentCount: number\n /** A soma das PARCELAS — é com este total que o título nasce (financial/084). */\n instalmentTotal: number\n invoiceId: string | null\n operationId: string | null\n stockedAt: string | null\n documentId: string | null\n /** O XML está guardado nesta nota. Falso nas importadas antes da migration 016. */\n hasXml: boolean\n unitId: string | null\n}\n\nexport interface InboxItem {\n id: string\n itemNumber: number\n supplierProductCode: string\n eanBarcode: string | null\n description: string\n ncm: string | null\n cest: string | null\n cfop: string | null\n unit: string | null\n quantity: number\n unitPrice: number\n total: number\n /**\n * `uTrib`/`qTrib` do XML — a unidade e a quantidade TRIBUTÁVEIS.\n *\n * É a evidência mais forte que existe para o fator de conversão, e ela já\n * estava no banco: 558 dos 3.691 itens têm unidade tributável diferente da\n * comercial. «4 CX» com `qTrib` 88,224 KG diz que a caixa tem 22,056 kg — e o\n * caso Artorius (carne a R$ 397/kg) foi exatamente esta conta não ter sido\n * feita. Ver `taxableFactor`.\n */\n unitTaxable: string | null\n quantityTaxable: number | null\n discount: number | null\n icmsCst: string | null\n icmsCsosn: string | null\n icmsValue: number | null\n productId: string | null\n entryType: string | null\n chartAccountId: string | null\n stockUnitId: string | null\n conversionFactor: number\n /** Quantidade × fator, menos a falta. É o número que a tela mostra ANTES de aceitar. */\n stockQuantity: number\n costMode: string\n unitCostNew: number | null\n reconciled: boolean\n /**\n * Quem escreveu a decisão desta linha. `null` é «uma pessoa escolheu», e é o\n * caso que importa: igualdade (`ean`, `supplier_map`) e semelhança (`ai`) não\n * se conferem do mesmo jeito que uma escolha humana. Ver a migration 013.\n */\n suggestedBy: 'ai' | 'ean' | 'supplier_map' | null\n /** 0..1, só quando `suggestedBy === 'ai'`. Abaixo de 0,6 a tela pede conferência. */\n suggestionConfidence: number | null\n stockMovementId: string | null\n shortageQuantity: number | null\n shortageReason: string | null\n shortageNote: string | null\n}\n\nexport interface InboxInstalment {\n id: string\n index: number\n number: string | null\n dueDate: string | null\n amount: number\n paymentType: string | null\n barcode: string | null\n pixKey: string | null\n paymentMethodId: string | null\n}\n\nexport interface InboxNoteDetail extends InboxNote {\n defaultChartAccountId: string | null\n defaultLocationId: string | null\n items: InboxItem[]\n instalments: InboxInstalment[]\n /** `pag > detPag` do XML: o que o fornecedor DECLAROU, não o que se decidiu. */\n declaredPayments: Array<{ index: number; code: string | null; label: string | null; value: number }>\n}\n\nexport interface StageResult {\n documentId: string\n accessKey: string\n alreadyAccepted: boolean\n supplierPartyId: string | null\n itemCount: number\n /** Quantos itens o de-para do fornecedor já vinculou sozinho. */\n matchedCount: number\n}\n\nexport interface AcceptResult {\n documentId: string\n /** `true` é o segundo clique, não um erro: a RPC é idempotente na chave de acesso. */\n alreadyAccepted: boolean\n invoiceId: string | null\n invoiceTotal: number\n instalments: number\n operationId: string | null\n stockLines: number\n}\n\nexport interface ProductOption {\n id: string\n name: string\n sku: string | null\n unit: string | null\n cost: number | null\n kind: string | null\n}\n\n/**\n * Um candidato a produto para uma linha da nota, com o motivo de ter aparecido.\n *\n * Devolvido pela RPC `fiscalbr_match_product_candidates` (migration 012) e lido\n * DENTRO da edge function de sugestão — o cliente não chama essa RPC, porque quem\n * decide o que fazer com `reason` é quem monta a pergunta ao modelo.\n *\n * O motivo é a parte que importa: `ean` e `supplier_map` são igualdade — liga e\n * pronto. `text` é semelhança, e semelhança se confere.\n */\nexport interface ProductMatch {\n /** O id do item da nota que originou a busca. */\n ref: string\n productId: string\n name: string\n sku: string | null\n unit: string | null\n cost: number | null\n score: number\n reason: 'supplier_map' | 'ean' | 'text'\n}\n\nexport interface MeasurementUnitOption {\n id: string\n name: string\n abbreviation: string\n isBase: boolean\n}\n\nexport interface ChartAccountOption {\n id: string\n code: string\n name: string\n kind: string | null\n}\n\nexport interface StockLocationOption {\n id: string\n name: string\n unitId: string | null\n}\n","// ---------------------------------------------------------------------------\n// Conciliação — onde a nota do fornecedor vira estoque e dinheiro.\n// ---------------------------------------------------------------------------\n// Os quatro blocos do V1, na mesma ordem: situação fiscal · itens · pagamento ·\n// anexos. O que mudou de forma, e por quê:\n//\n// O V1 põe isto num DIÁLOGO, e é o que esta tela faz de novo (`chrome='modal'`):\n// quem fecha a nota tem de CAIR DE VOLTA onde estava na lista — mesmo recorte,\n// mesma busca, mesma rolagem — e uma subpágina desmontava a lista inteira para\n// remontá-la depois com o filtro no estado inicial.\n//\n// O que fez o diálogo do V1 ser ruim era rolagem dentro de rolagem com o\n// «Aceitar» escondido atrás do rodapé. Aqui o modal rola num lugar só (o corpo)\n// e o rodapé é `sticky` DENTRO dele, então o gesto mais importante da tela nunca\n// sai de vista. `chrome='page'` continua existindo para quem abre a nota por\n// deep link em tela cheia.\n//\n// A regra que a tela existe para cumprir: a **Qtd estoque (calc.)** muda na tela\n// ANTES de aceitar. O FLOW.md do V1 diz que fator de conversão errado é\n// silencioso e que esse número é a única defesa.\n// ---------------------------------------------------------------------------\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { AlertTriangle, Check, ChevronDown, ChevronRight, Download, FileCode2, FileDown, FileText, Gift, Loader2, Plus, RefreshCw, Trash2, UserPlus, X } from 'lucide-react'\nimport { formatCurrency } from '@fayz-ai/core'\nimport { PersonLink } from '@fayz-ai/admin'\nimport { NoteAttachmentsCard } from './NoteAttachmentsCard'\nimport { PullByKeyDialog } from './PullByKeyDialog'\nimport {\n EmBreve, AiActionButton, Button, Card, InlineLink, Input, SearchSelect, Skeleton, SubpageHeader, DatePicker, Hint,\n ModalBody, ModalFooter, ModalHeader, ModalTitle, Dropdown, DropdownContent, DropdownItem, DropdownTrigger,\n} from '@fayz-ai/ui'\nimport {\n getInboxNote, saveNoteDecision, acceptNote, rejectNote,\n searchProducts, listProductsByIds, listMeasurementUnits, listChartAccounts, listStockLocations,\n suggestNoteItems, getInboxNoteXml, stageNoteFromXml, fillInboxLines, healInboxNote, listProductStockUnits, getNotePayable, getInboxNotePdf, linkInboxSupplier, moveNoteAttachmentsToInvoice,\n type ItemDecisionInput, type InstalmentInput, type NotePayable,\n} from '../data/inbox'\nimport type { SearchSelectOption } from '@fayz-ai/ui'\nimport type {\n InboxNoteDetail, InboxItem, InboxEntryType, ProductMatch,\n MeasurementUnitOption, ChartAccountOption, StockLocationOption, AcceptResult,\n} from '../types'\nimport { isStockBearing } from '../types'\nimport { packagingCount } from '../lib/note-suggestion'\n\nconst money = (v: number) => formatCurrency(v || 0, 'BRL')\nconst qty = (v: number) => new Intl.NumberFormat('pt-BR', { maximumFractionDigits: 4 }).format(v || 0)\nconst day = (iso: string | null | undefined) => (iso ? iso.slice(0, 10).split('-').reverse().join('/') : '—')\n\n// O vocabulário é o do V1, e a ordem é a de uso: insumo é 2.303 das 3.402 linhas.\nconst ENTRY_TYPES: Array<{ value: InboxEntryType; label: string; hint?: string }> = [\n { value: 'insumo', label: 'Insumo' },\n { value: 'revenda', label: 'Produto Revenda' },\n { value: 'patrimonio', label: 'Patrimônio' },\n { value: 'uso_consumo', label: 'Uso e Consumo', hint: 'com estoque' },\n { value: 'despesa', label: 'Despesa', hint: 'não vira estoque' },\n { value: 'servico', label: 'Serviço', hint: 'não vira estoque' },\n]\n\n/** O estado editável de uma linha. Espelha `ItemDecisionInput`, mais o que a tela calcula. */\ninterface Draft {\n productId: string | null\n productLabel: string\n entryType: InboxEntryType | null\n chartAccountId: string | null\n stockUnitId: string | null\n conversionFactor: string\n costMode: 'novo' | 'media'\n shortageQuantity: string\n /** Quem escreveu esta linha. `null` = uma pessoa. Ver a migration 013. */\n suggestedBy: 'ai' | 'ean' | 'supplier_map' | null\n suggestionConfidence: number | null\n}\n\n/**\n * `SearchSelect` não tem prop `options`: ele é sempre dirigido por busca — o que é\n * a escolha certa para produto (o catálogo tem 171) e continua servindo para as\n * listas curtas (plano de contas, unidade, local), filtrando em memória.\n */\nconst localSearch = (options: SearchSelectOption[]) => (query: string): SearchSelectOption[] => {\n const q = query.trim().toLowerCase()\n return (q ? options.filter((o) => o.label.toLowerCase().includes(q)) : options).slice(0, 40)\n}\n\nconst labelOf = (options: SearchSelectOption[], id: string | null | undefined) =>\n options.find((o) => o.id === id)?.label\n\n// The note's commercial unit, as the unit code a tenant registers ('KG' → 'kg').\n// Packaging (CX, FD…) is not a stock unit; the factor check handles those.\nconst NOTE_UNIT_CODES: Record<string, string> = {\n KG: 'kg', KGS: 'kg', KILO: 'kg', QUILO: 'kg', G: 'g', GR: 'g', GRS: 'g',\n L: 'l', LT: 'l', LTS: 'l', LITRO: 'l', ML: 'ml',\n UN: 'un', UND: 'un', UNID: 'un', UNI: 'un', UNIDADE: 'un',\n}\n\n/** The stock unit a line should get when nobody chose one: the product's, else the note's. */\nfunction suggestedStockUnit(\n item: InboxItem, units: MeasurementUnitOption[], productUnits: Map<string, string>, productId: string | null,\n): string | null {\n const fromProduct = productId ? productUnits.get(productId) : undefined\n if (fromProduct && units.some((u) => u.id === fromProduct)) return fromProduct\n if (packagingCount(item.unit) !== null) return null\n const code = NOTE_UNIT_CODES[String(item.unit ?? '').trim().toUpperCase().replace(/\\d+$/, '')]\n return code ? units.find((u) => u.abbreviation.toLowerCase() === code)?.id ?? null : null\n}\n\nconst draftOf = (item: InboxItem): Draft => ({\n productId: item.productId,\n productLabel: '',\n entryType: (item.entryType as InboxEntryType) ?? null,\n chartAccountId: item.chartAccountId,\n stockUnitId: item.stockUnitId,\n conversionFactor: String(item.conversionFactor ?? 1),\n costMode: (item.costMode === 'media' ? 'media' : 'novo'),\n shortageQuantity: item.shortageQuantity == null ? '' : String(item.shortageQuantity),\n // Vem do SERVIDOR: é o que faz o selo sobreviver a recarregar a página.\n suggestedBy: item.suggestedBy,\n suggestionConfidence: item.suggestionConfidence,\n})\n\nexport interface NoteReconcileViewProps {\n noteId: string\n onBack: () => void\n /** Onde o título a pagar abre depois de aceitar. O host sabe a rota; esta tela não. */\n onOpenInvoice?: (invoiceId: string) => void\n /**\n * `modal` quando o anfitrião já desenhou a moldura (título e fechar): o\n * cabeçalho de subpágina sai, porque dois títulos na mesma caixa é o defeito\n * que o `page-header-no-duplicate-title` descreve.\n */\n chrome?: 'page' | 'modal'\n}\n\nexport function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = 'page' }: NoteReconcileViewProps) {\n const emModal = chrome === 'modal'\n /** O rodapé encosta nas bordas da caixa que o contém, e ela tem padding diferente. */\n const sangria = emModal ? '-mx-6 px-6' : '-mx-4 px-4'\n const cabecalho = (titulo: string) =>\n emModal ? null : <SubpageHeader title={titulo} onBack={onBack} parentLabel=\"Manifesto de Notas\" />\n const [note, setNote] = useState<InboxNoteDetail | null>(null)\n const [loading, setLoading] = useState(true)\n const [drafts, setDrafts] = useState<Record<string, Draft>>({})\n const [instalments, setInstalments] = useState<InstalmentInput[]>([])\n const [defaultAccount, setDefaultAccount] = useState<string | null>(null)\n const [location, setLocation] = useState<string | null>(null)\n const [units, setUnits] = useState<MeasurementUnitOption[]>([])\n const [productUnits, setProductUnits] = useState<Map<string, string>>(() => new Map())\n const [accounts, setAccounts] = useState<ChartAccountOption[]>([])\n const [locations, setLocations] = useState<StockLocationOption[]>([])\n const [saving, setSaving] = useState(false)\n const [accepting, setAccepting] = useState(false)\n // One item open at a time: 11 expanded rows bury the one still missing a decision.\n const [openIds, setOpenIds] = useState<string[]>([])\n const [checked, setChecked] = useState<Record<string, boolean>>({})\n // A registry that fails to load leaves an empty picker, which reads as \"no data\".\n const [registryWarning, setRegistryWarning] = useState<string | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [accepted, setAccepted] = useState<AcceptResult | null>(null)\n const [baixandoXml, setBaixandoXml] = useState(false)\n const [suggesting, setSuggesting] = useState(false)\n const [suggestionNote, setSuggestionNote] = useState<string | null>(null)\n const [pullOpen, setPullOpen] = useState(false)\n // undefined: not looked up (or no link); null: the note points at a payable that does not exist.\n const [payable, setPayable] = useState<NotePayable | null | undefined>(undefined)\n const [payableLost, setPayableLost] = useState(false)\n\n const load = useCallback(async () => {\n setLoading(true)\n try {\n // A NOTA primeiro, e sozinha. Juntar tudo num `Promise.all` fazia a tela\n // MENTIR: bastava um dos três cadastros falhar para a promessa rejeitar, a\n // nota nunca ser atribuída, e a tela dizer «Nota não encontrada» sobre uma\n // nota que está lá. Foi o que aconteceu no primeiro E2E — a nota existia,\n // a consulta dela respondia 200, e a tela dizia que não existia.\n let detail = await getInboxNote(noteId)\n // Notes that crossed from the V1, or whose supplier was registered later,\n // arrive unbound; matching by CNPJ here costs one call and fixes the screen.\n if (detail && !detail.supplierPartyId && detail.supplierCnpj) {\n const linked = await linkInboxSupplier(noteId).catch(() => null)\n if (linked?.supplierPartyId) detail = { ...detail, supplierPartyId: linked.supplierPartyId }\n }\n // \"Accepted\" is read from the links; a payable deleted elsewhere must not lock the note.\n if (detail && (detail.invoiceId || detail.stockedAt)) {\n const healed = await healInboxNote(noteId).catch(() => null)\n if (healed?.released) setPayableLost(true)\n if (healed?.changed) detail = (await getInboxNote(noteId)) ?? detail\n }\n setPayable(detail?.invoiceId ? await getNotePayable(detail.invoiceId).catch(() => undefined) : undefined)\n // A note copied from the V1 can carry its XML but no lines: read them from\n // the stored file, by the same staging path as a dropped XML.\n // An accepted one only gets its lines; its payable and stock stay as they are.\n if (detail && detail.items.length === 0 && detail.hasXml && detail.status !== 'rejected') {\n const xml = await getInboxNoteXml(noteId).catch(() => null)\n if (xml) {\n const accepted = Boolean(detail.stockedAt || detail.invoiceId)\n const filled = accepted\n ? await fillInboxLines(noteId, xml).catch(() => 0)\n : (await stageNoteFromXml(xml, { unitId: detail.unitId }).catch(() => null))?.itemCount ?? 0\n if (filled) detail = (await getInboxNote(noteId)) ?? detail\n }\n }\n setNote(detail)\n\n // Os cadastros são para PREENCHER os seletores. Um que não carrega deixa um\n // seletor vazio — que é ruim, e é visível — em vez de esconder a nota.\n const failed: string[] = []\n const [u, a, l] = await Promise.all([\n listMeasurementUnits().catch(() => { failed.push('unidades'); return [] as MeasurementUnitOption[] }),\n listChartAccounts().catch(() => { failed.push('plano de contas'); return [] as ChartAccountOption[] }),\n listStockLocations().catch(() => { failed.push('locais de estoque'); return [] as StockLocationOption[] }),\n ])\n setUnits(u); setAccounts(a); setLocations(l)\n setRegistryWarning(failed.length ? `Não consegui carregar ${failed.join(', ')}. Estes seletores vão aparecer vazios.` : null)\n if (detail) {\n // O NOME DO PRODUTO JÁ VINCULADO. Sem isto o seletor abria VAZIO em toda\n // linha que já tinha produto — o id estava lá, o rótulo não — e a tela\n // dizia «conferido» sobre um campo que parecia em branco. Vale para toda\n // nota reaberta, não só para as que a IA tocou.\n const vinculados = [...new Set(detail.items.map((i) => i.productId).filter((id): id is string => !!id))]\n const nomes = vinculados.length\n ? new Map((await listProductsByIds(vinculados).catch(() => [])).map((p) => [p.id, p.name]))\n : new Map<string, string>()\n const unidadesDoProduto = await listProductStockUnits(vinculados).catch(() => new Map<string, string>())\n setProductUnits(unidadesDoProduto)\n setDrafts(Object.fromEntries(detail.items.map((i) => [\n i.id,\n {\n ...draftOf(i),\n productLabel: (i.productId && nomes.get(i.productId)) || '',\n // Stocked lines keep what was recorded; open ones get a unit instead of a blank.\n stockUnitId: i.stockUnitId ?? (i.stockMovementId ? null : suggestedStockUnit(i, u, unidadesDoProduto, i.productId)),\n },\n ])))\n // Server-side `reconciled` seeds the checks, so saving does not undo them.\n // SUBSTITUI, não mescla. Mesclando, um «conferido» marcado antes nunca\n // voltava atrás: a linha perdia o produto, o servidor devolvia\n // `reconciled: false`, e a tela continuava dizendo que estava conferida\n // porque a chave antiga sobrevivia ao recarregamento. Depois de um load o\n // servidor é a verdade.\n setChecked(Object.fromEntries(detail.items.filter((i) => i.reconciled).map((i) => [i.id, true])))\n const pending = detail.items.find((i) => !i.reconciled)\n setOpenIds(pending ? [pending.id] : [])\n setInstalments(detail.instalments.map((d) => ({\n index: d.index, number: d.number, dueDate: d.dueDate, amount: d.amount,\n paymentType: d.paymentType, barcode: d.barcode, pixKey: d.pixKey,\n })))\n setDefaultAccount(detail.defaultChartAccountId)\n setLocation(detail.defaultLocationId ?? l[0]?.id ?? null)\n }\n } catch (e) {\n // Falhar buscando a nota é diferente de não achar a nota, e a tela tem de\n // dizer qual dos dois foi.\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setLoading(false)\n }\n }, [noteId])\n\n useEffect(() => { void load() }, [load])\n\n /**\n * EDITAR À MÃO APAGA A AUTORIA DA MÁQUINA.\n *\n * O selo diz «este valor é o que a máquina escreveu». No instante em que\n * alguém corrige o fator, o selo passaria a mentir — e mentiria para o lado\n * pior, pedindo conferência de um número que acabou de ser conferido. Então a\n * regra é uma só, aqui, e não espalhada por quinze `onChange`: toda mudança\n * que não declara autoria zera a autoria.\n */\n const patch = (id: string, change: Partial<Draft>) =>\n setDrafts((prev) => ({\n ...prev,\n [id]: {\n ...prev[id],\n ...('suggestedBy' in change ? {} : { suggestedBy: null, suggestionConfidence: null }),\n ...change,\n },\n }))\n\n const accountOptions = useMemo<SearchSelectOption[]>(\n () => accounts.map((a) => ({ id: a.id, label: `${a.code} · ${a.name}` })),\n [accounts],\n )\n const unitOptions = useMemo<SearchSelectOption[]>(\n () => units.map((u) => ({ id: u.id, label: u.abbreviation, subtitle: u.name })),\n [units],\n )\n const locationOptions = useMemo<SearchSelectOption[]>(\n () => locations.map((l) => ({ id: l.id, label: l.name })),\n [locations],\n )\n\n /**\n * O rascunho virado em decisão. É FUNÇÃO e não só `useMemo` porque o\n * auto-salvar da sugestão precisa gravar o rascunho que ELE acabou de montar —\n * o memo ainda é o de antes do `setDrafts`, e salvar com ele gravaria a tela\n * anterior em cima da sugestão.\n */\n const buildDecisions = useCallback((rascunhos: Record<string, Draft>): ItemDecisionInput[] => {\n if (!note) return []\n return note.items.map((item) => {\n const d = rascunhos[item.id] ?? draftOf(item)\n return {\n id: item.id,\n productId: isStockBearing(d.entryType) ? d.productId : null,\n entryType: d.entryType,\n // A herança que a legenda do V1 promete: «itens sem plano herdarão este».\n chartAccountId: d.chartAccountId ?? defaultAccount,\n stockUnitId: d.stockUnitId,\n conversionFactor: Number(d.conversionFactor.replace(',', '.')) || 1,\n costMode: d.costMode,\n suggestedBy: d.suggestedBy,\n suggestionConfidence: d.suggestionConfidence,\n shortageQuantity: d.shortageQuantity === '' ? null : Number(d.shortageQuantity.replace(',', '.')),\n }\n })\n }, [note, defaultAccount])\n\n const decisions = useMemo(() => buildDecisions(drafts), [buildDecisions, drafts])\n\n const stockLines = decisions.filter((d) => isStockBearing(d.entryType))\n const missingProduct = stockLines.filter((d) => !d.productId).length\n // A stock line without a unit enters as a bare number the screens read as \"unidade\".\n const missingUnit = stockLines.filter((d) => {\n const item = note?.items.find((i) => i.id === d.id)\n return !d.stockUnitId && !item?.stockMovementId\n }).length\n const missingType = decisions.filter((d) => !d.entryType).length\n\n /**\n * FATOR DE EMBALAGEM QUE NINGUÉM CONFIRMOU.\n *\n * A unidade comercial declara conteúdo (MI = 1.000, DZ = 12, CENTO = 100) e uma\n * das duas coisas está em aberto: o fator continua 1 (a conta não foi feita), ou\n * a unidade de estoque não foi escolhida (a conta foi feita no escuro, porque o\n * produto não tem `unit` no cadastro).\n *\n * Nos dois casos a máquina chegou até onde podia e a palavra final é de gente:\n * «1 MI a R$ 616,00» são 1.000 sacos a R$ 0,616 ou 1 saco a R$ 616,00, e a\n * diferença entre as duas leituras é o estoque e o custo médio da casa.\n *\n * O cabeçalho deste arquivo diz que a «Qtd estoque (calc.)» é a única defesa\n * contra fator errado. Uma defesa que não trava o «Aceitar» não é defesa.\n */\n const suspectFactor = (item: InboxItem, d: Draft) =>\n packagingCount(item.unit) !== null\n && isStockBearing(d.entryType)\n && ((Number(d.conversionFactor.replace(',', '.')) || 1) === 1 || !d.stockUnitId)\n\n const unverifiedFactor = note\n ? note.items.filter((i) => suspectFactor(i, drafts[i.id] ?? draftOf(i))).length\n : 0\n const instalmentSum = instalments.reduce((acc, d) => acc + (Number(d.amount) || 0), 0)\n // A payable alone is not \"done\": the V1 opened it before reconciling, and many\n // of those notes never reached stock. Done = stocked, or nothing left to stock.\n const hasPayable = Boolean(note?.invoiceId)\n const pendingStock = (note?.items ?? []).some((i) =>\n !i.stockMovementId && (!i.entryType || isStockBearing(i.entryType)))\n const readOnly = Boolean(note?.stockedAt || (hasPayable && !pendingStock))\n const paymentLocked = readOnly || hasPayable\n\n // Same rule the save RPC uses for `reconciled`: checking adds no second state.\n const isReady = (item: InboxItem, d: Draft) =>\n Boolean(d.entryType)\n && (!isStockBearing(d.entryType) || Boolean(d.productId))\n && !suspectFactor(item, d)\n const doneCount = note ? note.items.filter((i) => checked[i.id]).length : 0\n\n const toggleItem = (id: string) =>\n setOpenIds((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]))\n\n /** Checking closes this item and opens the next pending one. */\n const confirmItem = (id: string) => {\n setChecked((prev) => ({ ...prev, [id]: true }))\n setOpenIds((prev) => {\n const rest = prev.filter((x) => x !== id)\n const next = note?.items.find((i) => i.id !== id && !checked[i.id])\n return next && !rest.includes(next.id) ? [...rest, next.id] : rest\n })\n }\n\n // ── Sugerir com IA ────────────────────────────────────────────────────────\n // A SUGESTÃO ACONTECE NO SERVIDOR, como no V1. A edge function pergunta ao\n // índice (de-para do fornecedor e EAN resolvem sem modelo), manda só o que\n // sobrou com os candidatos daquele item, aplica as evidências de fator que são\n // aritmética (uTrib/qTrib, milheiro) e GRAVA pela mesma RPC do «Salvar\n // conciliação». Então aqui não há merge de rascunho: pede, e recarrega.\n //\n // A primeira versão disto foi um turno de agente e o broker recusou no\n // primeiro clique real — `Message is too long`. Ver `lib/note-suggestion.ts`.\n\n /**\n * Grava o rascunho recebido, sem recarregar.\n *\n * Existe separada do `save()` porque o auto-salvar da sugestão precisa gravar um\n * rascunho que ele mesmo tem em mão, e não o que o `useMemo` ainda enxerga.\n */\n const persistir = useCallback(async (rascunhos: Record<string, Draft>) => {\n if (!note) return\n await saveNoteDecision({\n documentId: note.id,\n items: buildDecisions(rascunhos),\n defaultChartAccountId: defaultAccount,\n defaultLocationId: location,\n instalments,\n })\n }, [note, buildDecisions, defaultAccount, location, instalments])\n\n /** Só o que falta decidir. Decide o rótulo do botão e se ele existe. */\n const pendingItems = useMemo(\n () => (note?.items ?? []).filter((item) => {\n const d = drafts[item.id] ?? draftOf(item)\n return !d.entryType || (isStockBearing(d.entryType) && !d.productId)\n }),\n [note, drafts],\n )\n\n /**\n * Itens que a MÁQUINA decidiu. É o alvo do «Rodar IA novamente».\n *\n * Reavaliar nunca toca no que uma pessoa escolheu: `suggestedBy` nulo é escolha\n * humana, e sobrescrevê-la seria desfazer trabalho — o V1 tinha esse botão e\n * respeitava a mesma fronteira.\n */\n const machineItems = useMemo(\n () => (note?.items ?? []).filter((item) => (drafts[item.id] ?? draftOf(item)).suggestedBy !== null),\n [note, drafts],\n )\n\n const sugerir = useCallback(async (reavaliar = false) => {\n if (!note) return\n setSuggesting(true); setSuggestionNote(null); setError(null)\n try {\n // GRAVA O RASCUNHO ANTES DE PEDIR. A function escreve no banco e a tela\n // recarrega em seguida; rascunho não salvo seria apagado pelo que voltar.\n await persistir(drafts)\n\n const res = await suggestNoteItems(note.id, reavaliar)\n // A nota volta inteira do servidor: é ela que carrega `suggested_by`, e é\n // o que faz o selo sobreviver a recarregar a página.\n await load()\n\n if (res.applied === 0 && res.bound === 0 && res.typedOnly === 0) {\n setSuggestionNote(res.warnings[0] ?? 'Não achei nada para preencher nestes itens.')\n return\n }\n const semIA = res.bound\n ? `Sem IA: ${res.boundByEan ? `${res.boundByEan} pelo código de barras` : ''}`\n + (res.boundByEan && res.bound - res.boundByEan ? ' e ' : '')\n + (res.bound - res.boundByEan ? `${res.bound - res.boundByEan} pelo catálogo deste fornecedor` : '')\n + '.'\n : ''\n // A FRASE SEGUE A TELA. «Preenchido» é só o que ficou pronto; a linha que\n // recebeu o tipo e nenhum produto continua em «falta decidir», e dizer que\n // ela foi preenchida é a tela mentindo sobre o próprio trabalho.\n setSuggestionNote([\n semIA,\n res.applied\n ? `${res.applied} ${res.applied === 1 ? 'item preenchido' : 'itens preenchidos'} pela IA.`\n : '',\n res.typedOnly\n ? `${res.typedOnly} ${res.typedOnly === 1 ? 'item ficou' : 'itens ficaram'} sem produto no catálogo`\n + (res.newProductNames.length ? ` (${res.newProductNames.slice(0, 3).join(', ')})` : '')\n + ' — escolha o produto ou cadastre antes de aceitar.'\n : '',\n res.applied || res.bound ? 'Salvo.' : '',\n ...res.warnings,\n ].filter(Boolean).join(' '))\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setSuggesting(false)\n }\n }, [note, drafts, persistir, load])\n\n // O botão do V1, com o roxo que a conciliação já usa para «isto a máquina\n // O botão do V1, com o roxo que a conciliação já usa para «isto a máquina\n // propôs». Ele não existe quando não há nada a decidir: pedir sugestão para uma\n // nota pronta só poderia DESFAZER escolha de gente.\n //\n // E não depende mais de chave no cliente: a credencial do modelo mora na edge\n // function, então todo app que tem o plugin tem a sugestão — control,\n // full-control e ticket incluídos, que nunca tiveram VITE_FAYZ_AGENT_KEY.\n //\n // Depois da primeira rodada não há mais item pendente, e o botão SUMIA — a\n // sugestão ruim ficava sem segunda chance, e um botão que evapora ao ser usado\n // é esquisito. O V1 trocava o rótulo; aqui também, e «rodar de novo» só\n // reavalia o que a máquina decidiu.\n const reavaliar = pendingItems.length === 0 && machineItems.length > 0\n const botaoIA = readOnly || (pendingItems.length === 0 && !reavaliar)\n ? null\n : (\n <AiActionButton\n size=\"sm\"\n className=\"shrink-0\"\n busy={suggesting}\n busyLabel=\"Pensando…\"\n onClick={() => { void sugerir(reavaliar) }}\n >\n {reavaliar ? 'Rodar IA novamente' : 'Sugerir com IA'}\n </AiActionButton>\n )\n\n /**\n * A moldura do modal. O título e o «Sugerir com IA» ficam no CABEÇALHO, fora da\n * área que rola: a sugestão preenche onze itens de uma vez, e um botão que sai\n * de vista ao rolar até o item 7 é um botão que ninguém acha na segunda nota.\n */\n const moldura = (node: React.ReactNode, titulo: string, rodape?: { start: React.ReactNode; end: React.ReactNode } | null) => (emModal ? (\n <>\n <ModalHeader className=\"shrink-0 flex-row items-center justify-between gap-3 space-y-0 border-b px-6 py-3 pr-14 text-left sm:flex-row\">\n <ModalTitle className=\"min-w-0 truncate\">{titulo}</ModalTitle>\n <div className=\"flex shrink-0 items-center gap-1\">\n {botaoIA}\n {ferramentas}\n </div>\n </ModalHeader>\n <ModalBody className=\"px-6 py-4\">{node}</ModalBody>\n {rodape && <ModalFooter variant=\"bar\" start={rodape.start}>{rodape.end}</ModalFooter>}\n </>\n ) : (\n // Em tela cheia não há moldura onde pendurar o rodapé: ele volta para dentro\n // do conteúdo, grudado na base da janela enquanto a página rola.\n <>\n {node}\n {rodape && (\n <div className={`sticky bottom-0 ${sangria} flex items-center justify-between gap-3 border-t bg-card/95 py-3 pr-16 backdrop-blur`}>\n <div className=\"flex min-w-0 items-center gap-3\">{rodape.start}</div>\n <div className=\"flex shrink-0 items-center gap-2\">{rodape.end}</div>\n </div>\n )}\n </>\n ))\n\n /**\n * Baixa o XML desta nota.\n *\n * O texto desce agora e não junto do detalhe: são 10–50 KB por nota, e carregá-lo\n * em toda abertura da tela seria pagar por um arquivo que quase ninguém abre.\n */\n const [cadastrando, setCadastrando] = useState(false)\n const cadastrarFornecedor = useCallback(async () => {\n if (!note) return\n setCadastrando(true); setError(null)\n try {\n const { supplierPartyId } = await linkInboxSupplier(note.id, true)\n if (supplierPartyId) setNote({ ...note, supplierPartyId })\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setCadastrando(false)\n }\n }, [note])\n\n const [abrindoPdf, setAbrindoPdf] = useState(false)\n const abrirPdf = useCallback(async () => {\n if (!note?.accessKey) return\n // Opened before the await: a tab opened after it is a popup the browser blocks.\n const tab = window.open('', '_blank')\n setAbrindoPdf(true); setError(null)\n try {\n const pdf = await getInboxNotePdf(note.accessKey)\n if (tab) tab.location.href = URL.createObjectURL(pdf)\n } catch (e) {\n tab?.close()\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setAbrindoPdf(false)\n }\n }, [note])\n\n const baixarXml = useCallback(async () => {\n if (!note) return\n setBaixandoXml(true); setError(null)\n try {\n const xml = await getInboxNoteXml(note.id)\n if (!xml) { setError('O arquivo desta nota não está guardado.'); return }\n const url = URL.createObjectURL(new Blob([xml], { type: 'application/xml' }))\n const a = document.createElement('a')\n // O nome é a CHAVE DE ACESSO, como a Receita e todo contador esperam —\n // `nota.xml` numa pasta com trinta notas não diz qual é qual.\n a.href = url\n a.download = `${note.accessKey || note.number || 'nfe'}.xml`\n a.click()\n URL.revokeObjectURL(url)\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setBaixandoXml(false)\n }\n }, [note])\n\n // The note's own tools live in the header, beside the title, so they never\n // scroll away. The XML exists per note: notes staged before the file was kept\n // have no bytes, and the menu item says so instead of failing.\n const ferramentas = note ? (\n <div className=\"flex items-center gap-1\">\n <Dropdown>\n <DropdownTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" disabled={baixandoXml || abrindoPdf}>\n {baixandoXml || abrindoPdf\n ? <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" />\n : <Download className=\"mr-1.5 h-4 w-4\" />}\n Baixar\n <ChevronDown className=\"ml-1 h-3.5 w-3.5 opacity-60\" />\n </Button>\n </DropdownTrigger>\n <DropdownContent align=\"end\">\n <DropdownItem className=\"gap-2\" disabled={!note.hasXml} onSelect={() => { void baixarXml() }}>\n <FileCode2 className=\"h-4 w-4\" />\n {note.hasXml ? 'XML da nota' : 'XML não guardado — reimporte o .xml'}\n </DropdownItem>\n <DropdownItem className=\"gap-2\" disabled={!note.accessKey} onSelect={() => { void abrirPdf() }}>\n <FileText className=\"h-4 w-4\" />\n DANFE (PDF)\n </DropdownItem>\n </DropdownContent>\n </Dropdown>\n <Hint label=\"Atualizar\">\n <Button variant=\"ghost\" size=\"icon\" aria-label=\"Atualizar a nota\" onClick={() => { void load() }}>\n <RefreshCw className=\"h-4 w-4\" />\n </Button>\n </Hint>\n </div>\n ) : null\n\n\n const save = async () => {\n if (!note) return\n setSaving(true); setError(null)\n try {\n await saveNoteDecision({\n documentId: note.id, items: decisions,\n defaultChartAccountId: defaultAccount, defaultLocationId: location,\n instalments,\n })\n await load()\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setSaving(false)\n }\n }\n\n const accept = async () => {\n if (!note) return\n setAccepting(true); setError(null)\n try {\n // Salvar e aceitar num gesto: o operador clicou «Aceitar», e pedir que ele\n // salve antes seria uma etapa que só existe por causa do nosso desenho.\n await saveNoteDecision({\n documentId: note.id, items: decisions,\n defaultChartAccountId: defaultAccount, defaultLocationId: location,\n instalments,\n })\n const result = await acceptNote(note.id, location)\n // What was attached before the payable existed now belongs to it.\n if (result.invoiceId) await moveNoteAttachmentsToInvoice(note.id, result.invoiceId).catch(() => {})\n setAccepted(result)\n await load()\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setAccepting(false)\n }\n }\n\n // Skeleton mirrors the real layout so the page does not jump when it arrives.\n if (loading) {\n return moldura((\n <div className=\"space-y-4\">\n {cabecalho('Conciliação')}\n <Card className=\"p-4\">\n <Skeleton className=\"h-4 w-32\" />\n <div className=\"mt-3 grid gap-x-6 gap-y-3 sm:grid-cols-2 lg:grid-cols-3\">\n {[0, 1, 2, 3, 4, 5].map((i) => (\n <div key={i}>\n <Skeleton className=\"h-3 w-20\" />\n <Skeleton className=\"mt-1.5 h-4 w-36\" />\n </div>\n ))}\n </div>\n </Card>\n <Card className=\"p-4\">\n <Skeleton className=\"h-4 w-36\" />\n <div className=\"mt-3 grid gap-4 sm:grid-cols-2\">\n {[0, 1].map((i) => (\n <div key={i}>\n <Skeleton className=\"h-3 w-28\" />\n <Skeleton className=\"mt-1.5 h-9 w-full\" />\n </div>\n ))}\n </div>\n </Card>\n <Skeleton className=\"h-4 w-24\" />\n <div className=\"space-y-2\">\n {[0, 1, 2].map((i) => (\n <Card key={i} className=\"flex items-center gap-3 px-4 py-3\">\n <Skeleton className=\"h-4 w-4 rounded-full\" />\n <div className=\"min-w-0 flex-1\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"mt-1.5 h-3 w-1/3\" />\n </div>\n <Skeleton className=\"h-4 w-20\" />\n </Card>\n ))}\n </div>\n </div>\n ), 'Conciliação')\n }\n\n if (!note) {\n return moldura((\n <div className=\"space-y-4\">\n {cabecalho('Conciliação')}\n <Card className=\"p-8 text-center text-sm\">\n {error\n ? <span className=\"text-destructive\">Não consegui carregar a nota: {error}</span>\n : <span className=\"text-muted-foreground\">Nota não encontrada.</span>}\n </Card>\n </div>\n ), 'Conciliação')\n }\n\n // ── Rejeitar / Salvar / Aceitar ──────────────────────────────────────────\n const pendencias = [\n unverifiedFactor > 0 && `${unverifiedFactor} com fator por conferir`,\n missingType > 0 && `${missingType} sem tipo`,\n missingProduct > 0 && `${missingProduct} sem produto`,\n missingUnit > 0 && `${missingUnit} sem unidade de estoque`,\n ].filter(Boolean).join(' · ')\n const rodape = readOnly ? null : {\n start: (\n <>\n {!hasPayable && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-destructive hover:bg-destructive/10 hover:text-destructive\"\n onClick={async () => { await rejectNote(note.id); onBack() }}\n disabled={saving || accepting}\n >\n <X className=\"mr-1.5 h-3.5 w-3.5\" />\n Rejeitar\n </Button>\n )}\n {pendencias && <span className=\"truncate text-xs text-muted-foreground\">{pendencias}</span>}\n </>\n ),\n end: (\n <>\n <Button variant=\"outline\" size=\"sm\" onClick={() => { void save() }} disabled={saving || accepting}>\n {saving && <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />}\n Salvar conciliação\n </Button>\n <Button\n size=\"sm\"\n onClick={() => { void accept() }}\n disabled={accepting || saving || missingType > 0 || missingProduct > 0 || missingUnit > 0 || unverifiedFactor > 0}\n >\n {accepting ? <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" /> : <Check className=\"mr-1.5 h-3.5 w-3.5\" />}\n {hasPayable ? 'Dar entrada no estoque' : 'Aceitar'}\n </Button>\n </>\n ),\n }\n\n return moldura((\n <div className={`space-y-4 ${emModal ? '' : 'pb-24'}`}>\n {cabecalho(`Conciliação · NF-e ${note.number}`)}\n\n {accepted && (\n <Card className=\"border-success bg-success-soft p-4\">\n <p className=\"text-sm font-medium text-success-soft-foreground\">\n {accepted.alreadyAccepted\n ? 'Esta nota já havia sido aceita — nada foi lançado de novo.'\n : accepted.instalments === 0\n ? `Entrada no estoque: ${accepted.stockLines} ${accepted.stockLines === 1 ? 'linha' : 'linhas'}, ligadas à conta a pagar que a nota já tinha (${money(accepted.invoiceTotal)}).`\n : `Aceita: ${accepted.stockLines} ${accepted.stockLines === 1 ? 'linha' : 'linhas'} de estoque e um título de ${money(accepted.invoiceTotal)} em ${accepted.instalments} ${accepted.instalments === 1 ? 'parcela' : 'parcelas'}.`}\n </p>\n {accepted.invoiceId && onOpenInvoice && (\n <Button variant=\"outline\" size=\"sm\" className=\"mt-2\" onClick={() => onOpenInvoice(accepted.invoiceId!)}>\n Abrir a conta a pagar\n </Button>\n )}\n </Card>\n )}\n\n {payableLost && !readOnly && (\n <Card className=\"border-warning bg-warning-soft p-4\" data-testid=\"note-payable-lost\">\n <p className=\"text-sm font-medium text-warning-soft-foreground\">\n A conta a pagar e a entrada no estoque desta nota foram apagadas fora daqui.\n </p>\n <p className=\"mt-1 text-xs text-warning-soft-foreground\">\n Confira a conciliação e clique em Aceitar para lançar as duas de novo.\n </p>\n </Card>\n )}\n\n {!accepted && (\n <Card className=\"p-4\" data-testid=\"note-postings\">\n <h3 className=\"text-sm font-semibold\">Lançamentos desta nota</h3>\n <dl className=\"mt-3 grid gap-x-6 gap-y-3 text-sm sm:grid-cols-2\">\n <div>\n <dt className=\"text-xs text-muted-foreground\">Conta a pagar</dt>\n <dd className=\"mt-0.5 flex flex-wrap items-center gap-2\">\n {!note.invoiceId && (\n <span className={payableLost ? 'text-destructive' : 'text-muted-foreground'}>\n {payableLost\n ? 'Não existe mais — foi apagada; aceite a nota para lançar de novo'\n : readOnly ? 'Nenhuma — esta nota não abriu conta a pagar' : 'Ainda não lançada — nasce quando a nota for aceita'}\n </span>\n )}\n {note.invoiceId && payable === null && (\n <span className=\"text-destructive\">Não encontrada — a conta foi apagada</span>\n )}\n {payable && (\n <span data-testid=\"note-payable-link\">\n {onOpenInvoice\n ? <InlineLink onClick={() => onOpenInvoice(payable.id)}>{payable.number ?? 'Conta a pagar'}</InlineLink>\n : (payable.number ?? 'Conta a pagar')}\n {' · '}{money(payable.total)}\n {payable.cancelledAt && <span className=\"text-destructive\"> · cancelada</span>}\n </span>\n )}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-muted-foreground\">Estoque</dt>\n <dd className=\"mt-0.5\">\n {note.stockedAt\n ? `Entrada em ${day(note.stockedAt)}`\n : <span className=\"text-muted-foreground\">{readOnly ? 'Sem entrada no estoque' : hasPayable ? 'Ainda sem entrada — conclua a conciliação e dê entrada' : 'Ainda sem entrada — entra quando a nota for aceita'}</span>}\n </dd>\n </div>\n </dl>\n </Card>\n )}\n\n {/* ── 1. Situação fiscal ─────────────────────────────────────────── */}\n <Card className=\"p-4\">\n <h3 className=\"text-sm font-semibold\">Situação fiscal</h3>\n <dl className=\"mt-3 grid gap-x-6 gap-y-2 text-sm sm:grid-cols-2 lg:grid-cols-3\">\n <div>\n <dt className=\"text-xs text-muted-foreground\">Fornecedor</dt>\n <dd className=\"text-sm\">\n {note.supplierPartyId\n ? <PersonLink personId={note.supplierPartyId} name={note.supplierName || '—'} kind=\"supplier\" />\n : (note.supplierName || '—')}\n </dd>\n </div>\n <Field label=\"CNPJ\" value={note.supplierCnpj ?? '—'} mono />\n <Field label=\"Natureza da operação\" value={note.natureOperation ?? '—'} />\n <Field\n label=\"Manifestação\"\n value={`${note.manifestationStatus ?? 'não manifestada'}${note.manifestationAttempts ? ` · ${note.manifestationAttempts} tentativa(s)` : ''}`}\n />\n <Field label=\"Manifestada em\" value={day(note.manifestedAt)} />\n <Field label=\"Recebida em\" value={day(note.receivedAt)} />\n </dl>\n {/* O aviso é um bloco, não um trecho de texto: solto ele vazava do card e\n empurrava o botão para debaixo da própria frase. */}\n {!note.supplierPartyId && (\n <div className=\"mt-3 flex flex-wrap items-center justify-between gap-2 rounded-md border border-input bg-muted/40 px-3 py-2\">\n <p className=\"text-xs text-muted-foreground\">\n {note.supplierCnpj\n ? <>Este fornecedor ainda não está no cadastro. Ao aceitar, ele é cadastrado com o nome e o CNPJ da nota.</>\n : <>A nota não traz o CNPJ do fornecedor, então a conta a pagar vai nascer <strong>sem fornecedor</strong>.</>}\n </p>\n {note.supplierCnpj && !readOnly && (\n <Button variant=\"outline\" size=\"sm\" disabled={cadastrando} onClick={() => { void cadastrarFornecedor() }}>\n {cadastrando ? <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" /> : <UserPlus className=\"mr-1.5 h-4 w-4\" />}\n Cadastrar agora\n </Button>\n )}\n </div>\n )}\n {/* A nota de bonificação entra no estoque e NÃO deve gerar título. Hoje\n gera: 57 notas assim no V1 da Artorius, em 11 grafias de natureza. */}\n {/bonific|brinde|doacao|doação/i.test(note.natureOperation ?? '') && (\n <div className=\"mt-3 rounded-md border border-dashed border-input px-3 py-2\">\n <p className=\"text-xs text-muted-foreground\">\n <Gift className=\"mr-1 inline h-3.5 w-3.5\" aria-hidden />\n A natureza desta nota é <strong>bonificação</strong>. Ela deveria entrar no estoque{' '}\n <strong>sem</strong> abrir conta a pagar — hoje ainda abre.{' '}\n <span className=\"rounded-full bg-muted px-1.5 py-0.5 text-[10px]\">Em breve</span>\n </p>\n </div>\n )}\n\n {!emModal && <div className=\"mt-3 flex flex-wrap items-center gap-2\">{ferramentas}</div>}\n </Card>\n\n {/* ── 2. Padrões da nota ─────────────────────────────────────────── */}\n <Card className=\"p-4\">\n <h3 className=\"text-sm font-semibold\">Padrões desta nota</h3>\n {registryWarning && (\n <div className=\"mt-2 rounded-md border border-warning bg-warning-soft px-3 py-2\">\n <p className=\"text-xs text-warning-soft-foreground\">\n <AlertTriangle className=\"mr-1 inline h-3.5 w-3.5\" aria-hidden />\n {registryWarning}\n </p>\n </div>\n )}\n <div className=\"mt-3 grid gap-4 sm:grid-cols-2\">\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Plano de contas padrão</span>\n <SearchSelect\n onSearch={localSearch(accountOptions)}\n value={defaultAccount ?? undefined}\n displayValue={labelOf(accountOptions, defaultAccount)}\n onChange={(id) => setDefaultAccount(id || null)}\n minChars={0}\n placeholder=\"Escolher plano de contas\"\n noResultsLabel=\"Nenhum plano de contas\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n <span className=\"mt-1 block text-[11px] text-muted-foreground\">\n Itens sem plano herdarão este.\n </span>\n </label>\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Local de estoque</span>\n <SearchSelect\n onSearch={localSearch(locationOptions)}\n value={location ?? undefined}\n displayValue={labelOf(locationOptions, location)}\n onChange={(id) => setLocation(id || null)}\n minChars={0}\n placeholder=\"Escolher local\"\n noResultsLabel=\"Nenhum local de estoque\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n <span className=\"mt-1 block text-[11px] text-muted-foreground\">\n Onde as linhas de estoque desta nota entram.\n </span>\n </label>\n </div>\n </Card>\n\n {/* ── 3. Itens — one collapsed group per item, with progress ─────── */}\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h3 className=\"text-sm font-semibold\">\n Itens <span className=\"font-normal text-muted-foreground\">({note.items.length})</span>\n </h3>\n <div className=\"h-1.5 min-w-[6rem] flex-1 overflow-hidden rounded-full bg-muted\">\n <div\n className=\"h-full rounded-full bg-primary transition-all\"\n style={{ width: `${note.items.length ? (doneCount / note.items.length) * 100 : 0}%` }}\n />\n </div>\n <span className=\"text-xs tabular-nums text-muted-foreground\">\n {doneCount}/{note.items.length} conferidos\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setOpenIds(openIds.length ? [] : note.items.map((i) => i.id))}\n >\n {openIds.length ? 'Recolher todos' : 'Abrir todos'}\n </Button>\n {/* Em tela cheia não há cabeçalho de modal onde pendurá-lo, então ele\n fica junto do que ele preenche. */}\n {!emModal && botaoIA}\n </div>\n\n {suggestionNote && (\n <div className=\"flex items-start gap-2 rounded-md border border-magic/30 bg-magic-soft px-3 py-2\">\n <p className=\"flex-1 text-xs text-magic-soft-foreground\">{suggestionNote}</p>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n className=\"shrink-0 text-xs text-magic-soft-foreground/70 hover:underline font-normal\"\n onClick={() => setSuggestionNote(null)}\n >\n Fechar\n </Button>\n </div>\n )}\n {/* Notes that crossed from the V1 without their XML arrive with a header\n and no lines; pulling the same key restages this very note. */}\n {note.items.length === 0 && (\n <Card className=\"p-6 text-center\" data-testid=\"note-without-items\">\n <p className=\"text-sm font-medium\">Esta nota chegou sem os itens</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {readOnly || !note.accessKey\n ? 'Não há o XML dela guardado para ler os itens.'\n : note.hasXml\n ? 'O XML guardado é só o resumo da SEFAZ, sem os itens. Busque a nota completa pela chave de acesso.'\n : 'O XML dela não veio junto. Busque na SEFAZ pela chave de acesso para conciliar.'}\n </p>\n {!readOnly && note.accessKey && note.status !== 'rejected' && (\n <Button className=\"mt-3\" size=\"sm\" onClick={() => setPullOpen(true)}>\n <Download className=\"mr-1.5 h-4 w-4\" /> Buscar itens na SEFAZ\n </Button>\n )}\n <PullByKeyDialog\n open={pullOpen}\n onOpenChange={setPullOpen}\n unitId={note.unitId}\n initialKey={note.accessKey ?? undefined}\n onPulled={() => { void load() }}\n />\n </Card>\n )}\n {note.items.map((item) => {\n const d = drafts[item.id] ?? draftOf(item)\n const factor = Number(d.conversionFactor.replace(',', '.')) || 1\n const shortage = d.shortageQuantity === '' ? 0 : Number(d.shortageQuantity.replace(',', '.')) || 0\n const stockQty = item.quantity * factor - shortage\n const unitCost = factor > 0 ? item.unitPrice / factor : item.unitPrice\n const bearing = isStockBearing(d.entryType)\n\n const open = openIds.includes(item.id)\n const done = Boolean(checked[item.id])\n const ready = isReady(item, d)\n const typeLabel = ENTRY_TYPES.find((t) => t.value === d.entryType)?.label\n\n return (\n <Card key={item.id} className=\"overflow-hidden\">\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n onClick={() => toggleItem(item.id)}\n aria-expanded={open}\n className=\"flex w-full items-center justify-start gap-3 rounded-none px-4 py-3 text-left font-normal transition-colors hover:bg-muted/30\"\n >\n <ChevronRight\n className={`h-4 w-4 shrink-0 text-muted-foreground transition-transform ${open ? 'rotate-90' : ''}`}\n aria-hidden\n />\n <span className=\"w-5 shrink-0 text-xs tabular-nums text-muted-foreground\">{item.itemNumber}</span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium leading-tight\">{item.description}</span>\n <span className=\"block truncate text-xs text-muted-foreground\">\n {qty(item.quantity)} {item.unit ?? ''} · {money(item.unitPrice)}\n {typeLabel ? ` · ${typeLabel}` : ' · sem tipo'}\n </span>\n </span>\n <span className=\"shrink-0 text-sm tabular-nums\">{money(item.total)}</span>\n {/* Quem escreveu neste item. Sem isto, «Falta decidir» e «A\n conferir» tratam igual o que a pessoa escolheu e o que a\n máquina chutou — e o fator errado é silencioso. */}\n {d.suggestedBy && !done && <AuthorBadge draft={d} />}\n <ItemState done={done && ready} ready={ready} />\n </Button>\n\n {open && (\n <div className=\"grid gap-4 border-t p-4 lg:grid-cols-2\">\n {/* ITEM NA NOTA — o que o documento diz, e não se edita. */}\n <div>\n <p className=\"text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Item na nota\n </p>\n <p className=\"mt-1 font-medium leading-tight\">{item.itemNumber}. {item.description}</p>\n <dl className=\"mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-xs sm:grid-cols-4\">\n <Field small label=\"Qtd\" value={`${qty(item.quantity)} ${item.unit ?? ''}`} />\n <Field small label=\"Vl. unit.\" value={money(item.unitPrice)} />\n <Field small label=\"Total\" value={money(item.total)} />\n <Field small label=\"Cód\" value={item.supplierProductCode || '—'} mono />\n <Field small label=\"EAN\" value={item.eanBarcode ?? '—'} mono />\n <Field small label=\"NCM\" value={item.ncm ?? '—'} mono />\n <Field small label=\"CFOP\" value={item.cfop ?? '—'} mono />\n <Field small label=\"CST/CSOSN\" value={item.icmsCst ?? item.icmsCsosn ?? '—'} mono />\n </dl>\n </div>\n\n {/* ITEM NO ESTOQUE — a decisão. */}\n <div className=\"space-y-3 lg:border-l lg:pl-4\">\n <p className=\"text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Item no estoque\n </p>\n\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Tipo do registro</span>\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {ENTRY_TYPES.map((t) => (\n <Button variant=\"bare\" size=\"bare\"\n key={t.value}\n type=\"button\"\n disabled={readOnly}\n onClick={() => patch(item.id, { entryType: t.value })}\n className={`gap-0 font-normal rounded-full border px-2.5 py-1 text-[11px] transition-colors disabled:opacity-60 ${\n d.entryType === t.value\n ? 'border-primary bg-primary text-primary-foreground'\n : 'border-input hover:bg-muted'\n }`}\n >\n {t.label}\n {t.hint && <span className=\"ml-1 opacity-70\">· {t.hint}</span>}\n </Button>\n ))}\n </div>\n </label>\n\n {bearing && (\n <>\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Produto vinculado</span>\n <SearchSelect\n value={d.productId ?? undefined}\n displayValue={d.productLabel || undefined}\n onChange={(id, option) => {\n patch(item.id, { productId: id || null, productLabel: option?.label ?? '' })\n // The product's own unit wins over the note's guess, unless someone picked one.\n if (id && !d.stockUnitId) {\n void listProductStockUnits([id]).then((m) => {\n setProductUnits((prev) => new Map([...prev, ...m]))\n const unit = suggestedStockUnit(item, units, m, id)\n if (unit) patch(item.id, { stockUnitId: unit })\n }).catch(() => {})\n }\n }}\n onSearch={async (term: string) => {\n // Busca vazia traz o que mais se parece com a descrição da\n // nota: o operador quase sempre quer justamente aquilo.\n const found = await searchProducts(term || item.description.slice(0, 24))\n return found.map((prod) => ({\n id: prod.id,\n label: prod.name,\n subtitle: prod.sku ?? undefined,\n }))\n }}\n minChars={0}\n placeholder=\"Buscar produto do catálogo\"\n noResultsLabel=\"Nenhum produto encontrado\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n </label>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Fator de conversão</span>\n <Input\n value={d.conversionFactor}\n onChange={(e) => patch(item.id, { conversionFactor: e.target.value })}\n inputMode=\"decimal\"\n disabled={readOnly}\n />\n </label>\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Unidade de estoque</span>\n <SearchSelect\n onSearch={localSearch(unitOptions)}\n value={d.stockUnitId ?? undefined}\n displayValue={labelOf(unitOptions, d.stockUnitId)}\n onChange={(id) => patch(item.id, { stockUnitId: id || null })}\n minChars={0}\n placeholder=\"Escolha a unidade\"\n noResultsLabel=\"Nenhuma unidade\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n </label>\n </div>\n\n {suspectFactor(item, d) && (\n <div className=\"rounded-md border border-warning bg-warning-soft px-3 py-2\">\n <p className=\"text-xs text-warning-soft-foreground\">\n <AlertTriangle className=\"mr-1 inline h-3.5 w-3.5\" aria-hidden />\n Este item vem em <strong>{item.unit}</strong>, que são{' '}\n {qty(packagingCount(item.unit) ?? 0)} por embalagem.{' '}\n {!d.stockUnitId\n ? <>Escolha a <strong>unidade de estoque</strong> para confirmar o fator — o\n produto está cadastrado sem unidade.</>\n : <>O fator ainda é 1: do jeito que está entrariam {qty(item.quantity)}{' '}\n em vez de {qty(item.quantity * (packagingCount(item.unit) ?? 1))}.</>}\n </p>\n </div>\n )}\n\n {/* A única defesa contra fator errado, e ela tem de ser\n legível ANTES de aceitar. */}\n <div className=\"rounded-md bg-muted/50 px-3 py-2\">\n <div className=\"flex items-baseline justify-between text-sm\">\n <span className=\"text-xs text-muted-foreground\">Qtd estoque (calc.)</span>\n <span className=\"font-semibold tabular-nums\">{qty(stockQty)}</span>\n </div>\n <div className=\"flex items-baseline justify-between text-sm\">\n <span className=\"text-xs text-muted-foreground\">Novo custo unitário</span>\n <span className=\"tabular-nums\">{money(unitCost)}</span>\n </div>\n </div>\n\n {/* Os dois gestos que hoje mandam a Laissa sair da tela. */}\n <div className=\"flex flex-wrap gap-2\">\n <EmBreve\n label=\"Criar produto daqui\"\n o_que=\"Cadastrar o produto a partir desta linha da nota, com nome, código e unidade já preenchidos\"\n quantas=\"ela criou 33 produtos no V1 no meio de importações\"\n />\n <EmBreve\n label=\"Lote e validade\"\n o_que=\"Informar lote e vencimento desta entrada — a coluna já existe no movimento de estoque\"\n quantas=\"usado 5 vezes no V1; numa churrascaria é validade de carne\"\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Modo de custo</span>\n <div className=\"mt-1 flex gap-1\">\n {(['novo', 'media'] as const).map((mode) => (\n <Button variant=\"bare\" size=\"bare\"\n key={mode}\n type=\"button\"\n disabled={readOnly}\n onClick={() => patch(item.id, { costMode: mode })}\n className={`font-normal flex-1 rounded-md border px-2 py-1 text-[11px] disabled:opacity-60 ${\n d.costMode === mode ? 'border-primary bg-primary/10' : 'border-input hover:bg-muted'\n }`}\n >\n {mode === 'novo' ? 'Novo' : 'Média'}\n </Button>\n ))}\n </div>\n </label>\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Falta (qtd)</span>\n <Input\n value={d.shortageQuantity}\n onChange={(e) => patch(item.id, { shortageQuantity: e.target.value })}\n inputMode=\"decimal\"\n placeholder=\"0\"\n disabled={readOnly}\n />\n </label>\n </div>\n </>\n )}\n\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Plano de contas</span>\n <SearchSelect\n onSearch={localSearch(accountOptions)}\n value={(d.chartAccountId ?? defaultAccount) ?? undefined}\n displayValue={labelOf(accountOptions, d.chartAccountId ?? defaultAccount)}\n onChange={(id) => patch(item.id, { chartAccountId: id || null })}\n minChars={0}\n placeholder=\"Herda o padrão da nota\"\n noResultsLabel=\"Nenhum plano de contas\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n </label>\n\n {item.stockMovementId && (\n <p className=\"text-[11px] text-success-soft-foreground\">\n <Check className=\"mr-1 inline h-3 w-3\" aria-hidden />\n Esta linha já deu entrada no estoque.\n </p>\n )}\n\n {!readOnly && (\n <div className=\"flex items-center justify-end gap-3 border-t pt-3\">\n {!ready && (\n <span className=\"text-[11px] text-muted-foreground\">\n {!d.entryType ? 'Escolha o tipo do registro' : 'Vincule o produto'}\n </span>\n )}\n <Button\n size=\"sm\"\n variant={done ? 'ghost' : 'outline'}\n disabled={!ready}\n onClick={() => (done ? setChecked((prev) => ({ ...prev, [item.id]: false })) : confirmItem(item.id))}\n >\n <Check className=\"mr-1.5 h-4 w-4\" />\n {done ? 'Conferido' : 'Conferir item'}\n </Button>\n </div>\n )}\n </div>\n </div>\n )}\n </Card>\n )\n })}\n </div>\n\n {/* ── 4. Dados de pagamento ──────────────────────────────────────── */}\n <Card className=\"p-4\">\n <div className=\"flex items-baseline justify-between\">\n <h3 className=\"text-sm font-semibold\">Dados de pagamento</h3>\n <p className=\"text-xs text-muted-foreground\">\n {instalments.length} {instalments.length === 1 ? 'parcela' : 'parcelas'} ·{' '}\n <span className=\"tabular-nums\">{money(instalmentSum)}</span>\n </p>\n </div>\n\n {note.declaredPayments.length > 0 && (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n A nota declarou: {note.declaredPayments.map((p) => `${p.label ?? p.code} ${money(p.value)}`).join(' · ')}\n </p>\n )}\n\n <div className=\"mt-3 space-y-2\">\n {instalments.map((inst, i) => (\n <div key={i} className=\"grid items-end gap-2 sm:grid-cols-[2rem_1fr_1fr_1fr_2rem]\">\n <span className=\"pb-2 text-xs tabular-nums text-muted-foreground\">{inst.index}</span>\n <label className=\"block\">\n <span className=\"text-[11px] text-muted-foreground\">Vencimento</span>\n {/* Nota já aceita não tem vencimento editável, e um seletor de data\n apagado confunde mais que o texto: a parcela virou título. */}\n {paymentLocked ? (\n <p className=\"py-2 text-sm tabular-nums\">{day(inst.dueDate)}</p>\n ) : (\n <DatePicker\n value={inst.dueDate ?? ''}\n onChange={(v: string) =>\n setInstalments((prev) => prev.map((p, j) => (j === i ? { ...p, dueDate: v || null } : p)))}\n />\n )}\n </label>\n <label className=\"block\">\n <span className=\"text-[11px] text-muted-foreground\">Valor</span>\n <Input\n value={String(inst.amount)}\n inputMode=\"decimal\"\n disabled={paymentLocked}\n onChange={(e) =>\n setInstalments((prev) => prev.map((p, j) =>\n (j === i ? { ...p, amount: Number(e.target.value.replace(',', '.')) || 0 } : p)))}\n />\n </label>\n <label className=\"block\">\n <span className=\"text-[11px] text-muted-foreground\">Cód. barras / PIX</span>\n <Input\n value={inst.barcode ?? inst.pixKey ?? ''}\n disabled={paymentLocked}\n onChange={(e) =>\n setInstalments((prev) => prev.map((p, j) => (j === i ? { ...p, barcode: e.target.value } : p)))}\n />\n </label>\n {!paymentLocked && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={`Remover a parcela ${inst.index}`}\n onClick={() => setInstalments((prev) => prev.filter((_, j) => j !== i))}\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n ))}\n </div>\n\n {!paymentLocked && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"mt-3\"\n onClick={() => setInstalments((prev) => [...prev, {\n index: prev.length + 1, number: null, dueDate: note.issueDate, amount: 0, paymentType: 'boleto',\n }])}\n >\n <Plus className=\"mr-1.5 h-4 w-4\" />\n Adicionar parcela\n </Button>\n )}\n\n {/* O título nasce com a soma das parcelas. Se ela não bate com a nota, a\n tela diz — é a divergência que a financial/084 mediu em 6,3% dos casos. */}\n {Math.abs(instalmentSum - note.total) > 0.01 && (\n <Hint className=\"mt-3\">\n <span>\n <AlertTriangle className=\"mr-1 inline h-3.5 w-3.5\" aria-hidden />\n A nota diz {money(note.total)} e as parcelas somam {money(instalmentSum)}. O título vai\n nascer com <strong>{money(instalmentSum)}</strong> — é a soma das parcelas que define o\n saldo a pagar.\n </span>\n </Hint>\n )}\n </Card>\n\n {/* ── 5. Anexos da conta ─────────────────────────────────────────── */}\n <NoteAttachmentsCard\n noteId={note.id}\n invoiceId={note.invoiceId}\n readOnly={readOnly}\n instalments={instalments}\n onInstalments={setInstalments}\n />\n\n {error && (\n <Card className=\"border-destructive bg-destructive/5 p-4\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </Card>\n )}\n\n </div>\n ), `Conciliação · NF-e ${note.number}`, rodape)\n}\n\n/**\n * QUEM escreveu esta linha, quando não foi gente.\n *\n * Igualdade e semelhança em cores diferentes porque se conferem de maneiras\n * diferentes: um EAN batido não precisa de leitura, um «parecido» precisa. Roxo\n * (`magic`) é a cor do que a máquina propôs em todo o produto; azul é o vínculo\n * exato, que é informação e não aviso.\n */\nfunction AuthorBadge({ draft }: { draft: Draft }) {\n if (draft.suggestedBy === 'ai') {\n const confira = draft.suggestionConfidence != null && draft.suggestionConfidence < 0.6\n return (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-magic-soft px-2 py-0.5 text-[11px] font-medium text-magic-soft-foreground\">\n IA{confira ? ' · confira' : ''}\n </span>\n )\n }\n return (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-info-soft px-2 py-0.5 text-[11px] font-medium text-info-soft-foreground\">\n {draft.suggestedBy === 'ean' ? 'EAN' : 'fornecedor'}\n </span>\n )\n}\n\n/**\n * O estado da linha, e ele NUNCA diz «conferido» sobre o que não está pronto.\n *\n * `done` sozinho mentia: a marca de conferência sobrevive a mexer no campo\n * depois — e ninguém confere de novo um item que a tela já deu por fechado.\n * Quem chama passa `done && ready`.\n */\nfunction ItemState({ done, ready }: { done: boolean; ready: boolean }) {\n if (done) {\n return (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-success-soft px-2 py-0.5 text-[11px] font-medium text-success-soft-foreground\">\n <Check className=\"mr-1 h-3 w-3\" aria-hidden />\n Conferido\n </span>\n )\n }\n return (\n <span className={`inline-flex shrink-0 items-center rounded-full px-2 py-0.5 text-[11px] font-medium ${\n ready ? 'bg-muted text-muted-foreground' : 'bg-warning-soft text-warning-soft-foreground'\n }`}>\n {ready ? 'A conferir' : 'Falta decidir'}\n </span>\n )\n}\n\nfunction Field({ label, value, mono, small }: { label: string; value: string; mono?: boolean; small?: boolean }) {\n return (\n <div>\n <dt className={`text-muted-foreground ${small ? 'text-[10px]' : 'text-xs'}`}>{label}</dt>\n <dd className={`${mono ? 'tabular-nums' : ''} ${small ? 'text-xs' : 'text-sm'}`}>{value}</dd>\n </div>\n )\n}\n","// ---------------------------------------------------------------------------\n// A página de notas de compra: lista, conciliação e fila da SEFAZ numa moldura.\n// ---------------------------------------------------------------------------\n// As vistas trocam por ESTADO LOCAL, não por rota. Trocar de rota remonta a\n// página e rebusca tudo — a lista pisca, a posição de rolagem se perde, e voltar\n// da conciliação recarrega 200 notas para mostrar a mesma coisa.\n//\n// A CONCILIAÇÃO É MODAL, e a lista FICA MONTADA ATRÁS DELA. Era subpágina, e\n// subpágina desmonta: quem conciliava a quinta nota de um recorte de 200 voltava\n// para a lista no estado inicial — sem o filtro, sem a busca, no topo. O trabalho\n// é «abrir, decidir, fechar, abrir a próxima», e o custo era pago uma vez por\n// nota. Com o modal a lista nunca é desfeita, então fechar devolve exatamente o\n// que estava na tela.\n//\n// O ENDEREÇO EMPILHA NA DESCIDA. `pushState` não dispara `hashchange`, então o\n// roteador do anfitrião continua sem remontar nada — mas a conciliação passa a\n// existir como um degrau no histórico. Com `replaceState` ela não existia, e o\n// «voltar» do cabeçalho (que anda pelo histórico quando a pessoa veio de outro\n// módulo) saltava a lista inteira e caía no Painel. Subir é desempilhar.\n// ---------------------------------------------------------------------------\nimport React, { useCallback, useEffect, useState } from 'react'\nimport { Modal, ModalContent } from '@fayz-ai/ui'\nimport { findInboxNoteByOperation } from '../data/inbox'\nimport { InboundNotesView } from './InboundNotesView'\nimport { NoteReconcileView } from './NoteReconcileView'\n\ntype View =\n | { kind: 'list' }\n | { kind: 'note'; id: string }\n\nconst HASH_PREFIX = '#/inbound-notes'\n\nfunction viewFromLocation(): View {\n if (typeof window === 'undefined') return { kind: 'list' }\n const hash = window.location.hash\n const note = hash.match(/\\/inbound-notes\\/note\\/([0-9a-f-]{36})/i)\n if (note) return { kind: 'note', id: note[1] }\n return { kind: 'list' }\n}\n\nconst pathOf = (view: View) =>\n view.kind === 'note' ? `${HASH_PREFIX}/note/${view.id}` : HASH_PREFIX\n\nexport interface InboundNotesPageProps {\n /** Onde o título a pagar vive no app anfitrião. Sem isto o botão não aparece. */\n payableRoute?: (invoiceId: string) => string\n}\n\n/** Marca as entradas que ESTA página empilhou, para só elas serem desempilhadas. */\nconst STACK_MARK = { inboundNotes: true }\n\nexport function InboundNotesPage({ payableRoute = (id) => `/financial/payables/${id}` }: InboundNotesPageProps = {}) {\n const [view, setView] = useState<View>(viewFromLocation)\n\n const go = useCallback((next: View) => {\n setView(next)\n if (typeof window === 'undefined') return\n const path = pathOf(next)\n if (window.location.hash === path) return\n const empilhado = (window.history.state as { inboundNotes?: boolean } | null)?.inboundNotes\n if (next.kind !== 'note' && empilhado) {\n // Desempilha de verdade: trocar a URL à mão deixaria a conciliação no\n // histórico e o «voltar» do navegador entraria nela outra vez.\n window.history.back()\n return\n }\n if (next.kind === 'list') window.history.replaceState(null, '', path)\n else window.history.pushState(STACK_MARK, '', path)\n }, [])\n\n // O «voltar» do navegador é um gesto legítimo aqui: quem entrou na conciliação\n // por um deep link espera sair dela com ele.\n useEffect(() => {\n if (typeof window === 'undefined') return\n const onPop = () => {\n const next = viewFromLocation()\n setView(next)\n }\n window.addEventListener('popstate', onPop)\n window.addEventListener('hashchange', onPop)\n return () => {\n window.removeEventListener('popstate', onPop)\n window.removeEventListener('hashchange', onPop)\n }\n }, [])\n\n const fecharNota = useCallback(() => go({ kind: 'list' }), [go])\n\n // ENTRAR PELA OPERAÇÃO DE ESTOQUE. A linha de Movimentações sabe de que\n // OPERAÇÃO ela veio, não de que nota — o id da nota só o banco tem. Então o\n // link chega como `?operation=…` e esta página resolve, em vez de obrigar o\n // Estoque a consultar uma tabela do fiscal para desenhar um href.\n useEffect(() => {\n if (typeof window === 'undefined') return\n const op = window.location.hash.match(/[?&]operation=([0-9a-f-]{36})/i)?.[1]\n if (!op) return\n let vivo = true\n findInboxNoteByOperation(op)\n .then((id) => { if (vivo && id) go({ kind: 'note', id }) })\n .catch(() => { /* link velho ou nota de outra conta: fica na lista */ })\n return () => { vivo = false }\n }, [go])\n\n return (\n <>\n {/* A tela de fundo nunca é desmontada enquanto a nota está aberta: é ela\n que guarda o recorte, a busca e a rolagem a que a pessoa volta. */}\n <InboundNotesView onOpenNote={(id) => go({ kind: 'note', id })} />\n\n <Modal open={view.kind === 'note'} onOpenChange={(open) => { if (!open) fecharNota() }}>\n {view.kind === 'note' && (\n // `noPadding`: a conciliação desenha o próprio cabeçalho e o próprio\n // corpo — o título e o «Sugerir com IA» ficam fora da área que rola, e o\n // rodapé «Aceitar» precisa encostar nas bordas do modal.\n <ModalContent size=\"5xl\" noPadding className=\"sm:max-h-[90vh]\">\n <NoteReconcileView\n chrome=\"modal\"\n noteId={view.id}\n onBack={fecharNota}\n onOpenInvoice={payableRoute\n ? (invoiceId) => { window.location.hash = payableRoute(invoiceId) }\n : undefined}\n />\n </ModalContent>\n )}\n </Modal>\n </>\n )\n}\n\n/**\n * O componente que o registro de rotas monta. Ele recebe as rotas sem prop, então\n * a configuração do host entra por fechamento — e a fábrica mora aqui, num `.tsx`,\n * para o manifesto continuar sendo TypeScript sem JSX.\n */\nexport function makeInboundNotesRoute(options: InboundNotesPageProps = {}): () => React.ReactElement {\n return function InboundNotesRoute() {\n return <InboundNotesPage {...options} />\n }\n}\n","import React from 'react'\nimport {\n Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Select, SelectContent,\n SelectItem, SelectTrigger, SelectValue, Skeleton, Switch, toast,\n} from '@fayz-ai/ui'\nimport { getActiveTenantId, getSupabaseClientOptional, maskCpfCnpj } from '@fayz-ai/core'\nimport { adminNavigateTo } from '@fayz-ai/admin'\nimport { Check, Info, ShieldCheck, X } from 'lucide-react'\n\n/**\n * The \"Certificado\" and \"Emissão Fiscal\" tabs of the V1 company form, on the\n * unit detail page. One row per legal entity (017): two units with the same\n * CNPJ share it. `nfce_csc_token` is write-only — it is outside the SELECT\n * grant, and the screen reads `nfce_csc_token_set`.\n *\n * The A1 goes through `fiscalbr-certificate`, which forwards it to PlugNotas\n * without storing it and records holder and validity read from the file.\n */\n\nconst COLUMNS = [\n 'id', 'legal_entity_id',\n 'nfse_enabled', 'nfse_production', 'nfse_national', 'nfse_service_code_national', 'nfse_service_code_municipal',\n 'nfse_nbs_code', 'nfse_cnae', 'nfse_iss_rate', 'nfse_iss_taxation', 'nfse_ibscbs_cst', 'nfse_ibscbs_classification',\n 'nfse_simples_regime', 'nfse_net_value', 'nfse_additional_info',\n 'nfce_enabled', 'nfce_production', 'nfce_series', 'nfce_csc_id', 'nfce_csc_token_set', 'nfce_generic_item',\n 'certificate_cn', 'certificate_expires_at', 'certificate_uploaded_at',\n 'dfe_sync_enabled', 'dfe_last_sync_at', 'dfe_last_error', 'provider_synced_at',\n].join(', ')\n\ntype Settings = Record<string, any>\n\ninterface UnitItem {\n id?: string\n tenantId?: string\n legalEntityId?: string | null\n legalName?: string | null\n cnpj?: string | null\n stateRegistration?: string | null\n municipalRegistration?: string | null\n taxRegime?: string | null\n cnae?: string | null\n ibgeCityCode?: string | null\n}\n\nconst sb = () => getSupabaseClientOptional() as any\n\nasync function uploadCertificate(legalEntityId: string, file: File, password: string) {\n const buf = new Uint8Array(await file.arrayBuffer())\n let bin = ''\n for (let i = 0; i < buf.length; i++) bin += String.fromCharCode(buf[i])\n const { data, error } = await sb().functions.invoke('fiscalbr-certificate', {\n body: { legalEntityId, pfxBase64: btoa(bin), password, fileName: file.name, tenantId: getActiveTenantId() ?? null },\n })\n if (error) {\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* generic below */ }\n throw new Error(body?.error || error.message || 'Falha ao falar com o serviço fiscal.')\n }\n return data as { cn: string; expiresAt: string; warning: string | null }\n}\n\nfunction useEmitterSettings(legalEntityId: string | null | undefined) {\n const [row, setRow] = React.useState<Settings | null>(null)\n const [loading, setLoading] = React.useState(true)\n\n React.useEffect(() => {\n if (!legalEntityId) { setLoading(false); return }\n let alive = true\n void sb()?.from('plg_fiscalbr_emitter_settings').select(COLUMNS).eq('legal_entity_id', legalEntityId).maybeSingle()\n .then(({ data, error }: { data: Settings | null; error: { message: string } | null }) => {\n if (!alive) return\n if (error) toast.error('Não foi possível ler a configuração fiscal', { description: error.message })\n setRow(data ?? {})\n setLoading(false)\n })\n return () => { alive = false }\n }, [legalEntityId])\n\n const save = React.useCallback(async (tenantId: string, patch: Settings): Promise<boolean> => {\n if (!legalEntityId) return false\n const payload = { ...patch, tenant_id: tenantId, legal_entity_id: legalEntityId, updated_at: new Date().toISOString() }\n const { data, error } = await sb().from('plg_fiscalbr_emitter_settings')\n .upsert(payload, { onConflict: 'legal_entity_id' }).select(COLUMNS).single()\n if (error) {\n toast.error('Não foi possível salvar', { description: error.message })\n return false\n }\n setRow(data)\n return true\n }, [legalEntityId])\n\n return { row, loading, save, setRow }\n}\n\nfunction NeedsLegalEntity({ item, what }: { item: UnitItem; what: string }) {\n return (\n <Card>\n <CardContent className=\"flex flex-col items-start gap-3 py-6\">\n <p className=\"text-sm font-medium\">Falta o CNPJ desta unidade</p>\n <p className=\"text-sm text-muted-foreground\">\n {what} pertence à pessoa jurídica. Preencha a razão social e o CNPJ em Dados da empresa para configurar aqui.\n </p>\n <Button variant=\"outline\" onClick={() => adminNavigateTo(`/settings/locations/${item.id}/edit`)}>Preencher CNPJ</Button>\n </CardContent>\n </Card>\n )\n}\n\nfunction LoadingCard() {\n return (\n <Card>\n <CardContent className=\"space-y-3 py-6\">\n <Skeleton className=\"h-5 w-48\" />\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n </CardContent>\n </Card>\n )\n}\n\nfunction ToggleRow({ title, description, checked, onChange, disabled, children }: {\n title: string; description?: string; checked: boolean; onChange: (v: boolean) => void; disabled?: boolean; children?: React.ReactNode\n}) {\n return (\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium\">{title}</p>\n {description && <p className=\"text-xs text-muted-foreground\">{description}</p>}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {children}\n <Switch checked={checked} disabled={disabled} onCheckedChange={onChange} />\n </div>\n </div>\n )\n}\n\nfunction Field({ label, hint, children }: { label: string; hint?: string; children: React.ReactNode }) {\n return (\n <div className=\"space-y-1.5\">\n <span className=\"text-sm font-medium\">{label}</span>\n {children}\n {hint && <p className=\"text-xs text-muted-foreground\">{hint}</p>}\n </div>\n )\n}\n\n/** The closed state of a fiscal block: what is configured, and the button to change it. */\nfunction SummaryCard({ title, lines, badge, onConfigure }: {\n title: string\n lines: Array<{ label: string; value: string }>\n badge?: { text: string; tone: 'ok' | 'muted' | 'bad' }\n onConfigure: () => void\n}) {\n return (\n <Card>\n <CardHeader className=\"flex-row items-start justify-between gap-3 space-y-0\">\n <div className=\"min-w-0\">\n <CardTitle className=\"text-base\">{title}</CardTitle>\n <dl className=\"mt-2 grid gap-x-6 gap-y-1 text-sm\" style={{ gridTemplateColumns: 'auto 1fr' }}>\n {lines.map((l) => (\n <React.Fragment key={l.label}>\n <dt className=\"text-muted-foreground\">{l.label}</dt>\n <dd className=\"text-foreground\">{l.value}</dd>\n </React.Fragment>\n ))}\n </dl>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {badge && (\n <Badge\n variant={badge.tone === 'bad' ? 'destructive' : 'outline'}\n className={badge.tone === 'ok' ? 'border-emerald-500/40 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400' : badge.tone === 'muted' ? 'text-muted-foreground' : undefined}\n >\n {badge.text}\n </Badge>\n )}\n <Button variant=\"outline\" size=\"sm\" onClick={onConfigure}>Configurar</Button>\n </div>\n </CardHeader>\n </Card>\n )\n}\n\nconst fmtDateTime = (v?: string | null) => (v ? new Date(v).toLocaleString('pt-BR') : null)\n\n// ── Certificado ─────────────────────────────────────────────────────────────\n\nexport function UnitCertificateWidget({ item }: { item?: UnitItem }) {\n const { row, loading, save, setRow } = useEmitterSettings(item?.legalEntityId)\n const [open, setOpen] = React.useState(false)\n const [file, setFile] = React.useState<File | null>(null)\n const [password, setPassword] = React.useState('')\n const [sending, setSending] = React.useState(false)\n // An expired certificate is why someone landed here: open on the upload.\n const expiredNow = !!row?.certificate_expires_at && Date.parse(row.certificate_expires_at) < Date.now()\n React.useEffect(() => { if (expiredNow) setOpen(true) }, [expiredNow])\n if (!item?.id) return null\n if (!item.legalEntityId) return <NeedsLegalEntity item={item} what=\"O certificado digital\" />\n if (loading || !row) return <LoadingCard />\n\n const expires = row.certificate_expires_at ? new Date(row.certificate_expires_at) : null\n const expired = expires ? expires.getTime() < Date.now() : false\n const hasCertificate = !!row.certificate_uploaded_at\n\n if (!open) {\n return (\n <SummaryCard\n title=\"Certificado digital e DANFes\"\n lines={[\n { label: 'Certificado A1', value: hasCertificate\n ? [row.certificate_cn, expires ? `válido até ${expires.toLocaleDateString('pt-BR')}` : null].filter(Boolean).join(' · ') || 'Enviado'\n : 'Nenhum certificado enviado' },\n { label: 'Receber DANFes', value: row.dfe_sync_enabled ? `Ligado · última sincronização ${fmtDateTime(row.dfe_last_sync_at) ?? 'nunca'}` : 'Desligado' },\n ]}\n badge={hasCertificate ? { text: expired ? 'Vencido' : 'Ativo', tone: expired ? 'bad' : 'ok' } : { text: 'Sem certificado', tone: 'muted' }}\n onConfigure={() => setOpen(true)}\n />\n )\n }\n\n return (\n <Card>\n <CardHeader className=\"flex-row items-start justify-between gap-3 space-y-0\">\n <CardTitle className=\"text-base\">Certificado digital e DANFes</CardTitle>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setOpen(false)}>Fechar</Button>\n </CardHeader>\n <CardContent className=\"space-y-5\">\n <ToggleRow\n title=\"Receber DANFes automaticamente\"\n description=\"Busca por hora as NF-e emitidas contra o CNPJ desta empresa.\"\n checked={!!row.dfe_sync_enabled}\n onChange={(v) => void save(item.tenantId!, { dfe_sync_enabled: v }).then((ok) => ok && toast.success(v ? 'Recepção ligada' : 'Recepção desligada'))}\n />\n\n <div className=\"rounded-md border bg-muted/40 p-3 text-sm\">\n <p className=\"mb-1.5 flex items-center gap-1.5 font-medium\"><Info className=\"h-4 w-4\" /> Como funciona</p>\n <ul className=\"ml-5 list-disc space-y-1 text-muted-foreground\">\n <li><strong className=\"text-foreground\">O que faz:</strong> consulta a SEFAZ e lista as NF-e emitidas contra o CNPJ, para você aceitar ou rejeitar e gerar entrada de estoque ou conta a pagar.</li>\n <li><strong className=\"text-foreground\">Requer certificado digital A1</strong> (.pfx) válido desta empresa. O arquivo vai direto ao serviço fiscal e não fica armazenado no nosso sistema.</li>\n <li><strong className=\"text-foreground\">Não faz manifestação na SEFAZ</strong> (ciência, confirmação, desconhecimento) nem emite NF-e.</li>\n </ul>\n </div>\n\n <div className=\"rounded-md border p-4 space-y-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <p className=\"flex items-center gap-1.5 text-sm font-medium\"><ShieldCheck className=\"h-4 w-4\" /> Certificado digital A1</p>\n <p className=\"text-xs text-muted-foreground\">\n {hasCertificate\n ? [row.certificate_cn, expires ? `válido até ${expires.toLocaleDateString('pt-BR')}` : null].filter(Boolean).join(' · ')\n : 'Nenhum certificado enviado'}\n </p>\n </div>\n {hasCertificate && <Badge variant={expired ? 'destructive' : 'secondary'}>{expired ? 'Vencido' : 'Ativo'}</Badge>}\n </div>\n <div className=\"fz-container\">\n <div className=\"fz-fields fz-fields-2 gap-4\">\n <Field label=\"Arquivo (.pfx)\">\n <Input type=\"file\" accept=\".pfx,.p12,application/x-pkcs12\" data-testid=\"certificate-file\"\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFile(e.target.files?.[0] ?? null)} />\n </Field>\n <Field label=\"Senha do certificado\">\n <Input type=\"password\" autoComplete=\"new-password\" name=\"pfx-password\" value={password} data-testid=\"certificate-password\"\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPassword(e.target.value)} />\n </Field>\n </div>\n </div>\n <div className=\"flex justify-end\">\n <Button\n size=\"sm\"\n data-testid=\"certificate-send\"\n disabled={!file || !password || sending}\n onClick={() => {\n if (!file) return\n setSending(true)\n void uploadCertificate(item.legalEntityId!, file, password)\n .then((res) => {\n setRow((r: Settings | null) => ({ ...(r ?? {}), certificate_cn: res.cn, certificate_expires_at: res.expiresAt,\n certificate_uploaded_at: new Date().toISOString(), dfe_sync_enabled: true, dfe_last_error: res.warning ?? null }))\n setFile(null); setPassword('')\n if (res.warning) toast.warning('Certificado enviado, com um aviso', { description: res.warning })\n else toast.success(`Certificado enviado · válido até ${new Date(res.expiresAt).toLocaleDateString('pt-BR')}`)\n })\n .catch((e: Error) => toast.error('Não foi possível enviar o certificado', { description: e.message }))\n .finally(() => setSending(false))\n }}\n >\n {sending ? 'Enviando…' : hasCertificate ? 'Atualizar certificado' : 'Enviar certificado'}\n </Button>\n </div>\n {row.dfe_last_error && <p className=\"text-xs text-destructive\">{row.dfe_last_error}</p>}\n </div>\n\n <p className=\"text-xs text-muted-foreground\">\n Última sincronização: {fmtDateTime(row.dfe_last_sync_at) ?? 'nunca'}\n </p>\n </CardContent>\n </Card>\n )\n}\n\n// ── Emissão fiscal ──────────────────────────────────────────────────────────\n\nconst ISS_TAXATION = [\n { value: '6', label: 'Tributável no município' },\n { value: '7', label: 'Tributável fora do município' },\n { value: '1', label: 'Isento' },\n { value: '2', label: 'Imune' },\n]\nconst SIMPLES_REGIME = [\n { value: 'auto', label: 'Automático (1 — tudo pelo Simples; excesso → 3)' },\n { value: '1', label: '1 — Federais e ISS pelo Simples (DAS)' },\n { value: '2', label: '2 — Federais pelo Simples; ISS pela NFS-e (lei municipal)' },\n { value: '3', label: '3 — Federais e ISS fora do Simples (sublimite)' },\n]\n\nfunction EnvSelect({ value, onChange, disabled }: { value: boolean; onChange: (prod: boolean) => void; disabled?: boolean }) {\n return (\n <Select value={value ? 'prod' : 'hom'} onValueChange={(v) => onChange(v === 'prod')} disabled={disabled}>\n <SelectTrigger className=\"h-8 w-36\"><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"hom\">Homologação</SelectItem>\n <SelectItem value=\"prod\">Produção</SelectItem>\n </SelectContent>\n </Select>\n )\n}\n\nexport function UnitFiscalWidget({ item }: { item?: UnitItem }) {\n const { row, loading, save } = useEmitterSettings(item?.legalEntityId)\n const [draft, setDraft] = React.useState<Settings>({})\n const [cscToken, setCscToken] = React.useState('')\n const [saving, setSaving] = React.useState(false)\n const [open, setOpen] = React.useState(false)\n\n React.useEffect(() => { if (row) setDraft(row) }, [row])\n\n if (!item?.id) return null\n if (!item.legalEntityId) return <NeedsLegalEntity item={item} what=\"A emissão fiscal\" />\n if (loading || !row) return <LoadingCard />\n\n const set = (patch: Settings) => setDraft((d) => ({ ...d, ...patch }))\n const generic = (draft.nfce_generic_item ?? {}) as { ncm?: string; cfop?: string; csosn?: string }\n const setGeneric = (patch: Partial<typeof generic>) => set({ nfce_generic_item: { ...generic, ...patch } })\n const isSimples = (item.taxRegime ?? '').startsWith('simples')\n\n const checks = [\n { ok: !!row.certificate_uploaded_at && !(row.certificate_expires_at && Date.parse(row.certificate_expires_at) < Date.now()), label: 'Certificado A1 válido' },\n // Only what the switched-on documents need: NFS-e off does not block a restaurant that issues NFC-e.\n ...(draft.nfse_enabled ? [\n { ok: !!draft.nfse_service_code_national, label: 'Código de tributação do serviço' },\n { ok: draft.nfse_iss_rate != null && draft.nfse_iss_rate !== '', label: 'Alíquota de ISS' },\n ] : []),\n ...(draft.nfce_enabled ? [\n { ok: !!item.stateRegistration && !!draft.nfce_csc_id && (!!row.nfce_csc_token_set || !!cscToken), label: 'IE + CSC (NFC-e)' },\n ] : []),\n { ok: !!row.provider_synced_at, label: 'Empresa registrada para emitir' },\n ]\n const ready = (draft.nfse_enabled || draft.nfce_enabled) && checks.every((c) => c.ok)\n\n const onSave = async () => {\n setSaving(true)\n const { id: _id, legal_entity_id: _le, nfce_csc_token_set: _t, certificate_cn: _cn, certificate_expires_at: _e,\n certificate_uploaded_at: _u, dfe_last_sync_at: _d, provider_synced_at: _p, ...patch } = draft\n const issRate = patch.nfse_iss_rate === '' || patch.nfse_iss_rate == null ? null : Number(String(patch.nfse_iss_rate).replace(',', '.'))\n const ok = await save(item.tenantId!, {\n ...patch,\n nfse_iss_rate: Number.isFinite(issRate as number) ? issRate : null,\n nfse_iss_taxation: patch.nfse_iss_taxation ? Number(patch.nfse_iss_taxation) : null,\n nfse_simples_regime: patch.nfse_simples_regime && patch.nfse_simples_regime !== 'auto' ? Number(patch.nfse_simples_regime) : null,\n nfce_series: patch.nfce_series ? Number(patch.nfce_series) : null,\n ...(cscToken ? { nfce_csc_token: cscToken } : {}),\n })\n setSaving(false)\n if (ok) { setCscToken(''); setOpen(false); toast.success('Configuração fiscal salva') }\n }\n\n if (!open) {\n const env = (prod: boolean) => (prod ? 'Produção' : 'Homologação')\n return (\n <SummaryCard\n title=\"Emissão fiscal (NFS-e / NFC-e)\"\n lines={[\n { label: 'NFS-e', value: row.nfse_enabled ? `Ligada · ${env(!!row.nfse_production)}` : 'Desligada' },\n { label: 'NFC-e', value: row.nfce_enabled ? `Ligada · ${env(!!row.nfce_production)}${row.nfce_series ? ` · série ${row.nfce_series}` : ''}` : 'Desligada' },\n ]}\n badge={ready ? { text: 'Pronto para emitir', tone: 'ok' } : { text: 'Configuração incompleta', tone: 'muted' }}\n onConfigure={() => setOpen(true)}\n />\n )\n }\n\n return (\n <Card>\n <CardHeader className=\"flex-row items-start justify-between gap-3 space-y-0\">\n <div>\n <CardTitle className=\"text-base\">Emissão fiscal (NFS-e / NFC-e)</CardTitle>\n <CardDescription>{item.legalName ?? 'Pessoa jurídica'}{item.cnpj ? ` · CNPJ ${maskCpfCnpj(item.cnpj)}` : ''}</CardDescription>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant={ready ? 'default' : 'secondary'}>\n {ready ? 'Pronto para emitir' : 'Configuração incompleta'}\n </Badge>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { setDraft(row); setCscToken(''); setOpen(false) }}>Cancelar</Button>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-5\">\n <section className=\"space-y-4 rounded-md border p-4\">\n <ToggleRow title=\"NFS-e — Nota de Serviço\" description=\"Padrão nacional (RJ, Vitória e demais aderentes)\"\n checked={!!draft.nfse_enabled} onChange={(v) => set({ nfse_enabled: v })}>\n <EnvSelect value={!!draft.nfse_production} onChange={(v) => set({ nfse_production: v })} disabled={!draft.nfse_enabled} />\n </ToggleRow>\n {draft.nfse_enabled && (\n <div className=\"fz-container space-y-4\">\n <div className=\"fz-fields fz-fields-2 gap-4\">\n <Field label=\"Cód. tributação nacional\"><Input value={draft.nfse_service_code_national ?? ''} placeholder=\"ex.: 06.02.01\" onChange={(e) => set({ nfse_service_code_national: e.target.value })} /></Field>\n <Field label=\"Cód. tributação municipal\"><Input value={draft.nfse_service_code_municipal ?? ''} placeholder=\"ex.: 001\" onChange={(e) => set({ nfse_service_code_municipal: e.target.value })} /></Field>\n <Field label=\"Código NBS\"><Input value={draft.nfse_nbs_code ?? ''} placeholder=\"ex.: 1.2602.90.00\" onChange={(e) => set({ nfse_nbs_code: e.target.value })} /></Field>\n <Field label=\"CNAE do serviço\"><Input value={draft.nfse_cnae ?? ''} placeholder=\"ex.: 9602-5/02\" onChange={(e) => set({ nfse_cnae: e.target.value })} /></Field>\n <Field label=\"Alíquota ISS (%)\"><Input inputMode=\"decimal\" value={draft.nfse_iss_rate ?? ''} placeholder=\"ex.: 5\" onChange={(e) => set({ nfse_iss_rate: e.target.value })} /></Field>\n <Field label=\"Tributação ISS\">\n <Select value={draft.nfse_iss_taxation != null ? String(draft.nfse_iss_taxation) : undefined} onValueChange={(v) => set({ nfse_iss_taxation: v })}>\n <SelectTrigger><SelectValue placeholder=\"Selecione\" /></SelectTrigger>\n <SelectContent>{ISS_TAXATION.map((o) => <SelectItem key={o.value} value={o.value}>{o.label}</SelectItem>)}</SelectContent>\n </Select>\n </Field>\n <Field label=\"IBS/CBS — CST\"><Input value={draft.nfse_ibscbs_cst ?? ''} placeholder=\"ex.: 000\" onChange={(e) => set({ nfse_ibscbs_cst: e.target.value })} /></Field>\n <Field label=\"IBS/CBS — Classificação\"><Input value={draft.nfse_ibscbs_classification ?? ''} placeholder=\"ex.: 000001\" onChange={(e) => set({ nfse_ibscbs_classification: e.target.value })} /></Field>\n {isSimples && (\n <Field label=\"Apuração dos tributos no Simples\">\n <Select value={draft.nfse_simples_regime != null ? String(draft.nfse_simples_regime) : 'auto'} onValueChange={(v) => set({ nfse_simples_regime: v })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>{SIMPLES_REGIME.map((o) => <SelectItem key={o.value} value={o.value}>{o.label}</SelectItem>)}</SelectContent>\n </Select>\n </Field>\n )}\n </div>\n <ToggleRow title=\"Emitir pelo valor líquido\" checked={!!draft.nfse_net_value} onChange={(v) => set({ nfse_net_value: v })} />\n <Field label=\"Informações complementares da nota\">\n <Input value={draft.nfse_additional_info ?? ''} placeholder=\"ex.: Totais Aproximados dos Tributos cfe. Lei nº 12.741/2012…\" onChange={(e) => set({ nfse_additional_info: e.target.value })} />\n </Field>\n </div>\n )}\n </section>\n\n <section className=\"space-y-4 rounded-md border p-4\">\n <ToggleRow title=\"NFC-e — Cupom do Consumidor\" description=\"Produtos / comanda\"\n checked={!!draft.nfce_enabled} onChange={(v) => set({ nfce_enabled: v })}>\n <EnvSelect value={!!draft.nfce_production} onChange={(v) => set({ nfce_production: v })} disabled={!draft.nfce_enabled} />\n </ToggleRow>\n {draft.nfce_enabled && (\n <div className=\"fz-container space-y-4\">\n <div className=\"fz-fields fz-fields-2 gap-4\">\n <Field label=\"Série\"><Input inputMode=\"numeric\" value={draft.nfce_series ?? ''} onChange={(e) => set({ nfce_series: e.target.value.replace(/\\D/g, '') })} /></Field>\n <Field label=\"CSC — ID\"><Input value={draft.nfce_csc_id ?? ''} onChange={(e) => set({ nfce_csc_id: e.target.value })} /></Field>\n </div>\n <Field label=\"CSC — Token\" hint=\"O CSC (id numérico + token) é gerado no portal da SEFAZ do estado — não é o login de nenhum sistema.\">\n <Input type=\"password\" value={cscToken} placeholder={row.nfce_csc_token_set ? '•••••••• (configurado — digite para trocar)' : ''} onChange={(e) => setCscToken(e.target.value)} />\n </Field>\n <div className=\"fz-fields fz-fields-2 gap-4\">\n <Field label=\"Item genérico — NCM\"><Input value={generic.ncm ?? ''} onChange={(e) => setGeneric({ ncm: e.target.value })} /></Field>\n <Field label=\"Item genérico — CFOP\"><Input value={generic.cfop ?? ''} onChange={(e) => setGeneric({ cfop: e.target.value })} /></Field>\n <Field label=\"Item genérico — CSOSN/CST\"><Input value={generic.csosn ?? ''} onChange={(e) => setGeneric({ csosn: e.target.value })} /></Field>\n </div>\n </div>\n )}\n </section>\n\n <ul className=\"flex flex-wrap gap-2\">\n {checks.map((c) => (\n <li key={c.label}>\n <Badge variant=\"outline\" className={c.ok ? 'gap-1 border-emerald-500/40 text-emerald-700 dark:text-emerald-400' : 'gap-1 text-muted-foreground'}>\n {c.ok ? <Check className=\"h-3 w-3\" /> : <X className=\"h-3 w-3\" />}{c.label}\n </Badge>\n </li>\n ))}\n </ul>\n\n <div className=\"flex flex-wrap items-center justify-end gap-3\">\n <p className=\"mr-auto text-xs text-muted-foreground\">\n Registrar a empresa no emissor ainda não está disponível nesta versão — a configuração fica salva para quando estiver.\n </p>\n <Button onClick={() => void onSave()} disabled={saving}>{saving ? 'Salvando…' : 'Salvar configuração'}</Button>\n </div>\n </CardContent>\n </Card>\n )\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport { getActiveTenantId } from '@fayz-ai/admin'\nimport type { IssuedNote, IssuedNoteEvent } from '../lib/issued-note'\n\nfunction sb() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not initialized')\n return supabase\n}\n\nconst NOTE_COLUMNS = `document_id, model, status, environment, number, series, access_key,\n verification_code, provider_integration_id, total_value, recipient_snapshot, rejection_payload,\n created_at, authorized_at, cancelled_at, cancel_reason`\n\nfunction toNote(r: any): IssuedNote {\n return {\n documentId: r.document_id,\n model: r.model,\n status: r.status,\n environment: r.environment ?? null,\n number: r.number ?? null,\n series: r.series ?? null,\n accessKey: r.access_key ?? null,\n verificationCode: r.verification_code ?? null,\n integrationId: r.provider_integration_id ?? null,\n totalValue: r.total_value == null ? null : Number(r.total_value),\n recipient: r.recipient_snapshot ?? null,\n rejection: r.rejection_payload ?? null,\n createdAt: r.created_at,\n authorizedAt: r.authorized_at ?? null,\n cancelledAt: r.cancelled_at ?? null,\n cancelReason: r.cancel_reason ?? null,\n }\n}\n\n/**\n * The notes of a financial invoice, reached through its order: a note covers\n * orders (N:N `plg_fiscalbr_document_orders`) or was issued straight from one\n * (`plg_fiscalbr_documents.order_id`, the restaurant tab).\n */\nexport async function listInvoiceNotes(invoiceId: string): Promise<IssuedNote[]> {\n const db = sb()\n const { data: inv, error: invError } = await db.from('plg_financial_invoices')\n .select('order_id').eq('id', invoiceId).maybeSingle()\n if (invError) throw invError\n const orderId: string | null = inv?.order_id ?? null\n if (!orderId) return []\n\n const [linked, direct] = await Promise.all([\n db.from('plg_fiscalbr_document_orders').select('document_id').eq('order_id', orderId),\n db.from('plg_fiscalbr_documents').select(NOTE_COLUMNS).eq('order_id', orderId),\n ])\n if (linked.error) throw linked.error\n if (direct.error) throw direct.error\n\n const byId = new Map<string, IssuedNote>()\n for (const r of direct.data ?? []) byId.set(r.document_id, toNote(r))\n const missing = (linked.data ?? []).map((r: any) => r.document_id as string).filter((id: string) => !byId.has(id))\n if (missing.length) {\n const { data, error } = await db.from('plg_fiscalbr_documents').select(NOTE_COLUMNS).in('document_id', missing)\n if (error) throw error\n for (const r of data ?? []) byId.set(r.document_id, toNote(r))\n }\n return [...byId.values()].sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n}\n\nexport async function listNoteEvents(documentId: string): Promise<IssuedNoteEvent[]> {\n const { data, error } = await sb().from('plg_fiscalbr_document_events')\n .select('id, event_type, status, justification, created_at')\n .eq('document_id', documentId)\n .order('created_at', { ascending: false })\n .limit(30)\n if (error) throw error\n return (data ?? []).map((e: any) => ({\n id: e.id, eventType: e.event_type, status: e.status ?? null,\n justification: e.justification ?? null, createdAt: e.created_at,\n }))\n}\n\nasync function callIssuer(body: Record<string, unknown>): Promise<any> {\n // Edge functions never get the tenant header (client.ts); it rides in the body.\n const { data, error } = await sb().functions.invoke('fiscalbr-plugnotas', { body: { ...body, tenantId: getActiveTenantId() } })\n if (error) {\n // The function's own message lives in the response body, not in `error.message`.\n const ctx = (error as any)?.context\n let message = error.message || 'Falha ao falar com o emissor fiscal.'\n if (ctx && typeof ctx.json === 'function') {\n try { const b = await ctx.json(); if (b?.error) message = String(b.error) } catch { /* keep generic */ }\n }\n throw new Error(message)\n }\n if (data?.error) throw new Error(String(data.error))\n return data\n}\n\n/** Asks the provider for the note's current state; returns the stored status. */\nexport async function refreshNote(documentId: string): Promise<string> {\n const r = await callIssuer({ action: 'poll_status', document_id: documentId })\n return String(r?.status ?? '')\n}\n\nexport async function cancelNote(documentId: string, justification: string, code?: string): Promise<string> {\n const r = await callIssuer({ action: 'cancel', document_id: documentId, justification, code })\n return String(r?.status ?? '')\n}\n\nexport async function fetchNotePdf(documentId: string): Promise<Blob> {\n const data = await callIssuer({ action: 'get_pdf', document_id: documentId })\n if (!(data instanceof Blob)) throw new Error('O emissor não devolveu um PDF.')\n return new Blob([data], { type: 'application/pdf' })\n}\n","// Vocabulary and reading rules for an issued note (plg_fiscalbr_documents),\n// shared by every screen that shows one.\n\nexport type IssuedNoteModel = 'nfse' | 'nfce' | 'nfe'\nexport type IssuedNoteStatus =\n | 'draft' | 'processing' | 'authorized' | 'rejected' | 'error' | 'cancelled' | 'substituted' | 'denied'\n\nexport interface IssuedNote {\n documentId: string\n model: IssuedNoteModel\n status: IssuedNoteStatus\n environment: 'producao' | 'homologacao' | null\n number: string | null\n series: string | null\n accessKey: string | null\n verificationCode: string | null\n integrationId: string | null\n totalValue: number | null\n recipient: Record<string, unknown> | null\n rejection: unknown\n createdAt: string\n authorizedAt: string | null\n cancelledAt: string | null\n cancelReason: string | null\n}\n\nexport interface IssuedNoteEvent {\n id: string\n eventType: string\n status: string | null\n justification: string | null\n createdAt: string\n}\n\nexport const MODEL_LABEL: Record<IssuedNoteModel, string> = { nfse: 'NFS-e', nfce: 'NFC-e', nfe: 'NF-e' }\n\nexport type StatusTone = 'success' | 'warning' | 'danger' | 'muted'\n\nexport const STATUS_META: Record<IssuedNoteStatus, { label: string; tone: StatusTone }> = {\n authorized: { label: 'Autorizada', tone: 'success' },\n draft: { label: 'Enviando', tone: 'warning' },\n processing: { label: 'Processando', tone: 'warning' },\n rejected: { label: 'Rejeitada', tone: 'danger' },\n denied: { label: 'Denegada', tone: 'danger' },\n error: { label: 'Erro', tone: 'danger' },\n cancelled: { label: 'Cancelada', tone: 'muted' },\n substituted: { label: 'Substituída', tone: 'muted' },\n}\n\nexport const EVENT_LABEL: Record<string, string> = {\n emissao: 'Emissão enviada',\n consulta: 'Consulta de status',\n cancelamento: 'Cancelamento',\n substituicao: 'Substituição',\n cce: 'Carta de correção',\n inutilizacao: 'Inutilização',\n webhook: 'Notificação do emissor fiscal',\n erro: 'Erro',\n}\n\n// Provider/V1 words on the trail. Internal steps (nfce_start…) have no\n// translation on purpose: they show nothing rather than the raw code.\nconst EVENT_STATUS_LABEL: Record<string, string> = {\n CRIADO: 'Enviando', PROCESSANDO: 'Processando', CONCLUIDO: 'Autorizada', REJEITADO: 'Rejeitada',\n DENEGADO: 'Denegada', CANCELADO: 'Cancelada', SUBSTITUIDO: 'Substituída', SOLICITADO: 'Solicitado', ERRO: 'Erro',\n}\n\nexport function eventStatusLabel(status: string | null): string | null {\n return status ? EVENT_STATUS_LABEL[status.toUpperCase()] ?? null : null\n}\n\nconst IN_FLIGHT: IssuedNoteStatus[] = ['draft', 'processing']\nconst WITHOUT_EFFECT: IssuedNoteStatus[] = ['rejected', 'denied', 'error', 'cancelled', 'substituted']\n\nexport function isWithoutEffect(status: IssuedNoteStatus): boolean {\n return WITHOUT_EFFECT.includes(status)\n}\n\n/** A cancellation in progress sits in `processing` exactly like an issue in progress. */\nexport function statusLabel(note: Pick<IssuedNote, 'status' | 'cancelledAt'>): string {\n if (IN_FLIGHT.includes(note.status) && note.cancelledAt) return 'Cancelamento solicitado'\n return (STATUS_META[note.status] ?? STATUS_META.error).label\n}\n\nexport interface NotesSummary {\n hasValid: boolean\n withoutEffect: number\n inFlight: number\n /** Only an AUTHORIZED test note misleads; a rejected one in homologação fools nobody. */\n validIsTest: boolean\n}\n\nexport function summarizeNotes(notes: Pick<IssuedNote, 'status' | 'environment'>[]): NotesSummary {\n const s: NotesSummary = { hasValid: false, withoutEffect: 0, inFlight: 0, validIsTest: false }\n for (const n of notes) {\n if (n.status === 'authorized') {\n s.hasValid = true\n if (n.environment === 'homologacao') s.validIsTest = true\n } else if (IN_FLIGHT.includes(n.status)) s.inFlight += 1\n else if (WITHOUT_EFFECT.includes(n.status)) s.withoutEffect += 1\n }\n return s\n}\n\nexport type NotesButtonState = 'none' | 'authorized' | 'processing' | 'failed-only'\n\nexport function notesButtonState(s: NotesSummary): NotesButtonState {\n if (s.hasValid) return 'authorized'\n if (s.inFlight > 0) return 'processing'\n if (s.withoutEffect > 0) return 'failed-only'\n return 'none'\n}\n\n// The SEFAZ message says what is wrong, never what to do. These codes each cost\n// a full diagnosis in the V1 (measured on tenant 1, 23-09-2026), so the hint\n// travels with the message.\nconst SEFAZ_HINTS: Array<[string, string]> = [\n ['E0120', 'no padrão nacional a Inscrição Municipal é opcional (a nota identifica pelo CNPJ). '\n + 'Apague a IM na configuração fiscal da unidade e emita de novo.'],\n ['E0312', 'geralmente falta o CÓDIGO DE TRIBUTAÇÃO DO MUNICÍPIO (3 dígitos) na configuração '\n + 'fiscal da unidade — não o nacional. Cada prefeitura tem a sua tabela; confirme o código '\n + 'com a contabilidade.'],\n ['E0314', 'o código de tributação do município não existe na tabela daquela prefeitura. '\n + 'Confirme o valor com a contabilidade da unidade — ele não é o mesmo em todo município. '\n + 'Fora do Rio de Janeiro, o normal é deixar esse campo VAZIO.'],\n ['E0084', 'o CNPJ não consta como estabelecido nesse município no cadastro nacional. '\n + 'Isso se resolve FORA do sistema: a empresa precisa ter inscrição municipal ativa na '\n + 'prefeitura e o endereço do CNPJ na Receita Federal apontando para o mesmo município. '\n + 'Fale com a contabilidade — não há o que ajustar aqui.'],\n]\n\nconst FIELD_LABELS: Record<string, string> = {\n 'prestador.cpfCnpj': 'CNPJ do emitente',\n 'tomador.cpfCnpj': 'CPF/CNPJ do cliente',\n 'tomador.razaoSocial': 'Nome do cliente',\n 'tomador.endereco.cep': 'CEP do cliente',\n 'tomador.endereco.codigoCidade': 'Município do cliente',\n 'servico.codigo': 'Código de tributação do serviço',\n 'servico.iss.aliquota': 'Alíquota de ISS',\n 'itens.ncm': 'NCM do produto',\n 'itens.cfop': 'CFOP do produto',\n 'pagamentos.meio': 'Forma de pagamento (tPag)',\n 'emitente.inscricaoMunicipal': 'Inscrição municipal',\n 'emitente.inscricaoEstadual': 'Inscrição estadual',\n}\n\nexport interface RejectionField { field: string; label: string; message: string }\n\n/** PlugNotas rejection payload ({error:{message,data:{fields}}}) → something a person can act on. */\nexport function explainRejection(rejection: unknown): { summary: string; fields: RejectionField[] } {\n if (!rejection) return { summary: 'Nota rejeitada sem detalhe do motivo.', fields: [] }\n const r = (Array.isArray(rejection) ? rejection[0] : rejection) as Record<string, any>\n const err = r?.error ?? r\n let message: string = String(err?.message || r?.mensagem || r?.motivo || 'Nota rejeitada.')\n // The national issuer embeds the reason as JSON inside the string.\n const embedded = message.match(/\\[\\s*\\{[\\s\\S]*\\}\\s*\\]/)\n if (embedded) {\n try {\n const arr = JSON.parse(embedded[0])\n const parts = (Array.isArray(arr) ? arr : [arr])\n .map((e: any) => [e.Codigo ?? e.codigo, e.Descricao ?? e.descricao ?? e.Mensagem ?? e.mensagem]\n .filter(Boolean).join(' — '))\n .filter(Boolean)\n if (parts.length) message = parts.join('; ')\n } catch { /* keep the raw message */ }\n }\n const hint = SEFAZ_HINTS.find(([code]) => message.includes(code))\n if (hint) message = `${message} — ${hint[1]}`\n\n const fieldsObj: Record<string, unknown> = err?.data?.fields ?? {}\n const fields = Object.entries(fieldsObj).map(([field, msg]) => {\n const normalized = field.replace(/\\[\\d+\\]/g, '').replace(/\\.\\d+\\./g, '.')\n return { field, label: FIELD_LABELS[normalized] ?? field, message: String(msg) }\n })\n return { summary: message, fields }\n}\n\nexport function recipientLabel(recipient: Record<string, unknown> | null): string {\n if (!recipient) return 'Consumidor final'\n if (recipient.consumidor) return 'Consumidor final'\n return String(recipient.razaoSocial ?? recipient.nome ?? recipient.cpfCnpj ?? 'Consumidor final')\n}\n","import React, { useCallback, useEffect, useState } from 'react'\nimport { AlertTriangle, CheckCircle2, ChevronDown, FileCheck2, FileText, Loader2, RefreshCw, XCircle } from 'lucide-react'\nimport {\n Badge, Button, Modal, ModalBody, ModalContent, ModalDescription, ModalHeader, ModalTitle, SegmentedControl, Skeleton,\n Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, toast,\n} from '@fayz-ai/ui'\nimport { usePermissionOptional } from '@fayz-ai/admin'\nimport { cancelNote, fetchNotePdf, listInvoiceNotes, listNoteEvents, refreshNote } from '../data/issued'\nimport {\n EVENT_LABEL, MODEL_LABEL, eventStatusLabel, STATUS_META, explainRejection, isWithoutEffect, notesButtonState,\n recipientLabel, statusLabel, summarizeNotes, type IssuedNote, type IssuedNoteEvent, type StatusTone,\n} from '../lib/issued-note'\nimport { describeError, formatCurrency } from '@fayz-ai/core'\n\nconst TONE_VARIANT: Record<StatusTone, 'success' | 'warning' | 'destructive' | 'default'> = {\n success: 'success', warning: 'warning', danger: 'destructive', muted: 'default',\n}\n\nconst dateTime = (v: string | null) => (v ? new Date(v).toLocaleString('pt-BR', { dateStyle: 'short', timeStyle: 'short' }) : '—')\n// The V1 kept only the day of authorization; a midnight here is \"no time known\", not 00:00.\nconst dayOrDateTime = (v: string | null) => {\n if (!v) return '—'\n const d = new Date(v)\n return d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0\n ? d.toLocaleDateString('pt-BR')\n : dateTime(v)\n}\nconst money = (v: number | null) => (v == null ? '—' : formatCurrency(v))\n\nfunction buttonHint(s: ReturnType<typeof summarizeNotes>): string {\n const parts = [s.hasValid ? 'Notas fiscais desta conta — há uma nota válida' : 'Notas fiscais desta conta']\n if (s.withoutEffect > 0) parts.push(`${s.withoutEffect} cancelada(s), rejeitada(s) ou com erro`)\n if (s.validIsTest) parts.push('a nota válida é de TESTE, sem valor fiscal')\n return parts.join(' · ')\n}\n\nexport interface InvoiceNotesButtonProps {\n invoiceId?: string\n direction?: string\n cancelled?: boolean\n}\n\n/** Header action of a receivable: the notes issued for it, as the V1's \"Nota Fiscal\" button. */\nexport function InvoiceNotesButton({ invoiceId, direction, cancelled }: InvoiceNotesButtonProps) {\n const [notes, setNotes] = useState<IssuedNote[] | null>(null)\n const [open, setOpen] = useState(false)\n const can = usePermissionOptional()\n // A cancelled invoice still lets a note be cancelled; only issuing stops there.\n const canCancel = can('financial', 'edit')\n\n const reload = useCallback(async () => {\n if (!invoiceId || direction !== 'credit') return\n try {\n setNotes(await listInvoiceNotes(invoiceId))\n } catch {\n // A fiscal read failing must not take the invoice screen down with it.\n setNotes((prev) => prev ?? [])\n }\n }, [invoiceId, direction])\n\n useEffect(() => { void reload() }, [reload])\n\n // Without emission in the V2 yet, an empty central would only say \"nothing here\".\n if (!notes || notes.length === 0) return null\n\n const summary = summarizeNotes(notes)\n const state = notesButtonState(summary)\n\n return (\n <>\n <TooltipProvider delayDuration={200}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"relative h-9 gap-1.5\" aria-label=\"Nota Fiscal\" onClick={() => setOpen(true)}>\n {state === 'authorized' ? (\n <CheckCircle2 className=\"h-4 w-4 text-success\" aria-hidden />\n ) : state === 'processing' ? (\n <Loader2 className=\"h-4 w-4 animate-spin text-warning\" aria-hidden />\n ) : (\n <FileCheck2 className=\"h-4 w-4\" aria-hidden />\n )}\n {/* A phone header has room for the screen title or this label, not both. */}\n <span className=\"hidden sm:inline\">Nota Fiscal</span>\n {summary.withoutEffect > 0 && (\n <span className=\"inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 text-[10px] font-bold text-destructive-foreground\">\n {summary.withoutEffect}\n </span>\n )}\n {summary.validIsTest && (\n <span className=\"rounded border border-destructive px-1 text-[10px] font-semibold text-destructive\">TESTE</span>\n )}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{buttonHint(summary)}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n\n <Modal open={open} onOpenChange={setOpen}>\n <ModalContent size=\"2xl\">\n <ModalHeader>\n <ModalTitle>Nota Fiscal</ModalTitle>\n <ModalDescription>Notas emitidas para esta conta.</ModalDescription>\n </ModalHeader>\n <ModalBody className=\"gap-2\">\n {notes.map((n) => <NoteRow key={n.documentId} note={n} canCancel={canCancel} onChanged={reload} />)}\n <p className=\"pt-2 text-xs text-muted-foreground\">Emitir uma nota nova por aqui chega na próxima etapa.</p>\n </ModalBody>\n </ModalContent>\n </Modal>\n </>\n )\n}\n\nconst POLL_DELAYS = [3000, 5000, 8000, 12000, 20000]\n\nfunction NoteRow({ note, canCancel, onChanged }: { note: IssuedNote; canCancel: boolean; onChanged: () => Promise<void> }) {\n const [expanded, setExpanded] = useState(false)\n const [cancelling, setCancelling] = useState(false)\n const [busy, setBusy] = useState<'pdf' | 'refresh' | null>(null)\n const dimmed = isWithoutEffect(note.status)\n const tone = (STATUS_META[note.status] ?? STATUS_META.error).tone\n const usable = note.status === 'authorized' || note.status === 'cancelled'\n const inFlight = note.status === 'processing' || note.status === 'draft'\n const cancellable = canCancel && note.status === 'authorized' && !note.cancelledAt\n\n const openPdf = async () => {\n // Open synchronously: a window opened after an await is a blocked pop-up.\n const w = window.open('', '_blank')\n setBusy('pdf')\n try {\n const blob = await fetchNotePdf(note.documentId)\n const url = URL.createObjectURL(blob)\n if (w) w.location.href = url\n else window.location.assign(url)\n } catch (e) {\n w?.close()\n toast.error('PDF indisponível', { description: describeError(e) })\n } finally {\n setBusy(null)\n }\n }\n\n const refresh = async () => {\n setBusy('refresh')\n try {\n const status = await refreshNote(note.documentId)\n await onChanged()\n toast(status === note.status ? 'Ainda em processamento na SEFAZ/prefeitura' : `Nota ${statusLabel({ status: status as IssuedNote['status'], cancelledAt: null }).toLowerCase()}`)\n } catch (e) {\n toast.error('Não foi possível consultar', { description: describeError(e) })\n } finally {\n setBusy(null)\n }\n }\n\n return (\n <div className={`rounded-lg border ${dimmed ? 'bg-muted/30' : ''}`}>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n className=\"font-normal whitespace-normal justify-start flex w-full items-center gap-2 p-3 text-left\"\n onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}\n >\n <span className=\"flex min-w-0 flex-1 flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{MODEL_LABEL[note.model] ?? note.model}</Badge>\n {note.number && <span className=\"font-mono text-sm\">nº {note.number}</span>}\n <Badge variant={TONE_VARIANT[tone]}>{statusLabel(note)}</Badge>\n {note.environment === 'homologacao' && (\n <span className=\"rounded border border-destructive px-1 text-[10px] font-semibold text-destructive\">TESTE</span>\n )}\n <span className=\"ml-auto text-xs tabular-nums text-muted-foreground\">{dateTime(note.createdAt)}</span>\n </span>\n <ChevronDown className={`h-4 w-4 shrink-0 text-muted-foreground transition-transform ${expanded ? 'rotate-180' : ''}`} aria-hidden />\n </Button>\n {note.cancelReason && !expanded && (\n <p className=\"flex items-start gap-1.5 px-3 pb-2 text-xs text-muted-foreground\">\n <AlertTriangle className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" aria-hidden />\n <span className=\"break-words\">Motivo: {note.cancelReason}</span>\n </p>\n )}\n\n {(usable || inFlight || note.cancelledAt) && !cancelling && (\n <div className=\"flex flex-wrap items-center gap-1.5 px-3 pb-3\">\n {usable && (\n <Button variant=\"outline\" size=\"sm\" className=\"h-7 text-xs\" disabled={busy === 'pdf'} onClick={openPdf}>\n {busy === 'pdf' ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden /> : <FileText className=\"h-3.5 w-3.5\" aria-hidden />}\n PDF\n </Button>\n )}\n {(inFlight || (note.cancelledAt && note.status === 'authorized')) && (\n <Button variant=\"outline\" size=\"sm\" className=\"h-7 text-xs\" disabled={busy === 'refresh'} onClick={refresh}>\n {busy === 'refresh' ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden /> : <RefreshCw className=\"h-3.5 w-3.5\" aria-hidden />}\n Atualizar\n </Button>\n )}\n {cancellable && (\n <Button variant=\"ghost\" size=\"sm\" className=\"ml-auto h-7 text-xs text-destructive hover:text-destructive\" onClick={() => setCancelling(true)}>\n <XCircle className=\"h-3.5 w-3.5\" aria-hidden /> Cancelar nota\n </Button>\n )}\n </div>\n )}\n\n {cancelling && (\n <CancelNotePanel note={note} onClose={() => setCancelling(false)} onDone={async () => { setCancelling(false); await onChanged() }} />\n )}\n {expanded && <NoteDetails note={note} />}\n </div>\n )\n}\n\nconst NFSE_REASONS = [\n { value: '1', label: 'Erro na emissão' },\n { value: '2', label: 'Serviço não prestado' },\n { value: '9', label: 'Outros' },\n] as const\n\n/** Inline, not a dialog over the central (no modal stacking). */\nfunction CancelNotePanel({ note, onClose, onDone }: { note: IssuedNote; onClose: () => void; onDone: () => Promise<void> }) {\n const isNfse = note.model === 'nfse'\n const [code, setCode] = useState<'1' | '2' | '9'>('2')\n const [text, setText] = useState('')\n const [working, setWorking] = useState<'sending' | 'waiting' | null>(null)\n const [error, setError] = useState<string | null>(null)\n // SEFAZ requires 15 characters on NFC-e; the V1 asks 10 on NFS-e so the history keeps a real reason.\n const min = isNfse ? 10 : 15\n const missing = Math.max(0, min - text.trim().length)\n\n const confirm = async () => {\n setError(null)\n setWorking('sending')\n try {\n let status = await cancelNote(note.documentId, text.trim(), isNfse ? code : undefined)\n // City halls confirm later; follow for a while, as the V1 does.\n setWorking('waiting')\n for (const delay of POLL_DELAYS) {\n if (status === 'cancelled' || status === 'authorized') break\n await new Promise((r) => setTimeout(r, delay))\n try { status = await refreshNote(note.documentId) } catch { /* transient */ }\n }\n if (status === 'cancelled') toast.success(`${MODEL_LABEL[note.model]} nº ${note.number ?? ''} cancelada`)\n else if (status === 'authorized') toast.error('A SEFAZ/prefeitura recusou o cancelamento', { description: 'A nota continua válida. Veja o histórico nos detalhes.' })\n else toast('Cancelamento solicitado', { description: 'A SEFAZ/prefeitura ainda está processando. Use «Atualizar» para conferir.' })\n await onDone()\n } catch (e) {\n setError(describeError(e))\n setWorking(null)\n }\n }\n\n return (\n <div className=\"space-y-3 border-t bg-destructive-soft/40 px-3 py-3\">\n <p className=\"text-sm font-semibold\">Cancelar {MODEL_LABEL[note.model]} {note.number ? `nº ${note.number}` : ''}</p>\n <p className=\"text-xs text-muted-foreground\">\n {isNfse\n ? 'O prazo de cancelamento da NFS-e é definido pelo município.'\n : 'O prazo de cancelamento da NFC-e é curto (em geral ~30 minutos após a autorização, conforme a UF). Fora do prazo, a SEFAZ recusa.'}\n {' '}Cancelar não pode ser desfeito.\n </p>\n {isNfse && (\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium\">Motivo</p>\n <SegmentedControl size=\"sm\" aria-label=\"Motivo do cancelamento\" options={NFSE_REASONS} value={code} onChange={setCode} />\n </div>\n )}\n <div className=\"space-y-1\">\n <label htmlFor={`cancel-${note.documentId}`} className=\"text-xs font-medium\">Justificativa</label>\n <textarea\n id={`cancel-${note.documentId}`}\n value={text}\n onChange={(e) => setText(e.target.value)}\n maxLength={255}\n rows={3}\n disabled={!!working}\n placeholder={isNfse ? 'Descreva o motivo…' : 'Ex.: Emissão em duplicidade por erro operacional'}\n className=\"w-full resize-y rounded-md border bg-background px-3 py-2 text-sm\"\n autoFocus\n />\n <p className=\"text-[11px] text-muted-foreground\">\n {missing > 0 ? `Faltam ${missing} caractere(s) — a justificativa vai para a SEFAZ/prefeitura.` : 'Vai para a SEFAZ/prefeitura junto do pedido.'}\n </p>\n </div>\n {error && (\n <p className=\"flex items-start gap-1.5 rounded-md border border-destructive/40 bg-destructive-soft p-2 text-xs text-destructive-soft-foreground\">\n <AlertTriangle className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" aria-hidden /> <span className=\"break-words\">{error}</span>\n </p>\n )}\n <div className=\"flex flex-wrap justify-end gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={onClose} disabled={!!working}>Voltar</Button>\n <Button variant=\"destructive\" size=\"sm\" onClick={confirm} disabled={!!working || missing > 0}>\n {working ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden /> : <XCircle className=\"h-3.5 w-3.5\" aria-hidden />}\n {working === 'waiting' ? 'Aguardando a SEFAZ/prefeitura…' : working ? 'Enviando…' : 'Confirmar cancelamento'}\n </Button>\n </div>\n </div>\n )\n}\n\nfunction NoteDetails({ note }: { note: IssuedNote }) {\n const [events, setEvents] = useState<IssuedNoteEvent[] | null>(null)\n useEffect(() => {\n let alive = true\n listNoteEvents(note.documentId).then((e) => { if (alive) setEvents(e) }).catch(() => { if (alive) setEvents([]) })\n return () => { alive = false }\n }, [note.documentId])\n\n const failed = ['rejected', 'denied', 'error'].includes(note.status)\n const rejection = failed ? explainRejection(note.rejection) : null\n const rows: Array<[string, React.ReactNode]> = [\n ['Referência', note.integrationId && <span className=\"break-all font-mono text-xs\">{note.integrationId}</span>],\n ['Chave de acesso', note.accessKey && <span className=\"break-all font-mono text-xs\">{note.accessKey}</span>],\n ['Código de verificação', note.verificationCode],\n ['Valor', money(note.totalValue)],\n ['Tomador', recipientLabel(note.recipient)],\n ['Criada em', dateTime(note.createdAt)],\n ['Autorizada em', note.authorizedAt && dayOrDateTime(note.authorizedAt)],\n ['Cancelada em', note.cancelledAt && `${dateTime(note.cancelledAt)}${note.cancelReason ? ` — ${note.cancelReason}` : ''}`],\n ]\n\n return (\n <div className=\"space-y-3 border-t px-3 py-3\">\n <dl className=\"text-sm\">\n {rows.filter(([, v]) => v).map(([label, value]) => (\n <div key={label} className=\"flex gap-3 border-b py-1.5 last:border-0\">\n <dt className=\"w-28 shrink-0 text-muted-foreground sm:w-36\">{label}</dt>\n <dd className=\"min-w-0 flex-1 break-words font-medium\">{value}</dd>\n </div>\n ))}\n </dl>\n\n {rejection && (\n <div className=\"space-y-1.5 rounded-md border border-destructive/40 bg-destructive-soft p-3\">\n <p className=\"text-sm font-semibold text-destructive-soft-foreground\">Por que foi rejeitada?</p>\n <p className=\"text-sm text-foreground\">{rejection.summary}</p>\n {rejection.fields.length > 0 && (\n <ul className=\"space-y-1 text-xs text-foreground\">\n {rejection.fields.map((f) => <li key={f.field}><span className=\"font-medium\">{f.label}:</span> {f.message}</li>)}\n </ul>\n )}\n </div>\n )}\n\n {events === null ? (\n <div className=\"space-y-1.5\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n ) : events.length > 0 && (\n <div>\n <p className=\"mb-1.5 text-sm font-semibold\">Histórico</p>\n <ul className=\"space-y-1\">\n {events.map((e) => (\n <li key={e.id} className=\"flex flex-wrap items-center gap-2 text-xs\">\n <span className=\"whitespace-nowrap tabular-nums text-muted-foreground\">{dateTime(e.createdAt)}</span>\n <Badge variant=\"outline\" className=\"text-[10px]\">{EVENT_LABEL[e.eventType] ?? 'Evento'}</Badge>\n {eventStatusLabel(e.status) && <span className=\"text-muted-foreground\">{eventStatusLabel(e.status)}</span>}\n {e.justification && <span className=\"min-w-0 truncate\">— {e.justification}</span>}\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n )\n}\n","import type { FinancialDataProvider } from '@fayz-ai/financial/data/provider'\nimport type { PlugNotasFinancialProviderOptions } from '../types'\n\ntype FiscalDocument = NonNullable<Awaited<ReturnType<NonNullable<FinancialDataProvider['getNotaById']>>>>\n\nfunction fiscalReader(provider: FinancialDataProvider) {\n if (!provider.getNotaById) throw new Error('PlugNotas requires fiscal document reads from Financial.')\n return provider.getNotaById.bind(provider)\n}\n\nasync function committed(read: (id: string) => Promise<FiscalDocument | null>, id: string) {\n const document = await read(id)\n if (!document) throw new Error('Fiscal document was not found after the server operation.')\n return document\n}\n\nfunction resultError(result: { status: string; message?: string }, document: FiscalDocument, fallback: string) {\n if (result.status !== 'error') return\n throw new Error(result.message?.trim() || document.errorMessage?.trim() || fallback)\n}\n\nfunction cancellationPending(metadata: Record<string, unknown> | undefined): boolean {\n const provider = metadata?.plugnotas\n if (!provider || typeof provider !== 'object' || Array.isArray(provider)) return false\n return (provider as Record<string, unknown>).cancellationPending === true\n}\n\nfunction artifactUrl(value: unknown): string {\n if (typeof value !== 'string' || !value.trim()) throw new Error('PlugNotas returned an invalid artifact URL.')\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n throw new Error('PlugNotas returned an invalid artifact URL.')\n }\n if (!['http:', 'https:'].includes(parsed.protocol)) throw new Error('PlugNotas returned an invalid artifact URL.')\n return parsed.toString()\n}\n\n/**\n * Decorates Financial without creating another fiscal ledger. The gateway only\n * requests server operations; every result returned to the UI is read back\n * from the server-committed `plg_financial_nfe` row.\n */\nexport function createPlugNotasFinancialProvider(\n options: PlugNotasFinancialProviderOptions,\n): FinancialDataProvider {\n const { base, gateway } = options\n\n const issueNota: NonNullable<FinancialDataProvider['issueNota']> = async (id) => {\n const read = fiscalReader(base)\n const document = await read(id)\n if (!document) throw new Error('Fiscal document not found.')\n if (document.model !== 'nfce') throw new Error('PlugNotas currently authorizes NFC-e only.')\n if (!document.orderId?.trim()) throw new Error('PlugNotas NFC-e must be created from an order.')\n if (!['draft', 'error'].includes(document.status)) return document\n const result = await gateway.issue({ notaId: id, idempotencyKey: `nfce:${id}` })\n const saved = await committed(read, id)\n resultError(result, saved, 'PlugNotas could not issue this NFC-e.')\n return saved\n }\n\n const refreshNota: NonNullable<FinancialDataProvider['refreshNota']> = async (id) => {\n const read = fiscalReader(base)\n const document = await read(id)\n if (!document) throw new Error('Fiscal document not found.')\n if (!['processing', 'error'].includes(document.status) && !cancellationPending(document.metadata)) return document\n const result = await gateway.refresh({ notaId: id })\n const saved = await committed(read, id)\n resultError(result, saved, 'PlugNotas could not refresh this NFC-e.')\n return saved\n }\n\n const cancelNota: NonNullable<FinancialDataProvider['cancelNota']> = async (id, reason) => {\n const read = fiscalReader(base)\n const document = await read(id)\n if (!document) throw new Error('Fiscal document not found.')\n if (document.status !== 'issued') throw new Error('Only an issued NFC-e can be cancelled.')\n if (cancellationPending(document.metadata)) throw new Error('NFC-e cancellation is already in progress.')\n const normalized = reason?.trim() ?? ''\n if (normalized.length < 15 || normalized.length > 255) {\n throw new Error('Cancellation reason must contain between 15 and 255 characters.')\n }\n const result = await gateway.cancel({ notaId: id, reason: normalized })\n const saved = await committed(read, id)\n resultError(result, saved, 'PlugNotas could not cancel this NFC-e.')\n return saved\n }\n\n const getNotaArtifactUrl: NonNullable<FinancialDataProvider['getNotaArtifactUrl']> = async (id, kind) => {\n const read = fiscalReader(base)\n const document = await read(id)\n if (!document) throw new Error('Fiscal document not found.')\n if (!['issued', 'cancelled'].includes(document.status)) {\n throw new Error('Fiscal artifacts are available only after authorization.')\n }\n if (kind === 'cancellation_xml' && document.status !== 'cancelled') {\n throw new Error('Cancellation XML is available only after cancellation.')\n }\n return artifactUrl((await gateway.artifact({ notaId: id, kind })).url)\n }\n\n return new Proxy(base, {\n get(target, property, receiver) {\n if (property === 'issueNota') return issueNota\n if (property === 'refreshNota') return refreshNota\n if (property === 'cancelNota') return cancelNota\n if (property === 'getNotaArtifactUrl') return getNotaArtifactUrl\n return Reflect.get(target, property, receiver)\n },\n })\n}\n","// ---------------------------------------------------------------------------\n// As telas que ainda não existem, com o que se sabe sobre cada uma.\n// ---------------------------------------------------------------------------\n// Tudo aqui saiu de medição no V1 de produção da Artorius (tenant 12) entre\n// 29 e 30/09/2026 — o rastro de auditoria da LAISSA FLOR, que é quem lança. Os\n// números não são estimativa: são quantas vezes ela fez aquilo.\n// ---------------------------------------------------------------------------\nimport React from 'react'\nimport { ComingSoon } from '@fayz-ai/ui'\n\n/**\n * Grupos Fiscais — a 5ª tela do grupo no V1. Na V2 o grupo fiscal já existe como\n * CADASTRO (`fiscalRegistries`), só não tem porta aqui dentro.\n */\nexport function TaxGroupsView({ onBack }: { onBack?: () => void } = {}) {\n return (\n <ComingSoon\n title=\"Grupos Fiscais\"\n summary=\"Perfis tributários reutilizáveis — CFOP, CSOSN/CST, PIS, COFINS, ICMS — que os produtos usam na emissão.\"\n v1Path=\"Estoque → Notas Fiscais → Grupos Fiscais\"\n measured=\"Vazio no V1 da Artorius («Nenhum grupo fiscal cadastrado»), coerente com eles não emitirem nota. O Pertinho do Céu e o Espaço Facial têm 11 entre os dois.\"\n missing={[\n 'Trazer o cadastro para dentro do grupo: a tabela plg_fiscalbr_tax_groups já existe e já recebeu os 11 grupos do V1',\n 'Hoje ele só aparece na lista genérica de cadastros, longe de onde a nota é usada',\n 'Só faz sentido junto com Notas Emitidas — grupo fiscal é insumo de emissão',\n ]}\n onBack={onBack}\n backTo=\"Notas Fiscais\"\n />\n )\n}\n\n/** Notas Emitidas — no V1 FUNCIONA, e é o gap maior dos dois. */\nexport function IssuedNotesView({ onBack }: { onBack?: () => void } = {}) {\n return (\n <ComingSoon\n title=\"Notas Emitidas\"\n summary=\"As NF-e, NFS-e e NFC-e que a casa emitiu, com o estado de cada uma na SEFAZ — autorizada, processando, rejeitada ou cancelada — e a comanda ou fatura que deu origem a ela.\"\n v1Path=\"Estoque → Notas Fiscais → Notas Emitidas\"\n measured=\"A Artorius não emite nota hoje: em 80 documentos recebidos, zero emitidos. Quem emite é o Pertinho do Céu e o Espaço Facial.\"\n missing={[\n 'Ligar o emissor da PlugNotas a este CNPJ (o certificado A1 já está lá desde maio; falta a credencial chegar neste ambiente)',\n 'A lista com o estado na SEFAZ e o rastro de tentativas — as tabelas já existem (plg_fiscalbr_nfce_jobs, _events)',\n 'Abrir o XML autorizado e o DANFE de cada nota',\n 'Cancelar uma nota emitida, com justificativa',\n ]}\n onBack={onBack}\n backTo=\"Notas Fiscais\"\n />\n )\n}\n\n/** Notas Devolvidas — no V1 é STUB, e a tela diz isso. */\nexport function ReturnedNotesView({ onBack }: { onBack?: () => void } = {}) {\n return (\n <ComingSoon\n title=\"Notas Devolvidas\"\n summary=\"As notas fiscais de devolução: o que voltou para o fornecedor, e o que isso desfaz no estoque e na conta a pagar.\"\n v1Path=\"Estoque → Notas Fiscais → Notas Devolvidas\"\n v1AlsoMissing\n missing={[\n 'Decidir o gesto: devolver a nota INTEIRA ou só algumas linhas dela',\n 'A devolução ESTORNA o estoque que a entrada criou — e o movimento de estorno já existe no V2 (reverses_movement_id)',\n 'E abate o título a pagar, ou gera um crédito com o fornecedor. É decisão de produto, não de código',\n 'Emitir a NF-e de devolução exige emissor ligado — mesma dependência de Notas Emitidas',\n ]}\n onBack={onBack}\n backTo=\"Notas Fiscais\"\n />\n )\n}\n\n","// ---------------------------------------------------------------------------\n// O grupo «Notas Fiscais», pronto para o Estoque montar.\n// ---------------------------------------------------------------------------\n// O V1 agrupa CINCO telas sob «Notas Fiscais», dentro do Estoque:\n//\n// Manifesto de Notas funciona (118 pendentes lá)\n// Entrada de Notas funciona — é o grosso do trabalho\n// Grupos Fiscais funciona, vazio (é cadastro, e no V2 entra como registry)\n// Notas Emitidas funciona no V1, falta aqui\n// Notas Devolvidas STUB no V1 também\n//\n// Aqui vão as quatro que são TELA. O app chama isto em\n// `createInventoryPlugin({ extraViews: [inboundNotesInventoryView()] })`, e o\n// operador acha tudo onde sempre achou: dentro do Estoque.\n//\n// As que não funcionam não são escondidas. Quem não vê a função conclui que o V2\n// não a tem — e descobrimos isso pelo suporte, não pelo plano.\n// ---------------------------------------------------------------------------\nimport React from 'react'\nimport { registerDocumentOpener } from '@fayz-ai/admin'\nimport { ModalBody, ModalHeader, ModalTitle, Skeleton } from '@fayz-ai/ui'\nimport { findInboxNoteByNumber, findInboxNoteByOperation } from '../data/inbox'\nimport { NoteReconcileView } from './NoteReconcileView'\nimport { InboundNotesPage, type InboundNotesPageProps } from './InboundNotesPage'\nimport { IssuedNotesView, ReturnedNotesView, TaxGroupsView } from './GapScreens'\nimport { describeError } from '@fayz-ai/core'\n\nexport function inboundNotesInventoryView(options: InboundNotesPageProps = {}) {\n // DE NOVO AQUI, e não por descuido: o pacote declara `sideEffects: false`, o\n // que autoriza o empacotador a descartar o registro do topo do módulo se nada\n // mais for importado dele. Esta função é chamada por todo app que monta o\n // grupo de notas — é o ponto que não some.\n registerDocumentOpener(NFE_OPENER)\n return {\n id: 'inbound-notes',\n label: 'Notas Fiscais',\n icon: 'FileText',\n // O nome do V1 para a fila de notas de compra. «Entrada» era o nome genérico\n // que o Estoque dá a qualquer tela emprestada, e dizia menos do que a tela faz.\n defaultChildLabel: 'Manifesto de Notas',\n render: () => <InboundNotesPage {...options} />,\n // A ordem é a do V1: Grupos Fiscais vem antes das duas de emissão, que é\n // onde ele é usado.\n //\n // Bonificação NÃO é aba. Ela chegou aqui por engano meu: no V1 não existe\n // esse menu — a bonificação é uma NATUREZA DE OPERAÇÃO que vem escrita na\n // nota (57 delas, em 11 grafias), e o que ela muda é o comportamento da\n // entrada: a mercadoria soma ao estoque e NÃO abre conta a pagar. O aviso\n // continua onde serve, na conciliação da nota. Uma tela vazia para um\n // comportamento é um menu que promete o que não vai entregar.\n children: [\n { id: 'tax-groups', label: 'Grupos Fiscais', render: () => <TaxGroupsView /> },\n { id: 'issued-notes', label: 'Notas Emitidas', render: () => <IssuedNotesView /> },\n { id: 'returned-notes', label: 'Notas Devolvidas', render: () => <ReturnedNotesView /> },\n ],\n }\n}\n\n/**\n * A NOTA que originou um movimento de estoque, dentro do modal que o Estoque abre.\n *\n * O Estoque guarda `operation_id` no movimento e não sabe o que é uma NF-e; esta\n * é a peça que faz a ponte — `plg_fiscalbr_inbox_documents.inventory_operation_id`\n * aponta para a mesma operação. A resolução é assíncrona (só o banco sabe qual\n * nota é), então o modal abre com esqueleto e preenche.\n *\n * Abre em MODAL e não em rota porque o documento é uma consulta, não um destino:\n * quem está percorrendo o razão clica no motivo para conferir e volta para onde\n * estava — e uma rota desmontaria a lista inteira para remontá-la sem o recorte.\n */\nexport function InboundNoteDocumentModal({ movement, onClose }: {\n movement: { operationId?: string; documentNumber?: string; reason?: string }\n onClose: () => void\n}) {\n const [noteId, setNoteId] = React.useState<string | null>(null)\n const [erro, setErro] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n let vivo = true\n // DUAS PORTAS, nesta ordem. A operação é o vínculo forte — a entrada que a V2\n // aceitou aponta para ela. O NÚMERO é o das linhas importadas do V1, que\n // trazem «NF-e 10592» escrito no motivo e vínculo nenhum: o importador copiou\n // o movimento e não a ligação. Sem a segunda porta, 3.088 linhas deste\n // cluster ficariam sem o link que o V1 tem.\n const numero = nfeNumberOf(movement)\n const busca = movement.operationId\n ? findInboxNoteByOperation(movement.operationId)\n .then((id) => id ?? (numero ? findInboxNoteByNumber(numero) : null))\n : numero ? findInboxNoteByNumber(numero) : Promise.resolve(null)\n\n busca\n .then((id) => {\n if (!vivo) return\n if (id) setNoteId(id)\n // Nota nenhuma reivindica esta entrada: ou ela não veio de nota, ou o\n // número repete entre fornecedores — e abrir a errada é pior que não\n // abrir. Dizer isso é melhor que girar para sempre.\n else setErro('Não achei a nota desta entrada nesta conta.')\n })\n .catch((e) => { if (vivo) setErro(describeError(e)) })\n return () => { vivo = false }\n }, [movement.operationId, movement.documentNumber, movement.reason])\n\n if (erro) {\n return (\n <>\n <ModalHeader className=\"shrink-0 border-b px-6 py-3 pr-14 text-left\">\n <ModalTitle>Nota de entrada</ModalTitle>\n </ModalHeader>\n <ModalBody className=\"px-6 py-8\">\n <p className=\"text-sm text-muted-foreground\">{erro}</p>\n </ModalBody>\n </>\n )\n }\n\n if (!noteId) {\n return (\n <>\n <ModalHeader className=\"shrink-0 border-b px-6 py-3 pr-14 text-left\">\n <ModalTitle>Nota de entrada</ModalTitle>\n </ModalHeader>\n <ModalBody className=\"space-y-3 px-6 py-4\">\n <Skeleton className=\"h-4 w-48\" />\n <Skeleton className=\"h-24 w-full\" />\n <Skeleton className=\"h-24 w-full\" />\n </ModalBody>\n </>\n )\n }\n\n return (\n <NoteReconcileView\n chrome=\"modal\"\n noteId={noteId}\n onBack={onClose}\n onOpenInvoice={(id) => { window.location.hash = `/financial/payables/${id}` }}\n />\n )\n}\n\n/**\n * O que o app passa em `createInventoryPlugin({ documentModal })`.\n *\n * Devolve `undefined` quando o movimento não veio de NF-e — e aí a legenda do\n * razão continua texto, em vez de virar um link que não abre nada.\n */\nexport function inboundNoteDocumentModal(\n movement: { documentType?: string; operationId?: string },\n close: () => void,\n): React.ReactNode | undefined {\n if (movement.documentType !== 'nfe' || !movement.operationId) return undefined\n return <InboundNoteDocumentModal movement={movement} onClose={close} />\n}\n\n// ---------------------------------------------------------------------------\n// O fiscal se apresenta como quem sabe abrir uma NF-e.\n// ---------------------------------------------------------------------------\n// No momento em que este módulo é carregado — ou seja, quando o aplicativo\n// instala o plugin. A tela de Movimentações do Estoque procura por\n// `document_type` e encontra; nenhum app precisa ligar fio nenhum.\n//\n// No topo do módulo e não dentro de uma função: um registro que depende de\n// alguém lembrar de chamá-lo é o mesmo problema que ele veio resolver.\n/** «NF-e 10592», «Entrada via DANFE NF-e 10592» — o número, onde ele estiver. */\nconst nfeNumberOf = (ref: { documentNumber?: string; reason?: string }): string | null =>\n (ref.documentNumber ?? ref.reason ?? '').match(/NF-e\\s*([0-9]{2,})/i)?.[1] ?? null\n\nconst NFE_OPENER = {\n documentType: 'nfe',\n // O razão é APPEND-ONLY — um gatilho recusa `UPDATE`, e com razão — então as\n // 3.088 linhas que a importação do V1 trouxe sem `document_type` nunca vão\n // ganhá-lo. O que elas têm é «Entrada via DANFE NF-e 10592» no motivo, frase\n // que este mesmo sistema escreveu. Reconhecê-la é ler o que se escreveu.\n claims: (ref: { documentType?: string; documentNumber?: string; reason?: string }) =>\n Boolean(nfeNumberOf(ref)),\n // Const de módulo e não arrow inline: o registro compara por identidade para\n // distinguir recarga quente de dois plugins disputando o mesmo tipo, e uma\n // função nova a cada chamada pareceria disputa.\n render: (ref: { operationId?: string; documentNumber?: string; reason?: string }, close: () => void) =>\n <InboundNoteDocumentModal movement={ref} onClose={close} />,\n}\n\nregisterDocumentOpener(NFE_OPENER)\n","import { definePlugin, type PluginManifest } from '@fayz-ai/core'\nimport { createPlugNotasConnector, type CreatePlugNotasConnectorOptions } from './connectors/plugnotas'\nimport { MIGRATIONS } from './migrations'\nimport { fiscalRegistries } from './data/registries'\nimport { makeInboundNotesRoute } from './views/InboundNotesPage'\nimport { UnitCertificateWidget, UnitFiscalWidget } from './views/UnitFiscalWidgets'\nimport { InvoiceNotesButton } from './views/InvoiceNotesButton'\nimport { UNIT_DETAIL_ZONES } from '@fayz-ai/admin'\nimport { FINANCIAL_INVOICE_ZONES } from '@fayz-ai/financial/views/zones'\nimport type React from 'react'\n\nexport * from './connectors/plugnotas'\nexport * from './lib/financial-provider'\nexport * from './types'\nexport * from './lib/nfe-xml'\nexport * from './data/inbox'\nexport * from './data/issued'\nexport * from './lib/issued-note'\nexport { InvoiceNotesButton } from './views/InvoiceNotesButton'\nexport { InboundNotesPage } from './views/InboundNotesPage'\nexport { InboundNotesView } from './views/InboundNotesView'\nexport { NoteReconcileView } from './views/NoteReconcileView'\nexport { ComingSoon, EmBreve } from '@fayz-ai/ui'\nexport { IssuedNotesView, ReturnedNotesView, TaxGroupsView } from './views/GapScreens'\n/**\n * O grupo «Notas Fiscais» como o V1 o desenha: cinco telas sob uma aba. Duas\n * funcionam, três anunciam o que falta. O app passa isto para\n * `createInventoryPlugin({ extraViews })` e o Estoque desenha.\n */\nexport { inboundNotesInventoryView, inboundNoteDocumentModal, InboundNoteDocumentModal } from './views/inventoryView'\n\nexport interface CreatePlugNotasPluginOptions extends CreatePlugNotasConnectorOptions {\n /** Onde a linha de Entrada de Notas entra no rail. Default: `main`, posição 5 (depois do estoque). */\n navSection?: 'main' | 'secondary' | 'settings'\n navPosition?: number\n /**\n * Onde o título a pagar vive no app anfitrião, para o botão «Abrir a conta a\n * pagar» depois de aceitar. Sem isto o botão não aparece — um botão que leva a\n * lugar nenhum é pior que a ausência dele.\n */\n payableRoute?: (invoiceId: string) => string\n}\n\n/**\n * Fiscal Brasil is an addon: Financial owns the fiscal document, while this\n * package owns the provider connection and its asynchronous delivery trail.\n */\nexport function createPlugNotasPlugin(options: CreatePlugNotasPluginOptions = {}): PluginManifest {\n return definePlugin({\n id: 'fiscal-br',\n name: 'Fiscal Brasil',\n icon: 'ReceiptText',\n version: '0.1.0',\n apiVersion: 1,\n scope: 'addon',\n defaultEnabled: true,\n dependencies: ['financial'],\n // SEM linha no rail, de propósito.\n //\n // Entrada de Notas é assunto de ESTOQUE, não assunto do menu: no V1 o caminho\n // é `Estoque → Notas Fiscais → Entrada de Notas`. Montei como linha solta na\n // primeira tentativa e estava errado — quem vem do V1 procura dentro do\n // Estoque e não acha. O app entrega a tela ao inventário por\n // `createInventoryPlugin({ extraViews })`, e ela aparece como aba irmã de\n // Produtos, Movimentações e Contagens.\n //\n // A rota própria FICA: ela é o deep link (`#/inbound-notes`), e é por onde o\n // agente e um link de e-mail chegam sem passar pela faixa de abas.\n navigation: [],\n routes: [\n {\n path: '/inbound-notes',\n // O registro de rotas monta componentes sem prop. A opção do host entra\n // por fechamento, e a fábrica mora no `.tsx` para este manifesto seguir\n // sendo TypeScript sem JSX.\n component: makeInboundNotesRoute({ payableRoute: options.payableRoute }),\n permission: { feature: 'financial', action: 'read' as const },\n },\n ],\n // O grupo fiscal é CADASTRO, e por isso entra como registry e não como\n // rota própria: ele aparece onde os outros cadastros do produto aparecem.\n registries: fiscalRegistries,\n widgets: [\n {\n id: 'fiscal-br-unit-certificate',\n zone: UNIT_DETAIL_ZONES.certificate,\n component: UnitCertificateWidget as unknown as React.ComponentType<unknown>,\n order: 0,\n permission: { feature: 'financial', action: 'read' as const },\n },\n {\n id: 'fiscal-br-invoice-notes',\n zone: FINANCIAL_INVOICE_ZONES.headerActions,\n component: InvoiceNotesButton as unknown as React.ComponentType<unknown>,\n order: 0,\n permission: { feature: 'financial', action: 'read' as const },\n },\n {\n id: 'fiscal-br-unit-fiscal',\n zone: UNIT_DETAIL_ZONES.fiscal,\n component: UnitFiscalWidget as unknown as React.ComponentType<unknown>,\n order: 0,\n permission: { feature: 'financial', action: 'read' as const },\n },\n ],\n connectors: [createPlugNotasConnector(options)],\n functions: [{\n slug: 'plugnotas-bridge',\n ingress: 'none',\n verifyJwt: false,\n secrets: [\n 'PLUGNOTAS_API_KEY',\n 'PLUGNOTAS_BASE_URL',\n 'PLUGNOTAS_ENVIRONMENT',\n 'PLUGNOTAS_WEBHOOK_SECRET',\n 'PLUGNOTAS_ARTIFACT_SIGNING_KEY',\n 'PLUGNOTAS_ALLOWED_ORIGINS',\n 'PLUGNOTAS_WORKER_SECRET',\n 'SUPABASE_URL',\n 'SUPABASE_ANON_KEY',\n 'SUPABASE_SERVICE_ROLE_KEY'\n ],\n grants: [\n 'plugnotas_register_emitter',\n 'plugnotas_disconnect_emitter',\n 'plugnotas_create_nfce_draft_for_order',\n 'plugnotas_prepare_nfce',\n 'plugnotas_prepare_nfce_cancel',\n 'plugnotas_apply_nfce_result',\n 'plugnotas_apply_nfce_webhook',\n 'plugnotas_get_artifact_locator',\n 'plugnotas_claim_nfce_recovery',\n 'plugnotas_record_nfce_attempt'\n ],\n }],\n migrations: MIGRATIONS.map((entry) => ({\n id: `fiscal-br-${entry.id}`,\n version: '1.0.0',\n sql: entry.sql,\n description: 'Durable PlugNotas delivery, recovery, webhook and emitter-registration boundary.',\n })),\n diagnostics: [{\n id: 'plugnotas-nfce-ready',\n description: 'NFC-e requires the shared connection, order, item and financial fiscal-document contracts.',\n requires: {\n tables: [\n 'connections',\n 'orders',\n 'items',\n 'plg_financial_nfe',\n 'plg_fiscalbr_nfce_jobs',\n 'plg_fiscalbr_nfce_events',\n 'plg_fiscalbr_webhook_receipts',\n ],\n rpcs: [\n 'plugnotas_create_nfce_draft_for_order',\n 'plugnotas_prepare_nfce',\n 'plugnotas_apply_nfce_result',\n 'plugnotas_apply_nfce_webhook',\n 'plugnotas_claim_nfce_recovery',\n ],\n env: [\n 'PLUGNOTAS_API_KEY',\n 'PLUGNOTAS_BASE_URL',\n 'PLUGNOTAS_ENVIRONMENT',\n 'PLUGNOTAS_WEBHOOK_SECRET',\n 'PLUGNOTAS_ARTIFACT_SIGNING_KEY',\n 'PLUGNOTAS_ALLOWED_ORIGINS',\n 'PLUGNOTAS_WORKER_SECRET',\n ],\n },\n level: 'error',\n }],\n })\n}\n"]}
1
+ {"version":3,"sources":["../src/connectors/plugnotas.ts","../src/migrations/index.ts","../src/data/registries.ts","../src/lib/nfe-xml.ts","../src/data/inbox.ts","../src/views/PullByKeyDialog.tsx","../src/views/InboundNotesView.tsx","../src/views/NoteAttachmentsCard.tsx","../src/types.ts","../src/views/NoteReconcileView.tsx","../src/views/InboundNotesPage.tsx","../src/views/UnitFiscalWidgets.tsx","../src/data/issued.ts","../src/lib/issued-note.ts","../src/views/InvoiceNotesButton.tsx","../src/lib/financial-provider.ts","../src/views/GapScreens.tsx","../src/views/inventoryView.tsx","../src/index.ts"],"names":["digits","useState","useEffect","jsx","jsxs","Button","Loader2","KeyRound","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","money","formatCurrency","day","useRef","useCallback","Card","ImageIcon","FileText","Trash2","UploadCloud","accepted","useMemo","reavaliar","rodape","Fragment","ModalHeader","ModalTitle","ModalBody","ModalFooter","FileCode2","Hint","RefreshCw","Input","Modal","ModalContent","sb","getSupabaseClientOptional","getActiveTenantId","React","adminNavigateTo","Skeleton","Field","Check","X","NOTE_COLUMNS","TooltipProvider","Tooltip","TooltipTrigger","TooltipContent","ModalDescription","toast","Badge","ChevronDown","AlertTriangle","document","describeError"],"mappings":";;;;;;;;;;AAaO,IAAM,sBAAA,GAAyB;AAEtC,IAAM,cAAA,GAAiB,qWAAA;AAEhB,IAAM,gBAAA,GAAmB;AAAA,EAC9B;AAAA,IACE,GAAA,EAAK,aAAA;AAAA,IACL,KAAA,EAAO,kBAAA;AAAA,IACP,IAAA,EAAM,MAAA;AAAA,IACN,WAAA,EAAa;AAAA;AAEjB;AAEO,IAAM,qBAAqB,CAAC;AAAA,EACjC,GAAA,EAAK,aAAA;AAAA,EACL,KAAA,EAAO,iBAAA;AAAA,EACP,WAAA,EAAa,kFAAA;AAAA,EACb,IAAA,EAAM,QAAA;AAAA,EACN,OAAA,EAAS;AAAA,IACP,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,kBAAA,EAAmB;AAAA,IAC9C,EAAE,KAAA,EAAO,cAAA,EAAgB,KAAA,EAAO,yBAAA;AAAoB,GACtD;AAAA,EACA,iBAAA,EAAmB,IAAA;AAAA,EACnB,YAAA,EAAc;AAChB,CAAC;AAED,IAAM,iBAAA,GAAoB;AAAA,EACxB,kBAAA;AAAA,EACA,UAAA;AAAA,EACA,mBAAA;AAAA,EACA,sBAAA;AAAA,EACA,wBAAA;AAAA;AAAA;AAAA;AAAA,EAIA,mBAAA;AAAA,EACA,eAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA;AACA,IAAM,MAAA,GAAS,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAE9B,SAAS,OAAO,KAAA,EAAuB;AACrC,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAChC;AAEO,SAAS,YAAY,KAAA,EAAwB;AAClD,EAAA,MAAM,UAAA,GAAa,OAAO,KAAK,CAAA;AAC/B,EAAA,IAAI,CAAC,WAAW,IAAA,CAAK,UAAU,KAAK,cAAA,CAAe,IAAA,CAAK,UAAU,CAAA,EAAG,OAAO,KAAA;AAC5E,EAAA,MAAM,KAAA,GAAQ,CAAC,IAAA,EAAc,OAAA,KAAsB;AACjD,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,MAAA,CAAO,CAAC,OAAO,MAAA,EAAQ,KAAA,KAAU,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA,GAAI,QAAQ,CAAC,CAAA;AAC5F,IAAA,MAAM,YAAY,GAAA,GAAM,EAAA;AACxB,IAAA,OAAO,SAAA,GAAY,CAAA,GAAI,CAAA,GAAI,EAAA,GAAK,SAAA;AAAA,EAClC,CAAA;AACA,EAAA,MAAM,KAAA,GAAQ,MAAM,UAAA,CAAW,KAAA,CAAM,GAAG,EAAE,CAAA,EAAG,CAAC,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC,CAAA;AACjF,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,CAAA,EAAG,UAAA,CAAW,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,CAAC,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC,CAAA;AAClG,EAAA,OAAO,WAAW,QAAA,CAAS,CAAA,EAAG,KAAK,CAAA,EAAG,MAAM,CAAA,CAAE,CAAA;AAChD;AAEA,SAAS,YAAY,KAAA,EAAsC;AACzD,EAAA,IAAI,KAAA,KAAU,UAAa,KAAA,KAAU,IAAA,IAAQ,UAAU,EAAA,IAAM,KAAA,KAAU,WAAW,OAAO,SAAA;AACzF,EAAA,IAAI,KAAA,KAAU,gBAAgB,OAAO,KAAA;AACrC,EAAA,MAAM,IAAI,MAAM,qEAAsD,CAAA;AACxE;AAEA,SAAS,KAAA,GAAQ;AACf,EAAA,OAAO,sBAAsB,sBAAA,EAAwB;AAAA,IACnD,MAAA,EAAQ,CAAC,GAAG,gBAAgB,CAAA;AAAA,IAC5B,QAAA,EAAU,CAAC,GAAG,kBAAkB,CAAA;AAAA,IAChC,YAAA,EAAc;AAAA,GACf,CAAA;AACH;AAEA,SAAS,aAAa,UAAA,EAAqC;AACzD,EAAA,IAAI,CAAC,UAAA,EAAY,MAAA,EAAQ,OAAO,EAAE,WAAW,KAAA,EAAM;AACnD,EAAA,MAAM,YAAY,cAAA,CAAe,CAAC,GAAG,kBAAkB,GAAG,UAAU,CAAA;AACpE,EAAA,MAAM,gBAAA,GAAmB,UAAA,CAAW,QAAA,CAAS,gBAAA,KAAqB,IAAA;AAClE,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,QAAA,CAAS,QAAA,KAAa,IAAA;AAClD,EAAA,MAAM,MAAA,GAAS,OAAO,UAAA,CAAW,QAAA,CAAS,oBAAA,KAAyB,QAAA,GAC/D,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,QAAA,CAAS,oBAAoB,CAAA,GACnD,MAAA,CAAO,GAAA;AACX,EAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,GAAI,IAAA,CAAK,IAAA,CAAA,CAAM,MAAA,GAAS,IAAA,CAAK,GAAA,EAAI,IAAK,MAAM,CAAA,GAAI,IAAA;AAC9F,EAAA,MAAM,OAAA,GAAU,eAAA,KAAoB,IAAA,IAAQ,eAAA,IAAmB,CAAA;AAC/D,EAAA,MAAM,YAAA,GAAe,eAAA,KAAoB,IAAA,IAAQ,eAAA,GAAkB,KAAK,eAAA,IAAmB,EAAA;AAC3F,EAAA,MAAM,eAAA,GAAkB,CAAC,mBAAG,IAAI,GAAA,CAAI;AAAA,IAClC,GAAI,SAAA,CAAU,eAAA,IAAmB,EAAC;AAAA,IAClC,GAAI,CAAC,gBAAA,IAAoB,UAAU,CAAC,aAAa,IAAI,EAAC;AAAA,IACtD,GAAI,CAAC,QAAA,GAAW,CAAC,KAAK,IAAI;AAAC,GAC5B,CAAC,CAAA;AAEF,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,IAAA;AAAA,IACX,UAAA,EAAY,gBAAgB,MAAA,GAAS,CAAA;AAAA,IACrC,GAAI,eAAA,CAAgB,MAAA,GAAS,EAAE,eAAA,KAAoB,EAAC;AAAA,IACpD,MAAA,EAAQ,OAAA,GACJ,wBAAA,GACA,CAAC,gBAAA,GACC,qCAAA,GACA,CAAC,QAAA,GACC,0CAAA,GACA,UAAA,CAAW,QAAA,CAAS,WAAA,KAAgB,iBAClC,sCAAA,GACA,4BAAA;AAAA,IACV,GAAI,YAAA,GACA,EAAE,MAAA,EAAQ,CAAC,CAAA,0BAAA,EAA6B,eAAe,CAAA,IAAA,EAAO,eAAA,KAAoB,IAAI,EAAA,GAAK,GAAG,CAAA,CAAA,CAAG,CAAA,KACjG,EAAC;AAAA,IACL,KAAA,EAAO;AAAA,GACT;AACF;AAOO,SAAS,wBAAA,CAAyB,OAAA,GAA2C,EAAC,EAAwB;AAC3G,EAAA,MAAM,kBAAkB,KAAA,EAAM;AAC9B,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,sBAAA;AAAA;AAAA;AAAA;AAAA,IAIJ,WAAA,EAAa,WAAA;AAAA,IACb,YAAA,EAAc,WAAA;AAAA,IACd,IAAA,EAAM,sBAAA;AAAA,IACN,WAAA,EAAa,mFAAA;AAAA,IACb,IAAA,EAAM,aAAA;AAAA,IACN,OAAA,EAAS,cAAA;AAAA,IACT,QAAA,EAAU,SAAA;AAAA,IACV,QAAA,EAAU,KAAA;AAAA,IACV,SAAA,EAAW,UAAA;AAAA,IACX,MAAA,EAAQ,CAAC,MAAM,CAAA;AAAA,IACf,OAAA,EAAS,gCAAA;AAAA,IACT,MAAA,EAAQ,CAAC,GAAG,gBAAgB,CAAA;AAAA,IAC5B,QAAA,EAAU,CAAC,GAAG,kBAAkB,CAAA;AAAA,IAChC,aAAa,CAAC;AAAA,MACZ,IAAA,EAAM,MAAA;AAAA,MACN,QAAA,EAAU,iBAAA;AAAA,MACV,OAAA,EAAS,CAAC,MAAA,EAAQ,OAAO,CAAA;AAAA,MACzB,MAAA,EAAQ,yFAAA;AAAA,MACR,SAAA,EAAW;AAAA,KACZ,CAAA;AAAA,IACD,WAAW,CAAC;AAAA,MACV,GAAA,EAAK,sBAAA;AAAA,MACL,KAAA,EAAO,6EAAA;AAAA,MACP,KAAA,EAAO,MAAA;AAAA,MACP,OAAA,EAAS,QAAA;AAAA,MACT,OAAA,EAAS,CAAC,iBAAiB;AAAA,KAC5B,CAAA;AAAA,IACD,UAAA,EAAY;AAAA,MACV,mFAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,GAAG,gBAAA,CAAiB,sBAAA,EAAwB,YAAA,EAAc,EAAE,OAAO,CAAA;AAAA,IACnE,GAAG,mBAAmB,eAAe,CAAA;AAAA,IACrC,MAAM,eAAe,MAAA,EAAQ;AAC3B,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,WAAA,IAAe,EAAE,CAAA;AACnD,MAAA,IAAI,CAAC,YAAY,WAAW,CAAA,SAAU,EAAE,EAAA,EAAI,KAAA,EAAO,OAAA,EAAS,4BAAA,EAA0B;AACtF,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,WAAA,CAAY,OAAO,WAAW,CAAA;AAAA,MAC3C,SAAS,KAAA,EAAO;AACd,QAAA,OAAO,EAAE,IAAI,KAAA,EAAO,OAAA,EAAS,iBAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,uBAAA,EAAqB;AAAA,MAC7F;AACA,MAAA,OAAO,OAAA,CAAQ,MAAA,EAAQ,WAAA,GACnB,OAAA,CAAQ,OAAO,WAAA,CAAY,EAAE,WAAA,EAAa,WAAA,EAAa,QAAA,EAAU,CAAA,GACjE,EAAE,IAAI,IAAA,EAAK;AAAA,IACjB,CAAA;AAAA,IACA,MAAM,eAAe,MAAA,EAAQ;AAC3B,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,WAAA,IAAe,EAAE,CAAA;AACnD,MAAA,IAAI,CAAC,WAAA,CAAY,WAAW,GAAG,MAAM,IAAI,MAAM,4BAAyB,CAAA;AACxE,MAAA,MAAM,gBAAgB,IAAA,CAAK;AAAA,QACzB,MAAA,EAAQ,IAAA;AAAA,QACR,WAAA,EAAa,CAAA,SAAA,EAAY,WAAA,CAAY,KAAA,CAAM,EAAE,CAAC,CAAA,CAAA;AAAA,QAC9C,kBAAA,EAAoB,WAAA;AAAA,QACpB,QAAA,EAAU;AAAA,UACR,WAAA;AAAA,UACA,WAAA,EAAa,WAAA,CAAY,MAAA,CAAO,WAAW,CAAA;AAAA,UAC3C,gBAAA,EAAkB,KAAA;AAAA,UAClB,QAAA,EAAU;AAAA;AACZ,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAI,OAAA,CAAQ,MAAA,EAAQ,iBAAA,GAChB,EAAE,UAAA,EAAY,MAAM,OAAA,CAAQ,MAAA,CAAQ,iBAAA,EAAmB,EAAE,GACzD,EAAC;AAAA,IACL,cAAA,EAAgB,+FAAA;AAAA,IAChB,YAAY,OAAA,CAAQ;AAAA,GACtB;AACF;AAGA,eAAsB,0BAA0B,KAAA,EAA2C;AACzF,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,KAAA,CAAM,WAAW,CAAA;AAC5C,EAAA,IAAI,CAAC,WAAA,CAAY,WAAW,GAAG,MAAM,IAAI,MAAM,4BAAyB,CAAA;AACxE,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK;AAAA,IACjB,MAAA,EAAQ,IAAA;AAAA,IACR,kBAAA,EAAoB,WAAA;AAAA,IACpB,QAAA,EAAU;AAAA,MACR,WAAA;AAAA,MACA,WAAA,EAAa,WAAA,CAAY,KAAA,CAAM,WAAW,CAAA;AAAA,MAC1C,kBAAkB,KAAA,CAAM,gBAAA;AAAA,MACxB,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,mBAAmB,KAAA,CAAM,iBAAA;AAAA,MACzB,sBAAsB,KAAA,CAAM,oBAAA;AAAA,MAC5B,wBAAwB,KAAA,CAAM;AAAA;AAChC,GACD,CAAA;AACH;;;AC7NO,IAAM,sBAAA,GAAyB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA6jB/B,IAAM,0DAAA,GAA6D,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAqMnE,IAAM,+CAAA,GAAkD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA2WxD,IAAM,0CAAA,GAA6C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAkPnD,IAAM,8CAAA,GAAiD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAwBvD,IAAM,2CAAA,GAA8C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA+MpD,IAAM,yCAAA,GAA4C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAoBlD,IAAM,oDAAA,GAAuD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAiC7D,IAAM,yDAAA,GAA4D,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AA4NlE,IAAM,gEAAA,GAAmE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAsiBzE,IAAM,gEAAA,GAAmE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAkOzE,IAAM,8CAAA,GAAiD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAmFvD,IAAM,oDAAA,GAAuD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA,CAAA;AA8J7D,IAAM,oDAAA,GAAuD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AA0J7D,IAAM,kDAAA,GAAqD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAsH7D,IAAM,+CAAA,GAAkD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","file":"index.js","sourcesContent":["import type React from 'react'\nimport {\n connectionSettings,\n connectionStatus,\n createConnectionStore,\n settingsStatus,\n type ConnectionConfig,\n type ConnectorDefinition,\n type ConnectorField,\n type ConnectorSetting,\n} from '@fayz-ai/core'\nimport type { PlugNotasConnectorClient, PlugNotasEnvironment, PlugNotasSetupState } from '../types'\n\nexport const PLUGNOTAS_CONNECTOR_ID = 'plugnotas'\n\nconst PLUGNOTAS_MARK = \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%230F766E'/%3E%3Cpath d='M10 7h12v18l-2-1.5-2 1.5-2-1.5-2 1.5-2-1.5-2 1.5V7Z' fill='white'/%3E%3Cpath d='M13 12h6M13 16h6M13 20h4' stroke='%230F766E' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E\"\n\nexport const PLUGNOTAS_FIELDS = [\n {\n key: 'emitterCnpj',\n label: 'CNPJ do emitente',\n type: 'text',\n placeholder: '00.000.000/0000-00',\n },\n] as const satisfies readonly ConnectorField[]\n\nexport const PLUGNOTAS_SETTINGS = [{\n key: 'environment',\n label: 'Ambiente fiscal',\n description: 'Sandbox simula o emissor. Homologação envia para a SEFAZ sem valor fiscal.',\n type: 'select',\n options: [\n { value: 'sandbox', label: 'Sandbox simulado' },\n { value: 'homologation', label: 'Homologação SEFAZ' },\n ],\n requiredToOperate: true,\n defaultValue: 'sandbox',\n}] as const satisfies readonly ConnectorSetting[]\n\nconst INTERNAL_SETTINGS = [\n 'certificateReady',\n 'cscReady',\n 'providerEmitterId',\n 'certificateExpiresAt',\n 'certificateFingerprint',\n // Non-secret operational data written by the host's server-side setup flow.\n // Declaring these keys keeps the shared connection store authoritative while\n // credentials (API key, A1 bytes/password, CSC) remain outside public JSON.\n 'stateRegistration',\n 'corporateName',\n 'tradeName',\n 'email',\n 'taxRegime',\n 'address',\n 'series',\n 'paymentMethod',\n]\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction digits(value: string): string {\n return value.replace(/\\D/g, '')\n}\n\nexport function isValidCnpj(value: string): boolean {\n const normalized = digits(value)\n if (!/^\\d{14}$/.test(normalized) || /^(\\d)\\1{13}$/.test(normalized)) return false\n const digit = (base: string, weights: number[]) => {\n const sum = weights.reduce((total, weight, index) => total + Number(base[index]) * weight, 0)\n const remainder = sum % 11\n return remainder < 2 ? 0 : 11 - remainder\n }\n const first = digit(normalized.slice(0, 12), [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2])\n const second = digit(`${normalized.slice(0, 12)}${first}`, [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2])\n return normalized.endsWith(`${first}${second}`)\n}\n\nfunction environment(value: unknown): PlugNotasEnvironment {\n if (value === undefined || value === null || value === '' || value === 'sandbox') return 'sandbox'\n if (value === 'homologation') return value\n throw new Error('Produção não está disponível neste conector preview.')\n}\n\nfunction store() {\n return createConnectionStore(PLUGNOTAS_CONNECTOR_ID, {\n fields: [...PLUGNOTAS_FIELDS],\n settings: [...PLUGNOTAS_SETTINGS],\n settingsKeys: INTERNAL_SETTINGS,\n })\n}\n\nfunction deriveStatus(connection: ConnectionConfig | null) {\n if (!connection?.active) return { connected: false }\n const readiness = settingsStatus([...PLUGNOTAS_SETTINGS], connection)\n const certificateReady = connection.settings.certificateReady === true\n const cscReady = connection.settings.cscReady === true\n const expiry = typeof connection.settings.certificateExpiresAt === 'string'\n ? Date.parse(connection.settings.certificateExpiresAt)\n : Number.NaN\n const daysUntilExpiry = Number.isFinite(expiry) ? Math.ceil((expiry - Date.now()) / DAY_MS) : null\n const expired = daysUntilExpiry !== null && daysUntilExpiry <= 0\n const expiringSoon = daysUntilExpiry !== null && daysUntilExpiry > 0 && daysUntilExpiry <= 30\n const missingSettings = [...new Set([\n ...(readiness.missingSettings ?? []),\n ...(!certificateReady || expired ? ['certificate'] : []),\n ...(!cscReady ? ['csc'] : []),\n ])]\n\n return {\n connected: true,\n needsSetup: missingSettings.length > 0,\n ...(missingSettings.length ? { missingSettings } : {}),\n detail: expired\n ? 'Certificado A1 vencido'\n : !certificateReady\n ? 'Envie o certificado A1 do emitente.'\n : !cscReady\n ? 'Confirme o CSC e o ID Token do emitente.'\n : connection.settings.environment === 'homologation'\n ? 'Emitente pronto em homologação'\n : 'Emitente pronto no sandbox',\n ...(expiringSoon\n ? { issues: [`O certificado A1 vence em ${daysUntilExpiry} dia${daysUntilExpiry === 1 ? '' : 's'}.`] }\n : {}),\n plane: 'sync' as const,\n }\n}\n\nexport interface CreatePlugNotasConnectorOptions {\n client?: PlugNotasConnectorClient\n SetupPanel?: React.ComponentType\n}\n\nexport function createPlugNotasConnector(options: CreatePlugNotasConnectorOptions = {}): ConnectorDefinition {\n const connectionStore = store()\n return {\n id: PLUGNOTAS_CONNECTOR_ID,\n // PlugBank and PlugNotas are different products from the same vendor. The\n // directory key names the product, otherwise one silently replaces the\n // other in the generated connector map.\n catalogSlug: 'plugnotas',\n hostPluginId: 'financial',\n name: 'PlugNotas · NFC-e',\n description: 'Emita NFC-e pela TecnoSpeed sem expor certificado, senha ou API key no navegador.',\n icon: 'ReceiptText',\n logoUrl: PLUGNOTAS_MARK,\n authKind: 'api-key',\n category: 'erp',\n direction: 'outbound',\n planes: ['sync'],\n docsUrl: 'https://docs.plugnotas.com.br/',\n fields: [...PLUGNOTAS_FIELDS],\n settings: [...PLUGNOTAS_SETTINGS],\n permissions: [{\n kind: 'data',\n resource: 'fiscal-document',\n actions: ['read', 'write'],\n reason: 'Enviar a NFC-e e reconciliar situação, chave de acesso e artefatos no Financeiro.',\n sensitive: true,\n }],\n invokedAt: [{\n key: 'financial.nfce.issue',\n label: 'Quando um operador confirma a emissão da NFC-e de um pedido concluído',\n plane: 'sync',\n trigger: 'manual',\n touches: ['fiscal-document'],\n }],\n howItSyncs: [\n 'A emissão cria primeiro um comando durável e só depois chama o provedor.',\n 'Webhook e recuperação consultiva convergem o mesmo comando, sem reenviar no escuro.',\n ],\n ...connectionStatus(PLUGNOTAS_CONNECTOR_ID, deriveStatus, { store }),\n ...connectionSettings(connectionStore),\n async testConnection(values) {\n const emitterCnpj = digits(values.emitterCnpj ?? '')\n if (!isValidCnpj(emitterCnpj)) return { ok: false, message: 'Informe um CNPJ válido.' }\n let selected: PlugNotasEnvironment\n try {\n selected = environment(values.environment)\n } catch (error) {\n return { ok: false, message: error instanceof Error ? error.message : 'Ambiente inválido.' }\n }\n return options.client?.testEmitter\n ? options.client.testEmitter({ emitterCnpj, environment: selected })\n : { ok: true }\n },\n async saveConnection(values) {\n const emitterCnpj = digits(values.emitterCnpj ?? '')\n if (!isValidCnpj(emitterCnpj)) throw new Error('Informe um CNPJ válido.')\n await connectionStore.save({\n active: true,\n displayName: `Emitente ${emitterCnpj.slice(-6)}`,\n providerAccountKey: emitterCnpj,\n settings: {\n emitterCnpj,\n environment: environment(values.environment),\n certificateReady: false,\n cscReady: false,\n },\n })\n },\n ...(options.client?.disconnectEmitter\n ? { disconnect: () => options.client!.disconnectEmitter!() }\n : {}),\n disconnectNote: 'As notas existentes permanecem no Financeiro; somente novas emissões são interrompidas.',\n ExtraPanel: options.SetupPanel,\n }\n}\n\n/** Persist only server-confirmed readiness and non-secret certificate metadata. */\nexport async function markPlugNotasEmitterReady(input: PlugNotasSetupState): Promise<void> {\n const emitterCnpj = digits(input.emitterCnpj)\n if (!isValidCnpj(emitterCnpj)) throw new Error('Informe um CNPJ válido.')\n await store().save({\n active: true,\n providerAccountKey: emitterCnpj,\n settings: {\n emitterCnpj,\n environment: environment(input.environment),\n certificateReady: input.certificateReady,\n cscReady: input.cscReady,\n providerEmitterId: input.providerEmitterId,\n certificateExpiresAt: input.certificateExpiresAt,\n certificateFingerprint: input.certificateFingerprint,\n },\n })\n}\n","// AUTO-GENERATED from 000_baseline.sql, 001_preserve_terminal_results_and_recover_leases.sql, 002_a_nota_que_chega_tem_onde_esperar.sql, 003_a_caixa_de_entrada_atravessa.sql, 004_o_grupo_fiscal_do_v1_repete_nome.sql, 005_a_nota_emitida_e_um_documento.sql, 006_o_grupo_fiscal_ganha_o_rail.sql, 007_a_rls_do_documento_passa_a_ser_legivel.sql, 008_a_nota_recebida_guarda_a_decisao_de_entrada.sql, 009_aceitar_a_nota_escreve_estoque_e_titulo_de_uma_vez.sql, 010_a_data_de_emissao_e_instante_e_a_competencia_e_dia.sql, 011_o_imposto_do_produto_e_do_fiscal.sql, 012_quem_e_o_produto_se_pergunta_ao_indice.sql, 013_a_sugestao_sobrevive_a_fechar_a_janela.sql, 014_a_descricao_da_nota_tem_lixo_no_meio.sql, 015_o_movimento_diz_que_veio_da_nota.sql, 016_a_nota_guarda_o_proprio_xml.sql, 017_quem_emite_e_o_cnpj_nao_a_loja.sql, 018_a_nota_do_v1_alcanca_a_conta.sql, 019_a_nota_emitida_se_cancela_pelo_v2.sql, 020_a_nota_acha_o_fornecedor_pelo_cnpj.sql, 021_uso_e_consumo_entra_no_estoque.sql, 022_a_nota_do_v1_traz_o_xml.sql, 023_a_nota_aceita_sem_linhas_recebe_as_linhas.sql, 024_a_nota_nao_aponta_para_conta_que_sumiu.sql, 025_a_conta_da_nota_fecha_com_o_total.sql, 026_o_recebimento_parado_diz_por_que.sql, 027_a_nota_com_conta_e_sem_estoque_termina_no_v2.sql, 028_a_linha_de_estoque_tem_unidade.sql, 029_the_service_writes_the_intake_health.sql, 030_the_service_onboards_the_emitter.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_000_BASELINE = `-- Fiscal Brasil / PlugNotas baseline.\n--\n-- This addon does not create a second fiscal ledger. \\`plg_financial_nfe\\`\n-- remains the authoritative document owned by plugin-financial. The tables\n-- below describe delivery to an external issuer: durable commands, attempts,\n-- webhooks and emitter ownership.\n--\n-- The file is additive and idempotent because the current restaurant pool is\n-- live. Applying it is deliberately outside this draft PR.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_nfce_jobs (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n -- Logical reference to plugin-financial's fiscal ledger. Cross-plugin\n -- physical foreign keys are intentionally forbidden: installation and\n -- removal of this addon must never rewrite another plugin's schema.\n nota_id uuid NOT NULL,\n order_id uuid NOT NULL REFERENCES public.orders(id) ON DELETE RESTRICT,\n connection_id uuid NOT NULL REFERENCES public.connections(id) ON DELETE RESTRICT,\n operation text NOT NULL CHECK (operation IN ('issue', 'cancel')),\n status text NOT NULL DEFAULT 'queued'\n CHECK (status IN ('queued', 'running', 'waiting', 'succeeded', 'failed', 'manual_review')),\n idempotency_key text NOT NULL,\n provider_document_id text,\n integration_id text,\n request_snapshot jsonb NOT NULL DEFAULT '{}'::jsonb,\n provider_response jsonb NOT NULL DEFAULT '{}'::jsonb,\n attempts integer NOT NULL DEFAULT 0 CHECK (attempts >= 0),\n next_attempt_at timestamptz,\n locked_until timestamptz,\n last_error text,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE (tenant_id, idempotency_key)\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_nfce_jobs_recovery_idx\n ON public.plg_fiscalbr_nfce_jobs (status, next_attempt_at, locked_until)\n WHERE status IN ('queued', 'waiting');\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_nfce_events (\n id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n nota_id uuid NOT NULL,\n job_id uuid REFERENCES public.plg_fiscalbr_nfce_jobs(id) ON DELETE SET NULL,\n event_type text NOT NULL,\n payload jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now()\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_nfce_events_document_idx\n ON public.plg_fiscalbr_nfce_events (tenant_id, nota_id, created_at DESC);\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_webhook_receipts (\n id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,\n provider text NOT NULL DEFAULT 'plugnotas',\n provider_event_id text NOT NULL,\n tenant_id uuid REFERENCES public.tenants(id) ON DELETE SET NULL,\n nota_id uuid,\n payload_sha256 text NOT NULL,\n received_at timestamptz NOT NULL DEFAULT now(),\n processed_at timestamptz,\n processing_error text,\n UNIQUE (provider, provider_event_id)\n);\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_emitter_ownership (\n emitter_cnpj text PRIMARY KEY CHECK (emitter_cnpj ~ '^[0-9]{14}$'),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n connection_id uuid NOT NULL REFERENCES public.connections(id) ON DELETE CASCADE,\n environment text NOT NULL CHECK (environment IN ('sandbox', 'homologation')),\n provider_emitter_id text,\n certificate_expires_at timestamptz,\n certificate_fingerprint text,\n csc_ready boolean NOT NULL DEFAULT false,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE (tenant_id, connection_id)\n);\n\nALTER TABLE public.plg_fiscalbr_nfce_jobs ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_nfce_events ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_webhook_receipts ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_emitter_ownership ENABLE ROW LEVEL SECURITY;\n\nDROP POLICY IF EXISTS plg_fiscalbr_nfce_jobs_read ON public.plg_fiscalbr_nfce_jobs;\nCREATE POLICY plg_fiscalbr_nfce_jobs_read ON public.plg_fiscalbr_nfce_jobs\n FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL))\n );\n\nDROP POLICY IF EXISTS plg_fiscalbr_nfce_events_read ON public.plg_fiscalbr_nfce_events;\nCREATE POLICY plg_fiscalbr_nfce_events_read ON public.plg_fiscalbr_nfce_events\n FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL))\n );\n\nDROP POLICY IF EXISTS plg_fiscalbr_emitter_ownership_read ON public.plg_fiscalbr_emitter_ownership;\nCREATE POLICY plg_fiscalbr_emitter_ownership_read ON public.plg_fiscalbr_emitter_ownership\n FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL))\n );\n\nREVOKE ALL ON public.plg_fiscalbr_nfce_jobs FROM anon, authenticated;\nREVOKE ALL ON public.plg_fiscalbr_nfce_events FROM anon, authenticated;\nREVOKE ALL ON public.plg_fiscalbr_webhook_receipts FROM anon, authenticated;\nREVOKE ALL ON public.plg_fiscalbr_emitter_ownership FROM anon, authenticated;\nGRANT SELECT ON public.plg_fiscalbr_nfce_jobs TO authenticated;\nGRANT SELECT ON public.plg_fiscalbr_nfce_events TO authenticated;\nGRANT SELECT ON public.plg_fiscalbr_emitter_ownership TO authenticated;\nGRANT ALL ON public.plg_fiscalbr_nfce_jobs TO service_role;\nGRANT ALL ON public.plg_fiscalbr_nfce_events TO service_role;\nGRANT ALL ON public.plg_fiscalbr_webhook_receipts TO service_role;\nGRANT ALL ON public.plg_fiscalbr_emitter_ownership TO service_role;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_register_emitter(\n p_tenant_id uuid,\n p_connection_id uuid,\n p_emitter_cnpj text,\n p_environment text,\n p_provider_emitter_id text DEFAULT NULL,\n p_certificate_expires_at timestamptz DEFAULT NULL,\n p_certificate_fingerprint text DEFAULT NULL,\n p_csc_ready boolean DEFAULT false\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_cnpj text := regexp_replace(coalesce(p_emitter_cnpj, ''), '[^0-9]', '', 'g');\nBEGIN\n IF v_cnpj !~ '^[0-9]{14}$' THEN\n RAISE EXCEPTION 'plugnotas_register_emitter: invalid CNPJ' USING ERRCODE = '22023';\n END IF;\n IF p_environment NOT IN ('sandbox', 'homologation') THEN\n RAISE EXCEPTION 'plugnotas_register_emitter: production is not enabled' USING ERRCODE = '22023';\n END IF;\n IF NOT EXISTS (\n SELECT 1 FROM public.connections c\n WHERE c.id = p_connection_id\n AND c.tenant_id = p_tenant_id\n AND c.connector_id = 'plugnotas'\n AND c.active\n ) THEN\n RAISE EXCEPTION 'plugnotas_register_emitter: active connection not found' USING ERRCODE = 'P0002';\n END IF;\n\n INSERT INTO public.plg_fiscalbr_emitter_ownership\n (emitter_cnpj, tenant_id, connection_id, environment, provider_emitter_id,\n certificate_expires_at, certificate_fingerprint, csc_ready, updated_at)\n VALUES\n (v_cnpj, p_tenant_id, p_connection_id, p_environment, p_provider_emitter_id,\n p_certificate_expires_at, p_certificate_fingerprint, p_csc_ready, now())\n ON CONFLICT (emitter_cnpj) DO UPDATE SET\n tenant_id = EXCLUDED.tenant_id,\n connection_id = EXCLUDED.connection_id,\n environment = EXCLUDED.environment,\n provider_emitter_id = EXCLUDED.provider_emitter_id,\n certificate_expires_at = EXCLUDED.certificate_expires_at,\n certificate_fingerprint = EXCLUDED.certificate_fingerprint,\n csc_ready = EXCLUDED.csc_ready,\n updated_at = now()\n WHERE public.plg_fiscalbr_emitter_ownership.tenant_id = EXCLUDED.tenant_id;\n\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_register_emitter: CNPJ belongs to another tenant' USING ERRCODE = '23505';\n END IF;\n\n UPDATE public.connections\n SET provider_account_key = v_cnpj,\n settings = settings || jsonb_build_object(\n 'environment', p_environment,\n 'certificateReady', p_certificate_expires_at IS NOT NULL,\n 'certificateExpiresAt', p_certificate_expires_at,\n 'certificateFingerprint', p_certificate_fingerprint,\n 'providerEmitterId', p_provider_emitter_id,\n 'cscReady', p_csc_ready\n ),\n status = CASE WHEN p_certificate_expires_at IS NOT NULL AND p_csc_ready THEN 'connected' ELSE 'pending' END,\n updated_at = now()\n WHERE id = p_connection_id AND tenant_id = p_tenant_id;\n\n RETURN jsonb_build_object('emitterCnpj', v_cnpj, 'environment', p_environment);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_disconnect_emitter(\n p_tenant_id uuid,\n p_connection_id uuid\n) RETURNS void\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n DELETE FROM public.plg_fiscalbr_emitter_ownership\n WHERE tenant_id = p_tenant_id AND connection_id = p_connection_id;\n UPDATE public.connections\n SET active = false, status = 'revoked', settings = '{}'::jsonb,\n provider_state = '{}'::jsonb, updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = p_connection_id AND connector_id = 'plugnotas';\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_create_nfce_draft_for_order(\n p_tenant_id uuid,\n p_order_id uuid\n) RETURNS uuid\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_order public.orders%ROWTYPE;\n v_nota_id uuid;\nBEGIN\n -- Serialize draft creation per tenant/order without adding a column or\n -- index to the financial plugin's table. The order itself remains the\n -- stable idempotency boundary for one NFC-e draft.\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || p_order_id::text, 0));\n\n SELECT * INTO v_order FROM public.orders\n WHERE tenant_id = p_tenant_id AND id = p_order_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_create_nfce_draft_for_order: order not found' USING ERRCODE = 'P0002';\n END IF;\n IF v_order.status NOT IN ('completed', 'paid', 'invoiced') THEN\n RAISE EXCEPTION 'plugnotas_create_nfce_draft_for_order: order is not closed' USING ERRCODE = '23514';\n END IF;\n IF NOT EXISTS (SELECT 1 FROM public.items i WHERE i.tenant_id = p_tenant_id AND i.order_id = p_order_id) THEN\n RAISE EXCEPTION 'plugnotas_create_nfce_draft_for_order: order has no items' USING ERRCODE = '23514';\n END IF;\n\n SELECT n.id INTO v_nota_id FROM public.plg_financial_nfe n\n WHERE n.tenant_id = p_tenant_id AND n.order_id = p_order_id AND n.model = 'nfce'\n ORDER BY n.created_at DESC LIMIT 1;\n IF v_nota_id IS NOT NULL THEN RETURN v_nota_id; END IF;\n\n INSERT INTO public.plg_financial_nfe\n (tenant_id, unit_id, model, status, order_id, contact_id, total_amount,\n emissor, metadata)\n VALUES\n (p_tenant_id, v_order.unit_id, 'nfce', 'draft', p_order_id, v_order.party_id,\n coalesce(v_order.total, 0), 'plugnotas',\n jsonb_build_object('source', 'order', 'orderKind', v_order.kind, 'orderChannel', v_order.channel))\n RETURNING id INTO v_nota_id;\n RETURN v_nota_id;\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_prepare_nfce(\n p_tenant_id uuid,\n p_nota_id uuid,\n p_connection_id uuid,\n p_idempotency_key text\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_nota public.plg_financial_nfe%ROWTYPE;\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_snapshot jsonb;\nBEGIN\n SELECT * INTO v_nota FROM public.plg_financial_nfe\n WHERE tenant_id = p_tenant_id AND id = p_nota_id FOR UPDATE;\n IF NOT FOUND OR v_nota.model <> 'nfce' OR v_nota.order_id IS NULL THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce: order-backed NFC-e not found' USING ERRCODE = 'P0002';\n END IF;\n IF v_nota.status NOT IN ('draft', 'error', 'processing') THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce: invalid document status %', v_nota.status USING ERRCODE = '23514';\n END IF;\n IF NOT EXISTS (\n SELECT 1 FROM public.plg_fiscalbr_emitter_ownership e\n WHERE e.tenant_id = p_tenant_id AND e.connection_id = p_connection_id\n AND e.csc_ready AND e.certificate_expires_at > now()\n ) THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce: emitter is not ready' USING ERRCODE = '23514';\n END IF;\n\n SELECT jsonb_build_object(\n 'nota', to_jsonb(v_nota),\n 'order', to_jsonb(o),\n 'items', coalesce((\n SELECT jsonb_agg(to_jsonb(i) ORDER BY i.sort_order, i.id)\n FROM public.items i\n WHERE i.tenant_id = p_tenant_id AND i.order_id = v_nota.order_id\n ), '[]'::jsonb),\n -- Product tax metadata must be frozen in the same transaction as the order\n -- lines. Looking products up in the Edge Function would let a retry emit\n -- with NCM/CFOP changed after the operator confirmed the document.\n 'products', coalesce((\n SELECT jsonb_agg(to_jsonb(p) ORDER BY p.id)\n FROM public.products p\n WHERE p.tenant_id = p_tenant_id\n AND p.id IN (\n SELECT i.product_id FROM public.items i\n WHERE i.tenant_id = p_tenant_id\n AND i.order_id = v_nota.order_id\n AND i.product_id IS NOT NULL\n )\n ), '[]'::jsonb)\n ) INTO v_snapshot\n FROM public.orders o\n WHERE o.tenant_id = p_tenant_id AND o.id = v_nota.order_id;\n\n IF jsonb_array_length(v_snapshot->'items') = 0 THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce: order has no items' USING ERRCODE = '23514';\n END IF;\n\n INSERT INTO public.plg_fiscalbr_nfce_jobs\n (tenant_id, nota_id, order_id, connection_id, operation, status,\n idempotency_key, request_snapshot, next_attempt_at, updated_at)\n VALUES\n (p_tenant_id, p_nota_id, v_nota.order_id, p_connection_id, 'issue', 'queued',\n p_idempotency_key, v_snapshot, now(), now())\n ON CONFLICT (tenant_id, idempotency_key) DO UPDATE\n SET updated_at = now()\n RETURNING * INTO v_job;\n\n UPDATE public.plg_financial_nfe\n SET status = 'processing', error_message = NULL,\n metadata = metadata || jsonb_build_object('plugnotas', jsonb_build_object(\n 'jobId', v_job.id, 'jobStatus', v_job.status, 'operation', 'issue'\n )), updated_at = now()\n WHERE id = p_nota_id AND tenant_id = p_tenant_id;\n\n INSERT INTO public.plg_fiscalbr_nfce_events (tenant_id, nota_id, job_id, event_type, payload)\n VALUES (p_tenant_id, p_nota_id, v_job.id, 'issue.queued', '{}'::jsonb);\n RETURN jsonb_build_object('jobId', v_job.id, 'snapshot', v_job.request_snapshot, 'replayed', v_job.attempts > 0);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_prepare_nfce_cancel(\n p_tenant_id uuid,\n p_nota_id uuid,\n p_connection_id uuid,\n p_reason text\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_nota public.plg_financial_nfe%ROWTYPE;\n v_job_id uuid;\n v_reason text := btrim(coalesce(p_reason, ''));\nBEGIN\n IF char_length(v_reason) NOT BETWEEN 15 AND 255 THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce_cancel: reason must contain 15 to 255 characters' USING ERRCODE = '22023';\n END IF;\n SELECT * INTO v_nota FROM public.plg_financial_nfe\n WHERE tenant_id = p_tenant_id AND id = p_nota_id FOR UPDATE;\n IF NOT FOUND OR v_nota.status <> 'issued' OR v_nota.access_key IS NULL THEN\n RAISE EXCEPTION 'plugnotas_prepare_nfce_cancel: authorized NFC-e not found' USING ERRCODE = '23514';\n END IF;\n\n INSERT INTO public.plg_fiscalbr_nfce_jobs\n (tenant_id, nota_id, order_id, connection_id, operation, status,\n idempotency_key, provider_document_id, integration_id,\n request_snapshot, next_attempt_at)\n VALUES\n (p_tenant_id, p_nota_id, v_nota.order_id, p_connection_id, 'cancel', 'queued',\n 'nfce-cancel:' || p_nota_id::text,\n v_nota.metadata #>> '{plugnotas,providerDocumentId}',\n v_nota.metadata #>> '{plugnotas,integrationId}',\n jsonb_build_object('reason', v_reason), now())\n ON CONFLICT (tenant_id, idempotency_key) DO UPDATE SET\n provider_document_id = coalesce(\n public.plg_fiscalbr_nfce_jobs.provider_document_id,\n EXCLUDED.provider_document_id\n ),\n integration_id = coalesce(\n public.plg_fiscalbr_nfce_jobs.integration_id,\n EXCLUDED.integration_id\n ),\n updated_at = now()\n RETURNING id INTO v_job_id;\n\n UPDATE public.plg_financial_nfe\n SET metadata = metadata || jsonb_build_object('plugnotas', jsonb_build_object(\n 'jobId', v_job_id, 'jobStatus', 'queued', 'operation', 'cancel', 'cancellationPending', true\n )), updated_at = now()\n WHERE id = p_nota_id AND tenant_id = p_tenant_id;\n RETURN jsonb_build_object('jobId', v_job_id, 'reason', v_reason);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_record_nfce_attempt(\n p_tenant_id uuid,\n p_job_id uuid,\n p_status text,\n p_provider_response jsonb DEFAULT '{}'::jsonb,\n p_error text DEFAULT NULL,\n p_next_attempt_at timestamptz DEFAULT NULL\n) RETURNS void\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n IF p_status NOT IN ('running', 'waiting', 'failed', 'manual_review') THEN\n RAISE EXCEPTION 'plugnotas_record_nfce_attempt: invalid status' USING ERRCODE = '22023';\n END IF;\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = p_status,\n -- One provider dispatch is one attempt. Moving that same attempt from\n -- running to waiting/failed must not count it a second time.\n attempts = attempts + CASE WHEN p_status = 'running' THEN 1 ELSE 0 END,\n provider_response = coalesce(p_provider_response, '{}'::jsonb),\n last_error = p_error, next_attempt_at = p_next_attempt_at,\n locked_until = NULL, updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = p_job_id;\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_apply_nfce_result(\n p_tenant_id uuid,\n p_job_id uuid,\n p_status text,\n p_provider_document_id text DEFAULT NULL,\n p_integration_id text DEFAULT NULL,\n p_number text DEFAULT NULL,\n p_series text DEFAULT NULL,\n p_access_key text DEFAULT NULL,\n p_message text DEFAULT NULL,\n p_provider_response jsonb DEFAULT '{}'::jsonb\n) RETURNS uuid\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_document_status text;\nBEGIN\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE tenant_id = p_tenant_id AND id = p_job_id FOR UPDATE;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: job not found' USING ERRCODE = 'P0002';\n END IF;\n IF p_status NOT IN ('processing', 'issued', 'cancelled', 'error') THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: invalid status' USING ERRCODE = '22023';\n END IF;\n\n v_document_status := CASE\n WHEN v_job.operation = 'cancel' AND p_status = 'processing' THEN 'issued'\n ELSE p_status\n END;\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = CASE\n WHEN p_status IN ('issued', 'cancelled') THEN 'succeeded'\n WHEN p_status = 'error' THEN 'failed'\n ELSE 'waiting'\n END,\n provider_document_id = coalesce(p_provider_document_id, provider_document_id),\n integration_id = coalesce(p_integration_id, integration_id),\n provider_response = coalesce(p_provider_response, '{}'::jsonb),\n last_error = CASE WHEN p_status = 'error' THEN p_message ELSE NULL END,\n next_attempt_at = CASE WHEN p_status = 'processing' THEN now() + interval '2 minutes' ELSE NULL END,\n locked_until = NULL, updated_at = now()\n WHERE id = p_job_id;\n\n UPDATE public.plg_financial_nfe\n SET status = v_document_status,\n number = coalesce(p_number, number),\n series = coalesce(p_series, series),\n access_key = coalesce(p_access_key, access_key),\n issued_at = CASE WHEN p_status = 'issued' THEN coalesce(issued_at, now()) ELSE issued_at END,\n error_message = CASE WHEN p_status = 'error' THEN p_message ELSE NULL END,\n metadata = metadata || jsonb_build_object('plugnotas', jsonb_strip_nulls(jsonb_build_object(\n 'jobId', p_job_id,\n 'jobStatus', CASE WHEN p_status IN ('issued', 'cancelled') THEN 'succeeded' WHEN p_status = 'error' THEN 'failed' ELSE 'waiting' END,\n 'operation', v_job.operation,\n 'providerDocumentId', coalesce(p_provider_document_id, v_job.provider_document_id),\n 'integrationId', coalesce(p_integration_id, v_job.integration_id),\n 'cancellationPending', v_job.operation = 'cancel' AND p_status = 'processing'\n ))),\n updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = v_job.nota_id;\n\n INSERT INTO public.plg_fiscalbr_nfce_events (tenant_id, nota_id, job_id, event_type, payload)\n VALUES (p_tenant_id, v_job.nota_id, p_job_id, v_job.operation || '.' || p_status,\n coalesce(p_provider_response, '{}'::jsonb));\n RETURN v_job.nota_id;\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_apply_nfce_webhook(\n p_provider_event_id text,\n p_payload_sha256 text,\n p_provider_document_id text,\n p_status text,\n p_integration_id text DEFAULT NULL,\n p_number text DEFAULT NULL,\n p_series text DEFAULT NULL,\n p_access_key text DEFAULT NULL,\n p_message text DEFAULT NULL,\n p_payload jsonb DEFAULT '{}'::jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_receipt_id bigint;\nBEGIN\n INSERT INTO public.plg_fiscalbr_webhook_receipts\n (provider_event_id, payload_sha256)\n VALUES (p_provider_event_id, p_payload_sha256)\n ON CONFLICT (provider, provider_event_id) DO NOTHING\n RETURNING id INTO v_receipt_id;\n IF v_receipt_id IS NULL THEN RETURN jsonb_build_object('duplicate', true); END IF;\n\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE provider_document_id = p_provider_document_id\n ORDER BY created_at DESC LIMIT 1;\n IF NOT FOUND THEN\n UPDATE public.plg_fiscalbr_webhook_receipts\n SET processed_at = now(), processing_error = 'job_not_found'\n WHERE id = v_receipt_id;\n RETURN jsonb_build_object('duplicate', false, 'matched', false);\n END IF;\n\n UPDATE public.plg_fiscalbr_webhook_receipts\n SET tenant_id = v_job.tenant_id, nota_id = v_job.nota_id, processed_at = now()\n WHERE id = v_receipt_id;\n PERFORM public.plugnotas_apply_nfce_result(\n v_job.tenant_id, v_job.id, p_status, p_provider_document_id,\n coalesce(p_integration_id, v_job.integration_id), p_number, p_series,\n p_access_key, p_message, p_payload\n );\n RETURN jsonb_build_object('duplicate', false, 'matched', true, 'jobId', v_job.id);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_get_artifact_locator(\n p_tenant_id uuid,\n p_nota_id uuid\n) RETURNS jsonb\nLANGUAGE sql SECURITY DEFINER SET search_path = '' STABLE AS $$\n SELECT jsonb_build_object(\n 'notaId', n.id,\n 'status', n.status,\n 'providerDocumentId', n.metadata #>> '{plugnotas,providerDocumentId}',\n 'integrationId', n.metadata #>> '{plugnotas,integrationId}'\n )\n FROM public.plg_financial_nfe n\n WHERE n.tenant_id = p_tenant_id AND n.id = p_nota_id\n AND n.status IN ('issued', 'cancelled');\n$$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_claim_nfce_recovery(\n p_limit integer DEFAULT 20\n) RETURNS SETOF public.plg_fiscalbr_nfce_jobs\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n RETURN QUERY\n WITH candidates AS (\n SELECT j.id FROM public.plg_fiscalbr_nfce_jobs j\n WHERE j.status IN ('queued', 'waiting')\n AND coalesce(j.next_attempt_at, j.created_at) <= now()\n AND coalesce(j.locked_until, '-infinity'::timestamptz) < now()\n ORDER BY coalesce(j.next_attempt_at, j.created_at), j.created_at\n FOR UPDATE SKIP LOCKED\n LIMIT greatest(1, least(coalesce(p_limit, 20), 100))\n )\n UPDATE public.plg_fiscalbr_nfce_jobs j\n SET status = 'running', locked_until = now() + interval '2 minutes', updated_at = now()\n FROM candidates c WHERE j.id = c.id\n RETURNING j.*;\nEND $$;\n\nREVOKE ALL ON FUNCTION public.plugnotas_register_emitter(uuid, uuid, text, text, text, timestamptz, text, boolean) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_disconnect_emitter(uuid, uuid) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_create_nfce_draft_for_order(uuid, uuid) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_prepare_nfce(uuid, uuid, uuid, text) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_prepare_nfce_cancel(uuid, uuid, uuid, text) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_record_nfce_attempt(uuid, uuid, text, jsonb, text, timestamptz) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_apply_nfce_result(uuid, uuid, text, text, text, text, text, text, text, jsonb) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_apply_nfce_webhook(text, text, text, text, text, text, text, text, text, jsonb) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_get_artifact_locator(uuid, uuid) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.plugnotas_claim_nfce_recovery(integer) FROM PUBLIC, anon, authenticated;\n\nGRANT EXECUTE ON FUNCTION public.plugnotas_register_emitter(uuid, uuid, text, text, text, timestamptz, text, boolean) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_disconnect_emitter(uuid, uuid) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_create_nfce_draft_for_order(uuid, uuid) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_prepare_nfce(uuid, uuid, uuid, text) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_prepare_nfce_cancel(uuid, uuid, uuid, text) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_record_nfce_attempt(uuid, uuid, text, jsonb, text, timestamptz) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_apply_nfce_result(uuid, uuid, text, text, text, text, text, text, text, jsonb) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_apply_nfce_webhook(text, text, text, text, text, text, text, text, text, jsonb) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_get_artifact_locator(uuid, uuid) TO service_role;\nGRANT EXECUTE ON FUNCTION public.plugnotas_claim_nfce_recovery(integer) TO service_role;\n`\n\nexport const MIGRATION_001_PRESERVE_TERMINAL_RESULTS_AND_RECOVER_LEASES = `-- Incremental recovery fix. Preserve 000_baseline.sql and its recorded checksum.\n-- Only existing fiscal functions change; no parallel ledger/schema or backfill.\n-- CREATE OR REPLACE retains the service-role-only ACL from the baseline.\n\nCREATE OR REPLACE FUNCTION public.plugnotas_record_nfce_attempt(\n p_tenant_id uuid,\n p_job_id uuid,\n p_status text,\n p_provider_response jsonb DEFAULT '{}'::jsonb,\n p_error text DEFAULT NULL,\n p_next_attempt_at timestamptz DEFAULT NULL\n) RETURNS void\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n IF p_status NOT IN ('running', 'waiting', 'failed', 'manual_review') THEN\n RAISE EXCEPTION 'plugnotas_record_nfce_attempt: invalid status' USING ERRCODE = '22023';\n END IF;\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = p_status,\n -- One provider dispatch is one attempt. Moving that same attempt from\n -- running to waiting/failed must not count it a second time.\n attempts = attempts + CASE WHEN p_status = 'running' THEN 1 ELSE 0 END,\n provider_response = coalesce(p_provider_response, '{}'::jsonb),\n last_error = p_error, next_attempt_at = p_next_attempt_at,\n locked_until = CASE WHEN p_status = 'running'\n THEN greatest(coalesce(locked_until, now()), now() + interval '2 minutes') ELSE NULL END,\n updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = p_job_id AND status <> 'succeeded';\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_apply_nfce_result(\n p_tenant_id uuid,\n p_job_id uuid,\n p_status text,\n p_provider_document_id text DEFAULT NULL,\n p_integration_id text DEFAULT NULL,\n p_number text DEFAULT NULL,\n p_series text DEFAULT NULL,\n p_access_key text DEFAULT NULL,\n p_message text DEFAULT NULL,\n p_provider_response jsonb DEFAULT '{}'::jsonb\n) RETURNS uuid\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_document_status text;\n v_existing_status text;\n v_job_status text;\nBEGIN\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE tenant_id = p_tenant_id AND id = p_job_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: job not found' USING ERRCODE = 'P0002';\n END IF;\n IF p_status NOT IN ('processing', 'issued', 'cancelled', 'error') THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: invalid status' USING ERRCODE = '22023';\n END IF;\n\n -- Match prepare/cancel's lock order: document, then job.\n SELECT status INTO v_existing_status FROM public.plg_financial_nfe\n WHERE tenant_id = p_tenant_id AND id = v_job.nota_id FOR UPDATE;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_result: document not found' USING ERRCODE = 'P0002';\n END IF;\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE tenant_id = p_tenant_id AND id = p_job_id FOR UPDATE;\n\n -- Late polling must not regress a concluded document or an active cancellation.\n IF v_existing_status = 'cancelled'\n OR (v_job.operation = 'issue' AND v_existing_status = 'issued' AND p_status <> 'cancelled')\n OR (v_job.status = 'succeeded' AND p_status IN ('processing', 'error')) THEN\n -- Old/interrupted jobs may still be running after the document concluded.\n -- Settle their lease too, otherwise recovery would claim them forever.\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = 'succeeded', locked_until = NULL, next_attempt_at = NULL, updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = p_job_id;\n RETURN v_job.nota_id;\n END IF;\n\n v_job_status := CASE\n WHEN p_status = 'cancelled' OR (v_job.operation = 'issue' AND p_status = 'issued') THEN 'succeeded'\n WHEN p_status = 'error' THEN 'failed'\n ELSE 'waiting' END;\n v_document_status := CASE\n WHEN v_job.operation = 'cancel' AND p_status <> 'cancelled' THEN v_existing_status\n ELSE p_status\n END;\n UPDATE public.plg_fiscalbr_nfce_jobs\n SET status = v_job_status,\n provider_document_id = coalesce(p_provider_document_id, provider_document_id),\n integration_id = coalesce(p_integration_id, integration_id),\n provider_response = coalesce(p_provider_response, '{}'::jsonb),\n last_error = CASE WHEN p_status = 'error' THEN p_message ELSE NULL END,\n next_attempt_at = CASE WHEN v_job_status = 'waiting' THEN now() + interval '2 minutes' ELSE NULL END,\n locked_until = NULL, updated_at = now()\n WHERE id = p_job_id;\n\n UPDATE public.plg_financial_nfe\n SET status = v_document_status,\n number = coalesce(p_number, number),\n series = coalesce(p_series, series),\n access_key = coalesce(p_access_key, access_key),\n issued_at = CASE WHEN p_status = 'issued' THEN coalesce(issued_at, now()) ELSE issued_at END,\n error_message = CASE WHEN v_document_status = 'error' THEN p_message ELSE NULL END,\n metadata = metadata || jsonb_build_object('plugnotas', jsonb_strip_nulls(jsonb_build_object(\n 'jobId', p_job_id,\n 'jobStatus', v_job_status,\n 'operation', v_job.operation,\n 'providerDocumentId', coalesce(p_provider_document_id, v_job.provider_document_id),\n 'integrationId', coalesce(p_integration_id, v_job.integration_id),\n 'cancellationPending', v_job.operation = 'cancel' AND v_job_status = 'waiting'\n ))),\n updated_at = now()\n WHERE tenant_id = p_tenant_id AND id = v_job.nota_id;\n\n INSERT INTO public.plg_fiscalbr_nfce_events (tenant_id, nota_id, job_id, event_type, payload)\n VALUES (p_tenant_id, v_job.nota_id, p_job_id, v_job.operation || '.' || p_status,\n coalesce(p_provider_response, '{}'::jsonb));\n RETURN v_job.nota_id;\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_apply_nfce_webhook(\n p_provider_event_id text,\n p_payload_sha256 text,\n p_provider_document_id text,\n p_status text,\n p_integration_id text DEFAULT NULL,\n p_number text DEFAULT NULL,\n p_series text DEFAULT NULL,\n p_access_key text DEFAULT NULL,\n p_message text DEFAULT NULL,\n p_payload jsonb DEFAULT '{}'::jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nDECLARE\n v_job public.plg_fiscalbr_nfce_jobs%ROWTYPE;\n v_receipt_id bigint;\n v_receipt public.plg_fiscalbr_webhook_receipts%ROWTYPE;\nBEGIN\n INSERT INTO public.plg_fiscalbr_webhook_receipts\n (provider_event_id, payload_sha256)\n VALUES (p_provider_event_id, p_payload_sha256)\n ON CONFLICT (provider, provider_event_id) DO NOTHING\n RETURNING id INTO v_receipt_id;\n SELECT * INTO v_receipt FROM public.plg_fiscalbr_webhook_receipts\n WHERE provider = 'plugnotas' AND provider_event_id = p_provider_event_id FOR UPDATE;\n v_receipt_id := v_receipt.id;\n IF v_receipt.payload_sha256 IS DISTINCT FROM p_payload_sha256 THEN\n RAISE EXCEPTION 'plugnotas_apply_nfce_webhook: conflicting event payload' USING ERRCODE = '22023';\n END IF;\n IF v_receipt.processed_at IS NOT NULL AND v_receipt.processing_error IS NULL THEN\n RETURN jsonb_build_object('duplicate', true, 'matched', true);\n END IF;\n\n SELECT * INTO v_job FROM public.plg_fiscalbr_nfce_jobs\n WHERE provider_document_id = p_provider_document_id\n ORDER BY created_at DESC LIMIT 1;\n IF NOT FOUND THEN\n UPDATE public.plg_fiscalbr_webhook_receipts\n SET processed_at = NULL, processing_error = 'job_not_found'\n WHERE id = v_receipt_id;\n RETURN jsonb_build_object('duplicate', false, 'matched', false);\n END IF;\n\n UPDATE public.plg_fiscalbr_webhook_receipts\n SET tenant_id = v_job.tenant_id, nota_id = v_job.nota_id, processed_at = now(), processing_error = NULL\n WHERE id = v_receipt_id;\n PERFORM public.plugnotas_apply_nfce_result(\n v_job.tenant_id, v_job.id, p_status, p_provider_document_id,\n coalesce(p_integration_id, v_job.integration_id), p_number, p_series,\n p_access_key, p_message, p_payload\n );\n RETURN jsonb_build_object('duplicate', false, 'matched', true, 'jobId', v_job.id);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.plugnotas_claim_nfce_recovery(\n p_limit integer DEFAULT 20\n) RETURNS SETOF public.plg_fiscalbr_nfce_jobs\nLANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$\nBEGIN\n RETURN QUERY\n WITH candidates AS (\n SELECT j.id FROM public.plg_fiscalbr_nfce_jobs j\n WHERE j.status IN ('queued', 'waiting', 'running')\n AND coalesce(j.next_attempt_at, j.created_at) <= now()\n AND coalesce(j.locked_until, '-infinity'::timestamptz) < now()\n ORDER BY coalesce(j.next_attempt_at, j.created_at), j.created_at\n FOR UPDATE SKIP LOCKED\n LIMIT greatest(1, least(coalesce(p_limit, 20), 100))\n )\n UPDATE public.plg_fiscalbr_nfce_jobs j\n SET status = 'running', locked_until = now() + interval '2 minutes', updated_at = now()\n FROM candidates c WHERE j.id = c.id\n RETURNING j.*;\nEND $$;\n`\n\nexport const MIGRATION_002_A_NOTA_QUE_CHEGA_TEM_ONDE_ESPERAR = `-- A nota que chega tem onde esperar.\n--\n-- O V1 recebe NF-e de fornecedor pela SEFAZ e guarda cada uma numa caixa de\n-- entrada antes de alguém decidir o que fazer com ela: manifestar, importar\n-- para o estoque, ou nada. Essa caixa não tinha destino no V2.\n--\n-- dfe_inbox 703 a nota recebida, com o XML inteiro\n-- dfe_inbox_items 3.215 o item da nota, com todo o tributo\n-- dfe_inbox_payments 739 a forma de pagamento declarada\n-- dfe_inbox_duplicatas 830 o vencimento da duplicata\n-- fiscal_groups 11 o grupo fiscal (CFOP, CST, alíquotas)\n--\n-- Os números somam os dois tenants: Espaço Facial e Pertinho do Céu. É o único\n-- domínio fiscal que os dois usam.\n--\n-- ── O XML é arquivo, e arquivo mora em public.documents ─────────────────────\n--\n-- \\`dfe_inbox.xml_content\\` é o XML inteiro numa coluna de texto, e\n-- \\`pdf_storage_path\\` aponta para o DANFE no storage do V1. Os dois são ARQUIVO,\n-- e o V2 já tem o arquétipo: \\`public.documents\\`, com kind, checksum, storage_*\n-- e a RLS de arquivo que uma coluna de texto nunca teria.\n--\n-- Então a extensão guarda um PONTEIRO — \\`document_id\\` — e os bytes vão para o\n-- arquétipo, pelo estágio de assets (\\`make mig-assets\\`), que é quem alcança\n-- object storage. Enquanto os bytes não chegam, \\`document_id\\` fica nulo e o\n-- caminho de origem fica em metadata: a linha é verdadeira nos dois momentos.\n--\n-- ── O tributo vem inteiro, e de propósito ───────────────────────────────────\n--\n-- 30 colunas de imposto por item (ICMS, ICMS-ST, PIS, COFINS, IPI, com base,\n-- alíquota e valor de cada). É muita coluna, e a tentação é jogar tudo num\n-- jsonb. Não: isto é documento fiscal recebido, e a pergunta que se faz dele é\n-- \"quanto de ICMS entrou neste mês\" — uma soma, sobre coluna, com índice. Um\n-- jsonb transformaria toda apuração numa varredura.\n--\n-- O que VAI para jsonb é o \\`raw_xml_item\\`, que já é jsonb na origem e existe\n-- para conferência, não para conta.\n--\n-- Idempotente.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_inbox_documents (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n unit_id uuid,\n -- O ponteiro para o arquétipo. Nulo enquanto os bytes não subiram — o\n -- caminho de origem fica em metadata até lá.\n document_id uuid,\n access_key text,\n nfe_number text,\n nfe_series text,\n nfe_model text,\n issue_date timestamp with time zone,\n received_at timestamp with time zone,\n status text DEFAULT 'received'::text NOT NULL,\n -- A manifestação do destinatário é outro eixo que o status: uma nota pode\n -- estar recebida e não manifestada, e é a manifestação que a SEFAZ cobra.\n manifestation_status text,\n manifested_at timestamp with time zone,\n manifestation_attempts integer DEFAULT 0 NOT NULL,\n manifestation_response jsonb,\n supplier_party_id uuid,\n supplier_cnpj text,\n supplier_name text,\n supplier_ie text,\n total_value numeric(14,2),\n total_products numeric(14,2),\n total_discount numeric(14,2),\n total_freight numeric(14,2),\n total_insurance numeric(14,2),\n total_other numeric(14,2),\n total_icms_base numeric(14,2),\n total_icms_value numeric(14,2),\n total_icms_st_base numeric(14,2),\n total_icms_st_value numeric(14,2),\n total_pis_value numeric(14,2),\n total_cofins_value numeric(14,2),\n total_ipi_value numeric(14,2),\n nfe_protocol text,\n nfe_authorized_at timestamp with time zone,\n carrier_name text,\n carrier_cnpj text,\n freight_mode_code text,\n additional_info text,\n reviewed_at timestamp with time zone,\n -- O que essa nota virou no estoque, quando virou. Nulo é nota recebida e\n -- não importada, que é a maioria.\n inventory_operation_id uuid,\n owner_id uuid,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE public.plg_fiscalbr_inbox_documents IS\n 'A NF-e de fornecedor recebida da SEFAZ, esperando manifestação ou importação. V1: dfe_inbox.';\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_documents.document_id IS\n 'V1: xml_content + pdf_storage_path. O XML e o DANFE são arquivo; os bytes moram em public.documents e aqui fica o ponteiro.';\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_inbox_items (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n inbox_document_id uuid NOT NULL,\n item_number integer,\n supplier_product_code text,\n ean_barcode text,\n ean_taxable text,\n description text,\n ncm text,\n cest text,\n cfop text,\n unit_commercial text,\n unit_taxable text,\n quantity_commercial numeric(18,4),\n quantity_taxable numeric(18,4),\n unit_price_commercial numeric(18,6),\n unit_price_taxable numeric(18,6),\n total_price numeric(14,2),\n discount numeric(14,2),\n freight numeric(14,2),\n insurance numeric(14,2),\n other_expenses numeric(14,2),\n icms_cst text, icms_csosn text, icms_origin text,\n icms_base numeric(14,2), icms_rate numeric(9,4), icms_value numeric(14,2),\n icms_st_base numeric(14,2), icms_st_value numeric(14,2),\n pis_cst text, pis_base numeric(14,2), pis_rate numeric(9,4), pis_value numeric(14,2),\n cofins_cst text, cofins_base numeric(14,2), cofins_rate numeric(9,4), cofins_value numeric(14,2),\n ipi_cst text, ipi_rate numeric(9,4), ipi_value numeric(14,2),\n -- O produto do V2 que esta linha da nota representa. \\`reconciled\\` é a\n -- decisão de quem conferiu; o id é o resultado dela.\n product_id uuid,\n reconciled boolean DEFAULT false NOT NULL,\n raw_xml_item jsonb,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE public.plg_fiscalbr_inbox_items IS\n 'O item da NF-e recebida, com o tributo em coluna — a apuração soma coluna, não varre jsonb. V1: dfe_inbox_items.';\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_inbox_payments (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n inbox_document_id uuid NOT NULL,\n payment_index integer,\n payment_indicator text,\n payment_type_code text,\n payment_type_label text,\n value numeric(14,2),\n change_given numeric(14,2),\n card_brand text,\n card_acquirer_cnpj text,\n card_auth_code text,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_inbox_duplicates (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n inbox_document_id uuid NOT NULL,\n duplicate_index integer,\n number text,\n due_date date,\n value numeric(14,2),\n -- O que essa duplicata virou no contas a pagar, se alguém a lançou.\n installment_id uuid,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE public.plg_fiscalbr_inbox_duplicates IS\n 'O vencimento declarado na NF-e recebida. Vira parcela do contas a pagar quando alguém lança a nota. V1: dfe_inbox_duplicatas.';\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_tax_groups (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n name text NOT NULL,\n cfop text,\n csosn text,\n cst text,\n icms_origin text,\n icms_rate numeric(9,4),\n icms_bc_mode text,\n pis_situation text,\n pis_rate numeric(9,4),\n cofins_situation text,\n cofins_rate numeric(9,4),\n -- A reforma tributária já está no cadastro do V1 e vem junto: deixar de\n -- fora obrigaria a recadastrar tudo no dia em que IBS/CBS valerem.\n ibs_cbs_situation text,\n ibs_cbs_classification text,\n base_calculation_mode text,\n benefit_code text,\n cest text,\n poverty_fund_rate numeric(9,4),\n is_active boolean DEFAULT true NOT NULL,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE public.plg_fiscalbr_tax_groups IS\n 'O grupo fiscal: CFOP, CST/CSOSN e alíquotas que o produto herda na emissão. V1: fiscal_groups. Traz IBS/CBS porque o cadastro do V1 já os tem.';\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- As chaves, os índices e a cerca\n-- ═══════════════════════════════════════════════════════════════════════════\n\nDO $$\nDECLARE t text;\nBEGIN\n FOREACH t IN ARRAY ARRAY['plg_fiscalbr_inbox_documents', 'plg_fiscalbr_inbox_items',\n 'plg_fiscalbr_inbox_payments', 'plg_fiscalbr_inbox_duplicates',\n 'plg_fiscalbr_tax_groups'] LOOP\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conrelid = ('public.' || t)::regclass AND contype = 'p') THEN\n EXECUTE format('ALTER TABLE ONLY public.%I ADD CONSTRAINT %I PRIMARY KEY (id)', t, t || '_pkey');\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = t || '_tenant_id_id_key') THEN\n EXECUTE format('ALTER TABLE ONLY public.%I ADD CONSTRAINT %I UNIQUE (tenant_id, id)', t, t || '_tenant_id_id_key');\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = t || '_tenant_fkey') THEN\n EXECUTE format('ALTER TABLE ONLY public.%I ADD CONSTRAINT %I FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE', t, t || '_tenant_fkey');\n END IF;\n END LOOP;\nEND $$;\n\nDO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_documents_unit_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_documents ADD CONSTRAINT plg_fiscalbr_inbox_documents_unit_fkey\n FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\n END IF;\n -- O arquivo pode ser apagado sem levar a nota junto: a nota fiscal existe\n -- mesmo sem o XML à mão, e é ela que a SEFAZ conhece.\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_documents_document_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_documents ADD CONSTRAINT plg_fiscalbr_inbox_documents_document_fkey\n FOREIGN KEY (document_id) REFERENCES public.documents(id) ON DELETE SET NULL;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_documents_supplier_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_documents ADD CONSTRAINT plg_fiscalbr_inbox_documents_supplier_fkey\n FOREIGN KEY (supplier_party_id) REFERENCES public.people(id) ON DELETE SET NULL;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_documents_operation_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_documents ADD CONSTRAINT plg_fiscalbr_inbox_documents_operation_fkey\n FOREIGN KEY (inventory_operation_id) REFERENCES public.plg_inventory_operations(id) ON DELETE SET NULL;\n END IF;\n\n -- Item, pagamento e duplicata não existem fora da nota: CASCADE.\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_document_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_items ADD CONSTRAINT plg_fiscalbr_inbox_items_document_fkey\n FOREIGN KEY (tenant_id, inbox_document_id) REFERENCES public.plg_fiscalbr_inbox_documents(tenant_id, id) ON DELETE CASCADE;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_product_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_items ADD CONSTRAINT plg_fiscalbr_inbox_items_product_fkey\n FOREIGN KEY (product_id) REFERENCES public.products(id) ON DELETE SET NULL;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_payments_document_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_payments ADD CONSTRAINT plg_fiscalbr_inbox_payments_document_fkey\n FOREIGN KEY (tenant_id, inbox_document_id) REFERENCES public.plg_fiscalbr_inbox_documents(tenant_id, id) ON DELETE CASCADE;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_duplicates_document_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_duplicates ADD CONSTRAINT plg_fiscalbr_inbox_duplicates_document_fkey\n FOREIGN KEY (tenant_id, inbox_document_id) REFERENCES public.plg_fiscalbr_inbox_documents(tenant_id, id) ON DELETE CASCADE;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_duplicates_installment_fkey') THEN\n ALTER TABLE ONLY public.plg_fiscalbr_inbox_duplicates ADD CONSTRAINT plg_fiscalbr_inbox_duplicates_installment_fkey\n FOREIGN KEY (installment_id) REFERENCES public.plg_financial_invoice_installments(id) ON DELETE SET NULL;\n END IF;\nEND $$;\n\n-- A chave de acesso é única por casa: a mesma nota chegando duas vezes da SEFAZ\n-- é a mesma nota, e é isso que impede a importação em dobro.\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_inbox_documents_access_key_uidx\n ON public.plg_fiscalbr_inbox_documents USING btree (tenant_id, access_key)\n WHERE access_key IS NOT NULL;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_documents_pending_idx\n ON public.plg_fiscalbr_inbox_documents USING btree (tenant_id, unit_id, issue_date DESC)\n WHERE inventory_operation_id IS NULL;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_items_document_idx\n ON public.plg_fiscalbr_inbox_items USING btree (tenant_id, inbox_document_id);\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_items_product_idx\n ON public.plg_fiscalbr_inbox_items USING btree (tenant_id, product_id) WHERE product_id IS NOT NULL;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_payments_document_idx\n ON public.plg_fiscalbr_inbox_payments USING btree (tenant_id, inbox_document_id);\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_duplicates_document_idx\n ON public.plg_fiscalbr_inbox_duplicates USING btree (tenant_id, inbox_document_id);\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_tax_groups_name_uidx\n ON public.plg_fiscalbr_tax_groups USING btree (tenant_id, lower(name));\n\nDO $$\nDECLARE t text;\nBEGIN\n FOREACH t IN ARRAY ARRAY['plg_fiscalbr_inbox_documents', 'plg_fiscalbr_inbox_items',\n 'plg_fiscalbr_inbox_payments', 'plg_fiscalbr_inbox_duplicates',\n 'plg_fiscalbr_tax_groups'] LOOP\n EXECUTE format('DROP TRIGGER IF EXISTS %I ON public.%I', t || '_updated_at', t);\n EXECUTE format('CREATE TRIGGER %I BEFORE UPDATE ON public.%I FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at()', t || '_updated_at', t);\n END LOOP;\nEND $$;\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- Quem enxerga\n-- ═══════════════════════════════════════════════════════════════════════════\n--\n-- Nota fiscal é do FINANCEIRO, e a permissão é a que ele já usa. A caixa de\n-- entrada não tem unidade nos filhos — eles herdam a da nota —, então o escopo\n-- de unidade vale só no documento; o resto é do tenant, e é a CASCADE da FK que\n-- garante que ninguém veja filho de nota alheia.\n-- RLS, uma a uma e por extenso. O laço adiante já liga tudo isto — mas ele liga\n-- por \\`EXECUTE format(...)\\`, e o portão que revisa plugin lê o ARQUIVO, não o\n-- banco: para ele, tabela com tenant_id e sem um ENABLE literal é tabela\n-- aberta. Uma garantia que o revisor não consegue ler é uma garantia que\n-- ninguém confere.\nALTER TABLE public.plg_fiscalbr_inbox_documents ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_inbox_items ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_tax_groups ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_inbox_payments ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_inbox_duplicates ENABLE ROW LEVEL SECURITY;\n\nDO $$\nDECLARE\n t text;\n doc boolean;\nBEGIN\n FOREACH t IN ARRAY ARRAY['plg_fiscalbr_inbox_documents', 'plg_fiscalbr_inbox_items',\n 'plg_fiscalbr_inbox_payments', 'plg_fiscalbr_inbox_duplicates',\n 'plg_fiscalbr_tax_groups'] LOOP\n doc := t = 'plg_fiscalbr_inbox_documents';\n EXECUTE format('ALTER TABLE public.%I FORCE ROW LEVEL SECURITY', t);\n EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', t);\n EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE public.%I TO authenticated', t);\n EXECUTE format('GRANT ALL ON TABLE public.%I TO service_role', t);\n\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_authz_select', t);\n EXECUTE format($f$CREATE POLICY %I ON public.%I FOR SELECT TO authenticated USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (%s)\n AND (SELECT app.has_permission('financial.read', %s)))$f$,\n t || '_authz_select', t,\n CASE WHEN doc THEN format('unit_id IS NULL OR (SELECT app.has_unit(%I.unit_id))', t) ELSE 'true' END,\n CASE WHEN doc THEN format('%I.unit_id', t) ELSE 'NULL::uuid' END);\n\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_authz_write', t);\n EXECUTE format($f$CREATE POLICY %I ON public.%I FOR ALL TO authenticated USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.edit', %s)))\n WITH CHECK (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.edit', %s)))$f$,\n t || '_authz_write', t,\n CASE WHEN doc THEN format('%I.unit_id', t) ELSE 'NULL::uuid' END,\n CASE WHEN doc THEN format('%I.unit_id', t) ELSE 'NULL::uuid' END);\n END LOOP;\nEND $$;\n\nINSERT INTO public.scoped_resources (resource_table, unit_column, owner_column, shareable, default_visibility, label)\nVALUES ('plg_fiscalbr_inbox_documents', 'unit_id', 'owner_id', false, 'unit', 'Notas recebidas')\nON CONFLICT (resource_table) DO UPDATE\n SET unit_column = EXCLUDED.unit_column, default_visibility = EXCLUDED.default_visibility, label = EXCLUDED.label;\n`\n\nexport const MIGRATION_003_A_CAIXA_DE_ENTRADA_ATRAVESSA = `-- A caixa de entrada atravessa.\n--\n-- A 002 fez as cinco tabelas. Esta escreve o de-para. As cinco usam o writer\n-- genérico \\`by_shape\\` (spine 123): as colunas do destino foram desenhadas\n-- olhando a origem, então o que falta é dizer qual nome vira qual — não uma\n-- função de upsert por tabela.\n--\n-- ── O arquivo não vem por aqui ──────────────────────────────────────────────\n--\n-- \\`xml_content\\` guarda o XML inteiro e \\`pdf_storage_path\\` aponta para o DANFE.\n-- Os dois saem do de-para com \\`-\\`: arquivo atravessa pelo estágio de assets,\n-- que é quem alcança object storage, e vira linha de \\`public.documents\\`. O\n-- caminho de origem fica em metadata para o estágio achar.\n--\n-- ── O fornecedor fica para a costura ────────────────────────────────────────\n--\n-- \\`supplier_party_id\\` não é preenchido aqui. A origem guarda CNPJ e nome, não\n-- um id de contato, e casar CNPJ com \\`public.people\\` é uma decisão de\n-- identidade — a mesma que já pôs 438 clientes em quarentena. Fica nulo, com o\n-- CNPJ na coluna ao lado, e uma passada de costura resolve quando alguém\n-- decidir a regra.\n--\n-- Idempotente.\n\nSET LOCAL migration.allowlist_unlock = 'on';\n\nSELECT migration._allow(\n 'fiscal_groups', 'public.plg_fiscalbr_tax_groups', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_tax_groups'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'name', 'name',\n 'cfop', 'cfop',\n 'csosn', 'csosn',\n 'cst', 'cst',\n 'icms_origin', 'icms_origin',\n 'icms_rate', 'icms_rate',\n 'icms_modalidade_bc', 'icms_bc_mode',\n 'pis_situation', 'pis_situation',\n 'pis_rate', 'pis_rate',\n 'cofins_situation', 'cofins_situation',\n 'cofins_rate', 'cofins_rate',\n 'ibs_cbs_situation', 'ibs_cbs_situation',\n 'ibs_cbs_classification', 'ibs_cbs_classification',\n 'base_calculation_mode', 'base_calculation_mode',\n 'cbenef', 'benefit_code',\n 'cest', 'cest',\n 'poverty_fund_rate', 'poverty_fund_rate',\n 'active', 'is_active',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'O grupo fiscal: CFOP, CST/CSOSN e alíquotas que o produto herda na emissão. '\n 'IBS/CBS vêm junto porque o cadastro do V1 já os tem — deixar de fora '\n 'obrigaria a recadastrar tudo no dia em que a reforma valer.'\n);\n\nSELECT migration._allow(\n 'dfe_inbox', 'public.plg_fiscalbr_inbox_documents', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_inbox_documents'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'company_id', 'unit_id@companies',\n 'access_key', 'access_key',\n 'nfe_number', 'nfe_number',\n 'nfe_series', 'nfe_series',\n 'nfe_model', 'nfe_model',\n 'issue_date', 'issue_date',\n 'received_at', 'received_at',\n 'status', 'status',\n 'manifestation_status', 'manifestation_status',\n 'manifested_at', 'manifested_at',\n 'manifestation_attempts', 'manifestation_attempts',\n 'manifestation_response', 'manifestation_response',\n 'supplier_cnpj', 'supplier_cnpj',\n 'supplier_name', 'supplier_name',\n 'supplier_ie', 'supplier_ie',\n 'total_value', 'total_value',\n 'total_products', 'total_products',\n 'total_discount', 'total_discount',\n 'total_freight', 'total_freight',\n 'total_insurance', 'total_insurance',\n 'total_other', 'total_other',\n 'total_icms_base', 'total_icms_base',\n 'total_icms_value', 'total_icms_value',\n 'total_icms_st_base', 'total_icms_st_base',\n 'total_icms_st_value', 'total_icms_st_value',\n 'total_pis_value', 'total_pis_value',\n 'total_cofins_value', 'total_cofins_value',\n 'total_ipi_value', 'total_ipi_value',\n 'nfe_protocol', 'nfe_protocol') ||\n -- \\`jsonb_build_object\\` aceita no máximo 100 argumentos, e este de-para tem\n -- 59 pares. Dois objetos concatenados, e não uma tabela a menos.\n jsonb_build_object(\n 'nfe_authorized_at', 'nfe_authorized_at',\n 'carrier_name', 'carrier_name',\n 'carrier_cnpj', 'carrier_cnpj',\n 'freight_mode_code', 'freight_mode_code',\n 'additional_info', 'additional_info',\n 'reviewed_at', 'reviewed_at',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'reviewed_by', '-',\n 'xml_content', '-',\n 'pdf_storage_path', 'jsonb:fiscalbr.v1_pdf_path',\n 'pdf_fetched_at', 'jsonb:fiscalbr.v1_pdf_fetched_at',\n 'danfe_import_id', 'jsonb:fiscalbr.v1_danfe_import_ref',\n 'plugnotas_payload', 'jsonb:fiscalbr.v1_plugnotas_payload',\n 'plugnotas_received_at', 'jsonb:fiscalbr.v1_plugnotas_received_at',\n 'nfe_cnf', 'jsonb:fiscalbr.nfe.cnf',\n 'nfe_natureza_operacao', 'jsonb:fiscalbr.nfe.natureza_operacao',\n 'nfe_finalidade', 'jsonb:fiscalbr.nfe.finalidade',\n 'nfe_tipo_operacao', 'jsonb:fiscalbr.nfe.tipo_operacao',\n 'nfe_destination', 'jsonb:fiscalbr.nfe.destination',\n 'supplier_address', 'jsonb:fiscalbr.supplier.street',\n 'supplier_number', 'jsonb:fiscalbr.supplier.number',\n 'supplier_complement', 'jsonb:fiscalbr.supplier.complement',\n 'supplier_neighborhood', 'jsonb:fiscalbr.supplier.neighborhood',\n 'supplier_city', 'jsonb:fiscalbr.supplier.city',\n 'supplier_state', 'jsonb:fiscalbr.supplier.state',\n 'supplier_postal_code', 'jsonb:fiscalbr.supplier.postal_code',\n 'supplier_phone', 'jsonb:fiscalbr.supplier.phone',\n 'supplier_email', 'jsonb:fiscalbr.supplier.email',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'A NF-e de fornecedor recebida da SEFAZ. \\`xml_content\\` sai com \\`-\\`: arquivo '\n 'atravessa pelo estágio de assets e vira public.documents, e o caminho do '\n 'DANFE fica em metadata para o estágio achar. O endereço do fornecedor vai '\n 'para metadata porque o fornecedor é \\`public.people\\`, e duplicá-lo em coluna '\n 'daria duas respostas para \"onde ele fica\".'\n);\n\nSELECT migration._allow(\n 'dfe_inbox_items', 'public.plg_fiscalbr_inbox_items', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_inbox_items'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'dfe_inbox_id', 'inbox_document_id@dfe_inbox',\n 'item_number', 'item_number',\n 'product_code_supplier', 'supplier_product_code',\n 'ean_barcode', 'ean_barcode',\n 'ean_trib', 'ean_taxable',\n 'description', 'description',\n 'ncm', 'ncm',\n 'cest', 'cest',\n 'cfop', 'cfop',\n 'unit_commercial', 'unit_commercial',\n 'unit_taxable', 'unit_taxable',\n 'quantity_commercial', 'quantity_commercial',\n 'quantity_taxable', 'quantity_taxable',\n 'unit_price_commercial', 'unit_price_commercial',\n 'unit_price_taxable', 'unit_price_taxable',\n 'total_price', 'total_price',\n 'discount', 'discount',\n 'freight', 'freight',\n 'insurance', 'insurance',\n 'other_expenses', 'other_expenses',\n 'icms_cst', 'icms_cst',\n 'icms_csosn', 'icms_csosn',\n 'icms_origin', 'icms_origin',\n 'icms_base', 'icms_base',\n 'icms_rate', 'icms_rate',\n 'icms_value', 'icms_value',\n 'icms_st_base', 'icms_st_base',\n 'icms_st_value', 'icms_st_value',\n 'pis_cst', 'pis_cst',\n 'pis_base', 'pis_base',\n 'pis_rate', 'pis_rate',\n 'pis_value', 'pis_value',\n 'cofins_cst', 'cofins_cst',\n 'cofins_base', 'cofins_base',\n 'cofins_rate', 'cofins_rate',\n 'cofins_value', 'cofins_value',\n 'ipi_cst', 'ipi_cst',\n 'ipi_rate', 'ipi_rate',\n 'ipi_value', 'ipi_value',\n 'linked_product_id', 'product_id@products',\n 'reconciled', 'reconciled',\n 'raw_xml_item', 'raw_xml_item',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'O item da nota, com o tributo em COLUNA — a apuração soma coluna, não varre '\n 'jsonb. \\`raw_xml_item\\` é a exceção: já é jsonb na origem e serve para '\n 'conferência, não para conta.'\n);\n\nSELECT migration._allow(\n 'dfe_inbox_payments', 'public.plg_fiscalbr_inbox_payments', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_inbox_payments'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'dfe_inbox_id', 'inbox_document_id@dfe_inbox',\n 'payment_index', 'payment_index',\n 'indicador_pagamento', 'payment_indicator',\n 'tipo_pagamento_code', 'payment_type_code',\n 'tipo_pagamento_label', 'payment_type_label',\n 'value', 'value',\n 'troco', 'change_given',\n 'card_flag', 'card_brand',\n 'card_acquirer_cnpj', 'card_acquirer_cnpj',\n 'card_auth_code', 'card_auth_code',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'A forma de pagamento declarada na nota recebida.'\n);\n\nSELECT migration._allow(\n 'dfe_inbox_duplicatas', 'public.plg_fiscalbr_inbox_duplicates', 'fiscal_br', 'by_shape',\n jsonb_build_object('target', 'public.plg_fiscalbr_inbox_duplicates'),\n NULL::text[],\n jsonb_build_object(\n 'uuid', 'id',\n 'dfe_inbox_id', 'inbox_document_id@dfe_inbox',\n 'duplicata_index', 'duplicate_index',\n 'numero', 'number',\n 'vencimento', 'due_date',\n 'valor', 'value',\n 'created_at', 'created_at',\n 'updated_at', 'updated_at',\n 'tenant_id', '-',\n 'id', 'jsonb:fiscalbr.v1_ref'),\n 'O vencimento declarado na nota. Vira parcela do contas a pagar quando alguém '\n 'lança a nota — \\`installment_id\\` fica nulo até lá, porque a parcela é '\n 'decisão de quem lança, não da SEFAZ.'\n);\n\nDELETE FROM migration.excluded_tables\n WHERE source_table IN ('dfe_inbox', 'dfe_inbox_items', 'dfe_inbox_payments',\n 'dfe_inbox_duplicatas', 'fiscal_groups');\n\nRESET migration.allowlist_unlock;\n`\n\nexport const MIGRATION_004_O_GRUPO_FISCAL_DO_V1_REPETE_NOME = `-- O grupo fiscal do V1 repete nome.\n--\n-- A 002 criou índice ÚNICO em \\`(tenant_id, lower(name))\\`. O V1 tem, no tenant\n-- 8, \"Bebidas Alcoólicas\", \"Bebidas Não Alcoólicas\" e \"Vinhos e Espumantes\"\n-- DUAS vezes cada — grupos fiscais diferentes com o mesmo rótulo, e o V1\n-- permite. Três das onze linhas foram para a quarentena por uma regra que eu\n-- inventei, não que a origem tenha.\n--\n-- O índice vira comum: serve para buscar, não para proibir. Quem quiser proibir\n-- decide isso na tela, com o dado já dentro — e sabendo quais três são.\n--\n-- Esta correção nasceu dentro de \\`financial/083\\` e mudou de arquivo: o\n-- financeiro roda ANTES do fiscal_br na corrente, e um arquivo do financeiro\n-- que mexe numa tabela do fiscal_br falha do zero com\n-- \\`relation \"public.plg_fiscalbr_tax_groups\" does not exist\\`. Cada plugin mexe\n-- na tabela que é dele.\n--\n-- Idempotente.\n\nDROP INDEX IF EXISTS public.plg_fiscalbr_tax_groups_name_uidx;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_tax_groups_name_idx\n ON public.plg_fiscalbr_tax_groups USING btree (tenant_id, lower(name));\n`\n\nexport const MIGRATION_005_A_NOTA_EMITIDA_E_UM_DOCUMENTO = `-- A nota emitida é um DOCUMENTO, e o documento já tem arquétipo.\n--\n-- O V1 do Pertinho do Céu emitiu 496 notas (todas NFC-e: 440 concluídas, 51\n-- rejeitadas, 5 com erro) e nenhuma delas tem onde morar no V2. O que existe\n-- hoje aqui é a caixa de ENTRADA (\\`plg_fiscalbr_inbox_*\\`, a nota que chega do\n-- fornecedor) e o JOB de saída (\\`plg_fiscalbr_nfce_jobs\\`, a tentativa de\n-- emitir). Falta o resultado: a nota que a casa emitiu, com chave, protocolo e\n-- XML.\n--\n-- ── Por que pendurar em \\`public.documents\\` e não numa tabela solta ─────────\n--\n-- Porque a pergunta que o operador faz não é \"quais notas fiscais existem\",\n-- é \"o que foi emitido sobre ESTE pedido\". Hoje a resposta está espalhada:\n-- o anexo do título está em \\`documents\\`, o formulário está em \\`documents\\`, a\n-- foto do ponto está em \\`documents\\` — e a nota fiscal ficaria de fora, sendo\n-- o documento mais documento de todos.\n--\n-- \\`documents\\` é o arquétipo: \\`kind\\` diz a espécie, \\`subject_type\\`/\\`subject_id\\`\n-- dizem sobre o quê, e o plugin pendura o que só ele entende numa extensão 1:1\n-- pela chave — exatamente como \\`plg_forms_documents\\` já faz. Esta migração\n-- segue esse padrão, não inventa outro.\n--\n-- ── O que entra e o que NÃO entra ─────────────────────────────────────────\n--\n-- ENTRA o artefato legal e a trilha:\n-- xml_content 113 de 496 preenchidos, 618 kB no total (5,6 kB cada).\n-- É a prova da emissão e não se regenera. Fica.\n-- os quatro payloads 108 kB para as 496 notas inteiras. É a conversa com a\n-- SEFAZ, e é ela que explica as 51 rejeições.\n-- pdf_storage_path 84 de 496. Vira \\`documents.storage_path\\` com\n-- \\`storage_provider = 'v1-pending'\\`, a mesma convenção\n-- que \\`upsert_document\\` usa: o REGISTRO chegou, os bytes\n-- ainda não.\n--\n-- NÃO entra nada que o V2 já saiba responder por conta própria, e a emissão\n-- nova do V2 continua nascendo por \\`plg_fiscalbr_nfce_jobs\\` — este arquivo é o\n-- destino do resultado, não um segundo caminho de emissão.\n--\n-- ── Os dois ponteiros da nota do V1, que não são o mesmo ──────────────────\n--\n-- fiscal_documents.order_id 496 de 496 — a COMANDA (\\`table_orders\\`)\n-- fiscal_documents.invoice_id 118 de 496 — a VENDA (\\`invoices\\`)\n--\n-- Os dois chegam em \\`public.orders\\` no V2, e às vezes na MESMA linha (a\n-- comanda que virou nota adota a venda). Guardar os dois na mesma coluna\n-- perderia justamente a distinção: \\`order_id\\` na extensão é a comanda; a venda\n-- vai para \\`plg_fiscalbr_document_orders\\`, que é N:N porque uma nota pode\n-- juntar várias (511 vínculos para 496 notas).\n--\n-- Idempotente.\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 1. A espécie entra no vocabulário\n-- ═══════════════════════════════════════════════════════════════════════════\n-- \\`migration.upsert_document\\` RECUSA espécie que não esteja aqui, e faz certo:\n-- é o registro que impede \\`kind\\` de virar campo livre.\n\nINSERT INTO public.document_kinds (kind, plugin, description, statuses, status)\nVALUES ('fiscal_document', 'fiscal_br',\n 'A nota fiscal que a casa EMITIU (NFC-e, NF-e, NFS-e), com chave, protocolo e XML',\n ARRAY['draft','processing','authorized','rejected','error','cancelled','substituted'],\n 'declared')\nON CONFLICT (kind) DO UPDATE\n SET plugin = EXCLUDED.plugin,\n description = EXCLUDED.description,\n statuses = EXCLUDED.statuses,\n updated_at = now();\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 2. A extensão: o que só o fiscal entende\n-- ═══════════════════════════════════════════════════════════════════════════\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_documents (\n -- A chave É o documento. Não há id próprio: a nota e o documento são a mesma\n -- coisa vista de dois lugares, e um segundo id só criaria a chance de eles\n -- discordarem.\n document_id uuid PRIMARY KEY REFERENCES public.documents(id) ON DELETE CASCADE,\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n unit_id uuid,\n -- A comanda/pedido que originou a emissão.\n order_id uuid REFERENCES public.orders(id) ON DELETE SET NULL,\n model text NOT NULL,\n environment text,\n status text NOT NULL,\n series text,\n number text,\n -- 44 dígitos. Sem CHECK de formato: uma nota REJEITADA não tem chave, e uma\n -- chave que a SEFAZ devolveu torta é informação, não erro de digitação.\n access_key text,\n verification_code text,\n protocol text,\n provider text,\n provider_document_id text,\n provider_integration_id text,\n total_value numeric(14,2),\n iss_value numeric(14,2),\n recipient_snapshot jsonb,\n request_payload jsonb,\n response_payload jsonb,\n status_payload jsonb,\n rejection_payload jsonb,\n source_snapshot jsonb,\n -- O artefato legal. 5,6 kB por nota nas 113 que o têm; não se regenera.\n xml text,\n authorized_at timestamptz,\n last_polled_at timestamptz,\n emitted_by_user_id uuid,\n cancelled_at timestamptz,\n cancel_reason text,\n cancelled_by_user_id uuid,\n -- A cadeia de substituição. Auto-referência, então SET NULL: apagar a nota\n -- substituída não pode arrastar a que a substituiu.\n substitutes_document_id uuid REFERENCES public.plg_fiscalbr_documents(document_id) ON DELETE SET NULL,\n substituted_by_document_id uuid REFERENCES public.plg_fiscalbr_documents(document_id) ON DELETE SET NULL,\n observations text,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\n\nDO $$ BEGIN\n ALTER TABLE public.plg_fiscalbr_documents\n ADD CONSTRAINT plg_fiscalbr_documents_unit_fkey\n FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\nEXCEPTION WHEN duplicate_object THEN NULL; END $$;\n\n-- A chave de acesso é única POR INQUILINO e só quando existe: 56 das 496 notas\n-- do Pertinho não têm chave nenhuma (rejeitadas e com erro), e um UNIQUE\n-- comum as empilharia todas num conflito só.\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_documents_chave_idx\n ON public.plg_fiscalbr_documents (tenant_id, access_key) WHERE access_key IS NOT NULL;\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_documents_order_idx\n ON public.plg_fiscalbr_documents (tenant_id, order_id);\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_documents_status_idx\n ON public.plg_fiscalbr_documents (tenant_id, unit_id, status, authorized_at DESC);\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 3. A trilha da emissão\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 1.886 eventos para 496 notas — quase quatro por nota. É aqui que a rejeição\n-- diz o motivo, e é o único lugar em que ela diz.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_document_events (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n unit_id uuid,\n document_id uuid NOT NULL REFERENCES public.plg_fiscalbr_documents(document_id) ON DELETE CASCADE,\n event_type text NOT NULL,\n status text,\n justification text,\n request_payload jsonb,\n response_payload jsonb,\n created_by_user_id uuid,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now()\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_document_events_doc_idx\n ON public.plg_fiscalbr_document_events (document_id, created_at DESC);\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 4. Quais vendas a nota cobre\n-- ═══════════════════════════════════════════════════════════════════════════\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_document_orders (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n document_id uuid NOT NULL REFERENCES public.plg_fiscalbr_documents(document_id) ON DELETE CASCADE,\n order_id uuid NOT NULL REFERENCES public.orders(id) ON DELETE CASCADE,\n created_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE (document_id, order_id)\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_document_orders_order_idx\n ON public.plg_fiscalbr_document_orders (tenant_id, order_id);\n\n-- ═══════════════════════════════════════════════════════════════════════════\n-- 5. updated_at e a cerca\n-- ═══════════════════════════════════════════════════════════════════════════\n\nDO $$ BEGIN\n CREATE TRIGGER plg_fiscalbr_documents_updated_at BEFORE UPDATE\n ON public.plg_fiscalbr_documents FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at();\nEXCEPTION WHEN duplicate_object THEN NULL; END $$;\n\n-- \\`app.current_tenant_id()\\` e não \\`user_tenant_ids()\\`, pela razão que a 013 do\n-- plugin-tables teve de consertar em produção: a segunda devolve a UNIÃO das\n-- contas do chamador e mostraria a nota fiscal de um cliente para outro.\nDO $$\nDECLARE t text;\nBEGIN\n FOREACH t IN ARRAY ARRAY['plg_fiscalbr_documents','plg_fiscalbr_document_events',\n 'plg_fiscalbr_document_orders'] LOOP\n EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', t);\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_select', t);\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_insert', t);\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_update', t);\n EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', t || '_delete', t);\n EXECUTE format('CREATE POLICY %I ON public.%I FOR SELECT USING (tenant_id = (select app.current_tenant_id()))', t || '_select', t);\n EXECUTE format('CREATE POLICY %I ON public.%I FOR INSERT WITH CHECK (tenant_id = (select app.current_tenant_id()))', t || '_insert', t);\n EXECUTE format('CREATE POLICY %I ON public.%I FOR UPDATE USING (tenant_id = (select app.current_tenant_id()))', t || '_update', t);\n EXECUTE format('CREATE POLICY %I ON public.%I FOR DELETE USING (tenant_id = (select app.current_tenant_id()))', t || '_delete', t);\n EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON public.%I TO authenticated', t);\n END LOOP;\nEND $$;\n`\n\nexport const MIGRATION_006_O_GRUPO_FISCAL_GANHA_O_RAIL = `-- O grupo fiscal ganha observação e etiqueta.\n--\n-- A tabela existe desde a 002 e nunca teve TELA: o grupo fiscal de toda conta\n-- migrada estava no banco sem porta. Estas duas colunas são o que falta para\n-- ele ter o mesmo rail de todo cadastro do produto — e a etiqueta tem uso\n-- imediato aqui, porque «Simples», «monofásico» e «substituição tributária»\n-- são recortes que nenhum campo do grupo responde e que decidem qual grupo\n-- alguém procura.\n--\n-- Idempotente.\n\nALTER TABLE public.plg_fiscalbr_tax_groups\n ADD COLUMN IF NOT EXISTS notes text,\n ADD COLUMN IF NOT EXISTS tags text[] DEFAULT '{}'::text[],\n ADD COLUMN IF NOT EXISTS unit_id uuid;\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_tax_groups_tags_gin\n ON public.plg_fiscalbr_tax_groups USING gin (tags);\n`\n\nexport const MIGRATION_007_A_RLS_DO_DOCUMENTO_PASSA_A_SER_LEGIVEL = `-- ---------------------------------------------------------------------------\n-- 007_a_rls_do_documento_passa_a_ser_legivel.sql\n--\n-- MESMO caso da 036 do plugin-tables, e a mesma medição antes de escrever.\n--\n-- \\`check-plugin-review\\` reprovou estas tabelas com *«cria public.X com\n-- tenant_id e nunca liga row security»*. Fui ao banco: **todas têm RLS ligada,\n-- com políticas** — medido no cluster do Pertinho em 29-09:\n--\n-- plg_fiscalbr_documents ........ rls=t, 4 políticas\n-- plg_fiscalbr_document_events .. rls=t, 4\n-- plg_fiscalbr_document_orders .. rls=t, 4\n--\n-- Não há vazamento. O \\`ENABLE\\` dessas tabelas mora dentro de um\n-- \\`DO $$ … EXECUTE format(...)\\`, e o portão lê o ARQUIVO, não o banco — uma\n-- garantia que o revisor não consegue ler é uma garantia que ninguém confere.\n--\n-- As migrations que as criam JÁ FORAM APLICADAS; reescrevê-las trocaria o\n-- checksum, que é a deriva de ledger pela qual este repositório para o mundo.\n-- Então a legibilidade entra por arquivo NOVO — o portão pergunta ao SQL\n-- INTEIRO do plugin.\n--\n-- Ligar RLS já ligada é no-op: isto não muda comportamento, torna conferível o\n-- que já era verdade.\n--\n-- Idempotente e replay-safe.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_fiscalbr_documents ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_document_events ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_document_orders ENABLE ROW LEVEL SECURITY;\n`\n\nexport const MIGRATION_008_A_NOTA_RECEBIDA_GUARDA_A_DECISAO_DE_ENTRADA = `-- ---------------------------------------------------------------------------\n-- 008_a_nota_recebida_guarda_a_decisao_de_entrada.sql\n--\n-- A 002 trouxe a nota; esta guarda o que se DECIDE sobre ela.\n--\n-- O inbox do V2 já sabe tudo que o XML diz: fornecedor, item, NCM, CFOP, os 30\n-- campos de tributo. O que não tem onde morar é a decisão que o operador toma\n-- em cima da nota, e é ela que transforma documento em estoque e em dinheiro:\n--\n-- a qual PRODUTO esta linha corresponde (product_id, já existia)\n-- que TIPO de entrada ela é (entry_type)\n-- em que UNIDADE de estoque, com que FATOR (stock_unit_id, conversion_factor)\n-- em que PLANO DE CONTAS ela cai (chart_account_id)\n-- com que CUSTO o produto fica (cost_mode, unit_cost_new)\n--\n-- Sem essas colunas a tela de conciliação não tem onde salvar, e \"importar nota\n-- fiscal\" viraria um leitor de XML — que é exatamente o que o V2 tinha.\n--\n-- ── O vocabulário vem do V1 medido, não de um enum inventado ────────────────\n--\n-- \\`danfe_import_items.entry_type\\` no V1 de produção (29-09-2026), 3.402 linhas:\n--\n-- insumo 2.303 revenda 546 patrimonio 280\n-- despesa 262 servico 11 (null) 5\n--\n-- São cinco, e duas delas — \\`despesa\\` e \\`servico\\` — NÃO viram estoque. É por\n-- isso que o tipo é coluna da linha e não da nota: a mesma NF-e traz o insumo\n-- que entra no estoque e a taxa de entrega que só vira despesa.\n--\n-- \\`cost_mode\\` tem UM valor em 3.407 linhas: \\`novo\\`. A média ponderada existe na\n-- tela do V1 e ninguém nunca escolheu. Fica no CHECK por paridade — tirar a\n-- opção é decisão de produto, e o dado não autoriza ninguém a tomá-la por aqui.\n--\n-- ── Por que \\`stock_movement_id\\` na linha, e não só na nota ──────────────────\n--\n-- Uma nota pode virar estoque PARCIALMENTE: o V1 tem os status \\`partial\\` e\n-- \\`partial_stocked\\` justamente porque o operador concilia 1 de 6 itens hoje e o\n-- resto amanhã. Guardar o movimento só no cabeçalho responderia \"esta nota\n-- entrou?\" e nunca \"esta LINHA entrou?\" — e é a segunda pergunta que decide se\n-- aceitar de novo duplica saldo.\n--\n-- ── O de-para é o que faz a segunda nota ser rápida ─────────────────────────\n--\n-- \\`supplier_product_mappings\\` no V1: (CNPJ do fornecedor, código do produto no\n-- fornecedor) → produto, tipo, plano, unidade, fator. 66 linhas na Artorius, e é\n-- o que faz a nota seguinte do mesmo fornecedor chegar já vinculada. Sem ele,\n-- toda importação recomeça do zero e o ganho de importar XML desaparece.\n--\n-- A chave é (tenant, CNPJ, código) e NÃO inclui unidade: o de-para é\n-- conhecimento sobre o catálogo do fornecedor, não sobre uma loja.\n--\n-- Aditivo e idempotente. Nada aqui apaga, renomeia ou reescreve dado existente.\n-- ---------------------------------------------------------------------------\n\n-- ── A decisão, linha a linha ────────────────────────────────────────────────\n\nALTER TABLE public.plg_fiscalbr_inbox_items\n ADD COLUMN IF NOT EXISTS entry_type text,\n ADD COLUMN IF NOT EXISTS chart_account_id uuid,\n ADD COLUMN IF NOT EXISTS stock_unit_id uuid,\n -- A quantidade que entra no estoque, já convertida. Derivada\n -- (quantity_commercial × conversion_factor), mas GRAVADA: é o número que o\n -- operador viu na tela antes de aceitar, e recalcular depois com um fator que\n -- alguém editou daria outra resposta para a mesma entrada.\n ADD COLUMN IF NOT EXISTS stock_quantity numeric(18,4),\n ADD COLUMN IF NOT EXISTS conversion_factor numeric(14,4) NOT NULL DEFAULT 1,\n ADD COLUMN IF NOT EXISTS cost_mode text,\n ADD COLUMN IF NOT EXISTS unit_cost_new numeric(18,6),\n -- O movimento que ESTA linha produziu. Nulo = não entrou.\n ADD COLUMN IF NOT EXISTS stock_movement_id uuid,\n -- Divergência: chegou menos do que a nota diz. O V1 guarda quantidade, motivo\n -- e observação, e a nota continua válida — quem responde pela diferença é o\n -- fornecedor, não o estoque.\n ADD COLUMN IF NOT EXISTS shortage_quantity numeric(18,4),\n ADD COLUMN IF NOT EXISTS shortage_reason text,\n ADD COLUMN IF NOT EXISTS shortage_note text;\n\nDO $$\nBEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_entry_type_chk') THEN\n ALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_entry_type_chk\n CHECK (entry_type IS NULL OR entry_type IN ('insumo','revenda','patrimonio','despesa','servico'));\n END IF;\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_cost_mode_chk') THEN\n ALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_cost_mode_chk\n CHECK (cost_mode IS NULL OR cost_mode IN ('novo','media'));\n END IF;\n -- Um fator zero ou negativo não converte nada: transformaria a quantidade da\n -- nota em zero estoque sem ninguém acusar. É o defeito silencioso que o\n -- FLOW.md do V1 nomeia («fator de conversão errado é silencioso»), e aqui ele\n -- deixa de ser possível.\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_items_factor_chk') THEN\n ALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_factor_chk CHECK (conversion_factor > 0);\n END IF;\nEND $$;\n\n-- FK lógica para o plano de contas e a unidade: as duas são de OUTROS plugins\n-- (financial e inventory), e a 000 deste plugin já estabelece que FK física\n-- entre plugins é proibida — instalar ou remover um addon não reescreve o\n-- schema do vizinho. A integridade é verificada na RPC, que é quem escreve.\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.chart_account_id IS\n 'Logical reference to plg_financial_chart_of_accounts.id — validated by the accept RPC, not by a cross-plugin FK.';\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.stock_unit_id IS\n 'Logical reference to plg_inventory_measurement_units.id — validated by the accept RPC.';\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.stock_quantity IS\n 'quantity_commercial x conversion_factor, stored as shown on screen before accepting.';\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_inbox_items_pending_idx\n ON public.plg_fiscalbr_inbox_items (tenant_id, inbox_document_id)\n WHERE reconciled IS NOT TRUE;\n\n-- ── A decisão no cabeçalho da nota ──────────────────────────────────────────\n\nALTER TABLE public.plg_fiscalbr_inbox_documents\n -- «itens sem plano herdarão este» — o plano da nota é padrão com HERANÇA, não\n -- obrigação por item. A frase é do V1 e a coluna existe para ela.\n ADD COLUMN IF NOT EXISTS default_chart_account_id uuid,\n -- O título a pagar que esta nota gerou. Mesma ideia do inventory_operation_id\n -- que a 002 já trouxe para o estoque: a nota aponta para as duas travessias.\n ADD COLUMN IF NOT EXISTS invoice_id uuid,\n ADD COLUMN IF NOT EXISTS stocked_at timestamptz,\n -- A natureza da operação declarada na NF-e («REM BONIFICACAO NAO\n -- CONTRIBUINTE»). O bloco de situação fiscal da conciliação mostra isso, e\n -- sem a coluna a tela mostraria um campo vazio.\n ADD COLUMN IF NOT EXISTS nature_operation text,\n ADD COLUMN IF NOT EXISTS default_location_id uuid;\n\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_documents.invoice_id IS\n 'Logical reference to plg_financial_invoices.id created by fiscalbr_accept_inbox_document.';\n\n-- ── A parcela sabe como se paga ─────────────────────────────────────────────\n--\n-- A duplicata do XML traz número, vencimento e valor. O que o operador acrescenta\n-- na tela é COMO ela se paga — e o boleto que ele anexa carrega o código de\n-- barras, que é o que a automação do V1 lê para preencher a parcela.\n\nALTER TABLE public.plg_fiscalbr_inbox_duplicates\n ADD COLUMN IF NOT EXISTS payment_type text,\n ADD COLUMN IF NOT EXISTS barcode text,\n ADD COLUMN IF NOT EXISTS pix_key text,\n ADD COLUMN IF NOT EXISTS payment_method_id uuid;\n\n-- O vocabulário é o do V1, medido em \\`danfe_payments.payment_type\\` (1.069 linhas):\n-- boleto 660 · sem_pagamento 108 · outro 107 · dinheiro 65 ·\n-- duplicata_mercantil 45 · pix 35 · cartao_credito 35 · cartao_debito 9 ·\n-- credito_loja 4 · vale_presente 1\nDO $$\nBEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_inbox_duplicates_payment_type_chk') THEN\n ALTER TABLE public.plg_fiscalbr_inbox_duplicates\n ADD CONSTRAINT plg_fiscalbr_inbox_duplicates_payment_type_chk\n CHECK (payment_type IS NULL OR payment_type IN (\n 'boleto','pix','dinheiro','cartao_credito','cartao_debito',\n 'duplicata_mercantil','credito_loja','vale_presente','sem_pagamento','outro'));\n END IF;\nEND $$;\n\n-- ── O de-para fornecedor × produto ──────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_supplier_product_map (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n -- Só dígitos, normalizado na escrita: o XML traz o CNPJ cru e a tela do V1\n -- aceitava pontuação, então duas grafias do mesmo fornecedor viravam dois\n -- de-para e a segunda nota não achava o primeiro.\n supplier_cnpj text NOT NULL,\n supplier_product_code text NOT NULL,\n product_id uuid NOT NULL REFERENCES public.products(id) ON DELETE CASCADE,\n entry_type text,\n chart_account_id uuid,\n stock_unit_id uuid,\n conversion_factor numeric(14,4) NOT NULL DEFAULT 1,\n cost_mode text,\n -- Quantas vezes este de-para acertou. Serve para a tela mostrar de onde veio o\n -- vínculo («já usado 12 vezes») em vez de um produto que apareceu sozinho.\n hit_count integer NOT NULL DEFAULT 0,\n last_used_at timestamptz,\n owner_id uuid,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT plg_fiscalbr_supplier_product_map_factor_chk CHECK (conversion_factor > 0),\n CONSTRAINT plg_fiscalbr_supplier_product_map_entry_type_chk\n CHECK (entry_type IS NULL OR entry_type IN ('insumo','revenda','patrimonio','despesa','servico')),\n CONSTRAINT plg_fiscalbr_supplier_product_map_cost_mode_chk\n CHECK (cost_mode IS NULL OR cost_mode IN ('novo','media'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_supplier_product_map_uq\n ON public.plg_fiscalbr_supplier_product_map (tenant_id, supplier_cnpj, supplier_product_code);\n\nALTER TABLE public.plg_fiscalbr_supplier_product_map ENABLE ROW LEVEL SECURITY;\n\n-- Mesmas políticas das tabelas do inbox (002): o de-para é conhecimento do\n-- financeiro sobre o fornecedor, então lê com \\`financial.read\\` e escreve com\n-- \\`financial.edit\\`. Não tem unit_id — é catálogo do fornecedor, não da loja.\nDROP POLICY IF EXISTS plg_fiscalbr_supplier_product_map_authz_select ON public.plg_fiscalbr_supplier_product_map;\nCREATE POLICY plg_fiscalbr_supplier_product_map_authz_select\n ON public.plg_fiscalbr_supplier_product_map FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL::uuid)));\n\nDROP POLICY IF EXISTS plg_fiscalbr_supplier_product_map_authz_write ON public.plg_fiscalbr_supplier_product_map;\nCREATE POLICY plg_fiscalbr_supplier_product_map_authz_write\n ON public.plg_fiscalbr_supplier_product_map FOR ALL TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.edit', NULL::uuid)))\n WITH CHECK (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.edit', NULL::uuid)));\n\nCOMMENT ON TABLE public.plg_fiscalbr_supplier_product_map IS\n 'Supplier catalogue memory: (CNPJ, supplier product code) -> the entry decision, so the next note from the same supplier arrives already bound. Mirrors V1 supplier_product_mappings.';\n`\n\nexport const MIGRATION_009_ACEITAR_A_NOTA_ESCREVE_ESTOQUE_E_TITULO_DE_UMA_VEZ = `-- ---------------------------------------------------------------------------\n-- 009_aceitar_a_nota_escreve_estoque_e_titulo_de_uma_vez.sql\n--\n-- É o arquivo que fecha o porte: «Aceitar» na conciliação dá entrada no estoque\n-- E cria a conta a pagar, numa transação só.\n--\n-- Medido no V1 de produção (tenant 12 da Artorius, 29-09-2026): **72 de 72**\n-- movimentos de estoque nasceram com \\`danfe_import_item_id\\`. Nenhum foi digitado.\n-- Dar ao V2 uma tela de movimentação manual e chamar isso de paridade seria\n-- entregar a tela que eles nunca abriram.\n--\n-- ── Não reimplementa estoque nem título. CHAMA quem já faz ──────────────────\n--\n-- O V2 já tem as duas primitivas, e as duas já são idempotentes:\n--\n-- public.inventory_receive(location, lines, document, idempotency_key)\n-- public.financial_create_invoice(direction, total, counterparty, …, key)\n--\n-- Reescrever INSERT em \\`plg_inventory_stock_movements\\` aqui daria uma segunda\n-- resposta para «como entra estoque» — e a posição é derivada por gatilho, então\n-- a segunda resposta sairia com saldo certo e sem ninguém acusar. A entrada de\n-- nota é mais um CHAMADOR dessas portas, como a requisição e a contagem.\n--\n-- Idempotência vem de graça daí: a chave é derivada da chave de acesso da NF-e,\n-- que é única por documento fiscal no Brasil. Aceitar duas vezes devolve o mesmo\n-- resultado sem escrever de novo — o AC7 do plano.\n--\n-- ── O total do título é a soma das PARCELAS ────────────────────────────────\n--\n-- Regra herdada da \\`plugin-financial/084\\`, que mediu: em 6,3% das notas a soma\n-- das duplicatas não bate com o total da nota. \\`plg_financial_invoices\\` é\n-- imutável depois de emitido, então um título aberto com o total errado fica\n-- com saldo errado para sempre em toda tela que faz «total − pago».\n-- O total da nota continua legível no \\`metadata\\` e na caixa de entrada.\n--\n-- E a MESMA chave de idempotência da 084 (\\`danfe:<chave>\\`): uma nota que o porte\n-- histórico já transformou em título não pode ganhar um segundo aqui.\n--\n-- ── Despesa e serviço não viram estoque ────────────────────────────────────\n--\n-- \\`entry_type\\` decide por LINHA. A mesma NF-e traz o insumo que entra no estoque\n-- e a taxa de entrega que só vira despesa — e as duas precisam ir para o mesmo\n-- título a pagar. Por isso a lista de linhas do estoque é um FILTRO sobre os\n-- itens, não os itens.\n--\n-- Idempotente. Só cria função.\n-- ---------------------------------------------------------------------------\n\n-- ── Ajudantes ──────────────────────────────────────────────────────────────\n\n-- O XML traz o CNPJ cru e a tela aceita pontuação. Duas grafias do mesmo\n-- fornecedor viravam dois de-para no V1, e a segunda nota não achava o primeiro.\nCREATE OR REPLACE FUNCTION public.plg_fiscalbr_digits(p_value text)\nRETURNS text LANGUAGE sql IMMUTABLE SET search_path TO '' AS $$\n SELECT regexp_replace(coalesce(p_value, ''), '[^0-9]', '', 'g')\n$$;\n\n-- ── Receber a nota: o XML já lido vira linhas ──────────────────────────────\n--\n-- O XML é decomposto no NAVEGADOR e chega aqui como jsonb. Parsear NF-e em\n-- PL/pgSQL seria escrever um leitor de XML dentro do banco, sem teste unitário\n-- possível e sem a mensagem de erro que a tela precisa dar para um arquivo que\n-- não é uma nota.\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_stage_inbox_document(p_note jsonb)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_key text := btrim(coalesce(p_note->>'access_key', ''));\n v_cnpj text := public.plg_fiscalbr_digits(p_note->'supplier'->>'cnpj');\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_unit uuid := nullif(p_note->>'unit_id', '')::uuid;\n v_party uuid;\n v_item jsonb;\n v_map public.plg_fiscalbr_supplier_product_map%ROWTYPE;\n v_n integer := 0;\n v_matched integer := 0;\nBEGIN\n PERFORM public.plg_financial_require_permission('financial.create', v_unit);\n\n IF length(v_key) <> 44 THEN\n RAISE EXCEPTION 'fiscalbr: chave de acesso inválida (esperado 44 dígitos, veio %)', length(v_key)\n USING ERRCODE = '22023';\n END IF;\n\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND access_key = v_key;\n\n -- Nota já aceita não é reimportada: o XML é o mesmo documento fiscal, e\n -- reescrever os itens apagaria a decisão que virou estoque e título.\n IF FOUND AND (v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL) THEN\n RETURN jsonb_build_object(\n 'document_id', v_doc.id, 'access_key', v_key, 'already_accepted', true,\n 'invoice_id', v_doc.invoice_id, 'items', 0, 'matched', 0);\n END IF;\n\n -- O fornecedor é uma PESSOA, não um nome. A 094 do financial documenta o custo\n -- de não ter o ponteiro: praticamente todo título nascido de DANFE ficou sem\n -- contraparte. Casar por CNPJ acerta; casar por nome acertaria 137 de 554.\n IF v_cnpj <> '' THEN\n SELECT id INTO v_party FROM public.people\n WHERE tenant_id = v_tenant AND public.plg_fiscalbr_digits(document_number) = v_cnpj\n LIMIT 1;\n END IF;\n\n INSERT INTO public.plg_fiscalbr_inbox_documents (\n tenant_id, unit_id, access_key, nfe_number, nfe_series, nfe_model, issue_date,\n received_at, status, nature_operation, supplier_party_id, supplier_cnpj,\n supplier_name, supplier_ie, total_value, total_products, total_discount,\n total_freight, total_insurance, total_other, additional_info, metadata)\n VALUES (\n v_tenant, v_unit, v_key, p_note->>'nfe_number', p_note->>'nfe_series',\n coalesce(p_note->>'nfe_model', '55'), nullif(p_note->>'issue_date', '')::date,\n now(), 'pending', p_note->>'nature_operation', v_party, nullif(v_cnpj, ''),\n p_note->'supplier'->>'name', p_note->'supplier'->>'ie',\n (p_note->'totals'->>'total')::numeric, (p_note->'totals'->>'products')::numeric,\n (p_note->'totals'->>'discount')::numeric, (p_note->'totals'->>'freight')::numeric,\n (p_note->'totals'->>'insurance')::numeric, (p_note->'totals'->>'other')::numeric,\n p_note->>'additional_info',\n jsonb_build_object('source', coalesce(p_note->>'source', 'xml_upload')))\n -- O índice único da 002 é PARCIAL (\\`WHERE access_key IS NOT NULL\\`), e a\n -- inferência do ON CONFLICT só o alcança repetindo o predicado. Sem ele o\n -- INSERT levanta «no unique or exclusion constraint matching» — e levantaria\n -- na primeira reimportação, não na aplicação.\n ON CONFLICT (tenant_id, access_key) WHERE access_key IS NOT NULL DO UPDATE SET\n -- Reimportar o mesmo XML corrige o cabeçalho; a contraparte só é preenchida\n -- quando está vazia, para não desfazer uma costura feita à mão.\n nfe_number = EXCLUDED.nfe_number,\n nature_operation = coalesce(EXCLUDED.nature_operation, public.plg_fiscalbr_inbox_documents.nature_operation),\n supplier_party_id = coalesce(public.plg_fiscalbr_inbox_documents.supplier_party_id, EXCLUDED.supplier_party_id),\n supplier_name = EXCLUDED.supplier_name,\n total_value = EXCLUDED.total_value,\n updated_at = now()\n RETURNING * INTO v_doc;\n\n -- Os itens e as duplicatas são do DOCUMENTO, não do operador: vêm do XML e\n -- podem ser reescritos enquanto a nota não foi aceita.\n DELETE FROM public.plg_fiscalbr_inbox_items WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n DELETE FROM public.plg_fiscalbr_inbox_duplicates WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n DELETE FROM public.plg_fiscalbr_inbox_payments WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n FOR v_item IN SELECT * FROM jsonb_array_elements(coalesce(p_note->'items', '[]'::jsonb)) LOOP\n v_n := v_n + 1;\n\n -- O de-para: a segunda nota do mesmo fornecedor chega já vinculada. É o que\n -- faz importar XML valer a pena — sem ele toda nota recomeça do zero.\n SELECT * INTO v_map FROM public.plg_fiscalbr_supplier_product_map\n WHERE tenant_id = v_tenant AND supplier_cnpj = v_cnpj\n AND supplier_product_code = coalesce(v_item->>'supplier_product_code', '');\n IF FOUND THEN v_matched := v_matched + 1; END IF;\n\n INSERT INTO public.plg_fiscalbr_inbox_items (\n tenant_id, inbox_document_id, item_number, supplier_product_code, ean_barcode,\n description, ncm, cest, cfop, unit_commercial, quantity_commercial,\n unit_price_commercial, total_price, discount, freight, other_expenses,\n icms_cst, icms_csosn, icms_base, icms_rate, icms_value,\n pis_value, cofins_value, ipi_value, raw_xml_item,\n product_id, entry_type, chart_account_id, stock_unit_id, conversion_factor,\n cost_mode, reconciled, stock_quantity, unit_cost_new)\n VALUES (\n v_tenant, v_doc.id, coalesce((v_item->>'item_number')::int, v_n),\n v_item->>'supplier_product_code', v_item->>'ean_barcode',\n v_item->>'description', v_item->>'ncm', v_item->>'cest', v_item->>'cfop',\n v_item->>'unit', (v_item->>'quantity')::numeric,\n (v_item->>'unit_price')::numeric, (v_item->>'total')::numeric,\n (v_item->>'discount')::numeric, (v_item->>'freight')::numeric,\n (v_item->>'other')::numeric,\n v_item->>'icms_cst', v_item->>'icms_csosn', (v_item->>'icms_base')::numeric,\n (v_item->>'icms_rate')::numeric, (v_item->>'icms_value')::numeric,\n (v_item->>'pis_value')::numeric, (v_item->>'cofins_value')::numeric,\n (v_item->>'ipi_value')::numeric, v_item,\n v_map.product_id, v_map.entry_type, v_map.chart_account_id, v_map.stock_unit_id,\n coalesce(v_map.conversion_factor, 1), coalesce(v_map.cost_mode, 'novo'),\n v_map.product_id IS NOT NULL,\n -- A quantidade de estoque já sai calculada quando o de-para deu o fator: é\n -- o número que a tela mostra antes de aceitar.\n CASE WHEN v_map.product_id IS NOT NULL\n THEN (v_item->>'quantity')::numeric * coalesce(v_map.conversion_factor, 1) END,\n CASE WHEN v_map.product_id IS NOT NULL AND coalesce(v_map.conversion_factor, 1) > 0\n THEN (v_item->>'unit_price')::numeric / coalesce(v_map.conversion_factor, 1) END);\n END LOOP;\n\n INSERT INTO public.plg_fiscalbr_inbox_duplicates (\n tenant_id, inbox_document_id, duplicate_index, number, due_date, value, payment_type)\n SELECT v_tenant, v_doc.id, coalesce((d->>'index')::int, ord), d->>'number',\n nullif(d->>'due_date', '')::date, (d->>'value')::numeric,\n nullif(d->>'payment_type', '')\n FROM jsonb_array_elements(coalesce(p_note->'duplicates', '[]'::jsonb)) WITH ORDINALITY AS t(d, ord);\n\n INSERT INTO public.plg_fiscalbr_inbox_payments (\n tenant_id, inbox_document_id, payment_index, payment_indicator,\n payment_type_code, payment_type_label, value)\n SELECT v_tenant, v_doc.id, coalesce((p->>'index')::int, ord), p->>'indicator',\n p->>'code', p->>'label', (p->>'value')::numeric\n FROM jsonb_array_elements(coalesce(p_note->'payments', '[]'::jsonb)) WITH ORDINALITY AS t(p, ord);\n\n RETURN jsonb_build_object(\n 'document_id', v_doc.id, 'access_key', v_key, 'already_accepted', false,\n 'supplier_party_id', v_party, 'items', v_n, 'matched', v_matched);\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_stage_inbox_document(jsonb) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_stage_inbox_document(jsonb) TO authenticated;\n\n-- ── Salvar a conciliação sem aceitar ───────────────────────────────────────\n--\n-- Conciliar e estocar são duas coisas no V1 — daí as duas colunas na lista, e\n-- daí a fila de 55 notas conciliadas e não estocadas. Quem salva o vínculo não\n-- está mandando dar entrada.\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_save_inbox_decision(\n p_document_id uuid,\n p_items jsonb,\n p_default_chart_account_id uuid DEFAULT NULL,\n p_default_location_id uuid DEFAULT NULL,\n p_duplicates jsonb DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_row jsonb;\n v_done integer := 0;\n v_total integer;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.edit', v_doc.unit_id);\n\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RAISE EXCEPTION 'fiscalbr: nota % já foi aceita — a decisão não muda depois do estoque', p_document_id\n USING ERRCODE = '23514';\n END IF;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n default_chart_account_id = coalesce(p_default_chart_account_id, default_chart_account_id),\n default_location_id = coalesce(p_default_location_id, default_location_id),\n reviewed_at = now(), updated_at = now()\n WHERE id = v_doc.id;\n\n FOR v_row IN SELECT * FROM jsonb_array_elements(coalesce(p_items, '[]'::jsonb)) LOOP\n UPDATE public.plg_fiscalbr_inbox_items i SET\n product_id = nullif(v_row->>'product_id', '')::uuid,\n entry_type = nullif(v_row->>'entry_type', ''),\n chart_account_id = nullif(v_row->>'chart_account_id', '')::uuid,\n stock_unit_id = nullif(v_row->>'stock_unit_id', '')::uuid,\n conversion_factor = coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1),\n cost_mode = coalesce(nullif(v_row->>'cost_mode', ''), 'novo'),\n shortage_quantity = nullif(v_row->>'shortage_quantity', '')::numeric,\n shortage_reason = nullif(v_row->>'shortage_reason', ''),\n shortage_note = nullif(v_row->>'shortage_note', ''),\n -- Derivadas, gravadas: é o que o operador viu.\n stock_quantity = i.quantity_commercial * coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1)\n - coalesce(nullif(v_row->>'shortage_quantity', '')::numeric, 0),\n unit_cost_new = CASE WHEN coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1) > 0\n THEN i.unit_price_commercial / coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1) END,\n -- Uma linha está conciliada quando sabe o que é. Despesa e serviço não\n -- pedem produto: elas nunca vão virar estoque.\n reconciled = CASE\n WHEN nullif(v_row->>'entry_type', '') IN ('despesa','servico') THEN true\n ELSE nullif(v_row->>'product_id', '') IS NOT NULL\n END,\n updated_at = now()\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n AND i.id = (v_row->>'id')::uuid;\n v_done := v_done + 1;\n END LOOP;\n\n IF p_duplicates IS NOT NULL THEN\n DELETE FROM public.plg_fiscalbr_inbox_duplicates\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n INSERT INTO public.plg_fiscalbr_inbox_duplicates (\n tenant_id, inbox_document_id, duplicate_index, number, due_date, value,\n payment_type, barcode, pix_key, payment_method_id)\n SELECT v_tenant, v_doc.id, coalesce((d->>'index')::int, ord), d->>'number',\n nullif(d->>'due_date', '')::date, (d->>'value')::numeric,\n nullif(d->>'payment_type', ''), nullif(d->>'barcode', ''),\n nullif(d->>'pix_key', ''), nullif(d->>'payment_method_id', '')::uuid\n FROM jsonb_array_elements(p_duplicates) WITH ORDINALITY AS t(d, ord);\n END IF;\n\n SELECT count(*) INTO v_total FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET status = CASE\n WHEN (SELECT count(*) FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id AND reconciled) = v_total\n THEN 'accepted' ELSE 'partial' END\n WHERE id = v_doc.id;\n\n RETURN jsonb_build_object('document_id', v_doc.id, 'saved', v_done, 'items', v_total,\n 'reconciled', (SELECT count(*) FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id AND reconciled));\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_save_inbox_decision(uuid, jsonb, uuid, uuid, jsonb) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_save_inbox_decision(uuid, jsonb, uuid, uuid, jsonb) TO authenticated;\n\n-- ── Aceitar: estoque e título, de uma vez ──────────────────────────────────\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_accept_inbox_document(\n p_document_id uuid,\n p_location_id uuid DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_loc uuid;\n v_lines jsonb := '[]'::jsonb;\n v_insts jsonb := '[]'::jsonb;\n v_recv jsonb;\n v_inv jsonb;\n v_it record;\n v_no integer := 0;\n v_total numeric := 0;\n v_stock_n integer := 0;\n v_key text;\n v_invoice uuid;\n -- Posição na lista de linhas → id do item da nota. \\`line_no\\` do movimento\n -- indexa este array direto.\n v_item_ids uuid[] := '{}';\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.create', v_doc.unit_id);\n\n -- Já aceita devolve o que aceitou. Não é erro: é a segunda vez que o operador\n -- clicou, e o AC7 diz que isso não pode dobrar nada.\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RETURN jsonb_build_object('document_id', v_doc.id, 'already_accepted', true,\n 'invoice_id', v_doc.invoice_id, 'operation_id', v_doc.inventory_operation_id);\n END IF;\n\n v_loc := coalesce(p_location_id, v_doc.default_location_id);\n\n -- Toda linha tem de saber o que é. Aceitar uma nota com item sem tipo gravaria\n -- um título cujo rateio ninguém consegue explicar depois.\n IF EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id\n AND (entry_type IS NULL OR entry_type = '')) THEN\n RAISE EXCEPTION 'fiscalbr: há item sem tipo de registro — conciliar antes de aceitar'\n USING ERRCODE = '23514';\n END IF;\n\n -- As linhas que viram estoque. Despesa e serviço ficam fora daqui e entram só\n -- no título.\n FOR v_it IN\n SELECT * FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id\n AND entry_type IN ('insumo','revenda','patrimonio')\n ORDER BY item_number\n LOOP\n IF v_it.product_id IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: item % é % e não tem produto vinculado', v_it.item_number, v_it.entry_type\n USING ERRCODE = '23514';\n END IF;\n v_no := v_no + 1;\n -- A ordem desta lista É o \\`line_no\\` que o movimento vai carregar. Guardo o\n -- id da linha na mesma posição para devolver o movimento ao item sem\n -- reconsultar — e sem depender de casar por produto, que repete quando a\n -- mesma mercadoria vem em duas linhas da nota.\n v_item_ids := v_item_ids || v_it.id;\n v_lines := v_lines || jsonb_build_object(\n 'product_id', v_it.product_id,\n 'quantity', coalesce(v_it.stock_quantity, v_it.quantity_commercial * v_it.conversion_factor),\n 'unit_cost', coalesce(v_it.unit_cost_new, v_it.unit_price_commercial / v_it.conversion_factor),\n 'measurement_unit_id', v_it.stock_unit_id,\n 'notes', v_it.description);\n END LOOP;\n v_stock_n := v_no;\n\n IF v_stock_n > 0 THEN\n IF v_loc IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: a nota tem % linha(s) de estoque e nenhum local de estoque escolhido', v_stock_n\n USING ERRCODE = '22023';\n END IF;\n -- A chave de acesso é única por documento fiscal no Brasil: é a chave de\n -- idempotência natural, e é ela que faz o segundo clique não dobrar saldo.\n v_recv := public.inventory_receive(\n v_loc, v_lines,\n jsonb_build_object(\n 'supplier_id', v_doc.supplier_party_id,\n 'date', v_doc.issue_date,\n 'type', 'nfe',\n 'ref', 'NF-e ' || coalesce(v_doc.nfe_number, '?'),\n 'notes', 'Entrada via DANFE NF-e ' || coalesce(v_doc.nfe_number, '?')),\n 'nfe:' || v_doc.access_key);\n\n -- Cada movimento volta para a SUA linha. Guardar só no cabeçalho responderia\n -- «esta nota entrou?» e nunca «esta linha entrou?» — e é a segunda pergunta\n -- que a conciliação parcial faz.\n --\n -- \\`line_no\\` do movimento é a posição na lista que montei acima, e\n -- \\`v_item_ids\\` está na mesma ordem: um join, não uma varredura por posição.\n UPDATE public.plg_fiscalbr_inbox_items i\n SET stock_movement_id = m.movement_id, updated_at = now()\n FROM (\n SELECT v_item_ids[(mov->>'line_no')::int] AS item_id, (mov->>'id')::uuid AS movement_id\n FROM jsonb_array_elements(coalesce(v_recv->'movements', '[]'::jsonb)) AS t(mov)\n WHERE (mov->>'line_no') IS NOT NULL\n ) m\n WHERE i.tenant_id = v_tenant AND i.id = m.item_id;\n END IF;\n\n -- ── O título ─────────────────────────────────────────────────────────────\n -- Total = soma das PARCELAS (regra da financial/084). Nota sem duplicata vira\n -- uma parcela só, no vencimento que a nota declarar ou na emissão.\n SELECT coalesce(sum(value), 0),\n coalesce(jsonb_agg(jsonb_build_object(\n 'number', coalesce(duplicate_index, 1),\n 'due_date', coalesce(due_date, v_doc.issue_date, current_date),\n 'amount', round(value, 2),\n 'metadata', jsonb_strip_nulls(jsonb_build_object(\n 'barcode', barcode, 'pixKey', pix_key, 'paymentType', payment_type,\n 'danfeNumber', number))) ORDER BY duplicate_index), '[]'::jsonb)\n INTO v_total, v_insts\n FROM public.plg_fiscalbr_inbox_duplicates\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n IF jsonb_array_length(v_insts) = 0 THEN\n v_total := round(coalesce(v_doc.total_value, 0), 2);\n v_insts := jsonb_build_array(jsonb_build_object(\n 'number', 1, 'due_date', coalesce(v_doc.issue_date, current_date), 'amount', v_total));\n ELSE\n v_total := round(v_total, 2);\n END IF;\n\n -- A MESMA chave da 084: nota já transformada em título pelo porte histórico\n -- não ganha um segundo aqui.\n v_key := 'danfe:' || v_doc.access_key;\n\n v_inv := public.financial_create_invoice(\n 'payable', v_total, v_doc.supplier_party_id, NULL, v_doc.unit_id, v_insts,\n v_doc.issue_date,\n 'NF-e ' || coalesce(v_doc.nfe_number, '?') || ' · ' || coalesce(v_doc.supplier_name, 'fornecedor'),\n NULL,\n jsonb_build_object(\n 'source', 'danfe',\n 'danfe', jsonb_strip_nulls(jsonb_build_object(\n 'accessKey', v_doc.access_key, 'number', v_doc.nfe_number,\n 'series', v_doc.nfe_series, 'supplierName', v_doc.supplier_name,\n 'supplierCnpj', v_doc.supplier_cnpj,\n -- O total da NOTA continua legível, mesmo quando difere do total do\n -- título. É a diferença que a 084 mediu em 6,3% das notas.\n 'noteTotal', v_doc.total_value,\n 'inboxDocumentId', v_doc.id))),\n v_key);\n v_invoice := (v_inv->>'invoice_id')::uuid;\n\n -- As linhas do título: TODOS os itens, inclusive despesa e serviço. É o que\n -- responde «de que essa conta é feita».\n INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)\n SELECT v_tenant, v_invoice, i.description, i.quantity_commercial, i.unit_price_commercial,\n round(coalesce(i.total_price, 0), 2), i.item_number,\n jsonb_strip_nulls(jsonb_build_object(\n 'itemKind', i.entry_type, 'referenceId', i.product_id,\n 'chartAccountId', i.chart_account_id, 'ncm', i.ncm, 'cfop', i.cfop,\n 'supplierProductCode', i.supplier_product_code))\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n ORDER BY i.item_number\n ON CONFLICT DO NOTHING;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n invoice_id = v_invoice,\n inventory_operation_id = coalesce((v_recv->>'operation_id')::uuid, inventory_operation_id),\n stocked_at = CASE WHEN v_stock_n > 0 THEN now() ELSE stocked_at END,\n status = 'accepted', updated_at = now()\n WHERE id = v_doc.id;\n\n -- ── O de-para aprende ────────────────────────────────────────────────────\n -- A decisão desta nota é o que faz a próxima do mesmo fornecedor chegar\n -- pronta. Guardar isto é o que separa «importei XML» de «o sistema sabe o meu\n -- fornecedor».\n INSERT INTO public.plg_fiscalbr_supplier_product_map (\n tenant_id, supplier_cnpj, supplier_product_code, product_id, entry_type,\n chart_account_id, stock_unit_id, conversion_factor, cost_mode, hit_count, last_used_at)\n SELECT v_tenant, v_doc.supplier_cnpj, i.supplier_product_code, i.product_id,\n i.entry_type, coalesce(i.chart_account_id, v_doc.default_chart_account_id),\n i.stock_unit_id, i.conversion_factor, i.cost_mode, 1, now()\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n AND i.product_id IS NOT NULL\n AND coalesce(v_doc.supplier_cnpj, '') <> ''\n AND coalesce(i.supplier_product_code, '') <> ''\n ON CONFLICT (tenant_id, supplier_cnpj, supplier_product_code) DO UPDATE SET\n product_id = EXCLUDED.product_id,\n entry_type = EXCLUDED.entry_type,\n chart_account_id = coalesce(EXCLUDED.chart_account_id, public.plg_fiscalbr_supplier_product_map.chart_account_id),\n stock_unit_id = coalesce(EXCLUDED.stock_unit_id, public.plg_fiscalbr_supplier_product_map.stock_unit_id),\n conversion_factor = EXCLUDED.conversion_factor,\n cost_mode = EXCLUDED.cost_mode,\n hit_count = public.plg_fiscalbr_supplier_product_map.hit_count + 1,\n last_used_at = now(),\n updated_at = now();\n\n RETURN jsonb_build_object(\n 'document_id', v_doc.id, 'already_accepted', false,\n 'invoice_id', v_invoice, 'invoice_total', v_total,\n 'installments', jsonb_array_length(v_insts),\n 'operation_id', v_recv->>'operation_id',\n 'stock_lines', v_stock_n,\n 'movements', coalesce(v_recv->'movements', '[]'::jsonb));\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_accept_inbox_document(uuid, uuid) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_accept_inbox_document(uuid, uuid) TO authenticated;\n\n-- ── Rejeitar ───────────────────────────────────────────────────────────────\n-- O rodapé do diálogo do V1 tem dois botões, e o outro também precisa existir:\n-- recusar a nota é dizer que ela não vira nada aqui — sem apagar o documento,\n-- que é fiscal e tem de continuar legível.\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_reject_inbox_document(\n p_document_id uuid, p_reason text DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.edit', v_doc.unit_id);\n\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RAISE EXCEPTION 'fiscalbr: nota % já virou estoque ou título — recusar não desfaz', p_document_id\n USING ERRCODE = '23514';\n END IF;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n status = 'rejected',\n metadata = metadata || jsonb_strip_nulls(jsonb_build_object('rejectReason', p_reason)),\n reviewed_at = now(), updated_at = now()\n WHERE id = v_doc.id;\n\n RETURN jsonb_build_object('document_id', v_doc.id, 'status', 'rejected');\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_reject_inbox_document(uuid, text) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_reject_inbox_document(uuid, text) TO authenticated;\n`\n\nexport const MIGRATION_010_A_DATA_DE_EMISSAO_E_INSTANTE_E_A_COMPETENCIA_E_DIA = `-- ---------------------------------------------------------------------------\n-- 010_a_data_de_emissao_e_instante_e_a_competencia_e_dia.sql\n--\n-- A 009 não conseguia aceitar nota nenhuma. Descoberto no primeiro teste com\n-- usuário logado de verdade, que é onde ela ia ser usada:\n--\n-- POST rpc/fiscalbr_accept_inbox_document → 404\n-- function public.financial_create_invoice(unknown, numeric, uuid, unknown,\n-- uuid, jsonb, timestamp with time zone, text, unknown, jsonb, text)\n-- does not exist\n--\n-- \\`plg_fiscalbr_inbox_documents.issue_date\\` é **timestamptz** — a NF-e declara um\n-- INSTANTE (\\`dhEmi\\`, com fuso), e a 002 preservou isso. Eu escrevi a chamada\n-- supondo \\`date\\`, e \\`financial_create_invoice\\` pede \\`p_competence_date date\\`.\n--\n-- Nenhum teste pegou porque nenhum podia: o SQL aplica, a função compila (o corpo\n-- de PL/pgSQL não resolve assinatura em CREATE), e o erro só existe na chamada.\n-- Foi preciso um usuário logado percorrendo o caminho.\n--\n-- ── Duas correções, não uma ────────────────────────────────────────────────\n--\n-- 1. \\`issue_date::date\\` onde a competência é pedida. Instante é quando a nota foi\n-- emitida; competência é o DIA a que o título pertence, e o mês do título vem\n-- dela — um \\`timestamptz\\` viajando para lá levaria fuso para dentro de uma\n-- conta contábil.\n--\n-- 2. **Todo argumento tipado na chamada.** A chamada posicional passava \\`'payable'\\`\n-- e \\`NULL\\` sem tipo, e o Postgres tem de adivinhar entre as sobrecargas. Adivinhar\n-- certo hoje e errado quando alguém acrescentar uma sobrecarga é o defeito que\n-- volta meses depois sem ninguém mexer neste arquivo. Agora vai \\`::text\\`,\n-- \\`::uuid\\`, \\`::date\\` em tudo.\n--\n-- Idempotente: só substitui o corpo de uma função.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_accept_inbox_document(\n p_document_id uuid,\n p_location_id uuid DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_loc uuid;\n v_lines jsonb := '[]'::jsonb;\n v_insts jsonb := '[]'::jsonb;\n v_recv jsonb;\n v_inv jsonb;\n v_it record;\n v_no integer := 0;\n v_total numeric := 0;\n v_stock_n integer := 0;\n v_key text;\n v_invoice uuid;\n v_item_ids uuid[] := '{}';\n -- A competência: o DIA da emissão, não o instante.\n v_competence date;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.create', v_doc.unit_id);\n\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RETURN jsonb_build_object('document_id', v_doc.id, 'already_accepted', true,\n 'invoice_id', v_doc.invoice_id, 'operation_id', v_doc.inventory_operation_id);\n END IF;\n\n v_loc := coalesce(p_location_id, v_doc.default_location_id);\n v_competence := (v_doc.issue_date)::date;\n\n IF EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id\n AND (entry_type IS NULL OR entry_type = '')) THEN\n RAISE EXCEPTION 'fiscalbr: há item sem tipo de registro — conciliar antes de aceitar'\n USING ERRCODE = '23514';\n END IF;\n\n FOR v_it IN\n SELECT * FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id\n AND entry_type IN ('insumo','revenda','patrimonio')\n ORDER BY item_number\n LOOP\n IF v_it.product_id IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: item % é % e não tem produto vinculado', v_it.item_number, v_it.entry_type\n USING ERRCODE = '23514';\n END IF;\n v_no := v_no + 1;\n v_item_ids := v_item_ids || v_it.id;\n v_lines := v_lines || jsonb_build_object(\n 'product_id', v_it.product_id,\n 'quantity', coalesce(v_it.stock_quantity, v_it.quantity_commercial * v_it.conversion_factor),\n 'unit_cost', coalesce(v_it.unit_cost_new, v_it.unit_price_commercial / v_it.conversion_factor),\n 'measurement_unit_id', v_it.stock_unit_id,\n 'notes', v_it.description);\n END LOOP;\n v_stock_n := v_no;\n\n IF v_stock_n > 0 THEN\n IF v_loc IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: a nota tem % linha(s) de estoque e nenhum local de estoque escolhido', v_stock_n\n USING ERRCODE = '22023';\n END IF;\n v_recv := public.inventory_receive(\n v_loc::uuid,\n v_lines::jsonb,\n jsonb_build_object(\n 'supplier_id', v_doc.supplier_party_id,\n -- O documento do estoque também quer o DIA.\n 'date', v_competence,\n 'type', 'nfe',\n 'ref', 'NF-e ' || coalesce(v_doc.nfe_number, '?'),\n 'notes', 'Entrada via DANFE NF-e ' || coalesce(v_doc.nfe_number, '?')),\n ('nfe:' || v_doc.access_key)::text);\n\n UPDATE public.plg_fiscalbr_inbox_items i\n SET stock_movement_id = m.movement_id, updated_at = now()\n FROM (\n SELECT v_item_ids[(mov->>'line_no')::int] AS item_id, (mov->>'id')::uuid AS movement_id\n FROM jsonb_array_elements(coalesce(v_recv->'movements', '[]'::jsonb)) AS t(mov)\n WHERE (mov->>'line_no') IS NOT NULL\n ) m\n WHERE i.tenant_id = v_tenant AND i.id = m.item_id;\n END IF;\n\n SELECT coalesce(sum(value), 0),\n coalesce(jsonb_agg(jsonb_build_object(\n 'number', coalesce(duplicate_index, 1),\n 'due_date', coalesce(due_date, v_competence, current_date),\n 'amount', round(value, 2),\n 'metadata', jsonb_strip_nulls(jsonb_build_object(\n 'barcode', barcode, 'pixKey', pix_key, 'paymentType', payment_type,\n 'danfeNumber', number))) ORDER BY duplicate_index), '[]'::jsonb)\n INTO v_total, v_insts\n FROM public.plg_fiscalbr_inbox_duplicates\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n IF jsonb_array_length(v_insts) = 0 THEN\n v_total := round(coalesce(v_doc.total_value, 0), 2);\n v_insts := jsonb_build_array(jsonb_build_object(\n 'number', 1, 'due_date', coalesce(v_competence, current_date), 'amount', v_total));\n ELSE\n v_total := round(v_total, 2);\n END IF;\n\n v_key := 'danfe:' || v_doc.access_key;\n\n -- TODO argumento tipado. A chamada posicional sem tipo obrigava o Postgres a\n -- adivinhar entre sobrecargas, e foi assim que esta função nasceu quebrada.\n v_inv := public.financial_create_invoice(\n 'payable'::text,\n v_total::numeric,\n v_doc.supplier_party_id::uuid,\n NULL::uuid,\n v_doc.unit_id::uuid,\n v_insts::jsonb,\n v_competence::date,\n ('NF-e ' || coalesce(v_doc.nfe_number, '?') || ' · ' || coalesce(v_doc.supplier_name, 'fornecedor'))::text,\n NULL::text,\n jsonb_build_object(\n 'source', 'danfe',\n 'danfe', jsonb_strip_nulls(jsonb_build_object(\n 'accessKey', v_doc.access_key, 'number', v_doc.nfe_number,\n 'series', v_doc.nfe_series, 'supplierName', v_doc.supplier_name,\n 'supplierCnpj', v_doc.supplier_cnpj,\n 'noteTotal', v_doc.total_value,\n 'inboxDocumentId', v_doc.id)))::jsonb,\n v_key::text);\n v_invoice := (v_inv->>'invoice_id')::uuid;\n\n INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)\n SELECT v_tenant, v_invoice, i.description, i.quantity_commercial, i.unit_price_commercial,\n round(coalesce(i.total_price, 0), 2), i.item_number,\n jsonb_strip_nulls(jsonb_build_object(\n 'itemKind', i.entry_type, 'referenceId', i.product_id,\n 'chartAccountId', i.chart_account_id, 'ncm', i.ncm, 'cfop', i.cfop,\n 'supplierProductCode', i.supplier_product_code))\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n ORDER BY i.item_number\n ON CONFLICT DO NOTHING;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n invoice_id = v_invoice,\n inventory_operation_id = coalesce((v_recv->>'operation_id')::uuid, inventory_operation_id),\n stocked_at = CASE WHEN v_stock_n > 0 THEN now() ELSE stocked_at END,\n status = 'accepted', updated_at = now()\n WHERE id = v_doc.id;\n\n INSERT INTO public.plg_fiscalbr_supplier_product_map (\n tenant_id, supplier_cnpj, supplier_product_code, product_id, entry_type,\n chart_account_id, stock_unit_id, conversion_factor, cost_mode, hit_count, last_used_at)\n SELECT v_tenant, v_doc.supplier_cnpj, i.supplier_product_code, i.product_id,\n i.entry_type, coalesce(i.chart_account_id, v_doc.default_chart_account_id),\n i.stock_unit_id, i.conversion_factor, i.cost_mode, 1, now()\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n AND i.product_id IS NOT NULL\n AND coalesce(v_doc.supplier_cnpj, '') <> ''\n AND coalesce(i.supplier_product_code, '') <> ''\n ON CONFLICT (tenant_id, supplier_cnpj, supplier_product_code) DO UPDATE SET\n product_id = EXCLUDED.product_id,\n entry_type = EXCLUDED.entry_type,\n chart_account_id = coalesce(EXCLUDED.chart_account_id, public.plg_fiscalbr_supplier_product_map.chart_account_id),\n stock_unit_id = coalesce(EXCLUDED.stock_unit_id, public.plg_fiscalbr_supplier_product_map.stock_unit_id),\n conversion_factor = EXCLUDED.conversion_factor,\n cost_mode = EXCLUDED.cost_mode,\n hit_count = public.plg_fiscalbr_supplier_product_map.hit_count + 1,\n last_used_at = now(),\n updated_at = now();\n\n RETURN jsonb_build_object(\n 'document_id', v_doc.id, 'already_accepted', false,\n 'invoice_id', v_invoice, 'invoice_total', v_total,\n 'installments', jsonb_array_length(v_insts),\n 'operation_id', v_recv->>'operation_id',\n 'stock_lines', v_stock_n,\n 'movements', coalesce(v_recv->'movements', '[]'::jsonb));\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_accept_inbox_document(uuid, uuid) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_accept_inbox_document(uuid, uuid) TO authenticated;\n`\n\nexport const MIGRATION_011_O_IMPOSTO_DO_PRODUTO_E_DO_FISCAL = `-- O imposto do PRODUTO mora no fiscal, não no estoque.\n--\n-- No V1 as dezessete colunas de tributo (NCM, CFOP, CST, PIS, COFINS, CEST, FCP\n-- e os dois campos novos da reforma) ficam numa tabela do módulo de estoque,\n-- ao lado de quantidade mínima e temperatura de armazenamento. O salão que\n-- nunca emitiu uma nota carrega as dezessete do mesmo jeito.\n--\n-- Aqui elas ficam onde o assunto é: \\`plg_fiscalbr_tax_groups\\` já guarda a\n-- mesma lista para o GRUPO fiscal, e esta tabela é o que um produto tem de\n-- diferente do grupo dele. Produto sem nada de fiscal não tem linha nenhuma, e\n-- o estoque de quem não emite nota não muda de forma.\n--\n-- \\`tax_group_id\\` é a herança e as outras colunas são a exceção: NULL aqui quer\n-- dizer «vale o que o grupo diz», não «zero». Por isso nenhuma tem DEFAULT 0 —\n-- um zero gravado afirmaria alíquota zero e sobrescreveria o grupo em silêncio.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_product_tax_info (\n product_id uuid PRIMARY KEY REFERENCES public.products(id) ON DELETE CASCADE,\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n tax_group_id uuid REFERENCES public.plg_fiscalbr_tax_groups(id) ON DELETE SET NULL,\n\n -- Nomenclatura Comum do Mercosul: é do PRODUTO, nunca do grupo. É o campo que\n -- o V1 preenche mesmo quando nenhum outro está preenchido.\n ncm text,\n cest text,\n icms_origin text,\n icms_rate numeric(9,4),\n cfop text,\n cst text,\n pis_situation text,\n pis_rate numeric(9,4),\n cofins_situation text,\n cofins_rate numeric(9,4),\n base_calculation_mode text,\n benefit_code text,\n poverty_fund_rate numeric(9,4),\n\n -- Reforma tributária. Entram agora pelo mesmo motivo que entraram no grupo:\n -- deixar de fora obrigaria a recadastrar o catálogo inteiro no dia em que\n -- IBS e CBS valerem.\n ibs_cbs_situation text,\n ibs_cbs_classification text,\n\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\n\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_product_tax_info_tenant_idx\n ON public.plg_fiscalbr_product_tax_info (tenant_id);\nCREATE INDEX IF NOT EXISTS plg_fiscalbr_product_tax_info_group_idx\n ON public.plg_fiscalbr_product_tax_info (tax_group_id);\n\nALTER TABLE public.plg_fiscalbr_product_tax_info ENABLE ROW LEVEL SECURITY;\n\n-- Quem lê e escreve é quem cuida do CADASTRO do produto, não quem emite a\n-- nota: a aba Fiscal do V1 vive dentro do formulário do produto, e exigir\n-- permissão de financeiro ali esconderia a seção do estoquista que digita o\n-- NCM da mercadoria que acabou de chegar.\nDROP POLICY IF EXISTS plg_fiscalbr_product_tax_info_authz_select ON public.plg_fiscalbr_product_tax_info;\nCREATE POLICY plg_fiscalbr_product_tax_info_authz_select\n ON public.plg_fiscalbr_product_tax_info FOR SELECT TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('inventory.read', NULL::uuid)));\n\nDROP POLICY IF EXISTS plg_fiscalbr_product_tax_info_authz_write ON public.plg_fiscalbr_product_tax_info;\nCREATE POLICY plg_fiscalbr_product_tax_info_authz_write\n ON public.plg_fiscalbr_product_tax_info FOR ALL TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('inventory.edit', NULL::uuid)))\n WITH CHECK (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('inventory.edit', NULL::uuid)));\n\nGRANT ALL ON TABLE public.plg_fiscalbr_product_tax_info TO authenticated;\nGRANT ALL ON TABLE public.plg_fiscalbr_product_tax_info TO service_role;\n\nCOMMENT ON TABLE public.plg_fiscalbr_product_tax_info IS\n 'Tributos do produto — a exceção ao grupo fiscal. Espelha a aba Fiscal do cadastro de produto do V1 (product_fiscal_info). NULL herda do grupo.';\n`\n\nexport const MIGRATION_012_QUEM_E_O_PRODUTO_SE_PERGUNTA_AO_INDICE = `-- ---------------------------------------------------------------------------\n-- Quem é o produto desta linha da nota: pergunta-se ao índice, não ao modelo.\n-- ---------------------------------------------------------------------------\n-- A sugestão de IA da entrada de notas mandava o CATÁLOGO para o modelo. O V1\n-- mandava 400 produtos em todo turno (\\`.slice(0, 400)\\` sobre um \\`.limit(800)\\`\n-- sem \\`order by\\` — o corte era arbitrário, e acima de 400 produtos a function\n-- respondia «crie este produto» para produto cadastrado, sem aviso).\n--\n-- O custo disso é \\`catálogo × notas\\`. Num tenant de 171 produtos são ~3,5k\n-- tokens por nota; num distribuidor de 8.000 são ~160k e não cabe no turno. E a\n-- varredura de catálogo não é trabalho de modelo: é trabalho de índice.\n--\n-- Esta função é a pré-seleção, em TRÊS fases, e a primeira que acerta encerra a\n-- linha:\n--\n-- supplier_map o de-para do fornecedor. O que aquele CNPJ já ensinou não se\n-- pergunta de novo — e numa nota repetida isso resolve a nota\n-- inteira, então a IA nem roda.\n-- ean código de barras contra o cadastro. Igualdade, não palpite.\n-- text semelhança de texto, com os candidatos que sobraram.\n--\n-- \\`reason\\` é o que a tela usa para decidir: \\`supplier_map\\` e \\`ean\\` são VÍNCULO\n-- (liga sozinho), \\`text\\` é CANDIDATO (vai para o modelo desambiguar). Sem essa\n-- coluna a tela trataria um EAN exato como um chute de trigrama.\n--\n-- A fase de texto NÃO reimplementa busca: ela chama \\`public.global_search\\`, que\n-- já tem índice GIN de trigrama, \\`fayz_norm()\\` (tira acento, minúscula, colapsa\n-- pontuação) e a escada de pontuação da casa. Reescrever isso pior era o erro\n-- que o \\`ILIKE\\` da descrição fatiada em 24 caracteres já estava cometendo do\n-- lado do cliente — \\`name.ilike.%SACO PLASTICO 10X15 TRAN%\\` não casa acento,\n-- ordem de palavra nem abreviação, e o resultado mais comum era zero candidatos.\n--\n-- O RPC foi renomeado na 137 (\\`fayz_global_search\\` → \\`global_search\\`) e há pool\n-- em cada lado. Aqui se descobre o nome em tempo de execução, como o cliente já\n-- faz em \\`@fayz-ai/core/search\\`.\n--\n-- NÃO é SECURITY DEFINER. Roda como quem chamou, a RLS de \\`products\\` vale, e o\n-- tenant vem de \\`app.current_tenant_id()\\` — o cliente não passa tenant e por\n-- isso não pode passar o de outra conta.\n--\n-- \\`SET search_path\\` é explícito porque \\`similarity\\`/\\`word_similarity\\` moram em\n-- \\`extensions\\`: corpo com search_path vazio passa no DDL e estoura na primeira\n-- chamada.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_match_product_candidates(\n -- [{ \"ref\": \"<id do item>\", \"text\": \"SACO PLASTICO 10X15\", \"ean\": \"789…\", \"code\": \"ABC1\" }]\n p_queries jsonb,\n p_supplier_cnpj text DEFAULT NULL,\n p_per_query integer DEFAULT 8\n) RETURNS TABLE (\n ref text,\n product_id uuid,\n name text,\n sku text,\n unit text,\n cost numeric,\n score real,\n reason text\n)\nLANGUAGE plpgsql\nSTABLE\nSET search_path TO 'public', 'extensions', 'pg_temp'\nAS $fn$\nDECLARE\n v_tenant uuid := (SELECT app.current_tenant_id());\n v_cnpj text := public.fayz_digits(coalesce(p_supplier_cnpj, ''));\n v_barcodes boolean := to_regclass('public.plg_inventory_product_barcodes') IS NOT NULL;\n v_map boolean := to_regclass('public.plg_fiscalbr_supplier_product_map') IS NOT NULL;\n v_search text;\n v_q record;\n v_found uuid;\nBEGIN\n IF v_tenant IS NULL THEN RETURN; END IF;\n IF p_queries IS NULL OR jsonb_typeof(p_queries) <> 'array' THEN RETURN; END IF;\n p_per_query := least(greatest(coalesce(p_per_query, 8), 1), 50);\n\n v_search := CASE\n WHEN to_regprocedure('public.global_search(text,uuid,text[],integer,integer)') IS NOT NULL\n THEN 'public.global_search'\n WHEN to_regprocedure('public.fayz_global_search(text,uuid,text[],integer,integer)') IS NOT NULL\n THEN 'public.fayz_global_search'\n ELSE NULL\n END;\n\n FOR v_q IN\n SELECT e->>'ref' AS ref,\n coalesce(e->>'text', '') AS text,\n public.fayz_digits(coalesce(e->>'ean', '')) AS ean,\n nullif(btrim(coalesce(e->>'code', '')), '') AS code\n FROM jsonb_array_elements(p_queries) AS e\n WHERE e->>'ref' IS NOT NULL\n LOOP\n v_found := NULL;\n\n -- ① O de-para do fornecedor. Aprendizado da casa, e ele ganha de tudo.\n IF v_map AND v_cnpj <> '' AND v_q.code IS NOT NULL THEN\n SELECT p.id INTO v_found\n FROM public.plg_fiscalbr_supplier_product_map m\n JOIN public.products p ON p.id = m.product_id\n WHERE m.supplier_cnpj = v_cnpj\n AND m.supplier_product_code = v_q.code\n AND p.is_active\n ORDER BY m.hit_count DESC NULLS LAST, m.last_used_at DESC NULLS LAST\n LIMIT 1;\n\n IF v_found IS NOT NULL THEN\n RETURN QUERY\n SELECT v_q.ref, p.id, p.name, p.sku, p.unit, p.cost, 1.0::real, 'supplier_map'::text\n FROM public.products p WHERE p.id = v_found;\n CONTINUE;\n END IF;\n END IF;\n\n -- ② O código de barras. O produto guarda o principal em \\`metadata->>barcode\\`\n -- (no V1 era coluna) e os demais na tabela de códigos do estoque.\n IF length(v_q.ean) >= 8 THEN\n SELECT p.id INTO v_found\n FROM public.products p\n WHERE p.is_active\n AND (\n public.fayz_digits(coalesce(p.metadata->>'barcode', '')) = v_q.ean\n OR (v_barcodes AND EXISTS (\n SELECT 1 FROM public.plg_inventory_product_barcodes b\n WHERE b.product_id = p.id\n AND public.fayz_digits(coalesce(b.barcode, '')) = v_q.ean))\n )\n LIMIT 1;\n\n IF v_found IS NOT NULL THEN\n RETURN QUERY\n SELECT v_q.ref, p.id, p.name, p.sku, p.unit, p.cost, 1.0::real, 'ean'::text\n FROM public.products p WHERE p.id = v_found;\n CONTINUE;\n END IF;\n END IF;\n\n -- ③ Semelhança de texto, pela busca indexada que já existe.\n CONTINUE WHEN v_search IS NULL OR length(public.fayz_norm(v_q.text)) < 3;\n\n RETURN QUERY EXECUTE format($q$\n SELECT $4::text, p.id, p.name, p.sku, p.unit, p.cost, g.score, 'text'::text\n FROM %s($1, $2, ARRAY['product']::text[], $3, $3) g\n JOIN public.products p ON p.id = g.record_id::uuid\n WHERE p.is_active\n ORDER BY g.score DESC\n $q$, v_search)\n USING v_q.text, v_tenant, p_per_query, v_q.ref;\n END LOOP;\nEND\n$fn$;\n\nGRANT EXECUTE ON FUNCTION public.fiscalbr_match_product_candidates(jsonb, text, integer) TO authenticated;\n\nCOMMENT ON FUNCTION public.fiscalbr_match_product_candidates(jsonb, text, integer) IS\n 'Pré-seleção de produtos para a sugestão de IA da entrada de notas: de-para do fornecedor e EAN resolvem sozinhos (reason supplier_map/ean, vínculo direto); o resto volta como candidatos de texto (reason text) para o modelo desambiguar. Uma viagem para a nota inteira — substitui o despejo de 400 produtos do V1 e o ILIKE da descrição fatiada.';\n`\n\nexport const MIGRATION_013_A_SUGESTAO_SOBREVIVE_A_FECHAR_A_JANELA = `-- ---------------------------------------------------------------------------\n-- A sugestão sobrevive a fechar a janela — e diz QUEM escreveu no campo.\n-- ---------------------------------------------------------------------------\n-- A conciliação virou modal para a lista não ser desmontada. O efeito colateral\n-- é que o modal fecha com clique fora e com Esc, e a sugestão só existia em\n-- memória até alguém clicar em «Salvar conciliação»:\n--\n-- sugerir (30s de IA) → revisar 7 de 11 itens → clique fora → perdeu os 11\n--\n-- No V1 fechar não custava nada, porque a edge function já tinha gravado. Então\n-- a V2 grava também, logo depois da sugestão, pelo caminho que já existia\n-- (\\`fiscalbr_save_inbox_decision\\`, que não marca \\`reconciled\\`) — nenhum segundo\n-- caminho de escrita, nenhuma coluna \\`ai_*\\` paralela aos campos de verdade.\n--\n-- O que faltava era a MEMÓRIA DE AUTORIA. Depois de recarregar, a tela via um\n-- fator 22,056 e não sabia se foi a Laissa que digitou ou a máquina que chutou —\n-- e as duas coisas se conferem de maneiras diferentes.\n--\n-- O V1 guardava um booleano, \\`ai_suggested\\`. Aqui é texto, porque a V2 tem TRÊS\n-- autores de máquina e eles não merecem o mesmo selo:\n--\n-- supplier_map o de-para deste fornecedor. Igualdade, e aprendizado da casa.\n-- ean código de barras. Igualdade.\n-- ai semelhança julgada por modelo. É o único que se confere item\n-- a item, e \\`suggestion_confidence\\` diz o quanto.\n--\n-- NULL é a resposta mais importante: significa «uma pessoa escolheu isto». O\n-- cliente limpa a coluna em qualquer edição do campo, então o selo nunca mente\n-- sobre um valor que alguém corrigiu à mão.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_fiscalbr_inbox_items\n ADD COLUMN IF NOT EXISTS suggested_by text,\n ADD COLUMN IF NOT EXISTS suggestion_confidence numeric;\n\nDO $$\nBEGIN\n IF NOT EXISTS (\n SELECT 1 FROM pg_constraint\n WHERE conname = 'plg_fiscalbr_inbox_items_suggested_by_check'\n AND conrelid = 'public.plg_fiscalbr_inbox_items'::regclass\n ) THEN\n ALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_suggested_by_check\n CHECK (suggested_by IS NULL OR suggested_by IN ('ai', 'ean', 'supplier_map'));\n END IF;\nEND $$;\n\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.suggested_by IS\n 'Quem escreveu a decisão desta linha: ai (modelo, confira), ean / supplier_map (igualdade), NULL (uma pessoa). O cliente limpa em qualquer edição manual.';\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_items.suggestion_confidence IS\n '0..1, só para suggested_by = ai. Abaixo de 0,6 a tela marca a linha como «confira».';\n\n-- ── A gravação da decisão passa a carregar a autoria ───────────────────────\n-- Mesma assinatura, então é \\`CREATE OR REPLACE\\` e nenhum chamador muda. O corpo\n-- é o da 009 com duas linhas a mais: o resto fica palavra por palavra, porque\n-- esta função é o único caminho de escrita da decisão e reescrevê-la de memória\n-- é como se perde uma regra (a de \\`reconciled\\`, por exemplo).\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_save_inbox_decision(\n p_document_id uuid,\n p_items jsonb,\n p_default_chart_account_id uuid DEFAULT NULL,\n p_default_location_id uuid DEFAULT NULL,\n p_duplicates jsonb DEFAULT NULL)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_row jsonb;\n v_done integer := 0;\n v_total integer;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota % não encontrada neste tenant', p_document_id USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.edit', v_doc.unit_id);\n\n IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN\n RAISE EXCEPTION 'fiscalbr: nota % já foi aceita — a decisão não muda depois do estoque', p_document_id\n USING ERRCODE = '23514';\n END IF;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET\n default_chart_account_id = coalesce(p_default_chart_account_id, default_chart_account_id),\n default_location_id = coalesce(p_default_location_id, default_location_id),\n reviewed_at = now(), updated_at = now()\n WHERE id = v_doc.id;\n\n FOR v_row IN SELECT * FROM jsonb_array_elements(coalesce(p_items, '[]'::jsonb)) LOOP\n UPDATE public.plg_fiscalbr_inbox_items i SET\n product_id = nullif(v_row->>'product_id', '')::uuid,\n entry_type = nullif(v_row->>'entry_type', ''),\n chart_account_id = nullif(v_row->>'chart_account_id', '')::uuid,\n stock_unit_id = nullif(v_row->>'stock_unit_id', '')::uuid,\n conversion_factor = coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1),\n cost_mode = coalesce(nullif(v_row->>'cost_mode', ''), 'novo'),\n shortage_quantity = nullif(v_row->>'shortage_quantity', '')::numeric,\n shortage_reason = nullif(v_row->>'shortage_reason', ''),\n shortage_note = nullif(v_row->>'shortage_note', ''),\n -- Quem escreveu. Ausente na chave é NULL, que é «uma pessoa escolheu» — e é\n -- o que acontece em todo salvamento comum, sem a IA ter passado por aqui.\n suggested_by = nullif(v_row->>'suggested_by', ''),\n suggestion_confidence = nullif(v_row->>'suggestion_confidence', '')::numeric,\n -- Derivadas, gravadas: é o que o operador viu.\n stock_quantity = i.quantity_commercial * coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1)\n - coalesce(nullif(v_row->>'shortage_quantity', '')::numeric, 0),\n unit_cost_new = CASE WHEN coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1) > 0\n THEN i.unit_price_commercial / coalesce(nullif(v_row->>'conversion_factor', '')::numeric, 1) END,\n -- Uma linha está conciliada quando sabe o que é. Despesa e serviço não\n -- pedem produto: elas nunca vão virar estoque.\n reconciled = CASE\n WHEN nullif(v_row->>'entry_type', '') IN ('despesa','servico') THEN true\n ELSE nullif(v_row->>'product_id', '') IS NOT NULL\n END,\n updated_at = now()\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n AND i.id = (v_row->>'id')::uuid;\n v_done := v_done + 1;\n END LOOP;\n\n IF p_duplicates IS NOT NULL THEN\n DELETE FROM public.plg_fiscalbr_inbox_duplicates\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n INSERT INTO public.plg_fiscalbr_inbox_duplicates (\n tenant_id, inbox_document_id, duplicate_index, number, due_date, value,\n payment_type, barcode, pix_key, payment_method_id)\n SELECT v_tenant, v_doc.id, coalesce((d->>'index')::int, ord), d->>'number',\n nullif(d->>'due_date', '')::date, (d->>'value')::numeric,\n nullif(d->>'payment_type', ''), nullif(d->>'barcode', ''),\n nullif(d->>'pix_key', ''), nullif(d->>'payment_method_id', '')::uuid\n FROM jsonb_array_elements(p_duplicates) WITH ORDINALITY AS t(d, ord);\n END IF;\n\n SELECT count(*) INTO v_total FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id;\n\n UPDATE public.plg_fiscalbr_inbox_documents SET status = CASE\n WHEN (SELECT count(*) FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id AND reconciled) = v_total\n THEN 'accepted' ELSE 'partial' END\n WHERE id = v_doc.id;\n\n RETURN jsonb_build_object('document_id', v_doc.id, 'saved', v_done, 'items', v_total,\n 'reconciled', (SELECT count(*) FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id AND reconciled));\nEND $function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_save_inbox_decision(uuid, jsonb, uuid, uuid, jsonb) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_save_inbox_decision(uuid, jsonb, uuid, uuid, jsonb) TO authenticated;\n`\n\nexport const MIGRATION_014_A_DESCRICAO_DA_NOTA_TEM_LIXO_NO_MEIO = `-- ---------------------------------------------------------------------------\n-- A descrição da nota tem lixo no meio, e um token de lixo matava a busca.\n-- ---------------------------------------------------------------------------\n-- Caso real, primeira nota de verdade: o item «20X35 AR VACUO» voltou SEM\n-- candidato, e o produto \\`EMBALAGEM VACUO 20X35\\` está cadastrado.\n--\n-- \\`public.global_search\\` exige que TODOS os tokens apareçam no haystack — é a\n-- regra certa para gente digitando («joão silva» não deve trazer todos os joãos)\n-- e é a regra errada para descrição de NF-e. Os tokens de \\`20X35 AR VACUO\\` são\n-- \\`20x35\\`, \\`ar\\`, \\`vacuo\\`; o produto é \\`embalagem vacuo 20x35\\`. Dois casam. \\`ar\\`\n-- não aparece em lugar nenhum, e o AND derruba a linha inteira.\n--\n-- A segunda fase (\\`word_similarity\\`) também não salva: ela compara a frase\n-- inteira contra o haystack, e com um terço da frase sendo ruído a semelhança\n-- fica abaixo do limiar.\n--\n-- Descrição de nota fiscal é assim por natureza: abreviada, em ordem própria, com\n-- sigla de unidade, micragem e palavra solta no meio. Então o que entra na busca\n-- deixa de ser a frase e passa a ser O QUE NELA DISTINGUE:\n--\n-- ① tokens de 3 letras ou mais. «ar», «kg», «un», «c/», «p/» saem. «20x35»\n-- e «vacuo» ficam — e são eles que identificam o produto.\n-- ② se mesmo assim não vier nada, UMA última tentativa com o token mais longo\n-- sozinho. É o recuo que acha «embalagem a vácuo 15 x 25» a partir de\n-- «VACUO», para a pessoa escolher entre poucos em vez de nenhum.\n--\n-- Não se mexe em \\`global_search\\`: lá a regra está certa para quem ela serve.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_match_product_candidates(\n p_queries jsonb,\n p_supplier_cnpj text DEFAULT NULL,\n p_per_query integer DEFAULT 8\n) RETURNS TABLE (\n ref text,\n product_id uuid,\n name text,\n sku text,\n unit text,\n cost numeric,\n score real,\n reason text\n)\nLANGUAGE plpgsql\nSTABLE\nSET search_path TO 'public', 'extensions', 'pg_temp'\nAS $fn$\nDECLARE\n v_tenant uuid := (SELECT app.current_tenant_id());\n v_cnpj text := public.fayz_digits(coalesce(p_supplier_cnpj, ''));\n v_barcodes boolean := to_regclass('public.plg_inventory_product_barcodes') IS NOT NULL;\n v_map boolean := to_regclass('public.plg_fiscalbr_supplier_product_map') IS NOT NULL;\n v_search text;\n v_q record;\n v_found uuid;\n v_tokens text[];\n v_strong text[];\n v_busca text;\n v_recuo text;\nBEGIN\n IF v_tenant IS NULL THEN RETURN; END IF;\n IF p_queries IS NULL OR jsonb_typeof(p_queries) <> 'array' THEN RETURN; END IF;\n p_per_query := least(greatest(coalesce(p_per_query, 8), 1), 50);\n\n v_search := CASE\n WHEN to_regprocedure('public.global_search(text,uuid,text[],integer,integer)') IS NOT NULL\n THEN 'public.global_search'\n WHEN to_regprocedure('public.fayz_global_search(text,uuid,text[],integer,integer)') IS NOT NULL\n THEN 'public.fayz_global_search'\n ELSE NULL\n END;\n\n FOR v_q IN\n SELECT e->>'ref' AS ref,\n coalesce(e->>'text', '') AS text,\n public.fayz_digits(coalesce(e->>'ean', '')) AS ean,\n nullif(btrim(coalesce(e->>'code', '')), '') AS code\n FROM jsonb_array_elements(p_queries) AS e\n WHERE e->>'ref' IS NOT NULL\n LOOP\n v_found := NULL;\n\n -- ① O de-para do fornecedor. Aprendizado da casa, e ele ganha de tudo.\n IF v_map AND v_cnpj <> '' AND v_q.code IS NOT NULL THEN\n SELECT p.id INTO v_found\n FROM public.plg_fiscalbr_supplier_product_map m\n JOIN public.products p ON p.id = m.product_id\n WHERE m.supplier_cnpj = v_cnpj\n AND m.supplier_product_code = v_q.code\n AND p.is_active\n ORDER BY m.hit_count DESC NULLS LAST, m.last_used_at DESC NULLS LAST\n LIMIT 1;\n\n IF v_found IS NOT NULL THEN\n RETURN QUERY\n SELECT v_q.ref, p.id, p.name, p.sku, p.unit, p.cost, 1.0::real, 'supplier_map'::text\n FROM public.products p WHERE p.id = v_found;\n CONTINUE;\n END IF;\n END IF;\n\n -- ② O código de barras. «SEM GTIN» é o que a NF-e escreve quando não há — e\n -- \\`fayz_digits\\` o reduz a vazio, então o teste de comprimento já o barra.\n IF length(v_q.ean) >= 8 THEN\n SELECT p.id INTO v_found\n FROM public.products p\n WHERE p.is_active\n AND (\n public.fayz_digits(coalesce(p.metadata->>'barcode', '')) = v_q.ean\n OR (v_barcodes AND EXISTS (\n SELECT 1 FROM public.plg_inventory_product_barcodes b\n WHERE b.product_id = p.id\n AND public.fayz_digits(coalesce(b.barcode, '')) = v_q.ean))\n )\n LIMIT 1;\n\n IF v_found IS NOT NULL THEN\n RETURN QUERY\n SELECT v_q.ref, p.id, p.name, p.sku, p.unit, p.cost, 1.0::real, 'ean'::text\n FROM public.products p WHERE p.id = v_found;\n CONTINUE;\n END IF;\n END IF;\n\n -- ③ Semelhança de texto, com o que DISTINGUE em vez da frase inteira.\n CONTINUE WHEN v_search IS NULL;\n\n v_tokens := array_remove(string_to_array(public.fayz_norm(v_q.text), ' '), '');\n SELECT array_agg(t ORDER BY length(t) DESC) INTO v_strong\n FROM unnest(v_tokens) t WHERE length(t) >= 3;\n\n v_busca := array_to_string(coalesce(v_strong, v_tokens), ' ');\n -- O recuo é o token mais longo sozinho: numa descrição de nota ele é quase\n -- sempre o nome da coisa, e os outros são medida, micragem ou conjunção.\n v_recuo := coalesce(v_strong[1], '');\n\n CONTINUE WHEN length(v_busca) < 3;\n\n RETURN QUERY EXECUTE format($q$\n WITH forte AS (\n SELECT g.record_id, g.score FROM %1$s($1, $2, ARRAY['product']::text[], $3, $3) g\n ),\n -- Só quando a busca forte não achou nada: um recuo que rodasse sempre\n -- encheria a lista de parecidos e empurraria o certo para fora do teto.\n fraco AS (\n SELECT g.record_id, g.score * 0.7 AS score\n FROM %1$s($4, $2, ARRAY['product']::text[], $3, $3) g\n WHERE $4 <> '' AND $4 <> $1 AND NOT EXISTS (SELECT 1 FROM forte)\n )\n SELECT $5::text, p.id, p.name, p.sku, p.unit, p.cost, g.score::real, 'text'::text\n FROM (SELECT * FROM forte UNION ALL SELECT * FROM fraco) g\n JOIN public.products p ON p.id = g.record_id::uuid\n WHERE p.is_active\n ORDER BY g.score DESC\n $q$, v_search)\n USING v_busca, v_tenant, p_per_query, v_recuo, v_q.ref;\n END LOOP;\nEND\n$fn$;\n\nGRANT EXECUTE ON FUNCTION public.fiscalbr_match_product_candidates(jsonb, text, integer) TO authenticated;\n\nCOMMENT ON FUNCTION public.fiscalbr_match_product_candidates(jsonb, text, integer) IS\n 'Pré-seleção de produtos para a sugestão de IA da entrada de notas: de-para do fornecedor e EAN resolvem sozinhos (reason supplier_map/ean); o resto volta como candidatos de texto. A busca usa os tokens de 3+ letras da descrição, não a frase — «20X35 AR VACUO» achava nada porque o AND de global_search exige o token «ar», que não existe em «embalagem vacuo 20x35».';\n`\n\nexport const MIGRATION_015_O_MOVIMENTO_DIZ_QUE_VEIO_DA_NOTA = `-- ---------------------------------------------------------------------------\n-- O movimento de estoque diz, por escrito, que veio desta nota.\n-- ---------------------------------------------------------------------------\n-- A aceitação já mandava a frase para \\`inventory_receive\\`, na chave \\`notes\\` do\n-- cabeçalho — e ela nunca chegava: lá dentro o \\`coalesce(v_ln.notes, …)\\` dá a vez\n-- à anotação DA LINHA, que aqui é sempre a descrição do item. A tela de\n-- Movimentações então escrevia «Sem motivo registrado» sobre a entrada mais\n-- rastreável que existe.\n--\n-- \\`inventory/021\\` abriu a chave \\`reason\\` no cabeçalho. Esta migration passa a\n-- usá-la, com a mesma frase que as linhas migradas do V1 carregam — para que a\n-- entrada de ontem e a de hoje se leiam igual no mesmo razão.\n--\n-- Só a chamada muda. O resto do corpo é o da 009, palavra por palavra: esta\n-- função escreve estoque e título na mesma transação, e reescrevê-la de memória\n-- é como se perde uma regra.\n-- ---------------------------------------------------------------------------\n\nDO $m$\nDECLARE\n v_def text;\n v_antes text := E' ''ref'', ''NF-e '' || coalesce(v_doc.nfe_number, ''?''),\\\\n ''notes'', ''Entrada via DANFE NF-e '' || coalesce(v_doc.nfe_number, ''?'')),';\n v_depois text := E' ''ref'', ''NF-e '' || coalesce(v_doc.nfe_number, ''?''),\\\\n ''notes'', ''Entrada via DANFE NF-e '' || coalesce(v_doc.nfe_number, ''?''),\\\\n ''reason'', ''Entrada via DANFE NF-e '' || coalesce(v_doc.nfe_number, ''?'')),';\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def\n FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n\n IF v_def IS NULL THEN\n RAISE NOTICE 'fiscalbr: accept ainda não existe neste pool — 009 roda antes e já traz o reason';\n RETURN;\n END IF;\n\n -- Já aplicada: sair sem tocar em nada é o que torna esta migration repetível.\n IF position('''reason'', ''Entrada via DANFE' in v_def) > 0 THEN RETURN; END IF;\n\n IF position(v_antes in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/015: o corpo de fiscalbr_accept_inbox_document não é o esperado — confira à mão em vez de deixar passar calado';\n END IF;\n\n EXECUTE replace(v_def, v_antes, v_depois);\nEND $m$;\n`\n\nexport const MIGRATION_016_A_NOTA_GUARDA_O_PROPRIO_XML = `-- ---------------------------------------------------------------------------\n-- A nota guarda o próprio XML, em vez de lê-lo e jogar fora.\n-- ---------------------------------------------------------------------------\n-- O V1 abre o XML e o DANFE direto da lista de notas. A V2 mostrava os dois\n-- botões desligados porque não tinha o arquivo: das 889 notas deste cluster,\n-- ZERO têm \\`document_id\\`, zero têm bytes em \\`documents\\`, zero têm nada no\n-- metadata.\n--\n-- E não é que o arquivo nunca tenha passado por aqui — ele passa INTEIRO pela\n-- mão do estágio: o navegador lê o \\`.xml\\` que a pessoa arrastou, o parser extrai\n-- itens, parcelas e totais, e os bytes são descartados no fim da função. A nota\n-- fiscal é documento com guarda legal de cinco anos, e a única cópia ficava na\n-- pasta de downloads de quem importou.\n--\n-- \\`xml_content text\\` é o mesmo nome e o mesmo tipo do \\`dfe_inbox.xml_content\\` do\n-- V1 — a ponte da 003 já citava essa coluna, e repetir o nome é o que faz uma\n-- futura migração de dados ser um \\`INSERT ... SELECT\\` em vez de um de-para.\n--\n-- Guardar no banco e não no bucket, de propósito: são 10–50 KB de texto por nota\n-- e são o ÚNICO conteúdo que torna a linha auditável. Storage é outro sistema,\n-- com outra vida útil e outra política de acesso, e um XML fiscal que vive em\n-- bucket é um XML que alguém apaga limpando bucket.\n--\n-- Isto NÃO preenche as 889 notas antigas: o que não foi guardado não se inventa.\n-- A tela desliga o botão por nota, não por feature.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_fiscalbr_inbox_documents\n ADD COLUMN IF NOT EXISTS xml_content text;\n\nCOMMENT ON COLUMN public.plg_fiscalbr_inbox_documents.xml_content IS\n 'O XML autorizado da NF-e, como chegou. Nulo nas notas importadas antes desta coluna existir — o que não foi guardado não se inventa.';\n\n-- ── O estágio passa a guardar o que já tinha em mão ────────────────────────\n-- Patch sobre o corpo que está no cluster, e não reescrita: esta função insere\n-- documento, itens, duplicatas e pagamentos numa transação só, e reescrevê-la de\n-- memória é como se perde uma regra.\n\nDO $m$\nDECLARE\n v_def text;\n v_cols_antes text := E' total_freight, total_insurance, total_other, additional_info, metadata)';\n v_cols_depois text := E' total_freight, total_insurance, total_other, additional_info, metadata, xml_content)';\n v_vals_antes text := E' jsonb_build_object(''source'', coalesce(p_note->>''source'', ''xml_upload'')))';\n v_vals_depois text := E' jsonb_build_object(''source'', coalesce(p_note->>''source'', ''xml_upload'')),' || E'\\\\n' ||\n E' nullif(p_note->>''xml'', ''''))';\n v_upd_antes text := E' total_value = EXCLUDED.total_value,';\n v_upd_depois text := E' total_value = EXCLUDED.total_value,' || E'\\\\n' ||\n E' -- Reimportar com o arquivo preenche o que faltava; reimportar sem ele' || E'\\\\n' ||\n E' -- não apaga o que já estava guardado.' || E'\\\\n' ||\n E' xml_content = coalesce(EXCLUDED.xml_content, public.plg_fiscalbr_inbox_documents.xml_content),';\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def\n FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_stage_inbox_document';\n\n IF v_def IS NULL THEN\n RAISE NOTICE 'fiscalbr/016: o estágio ainda não existe neste pool — a 009 roda antes';\n RETURN;\n END IF;\n\n -- Já aplicada: sair sem tocar em nada é o que torna esta migration repetível.\n IF position('xml_content' in v_def) > 0 THEN RETURN; END IF;\n\n IF position(v_cols_antes in v_def) = 0\n OR position(v_vals_antes in v_def) = 0\n OR position(v_upd_antes in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/016: o corpo de fiscalbr_stage_inbox_document não é o esperado — confira à mão em vez de deixar passar calado';\n END IF;\n\n v_def := replace(v_def, v_cols_antes, v_cols_depois);\n v_def := replace(v_def, v_vals_antes, v_vals_depois);\n v_def := replace(v_def, v_upd_antes, v_upd_depois);\n EXECUTE v_def;\nEND $m$;\n`\n\nexport const MIGRATION_017_QUEM_EMITE_E_O_CNPJ_NAO_A_LOJA = `-- Quem emite é o CNPJ, não a loja.\n--\n-- As abas \"Certificado\" e \"Emissão Fiscal\" do cadastro de empresa do V1\n-- guardam, em companies, como aquela pessoa jurídica emite NFS-e e NFC-e e se\n-- recebe DANFes da SEFAZ. No V2 a pessoa jurídica é\n-- public.company_legal_entities (base), e a filial chega nela por\n-- app.units.company_legal_entity_id (168). Esta tabela é uma linha por pessoa\n-- jurídica:\n--\n-- unidade → app.units.company_legal_entity_id → company_legal_entities.id\n-- → plg_fiscalbr_emitter_settings.legal_entity_id (UNIQUE)\n--\n-- Duas filiais com o mesmo CNPJ dividem a mesma configuração, como no V1.\n--\n-- O certificado A1 NÃO mora aqui. O .pfx e a senha vão direto ao provedor\n-- (PlugNotas) e o que fica é o recibo: id no provedor, titular e validade. O\n-- CSC da NFC-e é segredo — o navegador grava, mas não lê de volta: a coluna\n-- fica fora do GRANT SELECT e a tela vê só \\`nfce_csc_token_set\\`.\n--\n-- Plano aprovado em docs/port/empresa.schema.json. Idempotente.\n\nCREATE TABLE IF NOT EXISTS public.plg_fiscalbr_emitter_settings (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n legal_entity_id uuid NOT NULL,\n\n nfse_enabled boolean NOT NULL DEFAULT false,\n nfse_production boolean NOT NULL DEFAULT false,\n nfse_national boolean NOT NULL DEFAULT false,\n nfse_service_code_national text,\n nfse_service_code_municipal text,\n nfse_nbs_code text,\n nfse_cnae text,\n nfse_iss_rate numeric(5,2) CHECK (nfse_iss_rate IS NULL OR (nfse_iss_rate >= 0 AND nfse_iss_rate <= 100)),\n nfse_iss_taxation smallint,\n nfse_iss_exigibility smallint,\n nfse_ibscbs_cst text,\n nfse_ibscbs_classification text,\n nfse_simples_regime smallint,\n nfse_net_value boolean NOT NULL DEFAULT false,\n nfse_additional_info text,\n nfse_city_features jsonb,\n\n nfce_enabled boolean NOT NULL DEFAULT false,\n nfce_production boolean NOT NULL DEFAULT false,\n nfce_series integer CHECK (nfce_series IS NULL OR nfce_series > 0),\n nfce_csc_id text,\n nfce_csc_token text,\n nfce_csc_token_set boolean GENERATED ALWAYS AS (nfce_csc_token IS NOT NULL AND nfce_csc_token <> '') STORED,\n nfce_generic_item jsonb,\n\n nfe_enabled boolean NOT NULL DEFAULT false,\n\n certificate_provider_id text,\n certificate_cn text,\n certificate_expires_at timestamptz,\n certificate_uploaded_at timestamptz,\n\n dfe_sync_enabled boolean NOT NULL DEFAULT false,\n dfe_sync_cursor text,\n dfe_last_sync_at timestamptz,\n provider_synced_at timestamptz,\n\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE (tenant_id, id)\n);\n\nDO $$\nBEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'plg_fiscalbr_emitter_settings_legal_entity_fkey') THEN\n -- company_legal_entities é da base, não de outro plugin: a FK física é\n -- permitida (a regra do 000 proíbe FK entre PLUGINS).\n ALTER TABLE ONLY public.plg_fiscalbr_emitter_settings\n ADD CONSTRAINT plg_fiscalbr_emitter_settings_legal_entity_fkey\n FOREIGN KEY (legal_entity_id) REFERENCES public.company_legal_entities(id) ON DELETE CASCADE;\n END IF;\nEND $$;\n\nCREATE UNIQUE INDEX IF NOT EXISTS plg_fiscalbr_emitter_settings_legal_entity_uidx\n ON public.plg_fiscalbr_emitter_settings USING btree (legal_entity_id);\n\nCOMMENT ON TABLE public.plg_fiscalbr_emitter_settings IS\n 'V1: companies (abas Certificado + Emissão Fiscal). Como uma pessoa jurídica emite NFS-e/NFC-e e recebe DANFes. Uma linha por CNPJ; a filial chega por app.units.company_legal_entity_id.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.legal_entity_id IS 'A chave que conecta: company_legal_entities.id. UNIQUE.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_production IS 'V1: companies.nfse_producao — false = homologação.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_national IS 'V1: companies.nfse_nacional — padrão nacional × municipal.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_service_code_national IS 'V1: companies.nfse_codigo_tributacao_nacional';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_service_code_municipal IS 'V1: companies.nfse_codigo_tributacao_municipio';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_nbs_code IS 'V1: companies.nfse_codigo_nbs';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_cnae IS 'V1: companies.nfse_cnae — CNAE do serviço, pode diferir do principal.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_iss_rate IS 'V1: companies.nfse_iss_aliquota (%)';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_iss_taxation IS 'V1: companies.nfse_iss_tipo_tributacao';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_iss_exigibility IS 'V1: companies.nfse_iss_exigibilidade';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_simples_regime IS 'V1: companies.nfse_regime_apuracao_sn — só para optante do Simples.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_net_value IS 'V1: companies.nfse_valor_liquido — emitir pelo valor líquido.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfse_city_features IS 'V1: companies.nfse_city_features — o que a prefeitura aceita, devolvido pelo provedor.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfce_csc_token IS 'V1: companies.nfce_csc_token — SEGREDO. Fora do GRANT SELECT de authenticated.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfce_generic_item IS 'V1: companies.nfce_item_generico — {ncm, cfop, csosn}.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.certificate_provider_id IS 'V1: companies.certificate_plugnotas_id — recibo; o .pfx não fica no banco.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.dfe_sync_enabled IS 'V1: companies.dfe_sync_enabled — receber DANFes automaticamente.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.dfe_sync_cursor IS 'V1: companies.dfe_sync_cursor — NSU onde a busca na SEFAZ parou.';\n\nALTER TABLE public.plg_fiscalbr_emitter_settings ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.plg_fiscalbr_emitter_settings FORCE ROW LEVEL SECURITY;\n\n-- O segredo fica fora do SELECT: grava-se, não se lê.\nREVOKE ALL ON TABLE public.plg_fiscalbr_emitter_settings FROM anon, authenticated;\nGRANT INSERT, UPDATE, DELETE ON TABLE public.plg_fiscalbr_emitter_settings TO authenticated;\nGRANT SELECT (\n id, tenant_id, legal_entity_id,\n nfse_enabled, nfse_production, nfse_national, nfse_service_code_national, nfse_service_code_municipal,\n nfse_nbs_code, nfse_cnae, nfse_iss_rate, nfse_iss_taxation, nfse_iss_exigibility, nfse_ibscbs_cst,\n nfse_ibscbs_classification, nfse_simples_regime, nfse_net_value, nfse_additional_info, nfse_city_features,\n nfce_enabled, nfce_production, nfce_series, nfce_csc_id, nfce_csc_token_set, nfce_generic_item,\n nfe_enabled, certificate_provider_id, certificate_cn, certificate_expires_at, certificate_uploaded_at,\n dfe_sync_enabled, dfe_sync_cursor, dfe_last_sync_at, provider_synced_at, created_at, updated_at\n) ON public.plg_fiscalbr_emitter_settings TO authenticated;\nGRANT ALL ON TABLE public.plg_fiscalbr_emitter_settings TO service_role;\n\nDROP POLICY IF EXISTS plg_fiscalbr_emitter_settings_authz_select ON public.plg_fiscalbr_emitter_settings;\nCREATE POLICY plg_fiscalbr_emitter_settings_authz_select ON public.plg_fiscalbr_emitter_settings\n FOR SELECT TO authenticated USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('financial.read', NULL::uuid)));\n\nDROP POLICY IF EXISTS plg_fiscalbr_emitter_settings_authz_write ON public.plg_fiscalbr_emitter_settings;\nCREATE POLICY plg_fiscalbr_emitter_settings_authz_write ON public.plg_fiscalbr_emitter_settings\n FOR ALL TO authenticated\n USING (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('settings.manage', NULL::uuid)))\n WITH CHECK (\n tenant_id = (SELECT app.current_tenant_id())\n AND (SELECT app.has_permission('settings.manage', NULL::uuid))\n AND EXISTS (SELECT 1 FROM public.company_legal_entities le\n WHERE le.id = plg_fiscalbr_emitter_settings.legal_entity_id\n AND le.tenant_id = plg_fiscalbr_emitter_settings.tenant_id));\n`\n\nexport const MIGRATION_018_A_NOTA_DO_V1_ALCANCA_A_CONTA = `-- A nota que veio do V1 alcança a conta que a gerou.\n--\n-- A conta a receber pergunta \"que notas eu tenho?\" pelo pedido dela:\n-- plg_financial_invoices.order_id → plg_fiscalbr_document_orders → a nota.\n-- A importação só preencheu esse vínculo a partir da tabela N:N do V1\n-- (fiscal_document_invoice_sources). A NFS-e do V1 nunca usou essa tabela: ela\n-- aponta a conta por fiscal_documents.invoice_id, que chegou aqui apenas como\n-- metadata.v1.invoice_ref. Medido em 06-10-2026 no cluster do ChefControl: 488\n-- NFS-e e 122 NFC-e sem caminho até a conta.\n--\n-- A conta importada guarda o próprio id do V1 em\n-- metadata.migration.source_numeric_id, então o par se resolve sem adivinhar.\n-- Num pool sem dado do V1 isto não casa nada. Aditivo e idempotente.\n\nINSERT INTO public.plg_fiscalbr_document_orders (tenant_id, document_id, order_id)\nSELECT DISTINCT f.tenant_id, f.document_id, i.order_id\n FROM public.plg_fiscalbr_documents f\n JOIN public.plg_financial_invoices i\n ON i.tenant_id = f.tenant_id\n AND i.metadata -> 'migration' ->> 'source_table' = 'invoices'\n AND i.metadata -> 'migration' ->> 'source_numeric_id' = f.metadata -> 'v1' ->> 'invoice_ref'\n JOIN public.orders o ON o.id = i.order_id\n WHERE f.metadata -> 'v1' ->> 'invoice_ref' IS NOT NULL\nON CONFLICT (document_id, order_id) DO NOTHING;\n`\n\nexport const MIGRATION_019_A_NOTA_EMITIDA_SE_CANCELA_PELO_V2 = `-- A nota emitida se consulta e se cancela pelo V2.\n--\n-- Quem fala com a PlugNotas é a função \\`fiscalbr-plugnotas\\` (a chave só existe\n-- no servidor), mas ela roda com o JWT de quem clicou e não grava nada direto:\n-- pergunta aqui se a pessoa pode, e devolve o resultado aqui. Uma porta de\n-- leitura, uma de escrita, a permissão conferida nas duas.\n--\n-- consultar e baixar o PDF → financial.read na unidade da nota\n-- cancelar → financial.edit na unidade da nota\n--\n-- A espelho em \\`documents.status\\` anda junto: as duas tabelas são a mesma nota\n-- vista de dois lugares (005), e um status divergente entre elas é a nota\n-- dizendo duas coisas. Idempotente.\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_note_for_provider(p_document_id uuid, p_action text)\nRETURNS jsonb\nLANGUAGE plpgsql\nSTABLE SECURITY DEFINER\nSET search_path TO ''\nAS $$\nDECLARE\n v public.plg_fiscalbr_documents%ROWTYPE;\nBEGIN\n SELECT * INTO v FROM public.plg_fiscalbr_documents\n WHERE document_id = p_document_id AND tenant_id = app.current_tenant_id();\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscal: note not found' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission(\n CASE WHEN p_action = 'cancel' THEN 'financial.edit' ELSE 'financial.read' END, v.unit_id);\n RETURN jsonb_build_object(\n 'document_id', v.document_id, 'model', v.model, 'status', v.status,\n 'environment', v.environment, 'provider_document_id', v.provider_document_id,\n 'cancelled_at', v.cancelled_at, 'access_key', v.access_key, 'number', v.number);\nEND $$;\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_note_apply(\n p_document_id uuid,\n p_action text,\n p_patch jsonb,\n p_event jsonb DEFAULT NULL\n)\nRETURNS void\nLANGUAGE plpgsql\nSECURITY DEFINER\nSET search_path TO ''\nAS $$\nDECLARE\n v public.plg_fiscalbr_documents%ROWTYPE;\n v_status text := p_patch ->> 'status';\nBEGIN\n SELECT * INTO v FROM public.plg_fiscalbr_documents\n WHERE document_id = p_document_id AND tenant_id = app.current_tenant_id()\n FOR UPDATE;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscal: note not found' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission(\n CASE WHEN p_action = 'cancel' THEN 'financial.edit' ELSE 'financial.read' END, v.unit_id);\n IF v_status IS NOT NULL AND v_status NOT IN ('processing','authorized','rejected','error','cancelled','substituted') THEN\n RAISE EXCEPTION 'fiscal: unknown status %', v_status USING ERRCODE = '22023';\n END IF;\n\n -- Only what the provider answers; identity (model, unit, order) never moves.\n UPDATE public.plg_fiscalbr_documents SET\n status = COALESCE(v_status, status),\n number = COALESCE(p_patch ->> 'number', number),\n series = COALESCE(p_patch ->> 'series', series),\n access_key = COALESCE(p_patch ->> 'access_key', access_key),\n verification_code = COALESCE(p_patch ->> 'verification_code', verification_code),\n status_payload = COALESCE(p_patch -> 'status_payload', status_payload),\n rejection_payload = CASE WHEN p_patch ? 'rejection_payload' THEN p_patch -> 'rejection_payload' ELSE rejection_payload END,\n authorized_at = COALESCE((p_patch ->> 'authorized_at')::timestamptz, authorized_at),\n last_polled_at = CASE WHEN p_action = 'poll' THEN now() ELSE last_polled_at END,\n cancelled_at = CASE WHEN p_patch ? 'cancelled_at' THEN (p_patch ->> 'cancelled_at')::timestamptz ELSE cancelled_at END,\n cancel_reason = CASE WHEN p_patch ? 'cancel_reason' THEN p_patch ->> 'cancel_reason' ELSE cancel_reason END,\n cancelled_by_user_id = CASE WHEN p_action = 'cancel' THEN auth.uid()\n WHEN p_patch ? 'cancelled_at' AND p_patch -> 'cancelled_at' = 'null'::jsonb THEN NULL\n ELSE cancelled_by_user_id END\n WHERE document_id = p_document_id;\n\n IF v_status IS NOT NULL THEN\n UPDATE public.documents SET status = v_status WHERE id = p_document_id AND status IS DISTINCT FROM v_status;\n END IF;\n\n IF p_event IS NOT NULL THEN\n INSERT INTO public.plg_fiscalbr_document_events\n (tenant_id, unit_id, document_id, event_type, status, justification, response_payload, created_by_user_id)\n VALUES (v.tenant_id, v.unit_id, p_document_id, p_event ->> 'event_type', p_event ->> 'status',\n p_event ->> 'justification', p_event -> 'response_payload', auth.uid());\n END IF;\nEND $$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_note_for_provider(uuid, text) FROM PUBLIC, anon;\nREVOKE ALL ON FUNCTION public.fiscalbr_note_apply(uuid, text, jsonb, jsonb) FROM PUBLIC, anon;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_note_for_provider(uuid, text) TO authenticated;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_note_apply(uuid, text, jsonb, jsonb) TO authenticated;\n`\n\nexport const MIGRATION_020_A_NOTA_ACHA_O_FORNECEDOR_PELO_CNPJ = `-- A nota acha o fornecedor pelo CNPJ — e, se não achar, cadastra.\n--\n-- O estágio (009) só casava o CNPJ no momento do import. As notas que vieram\n-- do V1 atravessaram sem o vínculo (003 deixou para \"a costura\"), e um\n-- fornecedor cadastrado depois nunca era religado: 1029 notas com o fornecedor\n-- no cadastro e a tela dizendo \"não está no cadastro\", e o título aceito no V2\n-- nascendo sem contraparte (o traço em Contas a Pagar).\n--\n-- O V1 nunca pediu cadastro: ao aceitar, \\`resolveSupplierId\\` procura o\n-- fornecedor pelo CNPJ e, sem achar, cria com o nome e o CNPJ da nota. Esta\n-- função é esse gesto, com duas pontas:\n--\n-- p_create = false só casa (ao abrir a nota)\n-- p_create = true casa ou cria (antes de aceitar)\n--\n-- O título da nota, se já existe e está SEM contraparte, recebe a mesma pessoa.\n-- Nunca troca um vínculo gravado. Idempotente.\n\nCREATE OR REPLACE FUNCTION public.plg_fiscalbr_supplier_for_cnpj(p_tenant uuid, p_cnpj text)\nRETURNS uuid\nLANGUAGE sql\nSTABLE\nSET search_path TO ''\nAS $$\n SELECT p.id FROM public.people p\n WHERE p.tenant_id = p_tenant\n AND p_cnpj <> ''\n AND public.plg_fiscalbr_digits(p.document_number) = p_cnpj\n ORDER BY (p.kind = 'supplier') DESC, p.created_at\n LIMIT 1\n$$;\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_link_inbox_supplier(p_document_id uuid, p_create boolean DEFAULT false)\nRETURNS jsonb\nLANGUAGE plpgsql\nSECURITY DEFINER\nSET search_path TO ''\nAS $$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_cnpj text;\n v_party uuid;\n v_created boolean := false;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE id = p_document_id AND tenant_id = v_tenant;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscal: inbox note not found' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission(\n CASE WHEN p_create THEN 'financial.create' ELSE 'financial.read' END, v_doc.unit_id);\n\n v_party := v_doc.supplier_party_id;\n v_cnpj := public.plg_fiscalbr_digits(v_doc.supplier_cnpj);\n\n IF v_party IS NULL THEN\n v_party := public.plg_fiscalbr_supplier_for_cnpj(v_tenant, v_cnpj);\n END IF;\n\n -- Without a CNPJ there is nothing to match on; a name-only person would be a\n -- duplicate waiting to happen, so creation needs the document.\n IF v_party IS NULL AND p_create AND v_cnpj <> '' THEN\n INSERT INTO public.people (tenant_id, kind, name, document_number)\n VALUES (v_tenant, 'supplier', coalesce(nullif(trim(v_doc.supplier_name), ''), 'Fornecedor ' || v_cnpj), v_cnpj)\n RETURNING id INTO v_party;\n v_created := true;\n END IF;\n\n IF v_party IS NOT NULL AND v_doc.supplier_party_id IS NULL THEN\n UPDATE public.plg_fiscalbr_inbox_documents\n SET supplier_party_id = v_party\n WHERE id = v_doc.id AND supplier_party_id IS NULL;\n END IF;\n\n IF v_party IS NOT NULL AND v_doc.invoice_id IS NOT NULL THEN\n UPDATE public.plg_financial_invoices\n SET counterparty_person_id = v_party\n WHERE id = v_doc.invoice_id AND tenant_id = v_tenant AND counterparty_person_id IS NULL;\n END IF;\n\n RETURN jsonb_build_object('supplier_party_id', v_party, 'created', v_created);\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_link_inbox_supplier(uuid, boolean) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_link_inbox_supplier(uuid, boolean) TO authenticated;\n\n-- Backfill: match only, NULLs only. Nothing is created here — creating a person\n-- is the operator's gesture (accepting), not a migration's.\nWITH p AS (\n SELECT DISTINCT ON (tenant_id, dg) tenant_id, dg, id\n FROM (SELECT tenant_id, id, kind, created_at, public.plg_fiscalbr_digits(document_number) AS dg\n FROM public.people\n WHERE document_number IS NOT NULL) x\n WHERE length(dg) = 14\n ORDER BY tenant_id, dg, (kind = 'supplier') DESC, created_at\n)\nUPDATE public.plg_fiscalbr_inbox_documents d\n SET supplier_party_id = p.id\n FROM p\n WHERE d.supplier_party_id IS NULL\n AND p.tenant_id = d.tenant_id\n AND p.dg = public.plg_fiscalbr_digits(d.supplier_cnpj);\n\nUPDATE public.plg_financial_invoices i\n SET counterparty_person_id = d.supplier_party_id\n FROM public.plg_fiscalbr_inbox_documents d\n WHERE d.invoice_id = i.id\n AND d.tenant_id = i.tenant_id\n AND d.supplier_party_id IS NOT NULL\n AND i.counterparty_person_id IS NULL;\n`\n\nexport const MIGRATION_021_USO_E_CONSUMO_ENTRA_NO_ESTOQUE = `-- \"Materiais de Uso e Consumo\" vira um tipo de registro da nota recebida.\n--\n-- É o que a casa gasta sem vender nem transformar — luva, descartável, material\n-- de limpeza — e que ainda assim se conta no estoque. Entra no estoque como o\n-- insumo: precisa de produto vinculado e gera movimento ao aceitar.\n--\n-- Aditivo e idempotente. A função de aceite é REMENDADA, não reescrita (mesmo\n-- padrão da 015): copiar o corpo da 010 apagaria o \\`reason\\` que a 015 enxertou.\n\nALTER TABLE public.plg_fiscalbr_inbox_items\n DROP CONSTRAINT IF EXISTS plg_fiscalbr_inbox_items_entry_type_chk;\nALTER TABLE public.plg_fiscalbr_inbox_items\n ADD CONSTRAINT plg_fiscalbr_inbox_items_entry_type_chk\n CHECK (entry_type IS NULL OR entry_type IN ('insumo','revenda','patrimonio','uso_consumo','despesa','servico'));\n\nALTER TABLE public.plg_fiscalbr_supplier_product_map\n DROP CONSTRAINT IF EXISTS plg_fiscalbr_supplier_product_map_entry_type_chk;\nALTER TABLE public.plg_fiscalbr_supplier_product_map\n ADD CONSTRAINT plg_fiscalbr_supplier_product_map_entry_type_chk\n CHECK (entry_type IS NULL OR entry_type IN ('insumo','revenda','patrimonio','uso_consumo','despesa','servico'));\n\nDO $m$\nDECLARE\n v_def text;\n v_antes text := $q$entry_type IN ('insumo','revenda','patrimonio')$q$;\n v_depois text := $q$entry_type IN ('insumo','revenda','patrimonio','uso_consumo')$q$;\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def\n FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n\n IF v_def IS NULL THEN\n RAISE EXCEPTION 'fiscalbr/021: fiscalbr_accept_inbox_document não existe — aplicar 009/010 antes';\n END IF;\n\n IF position('uso_consumo' in v_def) > 0 THEN RETURN; END IF;\n\n IF position(v_antes in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/021: o corpo de fiscalbr_accept_inbox_document não é o esperado — confira à mão em vez de deixar passar calado';\n END IF;\n\n EXECUTE replace(v_def, v_antes, v_depois);\nEND\n$m$;\n`\n\nexport const MIGRATION_022_A_NOTA_DO_V1_TRAZ_O_XML = `-- ---------------------------------------------------------------------------\n-- The V1 bridge carries the note's XML.\n-- ---------------------------------------------------------------------------\n-- 003 dropped \\`xml_content\\` because, back then, V2 had no column for it (016\n-- added one). Without the file a note copied from the V1 cannot be downloaded,\n-- and a note the V1 never broke into lines arrives with zero items and no way\n-- to rebuild them. Only the mapping changes; rows already copied are not touched.\n-- ---------------------------------------------------------------------------\n\n-- The row is already frozen, and trg_allowlist_frozen refuses a plain write;\n-- from zero this file stopped the rest of fiscal_br. A migration file is the\n-- one writer the hatch exists for, and SET LOCAL ends with the transaction.\nSET LOCAL migration.allowlist_unlock = 'on';\n\nUPDATE migration.allowlist\n SET columns = columns || jsonb_build_object('xml_content', 'xml_content')\n WHERE source_table = 'dfe_inbox'\n AND columns->>'xml_content' IS DISTINCT FROM 'xml_content';\n`\n\nexport const MIGRATION_023_A_NOTA_ACEITA_SEM_LINHAS_RECEBE_AS_LINHAS = `-- ---------------------------------------------------------------------------\n-- An accepted note that has no lines gets its lines, and nothing else.\n-- ---------------------------------------------------------------------------\n-- Notes copied from the V1 can carry a payable (or stock) and zero lines: the\n-- V1 never split their XML. Restaging is refused for them on purpose (it would\n-- rewrite the decision that became stock and payable), so they showed 0/0\n-- forever. This writes ONLY the missing lines, from the stored XML, and only\n-- while the note has none; the document, its payable and its instalments stay.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.fiscalbr_fill_inbox_lines(p_document_id uuid, p_items jsonb)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_cnpj text;\n v_item jsonb;\n v_map public.plg_fiscalbr_supplier_product_map%ROWTYPE;\n v_n integer := 0;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id\n FOR UPDATE; -- two opens of the same note must not both see \"no lines\"\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota não encontrada' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.create', v_doc.unit_id);\n\n IF EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items\n WHERE tenant_id = v_tenant AND inbox_document_id = v_doc.id) THEN\n RETURN jsonb_build_object('document_id', v_doc.id, 'items', 0, 'already_had_lines', true);\n END IF;\n\n v_cnpj := public.plg_fiscalbr_digits(v_doc.supplier_cnpj);\n\n FOR v_item IN SELECT * FROM jsonb_array_elements(coalesce(p_items, '[]'::jsonb)) LOOP\n v_n := v_n + 1;\n v_map := NULL;\n SELECT * INTO v_map FROM public.plg_fiscalbr_supplier_product_map\n WHERE tenant_id = v_tenant AND supplier_cnpj = v_cnpj\n AND supplier_product_code = coalesce(v_item->>'supplier_product_code', '');\n\n INSERT INTO public.plg_fiscalbr_inbox_items (\n tenant_id, inbox_document_id, item_number, supplier_product_code, ean_barcode,\n description, ncm, cest, cfop, unit_commercial, quantity_commercial,\n unit_price_commercial, total_price, discount, freight, other_expenses,\n icms_cst, icms_csosn, icms_base, icms_rate, icms_value,\n pis_value, cofins_value, ipi_value, raw_xml_item,\n product_id, entry_type, chart_account_id, stock_unit_id, conversion_factor,\n cost_mode, reconciled)\n VALUES (\n v_tenant, v_doc.id, coalesce((v_item->>'item_number')::int, v_n),\n v_item->>'supplier_product_code', v_item->>'ean_barcode',\n v_item->>'description', v_item->>'ncm', v_item->>'cest', v_item->>'cfop',\n v_item->>'unit', (v_item->>'quantity')::numeric,\n (v_item->>'unit_price')::numeric, (v_item->>'total')::numeric,\n (v_item->>'discount')::numeric, (v_item->>'freight')::numeric,\n (v_item->>'other')::numeric,\n v_item->>'icms_cst', v_item->>'icms_csosn', (v_item->>'icms_base')::numeric,\n (v_item->>'icms_rate')::numeric, (v_item->>'icms_value')::numeric,\n (v_item->>'pis_value')::numeric, (v_item->>'cofins_value')::numeric,\n (v_item->>'ipi_value')::numeric, v_item,\n v_map.product_id, v_map.entry_type, v_map.chart_account_id, v_map.stock_unit_id,\n coalesce(v_map.conversion_factor, 1), coalesce(v_map.cost_mode, 'novo'),\n v_map.product_id IS NOT NULL);\n END LOOP;\n\n RETURN jsonb_build_object('document_id', v_doc.id, 'items', v_n, 'already_had_lines', false);\nEND;\n$function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_fill_inbox_lines(uuid, jsonb) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_fill_inbox_lines(uuid, jsonb) TO authenticated;\n`\n\nexport const MIGRATION_024_A_NOTA_NAO_APONTA_PARA_CONTA_QUE_SUMIU = `-- ---------------------------------------------------------------------------\n-- A note never points at a payable (or stock movement) that no longer exists.\n-- ---------------------------------------------------------------------------\n-- invoice_id and stock_movement_id cross into other plugins, so they carry no\n-- foreign key. When a re-copy rebuilt a tenant's payables under new ids, the\n-- notes kept the old ones: the screen read \"already accepted\" and hid every\n-- action, while Contas a Pagar had nothing. This heals a note: a dead payable\n-- link is re-pointed to the live payable of the same NF-e when exactly one\n-- exists, otherwise cleared; a dead movement link is cleared, and the note\n-- stops counting as stocked only when that dead movement was all it had. A\n-- cleared note can be accepted again, which writes the payable and the stock.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.plg_fiscalbr_heal_note_links(p_tenant uuid, p_document_id uuid)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_invoice uuid;\n v_matches integer;\n v_dead_mv integer := 0;\n v_relinked boolean := false;\n v_released boolean := false;\n v_unstocked boolean := false;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = p_tenant AND id = p_document_id\n FOR UPDATE;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('document_id', p_document_id, 'changed', false);\n END IF;\n\n IF v_doc.invoice_id IS NOT NULL AND NOT EXISTS (\n SELECT 1 FROM public.plg_financial_invoices f WHERE f.id = v_doc.invoice_id) THEN\n -- Same NF-e: the key this plugin writes, or the V1 conciliation's text for the same supplier.\n SELECT count(*), min(f.id::text)::uuid INTO v_matches, v_invoice\n FROM public.plg_financial_invoices f\n WHERE f.tenant_id = p_tenant AND f.direction = 'payable' AND f.cancelled_at IS NULL\n AND (f.idempotency_key = 'danfe:' || v_doc.access_key\n OR (v_doc.supplier_party_id IS NOT NULL\n AND f.counterparty_person_id = v_doc.supplier_party_id\n AND f.description ~ ('NF-e 0*' || ltrim(v_doc.nfe_number, '0') || '(\\\\D|$)')))\n AND NOT EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_documents o\n WHERE o.tenant_id = p_tenant AND o.invoice_id = f.id AND o.id <> v_doc.id);\n IF v_matches = 1 THEN\n v_relinked := true;\n ELSE\n v_invoice := NULL;\n v_released := true;\n END IF;\n UPDATE public.plg_fiscalbr_inbox_documents SET invoice_id = v_invoice, updated_at = now()\n WHERE id = v_doc.id;\n END IF;\n\n UPDATE public.plg_fiscalbr_inbox_items i SET stock_movement_id = NULL, updated_at = now()\n WHERE i.tenant_id = p_tenant AND i.inbox_document_id = v_doc.id\n AND i.stock_movement_id IS NOT NULL\n AND NOT EXISTS (SELECT 1 FROM public.plg_inventory_stock_movements m WHERE m.id = i.stock_movement_id);\n GET DIAGNOSTICS v_dead_mv = ROW_COUNT;\n\n IF v_dead_mv > 0 AND v_doc.stocked_at IS NOT NULL\n AND v_doc.inventory_operation_id IS NULL\n AND NOT EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = p_tenant AND i.inbox_document_id = v_doc.id\n AND i.stock_movement_id IS NOT NULL) THEN\n UPDATE public.plg_fiscalbr_inbox_documents SET stocked_at = NULL, updated_at = now()\n WHERE id = v_doc.id;\n v_unstocked := true;\n END IF;\n\n RETURN jsonb_build_object('document_id', v_doc.id,\n 'changed', v_relinked OR v_released OR v_dead_mv > 0,\n 'relinked', v_relinked, 'released', v_released,\n 'dead_movements', v_dead_mv, 'unstocked', v_unstocked);\nEND;\n$function$;\n\nREVOKE ALL ON FUNCTION public.plg_fiscalbr_heal_note_links(uuid, uuid) FROM PUBLIC, anon, authenticated;\n\n-- The screen heals the note it opens, so a future re-copy cannot strand one again.\nCREATE OR REPLACE FUNCTION public.fiscalbr_heal_inbox_note(p_document_id uuid)\nRETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_tenant uuid := public.plg_financial_require_tenant();\n v_unit uuid;\nBEGIN\n SELECT unit_id INTO v_unit FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = v_tenant AND id = p_document_id;\n IF NOT FOUND THEN\n RAISE EXCEPTION 'fiscalbr: nota não encontrada' USING ERRCODE = 'P0002';\n END IF;\n PERFORM public.plg_financial_require_permission('financial.create', v_unit);\n RETURN public.plg_fiscalbr_heal_note_links(v_tenant, p_document_id);\nEND;\n$function$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_heal_inbox_note(uuid) FROM PUBLIC;\nGRANT EXECUTE ON FUNCTION public.fiscalbr_heal_inbox_note(uuid) TO authenticated;\n\n-- Heal what is already stranded.\nDO $backfill$\nDECLARE r record;\nBEGIN\n FOR r IN\n SELECT DISTINCT d.tenant_id, d.id\n FROM public.plg_fiscalbr_inbox_documents d\n LEFT JOIN public.plg_fiscalbr_inbox_items i\n ON i.tenant_id = d.tenant_id AND i.inbox_document_id = d.id\n WHERE (d.invoice_id IS NOT NULL\n AND NOT EXISTS (SELECT 1 FROM public.plg_financial_invoices f WHERE f.id = d.invoice_id))\n OR (i.stock_movement_id IS NOT NULL\n AND NOT EXISTS (SELECT 1 FROM public.plg_inventory_stock_movements m WHERE m.id = i.stock_movement_id))\n LOOP\n PERFORM public.plg_fiscalbr_heal_note_links(r.tenant_id, r.id);\n END LOOP;\nEND\n$backfill$;\n`\n\nexport const MIGRATION_025_A_CONTA_DA_NOTA_FECHA_COM_O_TOTAL = `-- ---------------------------------------------------------------------------\n-- The payable a note opens lists products as products, and adds up to its total.\n-- ---------------------------------------------------------------------------\n-- Two defects in the lines fiscalbr_accept_inbox_document wrote:\n-- 1. \\`itemKind\\` carried the fiscal entry type ('insumo', 'revenda'…), which the\n-- financial screens do not know, so a linked product showed as \"Insumo\"\n-- with no product. The kind is 'product' when the line has one; the entry\n-- type moves to \\`entryType\\`, and product/chart account go to their columns.\n-- 2. Only the product lines were written, so freight, insurance, other\n-- expenses, IPI, ICMS-ST and discount were in the total but in no line\n-- (NF-e 1430116: R$ 480,47 owed, R$ 478,47 listed). Each becomes a line,\n-- and whatever still differs from the instalments becomes one more.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.plg_fiscalbr_note_charge_lines(\n p_tenant uuid, p_document_id uuid, p_invoice_id uuid, p_total numeric)\nRETURNS integer LANGUAGE plpgsql SECURITY DEFINER SET search_path TO '' AS $function$\nDECLARE\n v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;\n v_sum numeric;\n v_rest numeric;\n v_n integer := 0;\n v_c record;\nBEGIN\n SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents\n WHERE tenant_id = p_tenant AND id = p_document_id;\n IF NOT FOUND OR p_invoice_id IS NULL THEN RETURN 0; END IF;\n IF EXISTS (SELECT 1 FROM public.items\n WHERE tenant_id = p_tenant AND invoice_id = p_invoice_id\n AND metadata ? 'noteCharge') THEN\n RETURN 0;\n END IF;\n -- Only a payable that already lists the note's products: a V1 copy with no lines\n -- would get its whole total as one \"difference\" line.\n IF NOT EXISTS (SELECT 1 FROM public.items\n WHERE tenant_id = p_tenant AND invoice_id = p_invoice_id\n AND metadata ? 'cfop') THEN\n RETURN 0;\n END IF;\n\n FOR v_c IN\n SELECT * FROM (VALUES\n (1, 'freight', 'Frete', round(coalesce(v_doc.total_freight, 0), 2)),\n (2, 'insurance', 'Seguro', round(coalesce(v_doc.total_insurance, 0), 2)),\n (3, 'other', 'Outras despesas da nota', round(coalesce(v_doc.total_other, 0), 2)),\n (4, 'ipi', 'IPI', round(coalesce(v_doc.total_ipi_value, 0), 2)),\n (5, 'icms_st', 'ICMS-ST', round(coalesce(v_doc.total_icms_st_value, 0), 2)),\n (6, 'discount', 'Desconto da nota', -round(coalesce(v_doc.total_discount, 0), 2))\n ) AS c(ord, code, label, amount)\n WHERE amount <> 0\n ORDER BY ord\n LOOP\n INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)\n VALUES (p_tenant, p_invoice_id, v_c.label, 1, v_c.amount, v_c.amount, 1000 + v_c.ord,\n jsonb_build_object('itemKind', 'other', 'noteCharge', v_c.code));\n v_n := v_n + 1;\n END LOOP;\n\n SELECT coalesce(sum(total), 0) INTO v_sum FROM public.items\n WHERE tenant_id = p_tenant AND invoice_id = p_invoice_id AND cancelled_at IS NULL;\n v_rest := round(coalesce(p_total, 0) - v_sum, 2);\n IF v_rest <> 0 THEN\n INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)\n VALUES (p_tenant, p_invoice_id, 'Diferença entre a nota e as parcelas', 1, v_rest, v_rest, 1099,\n jsonb_build_object('itemKind', 'other', 'noteCharge', 'instalment_difference'));\n v_n := v_n + 1;\n END IF;\n RETURN v_n;\nEND;\n$function$;\n\nREVOKE ALL ON FUNCTION public.plg_fiscalbr_note_charge_lines(uuid, uuid, uuid, numeric) FROM PUBLIC, anon, authenticated;\n\nDO $m$\nDECLARE\n v_def text;\n v_start integer;\n v_end integer;\n v_marker text := 'INSERT INTO public.items (tenant_id, invoice_id, name, quantity, unit_price, total, sort_order, metadata)';\n v_close text := 'ON CONFLICT DO NOTHING;';\n v_new text := $q$INSERT INTO public.items (tenant_id, invoice_id, product_id, chart_account_id, name, quantity, unit_price, total, sort_order, metadata)\n SELECT v_tenant, v_invoice, i.product_id, coalesce(i.chart_account_id, v_doc.default_chart_account_id),\n i.description, i.quantity_commercial, i.unit_price_commercial,\n round(coalesce(i.total_price, 0), 2), i.item_number,\n jsonb_strip_nulls(jsonb_build_object(\n 'itemKind', CASE WHEN i.product_id IS NOT NULL THEN 'product' ELSE 'other' END,\n 'referenceId', i.product_id, 'entryType', i.entry_type,\n 'chartAccountId', coalesce(i.chart_account_id, v_doc.default_chart_account_id),\n 'ncm', i.ncm, 'cfop', i.cfop,\n 'supplierProductCode', i.supplier_product_code))\n FROM public.plg_fiscalbr_inbox_items i\n WHERE i.tenant_id = v_tenant AND i.inbox_document_id = v_doc.id\n ORDER BY i.item_number\n ON CONFLICT DO NOTHING;\n PERFORM public.plg_fiscalbr_note_charge_lines(v_tenant, v_doc.id, v_invoice, v_total);$q$;\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def\n FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n IF v_def IS NULL THEN\n RAISE EXCEPTION 'fiscalbr/025: fiscalbr_accept_inbox_document does not exist';\n END IF;\n IF position('plg_fiscalbr_note_charge_lines' in v_def) > 0 THEN RETURN; END IF;\n\n v_start := position(v_marker in v_def);\n IF v_start = 0 THEN\n RAISE EXCEPTION 'fiscalbr/025: unexpected body of fiscalbr_accept_inbox_document — check by hand';\n END IF;\n v_end := v_start + position(v_close in substr(v_def, v_start)) - 1 + length(v_close);\n EXECUTE substr(v_def, 1, v_start - 1) || v_new || substr(v_def, v_end);\nEND\n$m$;\n\n-- The payables already opened by notes: same kind/product fix, and the missing charge lines.\nALTER TABLE public.items DISABLE TRIGGER items_invoice_line_immutable;\n\nUPDATE public.items it\n SET product_id = coalesce(it.product_id, (it.metadata->>'referenceId')::uuid),\n metadata = jsonb_set(it.metadata || jsonb_build_object('entryType', it.metadata->>'itemKind'),\n '{itemKind}', '\"product\"'::jsonb, true),\n updated_at = now()\n FROM public.plg_financial_invoices f\n WHERE f.id = it.invoice_id\n AND f.metadata ? 'danfe'\n AND it.metadata->>'itemKind' IN ('insumo','revenda','patrimonio','uso_consumo','despesa','servico')\n AND it.metadata->>'referenceId' IS NOT NULL\n AND EXISTS (SELECT 1 FROM public.products p WHERE p.id = (it.metadata->>'referenceId')::uuid);\n\nUPDATE public.items it\n SET metadata = jsonb_set(it.metadata || jsonb_build_object('entryType', it.metadata->>'itemKind'),\n '{itemKind}', '\"other\"'::jsonb, true),\n updated_at = now()\n FROM public.plg_financial_invoices f\n WHERE f.id = it.invoice_id\n AND f.metadata ? 'danfe'\n AND it.metadata->>'itemKind' IN ('insumo','revenda','patrimonio','uso_consumo','despesa','servico');\n\nALTER TABLE public.items ENABLE TRIGGER items_invoice_line_immutable;\n\nDO $backfill$\nDECLARE r record;\nBEGIN\n FOR r IN\n SELECT d.tenant_id, d.id, f.id AS invoice_id, f.total\n FROM public.plg_fiscalbr_inbox_documents d\n JOIN public.plg_financial_invoices f ON f.id = d.invoice_id AND f.tenant_id = d.tenant_id\n WHERE f.metadata ? 'danfe' AND f.cancelled_at IS NULL\n LOOP\n PERFORM public.plg_fiscalbr_note_charge_lines(r.tenant_id, r.id, r.invoice_id, r.total);\n END LOOP;\nEND\n$backfill$;\n`\n\nexport const MIGRATION_026_O_RECEBIMENTO_PARADO_DIZ_POR_QUE = `-- ---------------------------------------------------------------------------\n-- When notes stop arriving, the emitter row says why.\n-- ---------------------------------------------------------------------------\n-- The SEFAZ pull fails per CNPJ (expired A1 certificate, provider refusal) and\n-- the V1 records only the last failure (integration_sync_state.last_error). The\n-- V2 kept nothing, so a tenant could go two weeks without a note and no screen\n-- would say so. These two columns hold that last failure; the notes list warns\n-- from them and from a stale dfe_last_sync_at.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_fiscalbr_emitter_settings\n ADD COLUMN IF NOT EXISTS dfe_last_error text,\n ADD COLUMN IF NOT EXISTS dfe_last_error_at timestamptz;\n\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.dfe_last_error IS\n 'V1: integration_sync_state.last_error (source = dfe_inbox) — last failure pulling notes from SEFAZ; null when the last pull worked.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.dfe_last_error_at IS\n 'V1: integration_sync_state.last_synced_at when last_status = error.';\n\nGRANT SELECT (dfe_last_error, dfe_last_error_at) ON public.plg_fiscalbr_emitter_settings TO authenticated;\n`\n\nexport const MIGRATION_027_A_NOTA_COM_CONTA_E_SEM_ESTOQUE_TERMINA_NO_V2 = `-- ---------------------------------------------------------------------------\n-- A note that has its payable but never reached stock can be finished in V2.\n-- ---------------------------------------------------------------------------\n-- In the V1, saving the payment plan of a DANFE import opened the payable\n-- before anyone reconciled the lines; many imports stopped there. Copied over,\n-- those notes carry invoice_id and no stock, and both RPCs read invoice_id as\n-- \"accepted\": nothing could be reconciled and the goods never entered stock\n-- (Artorius 18, Espaço Facial 72, Pertinho 17 on 14/10/2026).\n--\n-- \"Settled\" is now: stocked, or a payable with no stock line left to receive.\n-- Saving decisions is allowed until then, and accepting a note that already has\n-- its payable receives the stock against it instead of opening a second one.\n-- ---------------------------------------------------------------------------\n\nDO $m$\nDECLARE\n v_def text;\n v_old text;\n v_new text;\n v_start integer;\n v_end integer;\n v_pending constant text := $q$NOT EXISTS (SELECT 1 FROM public.plg_fiscalbr_inbox_items x\n WHERE x.tenant_id = v_tenant AND x.inbox_document_id = v_doc.id\n AND x.stock_movement_id IS NULL\n AND (x.entry_type IS NULL OR x.entry_type = '' OR x.entry_type IN ('insumo','revenda','patrimonio','uso_consumo')))$q$;\nBEGIN\n -- 1. Saving decisions.\n SELECT pg_get_functiondef(p.oid) INTO v_def FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_save_inbox_decision';\n v_old := 'IF v_doc.stocked_at IS NOT NULL OR v_doc.invoice_id IS NOT NULL THEN';\n IF v_def IS NULL THEN RAISE EXCEPTION 'fiscalbr/027: fiscalbr_save_inbox_decision does not exist'; END IF;\n IF position(v_old in v_def) > 0 THEN\n v_def := replace(v_def, v_old, 'IF v_doc.stocked_at IS NOT NULL OR (v_doc.invoice_id IS NOT NULL AND ' || v_pending || ') THEN');\n -- v_tenant is that function's own variable name too.\n EXECUTE v_def;\n ELSIF position('x.stock_movement_id IS NULL' in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/027: unexpected body of fiscalbr_save_inbox_decision — check by hand';\n END IF;\n\n -- 2. Accepting.\n SELECT pg_get_functiondef(p.oid) INTO v_def FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n IF v_def IS NULL THEN RAISE EXCEPTION 'fiscalbr/027: fiscalbr_accept_inbox_document does not exist'; END IF;\n IF position('Half-done in the V1' in v_def) > 0 THEN RETURN; END IF;\n\n IF position(v_old in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/027: unexpected guard in fiscalbr_accept_inbox_document — check by hand';\n END IF;\n v_def := replace(v_def, v_old, 'IF v_doc.stocked_at IS NOT NULL OR (v_doc.invoice_id IS NOT NULL AND ' || v_pending || ') THEN');\n\n v_start := position(' SELECT coalesce(sum(value), 0),' in v_def);\n v_new := 'PERFORM public.plg_fiscalbr_note_charge_lines(v_tenant, v_doc.id, v_invoice, v_total);';\n v_end := position(v_new in v_def);\n IF v_start = 0 OR v_end = 0 OR v_end < v_start THEN\n RAISE EXCEPTION 'fiscalbr/027: unexpected payable block in fiscalbr_accept_inbox_document — check by hand';\n END IF;\n v_end := v_end + length(v_new);\n v_def := substr(v_def, 1, v_start - 1)\n || $q$ IF v_doc.invoice_id IS NOT NULL THEN\n -- Half-done in the V1: the payable exists; only the stock is missing.\n v_invoice := v_doc.invoice_id;\n SELECT total INTO v_total FROM public.plg_financial_invoices WHERE id = v_invoice;\n v_insts := '[]'::jsonb;\n ELSE\n$q$ || substr(v_def, v_start, v_end - v_start) || $q$\n END IF;$q$\n || substr(v_def, v_end);\n EXECUTE v_def;\nEND\n$m$;\n`\n\nexport const MIGRATION_028_A_LINHA_DE_ESTOQUE_TEM_UNIDADE = `-- ---------------------------------------------------------------------------\n-- A stock line enters with its unit.\n-- ---------------------------------------------------------------------------\n-- Accepting let a stock line through with no stock unit; the movement then\n-- carried a bare quantity that every screen reads as \"unidade\" (Artorius, NF-e\n-- 222879: 20 kg of copa lombo entered as 20 units). The screen now suggests the\n-- unit and refuses without one; this is the same rule where it cannot be\n-- skipped.\n-- ---------------------------------------------------------------------------\n\nDO $m$\nDECLARE\n v_def text;\n v_old constant text := $q$ IF v_it.product_id IS NULL THEN$q$;\n v_new constant text := $q$ IF v_it.stock_unit_id IS NULL THEN\n RAISE EXCEPTION 'fiscalbr: item % entra no estoque sem unidade — escolha a unidade de estoque', v_it.item_number\n USING ERRCODE = '23514';\n END IF;\n IF v_it.product_id IS NULL THEN$q$;\nBEGIN\n SELECT pg_get_functiondef(p.oid) INTO v_def FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE n.nspname = 'public' AND p.proname = 'fiscalbr_accept_inbox_document';\n IF v_def IS NULL THEN RAISE EXCEPTION 'fiscalbr/028: fiscalbr_accept_inbox_document does not exist'; END IF;\n IF position('entra no estoque sem unidade' in v_def) > 0 THEN RETURN; END IF;\n IF position(v_old in v_def) = 0 THEN\n RAISE EXCEPTION 'fiscalbr/028: unexpected body of fiscalbr_accept_inbox_document — check by hand';\n END IF;\n EXECUTE replace(v_def, v_old, v_new);\nEND\n$m$;\n`\n\nexport const MIGRATION_029_THE_SERVICE_WRITES_THE_INTAKE_HEALTH = `-- ============================================================================\n-- 029_the_service_writes_the_intake_health — the DF-e pull moves to the\n-- integration service (ADR 0003 phase 2).\n--\n-- The pull reads a tenant's emitter rows AS the caller (RLS decides which), and\n-- then records each CNPJ's outcome in three health columns, even for a reader\n-- without settings.manage, so the notes list can say \"intake stopped\". The\n-- edge function did that with service_role; the service gets exactly those\n-- three columns, by row id, and nothing else on the table.\n--\n-- Guarded: the role is an operator step. Replay-safe.\n-- ============================================================================\n\nDO $$\nBEGIN\n IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'fayz_integration')\n AND to_regclass('public.plg_fiscalbr_emitter_settings') IS NOT NULL THEN\n GRANT SELECT (id) ON public.plg_fiscalbr_emitter_settings TO fayz_integration;\n GRANT UPDATE (dfe_last_sync_at, dfe_last_error, dfe_last_error_at) ON public.plg_fiscalbr_emitter_settings TO fayz_integration;\n DROP POLICY IF EXISTS plg_fiscalbr_emitter_settings_service_health ON public.plg_fiscalbr_emitter_settings;\n CREATE POLICY plg_fiscalbr_emitter_settings_service_health ON public.plg_fiscalbr_emitter_settings\n FOR UPDATE TO fayz_integration USING (true) WITH CHECK (true);\n DROP POLICY IF EXISTS plg_fiscalbr_emitter_settings_service_read ON public.plg_fiscalbr_emitter_settings;\n CREATE POLICY plg_fiscalbr_emitter_settings_service_read ON public.plg_fiscalbr_emitter_settings\n FOR SELECT TO fayz_integration USING (true);\n END IF;\nEND $$;\n`\n\nexport const MIGRATION_030_THE_SERVICE_ONBOARDS_THE_EMITTER = `-- ============================================================================\n-- 030 — the integration service onboards the emitter\n--\n-- The integration service registers the company at PlugNotas (certificate,\n-- company, NF-e and NFC-e configuration, webhook) from the integration screen\n-- (control-sdk-backend ADR 0008). The emitter's facts stay here: the legal\n-- entity (public.company_legal_entities) and its settings\n-- (plg_fiscalbr_emitter_settings, one row per CNPJ). These are the doors the\n-- service reads and writes them through, one function per action, the\n-- tenant explicit, open only to \\`fayz_integration\\`.\n--\n-- NF-e gets what NFC-e already had: environment, series and the next number\n-- (numbering continues from the previous system, so no number is skipped or\n-- used twice). The CSC token stays write-only for the screen; the service\n-- reads it here because PlugNotas needs it to sign NFC-e.\n-- ============================================================================\n\nALTER TABLE public.plg_fiscalbr_emitter_settings\n ADD COLUMN IF NOT EXISTS nfe_production boolean NOT NULL DEFAULT false,\n ADD COLUMN IF NOT EXISTS nfe_series integer CHECK (nfe_series IS NULL OR nfe_series > 0),\n ADD COLUMN IF NOT EXISTS nfe_next_number bigint CHECK (nfe_next_number IS NULL OR nfe_next_number > 0),\n ADD COLUMN IF NOT EXISTS nfce_next_number bigint CHECK (nfce_next_number IS NULL OR nfce_next_number > 0),\n ADD COLUMN IF NOT EXISTS provider_webhook_at timestamptz,\n -- PlugNotas' codes. The legal entity's tax_regime is free text copied from\n -- the V1 ('simples_nacional', 'other'); guessing a regime from 'other' would\n -- register the company wrong, so the store states it once.\n ADD COLUMN IF NOT EXISTS tax_regime_code smallint CHECK (tax_regime_code IS NULL OR tax_regime_code BETWEEN 1 AND 3),\n ADD COLUMN IF NOT EXISTS special_tax_regime_code smallint NOT NULL DEFAULT 0 CHECK (special_tax_regime_code BETWEEN 0 AND 11);\n\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.nfe_next_number IS\n 'The next NF-e number PlugNotas will use for nfe_series; set when the store moves from another system.';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.tax_regime_code IS\n '1 Simples Nacional, 2 Simples Nacional over the sublimit, 3 normal regime (presumed or real profit).';\nCOMMENT ON COLUMN public.plg_fiscalbr_emitter_settings.provider_webhook_at IS\n 'When the integration service registered its webhook for this CNPJ at PlugNotas.';\n\n-- One emitter as the service needs it: the legal entity and its settings,\n-- CSC token included. NULL when the legal entity is not the tenant's.\nCREATE OR REPLACE FUNCTION public.fiscalbr_emitter_for_service(p_tenant uuid, p_legal_entity uuid)\nRETURNS jsonb\nLANGUAGE sql STABLE SECURITY DEFINER\nSET search_path TO ''\nAS $$\n SELECT jsonb_build_object(\n 'legalEntityId', l.id,\n 'tenantId', l.tenant_id,\n 'cnpj', regexp_replace(coalesce(l.document_number, ''), '\\\\D', '', 'g'),\n 'legalName', l.legal_name,\n 'tradeName', l.trade_name,\n 'stateRegistration', l.state_registration,\n 'municipalRegistration', l.municipal_registration,\n 'taxRegime', l.tax_regime,\n -- Stated on the emitter, else read from a regime the text names unambiguously.\n 'taxRegimeCode', coalesce(s.tax_regime_code, CASE WHEN l.tax_regime = 'simples_nacional' THEN 1 END),\n 'specialTaxRegimeCode', coalesce(s.special_tax_regime_code, 0),\n 'cnae', l.cnae,\n 'email', coalesce(nullif(l.fiscal_email, ''), l.email),\n 'phone', l.phone,\n -- The address is a row of public.addresses (142); the legal entity's own\n -- columns are the retired shape, read only when no address row exists.\n 'address', CASE WHEN a.id IS NOT NULL THEN jsonb_build_object(\n 'street', a.street, 'number', a.number, 'complement', a.complement,\n 'district', a.district, 'city', a.city, 'state', a.state, 'postalCode', a.postal_code,\n 'ibgeCityCode', l.ibge_city_code, 'country', a.country\n ) ELSE jsonb_build_object(\n 'street', l.address, 'number', l.address_number, 'complement', l.address_complement,\n 'district', l.district, 'city', l.city, 'state', l.state, 'postalCode', l.postal_code,\n 'ibgeCityCode', l.ibge_city_code, 'country', l.country\n ) END,\n 'settings', CASE WHEN s.id IS NULL THEN NULL ELSE jsonb_build_object(\n 'nfe', jsonb_build_object('enabled', s.nfe_enabled, 'production', s.nfe_production, 'series', s.nfe_series, 'nextNumber', s.nfe_next_number),\n 'nfce', jsonb_build_object('enabled', s.nfce_enabled, 'production', s.nfce_production, 'series', s.nfce_series, 'nextNumber', s.nfce_next_number,\n 'cscId', s.nfce_csc_id, 'cscToken', s.nfce_csc_token, 'genericItem', s.nfce_generic_item),\n 'certificate', jsonb_build_object('providerId', s.certificate_provider_id, 'holder', s.certificate_cn,\n 'expiresAt', s.certificate_expires_at, 'uploadedAt', s.certificate_uploaded_at),\n 'providerSyncedAt', s.provider_synced_at,\n 'providerWebhookAt', s.provider_webhook_at\n ) END\n )\n FROM public.company_legal_entities l\n LEFT JOIN public.plg_fiscalbr_emitter_settings s ON s.legal_entity_id = l.id AND s.tenant_id = l.tenant_id\n LEFT JOIN LATERAL (\n SELECT * FROM public.addresses x\n WHERE x.tenant_id = l.tenant_id AND x.owner_type = 'company_legal_entity' AND x.owner_id = l.id\n ORDER BY (x.kind = 'fiscal') DESC, x.is_default DESC, x.created_at\n LIMIT 1\n ) a ON true\n WHERE l.id = p_legal_entity AND l.tenant_id = p_tenant\n$$;\n\n-- Every legal entity of the tenant that a unit points at: the emitters a\n-- screen can set up.\nCREATE OR REPLACE FUNCTION public.fiscalbr_emitters_for_service(p_tenant uuid)\nRETURNS SETOF jsonb\nLANGUAGE sql STABLE SECURITY DEFINER\nSET search_path TO ''\nAS $$\n SELECT public.fiscalbr_emitter_for_service(p_tenant, l.id)\n FROM public.company_legal_entities l\n WHERE l.tenant_id = p_tenant\n AND EXISTS (SELECT 1 FROM app.units u WHERE u.tenant_id = p_tenant AND u.company_legal_entity_id = l.id)\n ORDER BY l.legal_name\n$$;\n\n-- Records what the service set at PlugNotas. Only the keys below move; the\n-- row is created on first write.\nCREATE OR REPLACE FUNCTION public.fiscalbr_emitter_record(p_tenant uuid, p_legal_entity uuid, p_patch jsonb)\nRETURNS void\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path TO ''\nAS $$\nDECLARE\n v_unknown text;\nBEGIN\n IF NOT EXISTS (SELECT 1 FROM public.company_legal_entities WHERE id = p_legal_entity AND tenant_id = p_tenant) THEN\n RAISE EXCEPTION 'fiscalbr_emitter_record: legal entity % is not of tenant %', p_legal_entity, p_tenant USING ERRCODE = 'P0002';\n END IF;\n SELECT k INTO v_unknown FROM jsonb_object_keys(p_patch) k\n WHERE k NOT IN ('nfe_enabled', 'nfe_production', 'nfe_series', 'nfe_next_number',\n 'nfce_enabled', 'nfce_production', 'nfce_series', 'nfce_next_number', 'nfce_csc_id', 'nfce_csc_token',\n 'certificate_provider_id', 'certificate_cn', 'certificate_expires_at', 'certificate_uploaded_at',\n 'provider_synced_at', 'provider_webhook_at', 'tax_regime_code', 'special_tax_regime_code')\n LIMIT 1;\n IF v_unknown IS NOT NULL THEN\n RAISE EXCEPTION 'fiscalbr_emitter_record: % is not recorded here', v_unknown USING ERRCODE = '22023';\n END IF;\n\n INSERT INTO public.plg_fiscalbr_emitter_settings (tenant_id, legal_entity_id)\n VALUES (p_tenant, p_legal_entity)\n ON CONFLICT (legal_entity_id) DO NOTHING;\n\n UPDATE public.plg_fiscalbr_emitter_settings s SET\n nfe_enabled = CASE WHEN p_patch ? 'nfe_enabled' THEN (p_patch ->> 'nfe_enabled')::boolean ELSE s.nfe_enabled END,\n nfe_production = CASE WHEN p_patch ? 'nfe_production' THEN (p_patch ->> 'nfe_production')::boolean ELSE s.nfe_production END,\n nfe_series = CASE WHEN p_patch ? 'nfe_series' THEN (p_patch ->> 'nfe_series')::integer ELSE s.nfe_series END,\n nfe_next_number = CASE WHEN p_patch ? 'nfe_next_number' THEN (p_patch ->> 'nfe_next_number')::bigint ELSE s.nfe_next_number END,\n nfce_enabled = CASE WHEN p_patch ? 'nfce_enabled' THEN (p_patch ->> 'nfce_enabled')::boolean ELSE s.nfce_enabled END,\n nfce_production = CASE WHEN p_patch ? 'nfce_production' THEN (p_patch ->> 'nfce_production')::boolean ELSE s.nfce_production END,\n nfce_series = CASE WHEN p_patch ? 'nfce_series' THEN (p_patch ->> 'nfce_series')::integer ELSE s.nfce_series END,\n nfce_next_number = CASE WHEN p_patch ? 'nfce_next_number' THEN (p_patch ->> 'nfce_next_number')::bigint ELSE s.nfce_next_number END,\n nfce_csc_id = CASE WHEN p_patch ? 'nfce_csc_id' THEN p_patch ->> 'nfce_csc_id' ELSE s.nfce_csc_id END,\n nfce_csc_token = CASE WHEN p_patch ? 'nfce_csc_token' THEN p_patch ->> 'nfce_csc_token' ELSE s.nfce_csc_token END,\n certificate_provider_id = CASE WHEN p_patch ? 'certificate_provider_id' THEN p_patch ->> 'certificate_provider_id' ELSE s.certificate_provider_id END,\n certificate_cn = CASE WHEN p_patch ? 'certificate_cn' THEN p_patch ->> 'certificate_cn' ELSE s.certificate_cn END,\n certificate_expires_at = CASE WHEN p_patch ? 'certificate_expires_at' THEN (p_patch ->> 'certificate_expires_at')::timestamptz ELSE s.certificate_expires_at END,\n certificate_uploaded_at = CASE WHEN p_patch ? 'certificate_uploaded_at' THEN (p_patch ->> 'certificate_uploaded_at')::timestamptz ELSE s.certificate_uploaded_at END,\n provider_synced_at = CASE WHEN p_patch ? 'provider_synced_at' THEN (p_patch ->> 'provider_synced_at')::timestamptz ELSE s.provider_synced_at END,\n provider_webhook_at = CASE WHEN p_patch ? 'provider_webhook_at' THEN (p_patch ->> 'provider_webhook_at')::timestamptz ELSE s.provider_webhook_at END,\n tax_regime_code = CASE WHEN p_patch ? 'tax_regime_code' THEN (p_patch ->> 'tax_regime_code')::smallint ELSE s.tax_regime_code END,\n special_tax_regime_code = CASE WHEN p_patch ? 'special_tax_regime_code' THEN coalesce((p_patch ->> 'special_tax_regime_code')::smallint, 0) ELSE s.special_tax_regime_code END,\n updated_at = now()\n WHERE s.legal_entity_id = p_legal_entity AND s.tenant_id = p_tenant;\nEND\n$$;\n\nREVOKE ALL ON FUNCTION public.fiscalbr_emitter_for_service(uuid, uuid) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.fiscalbr_emitters_for_service(uuid) FROM PUBLIC, anon, authenticated;\nREVOKE ALL ON FUNCTION public.fiscalbr_emitter_record(uuid, uuid, jsonb) FROM PUBLIC, anon, authenticated;\n\nDO $$\nBEGIN\n IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'fayz_integration') THEN\n GRANT USAGE ON SCHEMA public TO fayz_integration;\n GRANT EXECUTE ON FUNCTION public.fiscalbr_emitter_for_service(uuid, uuid) TO fayz_integration;\n GRANT EXECUTE ON FUNCTION public.fiscalbr_emitters_for_service(uuid) TO fayz_integration;\n GRANT EXECUTE ON FUNCTION public.fiscalbr_emitter_record(uuid, uuid, jsonb) TO fayz_integration;\n END IF;\nEND\n$$;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"000_baseline\", sql: MIGRATION_000_BASELINE },\n { id: \"001_preserve_terminal_results_and_recover_leases\", sql: MIGRATION_001_PRESERVE_TERMINAL_RESULTS_AND_RECOVER_LEASES },\n { id: \"002_a_nota_que_chega_tem_onde_esperar\", sql: MIGRATION_002_A_NOTA_QUE_CHEGA_TEM_ONDE_ESPERAR },\n { id: \"003_a_caixa_de_entrada_atravessa\", sql: MIGRATION_003_A_CAIXA_DE_ENTRADA_ATRAVESSA },\n { id: \"004_o_grupo_fiscal_do_v1_repete_nome\", sql: MIGRATION_004_O_GRUPO_FISCAL_DO_V1_REPETE_NOME },\n { id: \"005_a_nota_emitida_e_um_documento\", sql: MIGRATION_005_A_NOTA_EMITIDA_E_UM_DOCUMENTO },\n { id: \"006_o_grupo_fiscal_ganha_o_rail\", sql: MIGRATION_006_O_GRUPO_FISCAL_GANHA_O_RAIL },\n { id: \"007_a_rls_do_documento_passa_a_ser_legivel\", sql: MIGRATION_007_A_RLS_DO_DOCUMENTO_PASSA_A_SER_LEGIVEL },\n { id: \"008_a_nota_recebida_guarda_a_decisao_de_entrada\", sql: MIGRATION_008_A_NOTA_RECEBIDA_GUARDA_A_DECISAO_DE_ENTRADA },\n { id: \"009_aceitar_a_nota_escreve_estoque_e_titulo_de_uma_vez\", sql: MIGRATION_009_ACEITAR_A_NOTA_ESCREVE_ESTOQUE_E_TITULO_DE_UMA_VEZ },\n { id: \"010_a_data_de_emissao_e_instante_e_a_competencia_e_dia\", sql: MIGRATION_010_A_DATA_DE_EMISSAO_E_INSTANTE_E_A_COMPETENCIA_E_DIA },\n { id: \"011_o_imposto_do_produto_e_do_fiscal\", sql: MIGRATION_011_O_IMPOSTO_DO_PRODUTO_E_DO_FISCAL },\n { id: \"012_quem_e_o_produto_se_pergunta_ao_indice\", sql: MIGRATION_012_QUEM_E_O_PRODUTO_SE_PERGUNTA_AO_INDICE },\n { id: \"013_a_sugestao_sobrevive_a_fechar_a_janela\", sql: MIGRATION_013_A_SUGESTAO_SOBREVIVE_A_FECHAR_A_JANELA },\n { id: \"014_a_descricao_da_nota_tem_lixo_no_meio\", sql: MIGRATION_014_A_DESCRICAO_DA_NOTA_TEM_LIXO_NO_MEIO },\n { id: \"015_o_movimento_diz_que_veio_da_nota\", sql: MIGRATION_015_O_MOVIMENTO_DIZ_QUE_VEIO_DA_NOTA },\n { id: \"016_a_nota_guarda_o_proprio_xml\", sql: MIGRATION_016_A_NOTA_GUARDA_O_PROPRIO_XML },\n { id: \"017_quem_emite_e_o_cnpj_nao_a_loja\", sql: MIGRATION_017_QUEM_EMITE_E_O_CNPJ_NAO_A_LOJA },\n { id: \"018_a_nota_do_v1_alcanca_a_conta\", sql: MIGRATION_018_A_NOTA_DO_V1_ALCANCA_A_CONTA },\n { id: \"019_a_nota_emitida_se_cancela_pelo_v2\", sql: MIGRATION_019_A_NOTA_EMITIDA_SE_CANCELA_PELO_V2 },\n { id: \"020_a_nota_acha_o_fornecedor_pelo_cnpj\", sql: MIGRATION_020_A_NOTA_ACHA_O_FORNECEDOR_PELO_CNPJ },\n { id: \"021_uso_e_consumo_entra_no_estoque\", sql: MIGRATION_021_USO_E_CONSUMO_ENTRA_NO_ESTOQUE },\n { id: \"022_a_nota_do_v1_traz_o_xml\", sql: MIGRATION_022_A_NOTA_DO_V1_TRAZ_O_XML },\n { id: \"023_a_nota_aceita_sem_linhas_recebe_as_linhas\", sql: MIGRATION_023_A_NOTA_ACEITA_SEM_LINHAS_RECEBE_AS_LINHAS },\n { id: \"024_a_nota_nao_aponta_para_conta_que_sumiu\", sql: MIGRATION_024_A_NOTA_NAO_APONTA_PARA_CONTA_QUE_SUMIU },\n { id: \"025_a_conta_da_nota_fecha_com_o_total\", sql: MIGRATION_025_A_CONTA_DA_NOTA_FECHA_COM_O_TOTAL },\n { id: \"026_o_recebimento_parado_diz_por_que\", sql: MIGRATION_026_O_RECEBIMENTO_PARADO_DIZ_POR_QUE },\n { id: \"027_a_nota_com_conta_e_sem_estoque_termina_no_v2\", sql: MIGRATION_027_A_NOTA_COM_CONTA_E_SEM_ESTOQUE_TERMINA_NO_V2 },\n { id: \"028_a_linha_de_estoque_tem_unidade\", sql: MIGRATION_028_A_LINHA_DE_ESTOQUE_TEM_UNIDADE },\n { id: \"029_the_service_writes_the_intake_health\", sql: MIGRATION_029_THE_SERVICE_WRITES_THE_INTAKE_HEALTH },\n { id: \"030_the_service_onboards_the_emitter\", sql: MIGRATION_030_THE_SERVICE_ONBOARDS_THE_EMITTER },\n]\n","import type { EntityDef, PluginRegistryDef } from '@fayz-ai/core'\nimport { RECORD_GROUP, recordRailFields, activeFacet } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Grupos fiscais — a tributação que um produto herda.\n//\n// A tabela existe desde a 002 deste plugin e NUNCA teve tela: o grupo fiscal\n// de toda conta migrada estava no banco sem porta. Isto é a porta.\n//\n// O que ele responde é uma pergunta só, feita muitas vezes: com que imposto\n// este produto sai na nota. Agrupar é o ponto — sem grupo, CFOP, CST, origem e\n// três alíquotas seriam repetidos em cada produto, e mudar a regra de um\n// estado viraria uma edição em massa.\n//\n// A ordem dos campos segue a da nota: primeiro o que classifica a OPERAÇÃO\n// (CFOP), depois o ICMS, depois PIS/COFINS, e por último IBS/CBS — que é a\n// reforma tributária, e que já tem campo porque o V1 já tem.\n// ---------------------------------------------------------------------------\n\nconst taxGroupEntity: EntityDef = {\n name: 'Grupo fiscal',\n namePlural: 'Grupos fiscais',\n icon: 'ReceiptText',\n displayField: 'name',\n defaultSort: 'name',\n formColumns: 2,\n facets: [activeFacet({ active: 'Ativos', inactive: 'Inativos', all: 'Todos' })],\n fieldGroups: [\n {\n id: 'identity', label: 'Identificação', columns: 2,\n description: 'O nome é como a casa chama o grupo («Bebida alcoólica», «Serviço isento») — o resto é o que a nota exige.',\n },\n { id: 'icms', label: 'ICMS', columns: 3 },\n { id: 'pis_cofins', label: 'PIS e COFINS', columns: 2 },\n {\n id: 'ibs_cbs', label: 'IBS e CBS', columns: 2,\n description: 'A reforma tributária. Em branco enquanto não for exigido da sua operação.',\n },\n { ...RECORD_GROUP },\n ],\n fields: [\n { key: 'name', label: 'Nome', type: 'text', required: true, showInTable: true, searchable: true, group: 'identity', span: 2 },\n // O CFOP classifica a OPERAÇÃO (venda dentro do estado, fora, devolução) e\n // é o primeiro campo que o contador confere.\n { key: 'cfop', label: 'CFOP', type: 'text', showInTable: true, searchable: true, group: 'identity' },\n // CEST anda com a substituição tributária: só existe para quem está nela.\n { key: 'cest', label: 'CEST', type: 'text', showInTable: false, group: 'identity' },\n { key: 'benefitCode', label: 'Código de benefício', type: 'text', showInTable: false, group: 'identity' },\n\n // CST é do regime normal e CSOSN é do Simples — a casa usa UM dos dois, e\n // qual depende do regime dela, não deste grupo. Os dois ficam à vista de\n // propósito: esconder o que a conta não usa exigiria saber o regime aqui.\n { key: 'cst', label: 'CST', type: 'text', showInTable: true, group: 'icms' },\n { key: 'csosn', label: 'CSOSN (Simples)', type: 'text', showInTable: false, group: 'icms' },\n {\n key: 'icmsOrigin', label: 'Origem da mercadoria', type: 'select', showInTable: false, group: 'icms',\n options: [\n { value: '0', label: '0 — Nacional' },\n { value: '1', label: '1 — Estrangeira, importação direta' },\n { value: '2', label: '2 — Estrangeira, mercado interno' },\n { value: '3', label: '3 — Nacional, conteúdo de importação > 40%' },\n { value: '4', label: '4 — Nacional, processos produtivos básicos' },\n { value: '5', label: '5 — Nacional, conteúdo de importação ≤ 40%' },\n { value: '6', label: '6 — Estrangeira, sem similar nacional' },\n { value: '7', label: '7 — Estrangeira, mercado interno sem similar' },\n { value: '8', label: '8 — Nacional, conteúdo de importação > 70%' },\n ],\n },\n { key: 'icmsRate', label: 'Alíquota ICMS (%)', type: 'number', min: 0, max: 100, showInTable: true, group: 'icms' },\n { key: 'icmsBcMode', label: 'Modalidade da base', type: 'text', showInTable: false, group: 'icms' },\n { key: 'baseCalculationMode', label: 'Cálculo da base', type: 'text', showInTable: false, group: 'icms' },\n // O fundo de combate à pobreza é adicional ao ICMS em alguns estados.\n { key: 'povertyFundRate', label: 'Fundo de pobreza (%)', type: 'number', min: 0, max: 100, showInTable: false, group: 'icms' },\n\n { key: 'pisSituation', label: 'Situação PIS', type: 'text', showInTable: false, group: 'pis_cofins' },\n { key: 'pisRate', label: 'Alíquota PIS (%)', type: 'number', min: 0, max: 100, showInTable: false, group: 'pis_cofins' },\n { key: 'cofinsSituation', label: 'Situação COFINS', type: 'text', showInTable: false, group: 'pis_cofins' },\n { key: 'cofinsRate', label: 'Alíquota COFINS (%)', type: 'number', min: 0, max: 100, showInTable: false, group: 'pis_cofins' },\n\n { key: 'ibsCbsSituation', label: 'Situação IBS/CBS', type: 'text', showInTable: false, group: 'ibs_cbs' },\n { key: 'ibsCbsClassification', label: 'Classificação IBS/CBS', type: 'text', showInTable: false, group: 'ibs_cbs' },\n\n ...recordRailFields({ tagsTable: 'plg_fiscalbr_tax_groups', activeLabel: 'Ativo' }),\n ],\n data: {\n table: 'plg_fiscalbr_tax_groups',\n schema: 'public',\n tenantScoped: true,\n searchColumns: ['name', 'cfop'],\n },\n}\n\nexport const fiscalRegistries: PluginRegistryDef[] = [\n {\n id: 'taxGroups',\n icon: 'ReceiptText',\n entity: taxGroupEntity,\n description: 'A tributação que um produto herda: CFOP, ICMS, PIS/COFINS e, quando exigido, IBS/CBS.',\n agentHint: 'Regras de imposto que um produto herda — NÃO é a nota emitida nem o imposto de uma venda específica.',\n },\n]\n","// ---------------------------------------------------------------------------\n// nfe-xml — read a supplier NF-e (layout 4.00) into the shape the inbox wants.\n// ---------------------------------------------------------------------------\n// The XML is decomposed HERE, in TypeScript, and not in PL/pgSQL. Three reasons,\n// in order of how much each one cost when ignored elsewhere:\n//\n// 1. A parser with a unit test is a parser you can trust. The assertions in\n// nfe-xml.test.ts compare against what the V1 itself read out of the same\n// three documents, so drift is caught by the origin rather than by a number\n// someone typed into an expectation.\n// 2. A file that is not a nota has to produce a sentence the operator can act\n// on (\"this is an NFC-e, not a supplier note\"), and `RAISE EXCEPTION` from\n// a trigger deep in a transaction is not that sentence.\n// 3. The same reader runs in the browser, so the drop zone can show what it\n// found before anything is written.\n//\n// No XML dependency. The reader below is ~70 lines because NF-e is\n// machine-generated: no CDATA in the elements we read, no DTD, no mixed content.\n// Adding a parser to the dependency tree of every app that installs this plugin\n// to avoid those 70 lines is the worse trade.\n// ---------------------------------------------------------------------------\n\nexport interface NfeSupplier {\n cnpj: string\n name: string\n tradeName?: string\n ie?: string\n city?: string\n state?: string\n}\n\nexport interface NfeItem {\n itemNumber: number\n supplierProductCode: string\n eanBarcode?: string\n description: string\n ncm?: string\n cest?: string\n cfop?: string\n unit?: string\n quantity: number\n unitPrice: number\n total: number\n discount?: number\n freight?: number\n other?: number\n icmsCst?: string\n icmsCsosn?: string\n icmsOrigin?: string\n icmsBase?: number\n icmsRate?: number\n icmsValue?: number\n pisValue?: number\n cofinsValue?: number\n ipiValue?: number\n}\n\nexport interface NfeDuplicate {\n index: number\n number?: string\n dueDate?: string\n value: number\n}\n\nexport interface NfePayment {\n index: number\n indicator?: string\n code?: string\n label?: string\n value: number\n}\n\nexport interface NfeTotals {\n total: number\n products: number\n discount: number\n freight: number\n insurance: number\n other: number\n icmsBase?: number\n icmsValue?: number\n pisValue?: number\n cofinsValue?: number\n ipiValue?: number\n}\n\nexport interface ParsedNfe {\n accessKey: string\n nfeNumber: string\n nfeSeries: string\n nfeModel: string\n issueDate: string\n natureOperation?: string\n supplier: NfeSupplier\n totals: NfeTotals\n items: NfeItem[]\n duplicates: NfeDuplicate[]\n payments: NfePayment[]\n additionalInfo?: string\n protocol?: string\n authorizedAt?: string\n}\n\nexport class NfeParseError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'NfeParseError'\n }\n}\n\n// ── The reader ─────────────────────────────────────────────────────────────\n\ninterface XNode {\n name: string\n attrs: Record<string, string>\n children: XNode[]\n text: string\n}\n\nconst ENTITIES: Record<string, string> = {\n amp: '&', lt: '<', gt: '>', quot: '\"', apos: \"'\",\n}\n\nfunction decode(raw: string): string {\n return raw.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (whole, body: string) => {\n if (body.startsWith('#x') || body.startsWith('#X')) return String.fromCodePoint(parseInt(body.slice(2), 16))\n if (body.startsWith('#')) return String.fromCodePoint(parseInt(body.slice(1), 10))\n return ENTITIES[body] ?? whole\n })\n}\n\n// Namespace prefixes are dropped: the whole document lives in the portalfiscal\n// namespace and a supplier that emits `ns2:infNFe` is emitting the same note.\nconst bare = (name: string) => {\n const i = name.indexOf(':')\n return i < 0 ? name : name.slice(i + 1)\n}\n\nfunction parseXml(xml: string): XNode {\n // Declaration, comments and processing instructions carry nothing we read.\n const src = xml\n .replace(/<\\?[\\s\\S]*?\\?>/g, '')\n .replace(/<!--[\\s\\S]*?-->/g, '')\n .replace(/<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>/g, (_m, inner: string) => inner)\n .replace(/<!DOCTYPE[^>]*>/gi, '')\n\n const root: XNode = { name: '#root', attrs: {}, children: [], text: '' }\n const stack: XNode[] = [root]\n const tag = /<\\s*(\\/?)\\s*([A-Za-z_][\\w.:-]*)((?:\\s+[\\w.:-]+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'))*)\\s*(\\/?)\\s*>/g\n\n let cursor = 0\n let m: RegExpExecArray | null\n while ((m = tag.exec(src)) !== null) {\n const [whole, closing, rawName, rawAttrs, selfClosing] = m\n const top = stack[stack.length - 1]\n const between = src.slice(cursor, m.index)\n if (between.trim()) top.text += decode(between)\n cursor = m.index + whole.length\n\n if (closing) {\n if (stack.length > 1) stack.pop()\n continue\n }\n\n const attrs: Record<string, string> = {}\n const attrRe = /([\\w.:-]+)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/g\n let a: RegExpExecArray | null\n while ((a = attrRe.exec(rawAttrs ?? '')) !== null) {\n attrs[bare(a[1])] = decode(a[2] ?? a[3] ?? '')\n }\n\n const node: XNode = { name: bare(rawName), attrs, children: [], text: '' }\n top.children.push(node)\n if (!selfClosing) stack.push(node)\n }\n return root\n}\n\nconst kids = (node: XNode | undefined, name: string): XNode[] =>\n node ? node.children.filter((c) => c.name === name) : []\n\nconst kid = (node: XNode | undefined, name: string): XNode | undefined => kids(node, name)[0]\n\n/** Walk a dot path (`ide.nNF`). Returns undefined at the first missing step. */\nfunction at(node: XNode | undefined, path: string): XNode | undefined {\n let cur = node\n for (const step of path.split('.')) {\n cur = kid(cur, step)\n if (!cur) return undefined\n }\n return cur\n}\n\nconst str = (node: XNode | undefined, path?: string): string | undefined => {\n const target = path ? at(node, path) : node\n const value = target?.text.trim()\n return value ? value : undefined\n}\n\n// The NF-e writes decimals with a dot and no thousands separator, so Number is\n// enough — but a missing tag must come back as undefined, not 0: a freight that\n// was not declared is not a freight of zero, and the difference shows up in the\n// total the payable is opened with.\nconst num = (node: XNode | undefined, path?: string): number | undefined => {\n const value = str(node, path)\n if (value === undefined) return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nconst zero = (node: XNode | undefined, path?: string): number => num(node, path) ?? 0\n\n// ── tPag → the V1's own payment vocabulary ─────────────────────────────────\n//\n// Table from NF-e 4.00 layout, collapsed onto the ten values V1 actually stores\n// (measured in `danfe_payments.payment_type`). Anything unmapped becomes\n// `outro`, which is what the V1 does with 107 of its 1.069 rows.\nconst PAYMENT_BY_CODE: Record<string, string> = {\n '01': 'dinheiro',\n '02': 'outro', // cheque\n '03': 'cartao_credito',\n '04': 'cartao_debito',\n '05': 'credito_loja',\n '10': 'outro', // vale alimentação\n '11': 'outro', // vale refeição\n '12': 'vale_presente',\n '13': 'outro', // vale combustível\n '14': 'duplicata_mercantil',\n '15': 'boleto',\n '16': 'outro', // depósito bancário\n '17': 'pix',\n '18': 'outro', // transferência bancária\n '19': 'outro', // programa de fidelidade\n '90': 'sem_pagamento',\n '99': 'outro',\n}\n\nconst PAYMENT_LABEL: Record<string, string> = {\n dinheiro: 'Dinheiro',\n cartao_credito: 'Cartão de crédito',\n cartao_debito: 'Cartão de débito',\n credito_loja: 'Crédito na loja',\n vale_presente: 'Vale presente',\n duplicata_mercantil: 'Duplicata mercantil',\n boleto: 'Boleto',\n pix: 'PIX',\n sem_pagamento: 'Sem pagamento',\n outro: 'Outro',\n}\n\n/** The V1's payment vocabulary for an NF-e `tPag` code. */\nexport function paymentTypeFromCode(code: string | undefined): string {\n if (!code) return 'outro'\n return PAYMENT_BY_CODE[code.padStart(2, '0')] ?? 'outro'\n}\n\nexport function paymentLabel(type: string): string {\n return PAYMENT_LABEL[type] ?? 'Outro'\n}\n\nexport const onlyDigits = (value: string | undefined): string => (value ?? '').replace(/\\D+/g, '')\n\n// ── The note ───────────────────────────────────────────────────────────────\n\n/**\n * Read a supplier NF-e. Accepts both the standalone `<NFe>` and the\n * `<nfeProc>` envelope the SEFAZ returns (which is what PlugNotas delivers and\n * what the V1 has stored for all 80 of Artorius' notes).\n */\nexport function parseNfeXml(xml: string): ParsedNfe {\n if (!xml || !xml.trim()) throw new NfeParseError('O arquivo está vazio.')\n\n const root = parseXml(xml)\n const proc = kid(root, 'nfeProc')\n const nfe = kid(proc ?? root, 'NFe') ?? kid(root, 'NFe')\n const inf = kid(nfe, 'infNFe')\n\n if (!inf) {\n throw new NfeParseError(\n 'Este arquivo não é uma NF-e: não encontrei <infNFe>. Se veio do fornecedor, peça o XML da nota, não o DANFE em PDF.',\n )\n }\n\n // The access key lives in the Id attribute as \"NFe\" + 44 digits. It is the\n // identity of the document — every idempotency key downstream derives from it.\n const accessKey = onlyDigits(inf.attrs.Id ?? inf.attrs.id ?? '')\n if (accessKey.length !== 44) {\n throw new NfeParseError(\n `A chave de acesso tem ${accessKey.length} dígitos e deveria ter 44. O arquivo pode estar truncado.`,\n )\n }\n\n const ide = kid(inf, 'ide')\n const model = str(ide, 'mod') ?? '55'\n if (model !== '55') {\n // 65 is NFC-e — a note the shop ISSUES at the till, not one a supplier sends.\n // Letting it through would open a payable against the shop's own customer.\n throw new NfeParseError(\n `Este XML é modelo ${model}${model === '65' ? ' (NFC-e, nota de venda no balcão)' : ''}, e a entrada de notas recebe NF-e modelo 55 de fornecedor.`,\n )\n }\n\n const emit = kid(inf, 'emit')\n const ender = kid(emit, 'enderEmit')\n const total = at(inf, 'total.ICMSTot')\n const dhEmi = str(ide, 'dhEmi') ?? str(ide, 'dEmi') ?? ''\n\n const items: NfeItem[] = kids(inf, 'det').map((det, i) => {\n const prod = kid(det, 'prod')\n const imposto = kid(det, 'imposto')\n // ICMS carries exactly one child, and which one depends on the supplier's tax\n // regime: ICMS00/20/40/60/90 for the normal regime, ICMSSN101/102/… for\n // Simples Nacional. Reading \"the child, whichever it is\" costs one line and\n // survives a supplier changing regime; a list of names does not.\n const icms = kid(imposto, 'ICMS')?.children[0]\n const pis = kid(imposto, 'PIS')?.children[0]\n const cofins = kid(imposto, 'COFINS')?.children[0]\n const ipi = kid(kid(imposto, 'IPI'), 'IPITrib')\n\n return {\n itemNumber: Number(det.attrs.nItem ?? i + 1) || i + 1,\n supplierProductCode: str(prod, 'cProd') ?? '',\n eanBarcode: str(prod, 'cEAN'),\n description: str(prod, 'xProd') ?? '(sem descrição)',\n ncm: str(prod, 'NCM'),\n cest: str(prod, 'CEST'),\n cfop: str(prod, 'CFOP'),\n unit: str(prod, 'uCom'),\n quantity: zero(prod, 'qCom'),\n unitPrice: zero(prod, 'vUnCom'),\n total: zero(prod, 'vProd'),\n discount: num(prod, 'vDesc'),\n freight: num(prod, 'vFrete'),\n other: num(prod, 'vOutro'),\n icmsCst: str(icms, 'CST'),\n icmsCsosn: str(icms, 'CSOSN'),\n icmsOrigin: str(icms, 'orig'),\n icmsBase: num(icms, 'vBC'),\n icmsRate: num(icms, 'pICMS'),\n icmsValue: num(icms, 'vICMS'),\n pisValue: num(pis, 'vPIS'),\n cofinsValue: num(cofins, 'vCOFINS'),\n ipiValue: num(ipi, 'vIPI'),\n }\n })\n\n if (items.length === 0) {\n throw new NfeParseError('A nota não tem nenhum item — não há o que dar entrada.')\n }\n\n // `cobr > dup` is the instalment plan the supplier declared. It is the reason\n // importing the note replaces typing the bill: the vencimentos come from the\n // document. A note without `dup` is not an error — it is paid on sight, and\n // the accept RPC opens a single instalment for it.\n const cobr = kid(inf, 'cobr')\n const duplicates: NfeDuplicate[] = kids(cobr, 'dup').map((dup, i) => ({\n index: i + 1,\n number: str(dup, 'nDup'),\n dueDate: str(dup, 'dVenc'),\n value: zero(dup, 'vDup'),\n }))\n\n const payments: NfePayment[] = kids(kid(inf, 'pag'), 'detPag').map((det, i) => {\n const code = str(det, 'tPag')\n const type = paymentTypeFromCode(code)\n return {\n index: i + 1,\n indicator: str(det, 'indPag'),\n code,\n label: paymentLabel(type),\n value: zero(det, 'vPag'),\n }\n })\n\n const prot = at(proc, 'protNFe.infProt')\n\n return {\n accessKey,\n nfeNumber: str(ide, 'nNF') ?? '',\n nfeSeries: str(ide, 'serie') ?? '',\n nfeModel: model,\n // The layout writes an ISO instant with offset; the inbox stores a date.\n issueDate: dhEmi.slice(0, 10),\n natureOperation: str(ide, 'natOp'),\n supplier: {\n cnpj: onlyDigits(str(emit, 'CNPJ') ?? str(emit, 'CPF')),\n name: str(emit, 'xNome') ?? '',\n tradeName: str(emit, 'xFant'),\n ie: str(emit, 'IE'),\n city: str(ender, 'xMun'),\n state: str(ender, 'UF'),\n },\n totals: {\n total: zero(total, 'vNF'),\n products: zero(total, 'vProd'),\n discount: zero(total, 'vDesc'),\n freight: zero(total, 'vFrete'),\n insurance: zero(total, 'vSeg'),\n other: zero(total, 'vOutro'),\n icmsBase: num(total, 'vBC'),\n icmsValue: num(total, 'vICMS'),\n pisValue: num(total, 'vPIS'),\n cofinsValue: num(total, 'vCOFINS'),\n ipiValue: num(total, 'vIPI'),\n },\n items,\n duplicates,\n payments,\n additionalInfo: str(at(inf, 'infAdic'), 'infCpl'),\n protocol: str(prot, 'nProt'),\n authorizedAt: str(prot, 'dhRecbto'),\n }\n}\n\n// ── The payload the staging RPC wants ──────────────────────────────────────\n//\n// `fiscalbr_stage_inbox_document` takes snake_case jsonb, and the mapping lives\n// next to the parser so a renamed field breaks in one place instead of being\n// silently dropped into a column that stays null.\n\nexport function toStagePayload(\n note: ParsedNfe,\n options: { unitId?: string | null; source?: string; xml?: string } = {},\n) {\n return {\n // O ARQUIVO VIAJA JUNTO. Ele já está na mão aqui — o parser acabou de lê-lo —\n // e sem isto os bytes morriam no fim da função: nota fiscal tem guarda legal\n // de cinco anos e a única cópia ficava na pasta de downloads de quem importou.\n ...(options.xml ? { xml: options.xml } : {}),\n access_key: note.accessKey,\n nfe_number: note.nfeNumber,\n nfe_series: note.nfeSeries,\n nfe_model: note.nfeModel,\n issue_date: note.issueDate,\n nature_operation: note.natureOperation ?? null,\n additional_info: note.additionalInfo ?? null,\n unit_id: options.unitId ?? null,\n source: options.source ?? 'xml_upload',\n supplier: {\n cnpj: note.supplier.cnpj,\n name: note.supplier.name,\n ie: note.supplier.ie ?? null,\n },\n totals: {\n total: note.totals.total,\n products: note.totals.products,\n discount: note.totals.discount,\n freight: note.totals.freight,\n insurance: note.totals.insurance,\n other: note.totals.other,\n },\n items: note.items.map((i) => ({\n item_number: i.itemNumber,\n supplier_product_code: i.supplierProductCode,\n ean_barcode: i.eanBarcode ?? null,\n description: i.description,\n ncm: i.ncm ?? null,\n cest: i.cest ?? null,\n cfop: i.cfop ?? null,\n unit: i.unit ?? null,\n quantity: i.quantity,\n unit_price: i.unitPrice,\n total: i.total,\n discount: i.discount ?? null,\n freight: i.freight ?? null,\n other: i.other ?? null,\n icms_cst: i.icmsCst ?? null,\n icms_csosn: i.icmsCsosn ?? null,\n icms_base: i.icmsBase ?? null,\n icms_rate: i.icmsRate ?? null,\n icms_value: i.icmsValue ?? null,\n pis_value: i.pisValue ?? null,\n cofins_value: i.cofinsValue ?? null,\n ipi_value: i.ipiValue ?? null,\n })),\n // The instalment carries the payment form the note declared, so the\n // reconciliation dialog opens with `Boleto` already chosen instead of blank.\n duplicates: note.duplicates.map((d) => ({\n index: d.index,\n number: d.number ?? null,\n due_date: d.dueDate ?? null,\n value: d.value,\n payment_type: note.payments.length === 1 ? paymentTypeFromCode(note.payments[0].code) : null,\n })),\n payments: note.payments.map((p) => ({\n index: p.index,\n indicator: p.indicator ?? null,\n code: p.code ?? null,\n label: p.label ?? null,\n value: p.value,\n })),\n }\n}\n","// ---------------------------------------------------------------------------\n// inbox — the data layer of Entrada de Notas.\n// ---------------------------------------------------------------------------\n// Reads go through PostgREST so RLS answers; every WRITE goes through one of the\n// four RPCs of migration 009. That split is the whole safety property of this\n// screen: the browser never inserts a stock movement or a payable, it asks the\n// database to do both in one transaction with an idempotency key derived from\n// the NF-e access key.\n//\n// Nothing here parses XML. `../lib/nfe-xml` does that, is unit-tested against\n// three real notes, and hands this module the payload the staging RPC wants.\n// ---------------------------------------------------------------------------\nimport { getSupabaseClientOptional } from '@fayz-ai/core'\nimport { getActiveTenantId } from '@fayz-ai/admin'\nimport { parseNfeXml, toStagePayload, type ParsedNfe } from '../lib/nfe-xml'\nimport type {\n InboxNote, InboxNoteDetail, InboxItem, InboxInstalment,\n InboxStatusFilter, AcceptResult, StageResult, ProductOption,\n MeasurementUnitOption, ChartAccountOption, StockLocationOption,\n} from '../types'\n\nfunction sb() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not initialized')\n return supabase\n}\n\n// ── Leitura ────────────────────────────────────────────────────────────────\n\n// The two states the V1 list shows side by side, and they are NOT the same\n// question: `reconciled/total` counts items bound to a product, `stocked_at`\n// says the entry happened. 55 notes in the V1 were reconciled and never\n// stocked — a single \"status\" column would have hidden all 55.\nconst NOTE_COLUMNS = `\n id, access_key, nfe_number, nfe_series, issue_date, received_at, status,\n manifestation_status, manifested_at, manifestation_attempts,\n nature_operation, supplier_name, supplier_cnpj, supplier_party_id, xml_content,\n total_value, total_products, total_discount, total_freight,\n invoice_id, inventory_operation_id, stocked_at, reviewed_at,\n default_chart_account_id, default_location_id, unit_id, document_id, metadata,\n items:plg_fiscalbr_inbox_items(id, reconciled, entry_type),\n duplicates:plg_fiscalbr_inbox_duplicates(id, value)\n`\n\ninterface RawNote {\n items?: Array<{ id: string; reconciled: boolean | null; entry_type: string | null }>\n duplicates?: Array<{ id: string; value: number | string | null }>\n [key: string]: unknown\n}\n\nfunction rowToNote(row: RawNote): InboxNote {\n const items = row.items ?? []\n const duplicates = row.duplicates ?? []\n return {\n id: String(row.id),\n accessKey: String(row.access_key ?? ''),\n number: String(row.nfe_number ?? ''),\n series: String(row.nfe_series ?? ''),\n issueDate: (row.issue_date as string) ?? null,\n receivedAt: (row.received_at as string) ?? null,\n status: (row.status as string) ?? 'pending',\n manifestationStatus: (row.manifestation_status as string) ?? null,\n manifestedAt: (row.manifested_at as string) ?? null,\n manifestationAttempts: Number(row.manifestation_attempts ?? 0),\n natureOperation: (row.nature_operation as string) ?? null,\n supplierName: (row.supplier_name as string) ?? '',\n supplierCnpj: (row.supplier_cnpj as string) ?? null,\n supplierPartyId: (row.supplier_party_id as string) ?? null,\n total: Number(row.total_value ?? 0),\n itemCount: items.length,\n reconciledCount: items.filter((i) => i.reconciled).length,\n instalmentCount: duplicates.length,\n // The sum of instalments, because that is the total the payable is opened\n // with (financial/084) — showing the note total here would make the list and\n // Contas a Pagar disagree on 6,3% of notes.\n instalmentTotal: duplicates.reduce((acc, d) => acc + Number(d.value ?? 0), 0),\n invoiceId: (row.invoice_id as string) ?? null,\n operationId: (row.inventory_operation_id as string) ?? null,\n stockedAt: (row.stocked_at as string) ?? null,\n documentId: (row.document_id as string) ?? null,\n hasXml: Boolean(row.xml_content),\n unitId: (row.unit_id as string) ?? null,\n }\n}\n\nexport async function listInboxNotes(options: {\n filter?: InboxStatusFilter\n search?: string\n /** Narrows to one unit. Omitted = every unit the person reaches (RLS fences\n * the rest), which is what the V1 list did on \"Todas as unidades\". */\n unitId?: string\n /** Emission window, YYYY-MM-DD and inclusive. */\n from?: string\n to?: string\n limit?: number\n} = {}): Promise<InboxNote[]> {\n const { filter = 'all', search, unitId, from, to, limit = 200 } = options\n let query = sb().from('plg_fiscalbr_inbox_documents').select(NOTE_COLUMNS)\n\n if (unitId) query = query.eq('unit_id', unitId)\n // A nota sem data de emissão não some do recorte: ela ainda não foi lida do\n // XML, e esconder o que falta ler é esconder o trabalho.\n if (from) query = query.or(`issue_date.gte.${from},issue_date.is.null`)\n if (to) query = query.or(`issue_date.lte.${to},issue_date.is.null`)\n\n // `stocked` and `pending` are about the STOCK column, not about `status`:\n // \"pendente\" in the V1 list means the entry has not happened, whatever the\n // reconciliation says.\n if (filter === 'stocked') query = query.not('stocked_at', 'is', null)\n if (filter === 'pending') query = query.is('stocked_at', null)\n if (filter === 'rejected') query = query.eq('status', 'rejected')\n if (filter === 'manifest_error') query = query.eq('manifestation_status', 'erro')\n if (search?.trim()) {\n const term = search.trim()\n query = query.or(\n `supplier_name.ilike.%${term}%,nfe_number.ilike.%${term}%,access_key.ilike.%${term}%`,\n )\n }\n\n const { data, error } = await query\n .order('issue_date', { ascending: false, nullsFirst: false })\n .order('received_at', { ascending: false })\n .limit(limit)\n if (error) throw error\n return (data ?? []).map(rowToNote)\n}\n\nconst ITEM_COLUMNS = `\n id, item_number, supplier_product_code, ean_barcode, description, ncm, cest, cfop,\n unit_commercial, quantity_commercial, unit_price_commercial, total_price, discount,\n unit_taxable, quantity_taxable,\n icms_cst, icms_csosn, icms_base, icms_rate, icms_value, pis_value, cofins_value, ipi_value,\n product_id, entry_type, chart_account_id, stock_unit_id, stock_quantity,\n conversion_factor, cost_mode, unit_cost_new, reconciled, stock_movement_id,\n shortage_quantity, shortage_reason, shortage_note, suggested_by, suggestion_confidence\n`\n\nfunction rowToItem(row: Record<string, any>): InboxItem {\n const quantity = Number(row.quantity_commercial ?? 0)\n const factor = Number(row.conversion_factor ?? 1) || 1\n return {\n id: String(row.id),\n itemNumber: Number(row.item_number ?? 0),\n supplierProductCode: row.supplier_product_code ?? '',\n eanBarcode: row.ean_barcode ?? null,\n description: row.description ?? '',\n ncm: row.ncm ?? null,\n cest: row.cest ?? null,\n cfop: row.cfop ?? null,\n unit: row.unit_commercial ?? null,\n quantity,\n unitPrice: Number(row.unit_price_commercial ?? 0),\n total: Number(row.total_price ?? 0),\n unitTaxable: row.unit_taxable ?? null,\n quantityTaxable: row.quantity_taxable == null ? null : Number(row.quantity_taxable),\n discount: row.discount == null ? null : Number(row.discount),\n icmsCst: row.icms_cst ?? null,\n icmsCsosn: row.icms_csosn ?? null,\n icmsValue: row.icms_value == null ? null : Number(row.icms_value),\n productId: row.product_id ?? null,\n entryType: row.entry_type ?? null,\n chartAccountId: row.chart_account_id ?? null,\n stockUnitId: row.stock_unit_id ?? null,\n conversionFactor: factor,\n // Derived AND stored by the RPC. Reading the stored value keeps the screen\n // showing the number the operator accepted, and falls back to the product of\n // the two only while the decision has not been saved yet.\n stockQuantity: row.stock_quantity == null ? quantity * factor : Number(row.stock_quantity),\n costMode: row.cost_mode ?? 'novo',\n unitCostNew: row.unit_cost_new == null ? null : Number(row.unit_cost_new),\n reconciled: Boolean(row.reconciled),\n suggestedBy: row.suggested_by === 'ai' || row.suggested_by === 'ean' || row.suggested_by === 'supplier_map'\n ? row.suggested_by\n : null,\n suggestionConfidence: row.suggestion_confidence == null ? null : Number(row.suggestion_confidence),\n stockMovementId: row.stock_movement_id ?? null,\n shortageQuantity: row.shortage_quantity == null ? null : Number(row.shortage_quantity),\n shortageReason: row.shortage_reason ?? null,\n shortageNote: row.shortage_note ?? null,\n }\n}\n\nexport async function getInboxNote(id: string): Promise<InboxNoteDetail | null> {\n const { data, error } = await sb()\n .from('plg_fiscalbr_inbox_documents')\n .select(NOTE_COLUMNS)\n .eq('id', id)\n .maybeSingle()\n if (error) throw error\n if (!data) return null\n\n const [items, instalments, payments] = await Promise.all([\n sb().from('plg_fiscalbr_inbox_items').select(ITEM_COLUMNS)\n .eq('inbox_document_id', id).order('item_number'),\n sb().from('plg_fiscalbr_inbox_duplicates')\n .select('id, duplicate_index, number, due_date, value, payment_type, barcode, pix_key, payment_method_id')\n .eq('inbox_document_id', id).order('duplicate_index'),\n sb().from('plg_fiscalbr_inbox_payments')\n .select('id, payment_index, payment_type_code, payment_type_label, value')\n .eq('inbox_document_id', id).order('payment_index'),\n ])\n if (items.error) throw items.error\n if (instalments.error) throw instalments.error\n\n return {\n ...rowToNote(data as RawNote),\n natureOperation: (data as any).nature_operation ?? null,\n defaultChartAccountId: (data as any).default_chart_account_id ?? null,\n defaultLocationId: (data as any).default_location_id ?? null,\n items: (items.data ?? []).map(rowToItem),\n instalments: (instalments.data ?? []).map((d: any): InboxInstalment => ({\n id: String(d.id),\n index: Number(d.duplicate_index ?? 0),\n number: d.number ?? null,\n dueDate: d.due_date ?? null,\n amount: Number(d.value ?? 0),\n paymentType: d.payment_type ?? null,\n barcode: d.barcode ?? null,\n pixKey: d.pix_key ?? null,\n paymentMethodId: d.payment_method_id ?? null,\n })),\n declaredPayments: (payments.data ?? []).map((p: any) => ({\n index: Number(p.payment_index ?? 0),\n code: p.payment_type_code ?? null,\n label: p.payment_type_label ?? null,\n value: Number(p.value ?? 0),\n })),\n }\n}\n\n// ── Escrita: sempre por RPC ────────────────────────────────────────────────\n\n/**\n * Read one XML file and stage it. Returns what the parser found together with\n * how many items the de-para already bound, because that is the number the drop\n * zone reports: \"3 itens, 2 já vinculados\" is the difference between a screen\n * that remembers the supplier and one that does not.\n */\nexport async function stageNoteFromXml(\n xml: string,\n options: { unitId?: string | null } = {},\n): Promise<StageResult & { parsed: ParsedNfe }> {\n const parsed = parseNfeXml(xml)\n const { data, error } = await sb().rpc('fiscalbr_stage_inbox_document', {\n p_note: toStagePayload(parsed, { unitId: options.unitId ?? null, xml }),\n })\n if (error) throw error\n const res = (data ?? {}) as Record<string, unknown>\n return {\n documentId: String(res.document_id ?? ''),\n accessKey: String(res.access_key ?? parsed.accessKey),\n alreadyAccepted: Boolean(res.already_accepted),\n supplierPartyId: (res.supplier_party_id as string) ?? null,\n itemCount: Number(res.items ?? 0),\n matchedCount: Number(res.matched ?? 0),\n parsed,\n }\n}\n\n/**\n * Lines only, for a note that already became payable or stock but has none:\n * restaging is refused for those, so the stored XML fills the lines and nothing else.\n */\nexport async function fillInboxLines(documentId: string, xml: string): Promise<number> {\n const payload = toStagePayload(parseNfeXml(xml))\n const { data, error } = await sb().rpc('fiscalbr_fill_inbox_lines', {\n p_document_id: documentId,\n p_items: payload.items,\n })\n if (error) throw error\n return Number((data as Record<string, unknown> | null)?.items ?? 0)\n}\n\nexport interface HealResult {\n changed: boolean\n /** The payable it pointed at was gone and no live one matched: the note can be accepted again. */\n released: boolean\n}\n\n/** Re-points or clears a payable/movement link whose target was deleted. */\nexport async function healInboxNote(documentId: string): Promise<HealResult> {\n const { data, error } = await sb().rpc('fiscalbr_heal_inbox_note', { p_document_id: documentId })\n if (error) throw error\n const r = (data as Record<string, unknown> | null) ?? {}\n return { changed: Boolean(r.changed), released: Boolean(r.released) }\n}\n\nexport interface NotePayable {\n id: string\n number: string | null\n total: number\n cancelledAt: string | null\n}\n\n/** The payable an accepted note opened; null when it no longer exists. */\nexport async function getNotePayable(invoiceId: string): Promise<NotePayable | null> {\n const { data, error } = await sb().from('plg_financial_invoices')\n .select('id, number, total, cancelled_at').eq('id', invoiceId).maybeSingle()\n if (error) throw error\n if (!data) return null\n return { id: data.id, number: data.number ?? null, total: Number(data.total ?? 0), cancelledAt: data.cancelled_at ?? null }\n}\n\nexport interface PullCnpjOption { id: string; name: string; cnpj: string }\n\n/** Why a pull by key did not stage a note — each one has a different fix on screen. */\nexport class PullByKeyError extends Error {\n constructor(message: string, readonly code?: string, readonly options?: PullCnpjOption[]) {\n super(message)\n }\n}\n\nexport type PullByKeyResult =\n | ({ status: 'staged' } & StageResult & { parsed: ParsedNfe })\n | { status: 'pending'; message: string }\n\n/**\n * Ask the SEFAZ (via PlugNotas) for one note by its access key, then stage it\n * exactly like a dropped XML. Nothing here manifests the note.\n */\nexport async function pullNoteByKey(\n key: string,\n options: { legalEntityId?: string; unitId?: string | null } = {},\n): Promise<PullByKeyResult> {\n const { data, error } = await sb().functions.invoke('fiscalbr-dfe-pull', {\n body: { key: key.replace(/\\D/g, ''), legalEntityId: options.legalEntityId, tenantId: getActiveTenantId() ?? null },\n })\n if (error) {\n // The function's own message lives in the response body, not in `error.message`.\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* keep generic */ }\n throw new PullByKeyError(body?.error || error.message || 'Falha ao falar com a SEFAZ.', body?.code, body?.options)\n }\n if (data?.pending) return { status: 'pending', message: String(data.message ?? '') }\n if (!data?.xml) throw new PullByKeyError('A SEFAZ não devolveu o XML desta nota.')\n return { status: 'staged', ...(await stageNoteFromXml(String(data.xml), { unitId: options.unitId })) }\n}\n\n/** The DANFE of an inbound note, from the fiscal provider. Rejects with the provider's reason. */\nexport async function getInboxNotePdf(accessKey: string): Promise<Blob> {\n const { data, error } = await sb().functions.invoke('fiscalbr-dfe-pull', {\n body: { action: 'pdf', key: accessKey, tenantId: getActiveTenantId() ?? null },\n })\n if (error) {\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* keep generic */ }\n throw new PullByKeyError(body?.error || error.message || 'Falha ao buscar o DANFE.', body?.code)\n }\n if (!(data instanceof Blob)) throw new PullByKeyError('O serviço fiscal não devolveu um PDF.')\n return data\n}\n\nexport interface ItemDecisionInput {\n id: string\n productId?: string | null\n entryType?: string | null\n chartAccountId?: string | null\n stockUnitId?: string | null\n conversionFactor?: number\n costMode?: string | null\n /** Quem escreveu. `null`/ausente grava NULL, que é «uma pessoa escolheu». */\n suggestedBy?: 'ai' | 'ean' | 'supplier_map' | null\n suggestionConfidence?: number | null\n shortageQuantity?: number | null\n shortageReason?: string | null\n shortageNote?: string | null\n}\n\nexport interface InstalmentInput {\n index: number\n number?: string | null\n dueDate?: string | null\n amount: number\n paymentType?: string | null\n barcode?: string | null\n pixKey?: string | null\n paymentMethodId?: string | null\n}\n\nexport async function saveNoteDecision(input: {\n documentId: string\n items: ItemDecisionInput[]\n defaultChartAccountId?: string | null\n defaultLocationId?: string | null\n instalments?: InstalmentInput[] | null\n}): Promise<{ saved: number; items: number; reconciled: number }> {\n const { data, error } = await sb().rpc('fiscalbr_save_inbox_decision', {\n p_document_id: input.documentId,\n p_items: input.items.map((i) => ({\n id: i.id,\n product_id: i.productId ?? null,\n entry_type: i.entryType ?? null,\n chart_account_id: i.chartAccountId ?? null,\n stock_unit_id: i.stockUnitId ?? null,\n conversion_factor: i.conversionFactor ?? 1,\n cost_mode: i.costMode ?? 'novo',\n suggested_by: i.suggestedBy ?? null,\n suggestion_confidence: i.suggestionConfidence ?? null,\n shortage_quantity: i.shortageQuantity ?? null,\n shortage_reason: i.shortageReason ?? null,\n shortage_note: i.shortageNote ?? null,\n })),\n p_default_chart_account_id: input.defaultChartAccountId ?? null,\n p_default_location_id: input.defaultLocationId ?? null,\n p_duplicates: input.instalments\n ? input.instalments.map((d) => ({\n index: d.index,\n number: d.number ?? null,\n due_date: d.dueDate ?? null,\n value: d.amount,\n payment_type: d.paymentType ?? null,\n barcode: d.barcode ?? null,\n pix_key: d.pixKey ?? null,\n payment_method_id: d.paymentMethodId ?? null,\n }))\n : null,\n })\n if (error) throw error\n const res = (data ?? {}) as Record<string, unknown>\n return {\n saved: Number(res.saved ?? 0),\n items: Number(res.items ?? 0),\n reconciled: Number(res.reconciled ?? 0),\n }\n}\n\n/**\n * Accept: stock entry and payable, one transaction. `alreadyAccepted` coming\n * back true is not an error — it is the second click, and the RPC is idempotent\n * on the NF-e access key.\n */\n/**\n * Bind the note to its supplier by CNPJ. With `create`, a supplier missing from\n * the registry is created from the note's name and CNPJ — the V1 gesture.\n */\nexport async function linkInboxSupplier(documentId: string, create = false): Promise<{ supplierPartyId: string | null; created: boolean }> {\n const { data, error } = await sb().rpc('fiscalbr_link_inbox_supplier', { p_document_id: documentId, p_create: create })\n if (error) throw error\n const res = (data ?? {}) as Record<string, unknown>\n return { supplierPartyId: (res.supplier_party_id as string) ?? null, created: Boolean(res.created) }\n}\n\nexport async function acceptNote(documentId: string, locationId?: string | null): Promise<AcceptResult> {\n // The payable takes its counterparty from the note, so the supplier is bound\n // (or created) first — otherwise the title is born without one.\n await linkInboxSupplier(documentId, true).catch((e: { code?: string }) => {\n // A pool without migration 020 has no such function; accepting still works there.\n if (e?.code !== 'PGRST202' && e?.code !== '42883') throw e\n })\n const { data, error } = await sb().rpc('fiscalbr_accept_inbox_document', {\n p_document_id: documentId,\n p_location_id: locationId ?? null,\n })\n if (error) throw error\n const res = (data ?? {}) as Record<string, unknown>\n return {\n documentId: String(res.document_id ?? documentId),\n alreadyAccepted: Boolean(res.already_accepted),\n invoiceId: (res.invoice_id as string) ?? null,\n invoiceTotal: Number(res.invoice_total ?? 0),\n instalments: Number(res.installments ?? 0),\n operationId: (res.operation_id as string) ?? null,\n stockLines: Number(res.stock_lines ?? 0),\n }\n}\n\nexport async function rejectNote(documentId: string, reason?: string): Promise<void> {\n const { error } = await sb().rpc('fiscalbr_reject_inbox_document', {\n p_document_id: documentId,\n p_reason: reason ?? null,\n })\n if (error) throw error\n}\n\n// ── Os cadastros que a conciliação precisa ─────────────────────────────────\n\nexport async function searchProducts(term: string, limit = 20): Promise<ProductOption[]> {\n let query = sb().from('products')\n .select('id, name, sku, unit, cost, kind')\n .eq('is_active', true)\n .limit(limit)\n if (term.trim()) query = query.or(`name.ilike.%${term.trim()}%,sku.ilike.%${term.trim()}%`)\n const { data, error } = await query.order('name')\n if (error) throw error\n return (data ?? []).map((p: any) => ({\n id: String(p.id), name: p.name ?? '', sku: p.sku ?? null,\n unit: p.unit ?? null, cost: p.cost == null ? null : Number(p.cost), kind: p.kind ?? null,\n }))\n}\n\n/**\n * O XML autorizado desta nota, como ele chegou.\n *\n * Consulta à parte e não campo do detalhe: são 10–50 KB de texto por nota, e a\n * lista de uma conta grande carregaria megabytes que ninguém abriu. Desce quando\n * alguém clica em baixar.\n */\nexport async function getInboxNoteXml(id: string): Promise<string | null> {\n const { data, error } = await sb().from('plg_fiscalbr_inbox_documents')\n .select('xml_content').eq('id', id).maybeSingle()\n if (error) throw error\n return (data as { xml_content?: string } | null)?.xml_content ?? null\n}\n\n/**\n * Qual nota tem este número, quando ele é único na conta.\n *\n * É o caminho das linhas IMPORTADAS do V1: elas trazem «Entrada via DANFE NF-e\n * 10592» escrito no motivo e não trazem operação nenhuma — o importador copiou o\n * movimento e não o vínculo. Das 3.088 assim, as 3.088 acham a nota aqui.\n *\n * Exige UNICIDADE: número de NF-e repete entre fornecedores, e abrir a nota\n * errada é pior que não abrir nenhuma.\n */\nexport async function findInboxNoteByNumber(nfeNumber: string): Promise<string | null> {\n const n = (nfeNumber ?? '').replace(/\\D/g, '')\n if (!n) return null\n const { data, error } = await sb().from('plg_fiscalbr_inbox_documents')\n .select('id').eq('nfe_number', n).limit(2)\n if (error) throw error\n const linhas = (data ?? []) as Array<{ id: string }>\n return linhas.length === 1 ? linhas[0].id : null\n}\n\n/**\n * Qual nota originou esta operação de estoque.\n *\n * O movimento guarda `operation_id`; a nota guarda `inventory_operation_id`. É o\n * único elo entre o razão do estoque e o documento que o produziu, e é o que\n * permite à linha de Movimentações abrir a NF-e de onde ela veio.\n */\nexport async function findInboxNoteByOperation(operationId: string): Promise<string | null> {\n if (!operationId) return null\n const { data, error } = await sb().from('plg_fiscalbr_inbox_documents')\n .select('id').eq('inventory_operation_id', operationId).limit(1).maybeSingle()\n if (error) throw error\n return (data as { id?: string } | null)?.id ?? null\n}\n\n/** O que a edge function de sugestão devolve. */\nexport interface SuggestNoteItemsResult {\n /** Itens que o modelo deixou PRONTOS — com produto. */\n applied: number\n /** Itens em que ele só soube dizer o tipo: continuam «falta decidir». */\n typedOnly: number\n /** Itens que o índice ligou sozinho, sem modelo (EAN ou de-para). */\n bound: number\n boundByEan: number\n /** Nomes que o modelo propôs para o que não existe no catálogo. */\n newProductNames: string[]\n warnings: string[]\n}\n\n/**\n * Pede a sugestão ao servidor.\n *\n * É edge function e não turno de agente porque o broker de chat recusou a\n * pergunta («Message is too long») e, antes disso, porque um turno de chat tem\n * teto de rodadas, morre na navegação e persiste tudo no histórico de alguém.\n * Ver `functions/fiscalbr-suggest-note-items`.\n *\n * A FUNCTION GRAVA. Ela escreve pela mesma RPC do «Salvar conciliação» (que não\n * marca `reconciled`), então quem chama só precisa recarregar a nota — e a\n * sugestão sobrevive a fechar o modal, que era o buraco da versão anterior.\n *\n * O TENANT VAI NO CORPO, nunca em cabeçalho. É a regra que o console já aplica\n * (ver `isEdgeFunctionCall` em `@fayz-ai/admin/data/client`): a borda declara\n * uma lista fixa de `Access-Control-Allow-Headers`, e um cabeçalho fora da lista\n * faz o NAVEGADOR recusar o preflight e bloquear o POST antes de ele sair — não\n * sobra requisição no log, só um `OPTIONS` sozinho, e quem está usando lê «CORS».\n * Foi assim que vinte funções pararam de uma vez.\n *\n * Do outro lado a function põe `x-fayz-tenant` no PRÓPRIO cliente dela, porque é\n * o PostgREST que lê esse cabeçalho (`app.requested_tenant()`), e ali não há\n * preflight nenhum. Sem isso, quem tem mais de uma conta não tem tenant: o recuo\n * de `app._current_tenant_id_raw()` é «sua única conta», e com dez contas ele\n * devolve NULL — a nota existe, a RLS a esconde, e a tela diz 404.\n */\nexport async function suggestNoteItems(\n documentId: string,\n reevaluate = false,\n): Promise<SuggestNoteItemsResult> {\n const { data, error } = await sb().functions.invoke('fiscalbr-suggest-note-items', {\n body: { documentId, reevaluate, tenantId: getActiveTenantId() ?? null },\n })\n // A function responde `{ok:false,error}` com status 4xx/5xx; o cliente do\n // Supabase embrulha isso num FunctionsHttpError cujo `message` é genérico\n // («non-2xx status code»), então a mensagem útil mora no corpo.\n if (error) {\n const corpo = await (error as { context?: Response }).context?.json?.().catch(() => null)\n throw new Error((corpo as { error?: string } | null)?.error ?? error.message)\n }\n const res = (data ?? {}) as Record<string, unknown>\n if (res.ok === false) throw new Error(String(res.error ?? 'A sugestão falhou.'))\n return {\n applied: Number(res.applied ?? 0),\n typedOnly: Number(res.typedOnly ?? 0),\n bound: Number(res.bound ?? 0),\n boundByEan: Number(res.boundByEan ?? 0),\n newProductNames: Array.isArray(res.newProductNames)\n ? res.newProductNames.filter((n): n is string => typeof n === 'string')\n : [],\n warnings: Array.isArray(res.warnings)\n ? res.warnings.filter((w): w is string => typeof w === 'string')\n : [],\n }\n}\n\n/**\n * Os produtos JÁ VINCULADOS, pelo id.\n *\n * `plg_fiscalbr_inbox_items.product_id` guarda o id e mais nada, e o seletor de\n * produto precisa do NOME para mostrar o que está escolhido. Sem isto a linha\n * abria com o campo vazio sobre um produto vinculado — a tela dizia «conferido»\n * apontando para um campo em branco.\n */\nexport async function listProductsByIds(ids: string[]): Promise<ProductOption[]> {\n if (ids.length === 0) return []\n const { data, error } = await sb().from('products')\n .select('id, name, sku, unit, cost, kind')\n .in('id', ids)\n if (error) throw error\n return (data ?? []).map((p: any) => ({\n id: String(p.id), name: p.name ?? '', sku: p.sku ?? null,\n unit: p.unit ?? null, cost: p.cost == null ? null : Number(p.cost), kind: p.kind ?? null,\n }))\n}\n\nexport async function listMeasurementUnits(): Promise<MeasurementUnitOption[]> {\n const { data, error } = await sb().from('plg_inventory_measurement_units')\n .select('id, name, abbreviation, is_base').eq('is_active', true).order('name')\n if (error) throw error\n return (data ?? []).map((u: any) => ({\n id: String(u.id), name: u.name ?? '', abbreviation: u.abbreviation ?? '',\n isBase: Boolean(u.is_base),\n }))\n}\n\n/**\n * Leaf accounts only. `kind` never existed on this table: PostgREST answered 400\n * to the whole query and the caught error left the picker silently empty.\n */\nexport async function listChartAccounts(): Promise<ChartAccountOption[]> {\n const { data, error } = await sb().from('plg_financial_chart_of_accounts')\n .select('id, code, name, account_type, node_type, parent_id, is_active').order('code')\n if (error) throw error\n const rows = (data ?? []).filter((a: any) => a.is_active !== false)\n const parents = new Set(rows.map((a: any) => a.parent_id).filter(Boolean).map(String))\n return rows\n .filter((a: any) => a.node_type !== 'group' && !parents.has(String(a.id)))\n .map((a: any) => ({\n id: String(a.id), code: a.code ?? '', name: a.name ?? '', kind: a.account_type ?? null,\n }))\n}\n\nexport async function listStockLocations(): Promise<StockLocationOption[]> {\n const { data, error } = await sb().from('plg_inventory_stock_locations')\n .select('id, name, unit_id, is_active').order('name')\n if (error) throw error\n return (data ?? [])\n .filter((l: any) => l.is_active !== false)\n .map((l: any) => ({ id: String(l.id), name: l.name ?? '', unitId: l.unit_id ?? null }))\n}\n\n/**\n * What the supplier catalogue already remembers. The reconciliation screen shows\n * it next to a bound product so the operator can tell a de-para hit from a\n * product that appeared out of nowhere.\n */\nexport async function listSupplierMap(supplierCnpj: string): Promise<Array<{\n supplierProductCode: string; productId: string; hitCount: number; lastUsedAt: string | null\n}>> {\n if (!supplierCnpj) return []\n const { data, error } = await sb().from('plg_fiscalbr_supplier_product_map')\n .select('supplier_product_code, product_id, hit_count, last_used_at')\n .eq('supplier_cnpj', supplierCnpj)\n if (error) throw error\n return (data ?? []).map((m: any) => ({\n supplierProductCode: m.supplier_product_code ?? '',\n productId: String(m.product_id),\n hitCount: Number(m.hit_count ?? 0),\n lastUsedAt: m.last_used_at ?? null,\n }))\n}\n\n// ── Anexos: a casa é `public.documents`, como os do título ───────────────────\n\nexport interface NoteAttachment {\n id: string\n fileName: string\n fileSize?: number\n mimeType?: string\n /** Signed, short-lived. Absent when the bytes cannot be opened from here. */\n url?: string\n createdAt: string\n}\n\nconst NOTE_SUBJECT = 'fiscalbr_inbox_document'\nconst INVOICE_SUBJECT = 'financial_invoice'\n\n/**\n * The note's attachments and, once it has a payable, the payable's — one list,\n * because to the operator the boleto belongs to the purchase, not to a table.\n */\nexport async function listNoteAttachments(noteId: string, invoiceId?: string | null): Promise<NoteAttachment[]> {\n const subjects = [`and(subject_type.eq.${NOTE_SUBJECT},subject_id.eq.${noteId})`]\n if (invoiceId) subjects.push(`and(subject_type.eq.${INVOICE_SUBJECT},subject_id.eq.${invoiceId})`)\n const { data, error } = await sb().from('documents')\n .select('id, file_name, file_size, mime_type, storage_bucket, storage_path, created_at')\n .or(subjects.join(','))\n .eq('is_active', true)\n .order('created_at')\n if (error) throw error\n const rows = (data ?? []) as Array<Record<string, any>>\n // The bucket is private: the stored public URL answers 400, so sign on read.\n const signed = new Map<string, string>()\n const byBucket = new Map<string, string[]>()\n for (const r of rows) {\n if (!r.storage_bucket || !r.storage_path) continue\n byBucket.set(r.storage_bucket, [...(byBucket.get(r.storage_bucket) ?? []), r.storage_path])\n }\n for (const [bucket, paths] of byBucket) {\n const { data: urls } = await sb().storage.from(bucket).createSignedUrls(paths, 60 * 30)\n for (const u of urls ?? []) if (u.path && u.signedUrl) signed.set(u.path, u.signedUrl)\n }\n return rows.map((r) => ({\n id: r.id,\n fileName: r.file_name ?? 'Anexo',\n fileSize: r.file_size ?? undefined,\n mimeType: r.mime_type ?? undefined,\n url: signed.get(r.storage_path) ?? undefined,\n createdAt: r.created_at,\n }))\n}\n\n/** Attach to the payable when it exists, otherwise to the note (moved on accept). */\nexport async function addNoteAttachment(noteId: string, invoiceId: string | null | undefined, file: File): Promise<void> {\n const tenantId = getActiveTenantId()\n if (!tenantId) throw new Error('Conta sem empresa ativa')\n const subjectType = invoiceId ? INVOICE_SUBJECT : NOTE_SUBJECT\n const subjectId = invoiceId ?? noteId\n // The bucket policy only accepts paths under the tenant's own folder.\n const path = `${tenantId}/${subjectType}/${subjectId}/${Date.now()}_${file.name.replace(/[^\\w.\\-]+/g, '_')}`\n const { error: upErr } = await sb().storage.from('attachments').upload(path, file, { contentType: file.type || undefined })\n if (upErr) throw upErr\n const { error } = await sb().from('documents').insert({\n tenant_id: tenantId,\n kind: 'attachment',\n status: 'active',\n subject_type: subjectType,\n subject_id: subjectId,\n file_name: file.name,\n file_size: file.size,\n mime_type: file.type || null,\n storage_provider: 'supabase',\n storage_bucket: 'attachments',\n storage_path: path,\n })\n if (error) {\n await sb().storage.from('attachments').remove([path]).catch(() => {})\n throw error\n }\n}\n\nexport async function removeNoteAttachment(id: string): Promise<void> {\n const { error } = await sb().from('documents').update({ is_active: false }).eq('id', id)\n if (error) throw error\n}\n\n/** After accept the payable exists: what was attached to the note becomes its. */\nexport async function moveNoteAttachmentsToInvoice(noteId: string, invoiceId: string): Promise<void> {\n const { error } = await sb().from('documents')\n .update({ subject_type: INVOICE_SUBJECT, subject_id: invoiceId })\n .eq('subject_type', NOTE_SUBJECT)\n .eq('subject_id', noteId)\n if (error) throw error\n}\n\nexport interface PaymentCode {\n kind: 'barcode' | 'pix'\n code: string\n amount: number | null\n dueDate: string | null\n}\n\n/** Read a boleto barcode or a Pix code off an image/PDF — the V1 automation. */\nexport async function extractPaymentCode(file: File): Promise<PaymentCode | null> {\n const base64 = await new Promise<string>((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => { const r = String(reader.result); resolve(r.slice(r.indexOf(',') + 1)) }\n reader.onerror = () => reject(reader.error)\n reader.readAsDataURL(file)\n })\n const { data, error } = await sb().functions.invoke('fiscalbr-payment-extract', {\n body: { name: file.name, mime: file.type, base64 },\n })\n if (error) {\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* keep generic */ }\n throw new Error(body?.error || error.message || 'Falha ao ler o boleto.')\n }\n if (!data?.ok || data.kind === 'none' || !data.code) return null\n const code = String(data.code)\n if (data.kind === 'barcode') {\n const parsed = parseBoleto(code)\n return {\n kind: 'barcode',\n code: code.replace(/\\D/g, ''),\n amount: parsed?.amount ?? (typeof data.amount === 'number' ? data.amount : null),\n dueDate: parsed?.dueDate ?? (data.due_date ?? null),\n }\n }\n return { kind: 'pix', code, amount: typeof data.amount === 'number' ? data.amount : null, dueDate: data.due_date ?? null }\n}\n\n/**\n * Amount and due date straight from a bank boleto's digits, so the instalment\n * does not depend on the model reading the printed value right. Concessionária\n * slips (starting with 8) carry no due-date factor and fall back to the model.\n */\nexport function parseBoleto(raw: string): { amount: number | null; dueDate: string | null } | null {\n const d = raw.replace(/\\D/g, '')\n if (d.startsWith('8')) return null\n let barcode: string\n if (d.length === 44) barcode = d\n else if (d.length === 47) barcode = d.slice(0, 4) + d[32] + d.slice(33, 47) + d.slice(4, 9) + d.slice(10, 20) + d.slice(21, 31)\n else return null\n const factor = Number(barcode.slice(5, 9))\n const cents = Number(barcode.slice(9, 19))\n let dueDate: string | null = null\n if (factor > 0) {\n // FEBRABAN reset the factor at 1000 on 22/02/2025 (it hit 9999 the day before).\n const base = factor >= 1000 && Date.now() >= Date.UTC(2025, 1, 22)\n ? Date.UTC(2025, 1, 22) - 1000 * 86400000\n : Date.UTC(1997, 9, 7)\n dueDate = new Date(base + factor * 86400000).toISOString().slice(0, 10)\n }\n return { amount: cents > 0 ? cents / 100 : null, dueDate }\n}\n\nexport interface InboxIntakeHealth {\n /** CNPJs that should receive notes from SEFAZ and are not. */\n stalled: number\n /** Last time any of them received, for \"não chegam desde…\". */\n since: string | null\n /** When the A1 certificate expired, if that is the reason. */\n certificateExpiredAt: string | null\n /** The provider's own words, when the reason is something else. */\n error: string | null\n /** A unit of the affected CNPJ, whose tax settings take the new certificate. */\n unitId: string | null\n}\n\nconst STALE_AFTER_MS = 24 * 60 * 60 * 1000\n\n/** Parses \"Certificado vencido em: 02/10/2026 10:16:00\" from the provider's error. */\nfunction expiryFromError(error: string | null): string | null {\n const m = error?.match(/vencido em:?\\s*(\\d{2})\\/(\\d{2})\\/(\\d{4})/i)\n return m ? `${m[3]}-${m[2]}-${m[1]}` : null\n}\n\n/** Whether automatic intake from SEFAZ is working for this account, and why not. Null when it is. */\nexport async function getInboxIntakeHealth(): Promise<InboxIntakeHealth | null> {\n const { data, error } = await sb().from('plg_fiscalbr_emitter_settings')\n .select('legal_entity_id, dfe_sync_enabled, dfe_last_sync_at, dfe_last_error, certificate_expires_at')\n .eq('dfe_sync_enabled', true)\n if (error) throw error\n const now = Date.now()\n const stalled = (data ?? []).filter((r: any) => {\n const expired = r.certificate_expires_at && Date.parse(r.certificate_expires_at) < now\n const stale = !r.dfe_last_sync_at || now - Date.parse(r.dfe_last_sync_at) > STALE_AFTER_MS\n return expired || stale || Boolean(r.dfe_last_error)\n })\n if (stalled.length === 0) return null\n const since = stalled.map((r: any) => r.dfe_last_sync_at as string | null).filter(Boolean).sort()[0] ?? null\n const withError = stalled.find((r: any) => r.dfe_last_error)\n const certificateExpiredAt = stalled\n .map((r: any) => (r.certificate_expires_at && Date.parse(r.certificate_expires_at) < now\n ? (r.certificate_expires_at as string)\n : expiryFromError(r.dfe_last_error)))\n .find(Boolean) ?? null\n const target = stalled.find((r: any) => r.certificate_expires_at && Date.parse(r.certificate_expires_at) < now)\n ?? withError ?? stalled[0]\n const { data: unit } = await sb().from('v_unit_company_legal_entities')\n .select('unit_id').eq('company_legal_entity_id', target.legal_entity_id).limit(1).maybeSingle()\n return { stalled: stalled.length, since, certificateExpiredAt, error: withError?.dfe_last_error ?? null, unitId: unit?.unit_id ?? null }\n}\n\nexport interface SyncNewNotesResult {\n added: number\n /** Delivered by SEFAZ only as a summary (not manifested yet) or still being fetched. */\n waiting: number\n failed: number\n}\n\n/**\n * Brings in the notes SEFAZ delivered since the newest one here: the server lists\n * the access keys, and each missing one goes through `pullNoteByKey` — the same\n * path as «Puxar por chave», so nothing here bypasses its permissions.\n */\nexport async function syncNewNotes(max = 25): Promise<SyncNewNotesResult> {\n const { data: newest } = await sb().from('plg_fiscalbr_inbox_documents')\n .select('issue_date').order('issue_date', { ascending: false }).limit(1).maybeSingle()\n // Two days of overlap: SEFAZ indexes some notes a day after they are issued.\n const since = newest?.issue_date\n ? new Date(Date.parse(newest.issue_date) - 2 * 86_400_000).toISOString().slice(0, 10)\n : undefined\n const { data, error } = await sb().functions.invoke('fiscalbr-dfe-pull', {\n body: { action: 'list', since, tenantId: getActiveTenantId() ?? null },\n })\n if (error) {\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* generic below */ }\n throw new PullByKeyError(body?.error || error.message || 'Falha ao falar com a SEFAZ.', body?.code)\n }\n const listed = (data?.notes ?? []) as Array<{ key: string; legalEntityId: string }>\n if (listed.length === 0) return { added: 0, waiting: 0, failed: (data?.failures ?? []).length }\n\n const keys = [...new Set(listed.map((n) => n.key))]\n const { data: known } = await sb().from('plg_fiscalbr_inbox_documents').select('access_key').in('access_key', keys)\n const have = new Set((known ?? []).map((r: any) => r.access_key as string))\n const missing = listed.filter((n, i) => !have.has(n.key) && listed.findIndex((m) => m.key === n.key) === i).slice(0, max)\n\n const result: SyncNewNotesResult = { added: 0, waiting: 0, failed: (data?.failures ?? []).length }\n for (const n of missing) {\n try {\n const r = await pullNoteByKey(n.key, { legalEntityId: n.legalEntityId })\n if (r.status === 'staged') result.added++\n else result.waiting++\n } catch (e) {\n if (e instanceof PullByKeyError && (e.code === 'summary_only' || e.code === 'throttled')) result.waiting++\n else result.failed++\n }\n }\n return result\n}\n\n/** Each product's stock unit (inventory details), for prefilling the note's lines. */\nexport async function listProductStockUnits(productIds: string[]): Promise<Map<string, string>> {\n if (productIds.length === 0) return new Map()\n const { data, error } = await sb().from('plg_inventory_product_details')\n .select('product_id, measurement_unit_id').in('product_id', productIds).not('measurement_unit_id', 'is', null)\n if (error) throw error\n return new Map((data ?? []).map((r: any) => [String(r.product_id), String(r.measurement_unit_id)]))\n}\n","import React, { useEffect, useState } from 'react'\nimport { KeyRound, Loader2 } from 'lucide-react'\nimport {\n Button, Input, Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle,\n Select, SelectContent, SelectItem, SelectTrigger, SelectValue,\n} from '@fayz-ai/ui'\nimport { pullNoteByKey, PullByKeyError, type PullCnpjOption, type PullByKeyResult } from '../data/inbox'\n\nconst formatCnpj = (d: string) => `${d.slice(0, 2)}.${d.slice(2, 5)}.${d.slice(5, 8)}/${d.slice(8, 12)}-${d.slice(12)}`\n\n/** Groups of four, the way the key is printed on the DANFE, so a typo is findable by eye. */\nconst groupKey = (digits: string) => digits.replace(/(\\d{4})(?=\\d)/g, '$1 ')\n\nexport interface PullByKeyDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n unitId?: string | null\n /** Opens with this key already typed, for a note that is already on screen. */\n initialKey?: string\n /** Called after a note was staged, with what the parser found. */\n onPulled: (result: Extract<PullByKeyResult, { status: 'staged' }>) => void\n}\n\nexport function PullByKeyDialog({ open, onOpenChange, unitId, initialKey, onPulled }: PullByKeyDialogProps) {\n const [value, setValue] = useState('')\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n const [cnpjOptions, setCnpjOptions] = useState<PullCnpjOption[] | null>(null)\n const [legalEntityId, setLegalEntityId] = useState('')\n\n useEffect(() => {\n if (open) { if (initialKey) setValue(initialKey); return }\n setValue(''); setError(null); setNotice(null); setCnpjOptions(null); setLegalEntityId('')\n }, [open, initialKey])\n\n const digits = value.replace(/\\D/g, '').slice(0, 44)\n const needsCnpj = !!cnpjOptions && !legalEntityId\n const blocked = digits.length !== 44\n ? `Faltam ${44 - digits.length} dígitos`\n : needsCnpj ? 'Escolha o CNPJ' : null\n\n const pull = async () => {\n setBusy(true); setError(null); setNotice(null)\n try {\n const result = await pullNoteByKey(digits, { legalEntityId: legalEntityId || undefined, unitId })\n if (result.status === 'pending') { setNotice(result.message); return }\n onPulled(result)\n onOpenChange(false)\n } catch (e) {\n if (e instanceof PullByKeyError && e.code === 'choose_cnpj' && e.options?.length) {\n setCnpjOptions(e.options)\n setError(null)\n return\n }\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <Modal open={open} onOpenChange={(o) => { if (!busy) onOpenChange(o) }}>\n <ModalContent size=\"md\">\n <ModalHeader>\n <ModalTitle className=\"flex items-center gap-2\">\n <KeyRound className=\"h-5 w-5\" aria-hidden />\n Puxar NF-e por chave de acesso\n </ModalTitle>\n <ModalDescription>\n Para baixar uma nota que não veio na coleta automática (por exemplo, emitida antes de ligar o\n recebimento de DANFes). Cole a chave de acesso de 44 dígitos.\n </ModalDescription>\n </ModalHeader>\n <ModalBody className=\"space-y-3\">\n <Input\n value={groupKey(digits)}\n onChange={(e) => { setValue(e.target.value); setError(null); setNotice(null) }}\n onKeyDown={(e) => { if (e.key === 'Enter' && !blocked && !busy) void pull() }}\n placeholder=\"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000\"\n inputMode=\"numeric\"\n autoFocus\n className=\"font-mono tabular-nums\"\n aria-label=\"Chave de acesso\"\n data-testid=\"pull-by-key-input\"\n />\n <p className={`text-xs tabular-nums ${digits.length === 44 ? 'text-success-soft-foreground' : 'text-muted-foreground'}`}>\n {digits.length}/44 dígitos\n </p>\n\n {cnpjOptions && (\n <div className=\"space-y-1.5\">\n <p className=\"text-sm font-medium\">De qual CNPJ é esta nota?</p>\n <Select value={legalEntityId} onValueChange={setLegalEntityId}>\n <SelectTrigger><SelectValue placeholder=\"Escolha o CNPJ destinatário\" /></SelectTrigger>\n <SelectContent>\n {cnpjOptions.map((o) => (\n <SelectItem key={o.id} value={o.id}>{o.name} · {formatCnpj(o.cnpj)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n\n {error && <p className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\" role=\"alert\">{error}</p>}\n {notice && <p className=\"rounded-md bg-warning-soft px-3 py-2 text-sm text-warning-soft-foreground\" role=\"status\">{notice}</p>}\n\n <p className=\"text-xs text-muted-foreground\">\n Puxar não manifesta a nota na SEFAZ — a manifestação continua sendo feita no sistema antigo.\n </p>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={busy}>Cancelar</Button>\n <Button onClick={() => { void pull() }} disabled={busy || !!blocked} data-testid=\"pull-by-key-submit\">\n {busy ? <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" /> : <KeyRound className=\"mr-1.5 h-4 w-4\" />}\n {busy ? 'Buscando na SEFAZ…' : blocked ?? 'Puxar nota'}\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n )\n}\n","// ---------------------------------------------------------------------------\n// Manifesto de Notas — a lista das notas de compra, e a área onde o XML entra.\n// ---------------------------------------------------------------------------\n// Duas colunas de estado, e a diferença entre elas é o coração da tela:\n//\n// Conciliação quantos itens já sabem a que produto correspondem — 0/1, 1/1, 0/6\n// Estoque se a entrada aconteceu — Pendente / Estocado\n//\n// No V1 havia 55 notas conciliadas e nunca estocadas. Uma coluna de \"status\" só\n// teria escondido as 55, e a pergunta \"por que o estoque não mudou?\" não teria\n// resposta na tela.\n// ---------------------------------------------------------------------------\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Eye, FileCode2, FileDown, FileText, Inbox, KeyRound, ListChecks, Loader2, RefreshCw, Trash2, UploadCloud } from 'lucide-react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport {\n Button, Card, ChevronPager, DataTable, FilterPanel, FilterPanelField, PageHeaderActions, SearchField,\n RowActions, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Tooltip, TooltipContent,\n TooltipProvider, TooltipTrigger, useFilterDraft,\n} from '@fayz-ai/ui'\nimport { PageActions, adminNavigateTo, useUnitFilter } from '@fayz-ai/admin'\nimport { formatCurrency } from '@fayz-ai/core'\nimport { getInboxIntakeHealth, getInboxNotePdf, getInboxNoteXml, listInboxNotes, stageNoteFromXml, rejectNote, syncNewNotes, type InboxIntakeHealth } from '../data/inbox'\nimport type { InboxNote, InboxStatusFilter } from '../types'\nimport { PullByKeyDialog } from './PullByKeyDialog'\n\nconst money = (value: number) => formatCurrency(value || 0, 'BRL')\n\nconst day = (iso: string | null) => (iso ? iso.slice(0, 10).split('-').reverse().join('/') : '—')\n\nconst cnpj = (digits: string | null) => {\n const d = (digits ?? '').replace(/\\D/g, '')\n if (d.length !== 14) return digits ?? '—'\n return `${d.slice(0, 2)}.${d.slice(2, 5)}.${d.slice(5, 8)}/${d.slice(8, 12)}-${d.slice(12)}`\n}\n\n// Same box as SelectTrigger: the date filters sit beside it and must read as one row.\nconst CAMPO = 'h-9 w-full rounded-input border border-input bg-background px-3 text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2'\n\n/** O recorte, como ele vai para a consulta. */\ninterface Recorte {\n filter: InboxStatusFilter\n unitId: string\n from: string\n to: string\n}\n\nconst STATE_OPTIONS: Array<{ value: InboxStatusFilter; label: string }> = [\n { value: 'all', label: 'Todos' },\n { value: 'pending', label: 'Estoque pendente' },\n { value: 'stocked', label: 'Estocado' },\n { value: 'manifest_error', label: 'Manifestação com erro' },\n { value: 'rejected', label: 'Recusada' },\n]\n\nconst isoDay = (d: Date) => d.toISOString().slice(0, 10)\nconst SYNC_KEY = 'fiscalbr.inbox.lastSefazSync'\n\n/** O resultado de arrastar um lote: o que entrou, o que o de-para já resolveu, o que recusou. */\ninterface DropReport {\n ok: Array<{ file: string; number: string; items: number; matched: number; repeated: boolean }>\n failed: Array<{ file: string; message: string }>\n}\n\nexport interface InboundNotesViewProps {\n /** Abre a conciliação da nota. A rota é do host — esta tela não sabe navegar. */\n onOpenNote: (noteId: string) => void\n}\n\nexport function InboundNotesView({ onOpenNote }: InboundNotesViewProps) {\n const [notes, setNotes] = useState<InboxNote[]>([])\n const [loading, setLoading] = useState(true)\n const [search, setSearch] = useState('')\n const [busy, setBusy] = useState(false)\n const [report, setReport] = useState<DropReport | null>(null)\n const [dragging, setDragging] = useState(false)\n const [pullOpen, setPullOpen] = useState(false)\n const fileInput = useRef<HTMLInputElement>(null)\n\n // A unidade é o ALCANCE de quem olha: a lista abre na unidade em que a pessoa\n // está e só oferece as que ela alcança.\n const unidades = useUnitFilter({ scope: 'list' })\n\n // ── Rascunho e aplicado ─────────────────────────────────────────────────\n // O MESMO motor de recorte da conciliação bancária (FilterPanel): os campos\n // escrevem num rascunho e a lista só muda no «Buscar». Mexer em unidade,\n // estado e nas duas pontas do período seria quatro consultas no caminho, três\n // das quais ninguém pediu — e a terceira pode voltar depois da quarta e\n // pintar a tela com o recorte errado.\n const { draft, applied, patch, setDraft, dirty, apply, reset } = useFilterDraft<Recorte>({\n filter: 'all',\n unitId: unidades.value ?? '',\n // Sem período por padrão: o V1 abre em «Todos os registros», e uma janela\n // de 30 dias esconderia justamente a nota velha que nunca foi estocada.\n from: '',\n to: '',\n })\n\n // Trocar de unidade na casca re-ancora a lista, como no V1 quando a unidade\n // corrente mudava — e aplica na hora, porque uma lista presa ao recorte\n // anterior mostraria dados de outra unidade até alguém clicar em buscar.\n const ancora = unidades.value ?? ''\n const ancoraAnterior = useRef(ancora)\n useEffect(() => {\n if (ancoraAnterior.current === ancora) return\n ancoraAnterior.current = ancora\n setDraft((atual) => ({ ...atual, unitId: ancora }))\n apply()\n }, [ancora, setDraft, apply])\n const reload = useCallback(async () => {\n setLoading(true)\n try {\n setNotes(await listInboxNotes({\n filter: applied.filter,\n unitId: applied.unitId || undefined,\n from: applied.from || undefined,\n to: applied.to || undefined,\n // The list pages on screen; the default 200 would silently drop the rest.\n limit: 5000,\n }))\n } finally {\n setLoading(false)\n }\n }, [applied])\n\n useEffect(() => { void reload() }, [reload])\n\n const [intake, setIntake] = useState<InboxIntakeHealth | null>(null)\n const [syncing, setSyncing] = useState(false)\n const [syncNote, setSyncNote] = useState<string | null>(null)\n const refreshIntake = useCallback(() => { getInboxIntakeHealth().then(setIntake).catch(() => setIntake(null)) }, [])\n\n const syncNow = useCallback(async (quiet: boolean) => {\n setSyncing(true)\n if (!quiet) setSyncNote(null)\n try {\n const r = await syncNewNotes()\n try { localStorage.setItem(SYNC_KEY, String(Date.now())) } catch { /* private mode */ }\n if (r.added) void reload()\n const parts = [\n r.added ? `${r.added} ${r.added === 1 ? 'nota nova' : 'notas novas'}` : null,\n r.waiting ? `${r.waiting} ainda sem o XML completo na SEFAZ` : null,\n r.failed ? `${r.failed} com erro` : null,\n ].filter(Boolean)\n if (!quiet || parts.length) setSyncNote(parts.length ? `SEFAZ: ${parts.join(' · ')}.` : 'SEFAZ: nenhuma nota nova.')\n } catch (e) {\n if (!quiet) setSyncNote(e instanceof Error ? e.message : String(e))\n } finally {\n setSyncing(false)\n refreshIntake()\n }\n }, [reload, refreshIntake])\n\n // Opening the list is when someone wants to see what arrived; at most every 30 minutes.\n useEffect(() => {\n refreshIntake()\n let last = 0\n try { last = Number(localStorage.getItem(SYNC_KEY) ?? 0) } catch { /* private mode */ }\n if (Date.now() - last > 30 * 60_000) void syncNow(true)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // One file at a time, sequentially. The staging RPC is idempotent on the access\n // key, so a repeated file is not an error — but firing 20 of them in parallel\n // would race on the same de-para rows for the same supplier.\n const ingest = useCallback(async (files: File[]) => {\n const xmls = files.filter((f) => /\\.xml$/i.test(f.name))\n if (xmls.length === 0) {\n setReport({ ok: [], failed: [{ file: '—', message: 'Nenhum arquivo .xml no que foi solto.' }] })\n return\n }\n setBusy(true)\n const next: DropReport = { ok: [], failed: [] }\n for (const file of xmls) {\n try {\n const res = await stageNoteFromXml(await file.text())\n next.ok.push({\n file: file.name,\n number: res.parsed.nfeNumber,\n items: res.itemCount,\n matched: res.matchedCount,\n repeated: res.alreadyAccepted,\n })\n } catch (error) {\n next.failed.push({ file: file.name, message: error instanceof Error ? error.message : String(error) })\n }\n }\n setBusy(false)\n setReport(next)\n await reload()\n }, [reload])\n\n const [rowError, setRowError] = useState<string | null>(null)\n\n const downloadXml = useCallback(async (note: InboxNote) => {\n setRowError(null)\n try {\n const xml = await getInboxNoteXml(note.id)\n if (!xml) { setRowError(`O XML da nota ${note.number} não está guardado.`); return }\n const url = URL.createObjectURL(new Blob([xml], { type: 'application/xml' }))\n const a = document.createElement('a')\n a.href = url\n a.download = `${note.accessKey || note.number || 'nfe'}.xml`\n a.click()\n URL.revokeObjectURL(url)\n } catch (e) {\n setRowError(e instanceof Error ? e.message : String(e))\n }\n }, [])\n\n const openPdf = useCallback(async (note: InboxNote) => {\n setRowError(null)\n // Opened before the await: a tab opened after it is a popup the browser blocks.\n const tab = window.open('', '_blank')\n try {\n const pdf = await getInboxNotePdf(note.accessKey ?? '')\n if (tab) tab.location.href = URL.createObjectURL(pdf)\n } catch (e) {\n tab?.close()\n setRowError(e instanceof Error ? e.message : String(e))\n }\n }, [])\n\n const remove = useCallback(async (note: InboxNote) => {\n // Recusar, não apagar: a nota é documento fiscal e continua legível.\n await rejectNote(note.id, 'Recusada na lista de entrada')\n await reload()\n }, [reload])\n\n const activeCount = (applied.filter === 'all' ? 0 : 1)\n + (applied.unitId ? 1 : 0)\n + (applied.from || applied.to ? 1 : 0)\n\n const limpar = useCallback(() => {\n reset({ filter: 'all', unitId: ancora, from: '', to: '' })\n }, [reset, ancora])\n\n /** As duas pontas nunca ficam invertidas: mexer numa arrasta a outra. */\n const setFrom = (from: string) => patch({ from, to: draft.to && from > draft.to ? from : draft.to })\n const setTo = (to: string) => patch({ to, from: draft.from && to < draft.from ? to : draft.from })\n\n // Local search: the list already arrives whole, so a round trip per keystroke buys nothing.\n const query = search.trim().toLowerCase()\n const shown = useMemo(() => {\n if (!query) return notes\n // CNPJ, access key and date match on digits, so punctuation never matters.\n const digits = query.replace(/\\D/g, '')\n return notes.filter((note) => {\n if (`${note.number} ${note.series} ${note.supplierName}`.toLowerCase().includes(query)) return true\n if (digits.length < 2) return false\n if ((note.supplierCnpj ?? '').replace(/\\D/g, '').includes(digits)) return true\n if ((note.accessKey ?? '').includes(digits)) return true\n return day(note.issueDate).replace(/\\D/g, '').includes(digits)\n })\n }, [notes, query])\n\n const [page, setPage] = useState(1)\n useEffect(() => { setPage(1) }, [notes, query])\n const pageRows = useMemo(() => shown.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE), [shown, page])\n\n const columns = useMemo<ColumnDef<InboxNote, unknown>[]>(() => [\n {\n id: 'issueDate',\n header: 'Emissão',\n accessorFn: (note) => note.issueDate ?? '',\n cell: ({ row }) => <span className=\"tabular-nums text-muted-foreground\">{day(row.original.issueDate)}</span>,\n },\n {\n id: 'number',\n header: 'Nº',\n accessorFn: (note) => Number(note.number) || note.number,\n cell: ({ row }) => <span className=\"tabular-nums font-medium\">{row.original.number}</span>,\n },\n {\n id: 'supplier',\n header: 'Fornecedor',\n accessorFn: (note) => note.supplierName,\n meta: { truncate: true, mobile: 'title' },\n cell: ({ row }) => (\n <div>\n <p className=\"font-medium leading-tight\">{row.original.supplierName || '—'}</p>\n <p className=\"text-xs text-muted-foreground tabular-nums\">{cnpj(row.original.supplierCnpj)}</p>\n </div>\n ),\n },\n {\n id: 'reconciled',\n header: () => <span className=\"block text-center\">Conciliação</span>,\n accessorFn: (note) => (note.itemCount > 0 ? note.reconciledCount / note.itemCount : -1),\n cell: ({ row }) => (\n <div className=\"text-center\">\n <ReconcileBadge done={row.original.reconciledCount} total={row.original.itemCount} />\n </div>\n ),\n },\n {\n id: 'total',\n header: () => <span className=\"block text-right\">Valor</span>,\n accessorFn: (note) => note.total,\n cell: ({ row }) => {\n const note = row.original\n return (\n <div className=\"text-right tabular-nums\">\n {money(note.total)}\n {/* O título nasce com a soma das PARCELAS. Quando ela difere do\n total da nota, a tela mostra as duas — é a divergência que a\n conciliação passaria o mês procurando. */}\n {note.instalmentCount > 0 && Math.abs(note.instalmentTotal - note.total) > 0.01 && (\n <p className=\"text-[11px] text-warning-soft-foreground\">\n parcelas: {money(note.instalmentTotal)}\n </p>\n )}\n </div>\n )\n },\n },\n {\n id: 'stock',\n header: () => <span className=\"block text-center\">Estoque</span>,\n accessorFn: (note) => (note.stockedAt ? 2 : note.status === 'rejected' ? 0 : 1),\n cell: ({ row }) => (\n <div className=\"text-center\">\n <StockBadge stockedAt={row.original.stockedAt} status={row.original.status} />\n </div>\n ),\n },\n {\n id: 'actions',\n header: () => <span className=\"block text-right\">Ações</span>,\n enableSorting: false,\n cell: ({ row }) => {\n const note = row.original\n const done = !!note.stockedAt || note.status === 'rejected'\n return (\n // The row itself opens the note; the buttons must not fire it a second time.\n <div className=\"flex justify-end gap-1\" onClick={(e) => e.stopPropagation()}>\n <ActionIcon label={done ? 'Ver nota' : 'Conciliar'}>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n aria-label={done ? `Ver a nota ${note.number}` : `Conciliar a nota ${note.number}`}\n className={done ? '' : 'bg-foreground text-background hover:bg-foreground/85 hover:text-background'}\n onClick={() => onOpenNote(note.id)}\n >\n {done ? <Eye className=\"h-4 w-4\" /> : <ListChecks className=\"h-4 w-4\" />}\n </Button>\n </ActionIcon>\n <RowActions\n inlineLimit={0}\n actions={[\n { id: 'xml', label: 'Baixar XML', icon: FileCode2, onSelect: () => downloadXml(note) },\n { id: 'pdf', label: 'Abrir PDF', icon: FileText, onSelect: () => openPdf(note), hidden: !note.accessKey },\n {\n id: 'reject', label: 'Recusar nota', icon: Trash2, intent: 'danger',\n onSelect: () => remove(note), hidden: done || !!note.invoiceId,\n },\n ]}\n />\n </div>\n )\n },\n },\n ], [onOpenNote, remove, downloadXml, openPdf])\n\n // Empty-by-search and empty-by-no-notes have different fixes.\n const emptyMessage = query || activeCount > 0 ? (\n <div>\n <Inbox className=\"mx-auto h-8 w-8 text-muted-foreground\" aria-hidden />\n <p className=\"mt-2 text-sm font-medium\">Nenhuma nota encontrada</p>\n <p className=\"text-xs text-muted-foreground\">Tente outro número, fornecedor ou CNPJ.</p>\n </div>\n ) : (\n <div>\n <Inbox className=\"mx-auto h-8 w-8 text-muted-foreground\" aria-hidden />\n <p className=\"mt-2 text-sm font-medium\">Nenhuma nota de entrada</p>\n <p className=\"text-xs text-muted-foreground\">\n As notas chegam da SEFAZ sozinhas, ou você arrasta o XML aqui.\n </p>\n </div>\n )\n\n return (\n <div className=\"space-y-4\">\n <PageHeaderActions>\n <PageActions\n actions={[\n {\n // Picking an XML off a filesystem is a desk job.\n id: 'import-xml', label: 'Importar XML', icon: busy ? Loader2 : UploadCloud,\n intent: 'primary', creates: true, desktopOnly: true, disabled: busy,\n onSelect: () => fileInput.current?.click(),\n },\n {\n id: 'sync-sefaz', label: syncing ? 'Buscando na SEFAZ…' : 'Buscar notas novas', icon: syncing ? Loader2 : RefreshCw,\n disabled: syncing, testId: 'sync-sefaz', onSelect: () => { void syncNow(false) },\n },\n {\n id: 'pull-by-key', label: 'Puxar por chave', icon: KeyRound, creates: true,\n testId: 'pull-by-key', onSelect: () => setPullOpen(true),\n },\n ]}\n />\n </PageHeaderActions>\n\n {syncNote && <p className=\"text-xs text-muted-foreground\" data-testid=\"sync-note\">{syncNote}</p>}\n\n {intake && (\n <Card className=\"border-warning bg-warning-soft p-4\" data-testid=\"intake-stalled\">\n <p className=\"text-sm font-medium text-warning-soft-foreground\">\n {intake.certificateExpiredAt\n ? `As notas da SEFAZ não estão chegando: o certificado digital venceu em ${day(intake.certificateExpiredAt)}.`\n : `As notas da SEFAZ não estão chegando${intake.since ? ` desde ${day(intake.since)}` : ''}.`}\n </p>\n <p className=\"mt-1 text-xs text-warning-soft-foreground\">\n {intake.certificateExpiredAt\n ? 'Renove o certificado A1 do CNPJ e envie o arquivo novo. As notas que ficaram para trás chegam sozinhas depois disso.'\n : intake.error ?? 'A busca automática parou. Enquanto isso, dá para importar o XML ou puxar a nota pela chave.'}\n {intake.stalled > 1 ? ` (${intake.stalled} CNPJs afetados)` : ''}\n </p>\n {intake.unitId && (intake.certificateExpiredAt || intake.error) && (\n <Button size=\"sm\" variant=\"outline\" className=\"mt-3\" data-testid=\"intake-update-certificate\"\n onClick={() => adminNavigateTo(`/settings/locations/${intake.unitId}/fields:tax`)}>\n Atualizar certificado\n </Button>\n )}\n </Card>\n )}\n\n {/* A área de arrastar é a porta de entrada, e o texto é o do V1: a entrada\n nasce do XML, não da digitação. */}\n <Card\n className={`hidden border-dashed p-6 text-center transition-colors md:block ${dragging ? 'border-primary bg-primary/5' : ''}`}\n onDragOver={(e: React.DragEvent) => { e.preventDefault(); setDragging(true) }}\n onDragLeave={() => setDragging(false)}\n onDrop={(e: React.DragEvent) => {\n e.preventDefault()\n setDragging(false)\n void ingest(Array.from(e.dataTransfer.files))\n }}\n >\n <UploadCloud className=\"mx-auto h-8 w-8 text-muted-foreground\" aria-hidden />\n <p className=\"mt-2 text-sm font-medium\">Arraste arquivos XML aqui ou clique para selecionar</p>\n <p className=\"text-xs text-muted-foreground\">\n Suporta múltiplos arquivos XML de NF-e. O XML do fornecedor dá entrada no estoque e cria a conta a pagar.\n </p>\n <input\n ref={fileInput}\n type=\"file\"\n accept=\".xml,text/xml,application/xml\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n void ingest(Array.from(e.target.files ?? []))\n e.target.value = ''\n }}\n />\n </Card>\n\n <PullByKeyDialog\n open={pullOpen}\n onOpenChange={setPullOpen}\n unitId={applied.unitId || null}\n onPulled={(r) => {\n setReport({\n ok: [{ file: 'chave', number: r.parsed.nfeNumber, items: r.itemCount, matched: r.matchedCount, repeated: r.alreadyAccepted }],\n failed: [],\n })\n void reload()\n }}\n />\n\n {report && (\n <Card className=\"p-4 space-y-2\">\n {report.ok.map((r) => (\n <p key={r.file} className=\"text-sm\">\n <span className=\"font-medium\">NF-e {r.number}</span>{' '}\n <span className=\"text-muted-foreground\">\n {r.repeated\n ? '— já tinha sido aceita, nada mudou'\n // O número que diz se o de-para está trabalhando. Sem ele, o\n // operador não sabe se importar XML economizou algo.\n : `— ${r.items} ${r.items === 1 ? 'item' : 'itens'}, ${r.matched} já ${r.matched === 1 ? 'vinculado' : 'vinculados'}`}\n </span>\n </p>\n ))}\n {report.failed.map((r) => (\n <p key={r.file} className=\"text-sm text-destructive\">\n <span className=\"font-medium\">{r.file}</span> — {r.message}\n </p>\n ))}\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setReport(null)}>Fechar</Button>\n </Card>\n )}\n\n {/* ── O painel de filtros ──────────────────────────────────────────── */}\n {/* O MESMO FilterPanel da conciliação bancária: unidade, estado e as duas\n pontas do período definem O QUE se busca, e «Buscar» é que aplica.\n A BUSCA não entra aqui — ela é a barra da lista: quem digita está\n procurando UMA nota entre as que já estão na tela, não redefinindo a\n consulta. */}\n <FilterPanel\n title=\"Filtros\"\n dirty={dirty}\n onApply={apply}\n applyLabel=\"Buscar\"\n pendingTitle=\"Filtros não aplicados\"\n pendingHint=\"A lista ainda mostra o recorte anterior.\"\n onClear={activeCount > 0 ? limpar : undefined}\n clearLabel=\"Limpar\"\n busy={loading}\n >\n {unidades.visible && (\n <FilterPanelField label={unidades.label}>\n <Select\n value={draft.unitId || '__all__'}\n onValueChange={(v) => patch({ unitId: v === '__all__' ? '' : v })}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__all__\">{unidades.allLabel}</SelectItem>\n {unidades.options.map((u) => <SelectItem key={u.id} value={u.id}>{u.name}</SelectItem>)}\n </SelectContent>\n </Select>\n </FilterPanelField>\n )}\n\n <FilterPanelField label=\"Estado\">\n <Select value={draft.filter} onValueChange={(v) => patch({ filter: v as InboxStatusFilter })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {STATE_OPTIONS.map((o) => <SelectItem key={o.value} value={o.value}>{o.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </FilterPanelField>\n\n <FilterPanelField label=\"Emissão de\">\n <input type=\"date\" value={draft.from} max={isoDay(new Date())} onChange={(e) => setFrom(e.target.value)} className={CAMPO} />\n </FilterPanelField>\n <FilterPanelField label=\"Emissão até\">\n <input type=\"date\" value={draft.to} max={isoDay(new Date())} onChange={(e) => setTo(e.target.value)} className={CAMPO} />\n </FilterPanelField>\n </FilterPanel>\n\n {rowError && (\n <p className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\" role=\"alert\">{rowError}</p>\n )}\n\n {/* Search and table are one surface — they act on the same rows. `clip`, as\n in CrudListView: `hidden` makes a scroll box that swallows the sticky header. */}\n <Card style={{ overflow: 'clip' }}>\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2\">\n <div className=\"min-w-[10rem] flex-1\">\n <SearchField\n value={search}\n onChange={setSearch}\n placeholder=\"Buscar por número, fornecedor, CNPJ…\"\n data-testid=\"inbound-notes-search\"\n />\n </div>\n </div>\n <TooltipProvider delayDuration={200}>\n <DataTable\n variant=\"bare\"\n columns={columns}\n data={loading ? [] : pageRows}\n loading={loading}\n getRowId={(note) => note.id}\n onRowClick={(note) => onOpenNote(note.id)}\n emptyMessage={emptyMessage}\n mobileLayout=\"cards\"\n />\n </TooltipProvider>\n {!loading && shown.length > 0 && (\n <ChevronPager page={page} pageSize={PAGE_SIZE} total={shown.length} onPageChange={setPage} noun=\"notas\" />\n )}\n </Card>\n </div>\n )\n}\n\nconst PAGE_SIZE = 50\n\nfunction ActionIcon({ label, children }: { label: string; children: React.ReactElement }) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>{children}</TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n )\n}\n\nfunction ReconcileBadge({ done, total }: { done: number; total: number }) {\n const full = total > 0 && done === total\n return (\n <span\n className={`inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium tabular-nums ${\n full ? 'bg-success-soft text-success-soft-foreground' : 'bg-muted text-muted-foreground'\n }`}\n >\n {done}/{total}\n </span>\n )\n}\n\nfunction StockBadge({ stockedAt, status }: { stockedAt: string | null; status: string }) {\n if (status === 'rejected') {\n return <span className=\"inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground line-through\">Recusada</span>\n }\n return stockedAt ? (\n <span className=\"inline-flex items-center rounded-full bg-success-soft px-2 py-0.5 text-[11px] font-medium text-success-soft-foreground\">\n <FileDown className=\"mr-1 h-3 w-3\" aria-hidden />\n Estocado\n </span>\n ) : (\n <span className=\"inline-flex items-center rounded-full bg-warning-soft px-2 py-0.5 text-[11px] font-medium text-warning-soft-foreground\">\n Pendente\n </span>\n )\n}\n","import { formatCurrency } from '@fayz-ai/core'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\nimport { FileText, Image as ImageIcon, Loader2, Paperclip, ScanLine, Trash2, UploadCloud } from 'lucide-react'\nimport { Button, Card, Hint } from '@fayz-ai/ui'\nimport {\n addNoteAttachment, extractPaymentCode, listNoteAttachments, removeNoteAttachment,\n type InstalmentInput, type NoteAttachment, type PaymentCode,\n} from '../data/inbox'\n\nconst MAX_BYTES = 15 * 1024 * 1024\nconst money = (v: number) => formatCurrency(v || 0)\nconst day = (iso: string | null) => (iso ? iso.slice(0, 10).split('-').reverse().join('/') : '—')\nconst size = (b?: number) => (!b ? '' : b < 1024 * 1024 ? `${Math.max(1, Math.round(b / 1024))} KB` : `${(b / 1024 / 1024).toFixed(1)} MB`)\n\n/**\n * Put a read payment code on the instalment it belongs to: the empty one with\n * the same amount, else the first empty one, else a new instalment. Never\n * overwrites a code already there.\n */\nexport function applyPaymentCode(list: InstalmentInput[], code: PaymentCode): { next: InstalmentInput[]; index: number } {\n const field = code.kind === 'pix' ? 'pixKey' : 'barcode'\n const free = list.map((p, i) => ({ p, i })).filter(({ p }) => !p[field])\n const sameAmount = code.amount != null ? free.find(({ p }) => Math.abs((Number(p.amount) || 0) - code.amount!) < 0.01) : undefined\n const target = sameAmount ?? free[0]\n const patch = (p: InstalmentInput): InstalmentInput => ({\n ...p,\n [field]: code.code,\n paymentType: code.kind === 'pix' ? 'pix' : 'boleto',\n dueDate: p.dueDate || code.dueDate,\n amount: Number(p.amount) > 0 ? p.amount : (code.amount ?? 0),\n })\n if (target) return { next: list.map((p, i) => (i === target.i ? patch(p) : p)), index: target.i }\n const fresh = patch({ index: list.length, amount: 0 })\n return { next: [...list, fresh], index: list.length }\n}\n\nexport function NoteAttachmentsCard({ noteId, invoiceId, readOnly, instalments, onInstalments }: {\n noteId: string\n invoiceId?: string | null\n readOnly?: boolean\n instalments: InstalmentInput[]\n onInstalments: (next: InstalmentInput[]) => void\n}) {\n const input = useRef<HTMLInputElement>(null)\n const [items, setItems] = useState<NoteAttachment[] | null>(null)\n const [busy, setBusy] = useState<string | null>(null)\n const [over, setOver] = useState(false)\n const [confirming, setConfirming] = useState<string | null>(null)\n const [messages, setMessages] = useState<Array<{ tone: 'ok' | 'warn' | 'error'; text: string }>>([])\n // The latest instalments, so several files read in sequence each see the previous fill.\n const current = useRef(instalments)\n current.current = instalments\n\n const load = useCallback(async () => {\n try { setItems(await listNoteAttachments(noteId, invoiceId)) } catch { setItems([]) }\n }, [noteId, invoiceId])\n useEffect(() => { void load() }, [load])\n\n const upload = async (files: File[]) => {\n const out: typeof messages = []\n for (const file of files) {\n if (!(file.type.startsWith('image/') || file.type === 'application/pdf') || file.size > MAX_BYTES) {\n out.push({ tone: 'error', text: `${file.name}: envie imagem ou PDF de até 15 MB.` })\n continue\n }\n setBusy(`Anexando ${file.name}…`)\n try {\n await addNoteAttachment(noteId, invoiceId, file)\n } catch (e) {\n out.push({ tone: 'error', text: `${file.name}: ${e instanceof Error ? e.message : String(e)}` })\n continue\n }\n if (readOnly) continue\n setBusy(`Lendo ${file.name}…`)\n try {\n const code = await extractPaymentCode(file)\n if (!code) {\n out.push({ tone: 'warn', text: `${file.name}: anexado. Não achei código de boleto nem Pix nele.` })\n } else {\n const { next, index } = applyPaymentCode(current.current, code)\n current.current = next\n onInstalments(next)\n const p = next[index]\n out.push({\n tone: 'ok',\n text: `${code.kind === 'pix' ? 'Pix' : 'Boleto'} lido → parcela ${index + 1}: ${money(Number(p.amount) || 0)}, vence ${day(p.dueDate ?? null)}. Confira e salve.`,\n })\n }\n } catch (e) {\n out.push({ tone: 'warn', text: `${file.name}: anexado, mas não consegui ler o código (${e instanceof Error ? e.message : String(e)}).` })\n }\n }\n setBusy(null)\n setMessages(out)\n await load()\n }\n\n const remove = async (a: NoteAttachment) => {\n setBusy(`Removendo ${a.fileName}…`)\n try {\n await removeNoteAttachment(a.id)\n setMessages([{ tone: 'ok', text: `${a.fileName} removido.` }])\n } catch (e) {\n setMessages([{ tone: 'error', text: `${a.fileName}: ${e instanceof Error ? e.message : String(e)}` }])\n } finally {\n setBusy(null)\n await load()\n }\n }\n\n return (\n <Card className=\"p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <h3 className=\"text-sm font-semibold\">Anexos da conta</h3>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n Boleto, comprovante, foto da nota. Boleto e Pix anexados são lidos e preenchem a parcela.\n </p>\n </div>\n {items && items.length > 0 && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{items.length} {items.length === 1 ? 'anexo' : 'anexos'}</span>\n )}\n </div>\n\n {items === null ? (\n <div className=\"mt-3 h-10 animate-pulse rounded-md bg-muted\" />\n ) : items.length > 0 && (\n <ul className=\"mt-3 divide-y rounded-md border\">\n {items.map((a) => (\n <li key={a.id} className=\"flex items-center gap-2 px-3 py-2 text-sm\">\n {a.mimeType?.startsWith('image/')\n ? <ImageIcon className=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden />\n : <FileText className=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden />}\n {a.url\n ? <a href={a.url} target=\"_blank\" rel=\"noreferrer\" className=\"min-w-0 flex-1 truncate hover:underline\">{a.fileName}</a>\n : <span className=\"min-w-0 flex-1 truncate text-muted-foreground\">{a.fileName}</span>}\n {confirming === a.id ? (\n // Inline, not a dialog: this card already lives inside a modal.\n <span className=\"flex shrink-0 items-center gap-1\">\n <span className=\"text-xs text-muted-foreground\">Remover?</span>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => { setConfirming(null); void remove(a) }}>Remover</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setConfirming(null)}>Cancelar</Button>\n </span>\n ) : (\n <>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{size(a.fileSize)}</span>\n <Hint label=\"Remover anexo\">\n <Button variant=\"ghost\" size=\"icon\" aria-label={`Remover ${a.fileName}`} disabled={!!busy} onClick={() => setConfirming(a.id)}>\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </Hint>\n </>\n )}\n </li>\n ))}\n </ul>\n )}\n\n <div\n className={`mt-3 flex flex-col items-center gap-1 rounded-md border border-dashed px-4 py-5 text-center transition-colors ${over ? 'border-primary bg-primary/5' : 'border-input'}`}\n onDragOver={(e) => { e.preventDefault(); setOver(true) }}\n onDragLeave={() => setOver(false)}\n onDrop={(e) => { e.preventDefault(); setOver(false); void upload(Array.from(e.dataTransfer.files)) }}\n >\n {busy ? (\n <p className=\"flex items-center gap-2 text-sm text-muted-foreground\"><Loader2 className=\"h-4 w-4 animate-spin\" />{busy}</p>\n ) : (\n <>\n <UploadCloud className=\"h-6 w-6 text-muted-foreground\" aria-hidden />\n <p className=\"text-sm\">Arraste o boleto ou o comprovante aqui</p>\n <div className=\"mt-1 flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => input.current?.click()} data-testid=\"note-attach\">\n <Paperclip className=\"mr-1.5 h-4 w-4\" />\n Anexar arquivo\n </Button>\n </div>\n {!readOnly && (\n <p className=\"mt-1 flex items-center gap-1 text-[11px] text-muted-foreground\">\n <ScanLine className=\"h-3 w-3\" aria-hidden /> o código de barras e o Pix são lidos sozinhos\n </p>\n )}\n </>\n )}\n <input\n ref={input}\n type=\"file\"\n multiple\n accept=\"image/*,application/pdf\"\n className=\"hidden\"\n onChange={(e) => { void upload(Array.from(e.target.files ?? [])); e.target.value = '' }}\n />\n </div>\n\n {messages.length > 0 && (\n <ul className=\"mt-3 space-y-1\">\n {messages.map((m, i) => (\n <li\n key={i}\n className={`text-xs ${m.tone === 'ok' ? 'text-success-soft-foreground' : m.tone === 'warn' ? 'text-warning-soft-foreground' : 'text-destructive'}`}\n >\n {m.text}\n </li>\n ))}\n </ul>\n )}\n </Card>\n )\n}\n","/** The preview contract deliberately excludes production emission. */\nexport type PlugNotasEnvironment = 'sandbox' | 'homologation'\nexport type PlugNotasDocumentStatus = 'draft' | 'processing' | 'issued' | 'cancelled' | 'error'\n\nexport interface PlugNotasSetupState {\n emitterCnpj: string\n environment: PlugNotasEnvironment\n certificateReady: boolean\n cscReady: boolean\n providerEmitterId?: string\n certificateExpiresAt?: string\n certificateFingerprint?: string\n}\n\nexport interface PlugNotasDocumentResult {\n status: PlugNotasDocumentStatus\n providerDocumentId?: string\n integrationId?: string\n number?: string\n series?: string\n accessKey?: string\n message?: string\n}\n\nexport interface PlugNotasFiscalGateway {\n issue(input: { notaId: string; idempotencyKey: string }): Promise<PlugNotasDocumentResult>\n refresh(input: { notaId: string }): Promise<PlugNotasDocumentResult>\n cancel(input: { notaId: string; reason: string }): Promise<PlugNotasDocumentResult>\n artifact(input: {\n notaId: string\n kind: 'xml' | 'pdf' | 'cancellation_xml'\n }): Promise<{ url: string }>\n}\n\nexport interface PlugNotasConnectorClient {\n testEmitter?(input: {\n emitterCnpj: string\n environment: PlugNotasEnvironment\n }): Promise<{ ok: boolean; message?: string }>\n disconnectEmitter?(): Promise<void>\n}\n\nexport interface PlugNotasFinancialProviderOptions {\n base: import('@fayz-ai/financial/data/provider').FinancialDataProvider\n gateway: PlugNotasFiscalGateway\n}\n\n// ---------------------------------------------------------------------------\n// Entrada de Notas — a nota que o fornecedor emitiu contra o CNPJ da casa.\n// ---------------------------------------------------------------------------\n// Dois estados, e eles NÃO respondem à mesma pergunta. `reconciledCount/itemCount`\n// diz quantos itens já sabem a que produto correspondem; `stockedAt` diz se a\n// entrada aconteceu. No V1 havia 55 notas conciliadas e nunca estocadas — uma\n// coluna de \"status\" só teria escondido as 55.\n\n/** Os cinco tipos de registro do V1, medidos em 3.402 linhas de produção. */\nexport type InboxEntryType = 'insumo' | 'revenda' | 'patrimonio' | 'uso_consumo' | 'despesa' | 'servico'\n\n/** Despesa e serviço nunca viram estoque: viram só título a pagar. */\nexport const STOCK_BEARING_ENTRY_TYPES: readonly InboxEntryType[] = ['insumo', 'revenda', 'patrimonio', 'uso_consumo']\n\nexport const isStockBearing = (type: string | null | undefined): boolean =>\n STOCK_BEARING_ENTRY_TYPES.includes(type as InboxEntryType)\n\nexport type InboxCostMode = 'novo' | 'media'\n\nexport type InboxStatusFilter = 'all' | 'pending' | 'stocked' | 'rejected' | 'manifest_error'\n\nexport interface InboxNote {\n id: string\n accessKey: string\n number: string\n series: string\n issueDate: string | null\n receivedAt: string | null\n status: string\n manifestationStatus: string | null\n manifestedAt: string | null\n manifestationAttempts: number\n natureOperation: string | null\n supplierName: string\n supplierCnpj: string | null\n supplierPartyId: string | null\n /** O total declarado na NOTA. */\n total: number\n itemCount: number\n reconciledCount: number\n instalmentCount: number\n /** A soma das PARCELAS — é com este total que o título nasce (financial/084). */\n instalmentTotal: number\n invoiceId: string | null\n operationId: string | null\n stockedAt: string | null\n documentId: string | null\n /** O XML está guardado nesta nota. Falso nas importadas antes da migration 016. */\n hasXml: boolean\n unitId: string | null\n}\n\nexport interface InboxItem {\n id: string\n itemNumber: number\n supplierProductCode: string\n eanBarcode: string | null\n description: string\n ncm: string | null\n cest: string | null\n cfop: string | null\n unit: string | null\n quantity: number\n unitPrice: number\n total: number\n /**\n * `uTrib`/`qTrib` do XML — a unidade e a quantidade TRIBUTÁVEIS.\n *\n * É a evidência mais forte que existe para o fator de conversão, e ela já\n * estava no banco: 558 dos 3.691 itens têm unidade tributável diferente da\n * comercial. «4 CX» com `qTrib` 88,224 KG diz que a caixa tem 22,056 kg — e o\n * caso Artorius (carne a R$ 397/kg) foi exatamente esta conta não ter sido\n * feita. Ver `taxableFactor`.\n */\n unitTaxable: string | null\n quantityTaxable: number | null\n discount: number | null\n icmsCst: string | null\n icmsCsosn: string | null\n icmsValue: number | null\n productId: string | null\n entryType: string | null\n chartAccountId: string | null\n stockUnitId: string | null\n conversionFactor: number\n /** Quantidade × fator, menos a falta. É o número que a tela mostra ANTES de aceitar. */\n stockQuantity: number\n costMode: string\n unitCostNew: number | null\n reconciled: boolean\n /**\n * Quem escreveu a decisão desta linha. `null` é «uma pessoa escolheu», e é o\n * caso que importa: igualdade (`ean`, `supplier_map`) e semelhança (`ai`) não\n * se conferem do mesmo jeito que uma escolha humana. Ver a migration 013.\n */\n suggestedBy: 'ai' | 'ean' | 'supplier_map' | null\n /** 0..1, só quando `suggestedBy === 'ai'`. Abaixo de 0,6 a tela pede conferência. */\n suggestionConfidence: number | null\n stockMovementId: string | null\n shortageQuantity: number | null\n shortageReason: string | null\n shortageNote: string | null\n}\n\nexport interface InboxInstalment {\n id: string\n index: number\n number: string | null\n dueDate: string | null\n amount: number\n paymentType: string | null\n barcode: string | null\n pixKey: string | null\n paymentMethodId: string | null\n}\n\nexport interface InboxNoteDetail extends InboxNote {\n defaultChartAccountId: string | null\n defaultLocationId: string | null\n items: InboxItem[]\n instalments: InboxInstalment[]\n /** `pag > detPag` do XML: o que o fornecedor DECLAROU, não o que se decidiu. */\n declaredPayments: Array<{ index: number; code: string | null; label: string | null; value: number }>\n}\n\nexport interface StageResult {\n documentId: string\n accessKey: string\n alreadyAccepted: boolean\n supplierPartyId: string | null\n itemCount: number\n /** Quantos itens o de-para do fornecedor já vinculou sozinho. */\n matchedCount: number\n}\n\nexport interface AcceptResult {\n documentId: string\n /** `true` é o segundo clique, não um erro: a RPC é idempotente na chave de acesso. */\n alreadyAccepted: boolean\n invoiceId: string | null\n invoiceTotal: number\n instalments: number\n operationId: string | null\n stockLines: number\n}\n\nexport interface ProductOption {\n id: string\n name: string\n sku: string | null\n unit: string | null\n cost: number | null\n kind: string | null\n}\n\n/**\n * Um candidato a produto para uma linha da nota, com o motivo de ter aparecido.\n *\n * Devolvido pela RPC `fiscalbr_match_product_candidates` (migration 012) e lido\n * DENTRO da edge function de sugestão — o cliente não chama essa RPC, porque quem\n * decide o que fazer com `reason` é quem monta a pergunta ao modelo.\n *\n * O motivo é a parte que importa: `ean` e `supplier_map` são igualdade — liga e\n * pronto. `text` é semelhança, e semelhança se confere.\n */\nexport interface ProductMatch {\n /** O id do item da nota que originou a busca. */\n ref: string\n productId: string\n name: string\n sku: string | null\n unit: string | null\n cost: number | null\n score: number\n reason: 'supplier_map' | 'ean' | 'text'\n}\n\nexport interface MeasurementUnitOption {\n id: string\n name: string\n abbreviation: string\n isBase: boolean\n}\n\nexport interface ChartAccountOption {\n id: string\n code: string\n name: string\n kind: string | null\n}\n\nexport interface StockLocationOption {\n id: string\n name: string\n unitId: string | null\n}\n","// ---------------------------------------------------------------------------\n// Conciliação — onde a nota do fornecedor vira estoque e dinheiro.\n// ---------------------------------------------------------------------------\n// Os quatro blocos do V1, na mesma ordem: situação fiscal · itens · pagamento ·\n// anexos. O que mudou de forma, e por quê:\n//\n// O V1 põe isto num DIÁLOGO, e é o que esta tela faz de novo (`chrome='modal'`):\n// quem fecha a nota tem de CAIR DE VOLTA onde estava na lista — mesmo recorte,\n// mesma busca, mesma rolagem — e uma subpágina desmontava a lista inteira para\n// remontá-la depois com o filtro no estado inicial.\n//\n// O que fez o diálogo do V1 ser ruim era rolagem dentro de rolagem com o\n// «Aceitar» escondido atrás do rodapé. Aqui o modal rola num lugar só (o corpo)\n// e o rodapé é `sticky` DENTRO dele, então o gesto mais importante da tela nunca\n// sai de vista. `chrome='page'` continua existindo para quem abre a nota por\n// deep link em tela cheia.\n//\n// A regra que a tela existe para cumprir: a **Qtd estoque (calc.)** muda na tela\n// ANTES de aceitar. O FLOW.md do V1 diz que fator de conversão errado é\n// silencioso e que esse número é a única defesa.\n// ---------------------------------------------------------------------------\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { AlertTriangle, Check, ChevronDown, ChevronRight, Download, FileCode2, FileDown, FileText, Gift, Loader2, Plus, RefreshCw, Trash2, UserPlus, X } from 'lucide-react'\nimport { formatCurrency } from '@fayz-ai/core'\nimport { PersonLink } from '@fayz-ai/admin'\nimport { NoteAttachmentsCard } from './NoteAttachmentsCard'\nimport { PullByKeyDialog } from './PullByKeyDialog'\nimport {\n EmBreve, AiActionButton, Button, Card, InlineLink, Input, SearchSelect, Skeleton, SubpageHeader, DatePicker, Hint,\n ModalBody, ModalFooter, ModalHeader, ModalTitle, Dropdown, DropdownContent, DropdownItem, DropdownTrigger,\n} from '@fayz-ai/ui'\nimport {\n getInboxNote, saveNoteDecision, acceptNote, rejectNote,\n searchProducts, listProductsByIds, listMeasurementUnits, listChartAccounts, listStockLocations,\n suggestNoteItems, getInboxNoteXml, stageNoteFromXml, fillInboxLines, healInboxNote, listProductStockUnits, getNotePayable, getInboxNotePdf, linkInboxSupplier, moveNoteAttachmentsToInvoice,\n type ItemDecisionInput, type InstalmentInput, type NotePayable,\n} from '../data/inbox'\nimport type { SearchSelectOption } from '@fayz-ai/ui'\nimport type {\n InboxNoteDetail, InboxItem, InboxEntryType, ProductMatch,\n MeasurementUnitOption, ChartAccountOption, StockLocationOption, AcceptResult,\n} from '../types'\nimport { isStockBearing } from '../types'\nimport { packagingCount } from '../lib/note-suggestion'\n\nconst money = (v: number) => formatCurrency(v || 0, 'BRL')\nconst qty = (v: number) => new Intl.NumberFormat('pt-BR', { maximumFractionDigits: 4 }).format(v || 0)\nconst day = (iso: string | null | undefined) => (iso ? iso.slice(0, 10).split('-').reverse().join('/') : '—')\n\n// O vocabulário é o do V1, e a ordem é a de uso: insumo é 2.303 das 3.402 linhas.\nconst ENTRY_TYPES: Array<{ value: InboxEntryType; label: string; hint?: string }> = [\n { value: 'insumo', label: 'Insumo' },\n { value: 'revenda', label: 'Produto Revenda' },\n { value: 'patrimonio', label: 'Patrimônio' },\n { value: 'uso_consumo', label: 'Uso e Consumo', hint: 'com estoque' },\n { value: 'despesa', label: 'Despesa', hint: 'não vira estoque' },\n { value: 'servico', label: 'Serviço', hint: 'não vira estoque' },\n]\n\n/** O estado editável de uma linha. Espelha `ItemDecisionInput`, mais o que a tela calcula. */\ninterface Draft {\n productId: string | null\n productLabel: string\n entryType: InboxEntryType | null\n chartAccountId: string | null\n stockUnitId: string | null\n conversionFactor: string\n costMode: 'novo' | 'media'\n shortageQuantity: string\n /** Quem escreveu esta linha. `null` = uma pessoa. Ver a migration 013. */\n suggestedBy: 'ai' | 'ean' | 'supplier_map' | null\n suggestionConfidence: number | null\n}\n\n/**\n * `SearchSelect` não tem prop `options`: ele é sempre dirigido por busca — o que é\n * a escolha certa para produto (o catálogo tem 171) e continua servindo para as\n * listas curtas (plano de contas, unidade, local), filtrando em memória.\n */\nconst localSearch = (options: SearchSelectOption[]) => (query: string): SearchSelectOption[] => {\n const q = query.trim().toLowerCase()\n return (q ? options.filter((o) => o.label.toLowerCase().includes(q)) : options).slice(0, 40)\n}\n\nconst labelOf = (options: SearchSelectOption[], id: string | null | undefined) =>\n options.find((o) => o.id === id)?.label\n\n// The note's commercial unit, as the unit code a tenant registers ('KG' → 'kg').\n// Packaging (CX, FD…) is not a stock unit; the factor check handles those.\nconst NOTE_UNIT_CODES: Record<string, string> = {\n KG: 'kg', KGS: 'kg', KILO: 'kg', QUILO: 'kg', G: 'g', GR: 'g', GRS: 'g',\n L: 'l', LT: 'l', LTS: 'l', LITRO: 'l', ML: 'ml',\n UN: 'un', UND: 'un', UNID: 'un', UNI: 'un', UNIDADE: 'un',\n}\n\n/** The stock unit a line should get when nobody chose one: the product's, else the note's. */\nfunction suggestedStockUnit(\n item: InboxItem, units: MeasurementUnitOption[], productUnits: Map<string, string>, productId: string | null,\n): string | null {\n const fromProduct = productId ? productUnits.get(productId) : undefined\n if (fromProduct && units.some((u) => u.id === fromProduct)) return fromProduct\n if (packagingCount(item.unit) !== null) return null\n const code = NOTE_UNIT_CODES[String(item.unit ?? '').trim().toUpperCase().replace(/\\d+$/, '')]\n return code ? units.find((u) => u.abbreviation.toLowerCase() === code)?.id ?? null : null\n}\n\nconst draftOf = (item: InboxItem): Draft => ({\n productId: item.productId,\n productLabel: '',\n entryType: (item.entryType as InboxEntryType) ?? null,\n chartAccountId: item.chartAccountId,\n stockUnitId: item.stockUnitId,\n conversionFactor: String(item.conversionFactor ?? 1),\n costMode: (item.costMode === 'media' ? 'media' : 'novo'),\n shortageQuantity: item.shortageQuantity == null ? '' : String(item.shortageQuantity),\n // Vem do SERVIDOR: é o que faz o selo sobreviver a recarregar a página.\n suggestedBy: item.suggestedBy,\n suggestionConfidence: item.suggestionConfidence,\n})\n\nexport interface NoteReconcileViewProps {\n noteId: string\n onBack: () => void\n /** Onde o título a pagar abre depois de aceitar. O host sabe a rota; esta tela não. */\n onOpenInvoice?: (invoiceId: string) => void\n /**\n * `modal` quando o anfitrião já desenhou a moldura (título e fechar): o\n * cabeçalho de subpágina sai, porque dois títulos na mesma caixa é o defeito\n * que o `page-header-no-duplicate-title` descreve.\n */\n chrome?: 'page' | 'modal'\n}\n\nexport function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = 'page' }: NoteReconcileViewProps) {\n const emModal = chrome === 'modal'\n /** O rodapé encosta nas bordas da caixa que o contém, e ela tem padding diferente. */\n const sangria = emModal ? '-mx-6 px-6' : '-mx-4 px-4'\n const cabecalho = (titulo: string) =>\n emModal ? null : <SubpageHeader title={titulo} onBack={onBack} parentLabel=\"Manifesto de Notas\" />\n const [note, setNote] = useState<InboxNoteDetail | null>(null)\n const [loading, setLoading] = useState(true)\n const [drafts, setDrafts] = useState<Record<string, Draft>>({})\n const [instalments, setInstalments] = useState<InstalmentInput[]>([])\n const [defaultAccount, setDefaultAccount] = useState<string | null>(null)\n const [location, setLocation] = useState<string | null>(null)\n const [units, setUnits] = useState<MeasurementUnitOption[]>([])\n const [productUnits, setProductUnits] = useState<Map<string, string>>(() => new Map())\n const [accounts, setAccounts] = useState<ChartAccountOption[]>([])\n const [locations, setLocations] = useState<StockLocationOption[]>([])\n const [saving, setSaving] = useState(false)\n const [accepting, setAccepting] = useState(false)\n // One item open at a time: 11 expanded rows bury the one still missing a decision.\n const [openIds, setOpenIds] = useState<string[]>([])\n const [checked, setChecked] = useState<Record<string, boolean>>({})\n // A registry that fails to load leaves an empty picker, which reads as \"no data\".\n const [registryWarning, setRegistryWarning] = useState<string | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [accepted, setAccepted] = useState<AcceptResult | null>(null)\n const [baixandoXml, setBaixandoXml] = useState(false)\n const [suggesting, setSuggesting] = useState(false)\n const [suggestionNote, setSuggestionNote] = useState<string | null>(null)\n const [pullOpen, setPullOpen] = useState(false)\n // undefined: not looked up (or no link); null: the note points at a payable that does not exist.\n const [payable, setPayable] = useState<NotePayable | null | undefined>(undefined)\n const [payableLost, setPayableLost] = useState(false)\n\n const load = useCallback(async () => {\n setLoading(true)\n try {\n // A NOTA primeiro, e sozinha. Juntar tudo num `Promise.all` fazia a tela\n // MENTIR: bastava um dos três cadastros falhar para a promessa rejeitar, a\n // nota nunca ser atribuída, e a tela dizer «Nota não encontrada» sobre uma\n // nota que está lá. Foi o que aconteceu no primeiro E2E — a nota existia,\n // a consulta dela respondia 200, e a tela dizia que não existia.\n let detail = await getInboxNote(noteId)\n // Notes that crossed from the V1, or whose supplier was registered later,\n // arrive unbound; matching by CNPJ here costs one call and fixes the screen.\n if (detail && !detail.supplierPartyId && detail.supplierCnpj) {\n const linked = await linkInboxSupplier(noteId).catch(() => null)\n if (linked?.supplierPartyId) detail = { ...detail, supplierPartyId: linked.supplierPartyId }\n }\n // \"Accepted\" is read from the links; a payable deleted elsewhere must not lock the note.\n if (detail && (detail.invoiceId || detail.stockedAt)) {\n const healed = await healInboxNote(noteId).catch(() => null)\n if (healed?.released) setPayableLost(true)\n if (healed?.changed) detail = (await getInboxNote(noteId)) ?? detail\n }\n setPayable(detail?.invoiceId ? await getNotePayable(detail.invoiceId).catch(() => undefined) : undefined)\n // A note copied from the V1 can carry its XML but no lines: read them from\n // the stored file, by the same staging path as a dropped XML.\n // An accepted one only gets its lines; its payable and stock stay as they are.\n if (detail && detail.items.length === 0 && detail.hasXml && detail.status !== 'rejected') {\n const xml = await getInboxNoteXml(noteId).catch(() => null)\n if (xml) {\n const accepted = Boolean(detail.stockedAt || detail.invoiceId)\n const filled = accepted\n ? await fillInboxLines(noteId, xml).catch(() => 0)\n : (await stageNoteFromXml(xml, { unitId: detail.unitId }).catch(() => null))?.itemCount ?? 0\n if (filled) detail = (await getInboxNote(noteId)) ?? detail\n }\n }\n setNote(detail)\n\n // Os cadastros são para PREENCHER os seletores. Um que não carrega deixa um\n // seletor vazio — que é ruim, e é visível — em vez de esconder a nota.\n const failed: string[] = []\n const [u, a, l] = await Promise.all([\n listMeasurementUnits().catch(() => { failed.push('unidades'); return [] as MeasurementUnitOption[] }),\n listChartAccounts().catch(() => { failed.push('plano de contas'); return [] as ChartAccountOption[] }),\n listStockLocations().catch(() => { failed.push('locais de estoque'); return [] as StockLocationOption[] }),\n ])\n setUnits(u); setAccounts(a); setLocations(l)\n setRegistryWarning(failed.length ? `Não consegui carregar ${failed.join(', ')}. Estes seletores vão aparecer vazios.` : null)\n if (detail) {\n // O NOME DO PRODUTO JÁ VINCULADO. Sem isto o seletor abria VAZIO em toda\n // linha que já tinha produto — o id estava lá, o rótulo não — e a tela\n // dizia «conferido» sobre um campo que parecia em branco. Vale para toda\n // nota reaberta, não só para as que a IA tocou.\n const vinculados = [...new Set(detail.items.map((i) => i.productId).filter((id): id is string => !!id))]\n const nomes = vinculados.length\n ? new Map((await listProductsByIds(vinculados).catch(() => [])).map((p) => [p.id, p.name]))\n : new Map<string, string>()\n const unidadesDoProduto = await listProductStockUnits(vinculados).catch(() => new Map<string, string>())\n setProductUnits(unidadesDoProduto)\n setDrafts(Object.fromEntries(detail.items.map((i) => [\n i.id,\n {\n ...draftOf(i),\n productLabel: (i.productId && nomes.get(i.productId)) || '',\n // Stocked lines keep what was recorded; open ones get a unit instead of a blank.\n stockUnitId: i.stockUnitId ?? (i.stockMovementId ? null : suggestedStockUnit(i, u, unidadesDoProduto, i.productId)),\n },\n ])))\n // Server-side `reconciled` seeds the checks, so saving does not undo them.\n // SUBSTITUI, não mescla. Mesclando, um «conferido» marcado antes nunca\n // voltava atrás: a linha perdia o produto, o servidor devolvia\n // `reconciled: false`, e a tela continuava dizendo que estava conferida\n // porque a chave antiga sobrevivia ao recarregamento. Depois de um load o\n // servidor é a verdade.\n setChecked(Object.fromEntries(detail.items.filter((i) => i.reconciled).map((i) => [i.id, true])))\n const pending = detail.items.find((i) => !i.reconciled)\n setOpenIds(pending ? [pending.id] : [])\n setInstalments(detail.instalments.map((d) => ({\n index: d.index, number: d.number, dueDate: d.dueDate, amount: d.amount,\n paymentType: d.paymentType, barcode: d.barcode, pixKey: d.pixKey,\n })))\n setDefaultAccount(detail.defaultChartAccountId)\n setLocation(detail.defaultLocationId ?? l[0]?.id ?? null)\n }\n } catch (e) {\n // Falhar buscando a nota é diferente de não achar a nota, e a tela tem de\n // dizer qual dos dois foi.\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setLoading(false)\n }\n }, [noteId])\n\n useEffect(() => { void load() }, [load])\n\n /**\n * EDITAR À MÃO APAGA A AUTORIA DA MÁQUINA.\n *\n * O selo diz «este valor é o que a máquina escreveu». No instante em que\n * alguém corrige o fator, o selo passaria a mentir — e mentiria para o lado\n * pior, pedindo conferência de um número que acabou de ser conferido. Então a\n * regra é uma só, aqui, e não espalhada por quinze `onChange`: toda mudança\n * que não declara autoria zera a autoria.\n */\n const patch = (id: string, change: Partial<Draft>) =>\n setDrafts((prev) => ({\n ...prev,\n [id]: {\n ...prev[id],\n ...('suggestedBy' in change ? {} : { suggestedBy: null, suggestionConfidence: null }),\n ...change,\n },\n }))\n\n const accountOptions = useMemo<SearchSelectOption[]>(\n () => accounts.map((a) => ({ id: a.id, label: `${a.code} · ${a.name}` })),\n [accounts],\n )\n const unitOptions = useMemo<SearchSelectOption[]>(\n () => units.map((u) => ({ id: u.id, label: u.abbreviation, subtitle: u.name })),\n [units],\n )\n const locationOptions = useMemo<SearchSelectOption[]>(\n () => locations.map((l) => ({ id: l.id, label: l.name })),\n [locations],\n )\n\n /**\n * O rascunho virado em decisão. É FUNÇÃO e não só `useMemo` porque o\n * auto-salvar da sugestão precisa gravar o rascunho que ELE acabou de montar —\n * o memo ainda é o de antes do `setDrafts`, e salvar com ele gravaria a tela\n * anterior em cima da sugestão.\n */\n const buildDecisions = useCallback((rascunhos: Record<string, Draft>): ItemDecisionInput[] => {\n if (!note) return []\n return note.items.map((item) => {\n const d = rascunhos[item.id] ?? draftOf(item)\n return {\n id: item.id,\n productId: isStockBearing(d.entryType) ? d.productId : null,\n entryType: d.entryType,\n // A herança que a legenda do V1 promete: «itens sem plano herdarão este».\n chartAccountId: d.chartAccountId ?? defaultAccount,\n stockUnitId: d.stockUnitId,\n conversionFactor: Number(d.conversionFactor.replace(',', '.')) || 1,\n costMode: d.costMode,\n suggestedBy: d.suggestedBy,\n suggestionConfidence: d.suggestionConfidence,\n shortageQuantity: d.shortageQuantity === '' ? null : Number(d.shortageQuantity.replace(',', '.')),\n }\n })\n }, [note, defaultAccount])\n\n const decisions = useMemo(() => buildDecisions(drafts), [buildDecisions, drafts])\n\n const stockLines = decisions.filter((d) => isStockBearing(d.entryType))\n const missingProduct = stockLines.filter((d) => !d.productId).length\n // A stock line without a unit enters as a bare number the screens read as \"unidade\".\n const missingUnit = stockLines.filter((d) => {\n const item = note?.items.find((i) => i.id === d.id)\n return !d.stockUnitId && !item?.stockMovementId\n }).length\n const missingType = decisions.filter((d) => !d.entryType).length\n\n /**\n * FATOR DE EMBALAGEM QUE NINGUÉM CONFIRMOU.\n *\n * A unidade comercial declara conteúdo (MI = 1.000, DZ = 12, CENTO = 100) e uma\n * das duas coisas está em aberto: o fator continua 1 (a conta não foi feita), ou\n * a unidade de estoque não foi escolhida (a conta foi feita no escuro, porque o\n * produto não tem `unit` no cadastro).\n *\n * Nos dois casos a máquina chegou até onde podia e a palavra final é de gente:\n * «1 MI a R$ 616,00» são 1.000 sacos a R$ 0,616 ou 1 saco a R$ 616,00, e a\n * diferença entre as duas leituras é o estoque e o custo médio da casa.\n *\n * O cabeçalho deste arquivo diz que a «Qtd estoque (calc.)» é a única defesa\n * contra fator errado. Uma defesa que não trava o «Aceitar» não é defesa.\n */\n const suspectFactor = (item: InboxItem, d: Draft) =>\n packagingCount(item.unit) !== null\n && isStockBearing(d.entryType)\n && ((Number(d.conversionFactor.replace(',', '.')) || 1) === 1 || !d.stockUnitId)\n\n const unverifiedFactor = note\n ? note.items.filter((i) => suspectFactor(i, drafts[i.id] ?? draftOf(i))).length\n : 0\n const instalmentSum = instalments.reduce((acc, d) => acc + (Number(d.amount) || 0), 0)\n // A payable alone is not \"done\": the V1 opened it before reconciling, and many\n // of those notes never reached stock. Done = stocked, or nothing left to stock.\n const hasPayable = Boolean(note?.invoiceId)\n const pendingStock = (note?.items ?? []).some((i) =>\n !i.stockMovementId && (!i.entryType || isStockBearing(i.entryType)))\n const readOnly = Boolean(note?.stockedAt || (hasPayable && !pendingStock))\n const paymentLocked = readOnly || hasPayable\n\n // Same rule the save RPC uses for `reconciled`: checking adds no second state.\n const isReady = (item: InboxItem, d: Draft) =>\n Boolean(d.entryType)\n && (!isStockBearing(d.entryType) || Boolean(d.productId))\n && !suspectFactor(item, d)\n const doneCount = note ? note.items.filter((i) => checked[i.id]).length : 0\n\n const toggleItem = (id: string) =>\n setOpenIds((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]))\n\n /** Checking closes this item and opens the next pending one. */\n const confirmItem = (id: string) => {\n setChecked((prev) => ({ ...prev, [id]: true }))\n setOpenIds((prev) => {\n const rest = prev.filter((x) => x !== id)\n const next = note?.items.find((i) => i.id !== id && !checked[i.id])\n return next && !rest.includes(next.id) ? [...rest, next.id] : rest\n })\n }\n\n // ── Sugerir com IA ────────────────────────────────────────────────────────\n // A SUGESTÃO ACONTECE NO SERVIDOR, como no V1. A edge function pergunta ao\n // índice (de-para do fornecedor e EAN resolvem sem modelo), manda só o que\n // sobrou com os candidatos daquele item, aplica as evidências de fator que são\n // aritmética (uTrib/qTrib, milheiro) e GRAVA pela mesma RPC do «Salvar\n // conciliação». Então aqui não há merge de rascunho: pede, e recarrega.\n //\n // A primeira versão disto foi um turno de agente e o broker recusou no\n // primeiro clique real — `Message is too long`. Ver `lib/note-suggestion.ts`.\n\n /**\n * Grava o rascunho recebido, sem recarregar.\n *\n * Existe separada do `save()` porque o auto-salvar da sugestão precisa gravar um\n * rascunho que ele mesmo tem em mão, e não o que o `useMemo` ainda enxerga.\n */\n const persistir = useCallback(async (rascunhos: Record<string, Draft>) => {\n if (!note) return\n await saveNoteDecision({\n documentId: note.id,\n items: buildDecisions(rascunhos),\n defaultChartAccountId: defaultAccount,\n defaultLocationId: location,\n instalments,\n })\n }, [note, buildDecisions, defaultAccount, location, instalments])\n\n /** Só o que falta decidir. Decide o rótulo do botão e se ele existe. */\n const pendingItems = useMemo(\n () => (note?.items ?? []).filter((item) => {\n const d = drafts[item.id] ?? draftOf(item)\n return !d.entryType || (isStockBearing(d.entryType) && !d.productId)\n }),\n [note, drafts],\n )\n\n /**\n * Itens que a MÁQUINA decidiu. É o alvo do «Rodar IA novamente».\n *\n * Reavaliar nunca toca no que uma pessoa escolheu: `suggestedBy` nulo é escolha\n * humana, e sobrescrevê-la seria desfazer trabalho — o V1 tinha esse botão e\n * respeitava a mesma fronteira.\n */\n const machineItems = useMemo(\n () => (note?.items ?? []).filter((item) => (drafts[item.id] ?? draftOf(item)).suggestedBy !== null),\n [note, drafts],\n )\n\n const sugerir = useCallback(async (reavaliar = false) => {\n if (!note) return\n setSuggesting(true); setSuggestionNote(null); setError(null)\n try {\n // GRAVA O RASCUNHO ANTES DE PEDIR. A function escreve no banco e a tela\n // recarrega em seguida; rascunho não salvo seria apagado pelo que voltar.\n await persistir(drafts)\n\n const res = await suggestNoteItems(note.id, reavaliar)\n // A nota volta inteira do servidor: é ela que carrega `suggested_by`, e é\n // o que faz o selo sobreviver a recarregar a página.\n await load()\n\n if (res.applied === 0 && res.bound === 0 && res.typedOnly === 0) {\n setSuggestionNote(res.warnings[0] ?? 'Não achei nada para preencher nestes itens.')\n return\n }\n const semIA = res.bound\n ? `Sem IA: ${res.boundByEan ? `${res.boundByEan} pelo código de barras` : ''}`\n + (res.boundByEan && res.bound - res.boundByEan ? ' e ' : '')\n + (res.bound - res.boundByEan ? `${res.bound - res.boundByEan} pelo catálogo deste fornecedor` : '')\n + '.'\n : ''\n // A FRASE SEGUE A TELA. «Preenchido» é só o que ficou pronto; a linha que\n // recebeu o tipo e nenhum produto continua em «falta decidir», e dizer que\n // ela foi preenchida é a tela mentindo sobre o próprio trabalho.\n setSuggestionNote([\n semIA,\n res.applied\n ? `${res.applied} ${res.applied === 1 ? 'item preenchido' : 'itens preenchidos'} pela IA.`\n : '',\n res.typedOnly\n ? `${res.typedOnly} ${res.typedOnly === 1 ? 'item ficou' : 'itens ficaram'} sem produto no catálogo`\n + (res.newProductNames.length ? ` (${res.newProductNames.slice(0, 3).join(', ')})` : '')\n + ' — escolha o produto ou cadastre antes de aceitar.'\n : '',\n res.applied || res.bound ? 'Salvo.' : '',\n ...res.warnings,\n ].filter(Boolean).join(' '))\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setSuggesting(false)\n }\n }, [note, drafts, persistir, load])\n\n // O botão do V1, com o roxo que a conciliação já usa para «isto a máquina\n // O botão do V1, com o roxo que a conciliação já usa para «isto a máquina\n // propôs». Ele não existe quando não há nada a decidir: pedir sugestão para uma\n // nota pronta só poderia DESFAZER escolha de gente.\n //\n // E não depende mais de chave no cliente: a credencial do modelo mora na edge\n // function, então todo app que tem o plugin tem a sugestão — control,\n // full-control e ticket incluídos, que nunca tiveram VITE_FAYZ_AGENT_KEY.\n //\n // Depois da primeira rodada não há mais item pendente, e o botão SUMIA — a\n // sugestão ruim ficava sem segunda chance, e um botão que evapora ao ser usado\n // é esquisito. O V1 trocava o rótulo; aqui também, e «rodar de novo» só\n // reavalia o que a máquina decidiu.\n const reavaliar = pendingItems.length === 0 && machineItems.length > 0\n const botaoIA = readOnly || (pendingItems.length === 0 && !reavaliar)\n ? null\n : (\n <AiActionButton\n size=\"sm\"\n className=\"shrink-0\"\n busy={suggesting}\n busyLabel=\"Pensando…\"\n onClick={() => { void sugerir(reavaliar) }}\n >\n {reavaliar ? 'Rodar IA novamente' : 'Sugerir com IA'}\n </AiActionButton>\n )\n\n /**\n * A moldura do modal. O título e o «Sugerir com IA» ficam no CABEÇALHO, fora da\n * área que rola: a sugestão preenche onze itens de uma vez, e um botão que sai\n * de vista ao rolar até o item 7 é um botão que ninguém acha na segunda nota.\n */\n const moldura = (node: React.ReactNode, titulo: string, rodape?: { start: React.ReactNode; end: React.ReactNode } | null) => (emModal ? (\n <>\n <ModalHeader className=\"shrink-0 flex-row items-center justify-between gap-3 space-y-0 border-b px-6 py-3 pr-14 text-left sm:flex-row\">\n <ModalTitle className=\"min-w-0 truncate\">{titulo}</ModalTitle>\n <div className=\"flex shrink-0 items-center gap-1\">\n {botaoIA}\n {ferramentas}\n </div>\n </ModalHeader>\n <ModalBody className=\"px-6 py-4\">{node}</ModalBody>\n {rodape && <ModalFooter variant=\"bar\" start={rodape.start}>{rodape.end}</ModalFooter>}\n </>\n ) : (\n // Em tela cheia não há moldura onde pendurar o rodapé: ele volta para dentro\n // do conteúdo, grudado na base da janela enquanto a página rola.\n <>\n {node}\n {rodape && (\n <div className={`sticky bottom-0 ${sangria} flex items-center justify-between gap-3 border-t bg-card/95 py-3 pr-16 backdrop-blur`}>\n <div className=\"flex min-w-0 items-center gap-3\">{rodape.start}</div>\n <div className=\"flex shrink-0 items-center gap-2\">{rodape.end}</div>\n </div>\n )}\n </>\n ))\n\n /**\n * Baixa o XML desta nota.\n *\n * O texto desce agora e não junto do detalhe: são 10–50 KB por nota, e carregá-lo\n * em toda abertura da tela seria pagar por um arquivo que quase ninguém abre.\n */\n const [cadastrando, setCadastrando] = useState(false)\n const cadastrarFornecedor = useCallback(async () => {\n if (!note) return\n setCadastrando(true); setError(null)\n try {\n const { supplierPartyId } = await linkInboxSupplier(note.id, true)\n if (supplierPartyId) setNote({ ...note, supplierPartyId })\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setCadastrando(false)\n }\n }, [note])\n\n const [abrindoPdf, setAbrindoPdf] = useState(false)\n const abrirPdf = useCallback(async () => {\n if (!note?.accessKey) return\n // Opened before the await: a tab opened after it is a popup the browser blocks.\n const tab = window.open('', '_blank')\n setAbrindoPdf(true); setError(null)\n try {\n const pdf = await getInboxNotePdf(note.accessKey)\n if (tab) tab.location.href = URL.createObjectURL(pdf)\n } catch (e) {\n tab?.close()\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setAbrindoPdf(false)\n }\n }, [note])\n\n const baixarXml = useCallback(async () => {\n if (!note) return\n setBaixandoXml(true); setError(null)\n try {\n const xml = await getInboxNoteXml(note.id)\n if (!xml) { setError('O arquivo desta nota não está guardado.'); return }\n const url = URL.createObjectURL(new Blob([xml], { type: 'application/xml' }))\n const a = document.createElement('a')\n // O nome é a CHAVE DE ACESSO, como a Receita e todo contador esperam —\n // `nota.xml` numa pasta com trinta notas não diz qual é qual.\n a.href = url\n a.download = `${note.accessKey || note.number || 'nfe'}.xml`\n a.click()\n URL.revokeObjectURL(url)\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setBaixandoXml(false)\n }\n }, [note])\n\n // The note's own tools live in the header, beside the title, so they never\n // scroll away. The XML exists per note: notes staged before the file was kept\n // have no bytes, and the menu item says so instead of failing.\n const ferramentas = note ? (\n <div className=\"flex items-center gap-1\">\n <Dropdown>\n <DropdownTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" disabled={baixandoXml || abrindoPdf}>\n {baixandoXml || abrindoPdf\n ? <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" />\n : <Download className=\"mr-1.5 h-4 w-4\" />}\n Baixar\n <ChevronDown className=\"ml-1 h-3.5 w-3.5 opacity-60\" />\n </Button>\n </DropdownTrigger>\n <DropdownContent align=\"end\">\n <DropdownItem className=\"gap-2\" disabled={!note.hasXml} onSelect={() => { void baixarXml() }}>\n <FileCode2 className=\"h-4 w-4\" />\n {note.hasXml ? 'XML da nota' : 'XML não guardado — reimporte o .xml'}\n </DropdownItem>\n <DropdownItem className=\"gap-2\" disabled={!note.accessKey} onSelect={() => { void abrirPdf() }}>\n <FileText className=\"h-4 w-4\" />\n DANFE (PDF)\n </DropdownItem>\n </DropdownContent>\n </Dropdown>\n <Hint label=\"Atualizar\">\n <Button variant=\"ghost\" size=\"icon\" aria-label=\"Atualizar a nota\" onClick={() => { void load() }}>\n <RefreshCw className=\"h-4 w-4\" />\n </Button>\n </Hint>\n </div>\n ) : null\n\n\n const save = async () => {\n if (!note) return\n setSaving(true); setError(null)\n try {\n await saveNoteDecision({\n documentId: note.id, items: decisions,\n defaultChartAccountId: defaultAccount, defaultLocationId: location,\n instalments,\n })\n await load()\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setSaving(false)\n }\n }\n\n const accept = async () => {\n if (!note) return\n setAccepting(true); setError(null)\n try {\n // Salvar e aceitar num gesto: o operador clicou «Aceitar», e pedir que ele\n // salve antes seria uma etapa que só existe por causa do nosso desenho.\n await saveNoteDecision({\n documentId: note.id, items: decisions,\n defaultChartAccountId: defaultAccount, defaultLocationId: location,\n instalments,\n })\n const result = await acceptNote(note.id, location)\n // What was attached before the payable existed now belongs to it.\n if (result.invoiceId) await moveNoteAttachmentsToInvoice(note.id, result.invoiceId).catch(() => {})\n setAccepted(result)\n await load()\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setAccepting(false)\n }\n }\n\n // Skeleton mirrors the real layout so the page does not jump when it arrives.\n if (loading) {\n return moldura((\n <div className=\"space-y-4\">\n {cabecalho('Conciliação')}\n <Card className=\"p-4\">\n <Skeleton className=\"h-4 w-32\" />\n <div className=\"mt-3 grid gap-x-6 gap-y-3 sm:grid-cols-2 lg:grid-cols-3\">\n {[0, 1, 2, 3, 4, 5].map((i) => (\n <div key={i}>\n <Skeleton className=\"h-3 w-20\" />\n <Skeleton className=\"mt-1.5 h-4 w-36\" />\n </div>\n ))}\n </div>\n </Card>\n <Card className=\"p-4\">\n <Skeleton className=\"h-4 w-36\" />\n <div className=\"mt-3 grid gap-4 sm:grid-cols-2\">\n {[0, 1].map((i) => (\n <div key={i}>\n <Skeleton className=\"h-3 w-28\" />\n <Skeleton className=\"mt-1.5 h-9 w-full\" />\n </div>\n ))}\n </div>\n </Card>\n <Skeleton className=\"h-4 w-24\" />\n <div className=\"space-y-2\">\n {[0, 1, 2].map((i) => (\n <Card key={i} className=\"flex items-center gap-3 px-4 py-3\">\n <Skeleton className=\"h-4 w-4 rounded-full\" />\n <div className=\"min-w-0 flex-1\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"mt-1.5 h-3 w-1/3\" />\n </div>\n <Skeleton className=\"h-4 w-20\" />\n </Card>\n ))}\n </div>\n </div>\n ), 'Conciliação')\n }\n\n if (!note) {\n return moldura((\n <div className=\"space-y-4\">\n {cabecalho('Conciliação')}\n <Card className=\"p-8 text-center text-sm\">\n {error\n ? <span className=\"text-destructive\">Não consegui carregar a nota: {error}</span>\n : <span className=\"text-muted-foreground\">Nota não encontrada.</span>}\n </Card>\n </div>\n ), 'Conciliação')\n }\n\n // ── Rejeitar / Salvar / Aceitar ──────────────────────────────────────────\n const pendencias = [\n unverifiedFactor > 0 && `${unverifiedFactor} com fator por conferir`,\n missingType > 0 && `${missingType} sem tipo`,\n missingProduct > 0 && `${missingProduct} sem produto`,\n missingUnit > 0 && `${missingUnit} sem unidade de estoque`,\n ].filter(Boolean).join(' · ')\n const rodape = readOnly ? null : {\n start: (\n <>\n {!hasPayable && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-destructive hover:bg-destructive/10 hover:text-destructive\"\n onClick={async () => { await rejectNote(note.id); onBack() }}\n disabled={saving || accepting}\n >\n <X className=\"mr-1.5 h-3.5 w-3.5\" />\n Rejeitar\n </Button>\n )}\n {pendencias && <span className=\"truncate text-xs text-muted-foreground\">{pendencias}</span>}\n </>\n ),\n end: (\n <>\n <Button variant=\"outline\" size=\"sm\" onClick={() => { void save() }} disabled={saving || accepting}>\n {saving && <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />}\n Salvar conciliação\n </Button>\n <Button\n size=\"sm\"\n onClick={() => { void accept() }}\n disabled={accepting || saving || missingType > 0 || missingProduct > 0 || missingUnit > 0 || unverifiedFactor > 0}\n >\n {accepting ? <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" /> : <Check className=\"mr-1.5 h-3.5 w-3.5\" />}\n {hasPayable ? 'Dar entrada no estoque' : 'Aceitar'}\n </Button>\n </>\n ),\n }\n\n return moldura((\n <div className={`space-y-4 ${emModal ? '' : 'pb-24'}`}>\n {cabecalho(`Conciliação · NF-e ${note.number}`)}\n\n {accepted && (\n <Card className=\"border-success bg-success-soft p-4\">\n <p className=\"text-sm font-medium text-success-soft-foreground\">\n {accepted.alreadyAccepted\n ? 'Esta nota já havia sido aceita — nada foi lançado de novo.'\n : accepted.instalments === 0\n ? `Entrada no estoque: ${accepted.stockLines} ${accepted.stockLines === 1 ? 'linha' : 'linhas'}, ligadas à conta a pagar que a nota já tinha (${money(accepted.invoiceTotal)}).`\n : `Aceita: ${accepted.stockLines} ${accepted.stockLines === 1 ? 'linha' : 'linhas'} de estoque e um título de ${money(accepted.invoiceTotal)} em ${accepted.instalments} ${accepted.instalments === 1 ? 'parcela' : 'parcelas'}.`}\n </p>\n {accepted.invoiceId && onOpenInvoice && (\n <Button variant=\"outline\" size=\"sm\" className=\"mt-2\" onClick={() => onOpenInvoice(accepted.invoiceId!)}>\n Abrir a conta a pagar\n </Button>\n )}\n </Card>\n )}\n\n {payableLost && !readOnly && (\n <Card className=\"border-warning bg-warning-soft p-4\" data-testid=\"note-payable-lost\">\n <p className=\"text-sm font-medium text-warning-soft-foreground\">\n A conta a pagar e a entrada no estoque desta nota foram apagadas fora daqui.\n </p>\n <p className=\"mt-1 text-xs text-warning-soft-foreground\">\n Confira a conciliação e clique em Aceitar para lançar as duas de novo.\n </p>\n </Card>\n )}\n\n {!accepted && (\n <Card className=\"p-4\" data-testid=\"note-postings\">\n <h3 className=\"text-sm font-semibold\">Lançamentos desta nota</h3>\n <dl className=\"mt-3 grid gap-x-6 gap-y-3 text-sm sm:grid-cols-2\">\n <div>\n <dt className=\"text-xs text-muted-foreground\">Conta a pagar</dt>\n <dd className=\"mt-0.5 flex flex-wrap items-center gap-2\">\n {!note.invoiceId && (\n <span className={payableLost ? 'text-destructive' : 'text-muted-foreground'}>\n {payableLost\n ? 'Não existe mais — foi apagada; aceite a nota para lançar de novo'\n : readOnly ? 'Nenhuma — esta nota não abriu conta a pagar' : 'Ainda não lançada — nasce quando a nota for aceita'}\n </span>\n )}\n {note.invoiceId && payable === null && (\n <span className=\"text-destructive\">Não encontrada — a conta foi apagada</span>\n )}\n {payable && (\n <span data-testid=\"note-payable-link\">\n {onOpenInvoice\n ? <InlineLink onClick={() => onOpenInvoice(payable.id)}>{payable.number ?? 'Conta a pagar'}</InlineLink>\n : (payable.number ?? 'Conta a pagar')}\n {' · '}{money(payable.total)}\n {payable.cancelledAt && <span className=\"text-destructive\"> · cancelada</span>}\n </span>\n )}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-muted-foreground\">Estoque</dt>\n <dd className=\"mt-0.5\">\n {note.stockedAt\n ? `Entrada em ${day(note.stockedAt)}`\n : <span className=\"text-muted-foreground\">{readOnly ? 'Sem entrada no estoque' : hasPayable ? 'Ainda sem entrada — conclua a conciliação e dê entrada' : 'Ainda sem entrada — entra quando a nota for aceita'}</span>}\n </dd>\n </div>\n </dl>\n </Card>\n )}\n\n {/* ── 1. Situação fiscal ─────────────────────────────────────────── */}\n <Card className=\"p-4\">\n <h3 className=\"text-sm font-semibold\">Situação fiscal</h3>\n <dl className=\"mt-3 grid gap-x-6 gap-y-2 text-sm sm:grid-cols-2 lg:grid-cols-3\">\n <div>\n <dt className=\"text-xs text-muted-foreground\">Fornecedor</dt>\n <dd className=\"text-sm\">\n {note.supplierPartyId\n ? <PersonLink personId={note.supplierPartyId} name={note.supplierName || '—'} kind=\"supplier\" />\n : (note.supplierName || '—')}\n </dd>\n </div>\n <Field label=\"CNPJ\" value={note.supplierCnpj ?? '—'} mono />\n <Field label=\"Natureza da operação\" value={note.natureOperation ?? '—'} />\n <Field\n label=\"Manifestação\"\n value={`${note.manifestationStatus ?? 'não manifestada'}${note.manifestationAttempts ? ` · ${note.manifestationAttempts} tentativa(s)` : ''}`}\n />\n <Field label=\"Manifestada em\" value={day(note.manifestedAt)} />\n <Field label=\"Recebida em\" value={day(note.receivedAt)} />\n </dl>\n {/* O aviso é um bloco, não um trecho de texto: solto ele vazava do card e\n empurrava o botão para debaixo da própria frase. */}\n {!note.supplierPartyId && (\n <div className=\"mt-3 flex flex-wrap items-center justify-between gap-2 rounded-md border border-input bg-muted/40 px-3 py-2\">\n <p className=\"text-xs text-muted-foreground\">\n {note.supplierCnpj\n ? <>Este fornecedor ainda não está no cadastro. Ao aceitar, ele é cadastrado com o nome e o CNPJ da nota.</>\n : <>A nota não traz o CNPJ do fornecedor, então a conta a pagar vai nascer <strong>sem fornecedor</strong>.</>}\n </p>\n {note.supplierCnpj && !readOnly && (\n <Button variant=\"outline\" size=\"sm\" disabled={cadastrando} onClick={() => { void cadastrarFornecedor() }}>\n {cadastrando ? <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" /> : <UserPlus className=\"mr-1.5 h-4 w-4\" />}\n Cadastrar agora\n </Button>\n )}\n </div>\n )}\n {/* A nota de bonificação entra no estoque e NÃO deve gerar título. Hoje\n gera: 57 notas assim no V1 da Artorius, em 11 grafias de natureza. */}\n {/bonific|brinde|doacao|doação/i.test(note.natureOperation ?? '') && (\n <div className=\"mt-3 rounded-md border border-dashed border-input px-3 py-2\">\n <p className=\"text-xs text-muted-foreground\">\n <Gift className=\"mr-1 inline h-3.5 w-3.5\" aria-hidden />\n A natureza desta nota é <strong>bonificação</strong>. Ela deveria entrar no estoque{' '}\n <strong>sem</strong> abrir conta a pagar — hoje ainda abre.{' '}\n <span className=\"rounded-full bg-muted px-1.5 py-0.5 text-[10px]\">Em breve</span>\n </p>\n </div>\n )}\n\n {!emModal && <div className=\"mt-3 flex flex-wrap items-center gap-2\">{ferramentas}</div>}\n </Card>\n\n {/* ── 2. Padrões da nota ─────────────────────────────────────────── */}\n <Card className=\"p-4\">\n <h3 className=\"text-sm font-semibold\">Padrões desta nota</h3>\n {registryWarning && (\n <div className=\"mt-2 rounded-md border border-warning bg-warning-soft px-3 py-2\">\n <p className=\"text-xs text-warning-soft-foreground\">\n <AlertTriangle className=\"mr-1 inline h-3.5 w-3.5\" aria-hidden />\n {registryWarning}\n </p>\n </div>\n )}\n <div className=\"mt-3 grid gap-4 sm:grid-cols-2\">\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Plano de contas padrão</span>\n <SearchSelect\n onSearch={localSearch(accountOptions)}\n value={defaultAccount ?? undefined}\n displayValue={labelOf(accountOptions, defaultAccount)}\n onChange={(id) => setDefaultAccount(id || null)}\n minChars={0}\n placeholder=\"Escolher plano de contas\"\n noResultsLabel=\"Nenhum plano de contas\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n <span className=\"mt-1 block text-[11px] text-muted-foreground\">\n Itens sem plano herdarão este.\n </span>\n </label>\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Local de estoque</span>\n <SearchSelect\n onSearch={localSearch(locationOptions)}\n value={location ?? undefined}\n displayValue={labelOf(locationOptions, location)}\n onChange={(id) => setLocation(id || null)}\n minChars={0}\n placeholder=\"Escolher local\"\n noResultsLabel=\"Nenhum local de estoque\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n <span className=\"mt-1 block text-[11px] text-muted-foreground\">\n Onde as linhas de estoque desta nota entram.\n </span>\n </label>\n </div>\n </Card>\n\n {/* ── 3. Itens — one collapsed group per item, with progress ─────── */}\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h3 className=\"text-sm font-semibold\">\n Itens <span className=\"font-normal text-muted-foreground\">({note.items.length})</span>\n </h3>\n <div className=\"h-1.5 min-w-[6rem] flex-1 overflow-hidden rounded-full bg-muted\">\n <div\n className=\"h-full rounded-full bg-primary transition-all\"\n style={{ width: `${note.items.length ? (doneCount / note.items.length) * 100 : 0}%` }}\n />\n </div>\n <span className=\"text-xs tabular-nums text-muted-foreground\">\n {doneCount}/{note.items.length} conferidos\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setOpenIds(openIds.length ? [] : note.items.map((i) => i.id))}\n >\n {openIds.length ? 'Recolher todos' : 'Abrir todos'}\n </Button>\n {/* Em tela cheia não há cabeçalho de modal onde pendurá-lo, então ele\n fica junto do que ele preenche. */}\n {!emModal && botaoIA}\n </div>\n\n {suggestionNote && (\n <div className=\"flex items-start gap-2 rounded-md border border-magic/30 bg-magic-soft px-3 py-2\">\n <p className=\"flex-1 text-xs text-magic-soft-foreground\">{suggestionNote}</p>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n className=\"shrink-0 text-xs text-magic-soft-foreground/70 hover:underline font-normal\"\n onClick={() => setSuggestionNote(null)}\n >\n Fechar\n </Button>\n </div>\n )}\n {/* Notes that crossed from the V1 without their XML arrive with a header\n and no lines; pulling the same key restages this very note. */}\n {note.items.length === 0 && (\n <Card className=\"p-6 text-center\" data-testid=\"note-without-items\">\n <p className=\"text-sm font-medium\">Esta nota chegou sem os itens</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {readOnly || !note.accessKey\n ? 'Não há o XML dela guardado para ler os itens.'\n : note.hasXml\n ? 'O XML guardado é só o resumo da SEFAZ, sem os itens. Busque a nota completa pela chave de acesso.'\n : 'O XML dela não veio junto. Busque na SEFAZ pela chave de acesso para conciliar.'}\n </p>\n {!readOnly && note.accessKey && note.status !== 'rejected' && (\n <Button className=\"mt-3\" size=\"sm\" onClick={() => setPullOpen(true)}>\n <Download className=\"mr-1.5 h-4 w-4\" /> Buscar itens na SEFAZ\n </Button>\n )}\n <PullByKeyDialog\n open={pullOpen}\n onOpenChange={setPullOpen}\n unitId={note.unitId}\n initialKey={note.accessKey ?? undefined}\n onPulled={() => { void load() }}\n />\n </Card>\n )}\n {note.items.map((item) => {\n const d = drafts[item.id] ?? draftOf(item)\n const factor = Number(d.conversionFactor.replace(',', '.')) || 1\n const shortage = d.shortageQuantity === '' ? 0 : Number(d.shortageQuantity.replace(',', '.')) || 0\n const stockQty = item.quantity * factor - shortage\n const unitCost = factor > 0 ? item.unitPrice / factor : item.unitPrice\n const bearing = isStockBearing(d.entryType)\n\n const open = openIds.includes(item.id)\n const done = Boolean(checked[item.id])\n const ready = isReady(item, d)\n const typeLabel = ENTRY_TYPES.find((t) => t.value === d.entryType)?.label\n\n return (\n <Card key={item.id} className=\"overflow-hidden\">\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n onClick={() => toggleItem(item.id)}\n aria-expanded={open}\n className=\"flex w-full items-center justify-start gap-3 rounded-none px-4 py-3 text-left font-normal transition-colors hover:bg-muted/30\"\n >\n <ChevronRight\n className={`h-4 w-4 shrink-0 text-muted-foreground transition-transform ${open ? 'rotate-90' : ''}`}\n aria-hidden\n />\n <span className=\"w-5 shrink-0 text-xs tabular-nums text-muted-foreground\">{item.itemNumber}</span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium leading-tight\">{item.description}</span>\n <span className=\"block truncate text-xs text-muted-foreground\">\n {qty(item.quantity)} {item.unit ?? ''} · {money(item.unitPrice)}\n {typeLabel ? ` · ${typeLabel}` : ' · sem tipo'}\n </span>\n </span>\n <span className=\"shrink-0 text-sm tabular-nums\">{money(item.total)}</span>\n {/* Quem escreveu neste item. Sem isto, «Falta decidir» e «A\n conferir» tratam igual o que a pessoa escolheu e o que a\n máquina chutou — e o fator errado é silencioso. */}\n {d.suggestedBy && !done && <AuthorBadge draft={d} />}\n <ItemState done={done && ready} ready={ready} />\n </Button>\n\n {open && (\n <div className=\"grid gap-4 border-t p-4 lg:grid-cols-2\">\n {/* ITEM NA NOTA — o que o documento diz, e não se edita. */}\n <div>\n <p className=\"text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Item na nota\n </p>\n <p className=\"mt-1 font-medium leading-tight\">{item.itemNumber}. {item.description}</p>\n <dl className=\"mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-xs sm:grid-cols-4\">\n <Field small label=\"Qtd\" value={`${qty(item.quantity)} ${item.unit ?? ''}`} />\n <Field small label=\"Vl. unit.\" value={money(item.unitPrice)} />\n <Field small label=\"Total\" value={money(item.total)} />\n <Field small label=\"Cód\" value={item.supplierProductCode || '—'} mono />\n <Field small label=\"EAN\" value={item.eanBarcode ?? '—'} mono />\n <Field small label=\"NCM\" value={item.ncm ?? '—'} mono />\n <Field small label=\"CFOP\" value={item.cfop ?? '—'} mono />\n <Field small label=\"CST/CSOSN\" value={item.icmsCst ?? item.icmsCsosn ?? '—'} mono />\n </dl>\n </div>\n\n {/* ITEM NO ESTOQUE — a decisão. */}\n <div className=\"space-y-3 lg:border-l lg:pl-4\">\n <p className=\"text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Item no estoque\n </p>\n\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Tipo do registro</span>\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {ENTRY_TYPES.map((t) => (\n <Button variant=\"bare\" size=\"bare\"\n key={t.value}\n type=\"button\"\n disabled={readOnly}\n onClick={() => patch(item.id, { entryType: t.value })}\n className={`gap-0 font-normal rounded-full border px-2.5 py-1 text-[11px] transition-colors disabled:opacity-60 ${\n d.entryType === t.value\n ? 'border-primary bg-primary text-primary-foreground'\n : 'border-input hover:bg-muted'\n }`}\n >\n {t.label}\n {t.hint && <span className=\"ml-1 opacity-70\">· {t.hint}</span>}\n </Button>\n ))}\n </div>\n </label>\n\n {bearing && (\n <>\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Produto vinculado</span>\n <SearchSelect\n value={d.productId ?? undefined}\n displayValue={d.productLabel || undefined}\n onChange={(id, option) => {\n patch(item.id, { productId: id || null, productLabel: option?.label ?? '' })\n // The product's own unit wins over the note's guess, unless someone picked one.\n if (id && !d.stockUnitId) {\n void listProductStockUnits([id]).then((m) => {\n setProductUnits((prev) => new Map([...prev, ...m]))\n const unit = suggestedStockUnit(item, units, m, id)\n if (unit) patch(item.id, { stockUnitId: unit })\n }).catch(() => {})\n }\n }}\n onSearch={async (term: string) => {\n // Busca vazia traz o que mais se parece com a descrição da\n // nota: o operador quase sempre quer justamente aquilo.\n const found = await searchProducts(term || item.description.slice(0, 24))\n return found.map((prod) => ({\n id: prod.id,\n label: prod.name,\n subtitle: prod.sku ?? undefined,\n }))\n }}\n minChars={0}\n placeholder=\"Buscar produto do catálogo\"\n noResultsLabel=\"Nenhum produto encontrado\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n </label>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Fator de conversão</span>\n <Input\n value={d.conversionFactor}\n onChange={(e) => patch(item.id, { conversionFactor: e.target.value })}\n inputMode=\"decimal\"\n disabled={readOnly}\n />\n </label>\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Unidade de estoque</span>\n <SearchSelect\n onSearch={localSearch(unitOptions)}\n value={d.stockUnitId ?? undefined}\n displayValue={labelOf(unitOptions, d.stockUnitId)}\n onChange={(id) => patch(item.id, { stockUnitId: id || null })}\n minChars={0}\n placeholder=\"Escolha a unidade\"\n noResultsLabel=\"Nenhuma unidade\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n </label>\n </div>\n\n {suspectFactor(item, d) && (\n <div className=\"rounded-md border border-warning bg-warning-soft px-3 py-2\">\n <p className=\"text-xs text-warning-soft-foreground\">\n <AlertTriangle className=\"mr-1 inline h-3.5 w-3.5\" aria-hidden />\n Este item vem em <strong>{item.unit}</strong>, que são{' '}\n {qty(packagingCount(item.unit) ?? 0)} por embalagem.{' '}\n {!d.stockUnitId\n ? <>Escolha a <strong>unidade de estoque</strong> para confirmar o fator — o\n produto está cadastrado sem unidade.</>\n : <>O fator ainda é 1: do jeito que está entrariam {qty(item.quantity)}{' '}\n em vez de {qty(item.quantity * (packagingCount(item.unit) ?? 1))}.</>}\n </p>\n </div>\n )}\n\n {/* A única defesa contra fator errado, e ela tem de ser\n legível ANTES de aceitar. */}\n <div className=\"rounded-md bg-muted/50 px-3 py-2\">\n <div className=\"flex items-baseline justify-between text-sm\">\n <span className=\"text-xs text-muted-foreground\">Qtd estoque (calc.)</span>\n <span className=\"font-semibold tabular-nums\">{qty(stockQty)}</span>\n </div>\n <div className=\"flex items-baseline justify-between text-sm\">\n <span className=\"text-xs text-muted-foreground\">Novo custo unitário</span>\n <span className=\"tabular-nums\">{money(unitCost)}</span>\n </div>\n </div>\n\n {/* Os dois gestos que hoje mandam a Laissa sair da tela. */}\n <div className=\"flex flex-wrap gap-2\">\n <EmBreve\n label=\"Criar produto daqui\"\n o_que=\"Cadastrar o produto a partir desta linha da nota, com nome, código e unidade já preenchidos\"\n quantas=\"ela criou 33 produtos no V1 no meio de importações\"\n />\n <EmBreve\n label=\"Lote e validade\"\n o_que=\"Informar lote e vencimento desta entrada — a coluna já existe no movimento de estoque\"\n quantas=\"usado 5 vezes no V1; numa churrascaria é validade de carne\"\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Modo de custo</span>\n <div className=\"mt-1 flex gap-1\">\n {(['novo', 'media'] as const).map((mode) => (\n <Button variant=\"bare\" size=\"bare\"\n key={mode}\n type=\"button\"\n disabled={readOnly}\n onClick={() => patch(item.id, { costMode: mode })}\n className={`font-normal flex-1 rounded-md border px-2 py-1 text-[11px] disabled:opacity-60 ${\n d.costMode === mode ? 'border-primary bg-primary/10' : 'border-input hover:bg-muted'\n }`}\n >\n {mode === 'novo' ? 'Novo' : 'Média'}\n </Button>\n ))}\n </div>\n </label>\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Falta (qtd)</span>\n <Input\n value={d.shortageQuantity}\n onChange={(e) => patch(item.id, { shortageQuantity: e.target.value })}\n inputMode=\"decimal\"\n placeholder=\"0\"\n disabled={readOnly}\n />\n </label>\n </div>\n </>\n )}\n\n <label className=\"block\">\n <span className=\"text-xs font-medium text-muted-foreground\">Plano de contas</span>\n <SearchSelect\n onSearch={localSearch(accountOptions)}\n value={(d.chartAccountId ?? defaultAccount) ?? undefined}\n displayValue={labelOf(accountOptions, d.chartAccountId ?? defaultAccount)}\n onChange={(id) => patch(item.id, { chartAccountId: id || null })}\n minChars={0}\n placeholder=\"Herda o padrão da nota\"\n noResultsLabel=\"Nenhum plano de contas\"\n searchingLabel=\"Buscando…\"\n clearLabel=\"Limpar\"\n disabled={readOnly}\n />\n </label>\n\n {item.stockMovementId && (\n <p className=\"text-[11px] text-success-soft-foreground\">\n <Check className=\"mr-1 inline h-3 w-3\" aria-hidden />\n Esta linha já deu entrada no estoque.\n </p>\n )}\n\n {!readOnly && (\n <div className=\"flex items-center justify-end gap-3 border-t pt-3\">\n {!ready && (\n <span className=\"text-[11px] text-muted-foreground\">\n {!d.entryType ? 'Escolha o tipo do registro' : 'Vincule o produto'}\n </span>\n )}\n <Button\n size=\"sm\"\n variant={done ? 'ghost' : 'outline'}\n disabled={!ready}\n onClick={() => (done ? setChecked((prev) => ({ ...prev, [item.id]: false })) : confirmItem(item.id))}\n >\n <Check className=\"mr-1.5 h-4 w-4\" />\n {done ? 'Conferido' : 'Conferir item'}\n </Button>\n </div>\n )}\n </div>\n </div>\n )}\n </Card>\n )\n })}\n </div>\n\n {/* ── 4. Dados de pagamento ──────────────────────────────────────── */}\n <Card className=\"p-4\">\n <div className=\"flex items-baseline justify-between\">\n <h3 className=\"text-sm font-semibold\">Dados de pagamento</h3>\n <p className=\"text-xs text-muted-foreground\">\n {instalments.length} {instalments.length === 1 ? 'parcela' : 'parcelas'} ·{' '}\n <span className=\"tabular-nums\">{money(instalmentSum)}</span>\n </p>\n </div>\n\n {note.declaredPayments.length > 0 && (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n A nota declarou: {note.declaredPayments.map((p) => `${p.label ?? p.code} ${money(p.value)}`).join(' · ')}\n </p>\n )}\n\n <div className=\"mt-3 space-y-2\">\n {instalments.map((inst, i) => (\n <div key={i} className=\"grid items-end gap-2 sm:grid-cols-[2rem_1fr_1fr_1fr_2rem]\">\n <span className=\"pb-2 text-xs tabular-nums text-muted-foreground\">{inst.index}</span>\n <label className=\"block\">\n <span className=\"text-[11px] text-muted-foreground\">Vencimento</span>\n {/* Nota já aceita não tem vencimento editável, e um seletor de data\n apagado confunde mais que o texto: a parcela virou título. */}\n {paymentLocked ? (\n <p className=\"py-2 text-sm tabular-nums\">{day(inst.dueDate)}</p>\n ) : (\n <DatePicker\n value={inst.dueDate ?? ''}\n onChange={(v: string) =>\n setInstalments((prev) => prev.map((p, j) => (j === i ? { ...p, dueDate: v || null } : p)))}\n />\n )}\n </label>\n <label className=\"block\">\n <span className=\"text-[11px] text-muted-foreground\">Valor</span>\n <Input\n value={String(inst.amount)}\n inputMode=\"decimal\"\n disabled={paymentLocked}\n onChange={(e) =>\n setInstalments((prev) => prev.map((p, j) =>\n (j === i ? { ...p, amount: Number(e.target.value.replace(',', '.')) || 0 } : p)))}\n />\n </label>\n <label className=\"block\">\n <span className=\"text-[11px] text-muted-foreground\">Cód. barras / PIX</span>\n <Input\n value={inst.barcode ?? inst.pixKey ?? ''}\n disabled={paymentLocked}\n onChange={(e) =>\n setInstalments((prev) => prev.map((p, j) => (j === i ? { ...p, barcode: e.target.value } : p)))}\n />\n </label>\n {!paymentLocked && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={`Remover a parcela ${inst.index}`}\n onClick={() => setInstalments((prev) => prev.filter((_, j) => j !== i))}\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n ))}\n </div>\n\n {!paymentLocked && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"mt-3\"\n onClick={() => setInstalments((prev) => [...prev, {\n index: prev.length + 1, number: null, dueDate: note.issueDate, amount: 0, paymentType: 'boleto',\n }])}\n >\n <Plus className=\"mr-1.5 h-4 w-4\" />\n Adicionar parcela\n </Button>\n )}\n\n {/* O título nasce com a soma das parcelas. Se ela não bate com a nota, a\n tela diz — é a divergência que a financial/084 mediu em 6,3% dos casos. */}\n {Math.abs(instalmentSum - note.total) > 0.01 && (\n <Hint className=\"mt-3\">\n <span>\n <AlertTriangle className=\"mr-1 inline h-3.5 w-3.5\" aria-hidden />\n A nota diz {money(note.total)} e as parcelas somam {money(instalmentSum)}. O título vai\n nascer com <strong>{money(instalmentSum)}</strong> — é a soma das parcelas que define o\n saldo a pagar.\n </span>\n </Hint>\n )}\n </Card>\n\n {/* ── 5. Anexos da conta ─────────────────────────────────────────── */}\n <NoteAttachmentsCard\n noteId={note.id}\n invoiceId={note.invoiceId}\n readOnly={readOnly}\n instalments={instalments}\n onInstalments={setInstalments}\n />\n\n {error && (\n <Card className=\"border-destructive bg-destructive/5 p-4\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </Card>\n )}\n\n </div>\n ), `Conciliação · NF-e ${note.number}`, rodape)\n}\n\n/**\n * QUEM escreveu esta linha, quando não foi gente.\n *\n * Igualdade e semelhança em cores diferentes porque se conferem de maneiras\n * diferentes: um EAN batido não precisa de leitura, um «parecido» precisa. Roxo\n * (`magic`) é a cor do que a máquina propôs em todo o produto; azul é o vínculo\n * exato, que é informação e não aviso.\n */\nfunction AuthorBadge({ draft }: { draft: Draft }) {\n if (draft.suggestedBy === 'ai') {\n const confira = draft.suggestionConfidence != null && draft.suggestionConfidence < 0.6\n return (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-magic-soft px-2 py-0.5 text-[11px] font-medium text-magic-soft-foreground\">\n IA{confira ? ' · confira' : ''}\n </span>\n )\n }\n return (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-info-soft px-2 py-0.5 text-[11px] font-medium text-info-soft-foreground\">\n {draft.suggestedBy === 'ean' ? 'EAN' : 'fornecedor'}\n </span>\n )\n}\n\n/**\n * O estado da linha, e ele NUNCA diz «conferido» sobre o que não está pronto.\n *\n * `done` sozinho mentia: a marca de conferência sobrevive a mexer no campo\n * depois — e ninguém confere de novo um item que a tela já deu por fechado.\n * Quem chama passa `done && ready`.\n */\nfunction ItemState({ done, ready }: { done: boolean; ready: boolean }) {\n if (done) {\n return (\n <span className=\"inline-flex shrink-0 items-center rounded-full bg-success-soft px-2 py-0.5 text-[11px] font-medium text-success-soft-foreground\">\n <Check className=\"mr-1 h-3 w-3\" aria-hidden />\n Conferido\n </span>\n )\n }\n return (\n <span className={`inline-flex shrink-0 items-center rounded-full px-2 py-0.5 text-[11px] font-medium ${\n ready ? 'bg-muted text-muted-foreground' : 'bg-warning-soft text-warning-soft-foreground'\n }`}>\n {ready ? 'A conferir' : 'Falta decidir'}\n </span>\n )\n}\n\nfunction Field({ label, value, mono, small }: { label: string; value: string; mono?: boolean; small?: boolean }) {\n return (\n <div>\n <dt className={`text-muted-foreground ${small ? 'text-[10px]' : 'text-xs'}`}>{label}</dt>\n <dd className={`${mono ? 'tabular-nums' : ''} ${small ? 'text-xs' : 'text-sm'}`}>{value}</dd>\n </div>\n )\n}\n","// ---------------------------------------------------------------------------\n// A página de notas de compra: lista, conciliação e fila da SEFAZ numa moldura.\n// ---------------------------------------------------------------------------\n// As vistas trocam por ESTADO LOCAL, não por rota. Trocar de rota remonta a\n// página e rebusca tudo — a lista pisca, a posição de rolagem se perde, e voltar\n// da conciliação recarrega 200 notas para mostrar a mesma coisa.\n//\n// A CONCILIAÇÃO É MODAL, e a lista FICA MONTADA ATRÁS DELA. Era subpágina, e\n// subpágina desmonta: quem conciliava a quinta nota de um recorte de 200 voltava\n// para a lista no estado inicial — sem o filtro, sem a busca, no topo. O trabalho\n// é «abrir, decidir, fechar, abrir a próxima», e o custo era pago uma vez por\n// nota. Com o modal a lista nunca é desfeita, então fechar devolve exatamente o\n// que estava na tela.\n//\n// O ENDEREÇO EMPILHA NA DESCIDA. `pushState` não dispara `hashchange`, então o\n// roteador do anfitrião continua sem remontar nada — mas a conciliação passa a\n// existir como um degrau no histórico. Com `replaceState` ela não existia, e o\n// «voltar» do cabeçalho (que anda pelo histórico quando a pessoa veio de outro\n// módulo) saltava a lista inteira e caía no Painel. Subir é desempilhar.\n// ---------------------------------------------------------------------------\nimport React, { useCallback, useEffect, useState } from 'react'\nimport { Modal, ModalContent } from '@fayz-ai/ui'\nimport { findInboxNoteByOperation } from '../data/inbox'\nimport { InboundNotesView } from './InboundNotesView'\nimport { NoteReconcileView } from './NoteReconcileView'\n\ntype View =\n | { kind: 'list' }\n | { kind: 'note'; id: string }\n\nconst HASH_PREFIX = '#/inbound-notes'\n\nfunction viewFromLocation(): View {\n if (typeof window === 'undefined') return { kind: 'list' }\n const hash = window.location.hash\n const note = hash.match(/\\/inbound-notes\\/note\\/([0-9a-f-]{36})/i)\n if (note) return { kind: 'note', id: note[1] }\n return { kind: 'list' }\n}\n\nconst pathOf = (view: View) =>\n view.kind === 'note' ? `${HASH_PREFIX}/note/${view.id}` : HASH_PREFIX\n\nexport interface InboundNotesPageProps {\n /** Onde o título a pagar vive no app anfitrião. Sem isto o botão não aparece. */\n payableRoute?: (invoiceId: string) => string\n}\n\n/** Marca as entradas que ESTA página empilhou, para só elas serem desempilhadas. */\nconst STACK_MARK = { inboundNotes: true }\n\nexport function InboundNotesPage({ payableRoute = (id) => `/financial/payables/${id}` }: InboundNotesPageProps = {}) {\n const [view, setView] = useState<View>(viewFromLocation)\n\n const go = useCallback((next: View) => {\n setView(next)\n if (typeof window === 'undefined') return\n const path = pathOf(next)\n if (window.location.hash === path) return\n const empilhado = (window.history.state as { inboundNotes?: boolean } | null)?.inboundNotes\n if (next.kind !== 'note' && empilhado) {\n // Desempilha de verdade: trocar a URL à mão deixaria a conciliação no\n // histórico e o «voltar» do navegador entraria nela outra vez.\n window.history.back()\n return\n }\n if (next.kind === 'list') window.history.replaceState(null, '', path)\n else window.history.pushState(STACK_MARK, '', path)\n }, [])\n\n // O «voltar» do navegador é um gesto legítimo aqui: quem entrou na conciliação\n // por um deep link espera sair dela com ele.\n useEffect(() => {\n if (typeof window === 'undefined') return\n const onPop = () => {\n const next = viewFromLocation()\n setView(next)\n }\n window.addEventListener('popstate', onPop)\n window.addEventListener('hashchange', onPop)\n return () => {\n window.removeEventListener('popstate', onPop)\n window.removeEventListener('hashchange', onPop)\n }\n }, [])\n\n const fecharNota = useCallback(() => go({ kind: 'list' }), [go])\n\n // ENTRAR PELA OPERAÇÃO DE ESTOQUE. A linha de Movimentações sabe de que\n // OPERAÇÃO ela veio, não de que nota — o id da nota só o banco tem. Então o\n // link chega como `?operation=…` e esta página resolve, em vez de obrigar o\n // Estoque a consultar uma tabela do fiscal para desenhar um href.\n useEffect(() => {\n if (typeof window === 'undefined') return\n const op = window.location.hash.match(/[?&]operation=([0-9a-f-]{36})/i)?.[1]\n if (!op) return\n let vivo = true\n findInboxNoteByOperation(op)\n .then((id) => { if (vivo && id) go({ kind: 'note', id }) })\n .catch(() => { /* link velho ou nota de outra conta: fica na lista */ })\n return () => { vivo = false }\n }, [go])\n\n return (\n <>\n {/* A tela de fundo nunca é desmontada enquanto a nota está aberta: é ela\n que guarda o recorte, a busca e a rolagem a que a pessoa volta. */}\n <InboundNotesView onOpenNote={(id) => go({ kind: 'note', id })} />\n\n <Modal open={view.kind === 'note'} onOpenChange={(open) => { if (!open) fecharNota() }}>\n {view.kind === 'note' && (\n // `noPadding`: a conciliação desenha o próprio cabeçalho e o próprio\n // corpo — o título e o «Sugerir com IA» ficam fora da área que rola, e o\n // rodapé «Aceitar» precisa encostar nas bordas do modal.\n <ModalContent size=\"5xl\" noPadding className=\"sm:max-h-[90vh]\">\n <NoteReconcileView\n chrome=\"modal\"\n noteId={view.id}\n onBack={fecharNota}\n onOpenInvoice={payableRoute\n ? (invoiceId) => { window.location.hash = payableRoute(invoiceId) }\n : undefined}\n />\n </ModalContent>\n )}\n </Modal>\n </>\n )\n}\n\n/**\n * O componente que o registro de rotas monta. Ele recebe as rotas sem prop, então\n * a configuração do host entra por fechamento — e a fábrica mora aqui, num `.tsx`,\n * para o manifesto continuar sendo TypeScript sem JSX.\n */\nexport function makeInboundNotesRoute(options: InboundNotesPageProps = {}): () => React.ReactElement {\n return function InboundNotesRoute() {\n return <InboundNotesPage {...options} />\n }\n}\n","import React from 'react'\nimport {\n Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Select, SelectContent,\n SelectItem, SelectTrigger, SelectValue, Skeleton, Switch, toast,\n} from '@fayz-ai/ui'\nimport { getActiveTenantId, getSupabaseClientOptional, maskCpfCnpj } from '@fayz-ai/core'\nimport { adminNavigateTo } from '@fayz-ai/admin'\nimport { Check, Info, ShieldCheck, X } from 'lucide-react'\n\n/**\n * The \"Certificado\" and \"Emissão Fiscal\" tabs of the V1 company form, on the\n * unit detail page. One row per legal entity (017): two units with the same\n * CNPJ share it. `nfce_csc_token` is write-only — it is outside the SELECT\n * grant, and the screen reads `nfce_csc_token_set`.\n *\n * The A1 goes through `fiscalbr-certificate`, which forwards it to PlugNotas\n * without storing it and records holder and validity read from the file.\n */\n\nconst COLUMNS = [\n 'id', 'legal_entity_id',\n 'nfse_enabled', 'nfse_production', 'nfse_national', 'nfse_service_code_national', 'nfse_service_code_municipal',\n 'nfse_nbs_code', 'nfse_cnae', 'nfse_iss_rate', 'nfse_iss_taxation', 'nfse_ibscbs_cst', 'nfse_ibscbs_classification',\n 'nfse_simples_regime', 'nfse_net_value', 'nfse_additional_info',\n 'nfce_enabled', 'nfce_production', 'nfce_series', 'nfce_csc_id', 'nfce_csc_token_set', 'nfce_generic_item',\n 'certificate_cn', 'certificate_expires_at', 'certificate_uploaded_at',\n 'dfe_sync_enabled', 'dfe_last_sync_at', 'dfe_last_error', 'provider_synced_at',\n].join(', ')\n\ntype Settings = Record<string, any>\n\ninterface UnitItem {\n id?: string\n tenantId?: string\n legalEntityId?: string | null\n legalName?: string | null\n cnpj?: string | null\n stateRegistration?: string | null\n municipalRegistration?: string | null\n taxRegime?: string | null\n cnae?: string | null\n ibgeCityCode?: string | null\n}\n\nconst sb = () => getSupabaseClientOptional() as any\n\nasync function uploadCertificate(legalEntityId: string, file: File, password: string) {\n const buf = new Uint8Array(await file.arrayBuffer())\n let bin = ''\n for (let i = 0; i < buf.length; i++) bin += String.fromCharCode(buf[i])\n const { data, error } = await sb().functions.invoke('fiscalbr-certificate', {\n body: { legalEntityId, pfxBase64: btoa(bin), password, fileName: file.name, tenantId: getActiveTenantId() ?? null },\n })\n if (error) {\n let body: any = null\n try { body = await (error as any)?.context?.json?.() } catch { /* generic below */ }\n throw new Error(body?.error || error.message || 'Falha ao falar com o serviço fiscal.')\n }\n return data as { cn: string; expiresAt: string; warning: string | null }\n}\n\nfunction useEmitterSettings(legalEntityId: string | null | undefined) {\n const [row, setRow] = React.useState<Settings | null>(null)\n const [loading, setLoading] = React.useState(true)\n\n React.useEffect(() => {\n if (!legalEntityId) { setLoading(false); return }\n let alive = true\n void sb()?.from('plg_fiscalbr_emitter_settings').select(COLUMNS).eq('legal_entity_id', legalEntityId).maybeSingle()\n .then(({ data, error }: { data: Settings | null; error: { message: string } | null }) => {\n if (!alive) return\n if (error) toast.error('Não foi possível ler a configuração fiscal', { description: error.message })\n setRow(data ?? {})\n setLoading(false)\n })\n return () => { alive = false }\n }, [legalEntityId])\n\n const save = React.useCallback(async (tenantId: string, patch: Settings): Promise<boolean> => {\n if (!legalEntityId) return false\n const payload = { ...patch, tenant_id: tenantId, legal_entity_id: legalEntityId, updated_at: new Date().toISOString() }\n const { data, error } = await sb().from('plg_fiscalbr_emitter_settings')\n .upsert(payload, { onConflict: 'legal_entity_id' }).select(COLUMNS).single()\n if (error) {\n toast.error('Não foi possível salvar', { description: error.message })\n return false\n }\n setRow(data)\n return true\n }, [legalEntityId])\n\n return { row, loading, save, setRow }\n}\n\nfunction NeedsLegalEntity({ item, what }: { item: UnitItem; what: string }) {\n return (\n <Card>\n <CardContent className=\"flex flex-col items-start gap-3 py-6\">\n <p className=\"text-sm font-medium\">Falta o CNPJ desta unidade</p>\n <p className=\"text-sm text-muted-foreground\">\n {what} pertence à pessoa jurídica. Preencha a razão social e o CNPJ em Dados da empresa para configurar aqui.\n </p>\n <Button variant=\"outline\" onClick={() => adminNavigateTo(`/settings/locations/${item.id}/edit`)}>Preencher CNPJ</Button>\n </CardContent>\n </Card>\n )\n}\n\nfunction LoadingCard() {\n return (\n <Card>\n <CardContent className=\"space-y-3 py-6\">\n <Skeleton className=\"h-5 w-48\" />\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n </CardContent>\n </Card>\n )\n}\n\nfunction ToggleRow({ title, description, checked, onChange, disabled, children }: {\n title: string; description?: string; checked: boolean; onChange: (v: boolean) => void; disabled?: boolean; children?: React.ReactNode\n}) {\n return (\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium\">{title}</p>\n {description && <p className=\"text-xs text-muted-foreground\">{description}</p>}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {children}\n <Switch checked={checked} disabled={disabled} onCheckedChange={onChange} />\n </div>\n </div>\n )\n}\n\nfunction Field({ label, hint, children }: { label: string; hint?: string; children: React.ReactNode }) {\n return (\n <div className=\"space-y-1.5\">\n <span className=\"text-sm font-medium\">{label}</span>\n {children}\n {hint && <p className=\"text-xs text-muted-foreground\">{hint}</p>}\n </div>\n )\n}\n\n/** The closed state of a fiscal block: what is configured, and the button to change it. */\nfunction SummaryCard({ title, lines, badge, onConfigure }: {\n title: string\n lines: Array<{ label: string; value: string }>\n badge?: { text: string; tone: 'ok' | 'muted' | 'bad' }\n onConfigure: () => void\n}) {\n return (\n <Card>\n <CardHeader className=\"flex-row items-start justify-between gap-3 space-y-0\">\n <div className=\"min-w-0\">\n <CardTitle className=\"text-base\">{title}</CardTitle>\n <dl className=\"mt-2 grid gap-x-6 gap-y-1 text-sm\" style={{ gridTemplateColumns: 'auto 1fr' }}>\n {lines.map((l) => (\n <React.Fragment key={l.label}>\n <dt className=\"text-muted-foreground\">{l.label}</dt>\n <dd className=\"text-foreground\">{l.value}</dd>\n </React.Fragment>\n ))}\n </dl>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {badge && (\n <Badge\n variant={badge.tone === 'bad' ? 'destructive' : 'outline'}\n className={badge.tone === 'ok' ? 'border-emerald-500/40 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400' : badge.tone === 'muted' ? 'text-muted-foreground' : undefined}\n >\n {badge.text}\n </Badge>\n )}\n <Button variant=\"outline\" size=\"sm\" onClick={onConfigure}>Configurar</Button>\n </div>\n </CardHeader>\n </Card>\n )\n}\n\nconst fmtDateTime = (v?: string | null) => (v ? new Date(v).toLocaleString('pt-BR') : null)\n\n// ── Certificado ─────────────────────────────────────────────────────────────\n\nexport function UnitCertificateWidget({ item }: { item?: UnitItem }) {\n const { row, loading, save, setRow } = useEmitterSettings(item?.legalEntityId)\n const [open, setOpen] = React.useState(false)\n const [file, setFile] = React.useState<File | null>(null)\n const [password, setPassword] = React.useState('')\n const [sending, setSending] = React.useState(false)\n // An expired certificate is why someone landed here: open on the upload.\n const expiredNow = !!row?.certificate_expires_at && Date.parse(row.certificate_expires_at) < Date.now()\n React.useEffect(() => { if (expiredNow) setOpen(true) }, [expiredNow])\n if (!item?.id) return null\n if (!item.legalEntityId) return <NeedsLegalEntity item={item} what=\"O certificado digital\" />\n if (loading || !row) return <LoadingCard />\n\n const expires = row.certificate_expires_at ? new Date(row.certificate_expires_at) : null\n const expired = expires ? expires.getTime() < Date.now() : false\n const hasCertificate = !!row.certificate_uploaded_at\n\n if (!open) {\n return (\n <SummaryCard\n title=\"Certificado digital e DANFes\"\n lines={[\n { label: 'Certificado A1', value: hasCertificate\n ? [row.certificate_cn, expires ? `válido até ${expires.toLocaleDateString('pt-BR')}` : null].filter(Boolean).join(' · ') || 'Enviado'\n : 'Nenhum certificado enviado' },\n { label: 'Receber DANFes', value: row.dfe_sync_enabled ? `Ligado · última sincronização ${fmtDateTime(row.dfe_last_sync_at) ?? 'nunca'}` : 'Desligado' },\n ]}\n badge={hasCertificate ? { text: expired ? 'Vencido' : 'Ativo', tone: expired ? 'bad' : 'ok' } : { text: 'Sem certificado', tone: 'muted' }}\n onConfigure={() => setOpen(true)}\n />\n )\n }\n\n return (\n <Card>\n <CardHeader className=\"flex-row items-start justify-between gap-3 space-y-0\">\n <CardTitle className=\"text-base\">Certificado digital e DANFes</CardTitle>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setOpen(false)}>Fechar</Button>\n </CardHeader>\n <CardContent className=\"space-y-5\">\n <ToggleRow\n title=\"Receber DANFes automaticamente\"\n description=\"Busca por hora as NF-e emitidas contra o CNPJ desta empresa.\"\n checked={!!row.dfe_sync_enabled}\n onChange={(v) => void save(item.tenantId!, { dfe_sync_enabled: v }).then((ok) => ok && toast.success(v ? 'Recepção ligada' : 'Recepção desligada'))}\n />\n\n <div className=\"rounded-md border bg-muted/40 p-3 text-sm\">\n <p className=\"mb-1.5 flex items-center gap-1.5 font-medium\"><Info className=\"h-4 w-4\" /> Como funciona</p>\n <ul className=\"ml-5 list-disc space-y-1 text-muted-foreground\">\n <li><strong className=\"text-foreground\">O que faz:</strong> consulta a SEFAZ e lista as NF-e emitidas contra o CNPJ, para você aceitar ou rejeitar e gerar entrada de estoque ou conta a pagar.</li>\n <li><strong className=\"text-foreground\">Requer certificado digital A1</strong> (.pfx) válido desta empresa. O arquivo vai direto ao serviço fiscal e não fica armazenado no nosso sistema.</li>\n <li><strong className=\"text-foreground\">Não faz manifestação na SEFAZ</strong> (ciência, confirmação, desconhecimento) nem emite NF-e.</li>\n </ul>\n </div>\n\n <div className=\"rounded-md border p-4 space-y-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <p className=\"flex items-center gap-1.5 text-sm font-medium\"><ShieldCheck className=\"h-4 w-4\" /> Certificado digital A1</p>\n <p className=\"text-xs text-muted-foreground\">\n {hasCertificate\n ? [row.certificate_cn, expires ? `válido até ${expires.toLocaleDateString('pt-BR')}` : null].filter(Boolean).join(' · ')\n : 'Nenhum certificado enviado'}\n </p>\n </div>\n {hasCertificate && <Badge variant={expired ? 'destructive' : 'secondary'}>{expired ? 'Vencido' : 'Ativo'}</Badge>}\n </div>\n <div className=\"fz-container\">\n <div className=\"fz-fields fz-fields-2 gap-4\">\n <Field label=\"Arquivo (.pfx)\">\n <Input type=\"file\" accept=\".pfx,.p12,application/x-pkcs12\" data-testid=\"certificate-file\"\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFile(e.target.files?.[0] ?? null)} />\n </Field>\n <Field label=\"Senha do certificado\">\n <Input type=\"password\" autoComplete=\"new-password\" name=\"pfx-password\" value={password} data-testid=\"certificate-password\"\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPassword(e.target.value)} />\n </Field>\n </div>\n </div>\n <div className=\"flex justify-end\">\n <Button\n size=\"sm\"\n data-testid=\"certificate-send\"\n disabled={!file || !password || sending}\n onClick={() => {\n if (!file) return\n setSending(true)\n void uploadCertificate(item.legalEntityId!, file, password)\n .then((res) => {\n setRow((r: Settings | null) => ({ ...(r ?? {}), certificate_cn: res.cn, certificate_expires_at: res.expiresAt,\n certificate_uploaded_at: new Date().toISOString(), dfe_sync_enabled: true, dfe_last_error: res.warning ?? null }))\n setFile(null); setPassword('')\n if (res.warning) toast.warning('Certificado enviado, com um aviso', { description: res.warning })\n else toast.success(`Certificado enviado · válido até ${new Date(res.expiresAt).toLocaleDateString('pt-BR')}`)\n })\n .catch((e: Error) => toast.error('Não foi possível enviar o certificado', { description: e.message }))\n .finally(() => setSending(false))\n }}\n >\n {sending ? 'Enviando…' : hasCertificate ? 'Atualizar certificado' : 'Enviar certificado'}\n </Button>\n </div>\n {row.dfe_last_error && <p className=\"text-xs text-destructive\">{row.dfe_last_error}</p>}\n </div>\n\n <p className=\"text-xs text-muted-foreground\">\n Última sincronização: {fmtDateTime(row.dfe_last_sync_at) ?? 'nunca'}\n </p>\n </CardContent>\n </Card>\n )\n}\n\n// ── Emissão fiscal ──────────────────────────────────────────────────────────\n\nconst ISS_TAXATION = [\n { value: '6', label: 'Tributável no município' },\n { value: '7', label: 'Tributável fora do município' },\n { value: '1', label: 'Isento' },\n { value: '2', label: 'Imune' },\n]\nconst SIMPLES_REGIME = [\n { value: 'auto', label: 'Automático (1 — tudo pelo Simples; excesso → 3)' },\n { value: '1', label: '1 — Federais e ISS pelo Simples (DAS)' },\n { value: '2', label: '2 — Federais pelo Simples; ISS pela NFS-e (lei municipal)' },\n { value: '3', label: '3 — Federais e ISS fora do Simples (sublimite)' },\n]\n\nfunction EnvSelect({ value, onChange, disabled }: { value: boolean; onChange: (prod: boolean) => void; disabled?: boolean }) {\n return (\n <Select value={value ? 'prod' : 'hom'} onValueChange={(v) => onChange(v === 'prod')} disabled={disabled}>\n <SelectTrigger className=\"h-8 w-36\"><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"hom\">Homologação</SelectItem>\n <SelectItem value=\"prod\">Produção</SelectItem>\n </SelectContent>\n </Select>\n )\n}\n\nexport function UnitFiscalWidget({ item }: { item?: UnitItem }) {\n const { row, loading, save } = useEmitterSettings(item?.legalEntityId)\n const [draft, setDraft] = React.useState<Settings>({})\n const [cscToken, setCscToken] = React.useState('')\n const [saving, setSaving] = React.useState(false)\n const [open, setOpen] = React.useState(false)\n\n React.useEffect(() => { if (row) setDraft(row) }, [row])\n\n if (!item?.id) return null\n if (!item.legalEntityId) return <NeedsLegalEntity item={item} what=\"A emissão fiscal\" />\n if (loading || !row) return <LoadingCard />\n\n const set = (patch: Settings) => setDraft((d) => ({ ...d, ...patch }))\n const generic = (draft.nfce_generic_item ?? {}) as { ncm?: string; cfop?: string; csosn?: string }\n const setGeneric = (patch: Partial<typeof generic>) => set({ nfce_generic_item: { ...generic, ...patch } })\n const isSimples = (item.taxRegime ?? '').startsWith('simples')\n\n const checks = [\n { ok: !!row.certificate_uploaded_at && !(row.certificate_expires_at && Date.parse(row.certificate_expires_at) < Date.now()), label: 'Certificado A1 válido' },\n // Only what the switched-on documents need: NFS-e off does not block a restaurant that issues NFC-e.\n ...(draft.nfse_enabled ? [\n { ok: !!draft.nfse_service_code_national, label: 'Código de tributação do serviço' },\n { ok: draft.nfse_iss_rate != null && draft.nfse_iss_rate !== '', label: 'Alíquota de ISS' },\n ] : []),\n ...(draft.nfce_enabled ? [\n { ok: !!item.stateRegistration && !!draft.nfce_csc_id && (!!row.nfce_csc_token_set || !!cscToken), label: 'IE + CSC (NFC-e)' },\n ] : []),\n { ok: !!row.provider_synced_at, label: 'Empresa registrada para emitir' },\n ]\n const ready = (draft.nfse_enabled || draft.nfce_enabled) && checks.every((c) => c.ok)\n\n const onSave = async () => {\n setSaving(true)\n const { id: _id, legal_entity_id: _le, nfce_csc_token_set: _t, certificate_cn: _cn, certificate_expires_at: _e,\n certificate_uploaded_at: _u, dfe_last_sync_at: _d, provider_synced_at: _p, ...patch } = draft\n const issRate = patch.nfse_iss_rate === '' || patch.nfse_iss_rate == null ? null : Number(String(patch.nfse_iss_rate).replace(',', '.'))\n const ok = await save(item.tenantId!, {\n ...patch,\n nfse_iss_rate: Number.isFinite(issRate as number) ? issRate : null,\n nfse_iss_taxation: patch.nfse_iss_taxation ? Number(patch.nfse_iss_taxation) : null,\n nfse_simples_regime: patch.nfse_simples_regime && patch.nfse_simples_regime !== 'auto' ? Number(patch.nfse_simples_regime) : null,\n nfce_series: patch.nfce_series ? Number(patch.nfce_series) : null,\n ...(cscToken ? { nfce_csc_token: cscToken } : {}),\n })\n setSaving(false)\n if (ok) { setCscToken(''); setOpen(false); toast.success('Configuração fiscal salva') }\n }\n\n if (!open) {\n const env = (prod: boolean) => (prod ? 'Produção' : 'Homologação')\n return (\n <SummaryCard\n title=\"Emissão fiscal (NFS-e / NFC-e)\"\n lines={[\n { label: 'NFS-e', value: row.nfse_enabled ? `Ligada · ${env(!!row.nfse_production)}` : 'Desligada' },\n { label: 'NFC-e', value: row.nfce_enabled ? `Ligada · ${env(!!row.nfce_production)}${row.nfce_series ? ` · série ${row.nfce_series}` : ''}` : 'Desligada' },\n ]}\n badge={ready ? { text: 'Pronto para emitir', tone: 'ok' } : { text: 'Configuração incompleta', tone: 'muted' }}\n onConfigure={() => setOpen(true)}\n />\n )\n }\n\n return (\n <Card>\n <CardHeader className=\"flex-row items-start justify-between gap-3 space-y-0\">\n <div>\n <CardTitle className=\"text-base\">Emissão fiscal (NFS-e / NFC-e)</CardTitle>\n <CardDescription>{item.legalName ?? 'Pessoa jurídica'}{item.cnpj ? ` · CNPJ ${maskCpfCnpj(item.cnpj)}` : ''}</CardDescription>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant={ready ? 'default' : 'secondary'}>\n {ready ? 'Pronto para emitir' : 'Configuração incompleta'}\n </Badge>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { setDraft(row); setCscToken(''); setOpen(false) }}>Cancelar</Button>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-5\">\n <section className=\"space-y-4 rounded-md border p-4\">\n <ToggleRow title=\"NFS-e — Nota de Serviço\" description=\"Padrão nacional (RJ, Vitória e demais aderentes)\"\n checked={!!draft.nfse_enabled} onChange={(v) => set({ nfse_enabled: v })}>\n <EnvSelect value={!!draft.nfse_production} onChange={(v) => set({ nfse_production: v })} disabled={!draft.nfse_enabled} />\n </ToggleRow>\n {draft.nfse_enabled && (\n <div className=\"fz-container space-y-4\">\n <div className=\"fz-fields fz-fields-2 gap-4\">\n <Field label=\"Cód. tributação nacional\"><Input value={draft.nfse_service_code_national ?? ''} placeholder=\"ex.: 06.02.01\" onChange={(e) => set({ nfse_service_code_national: e.target.value })} /></Field>\n <Field label=\"Cód. tributação municipal\"><Input value={draft.nfse_service_code_municipal ?? ''} placeholder=\"ex.: 001\" onChange={(e) => set({ nfse_service_code_municipal: e.target.value })} /></Field>\n <Field label=\"Código NBS\"><Input value={draft.nfse_nbs_code ?? ''} placeholder=\"ex.: 1.2602.90.00\" onChange={(e) => set({ nfse_nbs_code: e.target.value })} /></Field>\n <Field label=\"CNAE do serviço\"><Input value={draft.nfse_cnae ?? ''} placeholder=\"ex.: 9602-5/02\" onChange={(e) => set({ nfse_cnae: e.target.value })} /></Field>\n <Field label=\"Alíquota ISS (%)\"><Input inputMode=\"decimal\" value={draft.nfse_iss_rate ?? ''} placeholder=\"ex.: 5\" onChange={(e) => set({ nfse_iss_rate: e.target.value })} /></Field>\n <Field label=\"Tributação ISS\">\n <Select value={draft.nfse_iss_taxation != null ? String(draft.nfse_iss_taxation) : undefined} onValueChange={(v) => set({ nfse_iss_taxation: v })}>\n <SelectTrigger><SelectValue placeholder=\"Selecione\" /></SelectTrigger>\n <SelectContent>{ISS_TAXATION.map((o) => <SelectItem key={o.value} value={o.value}>{o.label}</SelectItem>)}</SelectContent>\n </Select>\n </Field>\n <Field label=\"IBS/CBS — CST\"><Input value={draft.nfse_ibscbs_cst ?? ''} placeholder=\"ex.: 000\" onChange={(e) => set({ nfse_ibscbs_cst: e.target.value })} /></Field>\n <Field label=\"IBS/CBS — Classificação\"><Input value={draft.nfse_ibscbs_classification ?? ''} placeholder=\"ex.: 000001\" onChange={(e) => set({ nfse_ibscbs_classification: e.target.value })} /></Field>\n {isSimples && (\n <Field label=\"Apuração dos tributos no Simples\">\n <Select value={draft.nfse_simples_regime != null ? String(draft.nfse_simples_regime) : 'auto'} onValueChange={(v) => set({ nfse_simples_regime: v })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>{SIMPLES_REGIME.map((o) => <SelectItem key={o.value} value={o.value}>{o.label}</SelectItem>)}</SelectContent>\n </Select>\n </Field>\n )}\n </div>\n <ToggleRow title=\"Emitir pelo valor líquido\" checked={!!draft.nfse_net_value} onChange={(v) => set({ nfse_net_value: v })} />\n <Field label=\"Informações complementares da nota\">\n <Input value={draft.nfse_additional_info ?? ''} placeholder=\"ex.: Totais Aproximados dos Tributos cfe. Lei nº 12.741/2012…\" onChange={(e) => set({ nfse_additional_info: e.target.value })} />\n </Field>\n </div>\n )}\n </section>\n\n <section className=\"space-y-4 rounded-md border p-4\">\n <ToggleRow title=\"NFC-e — Cupom do Consumidor\" description=\"Produtos / comanda\"\n checked={!!draft.nfce_enabled} onChange={(v) => set({ nfce_enabled: v })}>\n <EnvSelect value={!!draft.nfce_production} onChange={(v) => set({ nfce_production: v })} disabled={!draft.nfce_enabled} />\n </ToggleRow>\n {draft.nfce_enabled && (\n <div className=\"fz-container space-y-4\">\n <div className=\"fz-fields fz-fields-2 gap-4\">\n <Field label=\"Série\"><Input inputMode=\"numeric\" value={draft.nfce_series ?? ''} onChange={(e) => set({ nfce_series: e.target.value.replace(/\\D/g, '') })} /></Field>\n <Field label=\"CSC — ID\"><Input value={draft.nfce_csc_id ?? ''} onChange={(e) => set({ nfce_csc_id: e.target.value })} /></Field>\n </div>\n <Field label=\"CSC — Token\" hint=\"O CSC (id numérico + token) é gerado no portal da SEFAZ do estado — não é o login de nenhum sistema.\">\n <Input type=\"password\" value={cscToken} placeholder={row.nfce_csc_token_set ? '•••••••• (configurado — digite para trocar)' : ''} onChange={(e) => setCscToken(e.target.value)} />\n </Field>\n <div className=\"fz-fields fz-fields-2 gap-4\">\n <Field label=\"Item genérico — NCM\"><Input value={generic.ncm ?? ''} onChange={(e) => setGeneric({ ncm: e.target.value })} /></Field>\n <Field label=\"Item genérico — CFOP\"><Input value={generic.cfop ?? ''} onChange={(e) => setGeneric({ cfop: e.target.value })} /></Field>\n <Field label=\"Item genérico — CSOSN/CST\"><Input value={generic.csosn ?? ''} onChange={(e) => setGeneric({ csosn: e.target.value })} /></Field>\n </div>\n </div>\n )}\n </section>\n\n <ul className=\"flex flex-wrap gap-2\">\n {checks.map((c) => (\n <li key={c.label}>\n <Badge variant=\"outline\" className={c.ok ? 'gap-1 border-emerald-500/40 text-emerald-700 dark:text-emerald-400' : 'gap-1 text-muted-foreground'}>\n {c.ok ? <Check className=\"h-3 w-3\" /> : <X className=\"h-3 w-3\" />}{c.label}\n </Badge>\n </li>\n ))}\n </ul>\n\n <div className=\"flex flex-wrap items-center justify-end gap-3\">\n <p className=\"mr-auto text-xs text-muted-foreground\">\n Registrar a empresa no emissor ainda não está disponível nesta versão — a configuração fica salva para quando estiver.\n </p>\n <Button onClick={() => void onSave()} disabled={saving}>{saving ? 'Salvando…' : 'Salvar configuração'}</Button>\n </div>\n </CardContent>\n </Card>\n )\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport { getActiveTenantId } from '@fayz-ai/admin'\nimport type { IssuedNote, IssuedNoteEvent } from '../lib/issued-note'\n\nfunction sb() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not initialized')\n return supabase\n}\n\nconst NOTE_COLUMNS = `document_id, model, status, environment, number, series, access_key,\n verification_code, provider_integration_id, total_value, recipient_snapshot, rejection_payload,\n created_at, authorized_at, cancelled_at, cancel_reason`\n\nfunction toNote(r: any): IssuedNote {\n return {\n documentId: r.document_id,\n model: r.model,\n status: r.status,\n environment: r.environment ?? null,\n number: r.number ?? null,\n series: r.series ?? null,\n accessKey: r.access_key ?? null,\n verificationCode: r.verification_code ?? null,\n integrationId: r.provider_integration_id ?? null,\n totalValue: r.total_value == null ? null : Number(r.total_value),\n recipient: r.recipient_snapshot ?? null,\n rejection: r.rejection_payload ?? null,\n createdAt: r.created_at,\n authorizedAt: r.authorized_at ?? null,\n cancelledAt: r.cancelled_at ?? null,\n cancelReason: r.cancel_reason ?? null,\n }\n}\n\n/**\n * The notes of a financial invoice, reached through its order: a note covers\n * orders (N:N `plg_fiscalbr_document_orders`) or was issued straight from one\n * (`plg_fiscalbr_documents.order_id`, the restaurant tab).\n */\nexport async function listInvoiceNotes(invoiceId: string): Promise<IssuedNote[]> {\n const db = sb()\n const { data: inv, error: invError } = await db.from('plg_financial_invoices')\n .select('order_id').eq('id', invoiceId).maybeSingle()\n if (invError) throw invError\n const orderId: string | null = inv?.order_id ?? null\n if (!orderId) return []\n\n const [linked, direct] = await Promise.all([\n db.from('plg_fiscalbr_document_orders').select('document_id').eq('order_id', orderId),\n db.from('plg_fiscalbr_documents').select(NOTE_COLUMNS).eq('order_id', orderId),\n ])\n if (linked.error) throw linked.error\n if (direct.error) throw direct.error\n\n const byId = new Map<string, IssuedNote>()\n for (const r of direct.data ?? []) byId.set(r.document_id, toNote(r))\n const missing = (linked.data ?? []).map((r: any) => r.document_id as string).filter((id: string) => !byId.has(id))\n if (missing.length) {\n const { data, error } = await db.from('plg_fiscalbr_documents').select(NOTE_COLUMNS).in('document_id', missing)\n if (error) throw error\n for (const r of data ?? []) byId.set(r.document_id, toNote(r))\n }\n return [...byId.values()].sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n}\n\nexport async function listNoteEvents(documentId: string): Promise<IssuedNoteEvent[]> {\n const { data, error } = await sb().from('plg_fiscalbr_document_events')\n .select('id, event_type, status, justification, created_at')\n .eq('document_id', documentId)\n .order('created_at', { ascending: false })\n .limit(30)\n if (error) throw error\n return (data ?? []).map((e: any) => ({\n id: e.id, eventType: e.event_type, status: e.status ?? null,\n justification: e.justification ?? null, createdAt: e.created_at,\n }))\n}\n\nasync function callIssuer(body: Record<string, unknown>): Promise<any> {\n // Edge functions never get the tenant header (client.ts); it rides in the body.\n const { data, error } = await sb().functions.invoke('fiscalbr-plugnotas', { body: { ...body, tenantId: getActiveTenantId() } })\n if (error) {\n // The function's own message lives in the response body, not in `error.message`.\n const ctx = (error as any)?.context\n let message = error.message || 'Falha ao falar com o emissor fiscal.'\n if (ctx && typeof ctx.json === 'function') {\n try { const b = await ctx.json(); if (b?.error) message = String(b.error) } catch { /* keep generic */ }\n }\n throw new Error(message)\n }\n if (data?.error) throw new Error(String(data.error))\n return data\n}\n\n/** Asks the provider for the note's current state; returns the stored status. */\nexport async function refreshNote(documentId: string): Promise<string> {\n const r = await callIssuer({ action: 'poll_status', document_id: documentId })\n return String(r?.status ?? '')\n}\n\nexport async function cancelNote(documentId: string, justification: string, code?: string): Promise<string> {\n const r = await callIssuer({ action: 'cancel', document_id: documentId, justification, code })\n return String(r?.status ?? '')\n}\n\nexport async function fetchNotePdf(documentId: string): Promise<Blob> {\n const data = await callIssuer({ action: 'get_pdf', document_id: documentId })\n if (!(data instanceof Blob)) throw new Error('O emissor não devolveu um PDF.')\n return new Blob([data], { type: 'application/pdf' })\n}\n","// Vocabulary and reading rules for an issued note (plg_fiscalbr_documents),\n// shared by every screen that shows one.\n\nexport type IssuedNoteModel = 'nfse' | 'nfce' | 'nfe'\nexport type IssuedNoteStatus =\n | 'draft' | 'processing' | 'authorized' | 'rejected' | 'error' | 'cancelled' | 'substituted' | 'denied'\n\nexport interface IssuedNote {\n documentId: string\n model: IssuedNoteModel\n status: IssuedNoteStatus\n environment: 'producao' | 'homologacao' | null\n number: string | null\n series: string | null\n accessKey: string | null\n verificationCode: string | null\n integrationId: string | null\n totalValue: number | null\n recipient: Record<string, unknown> | null\n rejection: unknown\n createdAt: string\n authorizedAt: string | null\n cancelledAt: string | null\n cancelReason: string | null\n}\n\nexport interface IssuedNoteEvent {\n id: string\n eventType: string\n status: string | null\n justification: string | null\n createdAt: string\n}\n\nexport const MODEL_LABEL: Record<IssuedNoteModel, string> = { nfse: 'NFS-e', nfce: 'NFC-e', nfe: 'NF-e' }\n\nexport type StatusTone = 'success' | 'warning' | 'danger' | 'muted'\n\nexport const STATUS_META: Record<IssuedNoteStatus, { label: string; tone: StatusTone }> = {\n authorized: { label: 'Autorizada', tone: 'success' },\n draft: { label: 'Enviando', tone: 'warning' },\n processing: { label: 'Processando', tone: 'warning' },\n rejected: { label: 'Rejeitada', tone: 'danger' },\n denied: { label: 'Denegada', tone: 'danger' },\n error: { label: 'Erro', tone: 'danger' },\n cancelled: { label: 'Cancelada', tone: 'muted' },\n substituted: { label: 'Substituída', tone: 'muted' },\n}\n\nexport const EVENT_LABEL: Record<string, string> = {\n emissao: 'Emissão enviada',\n consulta: 'Consulta de status',\n cancelamento: 'Cancelamento',\n substituicao: 'Substituição',\n cce: 'Carta de correção',\n inutilizacao: 'Inutilização',\n webhook: 'Notificação do emissor fiscal',\n erro: 'Erro',\n}\n\n// Provider/V1 words on the trail. Internal steps (nfce_start…) have no\n// translation on purpose: they show nothing rather than the raw code.\nconst EVENT_STATUS_LABEL: Record<string, string> = {\n CRIADO: 'Enviando', PROCESSANDO: 'Processando', CONCLUIDO: 'Autorizada', REJEITADO: 'Rejeitada',\n DENEGADO: 'Denegada', CANCELADO: 'Cancelada', SUBSTITUIDO: 'Substituída', SOLICITADO: 'Solicitado', ERRO: 'Erro',\n}\n\nexport function eventStatusLabel(status: string | null): string | null {\n return status ? EVENT_STATUS_LABEL[status.toUpperCase()] ?? null : null\n}\n\nconst IN_FLIGHT: IssuedNoteStatus[] = ['draft', 'processing']\nconst WITHOUT_EFFECT: IssuedNoteStatus[] = ['rejected', 'denied', 'error', 'cancelled', 'substituted']\n\nexport function isWithoutEffect(status: IssuedNoteStatus): boolean {\n return WITHOUT_EFFECT.includes(status)\n}\n\n/** A cancellation in progress sits in `processing` exactly like an issue in progress. */\nexport function statusLabel(note: Pick<IssuedNote, 'status' | 'cancelledAt'>): string {\n if (IN_FLIGHT.includes(note.status) && note.cancelledAt) return 'Cancelamento solicitado'\n return (STATUS_META[note.status] ?? STATUS_META.error).label\n}\n\nexport interface NotesSummary {\n hasValid: boolean\n withoutEffect: number\n inFlight: number\n /** Only an AUTHORIZED test note misleads; a rejected one in homologação fools nobody. */\n validIsTest: boolean\n}\n\nexport function summarizeNotes(notes: Pick<IssuedNote, 'status' | 'environment'>[]): NotesSummary {\n const s: NotesSummary = { hasValid: false, withoutEffect: 0, inFlight: 0, validIsTest: false }\n for (const n of notes) {\n if (n.status === 'authorized') {\n s.hasValid = true\n if (n.environment === 'homologacao') s.validIsTest = true\n } else if (IN_FLIGHT.includes(n.status)) s.inFlight += 1\n else if (WITHOUT_EFFECT.includes(n.status)) s.withoutEffect += 1\n }\n return s\n}\n\nexport type NotesButtonState = 'none' | 'authorized' | 'processing' | 'failed-only'\n\nexport function notesButtonState(s: NotesSummary): NotesButtonState {\n if (s.hasValid) return 'authorized'\n if (s.inFlight > 0) return 'processing'\n if (s.withoutEffect > 0) return 'failed-only'\n return 'none'\n}\n\n// The SEFAZ message says what is wrong, never what to do. These codes each cost\n// a full diagnosis in the V1 (measured on tenant 1, 23-09-2026), so the hint\n// travels with the message.\nconst SEFAZ_HINTS: Array<[string, string]> = [\n ['E0120', 'no padrão nacional a Inscrição Municipal é opcional (a nota identifica pelo CNPJ). '\n + 'Apague a IM na configuração fiscal da unidade e emita de novo.'],\n ['E0312', 'geralmente falta o CÓDIGO DE TRIBUTAÇÃO DO MUNICÍPIO (3 dígitos) na configuração '\n + 'fiscal da unidade — não o nacional. Cada prefeitura tem a sua tabela; confirme o código '\n + 'com a contabilidade.'],\n ['E0314', 'o código de tributação do município não existe na tabela daquela prefeitura. '\n + 'Confirme o valor com a contabilidade da unidade — ele não é o mesmo em todo município. '\n + 'Fora do Rio de Janeiro, o normal é deixar esse campo VAZIO.'],\n ['E0084', 'o CNPJ não consta como estabelecido nesse município no cadastro nacional. '\n + 'Isso se resolve FORA do sistema: a empresa precisa ter inscrição municipal ativa na '\n + 'prefeitura e o endereço do CNPJ na Receita Federal apontando para o mesmo município. '\n + 'Fale com a contabilidade — não há o que ajustar aqui.'],\n]\n\nconst FIELD_LABELS: Record<string, string> = {\n 'prestador.cpfCnpj': 'CNPJ do emitente',\n 'tomador.cpfCnpj': 'CPF/CNPJ do cliente',\n 'tomador.razaoSocial': 'Nome do cliente',\n 'tomador.endereco.cep': 'CEP do cliente',\n 'tomador.endereco.codigoCidade': 'Município do cliente',\n 'servico.codigo': 'Código de tributação do serviço',\n 'servico.iss.aliquota': 'Alíquota de ISS',\n 'itens.ncm': 'NCM do produto',\n 'itens.cfop': 'CFOP do produto',\n 'pagamentos.meio': 'Forma de pagamento (tPag)',\n 'emitente.inscricaoMunicipal': 'Inscrição municipal',\n 'emitente.inscricaoEstadual': 'Inscrição estadual',\n}\n\nexport interface RejectionField { field: string; label: string; message: string }\n\n/** PlugNotas rejection payload ({error:{message,data:{fields}}}) → something a person can act on. */\nexport function explainRejection(rejection: unknown): { summary: string; fields: RejectionField[] } {\n if (!rejection) return { summary: 'Nota rejeitada sem detalhe do motivo.', fields: [] }\n const r = (Array.isArray(rejection) ? rejection[0] : rejection) as Record<string, any>\n const err = r?.error ?? r\n let message: string = String(err?.message || r?.mensagem || r?.motivo || 'Nota rejeitada.')\n // The national issuer embeds the reason as JSON inside the string.\n const embedded = message.match(/\\[\\s*\\{[\\s\\S]*\\}\\s*\\]/)\n if (embedded) {\n try {\n const arr = JSON.parse(embedded[0])\n const parts = (Array.isArray(arr) ? arr : [arr])\n .map((e: any) => [e.Codigo ?? e.codigo, e.Descricao ?? e.descricao ?? e.Mensagem ?? e.mensagem]\n .filter(Boolean).join(' — '))\n .filter(Boolean)\n if (parts.length) message = parts.join('; ')\n } catch { /* keep the raw message */ }\n }\n const hint = SEFAZ_HINTS.find(([code]) => message.includes(code))\n if (hint) message = `${message} — ${hint[1]}`\n\n const fieldsObj: Record<string, unknown> = err?.data?.fields ?? {}\n const fields = Object.entries(fieldsObj).map(([field, msg]) => {\n const normalized = field.replace(/\\[\\d+\\]/g, '').replace(/\\.\\d+\\./g, '.')\n return { field, label: FIELD_LABELS[normalized] ?? field, message: String(msg) }\n })\n return { summary: message, fields }\n}\n\nexport function recipientLabel(recipient: Record<string, unknown> | null): string {\n if (!recipient) return 'Consumidor final'\n if (recipient.consumidor) return 'Consumidor final'\n return String(recipient.razaoSocial ?? recipient.nome ?? recipient.cpfCnpj ?? 'Consumidor final')\n}\n","import React, { useCallback, useEffect, useState } from 'react'\nimport { AlertTriangle, CheckCircle2, ChevronDown, FileCheck2, FileText, Loader2, RefreshCw, XCircle } from 'lucide-react'\nimport {\n Badge, Button, Modal, ModalBody, ModalContent, ModalDescription, ModalHeader, ModalTitle, SegmentedControl, Skeleton,\n Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, toast,\n} from '@fayz-ai/ui'\nimport { usePermissionOptional } from '@fayz-ai/admin'\nimport { cancelNote, fetchNotePdf, listInvoiceNotes, listNoteEvents, refreshNote } from '../data/issued'\nimport {\n EVENT_LABEL, MODEL_LABEL, eventStatusLabel, STATUS_META, explainRejection, isWithoutEffect, notesButtonState,\n recipientLabel, statusLabel, summarizeNotes, type IssuedNote, type IssuedNoteEvent, type StatusTone,\n} from '../lib/issued-note'\nimport { describeError, formatCurrency } from '@fayz-ai/core'\n\nconst TONE_VARIANT: Record<StatusTone, 'success' | 'warning' | 'destructive' | 'default'> = {\n success: 'success', warning: 'warning', danger: 'destructive', muted: 'default',\n}\n\nconst dateTime = (v: string | null) => (v ? new Date(v).toLocaleString('pt-BR', { dateStyle: 'short', timeStyle: 'short' }) : '—')\n// The V1 kept only the day of authorization; a midnight here is \"no time known\", not 00:00.\nconst dayOrDateTime = (v: string | null) => {\n if (!v) return '—'\n const d = new Date(v)\n return d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0\n ? d.toLocaleDateString('pt-BR')\n : dateTime(v)\n}\nconst money = (v: number | null) => (v == null ? '—' : formatCurrency(v))\n\nfunction buttonHint(s: ReturnType<typeof summarizeNotes>): string {\n const parts = [s.hasValid ? 'Notas fiscais desta conta — há uma nota válida' : 'Notas fiscais desta conta']\n if (s.withoutEffect > 0) parts.push(`${s.withoutEffect} cancelada(s), rejeitada(s) ou com erro`)\n if (s.validIsTest) parts.push('a nota válida é de TESTE, sem valor fiscal')\n return parts.join(' · ')\n}\n\nexport interface InvoiceNotesButtonProps {\n invoiceId?: string\n direction?: string\n cancelled?: boolean\n}\n\n/** Header action of a receivable: the notes issued for it, as the V1's \"Nota Fiscal\" button. */\nexport function InvoiceNotesButton({ invoiceId, direction, cancelled }: InvoiceNotesButtonProps) {\n const [notes, setNotes] = useState<IssuedNote[] | null>(null)\n const [open, setOpen] = useState(false)\n const can = usePermissionOptional()\n // A cancelled invoice still lets a note be cancelled; only issuing stops there.\n const canCancel = can('financial', 'edit')\n\n const reload = useCallback(async () => {\n if (!invoiceId || direction !== 'credit') return\n try {\n setNotes(await listInvoiceNotes(invoiceId))\n } catch {\n // A fiscal read failing must not take the invoice screen down with it.\n setNotes((prev) => prev ?? [])\n }\n }, [invoiceId, direction])\n\n useEffect(() => { void reload() }, [reload])\n\n // Without emission in the V2 yet, an empty central would only say \"nothing here\".\n if (!notes || notes.length === 0) return null\n\n const summary = summarizeNotes(notes)\n const state = notesButtonState(summary)\n\n return (\n <>\n <TooltipProvider delayDuration={200}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"relative h-9 gap-1.5\" aria-label=\"Nota Fiscal\" onClick={() => setOpen(true)}>\n {state === 'authorized' ? (\n <CheckCircle2 className=\"h-4 w-4 text-success\" aria-hidden />\n ) : state === 'processing' ? (\n <Loader2 className=\"h-4 w-4 animate-spin text-warning\" aria-hidden />\n ) : (\n <FileCheck2 className=\"h-4 w-4\" aria-hidden />\n )}\n {/* A phone header has room for the screen title or this label, not both. */}\n <span className=\"hidden sm:inline\">Nota Fiscal</span>\n {summary.withoutEffect > 0 && (\n <span className=\"inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 text-[10px] font-bold text-destructive-foreground\">\n {summary.withoutEffect}\n </span>\n )}\n {summary.validIsTest && (\n <span className=\"rounded border border-destructive px-1 text-[10px] font-semibold text-destructive\">TESTE</span>\n )}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{buttonHint(summary)}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n\n <Modal open={open} onOpenChange={setOpen}>\n <ModalContent size=\"2xl\">\n <ModalHeader>\n <ModalTitle>Nota Fiscal</ModalTitle>\n <ModalDescription>Notas emitidas para esta conta.</ModalDescription>\n </ModalHeader>\n <ModalBody className=\"gap-2\">\n {notes.map((n) => <NoteRow key={n.documentId} note={n} canCancel={canCancel} onChanged={reload} />)}\n <p className=\"pt-2 text-xs text-muted-foreground\">Emitir uma nota nova por aqui chega na próxima etapa.</p>\n </ModalBody>\n </ModalContent>\n </Modal>\n </>\n )\n}\n\nconst POLL_DELAYS = [3000, 5000, 8000, 12000, 20000]\n\nfunction NoteRow({ note, canCancel, onChanged }: { note: IssuedNote; canCancel: boolean; onChanged: () => Promise<void> }) {\n const [expanded, setExpanded] = useState(false)\n const [cancelling, setCancelling] = useState(false)\n const [busy, setBusy] = useState<'pdf' | 'refresh' | null>(null)\n const dimmed = isWithoutEffect(note.status)\n const tone = (STATUS_META[note.status] ?? STATUS_META.error).tone\n const usable = note.status === 'authorized' || note.status === 'cancelled'\n const inFlight = note.status === 'processing' || note.status === 'draft'\n const cancellable = canCancel && note.status === 'authorized' && !note.cancelledAt\n\n const openPdf = async () => {\n // Open synchronously: a window opened after an await is a blocked pop-up.\n const w = window.open('', '_blank')\n setBusy('pdf')\n try {\n const blob = await fetchNotePdf(note.documentId)\n const url = URL.createObjectURL(blob)\n if (w) w.location.href = url\n else window.location.assign(url)\n } catch (e) {\n w?.close()\n toast.error('PDF indisponível', { description: describeError(e) })\n } finally {\n setBusy(null)\n }\n }\n\n const refresh = async () => {\n setBusy('refresh')\n try {\n const status = await refreshNote(note.documentId)\n await onChanged()\n toast(status === note.status ? 'Ainda em processamento na SEFAZ/prefeitura' : `Nota ${statusLabel({ status: status as IssuedNote['status'], cancelledAt: null }).toLowerCase()}`)\n } catch (e) {\n toast.error('Não foi possível consultar', { description: describeError(e) })\n } finally {\n setBusy(null)\n }\n }\n\n return (\n <div className={`rounded-lg border ${dimmed ? 'bg-muted/30' : ''}`}>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n className=\"font-normal whitespace-normal justify-start flex w-full items-center gap-2 p-3 text-left\"\n onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}\n >\n <span className=\"flex min-w-0 flex-1 flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{MODEL_LABEL[note.model] ?? note.model}</Badge>\n {note.number && <span className=\"font-mono text-sm\">nº {note.number}</span>}\n <Badge variant={TONE_VARIANT[tone]}>{statusLabel(note)}</Badge>\n {note.environment === 'homologacao' && (\n <span className=\"rounded border border-destructive px-1 text-[10px] font-semibold text-destructive\">TESTE</span>\n )}\n <span className=\"ml-auto text-xs tabular-nums text-muted-foreground\">{dateTime(note.createdAt)}</span>\n </span>\n <ChevronDown className={`h-4 w-4 shrink-0 text-muted-foreground transition-transform ${expanded ? 'rotate-180' : ''}`} aria-hidden />\n </Button>\n {note.cancelReason && !expanded && (\n <p className=\"flex items-start gap-1.5 px-3 pb-2 text-xs text-muted-foreground\">\n <AlertTriangle className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" aria-hidden />\n <span className=\"break-words\">Motivo: {note.cancelReason}</span>\n </p>\n )}\n\n {(usable || inFlight || note.cancelledAt) && !cancelling && (\n <div className=\"flex flex-wrap items-center gap-1.5 px-3 pb-3\">\n {usable && (\n <Button variant=\"outline\" size=\"sm\" className=\"h-7 text-xs\" disabled={busy === 'pdf'} onClick={openPdf}>\n {busy === 'pdf' ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden /> : <FileText className=\"h-3.5 w-3.5\" aria-hidden />}\n PDF\n </Button>\n )}\n {(inFlight || (note.cancelledAt && note.status === 'authorized')) && (\n <Button variant=\"outline\" size=\"sm\" className=\"h-7 text-xs\" disabled={busy === 'refresh'} onClick={refresh}>\n {busy === 'refresh' ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden /> : <RefreshCw className=\"h-3.5 w-3.5\" aria-hidden />}\n Atualizar\n </Button>\n )}\n {cancellable && (\n <Button variant=\"ghost\" size=\"sm\" className=\"ml-auto h-7 text-xs text-destructive hover:text-destructive\" onClick={() => setCancelling(true)}>\n <XCircle className=\"h-3.5 w-3.5\" aria-hidden /> Cancelar nota\n </Button>\n )}\n </div>\n )}\n\n {cancelling && (\n <CancelNotePanel note={note} onClose={() => setCancelling(false)} onDone={async () => { setCancelling(false); await onChanged() }} />\n )}\n {expanded && <NoteDetails note={note} />}\n </div>\n )\n}\n\nconst NFSE_REASONS = [\n { value: '1', label: 'Erro na emissão' },\n { value: '2', label: 'Serviço não prestado' },\n { value: '9', label: 'Outros' },\n] as const\n\n/** Inline, not a dialog over the central (no modal stacking). */\nfunction CancelNotePanel({ note, onClose, onDone }: { note: IssuedNote; onClose: () => void; onDone: () => Promise<void> }) {\n const isNfse = note.model === 'nfse'\n const [code, setCode] = useState<'1' | '2' | '9'>('2')\n const [text, setText] = useState('')\n const [working, setWorking] = useState<'sending' | 'waiting' | null>(null)\n const [error, setError] = useState<string | null>(null)\n // SEFAZ requires 15 characters on NFC-e; the V1 asks 10 on NFS-e so the history keeps a real reason.\n const min = isNfse ? 10 : 15\n const missing = Math.max(0, min - text.trim().length)\n\n const confirm = async () => {\n setError(null)\n setWorking('sending')\n try {\n let status = await cancelNote(note.documentId, text.trim(), isNfse ? code : undefined)\n // City halls confirm later; follow for a while, as the V1 does.\n setWorking('waiting')\n for (const delay of POLL_DELAYS) {\n if (status === 'cancelled' || status === 'authorized') break\n await new Promise((r) => setTimeout(r, delay))\n try { status = await refreshNote(note.documentId) } catch { /* transient */ }\n }\n if (status === 'cancelled') toast.success(`${MODEL_LABEL[note.model]} nº ${note.number ?? ''} cancelada`)\n else if (status === 'authorized') toast.error('A SEFAZ/prefeitura recusou o cancelamento', { description: 'A nota continua válida. Veja o histórico nos detalhes.' })\n else toast('Cancelamento solicitado', { description: 'A SEFAZ/prefeitura ainda está processando. Use «Atualizar» para conferir.' })\n await onDone()\n } catch (e) {\n setError(describeError(e))\n setWorking(null)\n }\n }\n\n return (\n <div className=\"space-y-3 border-t bg-destructive-soft/40 px-3 py-3\">\n <p className=\"text-sm font-semibold\">Cancelar {MODEL_LABEL[note.model]} {note.number ? `nº ${note.number}` : ''}</p>\n <p className=\"text-xs text-muted-foreground\">\n {isNfse\n ? 'O prazo de cancelamento da NFS-e é definido pelo município.'\n : 'O prazo de cancelamento da NFC-e é curto (em geral ~30 minutos após a autorização, conforme a UF). Fora do prazo, a SEFAZ recusa.'}\n {' '}Cancelar não pode ser desfeito.\n </p>\n {isNfse && (\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium\">Motivo</p>\n <SegmentedControl size=\"sm\" aria-label=\"Motivo do cancelamento\" options={NFSE_REASONS} value={code} onChange={setCode} />\n </div>\n )}\n <div className=\"space-y-1\">\n <label htmlFor={`cancel-${note.documentId}`} className=\"text-xs font-medium\">Justificativa</label>\n <textarea\n id={`cancel-${note.documentId}`}\n value={text}\n onChange={(e) => setText(e.target.value)}\n maxLength={255}\n rows={3}\n disabled={!!working}\n placeholder={isNfse ? 'Descreva o motivo…' : 'Ex.: Emissão em duplicidade por erro operacional'}\n className=\"w-full resize-y rounded-md border bg-background px-3 py-2 text-sm\"\n autoFocus\n />\n <p className=\"text-[11px] text-muted-foreground\">\n {missing > 0 ? `Faltam ${missing} caractere(s) — a justificativa vai para a SEFAZ/prefeitura.` : 'Vai para a SEFAZ/prefeitura junto do pedido.'}\n </p>\n </div>\n {error && (\n <p className=\"flex items-start gap-1.5 rounded-md border border-destructive/40 bg-destructive-soft p-2 text-xs text-destructive-soft-foreground\">\n <AlertTriangle className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" aria-hidden /> <span className=\"break-words\">{error}</span>\n </p>\n )}\n <div className=\"flex flex-wrap justify-end gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={onClose} disabled={!!working}>Voltar</Button>\n <Button variant=\"destructive\" size=\"sm\" onClick={confirm} disabled={!!working || missing > 0}>\n {working ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden /> : <XCircle className=\"h-3.5 w-3.5\" aria-hidden />}\n {working === 'waiting' ? 'Aguardando a SEFAZ/prefeitura…' : working ? 'Enviando…' : 'Confirmar cancelamento'}\n </Button>\n </div>\n </div>\n )\n}\n\nfunction NoteDetails({ note }: { note: IssuedNote }) {\n const [events, setEvents] = useState<IssuedNoteEvent[] | null>(null)\n useEffect(() => {\n let alive = true\n listNoteEvents(note.documentId).then((e) => { if (alive) setEvents(e) }).catch(() => { if (alive) setEvents([]) })\n return () => { alive = false }\n }, [note.documentId])\n\n const failed = ['rejected', 'denied', 'error'].includes(note.status)\n const rejection = failed ? explainRejection(note.rejection) : null\n const rows: Array<[string, React.ReactNode]> = [\n ['Referência', note.integrationId && <span className=\"break-all font-mono text-xs\">{note.integrationId}</span>],\n ['Chave de acesso', note.accessKey && <span className=\"break-all font-mono text-xs\">{note.accessKey}</span>],\n ['Código de verificação', note.verificationCode],\n ['Valor', money(note.totalValue)],\n ['Tomador', recipientLabel(note.recipient)],\n ['Criada em', dateTime(note.createdAt)],\n ['Autorizada em', note.authorizedAt && dayOrDateTime(note.authorizedAt)],\n ['Cancelada em', note.cancelledAt && `${dateTime(note.cancelledAt)}${note.cancelReason ? ` — ${note.cancelReason}` : ''}`],\n ]\n\n return (\n <div className=\"space-y-3 border-t px-3 py-3\">\n <dl className=\"text-sm\">\n {rows.filter(([, v]) => v).map(([label, value]) => (\n <div key={label} className=\"flex gap-3 border-b py-1.5 last:border-0\">\n <dt className=\"w-28 shrink-0 text-muted-foreground sm:w-36\">{label}</dt>\n <dd className=\"min-w-0 flex-1 break-words font-medium\">{value}</dd>\n </div>\n ))}\n </dl>\n\n {rejection && (\n <div className=\"space-y-1.5 rounded-md border border-destructive/40 bg-destructive-soft p-3\">\n <p className=\"text-sm font-semibold text-destructive-soft-foreground\">Por que foi rejeitada?</p>\n <p className=\"text-sm text-foreground\">{rejection.summary}</p>\n {rejection.fields.length > 0 && (\n <ul className=\"space-y-1 text-xs text-foreground\">\n {rejection.fields.map((f) => <li key={f.field}><span className=\"font-medium\">{f.label}:</span> {f.message}</li>)}\n </ul>\n )}\n </div>\n )}\n\n {events === null ? (\n <div className=\"space-y-1.5\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n ) : events.length > 0 && (\n <div>\n <p className=\"mb-1.5 text-sm font-semibold\">Histórico</p>\n <ul className=\"space-y-1\">\n {events.map((e) => (\n <li key={e.id} className=\"flex flex-wrap items-center gap-2 text-xs\">\n <span className=\"whitespace-nowrap tabular-nums text-muted-foreground\">{dateTime(e.createdAt)}</span>\n <Badge variant=\"outline\" className=\"text-[10px]\">{EVENT_LABEL[e.eventType] ?? 'Evento'}</Badge>\n {eventStatusLabel(e.status) && <span className=\"text-muted-foreground\">{eventStatusLabel(e.status)}</span>}\n {e.justification && <span className=\"min-w-0 truncate\">— {e.justification}</span>}\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n )\n}\n","import type { FinancialDataProvider } from '@fayz-ai/financial/data/provider'\nimport type { PlugNotasFinancialProviderOptions } from '../types'\n\ntype FiscalDocument = NonNullable<Awaited<ReturnType<NonNullable<FinancialDataProvider['getNotaById']>>>>\n\nfunction fiscalReader(provider: FinancialDataProvider) {\n if (!provider.getNotaById) throw new Error('PlugNotas requires fiscal document reads from Financial.')\n return provider.getNotaById.bind(provider)\n}\n\nasync function committed(read: (id: string) => Promise<FiscalDocument | null>, id: string) {\n const document = await read(id)\n if (!document) throw new Error('Fiscal document was not found after the server operation.')\n return document\n}\n\nfunction resultError(result: { status: string; message?: string }, document: FiscalDocument, fallback: string) {\n if (result.status !== 'error') return\n throw new Error(result.message?.trim() || document.errorMessage?.trim() || fallback)\n}\n\nfunction cancellationPending(metadata: Record<string, unknown> | undefined): boolean {\n const provider = metadata?.plugnotas\n if (!provider || typeof provider !== 'object' || Array.isArray(provider)) return false\n return (provider as Record<string, unknown>).cancellationPending === true\n}\n\nfunction artifactUrl(value: unknown): string {\n if (typeof value !== 'string' || !value.trim()) throw new Error('PlugNotas returned an invalid artifact URL.')\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n throw new Error('PlugNotas returned an invalid artifact URL.')\n }\n if (!['http:', 'https:'].includes(parsed.protocol)) throw new Error('PlugNotas returned an invalid artifact URL.')\n return parsed.toString()\n}\n\n/**\n * Decorates Financial without creating another fiscal ledger. The gateway only\n * requests server operations; every result returned to the UI is read back\n * from the server-committed `plg_financial_nfe` row.\n */\nexport function createPlugNotasFinancialProvider(\n options: PlugNotasFinancialProviderOptions,\n): FinancialDataProvider {\n const { base, gateway } = options\n\n const issueNota: NonNullable<FinancialDataProvider['issueNota']> = async (id) => {\n const read = fiscalReader(base)\n const document = await read(id)\n if (!document) throw new Error('Fiscal document not found.')\n if (document.model !== 'nfce') throw new Error('PlugNotas currently authorizes NFC-e only.')\n if (!document.orderId?.trim()) throw new Error('PlugNotas NFC-e must be created from an order.')\n if (!['draft', 'error'].includes(document.status)) return document\n const result = await gateway.issue({ notaId: id, idempotencyKey: `nfce:${id}` })\n const saved = await committed(read, id)\n resultError(result, saved, 'PlugNotas could not issue this NFC-e.')\n return saved\n }\n\n const refreshNota: NonNullable<FinancialDataProvider['refreshNota']> = async (id) => {\n const read = fiscalReader(base)\n const document = await read(id)\n if (!document) throw new Error('Fiscal document not found.')\n if (!['processing', 'error'].includes(document.status) && !cancellationPending(document.metadata)) return document\n const result = await gateway.refresh({ notaId: id })\n const saved = await committed(read, id)\n resultError(result, saved, 'PlugNotas could not refresh this NFC-e.')\n return saved\n }\n\n const cancelNota: NonNullable<FinancialDataProvider['cancelNota']> = async (id, reason) => {\n const read = fiscalReader(base)\n const document = await read(id)\n if (!document) throw new Error('Fiscal document not found.')\n if (document.status !== 'issued') throw new Error('Only an issued NFC-e can be cancelled.')\n if (cancellationPending(document.metadata)) throw new Error('NFC-e cancellation is already in progress.')\n const normalized = reason?.trim() ?? ''\n if (normalized.length < 15 || normalized.length > 255) {\n throw new Error('Cancellation reason must contain between 15 and 255 characters.')\n }\n const result = await gateway.cancel({ notaId: id, reason: normalized })\n const saved = await committed(read, id)\n resultError(result, saved, 'PlugNotas could not cancel this NFC-e.')\n return saved\n }\n\n const getNotaArtifactUrl: NonNullable<FinancialDataProvider['getNotaArtifactUrl']> = async (id, kind) => {\n const read = fiscalReader(base)\n const document = await read(id)\n if (!document) throw new Error('Fiscal document not found.')\n if (!['issued', 'cancelled'].includes(document.status)) {\n throw new Error('Fiscal artifacts are available only after authorization.')\n }\n if (kind === 'cancellation_xml' && document.status !== 'cancelled') {\n throw new Error('Cancellation XML is available only after cancellation.')\n }\n return artifactUrl((await gateway.artifact({ notaId: id, kind })).url)\n }\n\n return new Proxy(base, {\n get(target, property, receiver) {\n if (property === 'issueNota') return issueNota\n if (property === 'refreshNota') return refreshNota\n if (property === 'cancelNota') return cancelNota\n if (property === 'getNotaArtifactUrl') return getNotaArtifactUrl\n return Reflect.get(target, property, receiver)\n },\n })\n}\n","// ---------------------------------------------------------------------------\n// As telas que ainda não existem, com o que se sabe sobre cada uma.\n// ---------------------------------------------------------------------------\n// Tudo aqui saiu de medição no V1 de produção da Artorius (tenant 12) entre\n// 29 e 30/09/2026 — o rastro de auditoria da LAISSA FLOR, que é quem lança. Os\n// números não são estimativa: são quantas vezes ela fez aquilo.\n// ---------------------------------------------------------------------------\nimport React from 'react'\nimport { ComingSoon } from '@fayz-ai/ui'\n\n/**\n * Grupos Fiscais — a 5ª tela do grupo no V1. Na V2 o grupo fiscal já existe como\n * CADASTRO (`fiscalRegistries`), só não tem porta aqui dentro.\n */\nexport function TaxGroupsView({ onBack }: { onBack?: () => void } = {}) {\n return (\n <ComingSoon\n title=\"Grupos Fiscais\"\n summary=\"Perfis tributários reutilizáveis — CFOP, CSOSN/CST, PIS, COFINS, ICMS — que os produtos usam na emissão.\"\n v1Path=\"Estoque → Notas Fiscais → Grupos Fiscais\"\n measured=\"Vazio no V1 da Artorius («Nenhum grupo fiscal cadastrado»), coerente com eles não emitirem nota. O Pertinho do Céu e o Espaço Facial têm 11 entre os dois.\"\n missing={[\n 'Trazer o cadastro para dentro do grupo: a tabela plg_fiscalbr_tax_groups já existe e já recebeu os 11 grupos do V1',\n 'Hoje ele só aparece na lista genérica de cadastros, longe de onde a nota é usada',\n 'Só faz sentido junto com Notas Emitidas — grupo fiscal é insumo de emissão',\n ]}\n onBack={onBack}\n backTo=\"Notas Fiscais\"\n />\n )\n}\n\n/** Notas Emitidas — no V1 FUNCIONA, e é o gap maior dos dois. */\nexport function IssuedNotesView({ onBack }: { onBack?: () => void } = {}) {\n return (\n <ComingSoon\n title=\"Notas Emitidas\"\n summary=\"As NF-e, NFS-e e NFC-e que a casa emitiu, com o estado de cada uma na SEFAZ — autorizada, processando, rejeitada ou cancelada — e a comanda ou fatura que deu origem a ela.\"\n v1Path=\"Estoque → Notas Fiscais → Notas Emitidas\"\n measured=\"A Artorius não emite nota hoje: em 80 documentos recebidos, zero emitidos. Quem emite é o Pertinho do Céu e o Espaço Facial.\"\n missing={[\n 'Ligar o emissor da PlugNotas a este CNPJ (o certificado A1 já está lá desde maio; falta a credencial chegar neste ambiente)',\n 'A lista com o estado na SEFAZ e o rastro de tentativas — as tabelas já existem (plg_fiscalbr_nfce_jobs, _events)',\n 'Abrir o XML autorizado e o DANFE de cada nota',\n 'Cancelar uma nota emitida, com justificativa',\n ]}\n onBack={onBack}\n backTo=\"Notas Fiscais\"\n />\n )\n}\n\n/** Notas Devolvidas — no V1 é STUB, e a tela diz isso. */\nexport function ReturnedNotesView({ onBack }: { onBack?: () => void } = {}) {\n return (\n <ComingSoon\n title=\"Notas Devolvidas\"\n summary=\"As notas fiscais de devolução: o que voltou para o fornecedor, e o que isso desfaz no estoque e na conta a pagar.\"\n v1Path=\"Estoque → Notas Fiscais → Notas Devolvidas\"\n v1AlsoMissing\n missing={[\n 'Decidir o gesto: devolver a nota INTEIRA ou só algumas linhas dela',\n 'A devolução ESTORNA o estoque que a entrada criou — e o movimento de estorno já existe no V2 (reverses_movement_id)',\n 'E abate o título a pagar, ou gera um crédito com o fornecedor. É decisão de produto, não de código',\n 'Emitir a NF-e de devolução exige emissor ligado — mesma dependência de Notas Emitidas',\n ]}\n onBack={onBack}\n backTo=\"Notas Fiscais\"\n />\n )\n}\n\n","// ---------------------------------------------------------------------------\n// O grupo «Notas Fiscais», pronto para o Estoque montar.\n// ---------------------------------------------------------------------------\n// O V1 agrupa CINCO telas sob «Notas Fiscais», dentro do Estoque:\n//\n// Manifesto de Notas funciona (118 pendentes lá)\n// Entrada de Notas funciona — é o grosso do trabalho\n// Grupos Fiscais funciona, vazio (é cadastro, e no V2 entra como registry)\n// Notas Emitidas funciona no V1, falta aqui\n// Notas Devolvidas STUB no V1 também\n//\n// Aqui vão as quatro que são TELA. O app chama isto em\n// `createInventoryPlugin({ extraViews: [inboundNotesInventoryView()] })`, e o\n// operador acha tudo onde sempre achou: dentro do Estoque.\n//\n// As que não funcionam não são escondidas. Quem não vê a função conclui que o V2\n// não a tem — e descobrimos isso pelo suporte, não pelo plano.\n// ---------------------------------------------------------------------------\nimport React from 'react'\nimport { registerDocumentOpener } from '@fayz-ai/admin'\nimport { ModalBody, ModalHeader, ModalTitle, Skeleton } from '@fayz-ai/ui'\nimport { findInboxNoteByNumber, findInboxNoteByOperation } from '../data/inbox'\nimport { NoteReconcileView } from './NoteReconcileView'\nimport { InboundNotesPage, type InboundNotesPageProps } from './InboundNotesPage'\nimport { IssuedNotesView, ReturnedNotesView, TaxGroupsView } from './GapScreens'\nimport { describeError } from '@fayz-ai/core'\n\nexport function inboundNotesInventoryView(options: InboundNotesPageProps = {}) {\n // DE NOVO AQUI, e não por descuido: o pacote declara `sideEffects: false`, o\n // que autoriza o empacotador a descartar o registro do topo do módulo se nada\n // mais for importado dele. Esta função é chamada por todo app que monta o\n // grupo de notas — é o ponto que não some.\n registerDocumentOpener(NFE_OPENER)\n return {\n id: 'inbound-notes',\n label: 'Notas Fiscais',\n icon: 'FileText',\n // O nome do V1 para a fila de notas de compra. «Entrada» era o nome genérico\n // que o Estoque dá a qualquer tela emprestada, e dizia menos do que a tela faz.\n defaultChildLabel: 'Manifesto de Notas',\n render: () => <InboundNotesPage {...options} />,\n // A ordem é a do V1: Grupos Fiscais vem antes das duas de emissão, que é\n // onde ele é usado.\n //\n // Bonificação NÃO é aba. Ela chegou aqui por engano meu: no V1 não existe\n // esse menu — a bonificação é uma NATUREZA DE OPERAÇÃO que vem escrita na\n // nota (57 delas, em 11 grafias), e o que ela muda é o comportamento da\n // entrada: a mercadoria soma ao estoque e NÃO abre conta a pagar. O aviso\n // continua onde serve, na conciliação da nota. Uma tela vazia para um\n // comportamento é um menu que promete o que não vai entregar.\n children: [\n { id: 'tax-groups', label: 'Grupos Fiscais', render: () => <TaxGroupsView /> },\n { id: 'issued-notes', label: 'Notas Emitidas', render: () => <IssuedNotesView /> },\n { id: 'returned-notes', label: 'Notas Devolvidas', render: () => <ReturnedNotesView /> },\n ],\n }\n}\n\n/**\n * A NOTA que originou um movimento de estoque, dentro do modal que o Estoque abre.\n *\n * O Estoque guarda `operation_id` no movimento e não sabe o que é uma NF-e; esta\n * é a peça que faz a ponte — `plg_fiscalbr_inbox_documents.inventory_operation_id`\n * aponta para a mesma operação. A resolução é assíncrona (só o banco sabe qual\n * nota é), então o modal abre com esqueleto e preenche.\n *\n * Abre em MODAL e não em rota porque o documento é uma consulta, não um destino:\n * quem está percorrendo o razão clica no motivo para conferir e volta para onde\n * estava — e uma rota desmontaria a lista inteira para remontá-la sem o recorte.\n */\nexport function InboundNoteDocumentModal({ movement, onClose }: {\n movement: { operationId?: string; documentNumber?: string; reason?: string }\n onClose: () => void\n}) {\n const [noteId, setNoteId] = React.useState<string | null>(null)\n const [erro, setErro] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n let vivo = true\n // DUAS PORTAS, nesta ordem. A operação é o vínculo forte — a entrada que a V2\n // aceitou aponta para ela. O NÚMERO é o das linhas importadas do V1, que\n // trazem «NF-e 10592» escrito no motivo e vínculo nenhum: o importador copiou\n // o movimento e não a ligação. Sem a segunda porta, 3.088 linhas deste\n // cluster ficariam sem o link que o V1 tem.\n const numero = nfeNumberOf(movement)\n const busca = movement.operationId\n ? findInboxNoteByOperation(movement.operationId)\n .then((id) => id ?? (numero ? findInboxNoteByNumber(numero) : null))\n : numero ? findInboxNoteByNumber(numero) : Promise.resolve(null)\n\n busca\n .then((id) => {\n if (!vivo) return\n if (id) setNoteId(id)\n // Nota nenhuma reivindica esta entrada: ou ela não veio de nota, ou o\n // número repete entre fornecedores — e abrir a errada é pior que não\n // abrir. Dizer isso é melhor que girar para sempre.\n else setErro('Não achei a nota desta entrada nesta conta.')\n })\n .catch((e) => { if (vivo) setErro(describeError(e)) })\n return () => { vivo = false }\n }, [movement.operationId, movement.documentNumber, movement.reason])\n\n if (erro) {\n return (\n <>\n <ModalHeader className=\"shrink-0 border-b px-6 py-3 pr-14 text-left\">\n <ModalTitle>Nota de entrada</ModalTitle>\n </ModalHeader>\n <ModalBody className=\"px-6 py-8\">\n <p className=\"text-sm text-muted-foreground\">{erro}</p>\n </ModalBody>\n </>\n )\n }\n\n if (!noteId) {\n return (\n <>\n <ModalHeader className=\"shrink-0 border-b px-6 py-3 pr-14 text-left\">\n <ModalTitle>Nota de entrada</ModalTitle>\n </ModalHeader>\n <ModalBody className=\"space-y-3 px-6 py-4\">\n <Skeleton className=\"h-4 w-48\" />\n <Skeleton className=\"h-24 w-full\" />\n <Skeleton className=\"h-24 w-full\" />\n </ModalBody>\n </>\n )\n }\n\n return (\n <NoteReconcileView\n chrome=\"modal\"\n noteId={noteId}\n onBack={onClose}\n onOpenInvoice={(id) => { window.location.hash = `/financial/payables/${id}` }}\n />\n )\n}\n\n/**\n * O que o app passa em `createInventoryPlugin({ documentModal })`.\n *\n * Devolve `undefined` quando o movimento não veio de NF-e — e aí a legenda do\n * razão continua texto, em vez de virar um link que não abre nada.\n */\nexport function inboundNoteDocumentModal(\n movement: { documentType?: string; operationId?: string },\n close: () => void,\n): React.ReactNode | undefined {\n if (movement.documentType !== 'nfe' || !movement.operationId) return undefined\n return <InboundNoteDocumentModal movement={movement} onClose={close} />\n}\n\n// ---------------------------------------------------------------------------\n// O fiscal se apresenta como quem sabe abrir uma NF-e.\n// ---------------------------------------------------------------------------\n// No momento em que este módulo é carregado — ou seja, quando o aplicativo\n// instala o plugin. A tela de Movimentações do Estoque procura por\n// `document_type` e encontra; nenhum app precisa ligar fio nenhum.\n//\n// No topo do módulo e não dentro de uma função: um registro que depende de\n// alguém lembrar de chamá-lo é o mesmo problema que ele veio resolver.\n/** «NF-e 10592», «Entrada via DANFE NF-e 10592» — o número, onde ele estiver. */\nconst nfeNumberOf = (ref: { documentNumber?: string; reason?: string }): string | null =>\n (ref.documentNumber ?? ref.reason ?? '').match(/NF-e\\s*([0-9]{2,})/i)?.[1] ?? null\n\nconst NFE_OPENER = {\n documentType: 'nfe',\n // O razão é APPEND-ONLY — um gatilho recusa `UPDATE`, e com razão — então as\n // 3.088 linhas que a importação do V1 trouxe sem `document_type` nunca vão\n // ganhá-lo. O que elas têm é «Entrada via DANFE NF-e 10592» no motivo, frase\n // que este mesmo sistema escreveu. Reconhecê-la é ler o que se escreveu.\n claims: (ref: { documentType?: string; documentNumber?: string; reason?: string }) =>\n Boolean(nfeNumberOf(ref)),\n // Const de módulo e não arrow inline: o registro compara por identidade para\n // distinguir recarga quente de dois plugins disputando o mesmo tipo, e uma\n // função nova a cada chamada pareceria disputa.\n render: (ref: { operationId?: string; documentNumber?: string; reason?: string }, close: () => void) =>\n <InboundNoteDocumentModal movement={ref} onClose={close} />,\n}\n\nregisterDocumentOpener(NFE_OPENER)\n","import { definePlugin, type PluginManifest } from '@fayz-ai/core'\nimport { createPlugNotasConnector, type CreatePlugNotasConnectorOptions } from './connectors/plugnotas'\nimport { MIGRATIONS } from './migrations'\nimport { fiscalRegistries } from './data/registries'\nimport { makeInboundNotesRoute } from './views/InboundNotesPage'\nimport { UnitCertificateWidget, UnitFiscalWidget } from './views/UnitFiscalWidgets'\nimport { InvoiceNotesButton } from './views/InvoiceNotesButton'\nimport { UNIT_DETAIL_ZONES } from '@fayz-ai/admin'\nimport { FINANCIAL_INVOICE_ZONES } from '@fayz-ai/financial/views/zones'\nimport type React from 'react'\n\nexport * from './connectors/plugnotas'\nexport * from './lib/financial-provider'\nexport * from './types'\nexport * from './lib/nfe-xml'\nexport * from './data/inbox'\nexport * from './data/issued'\nexport * from './lib/issued-note'\nexport { InvoiceNotesButton } from './views/InvoiceNotesButton'\nexport { InboundNotesPage } from './views/InboundNotesPage'\nexport { InboundNotesView } from './views/InboundNotesView'\nexport { NoteReconcileView } from './views/NoteReconcileView'\nexport { ComingSoon, EmBreve } from '@fayz-ai/ui'\nexport { IssuedNotesView, ReturnedNotesView, TaxGroupsView } from './views/GapScreens'\n/**\n * O grupo «Notas Fiscais» como o V1 o desenha: cinco telas sob uma aba. Duas\n * funcionam, três anunciam o que falta. O app passa isto para\n * `createInventoryPlugin({ extraViews })` e o Estoque desenha.\n */\nexport { inboundNotesInventoryView, inboundNoteDocumentModal, InboundNoteDocumentModal } from './views/inventoryView'\n\nexport interface CreatePlugNotasPluginOptions extends CreatePlugNotasConnectorOptions {\n /** Onde a linha de Entrada de Notas entra no rail. Default: `main`, posição 5 (depois do estoque). */\n navSection?: 'main' | 'secondary' | 'settings'\n navPosition?: number\n /**\n * Onde o título a pagar vive no app anfitrião, para o botão «Abrir a conta a\n * pagar» depois de aceitar. Sem isto o botão não aparece — um botão que leva a\n * lugar nenhum é pior que a ausência dele.\n */\n payableRoute?: (invoiceId: string) => string\n}\n\n/**\n * Fiscal Brasil is an addon: Financial owns the fiscal document, while this\n * package owns the provider connection and its asynchronous delivery trail.\n */\nexport function createPlugNotasPlugin(options: CreatePlugNotasPluginOptions = {}): PluginManifest {\n return definePlugin({\n id: 'fiscal-br',\n name: 'Fiscal Brasil',\n icon: 'ReceiptText',\n version: '0.1.0',\n apiVersion: 1,\n scope: 'addon',\n defaultEnabled: true,\n dependencies: ['financial'],\n // SEM linha no rail, de propósito.\n //\n // Entrada de Notas é assunto de ESTOQUE, não assunto do menu: no V1 o caminho\n // é `Estoque → Notas Fiscais → Entrada de Notas`. Montei como linha solta na\n // primeira tentativa e estava errado — quem vem do V1 procura dentro do\n // Estoque e não acha. O app entrega a tela ao inventário por\n // `createInventoryPlugin({ extraViews })`, e ela aparece como aba irmã de\n // Produtos, Movimentações e Contagens.\n //\n // A rota própria FICA: ela é o deep link (`#/inbound-notes`), e é por onde o\n // agente e um link de e-mail chegam sem passar pela faixa de abas.\n navigation: [],\n routes: [\n {\n path: '/inbound-notes',\n // O registro de rotas monta componentes sem prop. A opção do host entra\n // por fechamento, e a fábrica mora no `.tsx` para este manifesto seguir\n // sendo TypeScript sem JSX.\n component: makeInboundNotesRoute({ payableRoute: options.payableRoute }),\n permission: { feature: 'financial', action: 'read' as const },\n },\n ],\n // O grupo fiscal é CADASTRO, e por isso entra como registry e não como\n // rota própria: ele aparece onde os outros cadastros do produto aparecem.\n registries: fiscalRegistries,\n widgets: [\n {\n id: 'fiscal-br-unit-certificate',\n zone: UNIT_DETAIL_ZONES.certificate,\n component: UnitCertificateWidget as unknown as React.ComponentType<unknown>,\n order: 0,\n permission: { feature: 'financial', action: 'read' as const },\n },\n {\n id: 'fiscal-br-invoice-notes',\n zone: FINANCIAL_INVOICE_ZONES.headerActions,\n component: InvoiceNotesButton as unknown as React.ComponentType<unknown>,\n order: 0,\n permission: { feature: 'financial', action: 'read' as const },\n },\n {\n id: 'fiscal-br-unit-fiscal',\n zone: UNIT_DETAIL_ZONES.fiscal,\n component: UnitFiscalWidget as unknown as React.ComponentType<unknown>,\n order: 0,\n permission: { feature: 'financial', action: 'read' as const },\n },\n ],\n connectors: [createPlugNotasConnector(options)],\n functions: [{\n slug: 'plugnotas-bridge',\n ingress: 'none',\n verifyJwt: false,\n secrets: [\n 'PLUGNOTAS_API_KEY',\n 'PLUGNOTAS_BASE_URL',\n 'PLUGNOTAS_ENVIRONMENT',\n 'PLUGNOTAS_WEBHOOK_SECRET',\n 'PLUGNOTAS_ARTIFACT_SIGNING_KEY',\n 'PLUGNOTAS_ALLOWED_ORIGINS',\n 'PLUGNOTAS_WORKER_SECRET',\n 'SUPABASE_URL',\n 'SUPABASE_ANON_KEY',\n 'SUPABASE_SERVICE_ROLE_KEY'\n ],\n grants: [\n 'plugnotas_register_emitter',\n 'plugnotas_disconnect_emitter',\n 'plugnotas_create_nfce_draft_for_order',\n 'plugnotas_prepare_nfce',\n 'plugnotas_prepare_nfce_cancel',\n 'plugnotas_apply_nfce_result',\n 'plugnotas_apply_nfce_webhook',\n 'plugnotas_get_artifact_locator',\n 'plugnotas_claim_nfce_recovery',\n 'plugnotas_record_nfce_attempt'\n ],\n }],\n migrations: MIGRATIONS.map((entry) => ({\n id: `fiscal-br-${entry.id}`,\n version: '1.0.0',\n sql: entry.sql,\n description: 'Durable PlugNotas delivery, recovery, webhook and emitter-registration boundary.',\n })),\n diagnostics: [{\n id: 'plugnotas-nfce-ready',\n description: 'NFC-e requires the shared connection, order, item and financial fiscal-document contracts.',\n requires: {\n tables: [\n 'connections',\n 'orders',\n 'items',\n 'plg_financial_nfe',\n 'plg_fiscalbr_nfce_jobs',\n 'plg_fiscalbr_nfce_events',\n 'plg_fiscalbr_webhook_receipts',\n ],\n rpcs: [\n 'plugnotas_create_nfce_draft_for_order',\n 'plugnotas_prepare_nfce',\n 'plugnotas_apply_nfce_result',\n 'plugnotas_apply_nfce_webhook',\n 'plugnotas_claim_nfce_recovery',\n ],\n env: [\n 'PLUGNOTAS_API_KEY',\n 'PLUGNOTAS_BASE_URL',\n 'PLUGNOTAS_ENVIRONMENT',\n 'PLUGNOTAS_WEBHOOK_SECRET',\n 'PLUGNOTAS_ARTIFACT_SIGNING_KEY',\n 'PLUGNOTAS_ALLOWED_ORIGINS',\n 'PLUGNOTAS_WORKER_SECRET',\n ],\n },\n level: 'error',\n }],\n })\n}\n"]}