/** * Merges mandate core fields with billing settings for SysAdmin mandate forms. * Billing is stored separately (BillingSettings); attributes API only exposes Mandate model fields. */ import type { AttributeDefinition } from '../components/FormGenerator/FormGeneratorForm'; import type { BillingSettings, BillingSettingsUpdate } from '../api/billingApi'; export const mandateBillingFieldNames = [ 'billingModel', 'defaultUserCredit', 'warningThresholdPercent', 'notifyOnWarning', 'notifyEmails', ] as const; export type MandateBillingFieldName = (typeof mandateBillingFieldNames)[number]; /** FormGenerator attribute definitions for mandate billing (appended after /api/attributes/Mandate). */ export function getMandateBillingFormAttributes(): AttributeDefinition[] { return [ { name: 'billingModel', type: 'select', label: 'Abrechnungsmodell', description: 'Vorauszahlung auf Mandanten- oder Benutzerkonten.', required: false, default: 'PREPAY_MANDATE', editable: true, order: 100, options: [ { value: 'PREPAY_MANDATE', label: 'Vorauszahlung (Mandanten-Guthaben)' }, { value: 'PREPAY_USER', label: 'Vorauszahlung pro Benutzer' }, ], }, { name: 'defaultUserCredit', type: 'float', label: 'Startguthaben neuem Benutzer (CHF)', description: 'Nur relevant bei PREPAY_USER (u. a. Root-Mandant). Sonst meist 0.', required: false, default: 0, editable: true, order: 101, }, { name: 'warningThresholdPercent', type: 'float', label: 'Warnschwelle (%)', description: 'Benachrichtigung, wenn das Guthaben unter diesem Prozentsatz fällt.', required: false, default: 10, editable: true, order: 102, }, { name: 'notifyOnWarning', type: 'checkbox', label: 'Bei Warnung benachrichtigen', required: false, default: true, editable: true, order: 103, }, { name: 'notifyEmails', type: 'textarea', label: 'Benachrichtigungs-E-Mails', description: 'Eine Adresse pro Zeile oder durch Komma/Semikolon getrennt.', required: false, default: '', editable: true, order: 104, minRows: 2, maxRows: 6, }, ]; } function _parseNotifyEmailsInput(val: unknown): string[] { if (Array.isArray(val)) { return val.map(String).map(s => s.trim()).filter(Boolean); } if (typeof val !== 'string') { return []; } return val .split(/[\n,;]+/) .map(s => s.trim()) .filter(Boolean); } /** Build initial form values: mandate row + billing settings (notifyEmails as multi-line string). */ function _normalizeBillingModelUi(raw: string | undefined): BillingSettings['billingModel'] { if (raw === 'PREPAY_USER') return 'PREPAY_USER'; return 'PREPAY_MANDATE'; } export function mergeBillingIntoMandateFormData( mandate: Record, settings: BillingSettings | null ): Record { if (!settings) { return { ...mandate, billingModel: 'PREPAY_MANDATE', defaultUserCredit: 0, warningThresholdPercent: 10, notifyOnWarning: true, notifyEmails: '', }; } return { ...mandate, billingModel: _normalizeBillingModelUi(settings.billingModel), defaultUserCredit: Number(settings.defaultUserCredit ?? 0), warningThresholdPercent: Number(settings.warningThresholdPercent ?? 10), notifyOnWarning: settings.notifyOnWarning ?? true, notifyEmails: (settings.notifyEmails || []).join('\n'), }; } /** Split form submit payload into mandate PUT body and billing POST body. */ export function splitMandateAndBillingFromForm( formData: Record ): { mandatePayload: Record; billingUpdate: BillingSettingsUpdate } { const mandatePayload: Record = {}; if ('name' in formData) mandatePayload.name = formData.name; if ('label' in formData) mandatePayload.label = formData.label; if ('enabled' in formData) mandatePayload.enabled = formData.enabled; const billingUpdate: BillingSettingsUpdate = {}; if ('billingModel' in formData && formData.billingModel !== undefined && formData.billingModel !== '') { billingUpdate.billingModel = formData.billingModel as BillingSettingsUpdate['billingModel']; } { const raw = formData.defaultUserCredit; const n = raw === undefined || raw === null || raw === '' ? 0 : Number(raw); if (!Number.isNaN(n)) { billingUpdate.defaultUserCredit = n; } } if ( 'warningThresholdPercent' in formData && formData.warningThresholdPercent !== undefined && formData.warningThresholdPercent !== '' ) { const n = Number(formData.warningThresholdPercent); if (!Number.isNaN(n)) billingUpdate.warningThresholdPercent = n; } if ('notifyOnWarning' in formData) { billingUpdate.notifyOnWarning = Boolean(formData.notifyOnWarning); } if ('notifyEmails' in formData) { billingUpdate.notifyEmails = _parseNotifyEmailsInput(formData.notifyEmails); } return { mandatePayload, billingUpdate }; }