- Introduced new fields: 'invoicedAmount', 'invoicedAmountWithTax', 'invoicedAmountRemaining', and 'invoicedAmountWithTaxRemaining' to the shipment schema for better tracking of invoicing status. - Updated the recalculation logic to compute remaining invoiced amounts based on the newly added fields.
124 lines
3.9 KiB
JavaScript
124 lines
3.9 KiB
JavaScript
import mongoose from 'mongoose';
|
|
import { generateId } from '../../utils.js';
|
|
const { Schema } = mongoose;
|
|
import { purchaseOrderModel } from './purchaseorder.schema.js';
|
|
import { taxRateModel } from '../management/taxrate.schema.js';
|
|
import { aggregateRollups, editObject, getObject } from '../../database.js';
|
|
|
|
const shipmentSchema = new Schema(
|
|
{
|
|
_reference: { type: String, default: () => generateId()() },
|
|
orderType: { type: String, required: true },
|
|
order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
|
|
courierService: { type: Schema.Types.ObjectId, ref: 'courierService', required: false },
|
|
trackingNumber: { type: String, required: false },
|
|
amount: { type: Number, required: true },
|
|
amountWithTax: { type: Number, required: true },
|
|
taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
|
invoicedAmount: { type: Number, required: false, default: 0 },
|
|
invoicedAmountWithTax: { type: Number, required: false, default: 0 },
|
|
invoicedAmountRemaining: { type: Number, required: false, default: 0 },
|
|
invoicedAmountWithTaxRemaining: { type: Number, required: false, default: 0 },
|
|
shippedAt: { type: Date, required: false },
|
|
expectedAt: { type: Date, required: false },
|
|
deliveredAt: { type: Date, required: false },
|
|
cancelledAt: { type: Date, required: false },
|
|
state: {
|
|
type: {
|
|
type: String,
|
|
required: 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 = parseFloat(
|
|
(shipment.amount || 0) * (1 + (taxRate?.rate || 0) / 100)
|
|
).toFixed(2);
|
|
await editObject({
|
|
model: shipmentModel,
|
|
id: shipment._id,
|
|
updateData: {
|
|
amountWithTax: amountWithTax,
|
|
invoicedAmountRemaining: shipment.amount - (shipment.invoicedAmount || 0),
|
|
invoicedAmountWithTaxRemaining: amountWithTax - (shipment.invoicedAmountWithTax || 0),
|
|
},
|
|
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
|
|
shipmentSchema.virtual('id').get(function () {
|
|
return this._id;
|
|
});
|
|
|
|
// Configure JSON serialization to include virtuals
|
|
shipmentSchema.set('toJSON', { virtuals: true });
|
|
|
|
// Create and export the model
|
|
export const shipmentModel = mongoose.model('shipment', shipmentSchema);
|