UI/settings api mcp (#524)
* feat(voucher): add create voucher and correct entry previews; update commit methods * feat: add support for pending operations in API key scopes and OAuth client management - Introduced new API key scopes for reading and approving pending operations. - Updated the scope groups to include pending operations. - Added new tools for listing and managing pending operations. - Implemented OAuth client registration and revocation endpoints. - Created a UI panel for managing OAuth clients, including registration and revocation. - Added tests for pending operations tools and OAuth allowlist functionality. - Implemented a database migration for OAuth client registrations with appropriate policies and constraints. * feat: Implement OAuth client registration rate limiting and enhance security measures - Added IP-based rate limiting to the OAuth client registration endpoint to prevent enumeration attacks. - Introduced a service-role client for allowlist lookups, ensuring trust boundaries are maintained. - Updated error responses to be uniform across different types of redirect URI validation failures. - Enhanced tests to reflect changes in OAuth scope handling, ensuring fallback to read-only scopes when no scopes are provided. - Improved handling of high-risk pending operations, requiring explicit confirmation for approvals. - Added audit logging for OAuth client revocations and pending operation approvals/rejections to maintain a security audit trail. - Refactored API key scope management to include default read-only scopes for OAuth-issued keys and added segregation-of-duties checks. * feat: add recurring invoice scheduling functionality - Implemented recurring invoice schedules with a new database schema. - Created API routes for managing recurring invoices (GET and POST). - Added cron job to automatically generate invoices based on schedules. - Developed service functions for computing next run dates and executing schedules. - Added tests for the new functionality, including validation and success cases. - Introduced error handling for various scenarios in the invoice creation process. * feat: refine VAT rate validation and enhance recurring invoice handling
This commit is contained in:
@@ -177,6 +177,56 @@ export const CreateCreditNoteSchema = z.object({
|
||||
reason: z.string().optional(),
|
||||
})
|
||||
|
||||
// ============================================================
|
||||
// Recurring invoice schedule schemas
|
||||
// ============================================================
|
||||
|
||||
// Swedish VAT rates per ML 17 kap 24§ p.9 — null means "use customer default
|
||||
// from getAvailableVatRates". Any other value would produce a non-compliant
|
||||
// invoice (buyer cannot deduct ingående moms). Cron-time validation against
|
||||
// the customer's allowed set still runs in executeRecurringSchedule.
|
||||
export const RecurringScheduleItemSchema = 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)])
|
||||
.nullable()
|
||||
.optional(),
|
||||
})
|
||||
|
||||
export const CreateRecurringScheduleSchema = z.object({
|
||||
customer_id: uuid,
|
||||
name: z.string().min(1, 'Schedule name is required').max(200),
|
||||
day_of_month: z.number().int().min(1).max(31),
|
||||
payment_terms_days: z.number().int().min(0).max(90).default(30),
|
||||
currency: CurrencySchema.default('SEK'),
|
||||
your_reference: z.string().optional(),
|
||||
our_reference: z.string().optional(),
|
||||
notes: z.string().optional(),
|
||||
auto_send: z.boolean().default(false),
|
||||
// Optional: when to first run. Defaults to next occurrence of day_of_month
|
||||
// (today if day_of_month === today, otherwise next month).
|
||||
start_date: isoDate.optional(),
|
||||
items: z.array(RecurringScheduleItemSchema).min(1, 'At least one item is required'),
|
||||
})
|
||||
|
||||
export const UpdateRecurringScheduleSchema = z.object({
|
||||
customer_id: uuid.optional(),
|
||||
name: z.string().min(1).max(200).optional(),
|
||||
day_of_month: z.number().int().min(1).max(31).optional(),
|
||||
payment_terms_days: z.number().int().min(0).max(90).optional(),
|
||||
currency: CurrencySchema.optional(),
|
||||
your_reference: z.string().nullable().optional(),
|
||||
our_reference: z.string().nullable().optional(),
|
||||
notes: z.string().nullable().optional(),
|
||||
auto_send: z.boolean().optional(),
|
||||
status: z.enum(['active', 'paused']).optional(),
|
||||
// Replace all items if provided. Omit to keep existing items unchanged.
|
||||
items: z.array(RecurringScheduleItemSchema).min(1).optional(),
|
||||
})
|
||||
|
||||
export const MarkInvoicePaidSchema = z.object({
|
||||
payment_date: isoDate.optional(),
|
||||
exchange_rate_difference: z.number().optional(),
|
||||
|
||||
Reference in New Issue
Block a user