Handling Purchase Orders and Net-30 Invoicing

An enterprise invoice that arrives without a purchase-order number is not late — it is rejected, silently, by an accounts-payable system that will never tell you. The invoice sits unpaid, your dunning process assumes the customer is delinquent, and the account manager discovers three weeks later that a missing field is the entire problem. This guide sits under Enterprise Contracts & Quote-to-Cash and covers invoice-based billing end to end, from PO capture to remittance matching.

The mental shift is that the payer and the user are different people in different systems. A card subscription’s payer is the person clicking; an enterprise invoice’s payer is an accounts-payable team that has never used your product, follows its own rules, and communicates only through structured documents. Everything about the billing flow has to accommodate that.

Trade-offs

Collection method Cash timing Failure signal Automation ceiling Fits
Card on file Immediate Decline within seconds Very high Self-serve, SMB
Bank debit mandate 2–5 days Return code within a week High EU/UK recurring
Invoice, net 30 30–60 days typical Silence past due date Medium Enterprise
Invoice, net 60/90 60–120 days Silence past due date Low Large enterprise, public sector
Card versus invoice collection timeline A card charge resolves within seconds while a net-30 invoice has an issue date, a due date, and an ageing period before any escalation begins. Card charge · outcome in seconds Net 30 issue + PO check 30 days to due date ageing 1-30 escalation
The two timelines share no assumptions — a system that treats the lower one with the upper one's logic produces false delinquency.

The automation ceiling column is the honest constraint. Invoice collections can be instrumented, measured, and prompted, but the final step is frequently a person calling another person. Design for that: the software’s job is to make sure the right human is prompted at the right time with the right information, not to close the loop unaided.

Step-by-Step Implementation

1. Capture and validate the PO before issuing

ALTER TABLE billing_profiles
  ADD COLUMN collection_method   TEXT NOT NULL DEFAULT 'charge_automatically',
  ADD COLUMN payment_terms_days  INT  NOT NULL DEFAULT 0,
  ADD COLUMN po_number           TEXT,
  ADD COLUMN po_required         BOOLEAN NOT NULL DEFAULT FALSE,
  ADD COLUMN po_valid_until      DATE,
  ADD COLUMN ap_contact_email    TEXT;

-- Refuse to issue an invoice that will be rejected on arrival.
ALTER TABLE invoices
  ADD CONSTRAINT invoice_po_present
  CHECK (collection_method <> 'send_invoice' OR po_required IS NOT TRUE OR po_number IS NOT NULL);

A purchase order frequently has its own expiry and its own approved amount. Both matter: an invoice against an expired PO is rejected, and an invoice that would take cumulative billing past the PO’s approved value is rejected for the excess. Track both and check them at issue time rather than discovering the problem in the ageing report.

2. Compute the due date deliberately

from datetime import date, timedelta

def due_date(issued_on: date, terms_days: int, calendar) -> date:
    """Net terms run in calendar days; the result is nudged to a business day."""
    d = issued_on + timedelta(days=terms_days)
    while not calendar.is_business_day(d):
        d += timedelta(days=1)
    return d

Terms like “net 30 from end of month” and “net 45 from receipt” exist and mean different things; store the rule, not just the number. Getting this wrong by a few days produces invoices that appear overdue in your system and on time in the customer’s, which is a credibility problem in exactly the conversation where credibility matters.

3. Send to accounts payable

The invoice must reach the AP contact, in the format their system accepts, with the PO number in the field their system reads. That usually means a PDF attachment plus a structured copy, and increasingly a portal upload. Record delivery as an event with a timestamp — “we sent it on the 3rd” is a claim you will need to substantiate.

Never send enterprise invoices only to the product user. They are not the payer, they will not forward it reliably, and they cannot resolve a rejection.

4. Match remittances to invoices

Remittance matching An incoming transfer is matched by reference, then by exact amount, then by a combination of open invoices, with anything unmatched queued for a human. Bank transfer amount + reference 1 · invoice reference 2 · exact amount 3 · sum of open invoices applied human queue
Three automatic strategies then a human — attempting to guess beyond these produces misapplied cash that is painful to unwind.

Partial payments are normal and must be first-class: an invoice can be part-paid, and the ageing bucket applies to the remaining balance. Modelling payment as a boolean forces the team into workarounds that corrupt the ledger.

5. Escalate on a human timeline

Reminders before the due date, a courteous notice on the day, then escalation at 15, 30, and 60 days past due, moving from automated email to the account manager to a formal notice. Suppress every card-oriented message for these accounts — an enterprise customer receiving “update your payment method” for a wire transfer is a small failure that costs disproportionate trust.

Ageing, Reporting, and When to Suspend

The ageing report is the operational heart of invoice billing, and it should be derived from invoice data rather than maintained separately.

SELECT CASE
         WHEN current_date <= due_date            THEN 'current'
         WHEN current_date - due_date <= 30       THEN '1-30'
         WHEN current_date - due_date <= 60       THEN '31-60'
         WHEN current_date - due_date <= 90       THEN '61-90'
         ELSE '90+'
       END                                  AS bucket,
       count(*)                             AS invoices,
       sum(amount_remaining_minor)          AS outstanding_minor
  FROM invoices
 WHERE status = 'open' AND collection_method = 'send_invoice'
 GROUP BY 1;

