We're building an API to help a school manage their supplies and classroom assignments. The core business question we need to answer is: "What order do I need to place for school supplies this year?" This seemingly simple question requires us to build a robust system that can:
Our database consists of several interconnected tables:
// Ordering students by name
router.get('/students', async (req, res) => {
const students = await Student.findAll({
order: [
['lastName', 'ASC'],
['firstName', 'ASC']
],
attributes: ['id', 'firstName', 'lastName', 'leftHanded']
});
res.json(students);
});
// Ordering classrooms alphabetically
router.get('/classrooms', async (req, res) => {
const classrooms = await Classroom.findAll({
order: [['name', 'ASC']],
attributes: ['id', 'name', 'studentLimit']
});
res.json(classrooms);
});
Think of this like organizing a filing cabinet - we want to make it easy to find any student or classroom quickly and consistently.
router.get('/students', async (req, res) => {
// Parse page and size with defaults
let page = parseInt(req.query.page) || 1;
let size = parseInt(req.query.size) || 10;
// Validate parameters
if (page < 0 || size < 0 || size > 200) {
return res.status(400).json({
errors: [{ message: 'Requires valid page and size params' }],
count: 0,
pageCount: 0
});
}
// Calculate offset
const offset = size * (page - 1);
const students = await Student.findAndCountAll({
limit: size,
offset: offset,
order: [['lastName', 'ASC'], ['firstName', 'ASC']]
});
// Calculate total pages
const pageCount = Math.ceil(students.count / size);
res.json({
rows: students.rows,
count: students.count,
page: page,
pageCount: pageCount
});
});
This is similar to how a textbook is organized - we break the content into manageable chunks (pages) while keeping track of the total content (page count).
router.get('/supplies/scissors/calculate', async (req, res) => {
// Find current scissors inventory
const scissorsCount = await Supply.findAll({
where: {
name: 'Safety Scissors',
handed: {
[Op.in]: ['left', 'right']
}
},
attributes: [
'handed',
[sequelize.fn('COUNT', sequelize.col('id')), 'count']
],
group: ['handed']
});
// Calculate needed supplies
const studentCounts = await Student.findAll({
attributes: [
'leftHanded',
[sequelize.fn('COUNT', sequelize.col('id')), 'count']
],
group: ['leftHanded']
});
// Calculate differences
const result = calculateNeededSupplies(scissorsCount, studentCounts);
res.json(result);
});
Always validate input and return clear error messages:
const validatePaginationParams = (page, size) => {
const errors = [];
if (page < 1) errors.push('Page must be greater than 0');
if (size < 1 || size > 200) errors.push('Size must be between 1 and 200');
return errors;
};
Use efficient querying techniques to minimize database load:
Important scenarios to test:
This pattern of development can be applied to many business scenarios:
Key areas to monitor and optimize: