Skip to content

development #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
fc0d3ef
feat: Add investment model
gabrsil Jun 3, 2022
187682d
feat: Add investment resolver]
gabrsil Jun 3, 2022
f5728bf
feat: Add investment type validators.
gabrsil Jun 3, 2022
440a214
feat: Add user model
gabrsil Jun 3, 2022
fe995e5
feat: Add user resolver
gabrsil Jun 3, 2022
c7e205c
feat: Add user type validators
gabrsil Jun 3, 2022
69125d5
feat: Add investment withdrawal model
gabrsil Jun 3, 2022
6a2c569
feat: Add withdrawal resolver
gabrsil Jun 3, 2022
7cf935e
feat: Add withdrawal type validators
gabrsil Jun 3, 2022
3c007a0
feat: add setup express and graphql server.
gabrsil Jun 3, 2022
8779eb9
test: add graphql queries for testing
gabrsil Jun 3, 2022
8c67a5c
test: add database helpers for tests
gabrsil Jun 3, 2022
ce82fd8
test: add withdrawal integration-tests
gabrsil Jun 3, 2022
fb3f9c4
test: add user integration-tests
gabrsil Jun 3, 2022
38e9d0b
test: add investment integration-tests
gabrsil Jun 3, 2022
efa8d7f
feat: add docker configuration files
gabrsil Jun 3, 2022
3980f37
feat: add libs configuration files
gabrsil Jun 3, 2022
ff2bb3b
feat: add types
gabrsil Jun 3, 2022
21101c2
add config files
gabrsil Jun 3, 2022
bac50ef
feat: add auto-generated graphql file
gabrsil Jun 3, 2022
701c140
chore: update README
gabrsil Jun 3, 2022
1af83f6
fix: remove comments
gabrsil Jun 3, 2022
c1c6787
chore: update import Ref
gabrsil Jun 3, 2022
5632fea
chore: update import Ref
gabrsil Jun 3, 2022
93611fb
fix: change date validation
gabrsil Jun 4, 2022
fd78ff8
fix: change message error
gabrsil Jun 4, 2022
06b298c
fix: change date validation
gabrsil Jun 4, 2022
3bf223e
fix: add withdrawal query and remove bracets from query
gabrsil Jun 4, 2022
1f6f451
test: fix result tests
gabrsil Jun 4, 2022
1acffbf
test: fix result tests
gabrsil Jun 4, 2022
db9f3cb
test: add get-withdrawal tests
gabrsil Jun 4, 2022
d000d14
fix package.json
gabrsil Jun 4, 2022
8e5072c
resolve files
gabrsil Jun 4, 2022
eeea9be
add data folder to .gitignore
gabrsil Jun 4, 2022
6e8549f
change .gitignore
gabrsil Jun 4, 2022
dc14cc5
change .gitignore
gabrsil Jun 4, 2022
c178e89
delete data folder
gabrsil Jun 4, 2022
c2a7c52
merge
gabrsil Jun 4, 2022
fcb42a1
Update README.md
gabrsil Jun 6, 2022
c022e52
fix README
gabrsil Jun 6, 2022
67b43fd
Merge branch 'develop' of https://github.com/gabrsil/backend-test int…
gabrsil Jun 6, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MONGO_URI= mongodb://localhost:27017/investments
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.env
node_modules
.data
dist
data
8 changes: 8 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"trailingComma": "none",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"jsxSingleQuote": true,
"arrowParens": "always"
}
8 changes: 8 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM node:14-alpine
WORKDIR /app
COPY package.json /app
RUN yarn
COPY . /app
RUN yarn ts-build
CMD yarn start
EXPOSE 3333
95 changes: 14 additions & 81 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,88 +1,21 @@
# Back End Test Project <img src="https://coderockr.com/assets/images/coderockr.svg" align="right" height="50px" />
# Backend Test

You should see this challenge as an opportunity to create an application following modern development best practices (given the stack of your choice), but also feel free to use your own architecture preferences (coding standards, code organization, third-party libraries, etc). It’s perfectly fine to use vanilla code or any framework or libraries.
## What is this
its a investments app backend to create investments, control monthly gains (based on taxes) and withdrawal those investments.

## Scope
## Technologies and tools
Recently i'm enjoying to use this stack and tools mostly because of the easy setup and his semantical way to do things. So its a express server with graphql, using Apollo as server. Then we have *type-graphql* to handle graphql stuff with classes and use decorators (aka reflection-metadata). As database i choose mongodb because of the simple entities/relations setup and his lib (typegoose) works well with type-graphql. For tests i use Jest with supertest to simulate the graphql server.

In this challenge you should build an API for an application that stores and manages investments, it should have the following features:
## How to Execute

