Added stock location and stock transfer models, updated inventory schemas to include stockLocation references, and modified stock event schema to support stockTransfer owner type.

This commit is contained in:
Tom Butcher 2026-03-21 23:14:14 +00:00
parent 8a9c272de4
commit ca3f28fc74
8 changed files with 136 additions and 14 deletions

View File

@ -20,6 +20,11 @@ const filamentStockSchema = new Schema(
gross: { type: Number, required: true },
},
filamentSku: { type: mongoose.Schema.Types.ObjectId, ref: 'filamentSku', required: true },
stockLocation: {
type: mongoose.Schema.Types.ObjectId,
ref: 'stockLocation',
required: false,
},
},
{ timestamps: true }
);

View File

@ -12,6 +12,11 @@ const partStockSchema = new Schema(
progress: { type: Number, required: false },
},
partSku: { type: mongoose.Schema.Types.ObjectId, ref: 'partSku', required: true },
stockLocation: {
type: mongoose.Schema.Types.ObjectId,
ref: 'stockLocation',
required: false,
},
currentQuantity: { type: Number, required: true },
sourceType: { type: String, required: true },
source: { type: Schema.Types.ObjectId, refPath: 'sourceType', required: true },

View File

@ -19,6 +19,11 @@ const productStockSchema = new Schema(
},
postedAt: { type: Date, required: false },
productSku: { type: mongoose.Schema.Types.ObjectId, ref: 'productSku', required: true },
stockLocation: {
type: mongoose.Schema.Types.ObjectId,
ref: 'stockLocation',
required: false,
},
currentQuantity: { type: Number, required: true },
partStocks: [partStockUsageSchema],
},

View File

@ -25,7 +25,7 @@ const stockEventSchema = new Schema(
ownerType: {
type: String,
required: true,
enum: ['user', 'subJob', 'stockAudit'],
enum: ['user', 'subJob', 'stockAudit', 'stockTransfer'],
},
timestamp: { type: Date, default: Date.now },
},

View File

@ -0,0 +1,29 @@
import mongoose from 'mongoose';
import { generateId } from '../../utils.js';
const { Schema } = mongoose;
const stockLocationSchema = new Schema(
{
_reference: { type: String, default: () => generateId()() },
name: { type: String, required: true },
notes: { type: String, required: false },
},
{ timestamps: true }
);
stockLocationSchema.statics.stats = async function () {
const total = await this.countDocuments({});
return { total: { count: total } };
};
stockLocationSchema.statics.history = async function () {
return [];
};
stockLocationSchema.virtual('id').get(function () {
return this._id;
});
stockLocationSchema.set('toJSON', { virtuals: true });
export const stockLocationModel = mongoose.model('stockLocation', stockLocationSchema);

View File

@ -0,0 +1,71 @@
import mongoose from 'mongoose';
import { generateId } from '../../utils.js';
const { Schema } = mongoose;
const stockTransferLineSchema = new Schema(
{
fromStockType: {
type: String,
required: true,
enum: ['filamentStock', 'partStock', 'productStock'],
},
fromStock: {
type: Schema.Types.ObjectId,
refPath: 'fromStockType',
required: true,
},
quantity: { type: Number, required: true },
toStockLocation: {
type: Schema.Types.ObjectId,
ref: 'stockLocation',
required: true,
},
toStockType: {
type: String,
required: false,
enum: ['filamentStock', 'partStock', 'productStock'],
},
toStock: {
type: Schema.Types.ObjectId,
refPath: 'toStockType',
required: false,
},
},
{ _id: true }
);
const stockTransferSchema = new Schema(
{
_reference: { type: String, default: () => generateId()() },
state: {
type: { type: String, required: true, default: 'draft' },
progress: { type: Number, required: false },
},
postedAt: { type: Date, required: false },
lines: { type: [stockTransferLineSchema], default: [] },
},
{ timestamps: true }
);
stockTransferSchema.statics.stats = async function () {
const [draft, posted] = await Promise.all([
this.countDocuments({ 'state.type': 'draft' }),
this.countDocuments({ 'state.type': 'posted' }),
]);
return {
draft: { count: draft },
posted: { count: posted },
};
};
stockTransferSchema.statics.history = async function () {
return [];
};
stockTransferSchema.virtual('id').get(function () {
return this._id;
});
stockTransferSchema.set('toJSON', { virtuals: true });
export const stockTransferModel = mongoose.model('stockTransfer', stockTransferSchema);

View File

@ -31,19 +31,10 @@ partSchema.virtual('id').get(function () {
partSchema.set('toJSON', { virtuals: true });
partSchema.statics.recalculate = async function (part, user) {
const orderItemModel = mongoose.model('orderItem');
const itemId = part._id;
const draftOrderItems = await orderItemModel
.find({
'state.type': 'draft',
itemType: 'part',
item: itemId,
})
.populate('order')
.lean();
for (const orderItem of draftOrderItems) {
await orderItemModel.recalculate(orderItem, user);
const partSkuModel = mongoose.model('partSku');
const skus = await partSkuModel.find({ part: part._id }).select('_id').lean();
for (const sku of skus) {
await partSkuModel.recalculate(sku, user);
}
};

View File

@ -17,6 +17,8 @@ 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 { stockLocationModel } from './inventory/stocklocation.schema.js';
import { stockTransferModel } from './inventory/stocktransfer.schema.js';
import { auditLogModel } from './management/auditlog.schema.js';
import { userModel } from './management/user.schema.js';
import { appPasswordModel } from './management/apppassword.schema.js';
@ -157,6 +159,20 @@ export const models = {
referenceField: '_reference',
label: 'Product Stock',
},
SLN: {
model: stockLocationModel,
idField: '_id',
type: 'stockLocation',
referenceField: '_reference',
label: 'Stock Location',
},
STT: {
model: stockTransferModel,
idField: '_id',
type: 'stockTransfer',
referenceField: '_reference',
label: 'Stock Transfer',
},
ADL: {
model: auditLogModel,
idField: '_id',