Cash on delivery (COD)¶
Cash on delivery (COD) lets a webshop customer pay for an order in cash (or by card) at the moment the parcel is handed over, instead of paying online at checkout. Because a single sales order can ship in several physical packages — a multi-step warehouse route, an out-of-stock backorder, a partial delivery — the amount to collect on each package must be computed individually, and the risk of an unreliable COD customer must be screened before the order is confirmed. eYssen covers both problems with two focused modules: one computes the correct COD amount per shipment for the carrier integrations, the other gates cash-on-delivery-style payment methods at checkout against the shared utanvet-ellenor.hu fraud database.
Key features¶
Dynamic, per-package COD computation. Each outgoing delivery gets its own COD amount, proportionate to the goods it actually contains, so partial and multi-step shipments never over- or under-charge the customer.
One computation shared by every carrier. GLS, Foxpost and MPL each call the same underlying method when building their shipping label request, so the business rule lives in a single place instead of being duplicated per carrier.
Shared fraud-database check at checkout. Payment providers can be individually flagged to be hidden from customers with a poor reputation on the Utánvét Ellenőr shared database, before the order is even placed.
Fail-open by default. If the fraud-check API is unreachable, checkout is not blocked unless an administrator explicitly opts into the stricter policy.
Closed-loop reporting. Successful and failed/cancelled deliveries are reported back to Utánvét Ellenőr asynchronously, so the shared database stays accurate for every merchant using it.
How the COD amount is computed¶
The eyssen_delivery_cod module adds a read-only cod_amount field to
Transfers (stock.picking) and a single method,
_compute_dynamic_cod(), that carrier integrations call while preparing a
shipment. It is not triggered automatically — GLS (eyssen_delivery_gls),
Foxpost (eyssen_delivery_foxpost) and MPL (eyssen_delivery_mpl) each
depend on eyssen_delivery_cod and call the method with their own
“Payment on Delivery” provider’s XML ID when they build the shipping label
request for a picking.
The method only computes an amount when the sales order’s last payment
transaction is on that carrier’s own “Payment on Delivery” provider; for
any other payment method it returns 0.0 and logs a warning. When it does
apply, the amount is built up as follows:
Goods value of this package — for every stock move in the picking that is linked to a sale order line, the line’s unit price (
price_total÷product_uom_qty, i.e. tax included) is multiplied by the quantity actually shipped in this picking.Goods value already shipped — the same calculation is repeated for every other picking on the same order that already has a
cod_amountset, i.e. packages that shipped earlier.Service lines — order lines that are not stockable/consumable products and are not a down payment (for example shipping surcharges) are added to the cumulative total in full.
Invoiced down payments — down-payment order lines with an invoiced quantity are computed with taxes (via
tax_id.compute_all) and subtracted from the cumulative total.Amount already collected — the sum of
cod_amounton the sibling pickings that already shipped is subtracted from the cumulative target to get the amount still owed.Order total cap — the result is capped so the sum of everything collected across all packages of the order never exceeds the order’s
amount_total.
Note
Because the cumulative target already includes service lines from the first computation onward, and every later package subtracts what earlier packages already collected, in practice the customer only pays for service lines once — together with the first package that ships.
The resulting amount is stored on stock.picking.cod_amount and shown,
read-only, on the delivery form right after the Carrier field
(hidden while it is zero). Each carrier module then uses that amount to fill
in the “collect on delivery” field of its own label request. Some carriers
additionally enforce their own hard ceiling on top of this computation — for
example Foxpost refuses to generate a label above 150 000 HUF.
Important
eyssen_delivery_cod has no configuration screen of its own. It only
becomes active once a carrier module that depends on it (GLS, Foxpost or
MPL) is installed and the customer pays through that carrier’s own
“Payment on Delivery” method.
The Utánvét Ellenőr fraud check at checkout¶
The utanvetellenor module integrates the utanvet-ellenor.hu shared customer-reputation database, which
several Hungarian webshops feed with delivery outcomes. It plugs into two
points of the order lifecycle: filtering payment methods at checkout, and
reporting the delivery outcome back afterwards.
Filtering payment providers at checkout¶
The module extends the payment provider’s compatible-providers lookup so that any Payment Provider with Utánvét Ellenőr Check enabled is only offered to customers whose reputation clears the configured threshold.
If no enabled provider has the check turned on, the module does nothing — there is no performance cost for shops that don’t use it.
Before calling the API, the module verifies that the checkout partner is either the current user’s own partner, a contact in the same commercial entity, or that the caller is an internal user — this stops the endpoint from being used to probe the reputation of an arbitrary customer.
The customer’s e-mail, phone (normalised to E.164 through
phone_validationwhen installed), country code, ZIP code and street address are sent to the/requestendpoint together with the configured reputation threshold; name, payment data and tax numbers are never sent.The verdict is cached in memory per worker process for five minutes, keyed on company, partner, the partner’s
write_date, the threshold and the mode — so any local edit to the partner’s contact details immediately invalidates the cached verdict.The API’s HTTP response is translated into a decision: a
blockedresult, a204(temporary/non-existent mailbox), a missing e-mail, or a404(unknown customer, always allowed) are all handled explicitly.401(bad keys) and402(quota exhausted) are logged but never block checkout by themselves — only genuine transport failures (timeout, connection error, 5xx) and quota errors are subject to the fallback policy below.
Important
When the customer is blocked, or a transport/quota error occurs while Fallback on API Error is set to Block payment, every provider that has Utánvét Ellenőr Check enabled is removed from the list of payment methods offered at checkout. Providers that don’t opt in — for example a card payment method — are never affected.
Every API call that results in a block or an error can be logged as an internal note on the customer, controlled by the Chatter Verbosity setting:
The note records the mode, threshold, HTTP status, the API’s good/bad counts, the numeric reputation and the verbatim reason — never the API keys.
Reporting the outcome back¶
Once an outgoing delivery linked to a sale order paid through a guarded provider is validated or cancelled, the module queues a signal so the shared database learns the outcome:
validating the transfer (
_action_done) queues outcome1(Successful delivery (+1));cancelling the transfer (
action_cancel) queues outcome-1(Failed / refused (-1)).
A queue row is only created if the picking is outgoing, linked to a sale
order, and that order has a transaction in the done state on a provider
with Utánvét Ellenőr Check enabled. A database constraint
guarantees at most one row per picking and outcome, and a re-validated
picking can never queue a contradictory outcome once one has already been
sent.
The queued rows are visible under , colour-coded by State (Pending, Sent, Failed). A scheduled action, Utánvét Ellenőr: send pending signals, runs every 10 minutes and drains up to 100 due rows per run, retrying failed calls up to three times with a backoff of 5 minutes, then 30 minutes, then 2 hours, before marking a row Failed. An administrator can reset a failed row with the Retry button to have the cron pick it up again.
Configuration¶
eyssen_delivery_cod needs no setup: install it as a dependency of a
carrier module and the COD computation runs automatically for orders paid
through that carrier’s “Payment on Delivery” method.
To configure the Utánvét Ellenőr check:
Install
utanvetellenor.Go to and set:
Mode — Sandbox or Production;
the matching public/private key pair for that mode;
Reputation Threshold — a value between
-1.0and+1.0(default0.5);Fallback on API Error — Allow payment (default) or Block payment;
API Timeout (s) — the HTTP timeout used for every call (default
5);Chatter Verbosity — All API calls, Blocked customers and errors only (default) or Errors only.
On each payment provider that should be gated (typically a cash-on-delivery or bank-transfer method), open the Configuration tab, Availability group, and enable Utánvét Ellenőr Check.
Important
The integration is a joint-controller data sharing arrangement: it sends the customer’s e-mail, phone, postal code, country code and address line to a third party. Sign the Utánvét Ellenőr joint data controller agreement and update the shop’s privacy policy before enabling the check in Production mode.
Note
Sandbox and production API keys are stored in clear text on the company
record; the password widget in Settings only masks the value
on screen. Access to Settings is restricted to the
Administration / Settings (base.group_system) group, and
the same group is required to open the signal queue and to see the API
keys — never lower that restriction. Use different key pairs for
sandbox and production so a leaked test key cannot be replayed against
the live database.
Usage¶
A customer checks out on the website. If any offered payment provider has Utánvét Ellenőr Check enabled, the module looks up (or reuses the cached) reputation verdict for that customer and hides the guarded providers if the customer is blocked, or if the API failed and the fallback policy is set to Block payment. Other payment methods stay available either way.
The order is confirmed and the warehouse processes the delivery, in one package or several, depending on the route and stock availability.
When the carrier module (GLS, Foxpost or MPL) generates the shipping label for a picking paid through its own “Payment on Delivery” method, it calls
_compute_dynamic_cod()to work out exactly how much to collect on that package, and stores it on the picking’s COD Amount field.Once the transfer is validated (delivered) or cancelled, a signal is queued automatically and sent to Utánvét Ellenőr by the scheduled action within about 10 minutes, so the shared reputation database reflects the real outcome for future checks — by this shop and by every other merchant using the service.
Scope and modules¶
eyssen_delivery_cod— computes the dynamic, per-package cash-on-delivery amount (partial shipments, service lines, down payments, order-total cap) shared by the carrier integrations.utanvetellenor— integrates the utanvet-ellenor.hu shared fraud database into checkout (payment-provider filtering) and post-fulfilment reporting (signal queue and retry cron).