PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

Evaluates CSV parsing, numeric conversions and rounding, map lookups with fallbacks, transactional fee computation and per-merchant aggregation in the Coding & Algorithms category for Data Engineer roles.

  • hard
  • Stripe
  • Coding & Algorithms
  • Data Engineer

Compute transaction fees from a CSV string

Company: Stripe

Role: Data Engineer

Category: Coding & Algorithms

Difficulty: hard

Interview Round: Technical Screen

You are given a CSV **string** representing a list of payment transactions. Write a function that parses the CSV and returns a CSV string with the **total processing fee per merchant**. ### Input CSV The input has a header and the following columns: - `transaction_id` (string) - `merchant_id` (string) — the “person” you should aggregate fees for - `status` (string) — one of: - `payment_completed`, `payment_pending`, `payment_failed`, - `refund_completed`, - `dispute_won`, `dispute_lost` - `payment_provider` (string) — e.g., `card`, `bank_transfer`, `paypal` - `buyer_country` (string, ISO-2) — e.g., `US`, `DE`, `FR` - `currency` (string, ISO-3) — e.g., `USD`, `EUR` - `amount` (decimal) — transaction amount in the given `currency` Assume: - The CSV may contain extra whitespace; you should handle it. - All amounts are non-negative. ### Fee rules You are also given (as in-memory dictionaries/maps): 1) `base_rate_by_provider[payment_provider] -> decimal` Used for **all statuses except** `payment_completed`. 2) `completed_rate_by_provider_and_country[(payment_provider, buyer_country)] -> decimal` Used **only when** `status = 'payment_completed'`. 3) `fx_to_usd[currency] -> decimal` Multiply an amount in `currency` by this factor to convert to USD. Fee calculation per transaction: - If `status = 'refund_completed'`: fee is **0** (no refund fee). - If `status = 'payment_completed'`: - Convert `amount` to USD: `amount_usd = amount * fx_to_usd[currency]`. - `fee_usd = amount_usd * completed_rate + 0.30` where `completed_rate` comes from `completed_rate_by_provider_and_country`. - For all other statuses (`payment_pending`, `payment_failed`, `dispute_won`, `dispute_lost`): - Convert `amount` to USD: `amount_usd = amount * fx_to_usd[currency]`. - `fee_usd = amount_usd * base_rate + 0.30` where `base_rate` comes from `base_rate_by_provider`. Lookups and fallbacks: - If `(payment_provider, buyer_country)` is missing for a completed payment, fall back to `base_rate_by_provider[payment_provider]`. - If a `payment_provider` is unknown, treat its rate as `0` (still apply the `$0.30` fixed fee for non-refunds). - If `currency` is unknown, assume `fx_to_usd[currency] = 1.0`. ### Required output Return a CSV **string** with header: `merchant_id,total_fee_usd` Where `total_fee_usd` is the sum of `fee_usd` across that merchant’s transactions, rounded to 2 decimals. Order rows by `merchant_id` ascending. ### What to implement Implement a function (in a language of your choice): `compute_fees_per_merchant(csv_str, base_rate_by_provider, completed_rate_by_provider_and_country, fx_to_usd) -> csv_str` Discuss time complexity and how you’d test edge cases (e.g., empty input, malformed rows, missing lookup keys).

Quick Answer: Evaluates CSV parsing, numeric conversions and rounding, map lookups with fallbacks, transactional fee computation and per-merchant aggregation in the Coding & Algorithms category for Data Engineer roles.

Part 1: Parse a transaction CSV string and compute each user's fees

