├── .vscode └── launch.json ├── Display.js ├── README.md ├── SplitWise.js ├── Transaction.js ├── User.js ├── UserTransaction.js ├── Utils.js ├── constant.js └── index.js /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Launch Program", 5 | "program": "${workspaceFolder}/index.js", 6 | "request": "launch", 7 | "skipFiles": [ 8 | "/**" 9 | ], 10 | "type": "pwa-node" 11 | }, 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /Display.js: -------------------------------------------------------------------------------- 1 | 2 | class Display { 3 | static showUser(users) { 4 | console.log("\n==========Users=============") 5 | console.log("UID", "Name", "Email", "Phone") 6 | for (const [key, value] of Object.entries(users)) { 7 | console.log(key, "=>", value.ID, value.Name, value.Email, value.Phone) 8 | } 9 | } 10 | 11 | static showTransaction(transactions) { 12 | console.log("\n==========Transactions=============") 13 | console.log("TD", "Payer ID", "Exp.Type", "Amount", "Payee") 14 | for (const [key, value] of Object.entries(transactions)) { 15 | console.log(key, value.PayerId, value.ExpenseType, value.Amount, value.Payee) 16 | } 17 | } 18 | 19 | static showUserTransaction(transactions) { 20 | console.log("\n==========User Transactions=============") 21 | console.log("UTID", "TID", "Type", "UID", "Amount") 22 | for (const [key, value] of Object.entries(transactions)) { 23 | console.log(key, value.TransactionId, value.TransactionType, value.UserId, value.Amount) 24 | } 25 | } 26 | } 27 | 28 | module.exports.Display = Display -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Splitwise App 2 | 3 | 4 | ## Problem Statement 5 | Create an expense sharing application. 6 | 7 | An expense sharing application is where you can add your expenses and split it among different people. The app keeps balances between people as in who owes how much to whom. 8 | 9 | Example 10 | ``` 11 | You live with 3 other friends. 12 | You: User1 (id: u1) 13 | Flatmates: User2 (u2), User3 (u3), User4 (u4) 14 | 15 | This month's electricity bill was Rs. 1000. 16 | Now you can just go to the app and add that you paid 1000, 17 | select all the 4 people and then select split equally. 18 | Input: u1 1000 4 u1 u2 u3 u4 EQUAL 19 | 20 | For this transaction, everyone owes 250 to User1. 21 | The app should update the balances in each of the profiles accordingly. 22 | 23 | User2 owes User1: 250 (0+250) 24 | User3 owes User1: 250 (0+250) 25 | User4 owes User1: 250 (0+250) 26 | 27 | --- 28 | 29 | Now, It is the BBD sale on Flipkart and there is an offer on your card. 30 | You buy a few stuffs for User2 and User3 as they asked you to. 31 | The total amount for each person is different. 32 | Input: u1 1250 2 u2 u3 EXACT 370 880 33 | 34 | For this transaction, User2 owes 370 to User1 and User3 owes 880 to User1. 35 | 36 | The app should update the balances in each of the profiles accordingly. 37 | User2 owes User1: 620 (250+370) 38 | User3 owes User1: 1130 (250+880) 39 | User4 owes User1: 250 (250+0) 40 | 41 | --- 42 | 43 | Now, you go out with your flatmates and take your brother/sister along with you. 44 | User4 pays and everyone splits equally. You owe for 2 people. 45 | Input: u4 1200 4 u1 u2 u3 u4 PERCENT 40 20 20 20 46 | 47 | For this transaction, User1 owes 480 to User4, User2 owes 240 to User4 and User3 owes 240 to User4. 48 | 49 | The app should update the balances in each of the profiles accordingly. 50 | User1 owes User4: 230 (250-480) 51 | User2 owes User1: 620 (620+0) 52 | User2 owes User4: 240 (0+240) 53 | User3 owes User1: 1130 (1130+0) 54 | User3 owes User4: 240 (0+240) 55 | 56 | ``` 57 | 58 | ## Requirements 59 | * User: Each user should have a userId, name, email, mobile number. 60 | * Expense: Could either be EQUAL, EXACT or PERCENT 61 | * Users can add any amount, select any type of expense and split with any of the available users. 62 | * The percent and amount provided could have decimals upto two decimal places. 63 | * In case of percent, you need to verify if the total sum of percentage shares is 100 or not. 64 | * In case of exact, you need to verify if the total sum of shares is equal to the total amount or not. 65 | * The application should have a capability to show expenses for a single user as well as balances for everyone. 66 | * When asked to show balances, the application should show balances of a user with all the users where there is a non-zero balance. 67 | * The amount should be rounded off to two decimal places. Say if User1 paid 100 and amount is split equally among 3 people. Assign 33.34 to first person and 33.33 to others. 68 | 69 | 70 | 71 | Detail problem statement can be read at: https://workat.tech/machine-coding/practice/splitwise-problem-0kp2yneec2q2 72 | -------------------------------------------------------------------------------- /SplitWise.js: -------------------------------------------------------------------------------- 1 | var Transaction = require('./Transaction').Transaction 2 | var UserTransaction = require('./UserTransaction').UserTransaction 3 | var User = require('./User').User 4 | var Utils = require('./Utils').Utils 5 | 6 | var { 7 | TRANSACTION_TYPE_CREDIT, 8 | TRANSACTION_TYPE_DEBIT, 9 | } = require('./constant') 10 | 11 | class SplitWise { 12 | #users 13 | #transactions 14 | #user_transactions 15 | 16 | constructor() { 17 | this.#users = {} 18 | this.#transactions = {} 19 | this.#user_transactions = {} 20 | } 21 | 22 | get Users() { 23 | return this.#users 24 | } 25 | 26 | get Transactions() { 27 | return this.#transactions 28 | } 29 | 30 | get UserTransactions() { 31 | return this.#user_transactions 32 | } 33 | 34 | set Users(users) { 35 | this.#users = users 36 | } 37 | 38 | set Transactions(transactions) { 39 | this.#transactions = transactions 40 | } 41 | 42 | set UserTransactions(user_transactions) { 43 | this.#user_transactions = user_transactions 44 | } 45 | 46 | addUser(name, email, phone) { 47 | try { 48 | var user = User.createUser(name, email, phone) 49 | 50 | this.Users = { 51 | ...this.Users, 52 | [user.Phone] : user 53 | } 54 | 55 | return Utils.success(user) 56 | } catch(err) { 57 | return Utils.failed(err) 58 | } 59 | } 60 | 61 | addTransaction(payerPhone, expense_type, amount, payee) { 62 | try { 63 | var payer = this.findUser(payerPhone) 64 | var tran = Transaction.createTransaction(payer.ID, expense_type, amount, payee) 65 | 66 | this.Transactions = { 67 | ...this.Transactions, 68 | [tran.ID]: tran 69 | } 70 | 71 | var ut = UserTransaction.createUserTransaction(tran.ID, payer.ID, TRANSACTION_TYPE_DEBIT, amount) 72 | this.UserTransactions = { 73 | ...this.UserTransactions, 74 | [ut.ID] : ut 75 | } 76 | 77 | for(let i=0; i