I have an Invoice model that uses virtual attributes to compute values for tax, subtotal, total etc. The problem I have is that some of the virtual attributes need to be able to reference other virtual attributes.
For example, here is the Mongoose schema for the Invoice:
var InvoiceSchema = Schema({
number: String,
customer: {ref:String, email:String},
invoiceDate: {type: Date, default: Date.now},
dueDate: {type: Date, default: Date.now},
memo: String,
message: String,
taxRate: {type:Number, default:0},
discount: {
value: {type:Number, default:0},
percent: {type:Number, default:0}
},
items: [ItemSchema],
payment: {type: Schema.Types.ObjectId, ref: 'Payment'}
});
InvoiceSchema.virtual('tax').get(function(){
var tax = 0;
for (var ndx=0; ndx<this.items.length; ndx++) {
var item = this.items[ndx];
tax += (item.taxed)? item.amount * this.taxRate : 0;
}
return tax;
});
InvoiceSchema.virtual('subtotal').get(function(){
var amount = 0;
for (var ndx=0; ndx<this.items.length; ndx++) {
amount += this.items[ndx].amount;
}
return amount;
});
InvoiceSchema.virtual('total').get(function(){
return this.amount + this.tax;
});
InvoiceSchema.set('toJSON', { getters: true, virtuals: true });
var ItemSchema = Schema({
product: String,
description: String,
quantity: {type: Number, default: 1},
rate: Number,
taxed: {type: Boolean, default: false},
category: String
});
ItemSchema.virtual('amount').get(function(){
return this.rate * this.quantity;
});
ItemSchema.set('toJSON', { getters: true, virtuals: true });
module.exports = mongoose.model('Invoice', InvoiceSchema);
Now to understand the issue take a look at the virtual definition for 'tax' ...
InvoiceSchema.virtual('tax').get(function(){
var tax = 0;
for (var ndx=0; ndx<this.items.length; ndx++) {
var item = this.items[ndx];
tax += (item.taxed)? item.amount * this.taxRate : 0;
}
return tax;
});
... in this example item.amount, when called inside a virtual, doesn't use the virtual getter for item.amount.
Is there some way to tell Mongoose that I need to use the getter instead of trying to read a property that doesn't exist?
Did you try item.get('amount')
?
That seems to be the explicit way of using virtuals.
Got it from this Issue: https://github.com/Automattic/mongoose/issues/2326 Didn't find anything else related unfortunately.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With