38. Design a Product Plan Cost Explorer
Design a Product Plan Cost Explorer
Design an in-memory CostExplorer that tracks SaaS product plans and customer subscriptions, and computes a customer's monthly and annual cost for a given calendar year (Jan–Dec). If a subscription starts on any day of a month, the customer pays for that full month.
Methods
addProduct
void addProduct(String productName, List<String> plans)
- Add/update products and their plans (planId & monthly price).
productName: non-blank, unique, contains a-z and '-' (e.g. jira).
plans: each string "PLANID,monthlyPrice".
PLANID: contains [A-Z] (e.g. BASIC, PREMIUM).
monthlyPrice: integer 1–1000.
- Re-adding same
productName overwrites its plan list.
Removed plans now cost 0 for all subscribers.
subscribe
void subscribe(String customerId, String startDate, String productName, String planId)
- Subscribe a customer to a product plan starting from a given date.
customerId: non-blank, contains a-z and '-'.
startDate: YYYY-MM-DD.
- If called again with same
customerId and productName, update that product’s subscription (startDate & planId).
- customerId, productName, planId will always be valid.
monthlyCost
List<Integer> monthlyCost(String customerId, int year)
- For a given year, return monthly cost (12 entries) and total annual cost.
- Returns list of 12 integers: index 0 = Jan, ..., index 11 = Dec.
- For each subscribed product, charge full monthly price from its start month in that year onward.
- If subscription starts after the given year, contribution is 0.
- If plan is removed, its monthly price is treated as 0 in all reported months.
annualCost
int annualCost(String customerId, int year)
- If a subscribed plan is later removed, its price becomes 0 for all customers.
- Returns sum of all 12 monthly costs for that customer and year.
Examples
Example 1: Single product, mid-year start
CostExplorer ce = new CostExplorer();
ce.addProduct("jira", List.of("BASIC,100"));
ce.subscribe("acme-corp", "2025-03-10", "jira", "BASIC");
ce.monthlyCost("acme-corp", 2025);
// [0, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
ce.annualCost("acme-corp", 2025);
// 1000
Example 2: Multiple products, different start dates
CostExplorer ce = new CostExplorer();
ce.addProduct("jira", List.of("BASIC,50", "PREMIUM,120"));
ce.addProduct("confluence", List.of("STANDARD,80"));
ce.subscribe("team-alpha", "2025-01-05", "jira", "BASIC");
ce.subscribe("team-alpha", "2025-07-10", "confluence", "STANDARD");
ce.monthlyCost("team-alpha", 2025);
// [50, 50, 50, 50, 50, 50, 130, 130, 130, 130, 130, 130]
ce.annualCost("team-alpha", 2025);
// 1080