想象一张普通的发票:上面有几件物品。每个项目都有数量和单位价格,除其他外(单位和描述)。
每个项目的总金额计算如下:数量 * 每单位价格。这是为每个项目完成的。那么,整个发票的净额就是所有总额的总和。添加增值税,您就有了发票的总金额。
这就是我试图用我的 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,这似乎来自工厂并且显然没有被覆盖。如果我将它从夹具中移除,它会说它不能再计算总金额,因为它不能在任何 nil 对象上使用 *。
我假设我在过滤器和调用它们的顺序上做错了 - 总金额计算正确,所以它必须是关于 calculate_net_amount 方法的问题,因此它无法计算总额了。
你能看到我做错了什么吗?