demo-warehouse-software

A simple demo of a warehouse software with Typescript, PostgreSQL, Prisma, Golang, NextJS...

MIT License

Stars
5
Committers
3

This project was made for first-time contributors and open source beginners

This project follows the Poppins manifesto guidelines as part of it's community principles and policies, focusing all the decisions and interactions on providing open source beginners mentorship with real and relevant experiences, respecting each learning pace, background experience, academic formation, questions, suggestions, doubts and opinion.

Contribute now!

So, let's start contributing! Open an issue asking for a task to be done by you. A mentor/maintainer will come and provide a technical overview of the project and what are the possibles ways of contributing to the project. You will discuss the options and a suitable issue will be assigned or created to you.

That's it. Just make yourself at home and good luck!

Demo Warehouse Software

A simple demo of a warehouse software with TypeScript, PostgreSQL, Prisma, Go, NextJS...

Getting started

Option 1

git clone https://github.com/tiagostutz/demo-warehouse-software
docker-compose up

Wait for the services to be ready and then populate the database with using the file watch:

cp assets/inventory.json local-data/incoming/article/
cp assets/products.json local-data/incoming/product/
cd web-app
yarn install
yarn build
yarn start

Open http://localhost:3000 on your Browser and check

Option 2

  1. Create this docker-compose.yml:
version: "3.7"

services:
  db:
    image: tiagostutz/warehouse-demo-postgres:0.0.3
    environment:
      - POSTGRES_DB=demo-warehouse
      - POSTGRES_PASSWORD=123456
      - POSTGRES_INITDB_ARGS=--debug
    ports:
      - 5432:5432

  api-backend:
    image: tiagostutz/warehouse-demo-api-backend:0.0.3
    ports:
      - 4000:4000
    environment:
      - DATABASE_URL=postgres://postgres:123456@db:5432/demo-warehouse

  database-updater:
    image: tiagostutz/warehouse-demo-database-updater:0.0.3
    volumes:
      - ./local-data:/app/data
    environment:
      - LOG_LEVEL=debug
      - WAREHOUSE_ARTICLE_ENDPOINT=http://api-backend:4000/article
      - WAREHOUSE_PRODUCT_ENDPOINT=http://api-backend:4000/product

And bring it up:

docker-compose up
  1. After all the services are up, check that the database is clean by executing:
curl http://localhost:4000/article
curl http://localhost:4000/product

They should return and empty array [] as the response.

  1. Now let's put some Articles from the inventory.json file. To do this, you need to copy this file to the folder the database auto-updater is watching for. Execute this:
cp assets/inventory.json local-data/incoming/article/

Check again the return of the API:

curl http://localhost:4000/article
  1. Now let's put some Products from the products.json file. To do this, you need to copy this file to the folder the database auto-updater is watching for. Execute this:
cp assets/products.json local-data/incoming/product/

Check again the return of the API:

curl http://localhost:4000/product
  1. Let's get some details on the products created, like the quantity available based on the invetory stock:
curl http://localhost:4000/product/1
curl http://localhost:4000/product/2

If all went as expected, the quantityAvailable of this Product with id=1 should be 2 and of the Product with id=2 should be 1.

  1. Finally, let's update the inventory stock (reduce) simulating as if a second product was bought and let's check the quantity of the first:
curl --location --request POST 'http://localhost:4000/article/stock-update/by/product/2' \
--header 'Content-Type: application/json' \
--data-raw '{
    "quantity": 1
}'

And let's check how the quantity available of the Products we have now:

curl http://localhost:4000/product/1

Product with id=1 should have quantityAvailable=1

curl http://localhost:4000/product/2

Product with id=2 should have quantityAvailable=0

Overview of the Stack

  • Frontend: NextJS with FaaS that makes the requests to the API Backend
  • API Backend: Typescript application that uses ExpressJS to handle API routing, Prisma as ORM to access Database and JEST for testing.
  • Database Auto-updater: Golang application that watches for files being placed on a given folder and starts a Pipeline that will end up making a request to the API Backend to create Article and Products read and converted from files

Development Mode

To run each part individually in development mode, follow the steps bellow

API Backend

