From db7d11dc7ff7aff7f6da15698c9f964a1ab4d1a1 Mon Sep 17 00:00:00 2001 From: Luca <102960244+Luca-Timo@users.noreply.github.com> Date: Tue, 2 Jun 2026 09:50:51 +0200 Subject: [PATCH] feat(bills): capture event name/date when importing historical invoices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The historical-invoice import form had no event field, so imported rows landed with event_name = NULL even when the admin knew the occasion. Add free-text Event name + Event date inputs to the import modal, thread them through billsService.importHistorical and the POST /admin/invoices/import validator, and store them in the event_name/event_date snapshot columns (migration 107). event_id stays NULL — no FK, since the event may predate picpeak. Autocomplete-to-event_id linking deferred as a future bonus. --- backend/src/routes/adminInvoices.js | 7 +++++++ frontend/src/i18n/locales/de.json | 1 + frontend/src/i18n/locales/en.json | 1 + frontend/src/pages/admin/bills/BillsListPage.tsx | 15 +++++++++++++++ frontend/src/services/bills.service.ts | 4 ++++ 5 files changed, 28 insertions(+) diff --git a/backend/src/routes/adminInvoices.js b/backend/src/routes/adminInvoices.js index dd077a10..42375648 100644 --- a/backend/src/routes/adminInvoices.js +++ b/backend/src/routes/adminInvoices.js @@ -427,6 +427,8 @@ router.post( [ body('customerAccountId').isInt({ min: 1 }), body('invoiceNumber').isString().isLength({ min: 1, max: 64 }), + body('eventName').optional({ values: 'falsy' }).isString().isLength({ max: 255 }), + body('eventDate').optional({ values: 'falsy' }).isISO8601(), body('issueDate').isISO8601(), body('dueDate').optional({ values: 'falsy' }).isISO8601(), body('totalAmountMinor').isInt({ min: 0 }), @@ -487,7 +489,12 @@ router.post( invoice_number: req.body.invoiceNumber, customer_account_id: customer.id, source_quote_id: null, + // No FK link on import — the event may predate picpeak. Store the + // free-text snapshot only, mirroring createInvoice's event_name / + // event_date columns (migration 107). event_id: null, + event_name: req.body.eventName || null, + event_date: req.body.eventDate || null, language, currency, issue_date: issueDate, diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json index 7313a736..a8e43491 100644 --- a/frontend/src/i18n/locales/de.json +++ b/frontend/src/i18n/locales/de.json @@ -3541,6 +3541,7 @@ "selectTiming": "— Zahlungsablauf wählen —", "eventName": "Anlass", "eventDate": "Anlassdatum", + "eventNamePlaceholder": "z.B. Hochzeit Schmidt 2024", "eventTimeStart": "Startzeit", "eventTimeEnd": "Endzeit", "customer": "Kunde", diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 9037f9f4..4bd19899 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -3587,6 +3587,7 @@ "selectTiming": "— Select schedule —", "eventName": "Event", "eventDate": "Event date", + "eventNamePlaceholder": "e.g. Smith wedding 2024", "eventTimeStart": "Start time", "eventTimeEnd": "End time", "customer": "Customer", diff --git a/frontend/src/pages/admin/bills/BillsListPage.tsx b/frontend/src/pages/admin/bills/BillsListPage.tsx index 3a5100cf..f84c618e 100644 --- a/frontend/src/pages/admin/bills/BillsListPage.tsx +++ b/frontend/src/pages/admin/bills/BillsListPage.tsx @@ -221,6 +221,8 @@ const ImportHistoricalInvoiceModal: React.FC = ({ onClose }) = const [customerId, setCustomerId] = useState(null); const [customerLabel, setCustomerLabel] = useState(''); const [invoiceNumber, setInvoiceNumber] = useState(''); + const [eventName, setEventName] = useState(''); + const [eventDate, setEventDate] = useState(''); const [issueDate, setIssueDate] = useState(new Date().toISOString().slice(0, 10)); const [dueDate, setDueDate] = useState(''); const [totalMajor, setTotalMajor] = useState(''); @@ -245,6 +247,8 @@ const ImportHistoricalInvoiceModal: React.FC = ({ onClose }) = await billsService.importHistorical({ customerAccountId: customerId, invoiceNumber, + eventName: eventName.trim() || undefined, + eventDate: eventDate || undefined, issueDate, dueDate: dueDate || undefined, totalAmountMinor: Math.round(Number(totalMajor) * 100), @@ -327,6 +331,17 @@ const ImportHistoricalInvoiceModal: React.FC = ({ onClose }) =
+
+ setEventName(e.target.value)} /> +
+