Skip to content

Cash Payment Design

Jonathan Niles edited this page Oct 9, 2016 · 1 revision

This document describes the design for Cash Payments and Server-Side logic for the Cash Payments page.

Design

Cash payments describe two types of payments:

  1. Payments against Future Transactions (Cautions)
  2. Payments against Previous Invoices (Cash)

Both payment types are stored in the cash and cash_item tables. Cash Payments can be against multiple invoices. If the payment is not enough to cover the total cost, value is allocated in ascending order of the invoice date - oldest invoices are covered before newer ones until the value is allocated to all invoices.

Considering Exchange Rates

Cash Payments can be made in any currency, so they must consider the exchange rate of the day the payment is made.

  1. The payment information in the cash table is in the payment currency.
  2. The payment information coped to the posting_journal is in the enterprise currency.

To calculate the value of a cash payment in the enterprise currency, the exchange rate of payment date is used (see Exchange Rate Design). This step occurs in during the posting process.

Posting Cash Payments to the Posting Journal

Cash Payment records are written and posted using MySQL stored procedures StageCash(), StageCashItem(), CalculateCashInvoiceBalances(), WriteCash(), WriteCashItems(), and PostCash(). The Stage* procedures simply copy data from JavaScript into temporary tables.

CalculateCashInvoiceBalances()

Note: this procedure is only called if the payment is not a Caution.

This procedure collects the data of all unbalanced invoices for that patient. In order to reduce rounding errors, it converts all debts (stored in the enterprise currency) into the payment currency. These these values are written into the stage_cash_invoice_balances table to be used later.

WriteCash()

This procedure simply copies data into the cash table.

WriteCashItems()

Note: this procedure is only called if the payment is not a Caution.

This procedure uses the stage_cash_invoice_balances table to compute the amount allocated to each invoice. It loops through the debts and balances the invoice if the amount of cash paid is greater than the invoice amount. The cash amount is reduced by the amount allocated at each step. If the amount of money paid is not enough to cover all unbalanced invoices, the amount of money remaining credited to the final invoice and the algorithm terminates.

Note that the amount paid for each invoice might not be the same as the amount of owed, due to rounding. For example, an invoice that costs 930FC will be paid in full by paying 950FC. This is because FC only comes in units of 50FC, so the software rounds up. The unit is set in the min_monentary_unit column of the currency table. In this case, the cash record will list have amount as 950, but the cash_item will have amount as 930 allocated to one invoice. This imbalance shows that we must round.

PostCash()

This procedure posts values to the posting journal. It copies the line crediting the debtor to for the full amount paid. If the payment is a caution payment, a second line is written debiting the cashbox account for the balanced amount.

If the payment is not a caution, each payment item in cash_item is copied to the Posting Journal.

Handling Rounding

If there is a difference between the sum of all cash_item amounts and the cash amount, we must round. The algorithm first checks to make sure that they are within the min_monentary_unit range (and errors if not). Otherwise:

  1. If cash.amount - SUM(cash_item.amount) > 0, the enterprise received a gain on rounding. This value is debited to the gain_account_id found in the enterprise table.
  2. If cash.amount - SUM(cash_item.amount) < 0, the enterprise took a loss on rounding. This value is credited to the loss_account_id found in the enterprise table.