# Build an Inventory Management System Using MongoDB Atlas

In the competitive retail landscape, having the right stock in the right place at the right time is crucial. Too little inventory when and where it’s needed can create unhappy customers. However, a large inventory can increase costs and risks associated with its storage. Companies of all sizes struggle with inventory management. Solutions such as a single view of inventory, real-time analytics, and event-driven architectures can help your businesses overcome these challenges and take your inventory management to the next level. By the end of this guide, you'll have inventory management up and running, capable of all the solutions mentioned above. 

We will walk you through the process of configuring and using MongoDB Atlas as your back end for your Next.js app, a powerful framework for building modern web applications with React.

The architecture we're about to set up is depicted in the diagram below:

 Let's get started!

## Prerequisites

Before you begin working with this project, ensure that you have the following prerequisites set up in your development environment:

- **Git** (version 2.39 or higher): This project utilizes Git for version control. Make sure you have Git installed on your system. You can download and install the latest version of Git from the official website: Git Downloads.
- **Node.js** (version 20 or higher) and **npm** (version 9.6 or higher): The project relies on the Node.js runtime environment and npm (Node Package Manager) to manage dependencies and run scripts. You need to have them both installed on your machine. You can download Node.js from the official website: Node.js Downloads. After installing Node.js, npm will be available by default.
- **jq** (version 1.6 or higher): jq is a lightweight and flexible command-line JSON processor. We will use it to filter and format some command outputs to better identify the values we are interested in. Visit the official Download jq page to get the latest version.
- **mongorestore** (version 100.9.4 or higher): The mongorestore tool loads data from a binary database dump. The dump directory in the GitHub repository includes a demo database with preloaded collections, views, and indexes, to get you up and running in no time. This tool is part of the MongoDB Database Tools package. Follow the Database Tools Installation Guide to install mongorestore. When you are done with the installation, run mongorestore --version in your terminal to verify the tool is ready to use.
- **App Services CLI** (version 1.3.1 or higher): The Atlas App Services Command Line Interface (appservices) allows you to programmatically manage your applications. We will use it to speed up the app backend setup by using the provided template in the app_services directory in the GitHub repository. App Services CLI is available on npm. To install the CLI on your system, ensure that you have Node.js installed and then run the following command in your shell: npm install -g atlas-app-services-cli.
- **MongoDB Atlas cluster** (M0 or higher): This project uses a MongoDB Atlas cluster to manage the database. You should have a MongoDB Atlas account and a minimum free tier cluster set up. If you don't have an account, you can sign up for free at MongoDB Atlas. Once you have an account, follow these steps to set up a minimum free tier cluster or follow the Getting Started guide:
    - Log into your MongoDB Atlas account.
    - Create a new project or use an existing one, and then click “Create a new database.”
    - Choose the free tier option (M0).
    - You can choose the cloud provider of your choice but we recommend using the same provider and region both for the cluster and the app hosting in order to improve performance.
    - Configure the cluster settings according to your preferences and then click “finish and close” on the bottom right.

## Initial configuration

### Obtain your connection string

Once the MongoDB Atlas cluster is set up, locate your newly created cluster, click the "Connect" button, and select the "Compass" section. Copy the provided connection string. It should resemble something like this:

```
mongodb+srv://:@cluster-name.xxxxx.mongodb.net/
```

> Note: You will need the connection string to set up your environment variables later (`MONGODB_URI`).

### Cloning the GitHub repository

Now, it's time to clone the demo app source code from GitHub to your local machine:

1. Open your terminal or command prompt.

2. Navigate to your preferred directory where you want to store the project using the cd command. For example:

    ```
    cd /path/to/your/desired/directory
    ```

3. Once you're in the desired directory, use the `git clone` command to clone the repository. Copy the repository URL from the GitHub repository's main page:

    ```
    git clone git@github.com:mongodb-industry-solutions/Inventory_mgmt.git
    ```

4. After running the `git clone` command, a new directory with the repository's name will be created in your chosen directory. To navigate into the cloned repository, use the cd command:

    ```
     cd Inventory_mgmt
    ```

## MongoDB Atlas configuration

### Replicate the sample database

The database contains:

