C++ Inventory Management Project
Track stock levels, flag low items, and value the whole warehouse.
What you will build
A stock-control system for a small shop: products come in, sales take them out, and the system warns before anything runs dry. The valuable skills are stock invariants (never below zero), low-stock reporting, and valuing inventory from price × quantity.
What you will learn
- Encapsulating stock rules inside a class
- Restock and sale transactions with validation
- Generating low-stock and valuation reports
- Persisting structured records
Feature checklist
- Add products: SKU, name, price, quantity
- Record sales (refuses overselling)
- Record restock deliveries
- Low-stock alert list (below threshold)
- Total inventory value report
- Search products by name or SKU
Starter code
#include <iostream>
#include <map>
#include <string>
struct Product { std::string name; double price; int qty; int reorderAt; };
class Inventory {
std::map<std::string, Product> stock_; // key: SKU
public:
void add(const std::string& sku, Product p) { stock_[sku] = std::move(p); }
bool sell(const std::string& sku, int n) {
auto it = stock_.find(sku);
if (it == stock_.end() || n > it->second.qty) return false;
it->second.qty -= n;
return true;
}
void restock(const std::string& sku, int n) {
auto it = stock_.find(sku);
if (it != stock_.end()) it->second.qty += n;
}
void report() const {
double value = 0;
for (auto& [sku, p] : stock_) {
value += p.price * p.qty;
if (p.qty <= p.reorderAt)
std::cout << "LOW STOCK: " << p.name << " (" << p.qty
<< " left)\n";
}
std::cout << "Total inventory value: $" << value << "\n";
}
};Full walkthrough
Step 1: Model Product and let Inventory own the map
struct Product { std::string sku, name; double price; int qty; } and class Inventory holding std::map<std::string, Product> keyed by SKU. SKU is the key because it is unique by definition and never changes, while product names get retyped and misspelled — key choice is identity choice, same lesson as the library's ISBN.
Step 2: add(): new product or restock-by-another-name
If the SKU is new, insert the product. If it already exists, treat add as a delivery: increase qty (and let the price be updated deliberately, not silently). Ambiguity here causes real-world stock chaos, so make the program SAY which of the two things happened.
Step 3: sell() refuses overselling — atomically
sell(sku, n): find the product, check n <= qty, and only then qty -= n. The check and the subtraction are one operation from the caller's perspective. Selling 10 from a stock of 6 must change NOTHING and explain itself ('Only 6 in stock') — a partial sale nobody asked for is worse than a refusal.
bool Inventory::sell(sku, int n) {
auto it = stock.find(sku);
if (it == stock.end() || n > it->second.qty) return false;
it->second.qty -= n;
return true;
}Step 4: restock() is sell() with the sign flipped
restock(sku, n) adds n to qty for an existing SKU. Notice the pattern across this catalogue: symmetric operations (issue/return, deposit/withdraw, sell/restock) share validation shape — find, validate, mutate. Writing the second one should feel like déjà vu, and that feeling is pattern recognition growing.
Step 5: Low-stock alerts from a threshold
A named constant LOW = 10 (or a per-product threshold): list every product with qty < LOW, sorted by qty ascending so the most urgent is first. Alerts are a VIEW over the same data — no separate 'alert list' to maintain or let rot.
Step 6: Report the total inventory value
Sum price × qty over the map: money sitting on shelves. Print it with counts of distinct SKUs and total units. This is the report a shop owner actually opens the program for, so it belongs on the main menu, not buried.
Step 7: Search and persist
Search by SKU (map find, exact) or by name substring (scan values, partial — both styles from earlier projects in one feature). Save the map to a file on every change, one product per line, and reload at startup; then test: oversell attempt leaves qty untouched, restock lifts a product off the low-stock list, restart preserves everything.
Common mistakes
- Decrementing stock before checking sufficiency, so a refused sale still ate inventory.
- Keying the map by product name, then discovering two suppliers' 'USB Cable' are different products with different prices.
- Maintaining a separate low-stock list by hand instead of deriving it from qty each time it is viewed.
Compile and run
g++ -std=c++17 -o inventory inventory.cppSample run
$ ./inventory
1) Add 2) Sell 3) Restock 4) Low stock 5) Value report 6) Search 0) Quit
> 2
SKU:
> USB-CAB
Quantity:
> 5
Sold 5 x USB Cable. Remaining: 35
1) Add 2) Sell 3) Restock 4) Low stock 5) Value report 6) Search 0) Quit
> 2
SKU:
> MSE-02
Quantity:
> 9
Refused: only 6 in stock.
> 4
LOW STOCK (below 10):
MSE-02 Wireless Mouse — 6 left
> 5
Products: 2 SKUs, 41 units
Total inventory value: 79500.00 (USB Cable 1500 x 35 + Mouse 4500 x 6)
> 0Try it in your browser
No browser demo is included for this project. Build the C++ version below — that is the real program.