Fix/supp ag fb (#1023)

* fix: prevent credit notes from entering payment flow

* fix: persist and display customer personal numbers

* feat: configure automatic invoice reminder days

* fix: issue credit notes through send flow

* chore: add repository agent guidance

* feat(mcp): route tools across user companies

* fix(articles): delete unused register entries

* feat(invoices): improve issued invoice actions

* feat(supplier-invoices): retain uploaded source documents

* docs: record implementation decisions

* feat: enhance customer personal number handling and validation

- Updated CustomerForm to allow personal numbers in the format of "********-1234" for individual customers.
- Added validation to ensure personal numbers are only accepted for individual customers in CreateCustomerSchema.
- Implemented masking and encryption for personal numbers to enhance data protection.
- Introduced new utility functions for masking and encrypting personal numbers.
- Added database migration to enforce unique constraints on credit note relationships and prevent duplicate entries.
- Enhanced error handling and logging for credit note issuance and invoice processing.
- Updated tests to cover new credit note creation guards and personal number handling.

* test: enhance list companies test with supabase query mocks
This commit is contained in:
Mattsson
2026-07-15 15:53:15 +02:00
committed by GitHub
parent a558c75678
commit 072aedeaf9
116 changed files with 5708 additions and 669 deletions
+4
View File
@@ -26,6 +26,7 @@ const PERSISTED_EVENT_TYPES: CoreEventType[] = [
'period.locked',
'period.year_closed',
'customer.created',
'article.deleted',
'supplier.created',
'receipt.matched',
'receipt.confirmed',
@@ -98,6 +99,9 @@ function extractEntityId(payload: Record<string, unknown>): string | null {
if (typeof payload.invoiceId === 'string') {
return payload.invoiceId
}
if (typeof payload.articleId === 'string') {
return payload.articleId
}
// For journal_entry.corrected: use the corrected entry's ID
if ('corrected' in payload) {
+2 -1
View File
@@ -87,6 +87,7 @@ export type CoreEvent =
// Articles (artikelregister)
| { type: 'article.created'; payload: { article: Article; userId: string; companyId: string } }
| { type: 'article.updated'; payload: { article: Article; userId: string; companyId: string } }
| { type: 'article.deleted'; payload: { articleId: string; userId: string; companyId: string } }
// Suppliers
| { type: 'supplier.created'; payload: { supplier: Supplier; userId: string; companyId: string } }
// Receipts
@@ -174,7 +175,7 @@ export type CoreEvent =
success: boolean // true iff the tool returned without throwing AND was invoked (not denied)
isError: boolean // matches the JSON-RPC tool-result isError flag returned to the client
errorCode: string | null // structured error code from tool-result.toToolError when applicable
errorKind: 'execution' | 'scope_denied' | 'capability_denied' | 'unknown_tool' | 'test_key_write_blocked' | null
errorKind: 'execution' | 'scope_denied' | 'capability_denied' | 'company_access_denied' | 'unknown_tool' | 'test_key_write_blocked' | null
errorMessage: string | null // human-readable error message (truncated to 500 chars), null on success.
// Raw material for clustering real agent failures into curated gotchas:
// errorCode alone can't distinguish "period locked" from "unbalanced".