Enhance inventory schemas with additional rollup configurations for stock types
All checks were successful
farmcontrol/farmcontrol-api/pipeline/head This commit looks good

This commit adds new rollup configurations to the `filamentstock`, `partstock`, and `productstock` schemas to track the counts of different stock states: 'unconsumed', 'used', and 'consumed'. Additionally, the `stockevent` schema is updated to include rollup statistics for various stock types, improving the overall inventory management capabilities. Tests are also updated to mock new aggregate functions, ensuring comprehensive coverage of the new functionalities.
This commit is contained in:
Tom Butcher 2026-08-24 22:54:09 +01:00
parent 61ec9deecb
commit c57641518e
5 changed files with 85 additions and 1 deletions

View File

@ -58,6 +58,21 @@ const rollupConfigs = [
filter: {}, filter: {},
rollups: [{ name: 'totalCurrentWeight', property: 'currentWeight.net', operation: 'sum' }], rollups: [{ name: 'totalCurrentWeight', property: 'currentWeight.net', operation: 'sum' }],
}, },
{
name: 'unconsumed',
filter: { 'state.type': 'unconsumed' },
rollups: [{ name: 'unconsumed', property: 'state.type', operation: 'count' }],
},
{
name: 'used',
filter: { 'state.type': 'used' },
rollups: [{ name: 'used', property: 'state.type', operation: 'count' }],
},
{
name: 'consumed',
filter: { 'state.type': 'consumed' },
rollups: [{ name: 'consumed', property: 'state.type', operation: 'count' }],
},
]; ];
filamentStockSchema.statics.stats = async function () { filamentStockSchema.statics.stats = async function () {

View File

@ -46,6 +46,21 @@ const rollupConfigs = [
filter: {}, filter: {},
rollups: [{ name: 'totalCurrentQuantity', property: 'currentQuantity', operation: 'sum' }], rollups: [{ name: 'totalCurrentQuantity', property: 'currentQuantity', operation: 'sum' }],
}, },
{
name: 'new',
filter: { 'state.type': 'new' },
rollups: [{ name: 'new', property: 'state.type', operation: 'count' }],
},
{
name: 'used',
filter: { 'state.type': 'used' },
rollups: [{ name: 'used', property: 'state.type', operation: 'count' }],
},
{
name: 'consumed',
filter: { 'state.type': 'consumed' },
rollups: [{ name: 'consumed', property: 'state.type', operation: 'count' }],
},
]; ];
partStockSchema.statics.stats = async function () { partStockSchema.statics.stats = async function () {

View File

@ -89,6 +89,16 @@ const rollupConfigs = [
filter: { 'state.type': 'new' }, filter: { 'state.type': 'new' },
rollups: [{ name: 'new', property: 'state.type', operation: 'count' }], rollups: [{ name: 'new', property: 'state.type', operation: 'count' }],
}, },
{
name: 'used',
filter: { 'state.type': 'used' },
rollups: [{ name: 'used', property: 'state.type', operation: 'count' }],
},
{
name: 'consumed',
filter: { 'state.type': 'consumed' },
rollups: [{ name: 'consumed', property: 'state.type', operation: 'count' }],
},
]; ];
productStockSchema.statics.stats = async function () { productStockSchema.statics.stats = async function () {

View File

@ -1,6 +1,6 @@
import mongoose from 'mongoose'; import mongoose from 'mongoose';
import { generateId } from '../../utils.js'; import { generateId } from '../../utils.js';
import { getObject, editObject } from '../../database.js'; import { getObject, editObject, aggregateRollups, aggregateRollupsHistory } from '../../database.js';
const { Schema } = mongoose; const { Schema } = mongoose;
const parentStockModelNames = { const parentStockModelNames = {
@ -239,6 +239,44 @@ const stockEventSchema = new Schema(
stockEventSchema.index({ parentType: 'text', ownerType: 'text', unit: 'text' }); stockEventSchema.index({ parentType: 'text', ownerType: 'text', unit: 'text' });
const rollupConfigs = [
{
name: 'partStock',
filter: { parentType: 'partStock' },
rollups: [{ name: 'partStock', property: 'parentType', operation: 'count' }],
},
{
name: 'filamentStock',
filter: { parentType: 'filamentStock' },
rollups: [{ name: 'filamentStock', property: 'parentType', operation: 'count' }],
},
{
name: 'productStock',
filter: { parentType: 'productStock' },
rollups: [{ name: 'productStock', property: 'parentType', operation: 'count' }],
},
];
stockEventSchema.statics.stats = async function () {
const results = await aggregateRollups({
model: this,
rollupConfigs: rollupConfigs,
});
return results;
};
stockEventSchema.statics.history = async function (from, to) {
const results = await aggregateRollupsHistory({
model: this,
startDate: from,
endDate: to,
rollupConfigs: rollupConfigs,
});
return results;
};
stockEventSchema.statics.recalculate = async function (stockEvent, user) { stockEventSchema.statics.recalculate = async function (stockEvent, user) {
const history = stockEvent.history || []; const history = stockEvent.history || [];
const lastEntry = history.at(-1); const lastEntry = history.at(-1);

View File

@ -13,12 +13,18 @@ jest.unstable_mockModule('../../../database/database.js', () => ({
getModelStats: jest.fn(), getModelStats: jest.fn(),
getModelHistory: jest.fn(), getModelHistory: jest.fn(),
getObjectNeighbors: jest.fn(), getObjectNeighbors: jest.fn(),
aggregateRollups: jest.fn(),
aggregateRollupsHistory: jest.fn(),
})); }));
jest.unstable_mockModule('../../../database/schemas/inventory/filamentstock.schema.js', () => ({ jest.unstable_mockModule('../../../database/schemas/inventory/filamentstock.schema.js', () => ({
filamentStockModel: { modelName: 'FilamentStock' }, filamentStockModel: { modelName: 'FilamentStock' },
})); }));
jest.unstable_mockModule('../../../database/schemas/inventory/stockevent.schema.js', () => ({
stockEventModel: { modelName: 'StockEvent' },
}));
jest.unstable_mockModule('log4js', () => ({ jest.unstable_mockModule('log4js', () => ({
default: { default: {
getLogger: () => ({ getLogger: () => ({