To run api-backend in development mode, first clone this repo:

git clone https://github.com/tiagostutz/demo-warehouse-software.git

Bring the database up:

docker-compose up db

Then go to the api-backend folder and run

yarn install

Run the tests:

yarn test

Start the API in development mode:

yarn run dev

Database auto-updater

First, bring the database and the api-backend up (described in the previous session).

After that, run

go mod download

Then, to run the tests run:

go test ./...

Evolution Stages

Stage 1 (current implementation): no security, no load handling, no caching stage 1 overview

Stage 2 (goal of this project): security, load balancing one level (API Gateway), no caching stage 2 overview

Stage 3 (start production): security, load balancing one level (API Gateway), observability, caching stage 3 overview

Stage 4 (scaling to the cloud): security, load handling, caching, observability, database replica/shard, job scheduling with queues and workflow management stage 4 overview

Testing

There are two levels of tests: component/service/unit level and integration/API level test.

Running API Backend tests:

yarn run test

To run the Database Auto-updater integrated tests, you need the database and one instance of the API Backend up at localhost:4000, then run:

go test ./...

API Backend

The tests here are at folders names tests and the files has a .test.ts suffix. To run the tests:

yarn run test

Database Auto-updater

Architecture overview and Design decisions

  • Pros and cons
  • Other possibilities
  • Kong API Gateway
  • Sidecar/Ambassador to hide from the Business Logic this complexity

Observability

  • Healthcheck
    • /health
    • /ready
  • Prometheus Metrics:
    • Database updater
    • API Backend
  • Grafana

Prisma as an ORM (and why not GraphQL?)

What happens when running:

yarn install @prisma/client

The install command automatically invokes prisma generate for you which reads your Prisma schema and generates a version of Prisma Client that is tailored to your models. Whenever you make changes to your Prisma schema in the future, you manually need to invoke npx prisma generate in order to accomodate the changes in your Prisma Client API.

DATABASE_URL=postgres://postgres:123456@localhost:5432/demo-warehouse npx prisma migrate dev --name init
  • GraphQL: definitely would be a good option, but there are some scenarios we need specific business logic that would need some code working. But for data fecthing and mutation to database, good one. The endpoints that need additional logic could expose those endpoints as regular APIs and use the GraphQL to fetch and mutate data.
  • Migration tool demo:
    • started with ON DELETE CASCADE for all FKs
    • then ON DELETE RESTRICT for all FKs
    • then ON DELETE RESTRICT for Article ON DELETE CASCADE for Product
DATABASE_URL=postgres://postgres:123456@localhost:5432/demo-warehouse npx prisma migrate dev --name init

TypeScript mixed with pure JavaScript

If there's no domain involved or for a more integration and "flow setup" kind of code, go with vanilla JavaScript. If there's model, business logic or heavy componentization, go with TypeScript.

Thoughts on scaling the solution

  • Change the load from watching files to consuming a queue
  • If a need for a more complex enrichment of the data, consider using a Workflow/pipeline orchestrator (like Netflix Conductor)

Software Highlevel Spec

This software should hold articles, and the articles should contain:

  • identification number
  • name
  • available stock

It should be possible to load articles into the software from a file, see the provided inventory.json sample file.

The warehouse software should also have products, products are made of different articles. Products should have:

  • name
  • price
  • list of articles of which they are made from with a quantity

The products should also be loaded from a file, see the provided products.json sample file.

The warehouse should have at least the following functionality;

  • Get all products and quantity of each that is available with the current inventory
  • Remove(Sell) a product and update the inventory accordingly

Awesome Poppins projects looking for contributors:

Here's a list of some more curated Poppins projects:

  • First Contributions Repository: This project is designed to help beginners make their very first contributions to open source projects.
  • Contribute to this Project: This is for absolute beginners. If you know how to write and edit an anchor tag then you're ready to start contributing!
  • Contribute to open source:
    Learn the GitHub workflow by contributing code in a fun simulation project.
  • goodfirstissue.dev: goodfirstissue.dev has a list of project repositories with the good first issue tag. Project moderators add this tag to help beginners get involved with their projects.
Badges
Extracted from project README
This is a Poppins project
Related Projects