# Cash - [Cash](#cash) - [About the solution](#about-the-solution) - [Stack](#stack) - [Design](#design) - [Assumptions & Trade offs](#assumptions-amp-trade-offs) - [What would I do more if I have more time](#what-would-i-do-more-if-i-have-more-time) - [How to run](#how-to-run) - [docker-compose](#docker-compose) - [The classic Way](#the-classic-way) - [Run the application against custom inputs](#run-the-application-against-custom-inputs) ## About the solution ### Stack - Go - [Logrus](https://github.com/sirupsen/logrus) for better logging - [testify/assert](https://github.com/stretchr/testify) some test assertion helpers ### Design In my design, there are `4` core domains, - Application, represents the cash application which can load inputs and execute actions. - BankAccount, contains the information of a single bank account and basic deposit/withdraw actions to the user. - Bank, the bank entity which holds all the bank accounts and the total balance. All the `deposit/withdraw` actions go to bank and then acknowledged by bank account. - Command, represent a single action. e.g. `deposit`, `withdraw`, `balance`. way. All commands have been implemented the `ICommand` interface with `Run(bank *Bank)` method, so they can be processed by the application in a standard The steps below shows how the application works. 1. When we start this application it will initialise a `bank` and the `cash application` instance. 2. All the actions recorded in a input file will be parsed and transferred to `command` 3. The Cash application will take the commands as input, process them and print out some basic information. ### Assumptions & Trade offs In order to start implementing this project, I have made a few assumptions below: - Only one seesion for any user at any single moment, which means there will no dirty reads/writes for a user - All the actions will be loaded through a input text file and will be processed following the sequence order, so it means the application currently can only run one command at a time. - I use Australian Dollar($) as the currency type, use `int` to represent `cent` as the currency unit. ### What would I do more if I have more time There are two things I want to do most in terms of building a proper cash app if I have more time. - Make it to be a CLI and support multiple users login and run actions at the same time. - Add some basic locks for depositing and withdrawing operations at both user and bank level. ## How to run ### docker-compose Please make sure you have `docker` and `docker-compose` installed Then just simply run the commands below ```bash # One command to run application docker-compose up # If you want to run another failure case with withdrawing more money than the user has docker-compose run cash go run main.go no_enough_money.txt # Run tests docker-compose run cash go test ./... -cover ``` Or you can try the classic way. ### The classic Way Similar, you should have `go` installed before we start ```bash # Install all dependencies go mod download # Run application go run main.go input.txt # Run Tests go test ./... -cover ``` ### Run the application against custom inputs You can also build your custom input and define as many commands as you want. There is a example below with single bank account. ``` OPEN_ACCOUNT Tom DEPOSIT Tom 520.30 WITHDRAW Tom 340.00 BALANCE Tom TOTAL_BALANCE ``` Then test it ```bash docker-compose run cash go run main.go yourfile ```