- Five collections
    - **Products**: The sample database contains 17 products corresponding to T-shirts of different colors. Each product has five variants that represent five different sizes, from XS to XL. These variants are stored as an embedded array inside the product. Each variant will have a different SKU and therefore, its own stock level. Stock is stored both at item (`items.stock`) and product level (`total_stock_sum`).
    - **Transactions**: This collection will be empty initially. Transactions will be generated using the app, and they can be of inbound or outbound type. Outbound transactions result in a decrease in the product stock such as a sale. On the other hand, inbound transactions result in a product stock increase, such as a replenishment order.
    - **Locations**: This collection stores details of each of the locations where we want to keep track of the product stock. For the sake of this guide, we will just have two stores to demonstrate a multi-store scenario, but this could be scaled to thousands of locations. Warehouses and other intermediate locations could be also included. In this case, we assume a single warehouse, and therefore, we don’t need to include a location record for it.
    - **Users**: Our app will have three users: two store managers and one area manager. Store managers will be in charge of the inventory for each of the store locations. Both stores are part of the same area, and the area manager will have an overview of the inventory in all stores assigned to the area.
    - **Counters**: This support collection will keep track of the number of documents in the transactions collection so an auto-increment number can be assigned to each transaction. In this way, apart from the default _id field, we can have a human-readable transaction identifier.
- One view:
    - Product area view: This view is used by the area manager to have an overview of the inventory in the area. Using the aggregation pipeline, the product and item stock levels are grouped for all the locations in the same area.
- One index:
    - The number of transactions can grow quickly as we use the app. To improve performance, it is a good practice to set indexes that can be leveraged by common queries. In this case, the latest transactions are usually more relevant and therefore, they are displayed first. We also tend to filter them by type — inbound/outbound — and product. These three fields — `placement_timestamp`, type, and `product.name` — are part of a compound index that will help us to improve transaction retrieval time.

To replicate the sample database on your MongoDB Atlas cluster, run the following command in your terminal:

```
 mongorestore --uri  dump/
```

Make sure to replace `` with your MongoDB Atlas connection string. If you've already followed the initial configuration steps, you should have obtained this connection string. Ensure that the URI includes the username, password, and cluster details.

After executing these commands, you can verify the successful restoration of the demo database by checking the last line of the command output, which should display "22 document(s) restored successfully." These correspond to the 17 products, three users, and two locations mentioned earlier.

 are fully managed backend services and APIs that help you build apps, integrate services, and connect to your Atlas data faster. 

Atlas’s built-in device-to-cloud-synchronization service — Device Sync — will enable real-time low-stock alerts. Triggers and functions can execute serverless application and database logic in response to these events to automatically issue replenishment orders. And by using the Data API and Custom HTTPS Endpoints, we ensure a seamless and secure integration with the rest of the components in our inventory management solution.

Check how the stock is automatically replenished when a low-stock event occurs. 

 pair to authenticate your CLI calls. Navigate to MongoDB Cloud Access Manager, click the "Create API Key" button, and select the `Project Owner` permission level. For an extra layer of security, you can add your current IP address to the Access List Entry.

3. Authenticate your CLI user by running the command below in your terminal. Make sure you replace the public and private API keys with the ones we just generated in the previous step. 

    ```
    appservices login --api-key="" --private-api-key=""
    ```

4. Import the app by running the following command. Remember to replace `` by your preferred name. 

    ```
    appservices push --local ./app_services/ --remote 
    ```

    You will be prompted to configure the app options. Set them according to your needs. If you are unsure which options to choose, the default ones are usually a good way to start! For example, this is the configuration I've used.

    ```
    ? Do you wish to create a new app? Yes
    ? App Name inventory-management-demo
    ? App Deployment Model LOCAL
    ? Cloud Provider aws
    ? App Region aws-eu-west-1
    ? App Environment testing
    ? Please confirm the new app details shown above Yes
    ```

    Once the app is successfully created, you will be asked to confirm some changes. These changes will load the functions, triggers, HTTP endpoints, and other configuration parameters our inventory management system will use. 

     After a few seconds, you will see a success message like “Successfully pushed app up: ``”. Take note of the obtained app ID.

5. In addition to the app ID, our front end will also need the base URL to send HTTP requests to the back end. Run the command below in your terminal to obtain it. Remember to replace `` with your own value. The jq tool will help us to get the appropriate field and format. Take note of the obtained URI.

    ```
    appservices apps describe --app  -f json | jq -r '.doc.http_endpoints0].url | split("/") | (.[0] + "//" + .[2])'
    ```

6. Finally, our calls to the back end will need to be authenticated. For this reason, we will create an API key that will be used by the server side of our inventory management system to generate an access token. It is only this access token that will be passed to the client side of the system to authenticate the calls to the back end.

> Important: This API key is not the same as the key used to log into the `appservices` CLI.

Again, before running the command, remember to replace the placeholder ``.

