1

通常の請求書を想像してみてください。そこにはいくつかの項目があります。各アイテムには、とりわけ、数量と単位あたりの価格 (単位と説明) があります。

各アイテムの合計金額は、数量 * 単位あたりの価格のように計算されます。これはアイテムごとに行われます。次に、請求書全体の正味金額は、すべての合計の合計です。VAT を追加すると、請求書の総額が得られます。

これは、Rails アプリでやろうとしていることです。請求書には多くの項目があり、それらのネストされた属性を受け入れます。通常、これはすべて正常に機能します。

ロジックに従って、手動で入力する必要があるのは、単位あたりの価格と各アイテムの数量、および請求書の VAT だけです。合計とその結果の正味額および総額は、自動的に計算されます。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

このテストは基本的に次のことを行います: どちらも USD 2 の 2 つの請求書の正味額は USD 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 に答える