Refactor inventory and filament schemas for improved consistency and readability
All checks were successful
farmcontrol/farmcontrol-ws/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-ws/pipeline/head This commit looks good
- 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.
This commit is contained in:
parent
f3a3d3914a
commit
ef5cfd34e4
@ -6,13 +6,13 @@ const { Schema } = mongoose;
|
|||||||
const parentStockModelNames = {
|
const parentStockModelNames = {
|
||||||
filamentStock: 'filamentStock',
|
filamentStock: 'filamentStock',
|
||||||
partStock: 'partStock',
|
partStock: 'partStock',
|
||||||
productStock: 'productStock'
|
productStock: 'productStock',
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialStockStates = {
|
const initialStockStates = {
|
||||||
filamentStock: 'unconsumed',
|
filamentStock: 'unconsumed',
|
||||||
partStock: 'new',
|
partStock: 'new',
|
||||||
productStock: 'posted'
|
productStock: 'posted',
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStartingAmount = (parentType, parentStock) => {
|
const getStartingAmount = (parentType, parentStock) => {
|
||||||
@ -23,12 +23,7 @@ const getStartingAmount = (parentType, parentStock) => {
|
|||||||
return parentStock.startingQuantity ?? 0;
|
return parentStock.startingQuantity ?? 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildParentState = (
|
const buildParentState = (parentType, parentStock, currentAmount, startingAmount) => {
|
||||||
parentType,
|
|
||||||
parentStock,
|
|
||||||
currentAmount,
|
|
||||||
startingAmount
|
|
||||||
) => {
|
|
||||||
if (parentStock.state?.type === 'draft') {
|
if (parentStock.state?.type === 'draft') {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -48,6 +43,8 @@ const buildParentState = (
|
|||||||
|
|
||||||
const progress = currentAmount / startingAmount;
|
const progress = currentAmount / startingAmount;
|
||||||
|
|
||||||
|
console.log('progress', progress);
|
||||||
|
|
||||||
if (currentAmount === startingAmount) {
|
if (currentAmount === startingAmount) {
|
||||||
return { ...parentStock.state, type: fullState, progress: 1 };
|
return { ...parentStock.state, type: fullState, progress: 1 };
|
||||||
}
|
}
|
||||||
@ -63,20 +60,18 @@ const getStockEventTotal = async (parentId, parentType) => {
|
|||||||
if (!parentId) return null;
|
if (!parentId) return null;
|
||||||
|
|
||||||
const objectId =
|
const objectId =
|
||||||
parentId instanceof mongoose.Types.ObjectId
|
parentId instanceof mongoose.Types.ObjectId ? parentId : new mongoose.Types.ObjectId(parentId);
|
||||||
? parentId
|
|
||||||
: new mongoose.Types.ObjectId(parentId);
|
|
||||||
|
|
||||||
const [result] = await mongoose
|
const [result] = await mongoose
|
||||||
.model('stockEvent')
|
.model('stockEvent')
|
||||||
.aggregate([
|
.aggregate([
|
||||||
{ $match: { parent: objectId, parentType } },
|
{ $match: { parent: objectId, parentType } },
|
||||||
{ $group: { _id: null, total: { $sum: '$value' }, count: { $sum: 1 } } }
|
{ $group: { _id: null, total: { $sum: '$value' }, count: { $sum: 1 } } },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
total: result?.total ?? 0,
|
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()) => {
|
const isWithinHistoryRateLimit = (lastEntry, timestamp = new Date()) => {
|
||||||
if (!lastEntry?.timestamp) return false;
|
if (!lastEntry?.timestamp) return false;
|
||||||
const elapsed =
|
const elapsed = new Date(timestamp).getTime() - new Date(lastEntry.timestamp).getTime();
|
||||||
new Date(timestamp).getTime() - new Date(lastEntry.timestamp).getTime();
|
|
||||||
return elapsed < HISTORY_RATE_LIMIT_MS;
|
return elapsed < HISTORY_RATE_LIMIT_MS;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,9 +116,7 @@ const getLastParentHistoryValue = (parentType, history = []) => {
|
|||||||
const lastEntry = history.at(-1);
|
const lastEntry = history.at(-1);
|
||||||
if (!lastEntry) return undefined;
|
if (!lastEntry) return undefined;
|
||||||
|
|
||||||
return parentType === 'filamentStock'
|
return parentType === 'filamentStock' ? lastEntry.currentWeight : lastEntry.currentQuantity;
|
||||||
? lastEntry.currentWeight
|
|
||||||
: lastEntry.currentQuantity;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const parentValuesEqual = (parentType, a, b) => {
|
const parentValuesEqual = (parentType, a, b) => {
|
||||||
@ -155,9 +147,7 @@ const appendParentHistoryIfChanged = (
|
|||||||
const history = parentStock.history || [];
|
const history = parentStock.history || [];
|
||||||
const lastEntry = history.at(-1);
|
const lastEntry = history.at(-1);
|
||||||
const currentValue =
|
const currentValue =
|
||||||
parentType === 'filamentStock'
|
parentType === 'filamentStock' ? updateData.currentWeight : updateData.currentQuantity;
|
||||||
? updateData.currentWeight
|
|
||||||
: updateData.currentQuantity;
|
|
||||||
const lastHistoryValue = getLastParentHistoryValue(parentType, history);
|
const lastHistoryValue = getLastParentHistoryValue(parentType, history);
|
||||||
|
|
||||||
if (parentValuesEqual(parentType, currentValue, lastHistoryValue)) {
|
if (parentValuesEqual(parentType, currentValue, lastHistoryValue)) {
|
||||||
@ -170,10 +160,7 @@ const appendParentHistoryIfChanged = (
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...updateData,
|
...updateData,
|
||||||
history: [
|
history: [...history, buildParentHistoryEntry(parentType, currentValue, timestamp)],
|
||||||
...history,
|
|
||||||
buildParentHistoryEntry(parentType, currentValue, timestamp)
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -187,7 +174,7 @@ const recalculateParentStock = async (parentType, parentId, user) => {
|
|||||||
const parentStock = await getObject({
|
const parentStock = await getObject({
|
||||||
model: parentModel,
|
model: parentModel,
|
||||||
id: parentId,
|
id: parentId,
|
||||||
cached: true
|
cached: true,
|
||||||
});
|
});
|
||||||
if (!parentStock || parentStock.error) return;
|
if (!parentStock || parentStock.error) return;
|
||||||
|
|
||||||
@ -203,7 +190,7 @@ const recalculateParentStock = async (parentType, parentId, user) => {
|
|||||||
buildParentUpdateData(parentType, parentStock, events)
|
buildParentUpdateData(parentType, parentStock, events)
|
||||||
),
|
),
|
||||||
user,
|
user,
|
||||||
recalculate: false
|
recalculate: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -215,30 +202,30 @@ const stockEventSchema = new Schema(
|
|||||||
parent: {
|
parent: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
refPath: 'parentType',
|
refPath: 'parentType',
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
parentType: {
|
parentType: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
enum: ['filamentStock', 'partStock', 'productStock'] // Add other models as needed
|
enum: ['filamentStock', 'partStock', 'productStock'], // Add other models as needed
|
||||||
},
|
},
|
||||||
owner: {
|
owner: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
refPath: 'ownerType',
|
refPath: 'ownerType',
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
ownerType: {
|
ownerType: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
enum: ['user', 'subJob', 'stockAudit', 'stockTransfer']
|
enum: ['user', 'subJob', 'stockAudit', 'stockTransfer'],
|
||||||
},
|
},
|
||||||
history: [
|
history: [
|
||||||
{
|
{
|
||||||
value: { type: Number, required: true },
|
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 }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
@ -252,18 +239,15 @@ stockEventSchema.statics.recalculate = async function (stockEvent, user) {
|
|||||||
const currentValue = stockEvent.value;
|
const currentValue = stockEvent.value;
|
||||||
const timestamp = stockEvent.timestamp || new Date();
|
const timestamp = stockEvent.timestamp || new Date();
|
||||||
|
|
||||||
if (
|
if (currentValue !== lastHistoryValue && !isWithinHistoryRateLimit(lastEntry, timestamp)) {
|
||||||
currentValue !== lastHistoryValue &&
|
|
||||||
!isWithinHistoryRateLimit(lastEntry, timestamp)
|
|
||||||
) {
|
|
||||||
await editObject({
|
await editObject({
|
||||||
model: this,
|
model: this,
|
||||||
id: stockEvent._id,
|
id: stockEvent._id,
|
||||||
updateData: {
|
updateData: {
|
||||||
history: [...history, { value: currentValue, timestamp }]
|
history: [...history, { value: currentValue, timestamp }],
|
||||||
},
|
},
|
||||||
user,
|
user,
|
||||||
recalculate: false
|
recalculate: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,28 +3,21 @@ import { generateId } from '../../utils.js';
|
|||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
// Filament base - cost and tax; color and cost override at FilamentSKU
|
// Filament base - cost and tax; color and cost override at FilamentSKU
|
||||||
const filamentSchema = new mongoose.Schema(
|
const filamentSchema = new mongoose.Schema({
|
||||||
{
|
_reference: { type: String, default: () => generateId()() },
|
||||||
_reference: { type: String, default: () => generateId()() },
|
name: { required: true, type: String },
|
||||||
name: { required: true, type: String },
|
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: false },
|
||||||
vendor: { required: false, type: Schema.Types.ObjectId, ref: 'vendor' },
|
barcode: { required: false, type: String },
|
||||||
barcode: { required: false, type: String },
|
url: { required: false, type: String },
|
||||||
url: { required: false, type: String },
|
image: { required: false, type: Buffer },
|
||||||
image: { required: false, type: Buffer },
|
material: { type: Schema.Types.ObjectId, ref: 'material', required: true },
|
||||||
material: { type: Schema.Types.ObjectId, ref: 'material', required: true },
|
diameter: { required: true, type: Number },
|
||||||
diameter: { required: true, type: Number },
|
density: { required: true, type: Number },
|
||||||
density: { required: true, type: Number },
|
emptySpoolWeight: { required: true, type: Number },
|
||||||
emptySpoolWeight: { required: true, type: Number },
|
cost: { type: Number, required: false },
|
||||||
cost: { type: Number, required: false },
|
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
costTaxRate: {
|
costWithTax: { type: Number, required: false },
|
||||||
type: Schema.Types.ObjectId,
|
}, { timestamps: true });
|
||||||
ref: 'taxRate',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
costWithTax: { type: Number, required: false }
|
|
||||||
},
|
|
||||||
{ timestamps: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
filamentSchema.index({ name: 'text', barcode: 'text', url: 'text' });
|
filamentSchema.index({ name: 'text', barcode: 'text', url: 'text' });
|
||||||
|
|
||||||
@ -36,10 +29,7 @@ filamentSchema.set('toJSON', { virtuals: true });
|
|||||||
|
|
||||||
filamentSchema.statics.recalculate = async function (filament, user) {
|
filamentSchema.statics.recalculate = async function (filament, user) {
|
||||||
const filamentSkuModel = mongoose.model('filamentSku');
|
const filamentSkuModel = mongoose.model('filamentSku');
|
||||||
const skus = await filamentSkuModel
|
const skus = await filamentSkuModel.find({ filament: filament._id }).select('_id').lean();
|
||||||
.find({ filament: filament._id })
|
|
||||||
.select('_id')
|
|
||||||
.lean();
|
|
||||||
for (const sku of skus) {
|
for (const sku of skus) {
|
||||||
await filamentSkuModel.recalculate(sku, user);
|
await filamentSkuModel.recalculate(sku, user);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { generateId } from '../../utils.js';
|
import { generateId } from '../../utils.js';
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
import { aggregateRollups, aggregateRollupsHistory } from '../../database.js';
|
import { aggregateRollups, aggregateRollupsHistory, editObject } from '../../database.js';
|
||||||
|
|
||||||
// Define the moonraker connection schema
|
// Define the moonraker connection schema
|
||||||
const moonrakerSchema = new Schema(
|
const moonrakerSchema = new Schema(
|
||||||
@ -124,6 +124,28 @@ printerSchema.statics.history = async function (from, to) {
|
|||||||
return results;
|
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
|
// Add virtual id getter
|
||||||
printerSchema.virtual('id').get(function () {
|
printerSchema.virtual('id').get(function () {
|
||||||
return this._id;
|
return this._id;
|
||||||
|
|||||||
@ -94,6 +94,25 @@ export class SocketHost {
|
|||||||
ownerType: 'host'
|
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');
|
logger.trace('handleAuthenticateEvent');
|
||||||
const id = data.id || undefined;
|
const id = data.id || undefined;
|
||||||
const authCode = data.authCode || undefined;
|
const authCode = data.authCode || undefined;
|
||||||
@ -103,6 +122,9 @@ export class SocketHost {
|
|||||||
logger.info('Authenticating host with id + authCode...');
|
logger.info('Authenticating host with id + authCode...');
|
||||||
const verifyResult = await this.codeAuth.verifyCode(id, authCode);
|
const verifyResult = await this.codeAuth.verifyCode(id, authCode);
|
||||||
if (verifyResult.valid == true) {
|
if (verifyResult.valid == true) {
|
||||||
|
if (this.host?._id) {
|
||||||
|
await setHostOffline();
|
||||||
|
}
|
||||||
await setHostOnline(verifyResult);
|
await setHostOnline(verifyResult);
|
||||||
await this.initializeHost();
|
await this.initializeHost();
|
||||||
}
|
}
|
||||||
@ -115,6 +137,9 @@ export class SocketHost {
|
|||||||
const verifyResult = await this.codeAuth.verifyOtp(otp);
|
const verifyResult = await this.codeAuth.verifyOtp(otp);
|
||||||
if (verifyResult.valid == true) {
|
if (verifyResult.valid == true) {
|
||||||
logger.info('Host authenticated and valid.');
|
logger.info('Host authenticated and valid.');
|
||||||
|
if (this.host?._id) {
|
||||||
|
await setHostOffline();
|
||||||
|
}
|
||||||
await setHostOnline(verifyResult);
|
await setHostOnline(verifyResult);
|
||||||
await this.initializeHost();
|
await this.initializeHost();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user