Refactored shipment schema to include new fields and methods for handling order types and tax calculations.

This commit is contained in:
Tom Butcher 2025-12-27 13:56:05 +00:00
parent 5545452b0c
commit c750b1a573

View File

@ -1,43 +1,108 @@
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 { purchaseOrderModel } from './purchaseorder.schema.js';
const shipmentItemSchema = new Schema({ import { taxRateModel } from '../management/taxrate.schema.js';
itemType: { type: String, required: true }, import { aggregateRollups, editObject, getObject } from '../../database.js';
item: { type: Schema.Types.ObjectId, refPath: 'itemType', required: true },
quantity: { type: Number, required: true },
itemCost: { type: Number, required: true },
totalCost: { type: Number, required: true },
totalCostWithTax: { type: Number, required: true },
taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
});
const shipmentSchema = new Schema( const shipmentSchema = new Schema(
{ {
_reference: { type: String, default: () => generateId()() }, _reference: { type: String, default: () => generateId()() },
purchaseOrder: { type: Schema.Types.ObjectId, ref: 'purchaseOrder', required: true }, orderType: { type: String, required: true },
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true }, order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
courierService: { type: Schema.Types.ObjectId, ref: 'courierService', required: false }, courierService: { type: Schema.Types.ObjectId, ref: 'courierService', required: false },
trackingNumber: { type: String, required: false }, trackingNumber: { type: String, required: false },
items: [shipmentItemSchema], amount: { type: Number, required: true },
cost: { net: { type: Number, required: true }, gross: { type: Number, required: true } }, amountWithTax: { type: Number, required: true },
shippedDate: { type: Date, required: false }, taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
expectedDeliveryDate: { type: Date, required: false }, shippedAt: { type: Date, required: false },
actualDeliveryDate: { type: Date, required: false }, expectedAt: { type: Date, required: false },
deliveredAt: { type: Date, required: false },
cancelledAt: { type: Date, required: false },
state: { state: {
type: { type: {
type: String, type: String,
required: true, required: true,
default: 'pending',
enum: ['pending', 'shipped', 'in_transit', 'delivered', 'cancelled'],
}, },
}, },
notes: { type: String },
timestamp: { type: Date, default: Date.now },
}, },
{ timestamps: true } { timestamps: true }
); );
shipmentSchema.statics.recalculate = async function (shipment, user) {
// Only purchase orders are supported for now
if (shipment.orderType !== 'purchaseOrder') {
return;
}
const orderId = shipment.order?._id || shipment.order;
if (!orderId) {
return;
}
var taxRate = shipment.taxRate;
if (shipment.taxRate?._id && Object.keys(shipment.taxRate).length == 1) {
taxRate = await getObject({
model: taxRateModel,
id: shipment.taxRate._id,
cached: true,
});
}
const amountWithTax = shipment.amount * (1 + (taxRate?.rate || 0) / 100);
await editObject({
model: shipmentModel,
id: shipment._id,
updateData: {
amountWithTax: amountWithTax,
},
user,
recalculate: false,
});
const rollupResults = await aggregateRollups({
model: this,
baseFilter: {
order: new mongoose.Types.ObjectId(orderId),
orderType: shipment.orderType,
},
rollupConfigs: [
{
name: 'shipmentTotals',
rollups: [
{ name: 'amount', property: 'amount', operation: 'sum' },
{ name: 'amountWithTax', property: 'amountWithTax', operation: 'sum' },
],
},
],
});
const totals = rollupResults.shipmentTotals || {};
const totalShippingAmount = totals.amount.sum?.toFixed(2) || 0;
const totalShippingAmountWithTax = totals.amountWithTax.sum?.toFixed(2) || 0;
const purchaseOrder = await getObject({
model: purchaseOrderModel,
id: orderId,
cached: true,
});
const grandTotalAmount =
parseFloat(purchaseOrder.totalAmountWithTax || 0) + parseFloat(totalShippingAmountWithTax || 0);
await editObject({
model: purchaseOrderModel,
id: orderId,
updateData: {
shippingAmount: parseFloat(totalShippingAmount).toFixed(2),
shippingAmountWithTax: parseFloat(totalShippingAmountWithTax).toFixed(2),
grandTotalAmount: parseFloat(grandTotalAmount).toFixed(2),
},
user,
recalculate: false,
});
};
// Add virtual id getter // Add virtual id getter
shipmentSchema.virtual('id').get(function () { shipmentSchema.virtual('id').get(function () {
return this._id; return this._id;