Nach Order-ID view of /accounting/amazon-settlements can now upload the invoices of the selected or all visible (filtered) orders to Lexoffice, reset their upload status, and shows per order whether an invoice exists, whether it was uploaded to Lexoffice and whether the order already went out in a settlement CSV.
- Checkbox row selection (pinned selection column, group selects filtered descendants, header selects all filtered rows) - SettlementLexofficeActions: "Lexoffice Upload" (Auswahl / Alle sichtbaren) and "Zurücksetzen" (upload status + CSV marker, both scopes); chunked requests with progress, category modal reused from /sales/invoices - New grid columns "Lexoffice" and "CSV-Export" (AgLexofficeSyncStatus, status shown on collapsed group rows, click = single upload/reset) - Filter card: new Lexoffice section (Rechnung / Lexoffice-Upload / CSV-Export) - CSV export marks all matched orders of the exported periods via new onExported hook in useLexofficeSettlementExport - settlement.get.ts returns invoice upload status + order CSV marker; C_Order columns isLexofficeCsvExported / lexofficeCsvExportDate are optional (fail-soft retry without them until created in iDempiere) - lexoffice-upload/-reset now return uploadedIds / skippedIds / resetIds - New route accounting/lexoffice-csv-export (mark / reset orders)
Bank reconciliation: auto-complete statement when the last line is matched
When a match (invoice, charge or linked payment) resolves the last open line of a Drafted C_BankStatement, the page now re-reads the lines from the server and, if all are matched, sends the Complete doc-action automatically. The statement posts and its payments are marked reconciled without a separate manual step.
- completion logic extracted into runCompletion(); the manual "Auszug abschließen" button keeps its confirm dialog and remains as a retry if the automatic completion is rejected by iDempiere - on failure the alert states that all lines are matched but the statement could not be closed automatically, with the backend reason - after completion the next oldest draft is auto-selected - progress hint tells the user the statement closes automatically once the last position is matched
Contract modal: 0-month notice default, aligned rows, checkbox spacing, opt-in PDF attachments on signing mail
- Kündigungsfrist defaults to 0; termination clause adapts (no notice / 1 month / N months + special right) - Parameter rows bottom-align inputs; shorter cure-period label - Spacing for contract-part, annex and signing checkboxes - New 'attach PDFs to link e-mail' option (default off); link-only mail text; persisted with conditions - Signing page: VAT hint now says German VAT ID may follow later but is required before shipping into Germany
The upload processed invoices strictly one after another with two fixed 500 ms sleeps per invoice (~4.7 s each on prod: 1.0 s sleeps, 1.2 s iDempiere PDF render, ~2.5 s Lexware calls). Lexware's upload endpoints return 202 before their asynchronous OCR, so there was never anything to wait for — the time was purely serial latency.
- lexofficeClient.ts: new `lexFetch` — the single gateway for all Lexware traffic. Process-wide pacing (>= 520 ms between call starts), max 2 calls in flight and 429/503 retry with backoff (honours Retry-After). All client helpers use it. - lexoffice-upload.post.ts: 3 invoices are worked on concurrently (worker pool), so PDF rendering overlaps the Lexware round-trips; the hard-coded sleeps are replaced by the throttle. Per-partner contact resolution is memoised for the run so concurrent invoices of one partner can't create duplicate contacts. Per-invoice logs are prefixed with the invoice id; result id lists keep the caller's input order. Response contract unchanged.
Expected: ~4.7 s -> ~1.5 s per invoice on bulk uploads.
Amazon settlements: show/filter Lexoffice + CSV status immediately after actions
After uploading invoices or exporting a settlement CSV the row status was patched in place, but the "Lexoffice" / "CSV-Export" column set filters kept the value list they built from the initially loaded rows. A period that started with only "Nein" never offered "Ja", so filtering on the just-uploaded / just-exported rows only worked after a full page reload.
- refreshLexCells now refreshes both set filters' value lists (getColumnFilterInstance -> refreshFilterValues) before re-running the filter, and updates the filtered row count + lexStats in the same pass. - Both columns get `filterParams: { refreshValuesOnOpen: true }` as a safety net.
Lexoffice upload: send invoices in chunks of 20 per request
The sales invoices list sent every selected invoice id in a single request, so a large selection became one very long HTTP request that could hit the proxy timeout. It now uploads in chunks of 20 ids sequentially and aggregates uploaded / skipped / error counts into one toast. The Amazon settlements page already chunked (10) — raised to 20 to match the faster concurrent server path while keeping progress visible.
Lexoffice upload: guard against double uploads of the same invoice
- Dedupe the requested ids: with concurrent workers a duplicated id could be picked up by two workers at once (serial processing used to mask this). - Process-local in-progress set: overlapping requests (double-click, two tabs, two users) that both pass the isUploadToLexoffice check before either has marked the invoice now skip it with "already being uploaded by another request" instead of uploading it twice.
Marketing flyer LogYou x LogShip: 16:9 PDF, opt-in attachment on quote/contract, dummy-data demo screens
- server/utils/offers/flyerPdf.ts + flyerTexts.ts (DE/EN), assets under server/assets/offers/flyer - GET /api/offers/flyer (preview/download), contractPackage 'flyer' key (explicit opt-in), quote send attachment - Checkboxes (default off) in ContractModal and QuoteModal with preview link - /flyer-demo/* public dummy-data screens used for the app screenshots - ci: deploy script preserves new SQLite stores + signing PDFs; ci/README convention; recipes