1

I've already written most of the functional parts to a custom billing system for my business (Wireless ISP,) but have stumped myself with a bit of it.

Here's the basic overview: It's a recurring billing system for my customers that automatically generates and sends invoices to each customer every month. However, I need to allow check/cash payments since I deal with local customers and also need to allow pre-payment so I can't just use something like Stripe's recurring billing. Essentially the payments are not directly associated with invoices to allow for these type of payments.

models/invoice.rb

class Invoice < ActiveRecord::Base
  belongs_to :customer
  has_many :line_items
  has_many :invoice_payments
  has_many :payments, through: :invoice_payments

models/payment.rb

class Payment < ActiveRecord::Base
  belongs_to :customer

models/customer.rb

class Customer < ActiveRecord::Base
  has_many :subscriptions, dependent: :destroy
  has_many :services, through: :subscriptions
  has_many :invoices, :order => 'id DESC'
  has_many :payments

I need a method that will automatically associate all unapplied payments to all unpaid invoices. Right now I'm putting that as def apply_unapplied_payments on the customer model, but will likely abstract it out later in to its own module in lib/.

This is what I've done so far in models/customer.rb

def apply_unapplied_payments
  unpaid_invoices = invoices.find_by_status("unpaid")
  unapplied_payments = payments.where("invoice_id is null")
  unpaid_invoices.each do |invoice|
    # find the oldest unapplied payment
    # apply payment to this invoice
    # if payment > invoice, keep whatever amount is left and move to next invoice
    # apply leftover amount to invoice, if invoice is still unpaid, move to next unapplied payment
  end
  customer.update_balance
end

Any suggestions for what to fill in the pseudocode with? I'm open to any level of refactoring, so please let me know if you can think of a better way to handle this!

4

1 に答える 1

0

これが私がすることです(支払いと請求書のクラスでいくつかのヘルパーメソッドが必要になる場合があります):

def apply_unapplied_payments
  unpaid_invoices = invoices.find_by_status("unpaid")
  unapplied_payments = payments.where("invoice_id is null")
  invoice = unpaid_invoices.shift
  payment = unapplied_payments.shift
  while invoice && invoice.remaining_balance > 0 && payment && payment.remaining_credit > 0
      apply_payment_to_invoice(invoice, payment)
      invoice = unpaid_invoices.shift    if invoice.remaining_balance == 0
      payment = unapplied_payments.shift if payment.remaining_credit  == 0
  end
end
于 2012-04-20T04:16:33.430 に答える