danoseun / hometask-be-template-master

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DEEL BACKEND TASK

πŸ’« Welcome! πŸŽ‰

This backend exercise involves building a Node.js/Express.js app that will serve a REST API. We imagine you should spend around 3 hours at implement this feature.

Data Models

All models are defined in src/model.js

Profile

A profile can be either a client or a contractor. clients create contracts with contractors. contractor does jobs for clients and get paid. Each profile has a balance property.

Contract

A contract between and client and a contractor. Contracts have 3 statuses, new, in_progress, terminated. contracts are considered active only when in status in_progress Contracts group jobs within them.

Job

contractor get paid for jobs by clients under a certain contract.

Getting Set Up

The exercise requires Node.js to be installed. We recommend using the LTS version.

  1. Start by creating a local repository for this folder.

  2. In the repo root directory, run npm install to gather all dependencies.

  3. Next, npm run seed will seed the local SQLite database. Warning: This will drop the database if it exists. The database lives in a local file database.sqlite3.

  4. Then run npm start which should start both the server and the React client.

❗️ Make sure you commit all changes to the master branch!

Technical Notes

  • The server is running with nodemon which will automatically restart for you when you modify and save a file.

  • The database provider is SQLite, which will store data in a file local to your repository called database.sqlite3. The ORM Sequelize is on top of it. You should only have to interact with Sequelize - please spend some time reading sequelize documentation before starting the exercise.

  • To authenticate users use the getProfile middleware that is located under src/middleware/getProfile.js. users are authenticated by passing profile_id in the request header. after a user is authenticated his profile will be available under req.profile. make sure only users that are on the contract can access their contracts.

  • The server is running on port 3001.

APIs To Implement

Below is a list of the required API's for the application.

  1. GET /contracts/:id - This API is broken 😡! it should return the contract only if it belongs to the profile calling. better fix that!

  2. GET /contracts - Returns a list of contracts belonging to a user (client or contractor), the list should only contain non terminated contracts.

  3. GET /jobs/unpaid - Get all unpaid jobs for a user (either a client or contractor), for active contracts only.

  4. POST /jobs/:job_id/pay - Pay for a job, a client can only pay if his balance >= the amount to pay. The amount should be moved from the client's balance to the contractor balance.

  5. POST /balances/deposit/:userId - Deposits money into the the the balance of a client, a client can't deposit more than 25% his total of jobs to pay. (at the deposit moment)

  6. GET /admin/best-profession?start=<date>&end=<date> - Returns the profession that earned the most money (sum of jobs paid) for any contactor that worked in the query time range.

  7. GET /admin/best-clients?start=<date>&end=<date>&limit=<integer> - returns the clients the paid the most for jobs in the query time period. limit query parameter should be applied, default limit is 2.

 [
    {
        "id": 1,
        "fullName": "Reece Moyer",
        "paid" : 100.3
    },
    {
        "id": 200,
        "fullName": "Debora Martin",
        "paid" : 99
    },
    {
        "id": 22,
        "fullName": "Debora Martin",
        "paid" : 21
    }
]

Going Above and Beyond the Requirements

Given the time expectations of this exercise, we don't expect anyone to submit anything super fancy, but if you find yourself with extra time, any extra credit item(s) that showcase your unique strengths would be awesome! πŸ™Œ

It would be great for example if you'd write some unit test / simple frontend demostrating calls to your fresh APIs.

Submitting the Assignment

When you have finished the assignment, zip your repo (make sure to include .git folder) and send us the zip.

Thank you and good luck! πŸ™


To run locally

  • Use npm run dev to run in development mode.
  • To lint the entire project, use npm run lint.
  • Use npm run test to run both unit and integration tests.

To run with docker

  • After cloning the repo, do the following,
    • in the root of the project run chmod +x run.sh(gives it executable permissions)
    • Then ./run.sh or sh run.sh.

Decisions made

  1. Added eslint and prettier to the project
  2. Separated the models into modules and congregated them into index.js file to improve code structure
  3. Added more error handlers and a central error handler.
  4. Services and models did the heavy lifting of the business logic making the controllers lean
  5. Routes were separated and brought together in an index file.
  6. Transactions and locking mechanisms were used where necessary to achieve atomicity and limit concurrency
  7. Tests were also written to verify that code works as expected.
  8. Project was dockerised and a start script was added to start the project for the docker option.
  9. Docs can be found in the /docs directory in the root.

Further Improvements to be considered

  1. Proper schema validation(e.g using Joi, express-validator or yup) to de-risk the app from accepting untrusted data and increase data consistency.
  2. Setting up proper logging and monitoring to add observability to the server.
  3. API versioning would also make sense. It helps in terms of backward compatibility, security and compliance et.c
  4. In production, it would be proper to use secure authentication practices using (JWT Auth) following OWASP principles, Authorization and RBAC(Role Based Access).
  5. In production, it will be advisable to use migrations rather than force syncing.
  6. Add more tests to check for fuzzy or certain edge cases.
  7. In production, we would want to use environment variables to manage database connections and other secret and dynamic data.
  8. If the project keeps growing, we could consider migrating to a typed language like Typescript to catch bugs at compile time and take advantage of more OOP concepts.

About


Languages

Language:JavaScript 99.7%Language:Dockerfile 0.2%Language:Shell 0.1%