FastPrepTrack Invoice Lifecycle and Outstanding USD Balance

Track Invoice Lifecycle and Outstanding USD Balance

Stripe logoStripe● MediumINTERNOA
Learn

Problem statement

Process invoice actions in their supplied order and return the total amount still owed in USD cents. An unpaid invoice contributes its current amount in either the created or finalized state.

  • CREATE: id=...&amount=...&currency=... opens a new invoice at its initial amount.
  • FINALIZE: id=...&amount=...&currency=... replaces the amount only while that invoice is created, then permanently finalizes it.
  • PAY: id=... permanently marks a finalized invoice paid; it then contributes zero.

Find required fields anywhere in the query. Their order is arbitrary, and extra key=value pairs may appear before, between or after them. Match action names, required field names and currency codes without ASCII letter-case sensitivity; preserve ID values exactly and treat IDs as case-sensitive.

For this exercise, malformed actions, unknown actions and invalid transitions are ignored without changing any invoice. A duplicate CREATE cannot overwrite or reopen an ID; a repeated FINALIZE or PAY cannot move a state backward. Non-USD CREATE and FINALIZE actions are ignored entirely: they neither reserve an ID nor change an existing invoice. PAY requires only id; its other structurally valid pairs are ignored.

Validate the whole action before changing state. Use exactly a colon and one space, followed by ampersand-separated key=value tokens with exactly one equals sign each. CREATE and FINALIZE require one id, one amount and one currency; PAY requires one id. Duplicate required fields invalidate the action. Unknown pairs are ignored, and percent-encoding is not decoded. An empty action array returns zero.

Function

outstandingUsdBalance(events: String[]) → long

Examples

Example 1

events = ["CREATE: id=13&amount=800&currency=USD"]return = 800

Invoice 13 remains created and unpaid: 800 USD cents are owed. The leading count in the PDF is wrapper metadata, not an action.

Example 2

events = ["CREATE: id=16&amount=800&currency=USD","FINALIZE: id=16&amount=600&currency=USD"]return = 600

Accepted finalization replaces 800 by 600. It remains unpaid, so 600 USD cents are owed.

Example 3

events = ["CREATE: id=14&amount=800&currency=USD","FINALIZE: id=14&amount=800&currency=USD","PAY: id=14"]return = 0

Payment is accepted after finalization and permanently removes invoice 14 from the total.

Constraints

  • 0 <= events.length <= 40; every event is a string of at most 96 printable ASCII characters. The sum of all action lengths is at most 800 characters.
  • Query keys match [A-Za-z][A-Za-z0-9_]{0,11}; query values match [A-Za-z0-9_.:/?+%-]*. These are token grammar rules; missing or invalid required values make the whole action invalid.
  • ID values match [A-Za-z0-9_-]{1,12}. IDs are case-sensitive.
  • A required amount is 0 or a positive decimal with no sign or leading zeros, at most 1000000. Trailing junk is invalid.
  • A required currency is exactly three ASCII letters; only case-insensitive USD is accepted for CREATE/FINALIZE.
  • The total owed is between 0 and 40000000, inclusive, and fits a signed 32-bit integer; return it as a Java long to preserve the existing practice interface.

More Stripe problems

See Stripe hiring insights
public long outstandingUsdBalance(String[] events) {
    // write your code here
}
events["CREATE: id=13&amount=800&currency=USD"]
expected800
Checking account…