From ef5cfd34e460c7d5b5c153ff3549cf99256c381e Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sun, 26 Jul 2026 22:41:09 +0100 Subject: [PATCH] Refactor inventory and filament schemas for improved consistency and readability - Enhanced the stock event schema by ensuring consistent formatting and removing unnecessary line breaks for better maintainability. - Updated the filament schema to improve code readability and maintain required fields while maintaining functionality. - Introduced a new `recalculate` method in the printer schema to manage printer state changes effectively. - Added logic to handle host disconnection in the socket host, ensuring proper state management and logging. --- .../schemas/inventory/stockevent.schema.js | 64 +++++++------------ .../schemas/management/filament.schema.js | 42 +++++------- .../schemas/production/printer.schema.js | 24 ++++++- src/socket/sockethost.js | 25 ++++++++ 4 files changed, 88 insertions(+), 67 deletions(-) diff --git a/src/database/schemas/inventory/stockevent.schema.js b/src/database/schemas/inventory/stockevent.schema.js index eaf6896..8809575 100644 --- a/src/database/schemas/inventory/stockevent.schema.js +++ b/src/database/schemas/inventory/stockevent.schema.js @@ -6,13 +6,13 @@ const { Schema } = mongoose; const parentStockModelNames = { filamentStock: 'filamentStock', partStock: 'partStock', - productStock: 'productStock' + productStock: 'productStock', }; const initialStockStates = { filamentStock: 'unconsumed', partStock: 'new', - productStock: 'posted' + productStock: 'posted', }; const getStartingAmount = (parentType, parentStock) => { @@ -23,12 +23,7 @@ const getStartingAmount = (parentType, parentStock) => { return parentStock.startingQuantity ?? 0; }; -const buildParentState = ( - parentType, - parentStock, - currentAmount, - startingAmount -) => { +const buildParentState = (parentType, parentStock, currentAmount, startingAmount) => { if (parentStock.state?.type === 'draft') { return undefined; } @@ -48,6 +43,8 @@ const buildParentState = ( const progress = currentAmount / startingAmount; + console.log('progress', progress); + if (currentAmount === startingAmount) { return { ...parentStock.state, type: fullState, progress: 1 }; } @@ -63,20 +60,18 @@ const getStockEventTotal = async (parentId, parentType) => { if (!parentId) return null; const objectId = - parentId instanceof mongoose.Types.ObjectId - ? parentId - : new mongoose.Types.ObjectId(parentId); + parentId instanceof mongoose.Types.ObjectId ? parentId : new mongoose.Types.ObjectId(parentId); const [result] = await mongoose .model('stockEvent') .aggregate([ { $match: { parent: objectId, parentType } }, - { $group: { _id: null, total: { $sum: '$value' }, count: { $sum: 1 } } } + { $group: { _id: null, total: { $sum: '$value' }, count: { $sum: 1 } } }, ]); return { total: result?.total ?? 0, - count: result?.count ?? 0 + count: result?.count ?? 0, }; }; @@ -113,8 +108,7 @@ const HISTORY_RATE_LIMIT_MS = 3000; const isWithinHistoryRateLimit = (lastEntry, timestamp = new Date()) => { if (!lastEntry?.timestamp) return false; - const elapsed = - new Date(timestamp).getTime() - new Date(lastEntry.timestamp).getTime(); + const elapsed = new Date(timestamp).getTime() - new Date(lastEntry.timestamp).getTime(); return elapsed < HISTORY_RATE_LIMIT_MS; }; @@ -122,9 +116,7 @@ const getLastParentHistoryValue = (parentType, history = []) => { const lastEntry = history.at(-1); if (!lastEntry) return undefined; - return parentType === 'filamentStock' - ? lastEntry.currentWeight - : lastEntry.currentQuantity; + return parentType === 'filamentStock' ? lastEntry.currentWeight : lastEntry.currentQuantity; }; const parentValuesEqual = (parentType, a, b) => { @@ -155,9 +147,7 @@ const appendParentHistoryIfChanged = ( const history = parentStock.history || []; const lastEntry = history.at(-1); const currentValue = - parentType === 'filamentStock' - ? updateData.currentWeight - : updateData.currentQuantity; + parentType === 'filamentStock' ? updateData.currentWeight : updateData.currentQuantity; const lastHistoryValue = getLastParentHistoryValue(parentType, history); if (parentValuesEqual(parentType, currentValue, lastHistoryValue)) { @@ -170,10 +160,7 @@ const appendParentHistoryIfChanged = ( return { ...updateData, - history: [ - ...history, - buildParentHistoryEntry(parentType, currentValue, timestamp) - ] + history: [...history, buildParentHistoryEntry(parentType, currentValue, timestamp)], }; }; @@ -187,7 +174,7 @@ const recalculateParentStock = async (parentType, parentId, user) => { const parentStock = await getObject({ model: parentModel, id: parentId, - cached: true + cached: true, }); if (!parentStock || parentStock.error) return; @@ -203,7 +190,7 @@ const recalculateParentStock = async (parentType, parentId, user) => { buildParentUpdateData(parentType, parentStock, events) ), user, - recalculate: false + recalculate: false, }); }; @@ -215,30 +202,30 @@ const stockEventSchema = new Schema( parent: { type: Schema.Types.ObjectId, refPath: 'parentType', - required: true + required: true, }, parentType: { type: String, required: true, - enum: ['filamentStock', 'partStock', 'productStock'] // Add other models as needed + enum: ['filamentStock', 'partStock', 'productStock'], // Add other models as needed }, owner: { type: Schema.Types.ObjectId, refPath: 'ownerType', - required: true + required: true, }, ownerType: { type: String, required: true, - enum: ['user', 'subJob', 'stockAudit', 'stockTransfer'] + enum: ['user', 'subJob', 'stockAudit', 'stockTransfer'], }, history: [ { value: { type: Number, required: true }, - timestamp: { type: Date, default: Date.now } - } + timestamp: { type: Date, default: Date.now }, + }, ], - timestamp: { type: Date, default: Date.now } + timestamp: { type: Date, default: Date.now }, }, { timestamps: true } ); @@ -252,18 +239,15 @@ stockEventSchema.statics.recalculate = async function (stockEvent, user) { const currentValue = stockEvent.value; const timestamp = stockEvent.timestamp || new Date(); - if ( - currentValue !== lastHistoryValue && - !isWithinHistoryRateLimit(lastEntry, timestamp) - ) { + if (currentValue !== lastHistoryValue && !isWithinHistoryRateLimit(lastEntry, timestamp)) { await editObject({ model: this, id: stockEvent._id, updateData: { - history: [...history, { value: currentValue, timestamp }] + history: [...history, { value: currentValue, timestamp }], }, user, - recalculate: false + recalculate: false, }); } diff --git a/src/database/schemas/management/filament.schema.js b/src/database/schemas/management/filament.schema.js index fca4707..ea53d0b 100644 --- a/src/database/schemas/management/filament.schema.js +++ b/src/database/schemas/management/filament.schema.js @@ -3,28 +3,21 @@ import { generateId } from '../../utils.js'; const { Schema } = mongoose; // Filament base - cost and tax; color and cost override at FilamentSKU -const filamentSchema = new mongoose.Schema( - { - _reference: { type: String, default: () => generateId()() }, - name: { required: true, type: String }, - vendor: { required: false, type: Schema.Types.ObjectId, ref: 'vendor' }, - barcode: { required: false, type: String }, - url: { required: false, type: String }, - image: { required: false, type: Buffer }, - material: { type: Schema.Types.ObjectId, ref: 'material', required: true }, - diameter: { required: true, type: Number }, - density: { required: true, type: Number }, - emptySpoolWeight: { required: true, type: Number }, - cost: { type: Number, required: false }, - costTaxRate: { - type: Schema.Types.ObjectId, - ref: 'taxRate', - required: false - }, - costWithTax: { type: Number, required: false } - }, - { timestamps: true } -); +const filamentSchema = new mongoose.Schema({ + _reference: { type: String, default: () => generateId()() }, + name: { required: true, type: String }, + vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: false }, + barcode: { required: false, type: String }, + url: { required: false, type: String }, + image: { required: false, type: Buffer }, + material: { type: Schema.Types.ObjectId, ref: 'material', required: true }, + diameter: { required: true, type: Number }, + density: { required: true, type: Number }, + emptySpoolWeight: { required: true, type: Number }, + cost: { type: Number, required: false }, + costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false }, + costWithTax: { type: Number, required: false }, +}, { timestamps: true }); filamentSchema.index({ name: 'text', barcode: 'text', url: 'text' }); @@ -36,10 +29,7 @@ filamentSchema.set('toJSON', { virtuals: true }); filamentSchema.statics.recalculate = async function (filament, user) { const filamentSkuModel = mongoose.model('filamentSku'); - const skus = await filamentSkuModel - .find({ filament: filament._id }) - .select('_id') - .lean(); + const skus = await filamentSkuModel.find({ filament: filament._id }).select('_id').lean(); for (const sku of skus) { await filamentSkuModel.recalculate(sku, user); } diff --git a/src/database/schemas/production/printer.schema.js b/src/database/schemas/production/printer.schema.js index 61fe220..750d003 100644 --- a/src/database/schemas/production/printer.schema.js +++ b/src/database/schemas/production/printer.schema.js @@ -1,7 +1,7 @@ import mongoose from 'mongoose'; import { generateId } from '../../utils.js'; const { Schema } = mongoose; -import { aggregateRollups, aggregateRollupsHistory } from '../../database.js'; +import { aggregateRollups, aggregateRollupsHistory, editObject } from '../../database.js'; // Define the moonraker connection schema const moonrakerSchema = new Schema( @@ -124,6 +124,28 @@ printerSchema.statics.history = async function (from, to) { return results; }; +printerSchema.statics.recalculate = async function (printer, user) { + if (printer.active === false && printer.state?.type !== 'inactive') { + await editObject({ + model: this, + id: printer._id, + updateData: { state: { type: 'inactive' } }, + user, + recalculate: false, + }); + return; + } + if (printer.active === true && printer.state?.type === 'inactive' && printer.online === false) { + await editObject({ + model: this, + id: printer._id, + updateData: { state: { type: 'offline' } }, + user, + recalculate: false, + }); + } +}; + // Add virtual id getter printerSchema.virtual('id').get(function () { return this._id; diff --git a/src/socket/sockethost.js b/src/socket/sockethost.js index a8b4475..eda38f0 100644 --- a/src/socket/sockethost.js +++ b/src/socket/sockethost.js @@ -94,6 +94,25 @@ export class SocketHost { ownerType: 'host' }); }; + + const setHostOffline = async () => { + logger.info('Host disconnected.'); + await editObject({ + model: hostModel, + id: this.host._id, + updateData: { + online: false, + state: { type: 'offline' }, + connectedAt: null + }, + owner: this.host, + ownerType: 'host' + }); + this.host = null; + this.id = null; + this.authenticated = false; + }; + logger.trace('handleAuthenticateEvent'); const id = data.id || undefined; const authCode = data.authCode || undefined; @@ -103,6 +122,9 @@ export class SocketHost { logger.info('Authenticating host with id + authCode...'); const verifyResult = await this.codeAuth.verifyCode(id, authCode); if (verifyResult.valid == true) { + if (this.host?._id) { + await setHostOffline(); + } await setHostOnline(verifyResult); await this.initializeHost(); } @@ -115,6 +137,9 @@ export class SocketHost { const verifyResult = await this.codeAuth.verifyOtp(otp); if (verifyResult.valid == true) { logger.info('Host authenticated and valid.'); + if (this.host?._id) { + await setHostOffline(); + } await setHostOnline(verifyResult); await this.initializeHost(); }