# jasper-reports/ — iDempiere Jasper templates (ops-staging copies)

Copies of the JasperReports templates that live on the iDempiere host
(`192.168.12.72:/opt/idempiere-server/data/reports/`). The app only calls
`models/m_inout/{id}/print` (A4, process "Shipment A4 Jasper" 10000001) or
`POST processes/10000002` (A5 packing slip); the rendering happens in iDempiere.

| Folder | Server path | Used by |
|--------|-------------|---------|
| `shipment/` | `data/reports/shipment/` | shipment print preview / print / mail (A4) |
| `shipment-a5/` | `data/reports/shipment-a5/` | A5 packing slip process |
| `invoice/` | `data/reports/` (root folder!) | invoice print (process 1000003 "Invoice Jasper" → `C_Invoice_Document.jrxml`; `report/` + `report/backup/` on the host are stale copies) |
| `styles.jrtx` | `data/reports/styles.jrtx` (+ a copy per folder) | shared styles |

`shipment/shipper/<M_Shipper_ID>.png` (carrier logos) stays on the server only.

## Deploy + compile

iDempiere does **not** reliably recompile a changed `.jrxml` (stale `.jasper` files
next to newer `.jrxml` were observed), so compile explicitly — there is no `javac`
on the host, but Groovy ships with the Jasper plugin:

```bash
ssh root@192.168.12.72 'cd /opt/idempiere-server/data/reports && cp -a shipment shipment.bak-$(date +%Y%m%d)'
scp reference/jasper-reports/shipment/*.jrxml root@192.168.12.72:/opt/idempiere-server/data/reports/shipment/
scp reference/jasper-reports/compile.groovy root@192.168.12.72:/root/jasper-compile/compile.groovy
ssh root@192.168.12.72 'cd /opt/idempiere-server/data/reports && \
  java -cp "/opt/idempiere-server/plugins/*" groovy.ui.GroovyMain /root/jasper-compile/compile.groovy \
    shipment/M_InOut_Document.jrxml shipment/M_InOut_OrgInfoblock.jrxml && \
  chown idempiere:idempiere shipment/*'
```

No iDempiere restart needed; the next print picks up the new `.jasper`.
Verify with the service token: `GET $URLV1/models/m_inout/<id>/print?$report_type=PDF` → `reportFile` (base64).

## Pickup vs. delivery (2026-10-30)

`M_InOut.DeliveryViaRule = 'P'` (Abholung) switches the "Versand via <carrier>" box to
"Abholung / Selbstabholung" (no carrier logo), relabels "Lieferdatum" → "Abholdatum" and
prints a "WARE ERHALTEN (ABHOLUNG)" signature box (Datum / Unterschrift) right of the
barcode — on A4 (`M_InOut_Document.jrxml` + `M_InOut_OrgInfoblock.jrxml`) and A5
(`M_InOut_Document_A5.jrxml`). Everything else keys off `M_Shipper_ID` as before.

## Org logo in templates (2026-11-02)

Always feed the logo as raw bytes: `LEFT JOIN ad_image img ON img.ad_image_id = <logo_id>` →
`img.binarydata AS logo_data` (field class `java.io.InputStream`) → `<imageExpression>$F{logo_data}</imageExpression>`.
Never `$P{COLUMN_LOOKUP}.apply("image", id)` — that returns an AWT image which Jasper re-encodes as JPEG, so a
transparent PNG prints on a black block (the invoice bug). The invoice template also prints
`COALESCE(companyname, name)` as text in the logo slot when the org has no logo (`printWhenExpression` pair).
Logos / letterhead fields are maintained on `/edit/organization-<id>` (AD_OrgInfo: Logo_ID = AD_Image,
LY_Subtitle, ReceiptFooterMsg, TaxID, Phone/Fax/EMail, C_Location_ID, TransferBank_ID). Compile after
deploying: `java -cp "/opt/idempiere-server/plugins/*" groovy.ui.GroovyMain /root/jasper-compile/compile.groovy C_Invoice_Document.jrxml`.
