Imagine you're creating a digital system for a warehouse manager. Just as a warehouse manager needs to track inventory and update item details, our API needs to provide endpoints that allow viewing and modifying warehouse items. We'll be building two main features: viewing all new items and updating existing items.
Before we start coding, let's set up our project environment, much like preparing a workspace in a real warehouse:
// First, ensure our environment is ready
cp .env.example .env
// Run our database setup
npx sequelize-cli db:migrate
npx sequelize-cli db:seed:all
Let's build our API piece by piece, starting with the foundation. Here's our complete implementation that will satisfy all test requirements:
// app.js
const express = require('express');
const { WarehouseItem } = require('./db/models');
const app = express();
// This middleware is like having a package inspector who knows how to
// handle incoming JSON packages
app.use(express.json());
// GET /items - Returns all new (unused) items
// Think of this as getting a list of all fresh inventory
app.get('/items', async (req, res) => {
try {
const items = await WarehouseItem.findAll({
// We only want unused items, like filtering for new stock
where: {
isUsed: false
}
});
// Send back our list of items
res.json(items);
} catch (error) {
// If something goes wrong, handle it gracefully
console.error('Error fetching items:', error);
res.status(500).json({ message: 'Error retrieving warehouse items' });
}
});
// PUT /items/:id - Updates an existing item
// Think of this as updating an item's details in inventory
app.put('/items/:id', async (req, res) => {
try {
// First, find the item we want to update
const item = await WarehouseItem.findByPk(req.params.id);
// If we can't find the item, let the user know
if (!item) {
return res.status(404).json({
message: "Warehouse Item not found"
});
}
// Update the item with new information
await item.update(req.body);
// Send back the updated item
res.json(item);
} catch (error) {
console.error('Error updating item:', error);
res.status(500).json({ message: 'Error updating warehouse item' });
}
});
module.exports = app;
This endpoint works like a warehouse clerk who only shows you the new items in stock. Let's break down its key components:
// The where clause filters for unused items
where: {
isUsed: false
}
// This is equivalent to asking:
// "Show me all items where isUsed is false"
The response will look like this when successful:
[
{
"id": 1,
"name": "Paint",
"price": 12.12,
"quantity": 12,
"isUsed": false
},
{
"id": 3,
"name": "Webcam",
"price": 50.5,
"quantity": 5,
"isUsed": false
}
]
This endpoint is like a warehouse worker updating an item's details in the inventory system. Here's how it works:
// First, we look for the item
const item = await WarehouseItem.findByPk(req.params.id);
// If we can't find it, we return a 404 error
if (!item) {
return res.status(404).json({
message: "Warehouse Item not found"
});
}
// If we find it, we update it with the new information
await item.update(req.body);
Let's verify our endpoints work correctly:
// Run all tests
npm test
// Or test specific endpoints
curl http://localhost:3000/items // Should return all unused items
curl -X PUT http://localhost:3000/items/2 // Should update item with ID 2
Our implementation includes robust error handling, much like how a warehouse needs procedures for when things go wrong:
When trying to update a non-existent item, we return a clear error message:
{
"message": "Warehouse Item not found"
}
We catch and handle unexpected errors gracefully, preventing our application from crashing.
For additional functionality, we can implement these bonus endpoints:
// GET /items/:name - Find item by name
app.get('/items/:name', async (req, res) => {
try {
const item = await WarehouseItem.findOne({
where: {
name: req.params.name
}
});
if (!item) {
return res.status(404).json({
message: "Warehouse Item not found"
});
}
res.json(item);
} catch (error) {
res.status(500).json({ message: 'Error retrieving warehouse item' });
}
});
// DELETE /items/:id - Remove an item
app.delete('/items/:id', async (req, res) => {
try {
const item = await WarehouseItem.findByPk(req.params.id);
if (!item) {
return res.status(404).json({
message: "Warehouse Item not found"
});
}
await item.destroy();
res.json({ message: "Successfully deleted" });
} catch (error) {
res.status(500).json({ message: 'Error deleting warehouse item' });
}
});
These endpoints mirror real warehouse operations in several ways:
Inventory Management: The GET endpoint helps managers see available new stock, just like checking warehouse shelves for new items.
Item Updates: The PUT endpoint allows updating item details, similar to how warehouse staff might update price tags or quantity counts.
Error Handling: Just as a warehouse needs procedures for missing items, our API has clear protocols for handling errors.
Consider these additional features to make the system more robust:
Implement inventory tracking history to log all changes to items.
Add validation for price and quantity updates to prevent invalid values.
Create endpoints for batch operations to handle multiple items at once.
Add filtering and sorting options to the GET endpoint for better item discovery.