Feat/voucher docs (#664)

* feat: implement inbox document picker and linking functionality

* feat: implement self-billing invoice functionality

- Added support for registering self-billed invoices received from customers.
- Updated the invoice schema to include fields for self-billing metadata such as `is_self_billed`, `external_invoice_number`, `self_billing_agreement_ref`, and `received_date`.
- Created API route for handling self-billed invoice submissions, including validation and error handling.
- Implemented database migrations to add necessary columns and constraints for self-billing invoices.
- Developed tests to ensure correct behavior of self-billing invoice creation and validation rules.
- Updated Swedish localization files to include new terms related to self-billing.

* feat: enforce SIE import requirement for non-Fortnox providers in migration process

* feat: streamline invoice processing and enhance error logging across APIs
This commit is contained in:
Mattsson
2026-06-04 13:14:57 +02:00
committed by GitHub
parent c1be9f15dd
commit 3e42fc6f32
45 changed files with 2675 additions and 529 deletions
+28
View File
@@ -216,6 +216,34 @@ export const CreateCreditNoteSchema = z.object({
reason: z.string().optional(),
})
// Self-billing received (mottagen självfaktura, ML 17 kap 15§). The customer
// issued the invoice on our behalf; for us it is a sale. We store the
// counterparty's number in external_invoice_number and never assign one from
// our own series. No ROT/RUT (that is a B2C, own-issued concept), so the item
// schema is the lean revenue-only shape — vat_rate is constrained to the legal
// Swedish set so the booked output VAT is always reportable.
export const SelfBillingInvoiceItemSchema = z.object({
description: z.string().min(1, 'Item description is required'),
quantity: z.number().positive('Quantity must be positive'),
unit: z.string().min(1, 'Unit is required').default('st'),
unit_price: z.number(),
vat_rate: z
.union([z.literal(0), z.literal(6), z.literal(12), z.literal(25)])
.optional(),
})
export const CreateSelfBillingInvoiceSchema = z.object({
customer_id: uuid,
external_invoice_number: z.string().min(1, 'External invoice number is required').max(64),
self_billing_agreement_ref: z.string().max(128).optional(),
invoice_date: isoDate,
received_date: isoDate,
due_date: isoDate,
currency: CurrencySchema,
notes: z.string().optional(),
items: z.array(SelfBillingInvoiceItemSchema).min(1, 'At least one item is required'),
})
// ============================================================
// Recurring invoice schedule schemas
// ============================================================