Reported November 2023
Stripesimulation

Schedule Invoice Emails and Delinquencies

Reported by candidates from Stripe's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.

Get StealthCoderRuns invisibly during the live Stripe OA. Under 2s to a working solution.
Founder's read

Stripe reported this one in November 2023, and it looks scarier than it is. Strip the invoice dressing and it's a simulation: generate events, sort them, and track a running balance per customer. If you're taking this OA soon, the long statement is the real obstacle, not the algorithm. Examples 1 and 2 hide the rules that cost people points: payments at the same timestamp apply first, and Bob's early payment kills every later email. Read the ordering rules twice before you type. StealthCoder sits invisibly on your screen as a safety net if you blank on the details mid-assessment.

The problem

You are given a configurable invoice-email schedule, one invoice per customer, and an unsorted list of customer payments.
Each schedule row is offset,title. The offset is relative to the invoice time.
Each invoice row is invoiceTime,name,amount.
Each payment row is paymentTime,name,amount.
For every scheduled email time, first apply all payments made at or before that time. Send the email only when the customer still owes a positive amount. Format it as time: [title] Invoice for name for amount dollars.
The greatest schedule offset is the due-date offset. After all email lines, append Delinquent customers:, followed by one line name owes amount dollars for every invoice with a positive balance at its due time.
Sort email events by time, then invoice input position, then schedule input position. List delinquent customers in invoice input order.

Function
scheduleInvoiceEmails(schedule: String[], invoices: String[], payments: String[]) → String[]

Examples
Example 1
schedule = ["-10,Upcoming","0,New","20,Reminder","30,Due"]
invoices = ["0,Alice,200","1,Bob,100"]
payments = ["-9,Alice,100","1,Alice,50","0,Bob,100"]
return = ["-10: [Upcoming] Invoice for Alice for 200 dollars","-9: [Upcoming] Invoice for Bob for 100 dollars","0: [New] Invoice for Alice for 100 dollars","20: [Reminder] Invoice for Alice for 50 dollars","30: [Due] Invoice for Alice for 50 dollars","Delinquent customers:","Alice owes 50 dollars"]
Payments reduce the amount shown by later emails. Bob pays in full before his new-invoice email, so all later Bob emails are skipped. Alice still owes 50 at the due time.
Example 2
schedule = ["-5,Upcoming","0,Due"]
invoices = ["10,Cara,50"]
payments = ["5,Cara,50"]
return = ["Delinquent customers:"]
The payment occurs at the first scheduled email time and is applied first, so no email is sent and Cara is not delinquent.
Example 3
schedule = ["0,New","10,Due"]
invoices = ["0,Ada,40","0,Bea,30"]
payments = []
return = ["0: [New] Invoice for Ada for 40 dollars","0: [New] Invoice for Bea for 30 dollars","10: [Due] Invoice for Ada for 40 dollars","10: [Due] Invoice for Bea for 30 dollars","Delinquent customers:","Ada owes 40 dollars","Bea owes 30 dollars"]
Equal-time emails preserve invoice input order. Neither customer pays, so both appear in the delinquency section.

Constraints
1 <= schedule.length <= 20; offsets are unique integers in strictly increasing order.
1 <= invoices.length <= 1000; customer names are unique.
0 <= payments.length <= 10000; every payment names a known customer.
Invoice amounts and payment amounts are positive integers at most 10^9.
Times and offsets fit in signed 32-bit integers, and their sums fit in signed 64-bit integers.
Payments at an email timestamp are applied before that email. Payments beyond the due time do not affect delinquency.

Reported by candidates. Source: FastPrep

Pattern and pitfall

The trick is to turn each invoice and schedule row into an email event with time = invoiceTime + offset, plus invoice index and schedule index as tiebreakers. Sort by those three keys. Group payments by customer, sort each list by time, and keep a pointer per customer so you apply payments with paymentTime <= emailTime before checking the balance. That gives roughly O(E log E + P log P), where E is at most 20,000. The pitfalls: using strict less-than instead of at-or-before, forgetting that payments past the due time are ignored, and using 32-bit ints when time sums need 64-bit. Delinquency is just the balance after applying payments up to the due time, which is the last schedule email, listed in invoice order. If the parsing or ordering rules slip away under pressure, StealthCoder is the hedge that keeps you moving during the live OA.

The honest play: practice the pattern, and have StealthCoder ready for the one you didn't see coming.

If this hits your live OA

You can drill Schedule Invoice Emails and Delinquencies cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play.

Get StealthCoder

Related leaked OAs

⏵ The honest play

You've seen the question. Make sure you actually pass Stripe's OA.

Stripe reuses patterns across OAs. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play. Works on HackerRank, CodeSignal, CoderPad, and Karat.

Schedule Invoice Emails and Delinquencies FAQ

How hard is the Stripe invoice email problem really?+

Easy on algorithm, annoying on details. There's no clever data structure. You parse strings, build events, sort, and track balances. Most failures come from misreading tie-breaking or the at-or-before payment rule, not from complexity.

What's the core trick?+

Compute each email's absolute time as invoiceTime plus offset, sort events by time, invoice position, then schedule position. Process payments per customer in time order with a pointer, so every email sees the balance after all payments at or before its timestamp.

Do payments at the same time as an email count?+

Yes. Example 2 shows it: the payment lands exactly at the first email time, gets applied first, and no email goes out. Use a less-than-or-equal comparison when consuming payments, and make sure you do it before the balance check.

Which edge cases should I test before submitting?+

Test a fully paid customer skipping all later emails, a payment after the due time that must be ignored, negative offsets, equal-time emails across customers, and an empty payments list. Also use 64-bit integers for time sums, since the constraints say sums can exceed 32 bits.

How do I prepare for this in 48 hours?+

Practice string parsing and multi-key sorting in your language. Write a quick simulation that groups payments by name and sorts them. Then rehearse the output formatting exactly, since a missing colon or wrong phrase fails the whole test.

Problem reported by candidates from a real Online Assessment. Sourced from a publicly-available candidate-aggregated repository. Not affiliated with Stripe.

OA at Stripe?
Invisible during screen share
Get it