2025-11-21: Invoice Generation Fix & Module Refactor¶
Probleem: Dubbele Facturen (Pending + Paid)¶
User 44 had 4 facturen voor 2 orders: - VG-2025-024 (pending) + VG-2025-023 (paid) voor order 27 - VG-2025-022 (pending) + VG-2025-021 (paid) voor order 26
Oorzaak¶
Commerce Invoice module genereerde automatisch facturen bij:
1. Order placed (validation → pending) via OrderPlacedSubscriber
2. Order paid (Mollie callback) via status update
Resultaat: 2 invoices per order (1 pending, 1 paid).
Oplossing¶
Custom Event Subscriber die alleen facturen genereert bij betaalde orders:
-
Automatische generatie uitgeschakeld:
-
Custom subscriber (
OrderPaidInvoiceSubscriber): - Luistert naar
commerce_order.order.paidevent - Checkt of invoice al bestaat (voorkomt duplicaten)
- Genereert invoice alleen voor betaalde orders
Implementatie¶
Bestand: /web/modules/custom/vg_commerce/src/EventSubscriber/OrderPaidInvoiceSubscriber.php
Service registratie in vg_commerce.services.yml:
vg_commerce.order_paid_invoice_subscriber:
class: Drupal\vg_commerce\EventSubscriber\OrderPaidInvoiceSubscriber
arguments: ['@commerce_invoice.invoice_generator', '@entity_type.manager']
tags:
- { name: event_subscriber }
Cleanup¶
Pending invoices verwijderd (alleen dev, productie: credit notes!): - VG-2025-002, 016, 022, 024 (pending)
User 44 heeft nu 2 correcte paid invoices: - VG-2025-021 voor order 26 - VG-2025-023 voor order 27
Module Refactor: vg_commerce_tax → vg_commerce¶
Reden¶
Module vg_commerce_tax bevatte meer dan alleen tax logic:
- Tax rate resolver (BTW 21% NL, 0% buiten NL)
- Shipping tax subscriber
- Invoice generation subscriber
- Gin theme fixes (invoice page crash)
- Checkout conditional fields
Naam was misleidend → hernoemen naar vg_commerce.
Hernoem Proces¶
- Module uninstall (config behouden)
- Directory + files hernoemen
- Namespaces updaten (
Drupal\vg_commerce_tax→Drupal\vg_commerce) - Services updaten (
vg_commerce_tax.*→vg_commerce.*) - Hook functions hernoemen (
vg_commerce_tax_*→vg_commerce_*) - Module reinstall
Module Structuur¶
web/modules/custom/vg_commerce/
├── vg_commerce.info.yml
├── vg_commerce.module (hooks: menu_links, preprocess_page, form_alter)
├── vg_commerce.services.yml
└── src/
├── TaxRateResolver.php
└── EventSubscriber/
├── ShippingTaxSubscriber.php
└── OrderPaidInvoiceSubscriber.php
Services¶
vg_commerce.tax_rate_resolver- BTW berekeningvg_commerce.shipping_tax_subscriber- BTW op verzendkostenvg_commerce.order_paid_invoice_subscriber- Invoice generatie bij betaling
Boekhoudregels¶
Belangrijk: Facturen NOOIT zomaar verwijderen in productie! - Gebruik credit notes/credit facturen - Verwijderen alleen in dev voor cleanup - Factuurnummers moeten sequentieel blijven
Testing¶
Test scenario: 1. Maak nieuwe order als authenticated user 2. Betaal via Mollie sandbox 3. Verifieer: 1 invoice met status "paid" (geen pending duplicate)
ECA Opmerking¶
Commerce Invoice module heeft geen native ECA actions voor invoice generation. Daarom custom Event Subscriber gebruikt (betrouwbaarder, geen UI overhead).