import mongoose from 'mongoose'; import { generateId } from '../../utils.js'; const { Schema } = mongoose; import { aggregateRollups, aggregateRollupsHistory, editObject } from '../../database.js'; const paymentSchema = new Schema( { _reference: { type: String, default: () => generateId()() }, amount: { type: Number, required: true, default: 0 }, vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: false }, client: { type: Schema.Types.ObjectId, ref: 'client', required: false }, invoice: { type: Schema.Types.ObjectId, ref: 'invoice', required: true }, state: { type: { type: String, required: true, default: 'draft' }, }, paymentDate: { type: Date, required: false }, postedAt: { type: Date, required: false }, cancelledAt: { type: Date, required: false }, paymentMethod: { type: String, required: false }, notes: { type: String, required: false }, }, { timestamps: true } ); const rollupConfigs = [ { name: 'draft', filter: { 'state.type': 'draft' }, rollups: [ { name: 'draftCount', property: 'state.type', operation: 'count' }, { name: 'draftAmount', property: 'amount', operation: 'sum' }, ], }, { name: 'posted', filter: { 'state.type': 'posted' }, rollups: [ { name: 'postedCount', property: 'state.type', operation: 'count' }, { name: 'postedAmount', property: 'amount', operation: 'sum' }, ], }, { name: 'cancelled', filter: { 'state.type': 'cancelled' }, rollups: [ { name: 'cancelledCount', property: 'state.type', operation: 'count' }, { name: 'cancelledAmount', property: 'amount', operation: 'sum' }, ], }, ]; paymentSchema.statics.stats = async function () { const results = await aggregateRollups({ model: this, rollupConfigs: rollupConfigs, }); // Transform the results to match the expected format return results; }; paymentSchema.statics.history = async function (from, to) { const results = await aggregateRollupsHistory({ model: this, startDate: from, endDate: to, rollupConfigs: rollupConfigs, }); // Return time-series data array return results; }; paymentSchema.statics.recalculate = async function (payment, user) { const paymentId = payment._id || payment; if (!paymentId) { return; } // For payments, the amount is set directly const amount = payment.amount || 0; const updateData = { amount: parseFloat(amount).toFixed(2), }; await editObject({ model: this, id: paymentId, updateData, user, recalculate: false, }); }; // Add virtual id getter paymentSchema.virtual('id').get(function () { return this._id; }); // Configure JSON serialization to include virtuals paymentSchema.set('toJSON', { virtuals: true }); // Create and export the model export const paymentModel = mongoose.model('payment', paymentSchema);