Parse a CSV of payment transactions and compute the **total processing fee** owed by each user, returned in **integer cents**. ## What to implement Implement `solution(csv_string)`. The input is a single CSV string; return a **dictionary mapping each user to their total fee, expressed as a whole number of cents** (an integer). ## Input format When non-empty, the CSV begins with the exact header line: ``` user,status,payment_provider,amount ``` Each subsequent line is one transaction with these fields: - **`user`** — the user the transaction belongs to. - **`status`** — one of `payment_completed`, `payment_failed`, `payment_pending`, `refund_completed`, `dispute_lost`, `dispute_won`. - **`payment_provider`** — one of `card`, `bank_transfer`, `wallet`. - **`amount`** — the transaction amount in **US dollars**, a non-negative decimal with at most 2 digits after the decimal point. ## Fee rules Compute the fee for each transaction based on its `status`: - **`payment_completed`, `payment_failed`, `payment_pending`** — the fee is a percentage of `amount` plus a fixed **$0.30**: `fee = amount × provider_rate + 0.30` (USD) where `provider_rate` depends on the payment provider: | provider | rate | |---|---| | `card` | 2.9% | | `bank_transfer` | 1.0% | | `wallet` | 1.5% | - **`dispute_lost`** — a flat **$15.00** fee. - **`refund_completed`** — **$0** (no fee). - **`dispute_won`** — **$0** (no fee). ## Rounding and accumulation - Round **each transaction's fee** to the nearest cent using **half-up** rounding, then convert it to an integer number of cents **before** adding it to that user's running total. - A user's returned value is the **sum of their per-transaction cent fees**. ## Output and edge cases - Return a **dictionary** mapping `user` → total fee **in cents** (integer). - **Include every user that appears** in the CSV, even if their total fee is `0` (for example, a user with only a `refund_completed` or `dispute_won` transaction still appears, mapped to `0`). - **Ignore blank lines** (and any row with no user). - If the input string is **empty or whitespace-only**, return an **empty dictionary** `{}`. ## Examples A `card` `payment_completed` of `100.00` produces `100.00 × 0.029 + 0.30 = 3.20` USD → **320** cents. A `wallet` `payment_completed` of `0.99` produces `0.99 × 0.015 + 0.30 = 0.31485` USD, which rounds half-up to `0.31` USD → **31** cents.

Constraints

  • 0 <= number of transactions <= 100000
  • The CSV has the exact header user,status,payment_provider,amount when non-empty
  • amount is a non-negative decimal number with at most 2 digits after the decimal point
  • status is one of payment_completed, payment_failed, payment_pending, refund_completed, dispute_lost, dispute_won
  • payment_provider is one of card, bank_transfer, wallet

Examples

Input: "user,status,payment_provider,amount\nalice,payment_completed,card,100.00\nbob,payment_failed,bank_transfer,50.00\nalice,refund_completed,card,20.00\nbob,dispute_lost,wallet,80.00"

Expected Output: {"alice": 320, "bob": 1580}

Explanation: alice pays 100.00 * 2.9% + 0.30 = 3.20 => 320 cents. Her refund adds 0. bob pays 50.00 * 1.0% + 0.30 = 0.80 => 80 cents, plus a lost dispute fee of 1500 cents.

Input: "user,status,payment_provider,amount\nalice,payment_pending,wallet,10.00\nalice,payment_completed,wallet,0.99\ncarol,dispute_won,card,42.00"

Expected Output: {"alice": 76, "carol": 0}

Explanation: alice pays 45 cents for 10.00 via wallet and 31 cents for 0.99 via wallet after rounding, totaling 76. carol appears in the CSV, so she is included with fee 0.

Input: ""

Expected Output: {}

Explanation: Empty input produces an empty result.

Input: "user,status,payment_provider,amount\n\nzoe,refund_completed,card,10.00\n"

Expected Output: {"zoe": 0}

Explanation: Blank lines are ignored, and refunds have no fee.

Hints

  1. Use the CSV header to access fields by name instead of relying on column positions.
  2. Avoid floating-point errors by using Decimal or by converting each rounded fee into cents before summing.

Part 2: Compute fees in USD for completed transactions using country-specific rates