```
appservices users create --type=api-key --app= --name=tutorial-key
```

After a few seconds, you should see the message “Successfully created API Key,” followed by a JSON object. Copy the content of the field `key` and store it in a secure place. Remember that if you lose this key, you will need to create a new one.

> Note: You will need the app ID, base App Services URI, and API key to set up your environment variables later (`REALM_APP_ID`, `APP_SERVICES_URI`, `API_KEY`).

### Set up Atlas Search and filter facets

Follow these steps to configure search indexes for full-text search and filter facets:

1. Navigate to the "Data Services" section within Atlas. Select your cluster and click on "Atlas Search" located next to "Collections."

2. If you are in the M0 tier, you can create two search indexes for the products collection. This will allow you to merely search across the products collection. However, if you have a tier above M0, you can create additional search indexes. This will come in handy if you want to search and filter not only across your product catalog but also your transaction records, such as sales and replenishment orders.

3. Let's begin with creating the indexes for full-text search:

    1. Click "Create Search Index."

    2. You can choose to use either the visual or JSON editor. Select "JSON Editor" and click "Next."

    3. Leave the index name as `default`.

    4. Select your newly created database and choose the **products** collection. We will leave the default index definition, which should look like the one below.

        ```
        {
          "mappings": {
            "dynamic": true
          }
        }
        ```

        5. Click "Next" and on the next screen, confirm by clicking "Create Search Index."
        6. After a few moments, your index will be ready for use. While you wait, you can create the other search index for the **transactions** collection. You need to repeat the same process but change the selected collection in the "Database and Collection" menu next to the JSON Editor.

> Important: The name of the index (default) must be the same in order for the application to be able to work properly.

4. Now, let's proceed to create the indexes required for the filter facets. Note that this process is slightly different from creating default search indexes:
    1. Click "Create Index" again, select the JSON Editor, and click "Next."
    2. Name this index `facets`.
    3. Select your database and the **products** collection. For the index definition, paste the code below.

**Facets index definition for products**

```javascript
{
  "mappings": {
    "dynamic": false,
    "fields": {
      "items": {
        "fields": {
          "name": {
            "type": "stringFacet"
          }
        },
        "type": "document"
      },
      "name": {
        "type": "stringFacet"
      }
    }
  }
}
```

Click "Next" and confirm by clicking "Create Search Index." The indexing process will take some time. You can create the **transactions** index while waiting for the indexing to complete. In order to do that, just repeat the process but change the selected collection and the index definition by the one below:

**Facets index definition for transactions**

```javascript
{
  "mappings": {
    "dynamic": false,
    "fields": {
      "items": {
        "fields": {
          "name": {
            "type": "stringFacet"
          },
          "product": {
            "fields": {
              "name": {
                "type": "stringFacet"
              }
            },
            "type": "document"
          }
        },
        "type": "document"
      }
    }
  }
}
```

> Important: The name of the index (`facets`) must be the same in order for the application to be able to work properly.

By setting up these search indexes and filter facets, your application will gain powerful search and filtering capabilities, making it more user-friendly and efficient in managing inventory data.

### Set up Atlas Charts

Enhance your application's visualization and analytics capabilities with Atlas Charts. Follow these steps to set up two dashboards — one for product information and another for general analytics:

1. Navigate to the "Charts" section located next to "App Services."
2. Let's begin by creating the product dashboard:
    1. If this is your first time using Atlas Charts, click on “Chart builder.” Then, select the relevant project, the database, and the collection. 
    2. If you’ve already used Atlas Charts (i.e., you’re not a first-time user), then click on "Add Dashboard" in the top right corner. Give the dashboard a name and an optional description. Choose a name that clearly reflects the purpose of the dashboard. You don't need to worry about the charts in the dashboard for now. You'll configure them after the app is ready to use. 
3. Return to the Dashboards menu, click on the three dots in the top right corner of the newly created dashboard, and select "Embed."
4. Check the "Enable unauthenticated access" option. In the "Allowed filter fields" section, edit the fields and select "Allow all fields in the data sources used in this dashboard." Choose the embedding method through the JavaScript SDK, and copy both the "Base URL" and the "Dashboard ID." Click “Close.”
5. Repeat the same process for the general dashboard. Select products again, as we will update this once the app has generated data. Note that the "Base URL" will be the same for both dashboards but the “dashboard ID” will be different so please take note of it.

> Note: You will need the base URL and dashboard IDs to set up your environment variables later (`CHARTS_EMBED_SDK_BASEURL`, `DASHBOARD_ID_PRODUCT`, `DASHBOARD_ID_GENERAL`).

