Payment Ledger with Refunds and Date Queries
Problem statement
Implement a lightweight payment ledger that records payments, applies full or partial refunds, tracks net revenue, and retrieves recorded payments by date.
Implement processPaymentLedger. Process the operations in order and return one result string for every operation.
Operation format
PAYMENT payment_id timestamp amount: record a payment with a unique ID, a strict UTC timestamp inYYYY-MM-DDTHH:mm:ssZform, and a positive amount. First validate the timestamp, then check whether the ID is already recorded. ReturnRECORDEDon success,INVALID_TIMESTAMPfor an invalid timestamp, orDUPLICATE_PAYMENTfor a valid-timestamp operation whose ID already exists. A rejected payment has no effect.REFUND payment_id amount: refund a positive amount from an existing payment. Multiple partial refunds are allowed, but their cumulative amount may not exceed the original payment amount. ReturnREFUNDED,PAYMENT_NOT_FOUND, orINVALID_REFUND. A rejected refund has no effect. A successful full refund does not remove the payment from date-query results.TOTAL: return the current net revenue as a decimal integer. Net revenue is the sum of recorded payment amounts minus successful refunds.PAYMENTS_ON date: return the matching payment IDs as one comma-separated string in original recording order. The date must use strictYYYY-MM-DDform. Return the empty string when no payment matches, orINVALID_DATEwhen the date is invalid.PAYMENTS_BETWEEN start_date end_date: return payment IDs whose payment date is in the inclusive range, ordered by payment date and then by original recording order within one date. Return the empty string when no payment matches. ReturnINVALID_RANGEwhen either date is invalid orstart_dateis afterend_date.
Operation lines are otherwise well-formed. Payment IDs are non-empty and contain no spaces.
Interview follow-ups
The interview report also asked how to optimize date lookup for large data, validate timestamps, query a range such as one month, and persist runtime state in a database. This callable exercise judges the in-memory behavior above; database persistence remains a discussion follow-up.
Function
processPaymentLedger(operations: String[]) → String[]Examples
Example 1
operations = ["PAYMENT p1 2026-04-10T09:00:00Z 100","PAYMENT p2 2026-04-10T10:30:00Z 70","TOTAL","REFUND p1 30","TOTAL","PAYMENTS_ON 2026-04-10"]return = ["RECORDED","RECORDED","170","REFUNDED","140","p1,p2"]The two unique payments create revenue of 170. Refunding 30 from p1 reduces it to 140. Both payments were recorded on 2026-04-10, so the date query returns their IDs in recording order.
Example 2
operations = ["PAYMENT pay-7 2026-04-11T12:00:00Z 50","PAYMENT pay-7 2026-04-12T12:00:00Z 90","REFUND pay-7 20","REFUND pay-7 31","REFUND missing 1","TOTAL"]return = ["RECORDED","DUPLICATE_PAYMENT","REFUNDED","INVALID_REFUND","PAYMENT_NOT_FOUND","30"]The duplicate ID is rejected. The successful partial refund leaves 30 of net revenue. Refunding another 31 would exceed the payment's remaining refundable amount.
Example 3
operations = ["PAYMENT p1 2026-02-30T09:00:00Z 25","PAYMENT p2 2026-04-11T09:00:00Z 40","PAYMENTS_ON 2026-13-01","PAYMENTS_BETWEEN 2026-04-12 2026-04-10","PAYMENTS_BETWEEN 2026-04-09 2026-04-12","TOTAL"]return = ["INVALID_TIMESTAMP","RECORDED","INVALID_DATE","INVALID_RANGE","p2","40"]February 30 and month 13 are invalid. The reversed range is also invalid. Only p2 is recorded, and it falls inside the final inclusive range.
Constraints
1 <= operations.length <= 100000.- Every operation has one of the documented forms and uses single spaces between tokens.
- Payment IDs are non-empty ASCII strings without spaces or commas.
- Every payment and refund amount is a positive integer at most
10^12. - Net revenue, cumulative refunds, and every intermediate monetary value fit in a signed 64-bit integer.
- A valid payment timestamp is a real UTC instant written exactly as
YYYY-MM-DDTHH:mm:ssZ. Query dates use exactYYYY-MM-DDform. - Date-query results must be produced without scanning unrelated payment IDs; preserve recording order among returned IDs.