Amazon invoices: book seller fee invoices (Tax Document Library PDFs) next to Ads invoices
Amazon offers no API for the seller fee invoices in Europe (the SP-API Invoices API is Brazil-only, no report type covers them), so the PDFs downloaded from Seller Central are dropped on the existing Amazon invoices page.
- parseSellerFeeInvoicePdf.ts: text-layer parser (kind 'fee'), one line per fee type with its own VAT rate; runs before the Ads parser in the upload route - vendor resolved by the issuer's VAT id, created under org * on first import - own charge (AMAZON_FEE_CHARGE_ID, default 1000009 "Amazon Gebühren"), tax per line rate; credit notes are listed but not importable yet - list route checks bookings across the Ads vendor and all fee vendors - page: Type / Aussteller / Empfänger columns, second charge selector
Custom forecast ("Individuelle Prognose"): standalone cost forecast for leads and partners, opened from a new "Prognose" button on both pages and from the quote modal's forecast card (seeded from the live quote form). Seeds from the saved custom forecast, else the saved quote conditions, else list prices. Every position can be switched off, relabelled and re-priced (per order with factor or % share, or per month), own positions added, up to 4 volume scenarios side by side (3+ print landscape), display toggles for calculation column, unit prices, subtotals, cost per order, yearly total and disclaimer. Save as draft (offer_conditions.forecast), download, or e-mail with record attachment and activity. Client computes, server only renders.
Quote validity: "Gültig (Tage)" and "Gültig bis" pair in the quote modal, default 7 days from now. One server resolver (resolveQuoteValidity) drives the PDF, the e-mail text, the activity, the saved conditions and the confirmation link expiry.
Amazon invoices: document details, paid vs created status, Lexoffice reset, pinned actions
- "Beleg in" column (org · vendor) + details dialog per created AP invoice (new booking.get.ts: header, payment/Lexoffice state, lines with charge + tax) - status no longer says "Verbucht" for a merely created document: "Beleg erstellt · Zahlung offen" until iDempiere has the invoice allocated to a payment (IsPaid) → "Bezahlt"; separate counters - Lexoffice reset for selected rows and from the details dialog (shared /api/invoices/lexoffice-reset), with a confirm that the voucher in Lexoffice is not deleted - actions column pinned right, status/document columns moved left, API notice collapsed by default, PDF icon fixed (ti-pdf)
Amazon invoices: recognise fee credit notes and book them as AP CreditMemo
- parser: "STEUERGUTSCHRIFT" template (Gutschriftennummer, Ausstellungsdatum / Zeitraum der Gutschrift), amounts with the sign before the currency ("-EUR 2.61"), "Ursprüngliche Rechnungsnummer" → originalInvoiceNo - import: credit notes become a vendor credit memo — doctype DocBaseType APC (AP CreditMemo) with positive amounts, reference to the original invoice in the description; no longer refused - OPOS + /sales/invoices: doctype 1000006 counts as customer-side only when the partner is flagged IsCustomer, so genuine vendor credit memos stay on the payables side (existing customer credit notes unchanged)
Leads list: dial icon aligned to the right edge, copy button on the e-mail column
- AgDialPhone: number stays left, only the dial button is pushed to the right (shared renderer — also applies to the users / external users lists) - new AgCopyEmail cell renderer: copy-to-clipboard button with check-mark feedback, does not start the inline editor
Recent calls card: blacklist control moved into the number popover, with live status and unblock
- no per-row block button any more (it cost a column of width); clicking the number opens the popover, which now shows the FreePBX blacklist status and either "Nummer sperren" (two-step confirm) or "gesperrt · Entsperren" - new TelephonyBlacklistControl, used inside the dial popover (DialButton show-blacklist) and in the card's own popover for sessions that cannot dial - server: blacklist status read via AMI DBGet (one session for the ≤ 10 numbers of a page), unblock via DBDel; GET + DELETE /api/telephony/blacklist. An unexpected AMI error is "status unknown", never a false "not blocked" - blocked numbers are marked red with a ban icon in the list
Amazon invoices: recognise the 2025 fee-invoice template, label the charge boxes as import settings
- parser: 2025 labels (Rechnungsnr, Name des Anbieters / Verkaeufers, Adresse / UStID des Anbieters) plus a label-independent fallback for supplier name and VAT id, so the next rename by Amazon does not break recognition - page: the two charge selectors are grouped as "Import-Einstellung · Kostenart für neue Belege (kein Filter)" with an explanatory tooltip
- quick-filter chips with counts: Typ (Ads / Gebühren / Gutschriften), Beleg (ohne / erstellt / bezahlt), Lexoffice (noch nicht hochgeladen / hochgeladen); totals follow the filter ("1 von 3") - no date filter by default; the optional invoice-date range sits behind a quiet "Zeitraum" button, reloads on change, and an upload widens it so new invoices are never hidden. The Ads API call keeps a bounded 12-month window server-side - the two cost-type selectors are collapsed behind "Import-Einstellungen" with a one-line summary and an info box (what they do, why two, not a filter, when to change); the panel opens by itself when a cost type is missing - upload area is a square drop box on the right with drag feedback and keyboard support
Amazon invoices: show voided documents properly, match them by POReference
- a voided invoice row names its Storno document ("Storniert #<id> · erneut importierbar"), opens its details (banner + link to iDempiere's reversal document, no Lexoffice reset), has its own row tint, a "Storno-Beleg" action, a "Storniert" quick-filter chip and a counter; it no longer counts as "Ohne Beleg (neu)" - list route: documents are matched to the Amazon invoice by POReference (full number) instead of DocumentNo — the void rename '<no>-VOID-<id>' is truncated to the 30-char column ('DE-AEU-2025-2978769' → 'DE-AEU-2025-29787-VOID-…'), so a voided document was not recognised; reversal documents are flagged and listed after the original
Amazon invoices: iDempiere is the source of truth for booked invoices, PDFs from the document attachment
The page's list lived only in data/amazon-ads.db, which was missing from the deploy script's preserve list — every deploy wiped it, so booked invoices vanished from the page (the documents themselves were never affected).
- list route: every Amazon invoice that HAS a document is rebuilt from iDempiere (AP documents of the Amazon vendors, found by vendor flag + name; key = POReference; kind from the vendor, credit note from the doctype, period from the description). The local store only adds uploads that are not imported yet plus parsed details / PDF cache - document route: without a local copy the ORIGINAL PDF attached to the iDempiere document is served (&cInvoiceId=); the page passes the document id - rows rebuilt from iDempiere are labelled (Quelle "iDempiere", PDF "Anhang"); a voided one asks for the PDF to be uploaded again before re-import - deploy script: amazon-ads.db + data/amazon-ads/ added to the preserve lists (must be pasted into the Jenkins job to take effect)
Amazon invoices: store uploads in the iDempiere table CUST_AmazonInvoiceInbox (PDF in Strapi)
- new invoiceStore.ts: one async storage API with two backends — the iDempiere table (row via REST, PDF attached in Strapi) and, only as a fallback when the table is not reachable, the old SQLite file - upload / list / import / void / document routes use it; the upload route reads the multipart body once and retries with a refreshed token - rows still in the SQLite file are moved over when the page loads (bounded, idempotent, fail-soft; imported rows keep their PDF on the c_invoice document, pending rows get their PDF uploaded to Strapi). A run where nothing can be written pauses for 10 minutes instead of retrying on every load, and rows that are not in the table yet stay visible and importable from the local file - status/list responses report the active backend
Amazon invoices: keep inbox rows consistent with iDempiere's documents (self-heal)
On each list load an inbox row whose document exists but is not linked (imported on another host / before the table existed) gets status 'imported' + the link; a row that still points to a voided or missing document is released. Bounded, fail-soft, idempotent — the page itself reads the documents and never depends on it.
Bank reconciliation: suggestions need at least 2 matching criteria, fuzzy names, date signal, score ranking
- a candidate is only suggested when at least 2 of 4 criteria match: document number, amount, partner (IBAN or name count as one) and date. On the current 33 open statements all 47 old invoice suggestions rested on a single signal - new date signal: statement line date −5 … +60 days around the invoice date - fuzzy partner names: umlauts spelled out, accents stripped, legal forms and filler words ignored, prefix matches, brand word, brand inside run-together text or the remittance text ("AMAZON PAYMENTS EUROPE S.C.A." matches "Amazon EU S.à r.l., Niederlassung Deutschland"; "Deutsche Bank" does not match "Deutsche Post") - ranking by score, best first (doc no. 50 · amount 30 · IBAN 25 / name 10–25 · date closeness 0–15); up to 8 candidates per line - match dialog: top 3 + "weitere anzeigen", date chip, n/4 criteria, best-match marker, top candidate preselected; list pill shows "+n" and a criteria tooltip
Amazon invoices: report the PDF as available when it sits on the iDempiere document
Rows migrated from the local file (and rows rebuilt from documents) carry no file of their own — their original PDF is the document's attachment. The list flagged them as "no PDF" although the link works; they now show "Anhang".
Amazon invoices: confirm every import with the cost type shown, no remembered cost types
12 fee invoices were booked to "Werbekosten": the page remembered the last selection of each cost-type box in the browser and a stale value silently overrode the correct default.
- cost types are no longer stored in the browser (old keys are removed); every page load starts from the server defaults (Ads → Werbekosten, fees/credit notes → Amazon Gebühren); a deviation is flagged (amber summary, reset to default) - every import goes through a confirmation dialog that groups the invoices by type, shows the cost type each group will be booked to (changeable there, the default is marked, a deviation is highlighted) and lists already booked ones as skipped. It opens on "Ausgewählte importieren" and right after an upload ("jetzt importieren" / "Später") - the import result names the cost type that was used per invoice
Amazon invoices: match documents by the full number in the description (POReference is 20 chars)
The first credit-memo import showed that POReference cannot carry the key: the column is 20 chars, so 'DE-CN-AEU-2026-134720' (21) is stored as 'DE-CN-AEU-2026-13472' — the new AP CreditMemo was not recognised as the credit note's document and the self-heal released its inbox row ('voided').
The importer's description starts with the FULL Amazon number on every document (active, voided rename, iDempiere's reversal), so that is the primary match key now; DocumentNo / POReference remain the fallback for documents not created by the importer. No double booking was possible — the importer's duplicate guard checks the full DocumentNo.
Amazon invoices: book the exact VAT from the PDF when a line-level purchase tax exists
Amazon rounds the VAT down (74,66 × 19 % → 14,18), iDempiere half-up (14,19); with the document-level "19% Mwst." the VAT is recomputed at completion, so 3 of 15 documents ended up one cent above the Amazon total.
iDempiere keeps a manually entered line TaxAmt on purchase documents whose tax rate is NOT document level. The importer now prefers such a rate (purchase, IsDocumentLevel = N) and writes the VAT from the PDF on each line (per-line VAT for fee invoices, proportional for Ads campaigns, remainder on the largest line). Without such a rate nothing changes — except that a difference between the booked total and the Amazon document is now reported as a warning instead of going unnoticed.