0

私は請求書と支払いのためのシンプルな正規化モデルを持っています。私はRuby on Railsの未払い金額にdenormaizedフィールドを使用する必要があります

関連分野が

invoices.id 
invoices.amount_with_tax 
invoice_payments.id 

invoice_payments.invoice_id 
invoice_payments.amount 

関係が

Invoice 
    has_many :invoice_payments 
    has_many :payments, through: :invoice_payments 

InvoicePayment 
    belongs_to :invoice 
    belongs_to :payment 

Payment 
    has_many :invoice_payments 
    has_many :invoices, through: :invoice_payments 

されている支払モデルは、この質問には関係ありませんが、同じ問題を呈します。

変数invoices@invoicesは、アクティブレコード関係です。

私は、請求書テーブルにamount_outstandingフィールドを追加した場合、未払いの請求書を取得するためのコードは単純です:

invoices.where('amount_outstanding > 0') 

が、非正規化フィールドの維持は迷惑です。そのフィールドなしでこれを取得する

私の現在のコードは複雑です:

invoices = invoices.left_outer_joins(:invoice_payments) 
invoices = invoices.distinct.select('invoices.*, sum(invoice_payments.amount) as total_payments') 
invoices = invoices.group('invoices.id')  
invoices = invoices.having('sum(invoice_payments.amount) < invoices.amount_with_tax or sum(invoice_payments.amount) is null') 

私はこの上の任意のパフォーマンステストを行っていないが、多くのがあるとき、それは非常に良いことはありませんように見えますシステム内の請求書。 ActiveRecordで生成されるコードは、SQLで記述したコードと似ていますので、恐ろしいことではありません。

請求先に完全には記載されていない支払いを見つけるには、支払い側で同様のコードが必要になります。

未払いの請求書を検索すると、未払いの金額が報告されるため、頻繁な操作です。堅実に運営されている会社にとっては、未収入金の未収金額は支払った金額に比べて少ない。時間が経つにつれて、それは全体の請求書の中ではるかに少ない割合になります。

請求書に支払いを適用するのは通常1回で、復帰や編集はほとんどありません。ほとんどの支払いは1つの請求書に関連し、それを完全にカバーします。

未払いの請求書があるかどうかを判断したり、erbでカウントを取得しようとしています。 <%[email protected] %>はSQLエラーを返します。

私は個人的に非正規化されたデータを好きではありません。それは、それを維持する作業が正規化されたままにしておくのが普通の約3倍であるからです。この場合、amount_with_taxが変更された場合、またはInvoicePaymentが編集、削除、または別の請求書に移動された場合は、項目を更新する必要があります。 amount_outstandingの値を計算するためのコードは、しかし、単一の請求書のために非常に簡単です:

paid = invoice_payments.sum(:amount) 
self.amount_outstanding = self.amount_with_tax - paid 
save 

私は現在amount_outstandingを維持するために、請求書やInvoicePaymentsモデルにコールバックを使用しています。

質問があります。この場合、価値のある非正規化フィールドがありますか、これを実現するにはより良い方法がありますか?

答えて

1

残高を表示したり依存したりするユースケースに大きく依存します。どのくらいの頻度でこの値を使用しますか?この値を表示するだけで、ユーザーは少し遅れても受け入れます(この値を計算するのが遅いと考えている)。

あなたは、このシナリオのパフォーマンステストを行っておらず、処理された請求書の数に関してシステムの範囲に関する情報もないと述べました。任意の金融システムと同様に、すべての取引は特定の財務期間に関連付けられる傾向があります。したがって、システムに格納されているすべての請求書ではなく、その期間を考慮して、

一般に、非正規化フィールドなしで必要な処理は、非常に多くの請求書を処理できる必要があります。もちろん、サーバーの設定にも依存します。また、コードを最適化して同じ機能を得るためにクエリの数を減らすことができる可能性もあります。

パフォーマンスに関する問題をまだ確認していない場合は、早すぎる最適化を試みている可能性がありますが、これは常にベストプラクティスではありません。だから私はそれが必要であることがわかるまで非正規化フィールドを避け、必要なときに必要な最適化を行うことを検討します。希望が役立ちます。

+0

請求書の更新に関する問い合わせの頻度はおそらく100対1程度です。最終的なシステムのサイズはわかりませんが、拡張の能力を制限したくありません。典型的な中小企業の場合、年に数千の請求書がありますが、それほど大きなものではありません。カウントを取得するエラーを除いて正規化されたコードが実行され、別のクエリを書き込むことができます。そして私は早すぎる最適化についてDKに同意します。 –

+0

何千もの請求書は心配するほど大きな数字ではありません。したがって、非正規化されていないフィールドを使用しないで開始する方が良いと思われ、必要に応じて最適化を行います。また、カウントについては、モデルやコントローラーでカウントを取得し、そのコードをerbに直接書き込むのではなくerbに渡すコードを書く方が良いです。 – coffeebytes

関連する問題