diff --git a/src/database/schemas/inventory/shipment.schema.js b/src/database/schemas/inventory/shipment.schema.js index 67331ae..16bf11d 100644 --- a/src/database/schemas/inventory/shipment.schema.js +++ b/src/database/schemas/inventory/shipment.schema.js @@ -1,43 +1,108 @@ import mongoose from 'mongoose'; import { generateId } from '../../utils.js'; const { Schema } = mongoose; - -const shipmentItemSchema = new Schema({ - itemType: { type: String, required: true }, - 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 }, -}); +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()() }, - purchaseOrder: { type: Schema.Types.ObjectId, ref: 'purchaseOrder', required: true }, - vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true }, + 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 }, - items: [shipmentItemSchema], - cost: { net: { type: Number, required: true }, gross: { type: Number, required: true } }, - shippedDate: { type: Date, required: false }, - expectedDeliveryDate: { type: Date, required: false }, - actualDeliveryDate: { type: Date, required: false }, + amount: { type: Number, required: true }, + amountWithTax: { type: Number, required: true }, + taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false }, + 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, - default: 'pending', - enum: ['pending', 'shipped', 'in_transit', 'delivered', 'cancelled'], }, }, - notes: { type: String }, - timestamp: { type: Date, default: Date.now }, }, { 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 shipmentSchema.virtual('id').get(function () { return this._id;