1

想象一张普通的发票:上面有几件物品。每个项目都有数量和单位价格,除其他外(单位和描述)。

每个项目的总金额计算如下:数量 * 每单位价格。这是为每个项目完成的。那么,整个发票的净额就是所有总额的总和。添加增值税,您就有了发票的总金额。

这就是我试图用我的 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 方法的问题,因此它无法计算总额了。

你能看到我做错了什么吗?

4

1 回答 1

1
self.items do |item|

应该

self.items.each do |item|

由于items是一个访问器,它是一种方法,它在技术上可以占用一个块,但该块没有被调用,所以没有发生求和。这是一个容易犯的错字。

顺便说一句,最好使用以下方法求和inject

self.net_amount = self.items.inject(0){|sum, item| sum + item.total}
于 2013-01-06T00:28:53.333 回答