Setting up Atlas Charts will provide you with visually appealing and insightful dashboards to monitor product information and overall analytics, enhancing your decision-making process and improving the efficiency of your inventory management system.

## Frontend configuration

### Set up environment variables

Copy the `env.local.example` file in this directory to `.env.local` (which will be ignored by Git), as seen below:

```
cp .env.local.example .env.local
```

Now, open this file in your preferred text editor and update each variable on .env.local.

Remember all of the notes you took earlier? Grab them because you’ll use them now! Also, remember to remove any spaces after the equal sign. 

- `MONGODB_URI` — This is your MongoDB connection string to [MongoDB Atlas. You can find this by clicking the "Connect" button for your cluster. Note that you will have to input your Atlas password into the connection string.
- `MONGODB_DATABASE_NAME` — This is your MongoDB database name for inventory management.
- `REALM_APP_ID` — This variable should contain the app ID of the MongoDB Atlas App Services app you've created for the purpose of this project.
- `APP_SERVICES_URI` — This is the base URL for your MongoDB App Services. It typically follows the format `https://..data.mongodb-api.com`.
- `API_KEY` — This is your API key for authenticating calls using the MongoDB Data API.
- `CHARTS_EMBED_SDK_BASEURL` — This variable should hold the URL of the charts you want to embed in your application.
- `DASHBOARD_ID_PRODUCT` — This variable should store the Atlas Charts dashboard ID for product information.
- `DASHBOARD_ID_GENERAL` — This variable should store the Atlas Charts dashboard ID for the general analytics tab.

> Note: You may observe that some environment variables in the .env.local.example file are commented out. Don’t worry about them for now. These variables will be used in the second part of the inventory management tutorial series.

Please remember to save the updated file. 

### Run locally

Execute the following commands to run your app locally: 

```
npm ci
npm run dev
```

Your app should be up and running on http://localhost:3000! If it doesn't work, ensure that you have provided the correct environment variables.

Also, make sure your local IP is in the Access List of your project. If it’s not, just click the “Add IP address” button in the top right corner. This will display a popup menu. Within the menu, select “Add current IP address,” and click “Confirm.”

.

### Enable real-time analytics

1. To create a general analytics dashboard based on sales, we will need to generate sales data. Navigate to the control panel in your app by clicking http://localhost:3000/control.

2. Then, click the “start selling” button. When you start selling, remember to not close this window as selling will only work when the window is open. This will simulate a sale every five seconds, so we recommend letting it run for a couple of minutes. 

3. In the meantime, navigate back to Atlas Charts to create a general analytics dashboard. For example, you can create a line graph that displays sales over the last hour, minute by minute. Now, you’ll see live data coming in, offering you real-time insights!

    To achieve this, from the general dashboard, click “Add Chart” and select `transactions` as the data source. Select “Discrete Line” in the chart type dropdown menu. Then, you will need to add `timestamp` in the X axis and `quantity` in the Y axis. 

 of this guide to learn how to enable offline inventory management with Atlas Edge Server.

Curious for more? Learn how MongoDB is helping retailers to build modern consumer experiences. Check the additional resources below:

- MongoDB for Retail Innovation
- How to Enhance Inventory Management With Real-Time Data Strategies
- Radial Powers Retail Sales With 10x Higher Performance on MongoDB Atlas

  [1]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltfbb152b55b18d55f/66213da1ac4b003831c3fdee/1.png
  [2]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt5c9cf9349644772a/66213dc851b16f3fd6c4b39d/2.png
  [3]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt0346d4fd163ccf8f/66213de5c9de46299bd456c3/3.gif
  [4]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltcbb13b4ab1197d82/66213e0aa02ad73b34ee6aa5/4.png
  [5]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt70eebbb5ceb633ca/66213e29b054413a7e99b163/5.png
  [6]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltf4880b64b44d0e59/66213e45a02ad7144fee6aaa/6.png
  [7]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt7501da1b41ea0574/66213e6233301d04c488fb0f/7.png
  [8]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltd493259a179fefa3/66213eaf210d902e8c3a2157/8.png
  [9]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt902ff936d063d450/66213ecea02ad76743ee6ab9/9.png
  [10]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltd99614dbd04fd894/66213ee545f9898396cf295c/10.png
  [11]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt993d7e3579fb930e/66213efffb977c3ce2368432/11.png
  [12]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt9a5075ae0de6f94b/6621579d81c884e44937d10f/12-fixed.gif