Suspension is the question this report eventually forces, and enterprise contracts usually constrain it. Many order forms specify a notice period before service can be withheld, and suspending inside that period is a breach that undermines your own collection position. Encode the contractual notice period on the order form and let the escalation ladder read it, so the system cannot suspend earlier than the contract allows.

Separate genuine delinquency from process friction before escalating. A large share of “overdue” enterprise invoices are stuck on a missing PO, a wrong AP address, a mismatch between the invoice and the PO amount, or a portal upload nobody completed. Track a resolution reason on every overdue invoice, and the distribution will show that most of the ageing balance is fixable by your team rather than by the customer’s.

Collections escalation ladder A reminder before the due date is followed by a notice on the day, an account manager contact at fifteen days, and a formal notice past sixty, bounded by the contractual notice period. −7 days courtesy reminder due date notice + PO recheck +15 days account manager +60 days formal notice no step mentions a card, a decline, or a payment method suspension only after the contractual notice period, never before
Each rung has a named owner and a named action; an escalation with neither is a reminder that ages alongside the invoice.

Instrument the ladder so that each rung’s effectiveness is visible. Recording which step preceded payment, across a few hundred invoices, usually shows that the courtesy reminder before the due date recovers more than every later step combined — which argues for investing there rather than in more aggressive escalation. It also exposes the accounts that only ever pay after the account manager calls, and those are the ones to move onto a different collection method at renewal.

Verification & Testing

Test the due-date arithmetic across the cases that actually occur: terms from issue date, terms from end of month, a due date landing on a weekend, and a due date landing on a public holiday in the customer’s jurisdiction. Each is a one-line function and a handful of assertions, and each has been the cause of a real dispute somewhere.

Test the PO constraint by attempting to issue an invoice for a PO-required account without a PO and asserting the write fails rather than producing an invoice that will be rejected downstream. Then test the expiry and amount-ceiling checks with a PO that expires mid-term and one whose approved amount is exhausted by the third invoice.

Snapshot the rendered invoice document and assert the presence and position of the PO number, the due date, the remittance details, and the absence of card-related language. AP systems parse these documents; a layout regression that moves the PO number out of the expected block causes rejections that look like customer delinquency in every report you have.

Cash Application and the Credit Balance

Once payment stops being a one-to-one match with an invoice, the account needs a credit balance — a small piece of ledger machinery that most card-first billing systems lack and every invoice-billed business needs within months.

Three ordinary situations require it. A customer pays a round number that exceeds the invoice by a small amount and expects the difference held. A customer pays two invoices with one transfer, one of which is not yet issued. A concession is agreed mid-term and applied against whatever the next invoice happens to be. In all three, the money exists on the account before it has an invoice to attach to.

Model the credit balance as an account-level ledger with its own movements — funded by overpayment or concession, consumed by application to an invoice — and apply it automatically at invoice issue before any collection attempt. Applying it at issue rather than at payment matters, because the amount due printed on the document should be the amount the customer actually owes; an invoice for the full amount accompanied by an email explaining that a credit will be applied is exactly the kind of ambiguity that stalls in an accounts-payable queue.

Never let the credit balance become a dumping ground for unmatched cash. Money that cannot be attributed to a customer belongs in a suspense account with a human queue, not on an account balance where it will eventually be applied to the wrong invoice. The distinction is between “we know whose money this is and not yet what it pays for” and “we do not know whose money this is” — the first is a credit balance, the second is an unresolved item.

Report the aggregate credit balance monthly alongside the ageing report. A growing balance means cash is arriving that your invoicing is not keeping pace with, which is usually a signal that invoices are being issued late rather than that customers are overpaying.

Gotchas & Production Pitfalls

  • Card dunning applied to invoice accounts. The single most common defect. Branch every dunning entry point on collection_method and assert it in tests.
  • PO expiry ignored. An invoice against an expired PO is rejected and ages silently. Check expiry and remaining approved amount at issue time.
  • Overpayment treated as an error. Customers pay round numbers and pay early. Model an account credit balance and apply it to the next invoice rather than refusing the cash.
  • Currency rounding on the remittance. A transfer arriving a few units short because of intermediary bank fees should be matched with a small write-off rule, not left open forever.
  • Invoice numbering restarted or reused. Enterprise invoices are legal documents; the sequence must be gapless and unique, as covered in generating compliant sequential invoice numbers.

Frequently Asked Questions

Can an account be on both card and invoice? Yes, and it is common during transitions — a self-serve account that grows into an enterprise contract. Make collection_method a property of the billing profile with a clear cutover date, and never let both paths attempt collection for the same invoice.

Should net terms be offered to anyone who asks? They are effectively unsecured credit. Gate them on contract value and a credit decision, and keep the default as automatic collection. The operational cost of invoice billing is significant enough that it should be a deliberate concession.

How do I handle a customer’s AP portal that requires manual upload? Treat it as a delivery channel with its own record: who uploaded, when, and the portal’s own reference. Automating the upload is sometimes possible and rarely worth it below a handful of large accounts.

What about early-payment discounts? Terms like 2/10 net 30 are straightforward to express — a discount if paid within ten days — but they need the payment date, not the invoice date, to resolve. Compute the discount at application time and record it as a credit against the invoice rather than reissuing the document.