-- ============================================================================= -- Alle Rechnungen pro Monat – Gesamt (ODOO + AMAZON) -- Odoo 17 / PostgreSQL -- -- Zweck: -- Liefert dieselben Spalten wie Rechnungsexport.sql (ODOO-Kundenrechnungen), -- aber zusammengefuehrt (UNION ALL) mit den Datensaetzen aus der Amazon- -- Tabelle brandize_datacenter_amazon_vat_transaction. Zusaetzlich gibt die -- Spalte "Quelle" an, aus welchem System die Zeile stammt ('ODOO'/'AMAZON'). -- -- Modelle: -- ODOO : account.move (Kundenrechnungen / Gutschriften) -- AMAZON : brandize_datacenter_amazon_vat_transaction -- -- Parameter: -- %(month)s Abrechnungszeitraum als Text, z. B. '2026-SEP' -- ODOO : Rechnungsdatum im Kalendermonat (siehe params-CTE) -- AMAZON: activity_period = %(month)s -- -- Aufruf (Odoo / psycopg2): -- cr.execute(open('Alle_Rechnungen.sql').read(), {'month': '2026-SEP'}) -- -- In psql stattdessen: -- \set month '2026-SEP' -- -- --------------------------------------------------------------------------- -- Spalten-Mapping ODOO -> AMAZON -- (Felder ohne Amazon-Pendant bleiben leer) -- --------------------------------------------------------------------------- -- Rechnungsdatum <- transaction_complete_date (Fallback: depart) -- Rechnungsnummer <- vat_inv_number -- Rechnungsland <- Name zu sale_arrival_country (res_country) -- Rechnungsland Code <- sale_arrival_country -- Zahlart <- '' (kein Amazon-Feld) -- Zahlungsreference <- transaction_event_id -- USt. Id Kaeufer <- buyer_vat_number -- Gesamtpreis brutto <- total_activity_value_amt_vat_incl -- Gesamtpreis netto <- total_activity_value_amt_vat_excl -- Brutto / -erm <- Steuersplit nach effektivem Satz (Schwelle -- USt. Satz / -erm CH >= 8, sonst >= 16 - wie im ODOO-Export) -- Netto Betrag / -erm Satz = total_activity_value_vat_amt / netto * 100 -- Versandkosten brutto <- total_ship_charge_amt_vat_incl -- Versandkosten netto <- total_ship_charge_amt_vat_excl -- Auftragsdatum <- transaction_depart_date -- Bestellnummer <- activity_transaction_id -- Zahldatum <- '' (kein Amazon-Feld) -- Lieferadresse Name <- buyer_name -- Tag <- '' (kein Amazon-Feld) -- Lieferland <- Name zu arrival_country (res_country) -- -- ACHTUNG: Das Amazon-Mapping ist eine 1:1-Uebertragung auf die ODOO-Spalten. -- Die Datumszuordnung (Rechnungsdatum/Auftragsdatum) sowie Bestellnummer -- sollten gegen die tatsaechliche Amazon-Report-Semantik geprueft und hier -- ggf. angepasst werden. -- ============================================================================= WITH params AS ( -- Kalendermonat aus %(month)s (z. B. '2026-SEP') ableiten (ODDO-Seite). SELECT to_date( split_part(%(month)s, '-', 1) || '-' || CASE upper(split_part(%(month)s, '-', 2)) WHEN 'JAN' THEN '01' WHEN 'FEB' THEN '02' WHEN 'MÄR' THEN '03' WHEN 'MAR' THEN '03' WHEN 'APR' THEN '04' WHEN 'MAI' THEN '05' WHEN 'MAY' THEN '05' WHEN 'JUN' THEN '06' WHEN 'JUL' THEN '07' WHEN 'AUG' THEN '08' WHEN 'SEP' THEN '09' WHEN 'OKT' THEN '10' WHEN 'OCT' THEN '10' WHEN 'NOV' THEN '11' WHEN 'DEZ' THEN '12' WHEN 'DEC' THEN '12' END, 'YYYY-MM' ) AS first_day ), -- =========================================================================== -- ODOO-Seite (identisch zu Rechnungsexport.sql) -- =========================================================================== invoices AS ( SELECT am.id, am.name, am.ref, am.move_type, am.invoice_date, am.invoice_origin, am.partner_id, am.partner_shipping_id, am.invoice_payment_term_id, am.payment_reference FROM account_move am CROSS JOIN params p WHERE am.invoice_date >= p.first_day AND am.invoice_date < p.first_day + INTERVAL '1 month' AND am.move_type IN ('out_invoice', 'out_refund') ), line_taxes AS ( SELECT aml.move_id AS invoice_id, at.amount AS tax_rate, SUM(aml.price_subtotal) AS netto, SUM(aml.price_total) AS brutto FROM invoices inv JOIN account_move_line aml ON aml.move_id = inv.id JOIN account_move_line_account_tax_rel amlatr ON amlatr.account_move_line_id = aml.id JOIN account_tax at ON at.id = amlatr.account_tax_id GROUP BY aml.move_id, at.amount ), tax_split AS ( SELECT lt.invoice_id, MAX(CASE WHEN (rc.code = 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 8) OR (COALESCE(rc.code, '') <> 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 16) THEN ROUND(lt.brutto::numeric, 2) END) AS brutto_normal, MAX(CASE WHEN (rc.code = 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 8) OR (COALESCE(rc.code, '') <> 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 16) THEN ROUND(lt.tax_rate::numeric, 2) END) AS ust_satz_normal, MAX(CASE WHEN (rc.code = 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 8) OR (COALESCE(rc.code, '') <> 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 16) THEN ROUND(lt.netto::numeric, 2) END) AS netto_normal, MAX(CASE WHEN NOT ( (rc.code = 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 8) OR (COALESCE(rc.code, '') <> 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 16) ) THEN ROUND(lt.brutto::numeric, 2) END) AS brutto_erm, MAX(CASE WHEN NOT ( (rc.code = 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 8) OR (COALESCE(rc.code, '') <> 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 16) ) THEN ROUND(lt.tax_rate::numeric, 2) END) AS ust_satz_erm, MAX(CASE WHEN NOT ( (rc.code = 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 8) OR (COALESCE(rc.code, '') <> 'CH' AND ROUND(lt.tax_rate::numeric, 2) >= 16) ) THEN ROUND(lt.netto::numeric, 2) END) AS netto_erm FROM line_taxes lt JOIN invoices inv ON inv.id = lt.invoice_id JOIN res_partner rp ON rp.id = inv.partner_id LEFT JOIN res_country rc ON rc.id = rp.country_id GROUP BY lt.invoice_id ), shipping AS ( SELECT aml.move_id AS invoice_id, ROUND(SUM(aml.price_total)::numeric, 2) AS shipping_brutto, ROUND(SUM(aml.price_subtotal)::numeric, 2) AS shipping_netto FROM invoices inv JOIN account_move_line aml ON aml.move_id = inv.id JOIN product_product pp ON pp.id = aml.product_id JOIN product_template pt ON pt.id = pp.product_tmpl_id WHERE pt.categ_id = 9 GROUP BY aml.move_id ), invoice_tags AS ( SELECT inv.id AS invoice_id, STRING_AGG( DISTINCT COALESCE(ct.name->>'en_US', ct.name->>'de_DE', ''), ', ' ORDER BY COALESCE(ct.name->>'en_US', ct.name->>'de_DE', '') ) AS tags FROM invoices inv JOIN sale_order so ON so.name = inv.invoice_origin JOIN sale_order_tag_rel sotr ON sotr.order_id = so.id JOIN crm_tag ct ON ct.id = sotr.tag_id GROUP BY inv.id ), invoice_transaction_reference AS ( SELECT rel.invoice_id, pt.provider_reference, ROW_NUMBER() OVER ( PARTITION BY rel.invoice_id ORDER BY pt.id ) AS rn FROM account_invoice_transaction_rel rel JOIN payment_transaction pt ON pt.id = rel.transaction_id ), sale_info AS ( SELECT inv.id AS invoice_id, MIN(so.date_order) AS order_date FROM invoices inv JOIN sale_order so ON so.name = inv.invoice_origin GROUP BY inv.id ), invoice_payments AS ( SELECT aml.move_id AS invoice_id, MAX(apr.max_date) AS payment_date FROM invoices inv JOIN account_move_line aml ON aml.move_id = inv.id JOIN account_account aa ON aa.id = aml.account_id AND aa.account_type = 'asset_receivable' JOIN account_partial_reconcile apr ON apr.debit_move_id = aml.id OR apr.credit_move_id = aml.id GROUP BY aml.move_id ), odoo_rows AS ( SELECT TO_CHAR(inv.invoice_date, 'YYYY-MM-DD') AS "Rechnungsdatum", CASE WHEN inv.move_type = 'out_refund' THEN COALESCE(inv.name, inv.ref, '') || '-gs' ELSE COALESCE(inv.name, inv.ref, '') END AS "Rechnungsnummer", COALESCE(rc_inv.name->>'en_US', rc_inv.name->>'de_DE', '') AS "Rechnungsland", COALESCE(rc_inv.code, '') AS "Rechnungsland Ländercode", COALESCE(apt.name->>'en_US', apt.name->>'de_DE', '') AS "Zahlart", COALESCE(itr.provider_reference, '') AS "Zahlungsreference der Bestellung", COALESCE(partner.vat, '') AS "USt. Id / VAT Id des Käufers (in Bestellung)", ROUND(COALESCE(ts.brutto_normal, 0) + COALESCE(ts.brutto_erm, 0), 2) AS "Gesamtpreis brutto", ROUND(COALESCE(ts.netto_normal, 0) + COALESCE(ts.netto_erm, 0), 2) AS "Gesamtpreis netto", COALESCE(ts.brutto_normal, 0) AS "Brutto", COALESCE(ts.brutto_erm, 0) AS "Brutto erm", COALESCE(ts.ust_satz_normal, 0) AS "USt. Satz", COALESCE(ts.ust_satz_erm, 0) AS "Ust. Satz erm", COALESCE(ts.netto_normal, 0) AS "Netto Betrag", COALESCE(ts.netto_erm, 0) AS "Netto Betrag erm", COALESCE(sh.shipping_brutto, 0) AS "Versandkosten brutto", COALESCE(sh.shipping_netto, 0) AS "Versandkosten netto", COALESCE(TO_CHAR(si.order_date, 'YYYY-MM-DD'), '') AS "Auftragsdatum", COALESCE(inv.invoice_origin, '') AS "Bestellnummer", COALESCE(TO_CHAR(ip.payment_date, 'YYYY-MM-DD'), '') AS "Zahldatum", COALESCE(ship.name, partner.name, '') AS "Lieferadresse Name", COALESCE(it.tags, '') AS "Tag", COALESCE( rc_ship.name->>'en_US', rc_ship.name->>'de_DE', rc_inv.name->>'en_US', rc_inv.name->>'de_DE', '' ) AS "Lieferland" FROM invoices inv JOIN res_partner partner ON partner.id = inv.partner_id LEFT JOIN res_country rc_inv ON rc_inv.id = partner.country_id LEFT JOIN res_partner ship ON ship.id = inv.partner_shipping_id LEFT JOIN res_country rc_ship ON rc_ship.id = ship.country_id LEFT JOIN account_payment_term apt ON apt.id = inv.invoice_payment_term_id LEFT JOIN tax_split ts ON ts.invoice_id = inv.id LEFT JOIN shipping sh ON sh.invoice_id = inv.id LEFT JOIN invoice_tags it ON it.invoice_id = inv.id LEFT JOIN invoice_transaction_reference itr ON itr.invoice_id = inv.id AND itr.rn = 1 LEFT JOIN sale_info si ON si.invoice_id = inv.id LEFT JOIN invoice_payments ip ON ip.invoice_id = inv.id ), -- =========================================================================== -- AMAZON-Seite -- =========================================================================== -- Basiszahlen + effektiver USt-Satz je Transaktionszeile. amazon_base AS ( SELECT a.transaction_complete_date, a.transaction_depart_date, a.vat_inv_number, a.sale_arrival_country, a.arrival_country, a.transaction_event_id, a.buyer_vat_number, a.buyer_name, a.activity_transaction_id, COALESCE(a.total_activity_value_amt_vat_incl, 0) AS gross, COALESCE(a.total_activity_value_amt_vat_excl, 0) AS net, COALESCE(a.total_ship_charge_amt_vat_incl, 0) AS ship_gross, COALESCE(a.total_ship_charge_amt_vat_excl, 0) AS ship_net, CASE WHEN COALESCE(a.total_activity_value_amt_vat_excl, 0) <> 0 THEN ROUND((COALESCE(a.total_activity_value_vat_amt, 0) / a.total_activity_value_amt_vat_excl * 100)::numeric, 2) ELSE 0 END AS rate FROM brandize_datacenter_amazon_vat_transaction a WHERE a.activity_period = %(month)s -- Optional: Gebuehrenzeilen ausschliessen (wie in VAT_Summary.sql): -- AND a.sales_channel <> 'AMAZON_FEE' ), amazon_rows AS ( SELECT TO_CHAR(COALESCE(b.transaction_complete_date, b.transaction_depart_date), 'YYYY-MM-DD') AS "Rechnungsdatum", COALESCE(b.vat_inv_number, '') AS "Rechnungsnummer", COALESCE(rc_inv.name->>'en_US', rc_inv.name->>'de_DE', '') AS "Rechnungsland", COALESCE(b.sale_arrival_country, '') AS "Rechnungsland Ländercode", '' AS "Zahlart", COALESCE(b.transaction_event_id, '') AS "Zahlungsreference der Bestellung", COALESCE(b.buyer_vat_number, '') AS "USt. Id / VAT Id des Käufers (in Bestellung)", ROUND(b.gross::numeric, 2) AS "Gesamtpreis brutto", ROUND(b.net::numeric, 2) AS "Gesamtpreis netto", CASE WHEN (b.sale_arrival_country = 'CH' AND b.rate >= 8) OR (COALESCE(b.sale_arrival_country, '') <> 'CH' AND b.rate >= 16) THEN ROUND(b.gross::numeric, 2) ELSE 0 END AS "Brutto", CASE WHEN NOT ( (b.sale_arrival_country = 'CH' AND b.rate >= 8) OR (COALESCE(b.sale_arrival_country, '') <> 'CH' AND b.rate >= 16) ) THEN ROUND(b.gross::numeric, 2) ELSE 0 END AS "Brutto erm", CASE WHEN (b.sale_arrival_country = 'CH' AND b.rate >= 8) OR (COALESCE(b.sale_arrival_country, '') <> 'CH' AND b.rate >= 16) THEN b.rate ELSE 0 END AS "USt. Satz", CASE WHEN NOT ( (b.sale_arrival_country = 'CH' AND b.rate >= 8) OR (COALESCE(b.sale_arrival_country, '') <> 'CH' AND b.rate >= 16) ) THEN b.rate ELSE 0 END AS "Ust. Satz erm", CASE WHEN (b.sale_arrival_country = 'CH' AND b.rate >= 8) OR (COALESCE(b.sale_arrival_country, '') <> 'CH' AND b.rate >= 16) THEN ROUND(b.net::numeric, 2) ELSE 0 END AS "Netto Betrag", CASE WHEN NOT ( (b.sale_arrival_country = 'CH' AND b.rate >= 8) OR (COALESCE(b.sale_arrival_country, '') <> 'CH' AND b.rate >= 16) ) THEN ROUND(b.net::numeric, 2) ELSE 0 END AS "Netto Betrag erm", ROUND(b.ship_gross::numeric, 2) AS "Versandkosten brutto", ROUND(b.ship_net::numeric, 2) AS "Versandkosten netto", COALESCE(TO_CHAR(b.transaction_depart_date, 'YYYY-MM-DD'), '') AS "Auftragsdatum", COALESCE(b.activity_transaction_id, '') AS "Bestellnummer", '' AS "Zahldatum", COALESCE(b.buyer_name, '') AS "Lieferadresse Name", '' AS "Tag", COALESCE(rc_ship.name->>'en_US', rc_ship.name->>'de_DE', '') AS "Lieferland" FROM amazon_base b LEFT JOIN res_country rc_inv ON rc_inv.code = b.sale_arrival_country LEFT JOIN res_country rc_ship ON rc_ship.code = b.arrival_country ) -- =========================================================================== -- Zusammenfuehrung: ODOO + AMAZON, je Zeile mit Quelle -- =========================================================================== SELECT *, 'ODOO' AS "Quelle" FROM odoo_rows UNION ALL SELECT *, 'AMAZON' AS "Quelle" FROM amazon_rows ORDER BY "Rechnungsdatum", "Rechnungsnummer";