Set default state as 'draft' and introduced 'postedAt' field. Implemented postProductStock route handler to transition product stock from draft to posted state, including state validation checks. Updated related service functions for consistency.
All checks were successful
farmcontrol/farmcontrol-api/pipeline/head This commit looks good

This commit is contained in:
Tom Butcher 2026-03-07 20:37:41 +00:00
parent 1b2d505a30
commit 866c29f33f
3 changed files with 88 additions and 2 deletions

View File

@ -14,9 +14,10 @@ const productStockSchema = new Schema(
{
_reference: { type: String, default: () => generateId()() },
state: {
type: { type: String, required: true },
type: { type: String, required: true, default: 'draft' },
progress: { type: Number, required: false },
},
postedAt: { type: Date, required: false },
product: { type: mongoose.Schema.Types.ObjectId, ref: 'product', required: true },
currentQuantity: { type: Number, required: true },
partStocks: [partStockUsageSchema],
@ -30,6 +31,16 @@ const rollupConfigs = [
filter: {},
rollups: [{ name: 'totalCurrentQuantity', property: 'currentQuantity', operation: 'sum' }],
},
{
name: 'draft',
filter: { 'state.type': 'draft' },
rollups: [{ name: 'draft', property: 'state.type', operation: 'count' }],
},
{
name: 'posted',
filter: { 'state.type': 'posted' },
rollups: [{ name: 'posted', property: 'state.type', operation: 'count' }],
},
];
productStockSchema.statics.stats = async function () {

View File

@ -10,6 +10,7 @@ import {
editMultipleProductStocksRouteHandler,
newProductStockRouteHandler,
deleteProductStockRouteHandler,
postProductStockRouteHandler,
listProductStocksByPropertiesRouteHandler,
getProductStockStatsRouteHandler,
getProductStockHistoryRouteHandler,
@ -61,4 +62,8 @@ router.delete('/:id', isAuthenticated, async (req, res) => {
deleteProductStockRouteHandler(req, res);
});
router.post('/:id/post', isAuthenticated, async (req, res) => {
postProductStockRouteHandler(req, res);
});
export default router;

View File

@ -12,6 +12,7 @@ import {
listObjectsByProperties,
getModelStats,
getModelHistory,
checkStates,
} from '../../database/database.js';
import { productModel } from '../../database/schemas/management/product.schema.js';
const logger = log4js.getLogger('Product Stocks');
@ -95,6 +96,20 @@ export const editProductStockRouteHandler = async (req, res) => {
logger.trace(`Product Stock with ID: ${id}`);
const checkStatesResult = await checkStates({ model: productStockModel, id, states: ['draft'] });
if (checkStatesResult.error) {
logger.error('Error checking product stock states:', checkStatesResult.error);
res.status(checkStatesResult.code).send(checkStatesResult);
return;
}
if (checkStatesResult === false) {
logger.error('Product stock is not in draft state.');
res.status(400).send({ error: 'Product stock is not in draft state.', code: 400 });
return;
}
const updateData = {
partStocks: req.body?.partStocks?.map((partStock) => ({
quantity: partStock.quantity,
@ -156,7 +171,7 @@ export const newProductStockRouteHandler = async (req, res) => {
updatedAt: new Date(),
currentQuantity: req.body.currentQuantity,
product: req.body.product,
state: req.body.state,
state: req.body.state ?? { type: 'draft' },
partStocks: product.parts.map((part) => ({
part: part.part,
quantity: part.quantity,
@ -183,6 +198,20 @@ export const deleteProductStockRouteHandler = async (req, res) => {
logger.trace(`Product Stock with ID: ${id}`);
const checkStatesResult = await checkStates({ model: productStockModel, id, states: ['draft'] });
if (checkStatesResult.error) {
logger.error('Error checking product stock states:', checkStatesResult.error);
res.status(checkStatesResult.code).send(checkStatesResult);
return;
}
if (checkStatesResult === false) {
logger.error('Product stock is not in draft state.');
res.status(400).send({ error: 'Product stock is not in draft state.', code: 400 });
return;
}
const result = await deleteObject({
model: productStockModel,
id,
@ -219,3 +248,44 @@ export const getProductStockHistoryRouteHandler = async (req, res) => {
logger.trace('Product stock history:', result);
res.send(result);
};
export const postProductStockRouteHandler = async (req, res) => {
const id = new mongoose.Types.ObjectId(req.params.id);
logger.trace(`Product Stock with ID: ${id}`);
const checkStatesResult = await checkStates({ model: productStockModel, id, states: ['draft'] });
if (checkStatesResult.error) {
logger.error('Error checking product stock states:', checkStatesResult.error);
res.status(checkStatesResult.code).send(checkStatesResult);
return;
}
if (checkStatesResult === false) {
logger.error('Product stock is not in draft state.');
res.status(400).send({ error: 'Product stock is not in draft state.', code: 400 });
return;
}
const updateData = {
updatedAt: new Date(),
state: { type: 'posted' },
postedAt: new Date(),
};
const result = await editObject({
model: productStockModel,
id,
updateData,
user: req.user,
});
if (result.error) {
logger.error('Error posting product stock:', result.error);
res.status(result.code).send(result);
return;
}
logger.debug(`Posted product stock with ID: ${id}`);
res.send(result);
};