Added missing SKUs.
This commit is contained in:
parent
bea9e45cd4
commit
7a500ffa58
@ -19,7 +19,7 @@ const filamentStockSchema = new Schema(
|
|||||||
net: { type: Number, required: true },
|
net: { type: Number, required: true },
|
||||||
gross: { type: Number, required: true },
|
gross: { type: Number, required: true },
|
||||||
},
|
},
|
||||||
filament: { type: mongoose.Schema.Types.ObjectId, ref: 'filament', required: true },
|
filamentSku: { type: mongoose.Schema.Types.ObjectId, ref: 'filamentSku', required: true },
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,6 +2,12 @@ import mongoose from 'mongoose';
|
|||||||
import { purchaseOrderModel } from './purchaseorder.schema.js';
|
import { purchaseOrderModel } from './purchaseorder.schema.js';
|
||||||
import { salesOrderModel } from '../sales/salesorder.schema.js';
|
import { salesOrderModel } from '../sales/salesorder.schema.js';
|
||||||
import { taxRateModel } from '../management/taxrate.schema.js';
|
import { taxRateModel } from '../management/taxrate.schema.js';
|
||||||
|
import { filamentModel } from '../management/filament.schema.js';
|
||||||
|
import { filamentSkuModel } from '../management/filamentsku.schema.js';
|
||||||
|
import { partModel } from '../management/part.schema.js';
|
||||||
|
import { partSkuModel } from '../management/partsku.schema.js';
|
||||||
|
import { productModel } from '../management/product.schema.js';
|
||||||
|
import { productSkuModel } from '../management/productsku.schema.js';
|
||||||
import {
|
import {
|
||||||
aggregateRollups,
|
aggregateRollups,
|
||||||
aggregateRollupsHistory,
|
aggregateRollupsHistory,
|
||||||
@ -11,6 +17,18 @@ import {
|
|||||||
import { generateId } from '../../utils.js';
|
import { generateId } from '../../utils.js';
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
|
const skuModelsByItemType = {
|
||||||
|
filament: filamentSkuModel,
|
||||||
|
part: partSkuModel,
|
||||||
|
product: productSkuModel,
|
||||||
|
};
|
||||||
|
|
||||||
|
const parentModelsByItemType = {
|
||||||
|
filament: filamentModel,
|
||||||
|
part: partModel,
|
||||||
|
product: productModel,
|
||||||
|
};
|
||||||
|
|
||||||
const orderItemSchema = new Schema(
|
const orderItemSchema = new Schema(
|
||||||
{
|
{
|
||||||
_reference: { type: String, default: () => generateId()() },
|
_reference: { type: String, default: () => generateId()() },
|
||||||
@ -21,7 +39,16 @@ const orderItemSchema = new Schema(
|
|||||||
},
|
},
|
||||||
order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
|
order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
|
||||||
itemType: { type: String, required: true },
|
itemType: { type: String, required: true },
|
||||||
item: { type: Schema.Types.ObjectId, refPath: 'itemType', required: true },
|
item: { type: Schema.Types.ObjectId, refPath: 'itemType', required: false },
|
||||||
|
sku: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: function () {
|
||||||
|
return ['filament', 'part', 'product'].includes(this.itemType)
|
||||||
|
? this.itemType + 'Sku'
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
syncAmount: { type: String, required: false, default: null },
|
syncAmount: { type: String, required: false, default: null },
|
||||||
itemAmount: { type: Number, required: true },
|
itemAmount: { type: Number, required: true },
|
||||||
quantity: { type: Number, required: true },
|
quantity: { type: Number, required: true },
|
||||||
@ -88,9 +115,55 @@ orderItemSchema.statics.recalculate = async function (orderItem, user) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var taxRate = orderItem.taxRate;
|
// If SKU present and syncAmount is set, check if override is on for the price mode and use that price instead
|
||||||
|
let effectiveItemAmount = orderItem.itemAmount;
|
||||||
|
const syncAmount = orderItem.syncAmount;
|
||||||
|
const skuId = orderItem.sku?._id || orderItem.sku;
|
||||||
|
const itemType = orderItem.itemType;
|
||||||
|
if (syncAmount && skuId && itemType && ['filament', 'part', 'product'].includes(itemType)) {
|
||||||
|
const skuModel = skuModelsByItemType[itemType];
|
||||||
|
const parentModel = parentModelsByItemType[itemType];
|
||||||
|
if (skuModel && parentModel) {
|
||||||
|
const sku = await getObject({
|
||||||
|
model: skuModel,
|
||||||
|
id: skuId,
|
||||||
|
cached: true,
|
||||||
|
});
|
||||||
|
if (sku) {
|
||||||
|
const parentId = sku.part?._id || sku.part || sku.product?._id || sku.product || sku.filament?._id || sku.filament;
|
||||||
|
if (syncAmount === 'itemCost') {
|
||||||
|
if (sku.overrideCost && sku.cost != null) {
|
||||||
|
effectiveItemAmount = sku.cost;
|
||||||
|
} else if (parentId) {
|
||||||
|
const parent = await getObject({
|
||||||
|
model: parentModel,
|
||||||
|
id: parentId,
|
||||||
|
cached: true,
|
||||||
|
});
|
||||||
|
if (parent && parent.cost != null) {
|
||||||
|
effectiveItemAmount = parent.cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (syncAmount === 'itemPrice' && itemType !== 'filament') {
|
||||||
|
if (sku.overridePrice && sku.price != null) {
|
||||||
|
effectiveItemAmount = sku.price;
|
||||||
|
} else if (parentId) {
|
||||||
|
const parent = await getObject({
|
||||||
|
model: parentModel,
|
||||||
|
id: parentId,
|
||||||
|
cached: true,
|
||||||
|
});
|
||||||
|
if (parent && parent.price != null) {
|
||||||
|
effectiveItemAmount = parent.price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (orderItem.taxRate?._id && Object.keys(orderItem.taxRate).length == 1) {
|
let taxRate = orderItem.taxRate;
|
||||||
|
if (orderItem.taxRate?._id && Object.keys(orderItem.taxRate).length === 1) {
|
||||||
taxRate = await getObject({
|
taxRate = await getObject({
|
||||||
model: taxRateModel,
|
model: taxRateModel,
|
||||||
id: orderItem.taxRate._id,
|
id: orderItem.taxRate._id,
|
||||||
@ -98,18 +171,25 @@ orderItemSchema.statics.recalculate = async function (orderItem, user) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderTotalAmount = orderItem.itemAmount * orderItem.quantity;
|
const orderTotalAmount = effectiveItemAmount * orderItem.quantity;
|
||||||
const orderTotalAmountWithTax = orderTotalAmount * (1 + (taxRate?.rate || 0) / 100);
|
const orderTotalAmountWithTax = orderTotalAmount * (1 + (taxRate?.rate || 0) / 100);
|
||||||
await editObject({
|
|
||||||
model: orderItemModel,
|
const orderItemUpdateData = {
|
||||||
id: orderItem._id,
|
totalAmount: orderTotalAmount,
|
||||||
updateData: {
|
totalAmountWithTax: orderTotalAmountWithTax,
|
||||||
invoicedAmountRemaining: orderTotalAmount - orderItem.invoicedAmount,
|
invoicedAmountRemaining: orderTotalAmount - orderItem.invoicedAmount,
|
||||||
invoicedAmountWithTaxRemaining: orderTotalAmountWithTax - orderItem.invoicedAmountWithTax,
|
invoicedAmountWithTaxRemaining: orderTotalAmountWithTax - orderItem.invoicedAmountWithTax,
|
||||||
invoicedQuantityRemaining: orderItem.quantity - orderItem.invoicedQuantity,
|
invoicedQuantityRemaining: orderItem.quantity - orderItem.invoicedQuantity,
|
||||||
totalAmount: orderTotalAmount,
|
};
|
||||||
totalAmountWithTax: orderTotalAmountWithTax,
|
if (effectiveItemAmount !== orderItem.itemAmount) {
|
||||||
},
|
orderItemUpdateData.itemAmount = effectiveItemAmount;
|
||||||
|
orderItem.itemAmount = effectiveItemAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
await editObject({
|
||||||
|
model: this,
|
||||||
|
id: orderItem._id,
|
||||||
|
updateData: orderItemUpdateData,
|
||||||
user,
|
user,
|
||||||
recalculate: false,
|
recalculate: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,24 +2,21 @@ import mongoose from 'mongoose';
|
|||||||
import { generateId } from '../../utils.js';
|
import { generateId } from '../../utils.js';
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
|
// 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 },
|
||||||
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 },
|
||||||
color: { required: true, type: String },
|
|
||||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
|
||||||
type: { required: true, type: String },
|
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 },
|
diameter: { required: true, type: Number },
|
||||||
density: { required: true, type: Number },
|
density: { required: true, type: Number },
|
||||||
createdAt: { required: true, type: Date },
|
|
||||||
updatedAt: { required: true, type: Date },
|
|
||||||
emptySpoolWeight: { 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.virtual('id').get(function () {
|
filamentSchema.virtual('id').get(function () {
|
||||||
return this._id;
|
return this._id;
|
||||||
@ -27,4 +24,21 @@ filamentSchema.virtual('id').get(function () {
|
|||||||
|
|
||||||
filamentSchema.set('toJSON', { virtuals: true });
|
filamentSchema.set('toJSON', { virtuals: true });
|
||||||
|
|
||||||
|
filamentSchema.statics.recalculate = async function (filament, user) {
|
||||||
|
const orderItemModel = mongoose.model('orderItem');
|
||||||
|
const itemId = filament._id;
|
||||||
|
const draftOrderItems = await orderItemModel
|
||||||
|
.find({
|
||||||
|
'state.type': 'draft',
|
||||||
|
itemType: 'filament',
|
||||||
|
item: itemId,
|
||||||
|
})
|
||||||
|
.populate('order')
|
||||||
|
.lean();
|
||||||
|
|
||||||
|
for (const orderItem of draftOrderItems) {
|
||||||
|
await orderItemModel.recalculate(orderItem, user);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const filamentModel = mongoose.model('filament', filamentSchema);
|
export const filamentModel = mongoose.model('filament', filamentSchema);
|
||||||
|
|||||||
48
src/database/schemas/management/filamentsku.schema.js
Normal file
48
src/database/schemas/management/filamentsku.schema.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import mongoose from 'mongoose';
|
||||||
|
import { generateId } from '../../utils.js';
|
||||||
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
|
// Define the main filament SKU schema - color and cost live at SKU level
|
||||||
|
const filamentSkuSchema = new Schema(
|
||||||
|
{
|
||||||
|
_reference: { type: String, default: () => generateId()() },
|
||||||
|
barcode: { type: String, required: false },
|
||||||
|
filament: { type: Schema.Types.ObjectId, ref: 'filament', required: true },
|
||||||
|
name: { type: String, required: true },
|
||||||
|
description: { type: String, required: false },
|
||||||
|
color: { type: String, required: true },
|
||||||
|
cost: { type: Number, required: false },
|
||||||
|
overrideCost: { type: Boolean, default: false },
|
||||||
|
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
|
costWithTax: { type: Number, required: false },
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add virtual id getter
|
||||||
|
filamentSkuSchema.virtual('id').get(function () {
|
||||||
|
return this._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Configure JSON serialization to include virtuals
|
||||||
|
filamentSkuSchema.set('toJSON', { virtuals: true });
|
||||||
|
|
||||||
|
filamentSkuSchema.statics.recalculate = async function (filamentSku, user) {
|
||||||
|
const orderItemModel = mongoose.model('orderItem');
|
||||||
|
const skuId = filamentSku._id;
|
||||||
|
const draftOrderItems = await orderItemModel
|
||||||
|
.find({
|
||||||
|
'state.type': 'draft',
|
||||||
|
itemType: 'filament',
|
||||||
|
sku: skuId,
|
||||||
|
})
|
||||||
|
.populate('order')
|
||||||
|
.lean();
|
||||||
|
|
||||||
|
for (const orderItem of draftOrderItems) {
|
||||||
|
await orderItemModel.recalculate(orderItem, user);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create and export the model
|
||||||
|
export const filamentSkuModel = mongoose.model('filamentSku', filamentSkuSchema);
|
||||||
@ -2,13 +2,22 @@ import mongoose from 'mongoose';
|
|||||||
import { generateId } from '../../utils.js';
|
import { generateId } from '../../utils.js';
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
// Define the main part schema - pricing moved to PartSku
|
// Define the main part schema - cost/price and tax; override at PartSku
|
||||||
const partSchema = new Schema(
|
const partSchema = new Schema(
|
||||||
{
|
{
|
||||||
_reference: { type: String, default: () => generateId()() },
|
_reference: { type: String, default: () => generateId()() },
|
||||||
name: { type: String, required: true },
|
name: { type: String, required: true },
|
||||||
fileName: { type: String, required: false },
|
fileName: { type: String, required: false },
|
||||||
file: { type: mongoose.SchemaTypes.ObjectId, ref: 'file', required: false },
|
file: { type: mongoose.SchemaTypes.ObjectId, ref: 'file', required: false },
|
||||||
|
cost: { type: Number, required: false },
|
||||||
|
price: { type: Number, required: false },
|
||||||
|
priceMode: { type: String, default: 'margin' },
|
||||||
|
margin: { type: Number, required: false },
|
||||||
|
amount: { type: Number, required: false },
|
||||||
|
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
|
priceTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
|
costWithTax: { type: Number, required: false },
|
||||||
|
priceWithTax: { type: Number, required: false },
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
@ -21,5 +30,22 @@ partSchema.virtual('id').get(function () {
|
|||||||
// Configure JSON serialization to include virtuals
|
// Configure JSON serialization to include virtuals
|
||||||
partSchema.set('toJSON', { virtuals: true });
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create and export the model
|
// Create and export the model
|
||||||
export const partModel = mongoose.model('part', partSchema);
|
export const partModel = mongoose.model('part', partSchema);
|
||||||
|
|||||||
@ -6,16 +6,17 @@ const { Schema } = mongoose;
|
|||||||
const partSkuSchema = new Schema(
|
const partSkuSchema = new Schema(
|
||||||
{
|
{
|
||||||
_reference: { type: String, default: () => generateId()() },
|
_reference: { type: String, default: () => generateId()() },
|
||||||
sku: { type: String, required: true },
|
barcode: { type: String, required: false },
|
||||||
part: { type: Schema.Types.ObjectId, ref: 'part', required: true },
|
part: { type: Schema.Types.ObjectId, ref: 'part', required: true },
|
||||||
name: { type: String, required: true },
|
name: { type: String, required: true },
|
||||||
description: { type: String, required: false },
|
description: { type: String, required: false },
|
||||||
priceMode: { type: String, default: 'margin' },
|
priceMode: { type: String, default: 'margin' },
|
||||||
price: { type: Number, required: false },
|
price: { type: Number, required: false },
|
||||||
cost: { type: Number, required: false },
|
cost: { type: Number, required: false },
|
||||||
|
overrideCost: { type: Boolean, default: false },
|
||||||
|
overridePrice: { type: Boolean, default: false },
|
||||||
margin: { type: Number, required: false },
|
margin: { type: Number, required: false },
|
||||||
amount: { type: Number, required: false },
|
amount: { type: Number, required: false },
|
||||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: false },
|
|
||||||
priceTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
priceTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
priceWithTax: { type: Number, required: false },
|
priceWithTax: { type: Number, required: false },
|
||||||
@ -32,5 +33,22 @@ partSkuSchema.virtual('id').get(function () {
|
|||||||
// Configure JSON serialization to include virtuals
|
// Configure JSON serialization to include virtuals
|
||||||
partSkuSchema.set('toJSON', { virtuals: true });
|
partSkuSchema.set('toJSON', { virtuals: true });
|
||||||
|
|
||||||
|
partSkuSchema.statics.recalculate = async function (partSku, user) {
|
||||||
|
const orderItemModel = mongoose.model('orderItem');
|
||||||
|
const skuId = partSku._id;
|
||||||
|
const draftOrderItems = await orderItemModel
|
||||||
|
.find({
|
||||||
|
'state.type': 'draft',
|
||||||
|
itemType: 'part',
|
||||||
|
sku: skuId,
|
||||||
|
})
|
||||||
|
.populate('order')
|
||||||
|
.lean();
|
||||||
|
|
||||||
|
for (const orderItem of draftOrderItems) {
|
||||||
|
await orderItemModel.recalculate(orderItem, user);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create and export the model
|
// Create and export the model
|
||||||
export const partSkuModel = mongoose.model('partSku', partSkuSchema);
|
export const partSkuModel = mongoose.model('partSku', partSkuSchema);
|
||||||
|
|||||||
@ -10,6 +10,15 @@ const productSchema = new Schema(
|
|||||||
tags: [{ type: String }],
|
tags: [{ type: String }],
|
||||||
version: { type: String },
|
version: { type: String },
|
||||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
||||||
|
cost: { type: Number, required: false },
|
||||||
|
price: { type: Number, required: false },
|
||||||
|
priceMode: { type: String, default: 'margin' },
|
||||||
|
margin: { type: Number, required: false },
|
||||||
|
amount: { type: Number, required: false },
|
||||||
|
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
|
priceTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
|
costWithTax: { type: Number, required: false },
|
||||||
|
priceWithTax: { type: Number, required: false },
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
@ -21,5 +30,22 @@ productSchema.virtual('id').get(function () {
|
|||||||
// Configure JSON serialization to include virtuals
|
// Configure JSON serialization to include virtuals
|
||||||
productSchema.set('toJSON', { virtuals: true });
|
productSchema.set('toJSON', { virtuals: true });
|
||||||
|
|
||||||
|
productSchema.statics.recalculate = async function (product, user) {
|
||||||
|
const orderItemModel = mongoose.model('orderItem');
|
||||||
|
const itemId = product._id;
|
||||||
|
const draftOrderItems = await orderItemModel
|
||||||
|
.find({
|
||||||
|
'state.type': 'draft',
|
||||||
|
itemType: 'product',
|
||||||
|
item: itemId,
|
||||||
|
})
|
||||||
|
.populate('order')
|
||||||
|
.lean();
|
||||||
|
|
||||||
|
for (const orderItem of draftOrderItems) {
|
||||||
|
await orderItemModel.recalculate(orderItem, user);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create and export the model
|
// Create and export the model
|
||||||
export const productModel = mongoose.model('product', productSchema);
|
export const productModel = mongoose.model('product', productSchema);
|
||||||
|
|||||||
@ -11,16 +11,17 @@ const partSkuUsageSchema = new Schema({
|
|||||||
const productSkuSchema = new Schema(
|
const productSkuSchema = new Schema(
|
||||||
{
|
{
|
||||||
_reference: { type: String, default: () => generateId()() },
|
_reference: { type: String, default: () => generateId()() },
|
||||||
sku: { type: String, required: true },
|
barcode: { type: String, required: false },
|
||||||
product: { type: Schema.Types.ObjectId, ref: 'product', required: true },
|
product: { type: Schema.Types.ObjectId, ref: 'product', required: true },
|
||||||
name: { type: String, required: true },
|
name: { type: String, required: true },
|
||||||
description: { type: String, required: false },
|
description: { type: String, required: false },
|
||||||
priceMode: { type: String, default: 'margin' },
|
priceMode: { type: String, default: 'margin' },
|
||||||
price: { type: Number, required: false },
|
price: { type: Number, required: false },
|
||||||
cost: { type: Number, required: false },
|
cost: { type: Number, required: false },
|
||||||
|
overrideCost: { type: Boolean, default: false },
|
||||||
|
overridePrice: { type: Boolean, default: false },
|
||||||
margin: { type: Number, required: false },
|
margin: { type: Number, required: false },
|
||||||
amount: { type: Number, required: false },
|
amount: { type: Number, required: false },
|
||||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: false },
|
|
||||||
parts: [partSkuUsageSchema],
|
parts: [partSkuUsageSchema],
|
||||||
priceTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
priceTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
@ -38,5 +39,22 @@ productSkuSchema.virtual('id').get(function () {
|
|||||||
// Configure JSON serialization to include virtuals
|
// Configure JSON serialization to include virtuals
|
||||||
productSkuSchema.set('toJSON', { virtuals: true });
|
productSkuSchema.set('toJSON', { virtuals: true });
|
||||||
|
|
||||||
|
productSkuSchema.statics.recalculate = async function (productSku, user) {
|
||||||
|
const orderItemModel = mongoose.model('orderItem');
|
||||||
|
const skuId = productSku._id;
|
||||||
|
const draftOrderItems = await orderItemModel
|
||||||
|
.find({
|
||||||
|
'state.type': 'draft',
|
||||||
|
itemType: 'product',
|
||||||
|
sku: skuId,
|
||||||
|
})
|
||||||
|
.populate('order')
|
||||||
|
.lean();
|
||||||
|
|
||||||
|
for (const orderItem of draftOrderItems) {
|
||||||
|
await orderItemModel.recalculate(orderItem, user);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create and export the model
|
// Create and export the model
|
||||||
export const productSkuModel = mongoose.model('productSku', productSkuSchema);
|
export const productSkuModel = mongoose.model('productSku', productSkuSchema);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { jobModel } from './production/job.schema.js';
|
|||||||
import { subJobModel } from './production/subjob.schema.js';
|
import { subJobModel } from './production/subjob.schema.js';
|
||||||
import { printerModel } from './production/printer.schema.js';
|
import { printerModel } from './production/printer.schema.js';
|
||||||
import { filamentModel } from './management/filament.schema.js';
|
import { filamentModel } from './management/filament.schema.js';
|
||||||
|
import { filamentSkuModel } from './management/filamentsku.schema.js';
|
||||||
import { gcodeFileModel } from './production/gcodefile.schema.js';
|
import { gcodeFileModel } from './production/gcodefile.schema.js';
|
||||||
import { partModel } from './management/part.schema.js';
|
import { partModel } from './management/part.schema.js';
|
||||||
import { partSkuModel } from './management/partsku.schema.js';
|
import { partSkuModel } from './management/partsku.schema.js';
|
||||||
@ -53,6 +54,13 @@ export const models = {
|
|||||||
referenceField: '_reference',
|
referenceField: '_reference',
|
||||||
label: 'Filament',
|
label: 'Filament',
|
||||||
},
|
},
|
||||||
|
FSU: {
|
||||||
|
model: filamentSkuModel,
|
||||||
|
idField: '_id',
|
||||||
|
type: 'filamentSku',
|
||||||
|
referenceField: '_reference',
|
||||||
|
label: 'Filament SKU',
|
||||||
|
},
|
||||||
GCF: {
|
GCF: {
|
||||||
model: gcodeFileModel,
|
model: gcodeFileModel,
|
||||||
idField: '_id',
|
idField: '_id',
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const gcodeFileSchema = new mongoose.Schema(
|
|||||||
name: { required: true, type: String },
|
name: { required: true, type: String },
|
||||||
gcodeFileName: { required: false, type: String },
|
gcodeFileName: { required: false, type: String },
|
||||||
size: { type: Number, required: false },
|
size: { type: Number, required: false },
|
||||||
filament: { type: Schema.Types.ObjectId, ref: 'filament', required: true },
|
filamentSku: { type: Schema.Types.ObjectId, ref: 'filamentSku', required: true },
|
||||||
parts: [partSchema],
|
parts: [partSchema],
|
||||||
file: { type: mongoose.SchemaTypes.ObjectId, ref: 'file', required: false },
|
file: { type: mongoose.SchemaTypes.ObjectId, ref: 'file', required: false },
|
||||||
cost: { type: Number, required: false },
|
cost: { type: Number, required: false },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user