Dhaka, Bangladesh
Case Studies

Extending One Partial-Payment Layer to Four WooCommerce Deposit Plugins

Cover image for the case study "Extending One Partial-Payment Layer to Four WooCommerce Deposit Plugins"

Quick answer

Four deposit plugins - Acowebs, WooCommerce Deposits, YITH Deposits and WowStore - feeding one partial-payment layer that returns the same paid, remaining and total shape to every WowInvoice invoice template.
WowInvoice, a WooCommerce PDF invoice plugin by WPXPO, shows deposit and balance amounts on invoices for orders paid in installments. Four deposit plugins now feed that through one partial-payment layer. The layer and its first provider already existed. I made the existing provider read payment schedules and added WooCommerce Deposits and WowStore. I also wired YITH Deposits back in, and added the rule that every invoice resolves to the parent order.

TL;DR

Stat strip: four deposit plugins supported, three providers added or re-enabled, the layer grown from 350 to 1,138 lines, and one parent-order rule.
TL;DR summary
ProblemEach deposit plugin stores deposits, balances, and totals in a different place
Starting pointAn existing provider layer with Acowebs support, and a YITH provider that had been switched off
What I addedAcowebs payment schedules, WooCommerce Deposits, YITH re-enabled, WowStore, paid dates on invoices
Key ruleA balance or installment order always resolves to its parent, so one order never gets two invoices
StatusLater removed from the free WordPress.org build of this repository
TeamMe, with guidance from Samin Yaser, who wrote the original layer

What I started from

The starting layer: a provider list returning a shared paid, remaining and total shape, with an active Acowebs provider reading order-level meta and a YITH provider that was written but commented out.
Samin Yaser wrote the partial-payment layer in June. It was a list of providers, each returning the same shape: what's paid, what remains, and the total. It supported Acowebs Deposits & Partial Payments by reading order-level meta. A YITH provider was wired in and switched off again on the same day. My work started in August, and I kept his shape. Every provider I added returns the same fields, so the invoice templates never need to know which plugin an order came from.

Four plugins, four data shapes

A comparison grid: Acowebs stores deposit state on the order, WooCommerce Deposits on each line item, YITH on both, and each creates follow-up orders differently - reference suborders, true child orders, or one-or-more balance suborders.
The four plugins solve the same problem in incompatible ways. Acowebs keeps deposit state on the order, and WooCommerce Deposits keeps it on each line item. YITH uses both. They also differ on follow-up payments. Acowebs tracks reference suborders, WooCommerce Deposits creates true child orders, and YITH can create several balance orders for one deposit. I installed each plugin locally and wrote a compatibility doc from its source code rather than its documentation. Each doc records the actual meta keys, the file and line where they're set, and how the plugin differs from the others. Acowebs had its own trap. Once an order has a payment schedule, the flat "deposit paid" flags aren't always kept in sync, so I made the provider read each scheduled payment's own order status, the same way Acowebs's own admin panel does.

The rule: invoice the parent

A balance order created by WooCommerce Deposits or YITH resolving up to its parent order, which owns the single invoice number, while the child order is crossed out as a separate invoice.
WowInvoice numbers invoices per WooCommerce order. If a deposit plugin creates a separate order for the balance, invoicing that order naively gives one purchase two invoice numbers. So I added a single resolution step. If an order is a WooCommerce Deposits or YITH follow-up order, the layer reads from its parent instead. Acowebs suborders are deliberately left out of that rule. They're reference records that are never invoiced directly, so they never need it.

The total you can't trust

Two parent orders for the same deposit: in WooCommerce Deposits the order total is only the scaled-down deposit and the real total must be rebuilt from line-item meta, while in YITH the order total already is the deposit charge.
In WooCommerce Deposits, the parent order's total is not the order's value. The plugin scales each deposit line item down at checkout, so the total equals only the deposit charged. The provider rebuilds the real total from the full-price meta stored on each line item. I also made line items show their real full price on the invoice, not the scaled-down deposit price. YITH is the opposite. Its parent order total already is the deposit charge, and the YITH doc flags it as a case not to "fix" by analogy with WooCommerce Deposits. WowStore, WPXPO's own store plugin, was the fourth provider, added a month later. By then the layer had grown from 350 to 1,138 lines.

Where this code lives now

The repository's free WordPress.org branch after a September commit that removed the partial-payment layer along with credit notes, UBL and bulk export, with a dashed box marking that the repository doesn't show where they went.
In mid-September, the same commit that removed credit notes from this repository also removed the partial-payment layer and its paid-date helper. It landed on the free WordPress.org build. That suggests a free and Pro split, but this repository doesn't show where the code went. This case study describes it as it existed here.

FAQ

Four why-questions with compressed answers: reading plugin source, keeping the existing shape, resolving to the parent order, and rebuilding the WooCommerce Deposits total.

Why read each plugin's source instead of its documentation?

The details that decide whether an invoice is right, like which total is real and where follow-up orders come from, live in each plugin's checkout code. Reading it let me record exact meta keys and the lines that set them instead of guessing.

Why keep the existing provider shape instead of redesigning the layer?

The shape already did its job: templates read paid, remaining, and total without knowing the source plugin. Adding providers to it kept every template unchanged.

Why resolve every follow-up order to its parent?

WowInvoice numbers invoices per WooCommerce order, so invoicing a balance order directly would give one purchase two numbers. Letting the parent own the document keeps one purchase on one invoice, and the child orders only inform it.

Why rebuild the WooCommerce Deposits total instead of using the order total?

The order total there is only the deposit, so trusting it would print a deposit as if it were the whole order. The full price is still on each line item, so rebuilding from that keeps the invoice honest. Other case studies in this series cover credit notes that show what was actually refunded → and linking shared template parts to the live preview's settings →.
Part of the WowInvoice frontend engineering case study series →
On this page
Quick answer
TL;DR
What I started from
Four plugins, four data shapes
The rule: invoice the parent
The total you can't trust
Where this code lives now
FAQ
Why read each plugin's source instead of its documentation?
Why keep the existing provider shape instead of redesigning the layer?
Why resolve every follow-up order to its parent?
Why rebuild the WooCommerce Deposits total instead of using the order total?