Transaction Fee Calculator — Volume-Based Discounts
Problem statement
Related parts: Start with Parts 1 and 2.
Part 3: Volume-Based Discounts
Adding Discounts
Now we add volume discounts. Merchants who sell more get cheaper fees. You need to count how many successful transactions a merchant has made.
Discount Table:
| Total Transactions so far | Discount |
|---|---|
| 1-10 | 0% (Normal price) |
| 11-50 | 10% off |
| 51-100 | 15% off |
| 101+ | 20% off |
Configuration Data:
You will get a dictionary with fees for many countries. It looks like this:
country_fees = {
"ie": {"card": (0.019, 20), "klarna": (0.025, 40), "bank_transfer": (0.006, 0)},
"de": {"card": (0.025, 25), "klarna": (0.030, 45), "bank_transfer": (0.007, 0)},
"fr": {"card": (0.027, 28), "klarna": (0.032, 48), "bank_transfer": (0.008, 0)},
"default": {"card": (0.029, 30), "klarna": (0.035, 50), "bank_transfer": (0.008, 0)}
}Example Data
Input:
Imagine acct_1 has done 10 transactions already. The 11th transaction (py_11) happens. The 12th transaction (py_12) happens.
Output:
- Transaction 11: Base fee is calculated. Then, apply a 10% discount.
- Transaction 12: Base fee is calculated. Apply a 10% discount.
Math Detail: For py_11 (Ireland Card): Base = 1500 × 0.019 + 20 = 48.5. Discount = 10%. New Fee = 48.5 × 0.9 = 43.65. Round down -> 43.
What You Need To Do
- Keep a count of transactions for every merchant.
- Check the merchant's count before the current transaction to find the discount.
- Only increase the count if the transaction is "payment_completed".
- Process rows in order. The order in the CSV matters.
- Use the provided dictionary for country fees. If the country isn't there, use "default".
Questions to Ask the Interviewer
- Do I apply the discount before rounding or after?
- What if a merchant sells in different countries? Does that count towards the same volume total?
- Does the volume count ever reset (like every month)?
Function
calculateDiscountedFees(csvData: String, countryFees: String[][]) → String[]Examples
Example 1
csvData = "id,reference,amount,currency,date,merchant_id,buyer_country,transaction_type,payment_provider,status\npy_1,1,1000,eur,2024-12-24,acct_1,ie,payment,card,payment_completed\npy_2,2,2500,eur,2024-12-24,acct_2,de,payment,card,payment_failed\npy_3,3,3400,eur,2024-12-25,acct_2,ie,payment,klarna,payment_completed\npy_4,4,5000,eur,2024-12-25,acct_1,fr,payment,bank_transfer,payment_completed\npy_5,5,2000,eur,2024-12-26,acct_1,ie,payment,card,payment_pending"countryFees = [["ie","card","190","20"],["ie","klarna","250","40"],["ie","bank_transfer","60","0"],["de","card","250","25"],["de","klarna","300","45"],["de","bank_transfer","70","0"],["fr","card","270","28"],["fr","klarna","320","48"],["fr","bank_transfer","80","0"],["default","card","290","30"],["default","klarna","350","50"],["default","bank_transfer","80","0"]]return = ["id,transaction_type,payment_provider,fee","py_1,payment,card,39","py_2,payment,card,0","py_3,payment,klarna,125","py_4,payment,bank_transfer,40","py_5,payment,card,0"]The two unsuccessful rows have fee 0 and do not affect volume. The remaining payments use their Ireland or France rules. No merchant reaches its eleventh successful payment, so no discount applies.
Example 2
csvData = "id,reference,amount,currency,date,merchant_id,buyer_country,transaction_type,payment_provider,status\nt1,1,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt2,2,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt3,3,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt4,4,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt5,5,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt6,6,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt7,7,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt8,8,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt9,9,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt10,10,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt11,11,1000,usd,2025-01-01,m1,ie,payment,card,payment_completed"countryFees = [["ie","card","190","20"],["default","card","290","30"],["default","klarna","350","50"],["default","bank_transfer","80","0"]]return = ["id,transaction_type,payment_provider,fee","t1,payment,card,59","t2,payment,card,59","t3,payment,card,59","t4,payment,card,59","t5,payment,card,59","t6,payment,card,59","t7,payment,card,59","t8,payment,card,59","t9,payment,card,59","t10,payment,card,59","t11,payment,card,35"]The first ten successful payments use the undiscounted default card fee of 59. The Ireland payment is merchant m1's eleventh success, so its base fee 39 receives a 10% discount and floors to 35.
Constraints
- Process transactions in CSV order.
- Only
payment_completedtransactions increase a merchant's count. - Use the merchant's transaction number including the current successful payment to select the discount tier.
- Apply the discount before rounding down.
- If a country is not present, use
default. - FastPrep adapter: each
countryFeesrow is[country, provider, rateBasisPoints, fixedFee]; for example,190basis points represents the source rate0.019. - FastPrep adapter: return the source's newline-delimited CSV result as a
String[], one CSV line per array element.