Skip to content

Changes

Started by timer
Started 3 days 18 hr ago
Took 1 min 5 sec on built-in

Summary

  1. Carrier rates: DPD price lists imported (myDPD G300 + MDB 2026-04 → dpd-pricelist-2026-04.json, 1261 rows; Classic/Paketshop Europe per country, Express as zone rows + country→zone map); carrier identity from M_Shipper.M_ShipperCfg_ID (DHL / DPD groups, settings/shipping-carriers endpoint, price-sheet carrier select by config); resolver groups flat weight tiers per country and renders zone rows; markup defaults to 0 % (stored 15 % migrated once); matrix search filter now limits the PDF to the visible rows; price-sheet options panel rebuilt with Nuxt UI components (details)
  2. Software offer: "Anlage Onboarding-Paket" as a separate PDF attached by default (onboardingPdf.ts: from-price, travel + hotel billed on top, not-included list, phases, editable setup scope: on-site process analysis, bins, article import, channels, carriers, label + document printers, scanners/devices, users, test run); portal document + mail/Strapi attachment + activity line, preview via document:'onboarding', attachments.onboarding persisted in the saved conditions. Price sheet: carrier select = configs only (DHL/DPD with logos, no attached shippers), multi-select carriers (shipperIds → one sheet per carrier merged by mergePriceSheets, carrier badges, PDF carrier prefixes, Tier writes under the row's carrier), row/section/surcharge checkboxes with "Alle abwählen" limiting the PDF export, markup 0 % default enforced (old 15 % pattern dropped on load); options panel rebuilt with Nuxt UI (UFieldGroup, USwitch/UCheckbox/URadio/UInputNumber gap fixes); recipes updated (details)
  3. Partner edit page on Nuxt UI: three-column layout (form | contact cards | KPI panel), grouped toolbar, segmented tabs, compact collapsible sections (details)
  4. Production deploy: no more SQLite writes into the replaced live dir (lost contract-signing row 2026-10-29) (details)
  5. Price sheet: carrier logos + per-carrier grouping (matrix and PDF), PDF rates first / notes last, services check-all, Nuxt UI country multi-select, markup 0 % everywhere (details)
  6. Top bar: merchant label moved into the left zone as a chip (no longer overlaps the centred Ticket/Order buttons); side zones may shrink (minmax(0,1fr)), search shrinks first, quick-action buttons go icon-only below 1600/1400 px (details)
  7. Order lines: "Alle Artikel mit Bestand" — one position per article of the order's organization that has stock, qty = QtyOnHand (details)
  8. Create sales order page (/create/sales-order) rebuilt with the quick-order modal's design and features, order form on Nuxt UI (details)
  9. Price sheet: Germany preselected on load, pinned DE/AT/FR/NL/CH quick picks, one carrier logo per group + gaps between groups (matrix and PDF), narrower wrapping surcharge column (details)
  10. Sales order edit: positions table anchored under the form columns (grid: form | side panel, positions in row 2 of column 1) — a long side column (shipments / invoices / contacts / tickets) no longer pushes the positions down (details)
  11. Order creation (modal + page): placeholder e-mail generator next to the e-mail field (details)
  12. Quick order: coerce AD_Org_ID / C_Country_ID / C_Region_ID ids to numbers before posting partner + address — a cookie/config string id made iDempiere reject the new customer's C_Location (WrongDataType … should be Integer, prod 2026-10-30) (details)
  13. Commission table edit page on Nuxt UI + printer pickers; shipment Jasper slip: pickup vs. delivery + signature box (details)
  14. Commission table form: badge hover no longer flickers (CSS scale was replacing the SVG translate → inner group scales), compact spacing like the partner form (8 px fields, dashed section heads, 2 rem inputs, smaller hero), grid 2/3 form + 1/3 side, rounded card accent bar, camera id 0 shown as empty (details)
  15. LogShip Cloud offer: with the onboarding annex attached the offer prints only a price-less 'Onboarding-Paket – optional' position (details + price in the annex, forecast one-time row dropped); preview step shows all outgoing documents (offer / annex / flyer) as tabs and 'PDFs herunterladen (n)' saves them all (iframe keyed per doc — nuxt-lazy-load one-shot data-src) (details)
  16. Printing: per-printer dispatch (local CUPS or LogShip Print Agent in the tenant LAN) — spool, agent protocol, settings UI (details)
  17. Print-Agents: remote printer administration on the device — 'Drucker einrichten' dialog (discover USB/network printers via lpinfo/ippfind, create CUPS queues with driver presets + media, test page, enable/disable/accept, cancel, remove) over the agent command channel; command whitelist extended; recipe .claude/rules/printing/print-agent.md (details)
  18. Print-Agent: fresh-start poll re-queues the agent's claimed jobs at once (no 3-min wait after an agent restart) (details)
  19. Print-Agent: fresh-start reconcile list of unconfirmed spooled jobs; maintenance closes spooled jobs without completion report after 30 min (details)
Commit fe1a084fad0a11016cbb3d0355ce69e4d7504eb0 by info
Carrier rates: DPD price lists imported (myDPD G300 + MDB 2026-04 → dpd-pricelist-2026-04.json, 1261 rows; Classic/Paketshop Europe per country, Express as zone rows + country→zone map); carrier identity from M_Shipper.M_ShipperCfg_ID (DHL / DPD groups, settings/shipping-carriers endpoint, price-sheet carrier select by config); resolver groups flat weight tiers per country and renders zone rows; markup defaults to 0 % (stored 15 % migrated once); matrix search filter now limits the PDF to the visible rows; price-sheet options panel rebuilt with Nuxt UI components
The file was modifiedapp/components/settings/price-sheet/PriceSheetPreviewModal.vue (diff)
The file was modifiedapp/assets/langs/shared.js (diff)
The file was modifiedapp/utils/shippingPriceSheet.ts (diff)
The file was addedreference/shippingprices/dpd/DPD-DE G300.pdf
The file was modifiedapp/pages/settings/price-sheet/index.vue (diff)
The file was addedreference/shippingprices/dpd/MDB-Gesamt_V05 2026-04.pdf
The file was modifiedserver/utils/shipping/carrierRates.ts (diff)
The file was modifiedapp/components/settings/price-sheet/PriceSheetOptions.vue (diff)
The file was addedreference/test-scripts/dpd-pricelist-parse.mts
The file was modified.claude/rules/fulfillment/carrier-rates.md (diff)
The file was modifiedapp/components/settings/price-sheet/PriceSheetMatrix.vue (diff)
The file was addedserver/api/settings/shipping-carriers.get.ts
The file was addedserver/assets/shipping/dpd-pricelist-2026-04.json
The file was modifiedserver/utils/shipping/carrierRateImport.ts (diff)
The file was modifiedserver/utils/shipping/priceSheet.ts (diff)
Commit e3f2b4de3992d637c6f6bfc61677ee676594a448 by info
Software offer: "Anlage Onboarding-Paket" as a separate PDF attached by default (onboardingPdf.ts: from-price, travel + hotel billed on top, not-included list, phases, editable setup scope: on-site process analysis, bins, article import, channels, carriers, label + document printers, scanners/devices, users, test run); portal document + mail/Strapi attachment + activity line, preview via document:'onboarding', attachments.onboarding persisted in the saved conditions. Price sheet: carrier select = configs only (DHL/DPD with logos, no attached shippers), multi-select carriers (shipperIds → one sheet per carrier merged by mergePriceSheets, carrier badges, PDF carrier prefixes, Tier writes under the row's carrier), row/section/surcharge checkboxes with "Alle abwählen" limiting the PDF export, markup 0 % default enforced (old 15 % pattern dropped on load); options panel rebuilt with Nuxt UI (UFieldGroup, USwitch/UCheckbox/URadio/UInputNumber gap fixes); recipes updated
The file was modifiedapp/components/offers/SoftwareQuoteModal.vue (diff)
The file was modifiedapp/components/settings/price-sheet/PriceSheetOptions.vue (diff)
The file was modifiedserver/api/offers/quote/send.post.ts (diff)
The file was modifiedapp/components/settings/price-sheet/PriceSheetPreviewModal.vue (diff)
The file was modifiedserver/api/settings/price-sheet/resolve.post.ts (diff)
The file was modified.claude/rules/nuxt/ui-components.md (diff)
The file was modifiedapp/pages/settings/price-sheet/index.vue (diff)
The file was modifiedapp/assets/langs/shared.js (diff)
The file was modifiedserver/api/offers/quote/preview.post.ts (diff)
The file was modifiedapp/components/settings/price-sheet/PriceSheetCellEditor.vue (diff)
The file was modifiedapp/utils/shippingPriceSheet.ts (diff)
The file was modifiedapp/composables/useOfferSoftwareQuote.ts (diff)
The file was modifiedapp/components/settings/price-sheet/PriceSheetMatrix.vue (diff)
The file was addedserver/utils/offers/onboardingPdf.ts
The file was modifiedserver/utils/shipping/priceSheetPdf.ts (diff)
The file was modifiedserver/utils/offers/softwareQuotePdf.ts (diff)
The file was modified.claude/rules/offers/software-quote.md (diff)
The file was modified.claude/rules/fulfillment/carrier-rates.md (diff)
Commit d65908d08308892d51a84856036b01a6723952ed by info
Partner edit page on Nuxt UI: three-column layout (form | contact cards | KPI panel), grouped toolbar, segmented tabs, compact collapsible sections

- Contacts (AD_User) as cards in their own column (PartnerDetailRecordUser mode="cards": avatar, e-mail + send, phones + click-to-dial, inactive badge, add/edit/delete via the existing modal); detail-record "Kontakt (Benutzer)" tab hidden on the edit page (hide-users), view/duplicate keep the table; sticky columns, equal gutters, long e-mails wrap
- Toolbar (bannercontrol): UFieldGroup save pair + UDropdownMenu groups "Neu" (Kundenauftrag, Anfrage), "Dokumente" (Angebot, Prognose, Vertrag, SEPA, Bericht), "E-Mails" (Verlauf IM/MP, Zugangsdaten), "…" (Anhang, Duplizieren, Änderungsprotokoll via ChangeLogModal); role/processing conditions kept as disabled items
- Tabs: UTabs as a segmented pill bar with icons, active tab highlighted; tab strip inside the edit wrapper so it starts at the form's left edge; first section, contacts card and KPI row aligned on one line
- PartnerForm converted to Nuxt UI: 23 sections as UCard with coloured, larger titles, collapsible and collapsed by default (open state in localStorage logship_partner_sections); UFormField (icon label slot + UTooltip hint), UInput/USelect/UTextarea (size sm), USwitch on toggle cards and flags (toggleFlag/setFlag), URadioGroup for the rent mode, UButton everywhere; SelectBox and DatePicker unchanged; compact spacing (field 8 px, label 2 px, halved column gutters, zero card padding)
- Fixes: freight-rule select crashed on the '' option (Reka SelectItem forbids it → sentinel), USelect trigger zero width + unstyled panel, 9 Tabler icon names missing from the shipped font (blank glyphs) replaced, contacts/locations loaders no longer throw when the API returns nothing
- Recipes: nuxt/ui-components.md (USelect/UTabs/UCard/UFormField gaps), partners/partner-edit-form.md (new form structure + edit page layout)
The file was modifiedapp/components/partners/PartnerDetailRecordUser.vue (diff)
The file was modifiedapp/components/partners/PartnerDetailRecordLocation.vue (diff)
The file was modifiedapp/pages/partners/partners/[id]/edit.vue (diff)
The file was modifiedapp/components/partners/PartnerDetailRecord.vue (diff)
The file was modified.claude/rules/nuxt/ui-components.md (diff)
The file was modifiedapp/components/partners/PartnerForm.vue (diff)
The file was modified.claude/rules/partners/partner-edit-form.md (diff)
Commit 87bd740025e1476eec9e8228f7162712ea3602d9 by info
Production deploy: no more SQLite writes into the replaced live dir (lost contract-signing row 2026-10-29)

- Native module builds (better-sqlite3 rebuild, sqlite3 from source, OCR/PDF runtime asset copies, load gate) now run in the STAGE dir before the swap; the live-dir swap itself takes seconds
- `pm2 stop` of the app before the rollback copy / rm -rf of the live dir: SQLite connections close and checkpoint, no request can write to deleted inodes (a contract-signing row written during the minutes-long post-swap build window was lost while its PDFs landed in the new dir)
- SQLite backups through the better-sqlite3 online backup API (includes WAL frames); plain cp as fallback
The file was modifiedreference/ci/deploy-production.sh (diff)
Commit 03731494971458295d341c3c7a52962a210e58d7 by info
Price sheet: carrier logos + per-carrier grouping (matrix and PDF), PDF rates first / notes last, services check-all, Nuxt UI country multi-select, markup 0 % everywhere

- shippingPriceSheet.ts: CARRIER_LOGO_PATHS / carrierLogoPath() as the single logo map, groupRowsByCarrier() for merged sheets
- Matrix: carrier heading row (logo, name, row count) per section and in the surcharge table, logo inline before each service on merged sheets, "Kosten" header carries the single carrier's logo
- PDF: DHL/DPD PNG logos bundled as Nitro server asset assets:shipper (carrierLogos.ts), cover "[logo] DHL + [logo] DPD", carrier heading rows + logo before the service in every table; page order cover → rate sections → surcharges → service overview → notes; the per-section notes are collected onto the notes page instead of sitting above the tables
- Options panel: "Alle an / Alle aus" for the services list with counter, country selection as USelectMenu multiple (search, flags, ISO codes, taller trigger) replacing the popover, carrier-neutral markup label (shared.js ps_markup), stored markups reset once to 0 % (markupV3) so no section keeps an old percentage
- Smoke script mocks assets:shipper too
The file was modifiedapp/components/settings/price-sheet/PriceSheetOptions.vue (diff)
The file was modifiedreference/test-scripts/price-sheet-pdf-smoke.mts (diff)
The file was modifiedserver/utils/shipping/priceSheetPdf.ts (diff)
The file was modifiedapp/assets/langs/shared.js (diff)
The file was modifiedapp/pages/settings/price-sheet/index.vue (diff)
The file was modifiednuxt.config.ts (diff)
The file was modified.claude/rules/fulfillment/carrier-rates.md (diff)
The file was modifiedapp/utils/shippingPriceSheet.ts (diff)
The file was addedserver/utils/shipping/carrierLogos.ts
The file was modifiedapp/components/settings/price-sheet/PriceSheetMatrix.vue (diff)
Commit e6ed749cb9aa1676b35a8f6793b67f1f9134e48c by info
Top bar: merchant label moved into the left zone as a chip (no longer overlaps the centred Ticket/Order buttons); side zones may shrink (minmax(0,1fr)), search shrinks first, quick-action buttons go icon-only below 1600/1400 px
The file was modifiedapp/components/TopMegaBar.vue (diff)
Commit 0d10b13fbabdb1809889fe218b5ac275914a22d6 by info
Order lines: "Alle Artikel mit Bestand" — one position per article of the order's organization that has stock, qty = QtyOnHand

- POST server/api/orders/stock-lines { orgId, priceListId, warehouseId }: active articles of the org with their storage rows (productStorageHelper, no child $expand), QtyOnHand summed over all locators (or the order's warehouse), return-locator stock reported separately, prices from the newest version of the order's price list in chunked m_productprice queries
- PartnerOrderLineTable: button next to "Position hinzufügen" (order modal + every create/edit line table) that appends the lines with qty = on hand and PriceList/PriceStd, skips articles already on the order, info line with added / skipped / without-price counts (price 0 → check)
The file was addedserver/api/orders/stock-lines.post.ts
The file was modifiedapp/components/partners/PartnerOrderLineTable.vue (diff)
Commit 40aafbad732e3ef3fef33b6737db0c5ab3fac06b by info
Create sales order page (/create/sales-order) rebuilt with the quick-order modal's design and features, order form on Nuxt UI

- add.vue: hero header (badge, title, org / customer / positions chips), segmented UTabs for Order / Delivery / Invoicing / Reference / Integration / Status, form card, positions card with the modal's line table (article search, qty / price editing, "Alle Artikel mit Bestand") live BEFORE the first save — the lines travel with the order (orderLines → C_OrderLine), sticky footer with "Fehlt: …" readiness hint, Ctrl+Enter, Weiter, Speichern; keeps the US-state gate, DHL insurance / customs / relabel / marketplace-id fields and the tab-aware navigation after save
- The duplicate create.vue (old /windows/sales-orders-create page) is removed; the window route now loads add.vue too
- sales/OrderForm.vue converted by script: 60 field wrappers → UFormField (label slot), 57 inputs → UInput, 8 checkboxes → USwitch, 4 static selects → USelect, copy / external-link / tracking buttons → UButton; non-scoped overrides for the empty-bodied Nuxt UI utilities (inputs, select trigger + panel, switch track/thumb, buttons); inline address editors, SelectBox and DatePicker unchanged
The file was modifiedapp/router.options.ts (diff)
The file was removedapp/pages/sales/orders/create.vue
The file was modifiedapp/pages/sales/orders/add.vue (diff)
The file was modifiedapp/components/sales/OrderForm.vue (diff)
Commit a43f136338a7b5f2149ceabf14a2caf953c3f06f by info
Price sheet: Germany preselected on load, pinned DE/AT/FR/NL/CH quick picks, one carrier logo per group + gaps between groups (matrix and PDF), narrower wrapping surcharge column

- defaultSheetOptions: countryScope 'list' with ['DE'] (stored options reset once via countryV3); PINNED_COUNTRY_CODES as toggle chips above the country select and sorted first in the list
- Matrix: a carrier group following another one gets a padded top border; surcharge label column 25 % narrower (142 px) with wrapping labels
- PDF: logo only on the carrier heading row (service rows plain), white spacer row between carrier groups, surcharge label column 142 pt
The file was modifiedapp/pages/settings/price-sheet/index.vue (diff)
The file was modifiedapp/components/settings/price-sheet/PriceSheetOptions.vue (diff)
The file was modifiedapp/utils/shippingPriceSheet.ts (diff)
The file was modifiedserver/utils/shipping/priceSheetPdf.ts (diff)
The file was modifiedapp/components/settings/price-sheet/PriceSheetMatrix.vue (diff)
The file was modified.claude/rules/fulfillment/carrier-rates.md (diff)
Commit be9d899a98a72a689c5a23adff03fa5fce3b6dea by info
Sales order edit: positions table anchored under the form columns (grid: form | side panel, positions in row 2 of column 1) — a long side column (shipments / invoices / contacts / tickets) no longer pushes the positions down
The file was modifiedapp/pages/sales/orders/[id]/edit.vue (diff)
Commit 178f9bf899be01a5c52db86cf4cf429b4402d99f by info
Order creation (modal + page): placeholder e-mail generator next to the e-mail field

- utils/randomEmail.ts: randomLogyouEmail() → kunde-<10 random base36>@logyou.de (crypto random)
- PartnerQuickForm (quick-order modal) and sales/OrderForm (create / edit page): wand button beside the e-mail input proposes an address; it is applied only after the user confirms it in an inline row (Übernehmen / Neu würfeln / Abbrechen)
The file was modifiedapp/components/sales/OrderForm.vue (diff)
The file was modifiedapp/components/partners/PartnerQuickForm.vue (diff)
The file was addedapp/utils/randomEmail.ts
Commit 9c1920c94bbf70ba21c11caa4cd92c54367c80e6 by info
Quick order: coerce AD_Org_ID / C_Country_ID / C_Region_ID ids to numbers before posting partner + address — a cookie/config string id made iDempiere reject the new customer's C_Location (WrongDataType … should be Integer, prod 2026-10-30)
The file was modifiedserver/api/partners/partners/quick-add.post.ts (diff)
Commit 8cac0a6a0a3ec6c69dd96c99db1da6170afe5cc8 by info
Commission table edit page on Nuxt UI + printer pickers; shipment Jasper slip: pickup vs. delivery + signature box

Commission tables (Settings → Commission Tables):
- CommissionTableForm rebuilt with Nuxt UI (UCard sections, UFormField with icon labels + UTooltip info
  icons, UInput/UTextarea/USelect/USwitch, UFieldGroup actions); edit page gets the partner-page toolbar
  (save group, preview, clone, manage printers, back) and a hero header; create/duplicate keep the in-form actions
- Shipping (label) printer and A4 printer are now pickers over Settings → Printers (/api/printers): label
  printers for shipping_printer, paper printers for a4_printer, each item with CUPS queue + location; the
  stored value stays the CUPS queue name, so the commissioning page pickers / getA4Printer keep working
- A queue saved on a table but missing in Settings → Printers is flagged and can be created in place
  (shared org *); the five queues referenced by Tisch 1–3 (labelprinter-4/-5, commission-a4-1/2/3) were
  created on prod as CUST_Printer rows
- Cameras: USelect over the Synology list (loaded on open) + ID fallback input
- Side card "Geräte am Tisch": table illustration (SVG) with numbered device badges 1 label printer,
  2 A4 printer, 3 camera, 4 camera 2 matching the numbered fields, hover sync, legend with current values;
  Organisation & Status card with org picker, tenant, Active switch
- Org "*" (id 0) was dropped as falsy on load and on update; tenant falls back to AD_Client identifier

Shipment Jasper report (iDempiere host, templates archived under reference/jasper-reports):
- DeliveryViaRule = 'P' (Abholung) replaces "Versand via <carrier>" + logo with "Abholung / Selbstabholung",
  relabels Lieferdatum → Abholdatum and prints a "WARE ERHALTEN (ABHOLUNG)" signature box (Datum /
  Unterschrift) right of the barcode — A4 (M_InOut_Document + M_InOut_OrgInfoblock) and A5 slip
- Deployed + compiled on 192.168.12.72 (Groovy compile one-liner, backups shipment*.bak-20261030);
  recipes: printing/jasper-shipment-report.md, commissioning.md printer note
The file was addedreference/jasper-reports/shipment-a5/M_InOut_Document_A5.jrxml
The file was addedreference/jasper-reports/shipment-a5/M_InOut_Lines_A5.jrxml
The file was modifiedserver/api/settings/commission-tables/update.put.ts (diff)
The file was modifiedapp/components/settings/CommissionTableForm.vue (diff)
The file was addedreference/jasper-reports/compile.groovy
The file was addedreference/jasper-reports/shipment-a5/M_InOut_Address_A5.jrxml
The file was addedreference/jasper-reports/shipment/Letterhead_Footer.jrxml
The file was added.claude/rules/printing/jasper-shipment-report.md
The file was addedreference/jasper-reports/shipment/M_InOut_Document.jrxml
The file was modified.claude/rules/fulfillment/commissioning.md (diff)
The file was addedreference/jasper-reports/shipment/M_InOut_OrgInfoblock.jrxml
The file was modifiedapp/pages/settings/commission-tables/[id]/edit.vue (diff)
The file was addedreference/jasper-reports/shipment/M_InOut_Address.jrxml
The file was addedreference/jasper-reports/shipment/M_InOut_Lines.jrxml
The file was addedreference/jasper-reports/styles.jrtx
The file was modifiedreference/README.md (diff)
The file was addedreference/jasper-reports/README.md
Commit d627fa5e4095ea494e9ff03bf2b75b2ec68bcb8f by info
Commission table form: badge hover no longer flickers (CSS scale was replacing the SVG translate → inner group scales), compact spacing like the partner form (8 px fields, dashed section heads, 2 rem inputs, smaller hero), grid 2/3 form + 1/3 side, rounded card accent bar, camera id 0 shown as empty
The file was modifiedapp/components/settings/CommissionTableForm.vue (diff)
The file was modifiedapp/pages/settings/commission-tables/[id]/edit.vue (diff)
Commit 252623b881525125812f6596c0af871d1d9b475c by info
LogShip Cloud offer: with the onboarding annex attached the offer prints only a price-less 'Onboarding-Paket – optional' position (details + price in the annex, forecast one-time row dropped); preview step shows all outgoing documents (offer / annex / flyer) as tabs and 'PDFs herunterladen (n)' saves them all (iframe keyed per doc — nuxt-lazy-load one-shot data-src)
The file was modified.claude/rules/offers/software-quote.md (diff)
The file was modifiedapp/composables/useOfferSoftwareQuote.ts (diff)
The file was modifiedapp/assets/langs/shared.js (diff)
The file was modifiedserver/utils/offers/softwareQuotePdf.ts (diff)
The file was modifiedapp/components/offers/SoftwareQuoteModal.vue (diff)
Commit 5c409d9126b9ab2e347f950c7422daa6b87d88ea by info
Printing: per-printer dispatch (local CUPS or LogShip Print Agent in the tenant LAN) — spool, agent protocol, settings UI

The 13 `lp` call sites (server/api/print/*, mobile reconditioning report) now go through
server/utils/printDispatch.ts: printFile()/printFiles() resolve the CUPS queue per printer —
no binding → local `lp` as before (execFile, whitelisted options, no shell string any more);
binding → job spooled for the tenant's Print Agent (status 'queued' + jobId, legacy
message/stdout fields kept). Storage root configurable (PRINT_STORAGE_DIR, default /root/storage);
the dead GET /api/print smoke route is removed.

Instance-local SQLite data/print-spool.db (server/utils/printSpoolDb.ts): agents (token hash,
heartbeat inventory/health), enrolment codes, printer→agent bindings keyed by CUST_Printer_ID
(no iDempiere column), jobs (queued→sent→spooled→completed|failed, batch id) and commands.
Agent protocol under /api/print-agent (enroll, heartbeat, long-poll jobs/next with inline files
≤ 300 KB, jobs/:id/file, jobs/ack, commands/:id/result, cups backup) — Bearer agent token.
Admin routes under /api/settings/print-agents (agents, enrol codes, bindings, jobs, commands,
status). Maintenance plugin re-queues stale 'sent' jobs and purges finished rows after 24 h.

Settings → Printers: Print-Agents card (online state, version, device queues with PPD label
size, queue depth, job stats, update/lpstat/restart-cups/journal/support-tunnel commands,
discovered queues → "Anlegen", job list with retry/cancel); printer form gets the per-printer
agent + device-queue picker; create/edit/duplicate save the binding after the iDempiere write.
labelMedia/cups-media read agent-reported label sizes for bound queues. Print-job feedback:
plugins/05.print-jobs.client.ts shows one toast per single job and one progress toast per
batch (SSE relay from the notifications plugin + cross-worker poll of jobs/mine).
The file was modifiedserver/api/printers/cups-media.get.ts (diff)
The file was addedserver/api/settings/print-agents/[id].delete.ts
The file was modifiedserver/api/print/product.post.ts (diff)
The file was addedserver/api/settings/print-agents/status.get.ts
The file was addedserver/api/print-agent/heartbeat.post.ts
The file was addedserver/api/settings/print-agents/bindings/[printerId].put.ts
The file was addedserver/plugins/print-spool-maintenance.ts
The file was addedapp/composables/usePrinterBinding.ts
The file was modifiedserver/api/fulfillment/generate-fee-report.post.ts (diff)
The file was modifiedapp/plugins/03.notifications-stream.client.ts (diff)
The file was modifiedserver/utils/labelMedia.ts (diff)
The file was addedserver/api/print-agent/backup.get.ts
The file was addedserver/api/print-agent/commands/[id]/result.post.ts
The file was modifiedserver/api/print/[id]/locator.post.ts (diff)
The file was modifiedserver/api/print/attachment-labels.post.ts (diff)
The file was modifiedserver/api/mobile/reconditioning/print-report.post.ts (diff)
The file was addedserver/api/print-agent/backup.post.ts
The file was addedserver/api/settings/print-agents/jobs/[id]/retry.post.ts
The file was modifiedapp/components/settings/PrinterForm.vue (diff)
The file was addedserver/api/settings/print-agents/enroll-code.post.ts
The file was modifiedserver/api/print/relabel-labels.post.ts (diff)
The file was modifiedserver/api/print/inout-labels.post.ts (diff)
The file was modifiedserver/api/print/labelprint.post.ts (diff)
The file was addedapp/components/settings/PrintAgentsCard.vue
The file was modifiedserver/api/print/index.post.ts (diff)
The file was modifiedserver/api/print/order-attachments.post.ts (diff)
The file was addedserver/api/settings/print-agents/index.get.ts
The file was addedserver/api/settings/print-agents/enroll-code/[code].delete.ts
The file was modifiedserver/api/print/[id]/product.post.ts (diff)
The file was addedserver/utils/printSpoolDb.ts
The file was modifiedserver/api/print/return-label.post.ts (diff)
The file was modifiedapp/pages/settings/printers/create.vue (diff)
The file was addedserver/api/settings/print-agents/[id]/command.post.ts
The file was addedserver/api/print-agent/jobs/next.get.ts
The file was addedserver/api/settings/print-agents/jobs/[id]/cancel.post.ts
The file was addedapp/plugins/05.print-jobs.client.ts
The file was addedserver/api/print-agent/jobs/[id]/file.get.ts
The file was modifiedserver/api/print/picklist.post.ts (diff)
The file was modifiedapp/pages/settings/printers/[id]/edit.vue (diff)
The file was modifiedapp/pages/settings/printers/index.vue (diff)
The file was addedserver/api/settings/print-agents/jobs/mine.get.ts
The file was addedserver/api/print-agent/jobs/ack.post.ts
The file was addedserver/utils/printDispatch.ts
The file was addedserver/api/settings/print-agents/[id].put.ts
The file was addedserver/utils/printAgentAuth.ts
The file was modifiedapp/pages/settings/printers/[id]/duplicate.vue (diff)
The file was modifiedserver/api/print/attachment-smart.post.ts (diff)
The file was addedserver/api/print-agent/enroll.post.ts
The file was addedserver/api/settings/print-agents/[id]/commands.get.ts
The file was addedserver/api/settings/print-agents/jobs/index.get.ts
The file was removedserver/api/print/index.get.ts
Commit defe0d60fe947f5da3b406eda1d06adef4eba43e by info
Print-Agents: remote printer administration on the device — 'Drucker einrichten' dialog (discover USB/network printers via lpinfo/ippfind, create CUPS queues with driver presets + media, test page, enable/disable/accept, cancel, remove) over the agent command channel; command whitelist extended; recipe .claude/rules/printing/print-agent.md
The file was modifiedapp/components/settings/PrintAgentsCard.vue (diff)
The file was added.claude/rules/printing/print-agent.md
The file was modifiedserver/utils/printSpoolDb.ts (diff)
Commit e8b6411756532146e174ac448b4b67c71ae4511b by info
Print-Agent: fresh-start poll re-queues the agent's claimed jobs at once (no 3-min wait after an agent restart)
The file was modifiedserver/api/print-agent/jobs/next.get.ts (diff)
The file was modifiedserver/utils/printSpoolDb.ts (diff)
Commit 8d0302a82681f4f1e8aa9238b31994d338bfd07d by info
Print-Agent: fresh-start reconcile list of unconfirmed spooled jobs; maintenance closes spooled jobs without completion report after 30 min
The file was modifiedserver/utils/printSpoolDb.ts (diff)
The file was modifiedserver/plugins/print-spool-maintenance.ts (diff)
The file was modifiedserver/api/print-agent/jobs/next.get.ts (diff)