Commit Graph

7 Commits

Author SHA1 Message Date
Gerhard Scheikl f16ef4e103 fix(invoice): drop fulfillmentOrders query (scope-denied), keep shippingLine pickup heuristic
Querying Order.fulfillmentOrders.deliveryMethod requires the
read_merchant_managed_fulfillment_orders scope (not read_orders, despite
what shopify.dev claims) and was failing with 'Access denied for
fulfillmentOrders field' against real stores.

Adding that scope would force every install to re-grant permissions, so
instead we rely on shippingLine alone:

- Shopify Local Pickup app: shippingLine.code = 'Pickup' (caught by the
  regex) and shippingLine.title is the chosen location name itself   (e.g. 'Lager Graz') \u2014 perfect as pickupLocationName.
- Custom-rate pickup ('Abholung im Lager'): regex matches title/code,
  title is used as the location hint.

Removes RawDeliveryMethod, the deliveryMethods field on RawOrderForInvoice,
and the fulfillmentOrders edges from RawAdminResponse.
2026-05-15 15:04:16 +02:00
Gerhard Scheikl d742e75419 fix(invoice): detect pickup via DeliveryMethodType and show 'Abholort: <location>' meta row
- Use Order.fulfillmentOrders.deliveryMethod.methodType === 'PICK_UP' as the
  primary signal (Shopify Local Pickup app exposes this reliably; the
  shippingLine title is just the location name with no 'pickup' keyword).
  Keep the legacy shippingLine string heuristic as a fallback for custom
  shipping rates merchants name 'Abholung'/'Pickup'.
- Surface assignedLocation.name as pickupLocationName on the view model.
- Replace the 'Versandart: <location name>' row with 'Abholort: <location>'
  (DE) / 'Pick-up location: <location>' (EN); falls back to plain
  'Abholung'/'Pick-up' when the location name is unavailable.
2026-05-15 14:46:55 +02:00
Gerhard Scheikl 415a9dd462 feat(invoice): per-line + cart discounts, fulfillment delivery date, pickup label, header layout refresh
- discounts: read discountedUnitPriceSet (per-line) and discountCode/discountCodes
  (order-level) from Shopify; render discounted unit price with strikethrough
  original on the invoice line and add a 'Rabattcode'/'Discount code' meta row
  when codes were used.
- delivery date: pick the latest fulfillment.createdAt for §11 UStG instead of
  hard-coding processedAt; fall back to invoice date when unfulfilled.
- pickup: detect Shopify Local Pickup (and 'Abholung'/'Pickup' custom rates) via
  shippingLine.source/code/title; suppress the pickup-location 'shipping address'
  block and render localized 'Abholung'/'Pick-up' as the shipping method.
- layout: move the company logo to the top-left and the meta block to the
  top-right, putting recipient (and any separate delivery address) on its own
  row below; drop the standalone invoice-/order-number meta rows and surface
  them inside the title (e.g. 'Rechnung Nr. RE-1004 · Bestellnummer: #1004') to
  recover vertical space.
- tests: smoke fixtures cover discount, pickup, and fulfillment-date variants
  without disturbing the AT B2B totals.
2026-05-15 13:59:08 +02:00
Gerhard Scheikl 8780b4a68a feat(invoice): add Shopify order #, shipping address/method/cost and tracking
- Query Order.shippingLine and Order.fulfillments.trackingInfo from Admin GraphQL.
- Surface orderName (#1004) so customers recognise their order alongside the sequential invoice number.
- Render shipping cost as a synthetic line item (folds into the VAT breakdown).
- Show shipping method (Versandart / Shipping method) and tracking numbers (clickable when URL present) in the meta block.
- Render a separate delivery-address block when the shipping address differs from billing.
- DE strings stay informal (Versandart / Sendungsnummer / Lieferadresse / Versand).
2026-05-15 13:41:53 +02:00
Gerhard Scheikl 55a0dd03f2 feat(invoice): informal German tone + show payment method and status
- i18n.de: switch Sie/Ihren to du/dein for salutation, thank-you line,
  customer-VAT label and payment-terms paragraph. Closing line was
  already informal.
- i18n: add paymentMethodLabel/paymentStatusLabel + per-status labels
  (paid/unpaid/partial/refunded) for both DE and EN, plus
  derivePaymentStatus helper that condenses Shopify's
  displayFinancialStatus (PAID, PARTIALLY_PAID, REFUNDED, …) into a
  4-value enum.
- loadOrderForInvoice: query Order.paymentGatewayNames and propagate it
  on the raw view-model.
- composeInvoice + types: expose paymentStatus + paymentGatewayNames on
  InvoiceViewModel (filtered/trimmed). loadDraftOrderForOffer keeps
  paymentGatewayNames empty (drafts have no gateway yet).
- InvoiceDocument: render two new meta rows on real invoices —
  'Zahlart / Payment method' (joined, prettified gateway names) and
  'Zahlstatus / Payment status' (translated label). Storno + offer kinds
  intentionally omit them.
- scripts/render-sample.ts: extend smoke checks to assert the informal
  DE wording, the new payment-method/status rows and the
  paymentStatus/paymentGatewayNames composer outputs.
2026-05-15 11:26:26 +02:00
Gerhard Scheikl 770c6fd16a many updates :-) 2026-05-08 10:40:19 +02:00
Gerhard Scheikl 5b2aa5d62b first version 2026-04-28 21:56:11 +02:00