想象一张普通发票:上面有几件物品。每个项目都有一个数量和单位价格,其中包括(单位和描述)。
每件商品的总金额计算如下:数量*每单位价格。 这是针对每个项目完成的。然后,总发票的净额是所有总额的总和。添加增值税,即可获得发票的总金额。
这就是我正在尝试使用我的Rails应用程序。发票包含许多项目并接受它们的嵌套属性。一般来说,一切正常。
按照逻辑,我需要手动输入的是每单位价格和每件商品的数量以及发票的增值税。应自动计算总数以及由此产生的净额和总额。我想使用before_save
过滤器实现此目的。
这是我的发票型号:
before_save :calculate_net_amount, :calculate_gross_amount
def calculate_net_amount
self.items do |item|
self.net_amount += item.total
end
end
def calculate_gross_amount
self.gross_amount = self.net_amount * (1 + self.vat_rate)
end
这是项目模型:
before_save :calculate_total
def calculate_total
self.total = self.quantity * self.price_per_unit
end
这是我的规格失败:
it "calculates the net amount from all item totals" do
invoice = FactoryGirl.build(:invoice)
item = invoice.items.build(quantity: 2, unit: "Unit", description: "Desc", price_per_unit: 2)
invoice.save
invoice.net_amount.should == 4
end
它使用此发票工厂:
FactoryGirl.define do
factory :invoice do
association :client
currency "EUR"
vat_rate 0.19
net_amount 1
payment_on "2013-01-01"
status "paid"
end
end
测试基本上执行以下操作:包含2件物品2美元的发票应该有4美元的净额。相反,测试返回1,这似乎来自工厂并且显然没有被覆盖。如果我将它从夹具中移除,它表示它不能再计算总量,因为它不能在任何零对象上使用*。
我假设我对过滤器及其调用顺序做错了 - 总量是正确计算的,所以它必须与calculate_net_amount方法有关,并且作为一个错误结果它不能再计算总金额。
你能看出我做错了吗?
答案 0 :(得分:1)
self.items do |item|
应该是
self.items.each do |item|
由于items
是一个访问器,它是一个方法,它在技术上可以占用一个块,但是不会调用该块,因此不会发生求和。这是一个容易拼写错误。
顺便说一句,最好是使用inject
求和:
self.net_amount = self.items.inject(0){|sum, item| sum + item.total}