From aa4d2c6873d1f9bb964b881f83934bf366271a7e Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sat, 13 Dec 2025 21:01:35 +0000 Subject: [PATCH] Schema modifications. --- .../schemas/inventory/filamentstock.schema.js | 30 +++++++++++ .../schemas/inventory/orderitem.schema.js | 48 +++++++++++++++++ .../schemas/inventory/partstock.schema.js | 33 +++++++++++- .../schemas/management/documentjob.schema.js | 3 +- .../schemas/management/filament.schema.js | 2 + .../schemas/management/host.schema.js | 33 ++++++------ src/database/schemas/production/job.schema.js | 51 +++++++++++++++++++ 7 files changed, 183 insertions(+), 17 deletions(-) diff --git a/src/database/schemas/inventory/filamentstock.schema.js b/src/database/schemas/inventory/filamentstock.schema.js index 182e1b3..468c8c4 100644 --- a/src/database/schemas/inventory/filamentstock.schema.js +++ b/src/database/schemas/inventory/filamentstock.schema.js @@ -1,6 +1,7 @@ import mongoose from 'mongoose'; import { generateId } from '../../utils.js'; const { Schema } = mongoose; +import { aggregateRollups, aggregateRollupsHistory } from '../../database.js'; // Define the main filamentStock schema const filamentStockSchema = new Schema( @@ -23,6 +24,35 @@ const filamentStockSchema = new Schema( { timestamps: true } ); +const rollupConfigs = [ + { + name: 'totalCurrentWeight', + filter: {}, + rollups: [{ name: 'totalCurrentWeight', property: 'currentWeight.net', operation: 'sum' }], + }, +]; + +filamentStockSchema.statics.stats = async function () { + const results = await aggregateRollups({ + model: this, + rollupConfigs: rollupConfigs, + }); + + return results; +}; + +filamentStockSchema.statics.history = async function (from, to) { + const results = await aggregateRollupsHistory({ + model: this, + startDate: from, + endDate: to, + rollupConfigs: rollupConfigs, + }); + + // Return time-series data array + return results; +}; + // Add virtual id getter filamentStockSchema.virtual('id').get(function () { return this._id; diff --git a/src/database/schemas/inventory/orderitem.schema.js b/src/database/schemas/inventory/orderitem.schema.js index 42a68f8..e50292f 100644 --- a/src/database/schemas/inventory/orderitem.schema.js +++ b/src/database/schemas/inventory/orderitem.schema.js @@ -1,4 +1,6 @@ import mongoose from 'mongoose'; +import { purchaseOrderModel } from './purchaseorder.schema.js'; +import { aggregateRollups, editObject } from '../../database.js'; import { generateId } from '../../utils.js'; const { Schema } = mongoose; @@ -20,6 +22,52 @@ const orderItemSchema = new Schema( { timestamps: true } ); +orderItemSchema.statics.recalculate = async function (orderItem, user) { + // Only purchase orders are supported for now + if (orderItem.orderType !== 'purchaseOrder') { + return; + } + + const orderId = orderItem.order?._id || orderItem.order; + if (!orderId) { + return; + } + + const rollupResults = await aggregateRollups({ + model: this, + baseFilter: { + order: new mongoose.Types.ObjectId(orderId), + orderType: orderItem.orderType, + }, + rollupConfigs: [ + { + name: 'orderTotals', + rollups: [ + { name: 'totalAmount', property: 'totalAmount', operation: 'sum' }, + { + name: 'totalAmountWithTax', + property: 'totalAmountWithTax', + operation: 'sum', + }, + ], + }, + ], + }); + + const totals = rollupResults.orderTotals || {}; + const totalAmount = totals.totalAmount.sum?.toFixed(2) || 0; + const totalAmountWithTax = totals.totalAmountWithTax.sum?.toFixed(2) || 0; + + await editObject({ + model: purchaseOrderModel, + id: orderId, + updateData: { + cost: { net: totalAmount, gross: totalAmountWithTax }, + }, + user, + }); +}; + // Add virtual id getter orderItemSchema.virtual('id').get(function () { return this._id; diff --git a/src/database/schemas/inventory/partstock.schema.js b/src/database/schemas/inventory/partstock.schema.js index 3b8ebc6..772ea61 100644 --- a/src/database/schemas/inventory/partstock.schema.js +++ b/src/database/schemas/inventory/partstock.schema.js @@ -1,6 +1,7 @@ import mongoose from 'mongoose'; import { generateId } from '../../utils.js'; const { Schema } = mongoose; +import { aggregateRollups, aggregateRollupsHistory } from '../../database.js'; // Define the main partStock schema const partStockSchema = new Schema( @@ -11,12 +12,42 @@ const partStockSchema = new Schema( progress: { type: Number, required: false }, }, part: { type: mongoose.Schema.Types.ObjectId, ref: 'part', required: true }, - startingQuantity: { type: Number, required: true }, currentQuantity: { type: Number, required: true }, + sourceType: { type: String, required: true }, + source: { type: Schema.Types.ObjectId, refPath: 'sourceType', required: true }, }, { timestamps: true } ); +const rollupConfigs = [ + { + name: 'totalCurrentQuantity', + filter: {}, + rollups: [{ name: 'totalCurrentQuantity', property: 'currentQuantity', operation: 'sum' }], + }, +]; + +partStockSchema.statics.stats = async function () { + const results = await aggregateRollups({ + model: this, + rollupConfigs: rollupConfigs, + }); + + return results; +}; + +partStockSchema.statics.history = async function (from, to) { + const results = await aggregateRollupsHistory({ + model: this, + startDate: from, + endDate: to, + rollupConfigs: rollupConfigs, + }); + + // Return time-series data array + return results; +}; + // Add virtual id getter partStockSchema.virtual('id').get(function () { return this._id; diff --git a/src/database/schemas/management/documentjob.schema.js b/src/database/schemas/management/documentjob.schema.js index 9d981f6..aba8135 100644 --- a/src/database/schemas/management/documentjob.schema.js +++ b/src/database/schemas/management/documentjob.schema.js @@ -18,7 +18,8 @@ const documentJobSchema = new Schema( }, state: { type: { type: String, required: true, default: 'queued' }, - percent: { type: Number, required: false }, + progress: { type: Number, required: false }, + message: { type: String, required: false }, }, documentTemplate: { type: Schema.Types.ObjectId, diff --git a/src/database/schemas/management/filament.schema.js b/src/database/schemas/management/filament.schema.js index 270dfd0..54589c2 100644 --- a/src/database/schemas/management/filament.schema.js +++ b/src/database/schemas/management/filament.schema.js @@ -12,6 +12,8 @@ const filamentSchema = new mongoose.Schema({ vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true }, type: { required: true, type: String }, cost: { required: true, type: Number }, + costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: true }, + costWithTax: { required: true, type: Number }, diameter: { required: true, type: Number }, density: { required: true, type: Number }, createdAt: { required: true, type: Date }, diff --git a/src/database/schemas/management/host.schema.js b/src/database/schemas/management/host.schema.js index fa7a684..4e1098f 100644 --- a/src/database/schemas/management/host.schema.js +++ b/src/database/schemas/management/host.schema.js @@ -41,22 +41,25 @@ const deviceInfoSchema = new mongoose.Schema( { _id: false } ); -const hostSchema = new mongoose.Schema({ - _reference: { type: String, default: () => generateId()() }, - name: { required: true, type: String }, - tags: [{ required: false, type: String }], - online: { required: true, type: Boolean, default: false }, - state: { - type: { type: String, required: true, default: 'offline' }, - message: { type: String, required: false }, - percent: { type: Number, required: false }, +const hostSchema = new mongoose.Schema( + { + _reference: { type: String, default: () => generateId()() }, + name: { required: true, type: String }, + tags: [{ required: false, type: String }], + online: { required: true, type: Boolean, default: false }, + state: { + type: { type: String, required: true, default: 'offline' }, + message: { type: String, required: false }, + percent: { type: Number, required: false }, + }, + active: { required: true, type: Boolean, default: true }, + connectedAt: { required: false, type: Date }, + authCode: { type: { required: false, type: String } }, + deviceInfo: { deviceInfoSchema }, + files: [{ type: mongoose.Schema.Types.ObjectId, ref: 'file' }], }, - active: { required: true, type: Boolean, default: true }, - connectedAt: { required: false, type: Date }, - authCode: { type: { required: false, type: String } }, - deviceInfo: { deviceInfoSchema }, - files: [{ type: mongoose.Schema.Types.ObjectId, ref: 'file' }], -}); + { timestamps: true } +); hostSchema.virtual('id').get(function () { return this._id; diff --git a/src/database/schemas/production/job.schema.js b/src/database/schemas/production/job.schema.js index 78f484a..2163e29 100644 --- a/src/database/schemas/production/job.schema.js +++ b/src/database/schemas/production/job.schema.js @@ -1,6 +1,7 @@ import mongoose from 'mongoose'; import { generateId } from '../../utils.js'; const { Schema } = mongoose; +import { aggregateRollups, aggregateRollupsHistory } from '../../database.js'; const jobSchema = new mongoose.Schema( { @@ -31,6 +32,56 @@ const jobSchema = new mongoose.Schema( { timestamps: true } ); +const rollupConfigs = [ + { + name: 'queued', + filter: { 'state.type': 'queued' }, + rollups: [{ name: 'queued', property: 'state.type', operation: 'count' }], + }, + { + name: 'printing', + filter: { 'state.type': 'printing' }, + rollups: [{ name: 'printing', property: 'state.type', operation: 'count' }], + }, + { + name: 'draft', + filter: { 'state.type': 'draft' }, + rollups: [{ name: 'draft', property: 'state.type', operation: 'count' }], + }, + { + name: 'complete', + filter: { 'state.type': 'complete' }, + rollups: [{ name: 'complete', property: 'state.type', operation: 'count' }], + }, + { + name: 'failed', + filter: { 'state.type': 'failed' }, + rollups: [{ name: 'failed', property: 'state.type', operation: 'count' }], + }, +]; + +jobSchema.statics.stats = async function () { + const results = await aggregateRollups({ + model: this, + rollupConfigs: rollupConfigs, + }); + + // Transform the results to match the expected format + return results; +}; + +jobSchema.statics.history = async function (from, to) { + const results = await aggregateRollupsHistory({ + model: this, + startDate: from, + endDate: to, + rollupConfigs: rollupConfigs, + }); + + // Return time-series data array + return results; +}; + jobSchema.virtual('id').get(function () { return this._id; });