Compute the total payment-processing fee charged to each user, in **whole USD cents**, given a CSV of transactions and a currency-to-USD exchange-rate table. ## Function ``` solution(csv_string, exchange_rates) ``` ## Inputs - **`csv_string`** — a CSV string whose header (when non-empty) is exactly: `user,status,payment_provider,buyer_country,currency,amount` - **`exchange_rates`** — a dictionary where `exchange_rates[currency]` is the USD value of **1 unit** of that currency. ## Output Return a dictionary mapping each **`user`** to their **total fee in USD cents** (an integer). Every user that appears in the CSV must be present in the result — **even if their total fee is `0`**. If `csv_string` is empty or contains only whitespace, return `{}`. (Key order in the returned dictionary does not matter.) ## How to process each transaction **1. Convert the amount to USD:** ``` converted_usd = amount * exchange_rates[currency] ``` **2. Compute the transaction fee in USD based on `status`:** ### `payment_completed` Fee = `converted_usd * rate + 0.30`, where `rate` depends on the **provider** and **buyer_country**: | Provider | US / CA | GB | DE / FR / AT | All other countries | |-----------------|---------|-------|--------------|---------------------| | `card` | 2.9% | 2.5% | 2.3% | 3.1% | | `bank_transfer` | 1.2% | 1.1% | 1.0% | 1.4% | | `wallet` | 1.8% | 1.8% | 1.8% | 1.8% | (`wallet` is **1.8%** for any country.) ### `payment_failed` and `payment_pending` Use the **provider-only** (country-independent) rates from Part 1 on the converted USD amount: | Provider | Rate | |-----------------|-------| | `card` | 2.9% | | `bank_transfer` | 1.0% | | `wallet` | 1.5% | Fee = `converted_usd * rate + 0.30`. ### Other statuses - `refund_completed` → fee = **0 USD** - `dispute_won` → fee = **0 USD** - `dispute_lost` → fee = **15.00 USD flat** (no conversion, no percentage, no fixed add-on) **3. Round and accumulate:** Round **each transaction's fee** to the nearest cent using **half-up rounding** (e.g. 0.005 rounds up to 0.01), then add the resulting integer cents to that user's running total. Round per transaction — **before** adding to the total, not after summing. ## Notes - **Skip any row whose `user` field is empty** (after trimming surrounding whitespace), including fully blank lines. - Even users whose only transactions are `refund_completed`, `dispute_won`, or otherwise sum to `0` must still appear in the result with a total of `0`. ## Constraints - `0 <= number of transactions <= 100000` - The CSV has the exact header `user,status,payment_provider,buyer_country,currency,amount` when non-empty. - `exchange_rates` contains every currency used in the CSV. - `amount` is a non-negative decimal number. - `payment_provider` is one of `card`, `bank_transfer`, `wallet`. - `status` is one of `payment_completed`, `payment_failed`, `payment_pending`, `refund_completed`, `dispute_lost`, `dispute_won`.

Constraints

  • 0 <= number of transactions <= 100000
  • The CSV has the exact header user,status,payment_provider,buyer_country,currency,amount when non-empty
  • exchange_rates contains every currency used in the CSV
  • amount is a non-negative decimal number
  • payment_provider is one of card, bank_transfer, wallet
  • status is one of payment_completed, payment_failed, payment_pending, refund_completed, dispute_lost, dispute_won

Examples

Input: ("user,status,payment_provider,buyer_country,currency,amount\nalice,payment_completed,card,DE,EUR,100.00\nbob,payment_pending,bank_transfer,US,USD,50.00\nalice,dispute_lost,wallet,GB,GBP,80.00", {"USD": 1.0, "EUR": 1.10, "GBP": 1.25})

Expected Output: {"alice": 1783, "bob": 80}

Input: ("user,status,payment_provider,buyer_country,currency,amount\nu1,payment_completed,card,JP,JPY,10000\nu1,payment_completed,wallet,FR,EUR,10.00\nu2,refund_completed,card,US,USD,9.99", {"USD": 1.0, "EUR": 1.10, "JPY": 0.0068})

Expected Output: {"u1": 291, "u2": 0}

Input: ("", {"USD": 1.0})

Expected Output: {}

Input: ("user,status,payment_provider,buyer_country,currency,amount\nsam,payment_completed,bank_transfer,GB,GBP,0.99\nsam,dispute_won,card,US,USD,20.00", {"USD": 1.0, "GBP": 1.25})

Expected Output: {"sam": 31}

Input: ("user,status,payment_provider,buyer_country,currency,amount\nzed,payment_completed,card,IN,INR,1000\nzed,payment_failed,card,US,USD,100.00", {"USD": 1.0, "INR": 0.012})

Expected Output: {"zed": 387}

Input: ("user,status,payment_provider,buyer_country,currency,amount\nkay,payment_completed,wallet,ZZ,USD,200.00\nray,refund_completed,card,US,USD,5.00", {"USD": 1.0})

Expected Output: {"kay": 390, "ray": 0}

Input: ("user,status,payment_provider,buyer_country,currency,amount\ndan,dispute_lost,card,US,USD,0", {"USD": 1.0})

Expected Output: {"dan": 1500}

Hints

  1. Use one lookup table for currency conversion and another lookup table for the payment_completed country-specific rates.
  2. Only payment_completed changes from Part 1. The other statuses keep the same logic after converting the amount to USD.
Last updated: Apr 19, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Assign Reviewers from Changed Files - Stripe (medium)
  • Generate Account Email Notifications - Stripe (medium)
  • Calculate Transaction Fees - Stripe (medium)
  • Build an Account Transfer Ledger - Stripe (medium)
  • Implement Validation and String Compression - Stripe (hard)