1. __Creation__ of an investment with an owner, a creation date and an amount.
1. The creation date of an investment can be today or a date in the past.
2. An investment should not be or become negative.
2. __View__ of an investment with its initial amount and expected balance.
1. Expected balance should be the sum of the invested amount and the [gains][].
3. __Withdrawal__ of a investment.
1. The withdraw will always be the sum of the initial amount and its gains,
partial withdrawn is not supported.
2. Withdrawals can happen in the past or today, but can't happen before the investment creation or the future.
3. [Taxes][taxes] need to be applied to the withdrawals before showing the
final value.
4. __List__ of a person's investments
1. This list should have pagination.
First of all you will need to install [git](https://git-scm.com/downloads), then [nodejs](https://nodejs.org/en/download/) and [docker](https://docs.docker.com/desktop/windows/install/) to run the server. With that, clone this repository. After open your terminal in the folder that you clone the repo, run ***npm install*** to install all dependencies. Finally to run the server and database type the command ***docker-compose up --build*** to up the docker container (if the command not work maybe you will have to [add docker in windows enviroment variables](https://stackoverflow.com/questions/49478343/windows-doesnt-recognize-docker-command)). Now the server should be running, open *http://localhost:3333/graphql* to see the magic.

__NOTE:__ the implementation of an interface will not be evaluated.
## Documentation
Apollo Graphql for itself has a documentation in his playground, showing all the queries, mutations and so on. To see the docs its just open the button *DOCS* on the right side of the playground.

### Gain Calculation
## Tests
To run the integration-tests, you will need to run the database container ***docker-compose up --build*** and run the command ***yarn test***.

The investment will pay 0.52% every month in the same day of the investment creation.

Given that the gain is paid every month, it should be treated as [compound gain][], which means that every new period (month) the amount gained will become part of the investment balance for the next payment.

### Taxation

When money is withdrawn, tax is triggered. Taxes apply only to the profit/gain portion of the money withdrawn. For example, if the initial investment was 1000.00, the current balance is 1200.00, then the taxes will be applied to the 200.00.

The tax percentage changes according to the age of the investment:
* If it is less than one year old, the percentage will be 22.5% (tax = 45.00).
* If it is between one and two years old, the percentage will be 18.5% (tax = 37.00).
* If older than two years, the percentage will be 15% (tax = 30.00).

## Requirements
1. Create project using any technology of your preference. It’s perfectly OK to use vanilla code or any framework or libraries;
2. Although you can use as many dependencies as you want, you should manage them wisely;
3. It is not necessary to send the notification emails, however, the code required for that would be welcome;
4. The API must be documented in some way.

## Deliverables
The project source code and dependencies should be made available in GitHub. Here are the steps you should follow:
1. Fork this repository to your GitHub account (create an account if you don't have one, you will need it working with us).
2. Create a "development" branch and commit the code to it. Do not push the code to the main branch.
3. Include a README file that describes:
- Special build instructions, if any
- List of third-party libraries used and short description of why/how they were used
- A link to the API documentation.
4. Once the work is complete, create a pull request from "development" into "main" and send us the link.
5. Avoid using huge commits hiding your progress. Feel free to work on a branch and use `git rebase` to adjust your commits before submitting the final version.

## Coding Standards
When working on the project be as clean and consistent as possible.

## Project Deadline
Ideally you'd finish the test project in 5 days. It shouldn't take you longer than a entire week.

## Quality Assurance
Use the following checklist to ensure high quality of the project.

### General
- First of all, the application should run without errors.
- Are all requirements set above met?
- Is coding style consistent?
- The API is well documented?
- The API has unit tests?

## Submission
1. A link to the Github repository.
2. Briefly describe how you decided on the tools that you used.

## Have Fun Coding 🤘
- This challenge description is intentionally vague in some aspects, but if you need assistance feel free to ask for help.
- If any of the seems out of your current level, you may skip it, but remember to tell us about it in the pull request.

## Credits

This coding challenge was inspired on [kinvoapp/kinvo-back-end-test](https://github.com/kinvoapp/kinvo-back-end-test/blob/2f17d713de739e309d17a1a74a82c3fd0e66d128/README.md)

[gains]: #gain-calculation
[taxes]: #taxation
[interest]: #interest-calculation
[compound gain]: https://www.investopedia.com/terms/g/gain.asp
## Final Considerations
I Enjoyed to do this test since i tried tools and stack that i like but don't use on normal days, so
was a great experience, put me out of comfort zone, read some docs and try to make things work.
21 changes: 21 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: '3.8'
services:
app:
container_name: app
restart: always
build: .
ports:
- "3333:3333"
links:
- mongodb
mongodb:
image: mongo
container_name: mongodb
environment:
- PUID=1000
- PGID=1000
volumes:
- ./data:/data/db
ports:
- "27017:27017"
restart: always
192 changes: 192 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/

export default {
// All imported modules in your tests should be mocked automatically
// automock: false,
preset: "ts-jest",
testEnvironment: "node",
// Stop running tests after `n` failures
// bail: 0,
testTimeout: 15000,
// The directory where Jest should store its cached dependency information
// cacheDirectory: "C:\\Users\\gabri\\AppData\\Local\\Temp\\jest",

// Automatically clear mock calls, instances, contexts and results before every test
clearMocks: true,

// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,
setupFiles: ['dotenv/config'],
// An array of glob patterns indicating a set of files for which coverage information should be collected
// collectCoverageFrom: undefined,

// The directory where Jest should output its coverage files
coverageDirectory: "coverage",

// An array of regexp pattern strings used to skip coverage collection
// coveragePathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],

// Indicates which provider should be used to instrument code for coverage
coverageProvider: "v8",

// A list of reporter names that Jest uses when writing coverage reports
// coverageReporters: [
// "json",
// "text",
// "lcov",
// "clover"
// ],

// An object that configures minimum threshold enforcement for coverage results
// coverageThreshold: undefined,

// A path to a custom dependency extractor
// dependencyExtractor: undefined,

// Make calling deprecated APIs throw helpful error messages
// errorOnDeprecated: false,

// The default configuration for fake timers
// fakeTimers: {
// "enableGlobally": false
// },

// Force coverage collection from ignored files using an array of glob patterns
// forceCoverageMatch: [],

// A path to a module which exports an async function that is triggered once before all test suites
// globalSetup: undefined,

// A path to a module which exports an async function that is triggered once after all test suites
// globalTeardown: undefined,

// A set of global variables that need to be available in all test environments
// globals: {},

// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: "50%",

// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],

// An array of file extensions your modules use
moduleFileExtensions: [
"js",
"ts",
"json",
"node"
],

// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
// moduleNameMapper: {},

// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],

// Activates notifications for test results
// notify: false,

// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "failure-change",

// A preset that is used as a base for Jest's configuration
// preset: undefined,

// Run tests from one or more projects
// projects: undefined,

// Use this configuration option to add custom reporters to Jest
// reporters: undefined,

// Automatically reset mock state before every test
// resetMocks: false,

// Reset the module registry before running each individual test
// resetModules: false,

// A path to a custom resolver
// resolver: undefined,

// Automatically restore mock state and implementation before every test
// restoreMocks: false,

// The root directory that Jest should scan for tests and modules within
// rootDir: undefined,

// A list of paths to directories that Jest should use to search for files in
// roots: [
// "<rootDir>"
// ],

// Allows you to use a custom runner instead of Jest's default test runner
// runner: "jest-runner",

// The paths to modules that run some code to configure or set up the testing environment before each test
// setupFiles: [],

// A list of paths to modules that run some code to configure or set up the testing framework before each test
// setupFilesAfterEnv: [],

// The number of seconds after which a test is considered as slow and reported as such in the results.
// slowTestThreshold: 5,

// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],

// The test environment that will be used for testing
// testEnvironment: "jest-environment-node",

// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},

// Adds a location field to test results
// testLocationInResults: false,

// The glob patterns Jest uses to detect test files
// testMatch: [
// "**/__tests__/**/*.[jt]s?(x)",
// "**/?(*.)+(spec|test).[tj]s?(x)"
// ],

// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],

// The regexp pattern or array of patterns that Jest uses to detect test files
// testRegex: [],

// This option allows the use of a custom results processor
// testResultsProcessor: undefined,

// This option allows use of a custom test runner
// testRunner: "jest-circus/runner",

// A map from regular expressions to paths to transformers
// transform: undefined,

// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
// "\\\\node_modules\\\\",
// "\\.pnp\\.[^\\\\]+$"
// ],

// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,

// Indicates whether each individual test should be reported during the run
// verbose: undefined,

// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
// watchPathIgnorePatterns: [],

// Whether to use watchman for file crawling
// watchman: true,
};
41 changes: 41 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "coderockr-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts-build": "tsc",
"test": "jest",
"serve": "node dist/app.js",
"start": "ts-node-dev --transpile-only --ignore-watch node_modules src/app.ts"
},
"author": "",
"license": "ISC",
"dependencies": {
"@typegoose/typegoose": "^9.8.1",
"apollo-server": "^3.8.1",
"apollo-server-express": "^3.8.1",
"class-validator": "^0.13.2",
"date-fns": "^2.28.0",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"graphql": "^15.3.0",
"mongoose": "^6.3.4",
"reflect-metadata": "^0.1.13",
"supertest": "^6.2.3",
"type-graphql": "^1.1.1"
},
"devDependencies": {
"@types/express": "^4.17.13",
"@types/graphql": "^14.5.0",
"@types/jest": "^28.1.0",
"@types/node": "^17.0.36",
"@types/supertest": "^2.0.12",
"jest": "^28.1.0",
"nodemon": "^2.0.16",
"prettier": "^2.6.2",
"ts-jest": "^28.0.3",
"ts-node-dev": "^2.0.0",
"typescript": "^4.7.2"
}
}
Loading