From a9999f95d09bba045850abb8b67b35d73a5fa018 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sat, 7 Mar 2026 13:38:19 +0000 Subject: [PATCH] Implemented product stocks. --- .../schemas/inventory/productstock.schema.js | 64 +++++++++++++++++++ src/database/schemas/models.js | 5 +- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/database/schemas/inventory/productstock.schema.js diff --git a/src/database/schemas/inventory/productstock.schema.js b/src/database/schemas/inventory/productstock.schema.js new file mode 100644 index 0000000..ce3d2e5 --- /dev/null +++ b/src/database/schemas/inventory/productstock.schema.js @@ -0,0 +1,64 @@ +import mongoose from 'mongoose'; +import { generateId } from '../../utils.js'; +const { Schema } = mongoose; +import { aggregateRollups, aggregateRollupsHistory } from '../../database.js'; + +const partStockUsageSchema = new Schema({ + partStock: { type: Schema.Types.ObjectId, ref: 'partStock', required: false }, + part: { type: Schema.Types.ObjectId, ref: 'part', required: true }, + quantity: { type: Number, required: true }, +}); + +// Define the main productStock schema - tracks assembled products consisting of part stocks +const productStockSchema = new Schema( + { + _reference: { type: String, default: () => generateId()() }, + state: { + type: { type: String, required: true }, + progress: { type: Number, required: false }, + }, + product: { type: mongoose.Schema.Types.ObjectId, ref: 'product', required: true }, + currentQuantity: { type: Number, required: true }, + partStocks: [partStockUsageSchema], + }, + { timestamps: true } +); + +const rollupConfigs = [ + { + name: 'totalCurrentQuantity', + filter: {}, + rollups: [{ name: 'totalCurrentQuantity', property: 'currentQuantity', operation: 'sum' }], + }, +]; + +productStockSchema.statics.stats = async function () { + const results = await aggregateRollups({ + model: this, + rollupConfigs: rollupConfigs, + }); + + return results; +}; + +productStockSchema.statics.history = async function (from, to) { + const results = await aggregateRollupsHistory({ + model: this, + startDate: from, + endDate: to, + rollupConfigs: rollupConfigs, + }); + + return results; +}; + +// Add virtual id getter +productStockSchema.virtual('id').get(function () { + return this._id; +}); + +// Configure JSON serialization to include virtuals +productStockSchema.set('toJSON', { virtuals: true }); + +// Create and export the model +export const productStockModel = mongoose.model('productStock', productStockSchema); diff --git a/src/database/schemas/models.js b/src/database/schemas/models.js index c647630..deae175 100644 --- a/src/database/schemas/models.js +++ b/src/database/schemas/models.js @@ -12,6 +12,7 @@ import { orderItemModel } from './inventory/orderitem.schema.js'; import { stockEventModel } from './inventory/stockevent.schema.js'; import { stockAuditModel } from './inventory/stockaudit.schema.js'; import { partStockModel } from './inventory/partstock.schema.js'; +import { productStockModel } from './inventory/productstock.schema.js'; import { auditLogModel } from './management/auditlog.schema.js'; import { userModel } from './management/user.schema.js'; import { appPasswordModel } from './management/apppassword.schema.js'; @@ -115,12 +116,12 @@ export const models = { label: 'Part Stock', }, PDS: { - model: null, + model: productStockModel, idField: '_id', type: 'productStock', referenceField: '_reference', label: 'Product Stock', - }, // No productStockModel found + }, ADL: { model: auditLogModel, idField: '_id',