Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  1. Link this civicrm_financial_item to the civicrm_financial_trxn using both through the civicrm_financial_item.entity_table and civicrm_financial_item.entity_id (this indicates what the fee is about) and through civicrm_entity_financial_trxn (this shows the the civicrm_financial_item has been paid, and that the payment that caused fee actually paid for the fee):
    1. civicrm_financial_item.entity_table = 'civicrm_financial_trxn'
    2. civicrm_financial_item.entity_id = the new civicrm_financial_trxn.id
    3. civicrm_entity_financial_trxn.entity_table = 'civicrm_financial_item'
    4. civicrm_entity_financial_trxn.entity_id = the new civicrm_financial_item.id
  2. For both manual and payment processor cases, use the to_financial_account_id for the payment identified in "Recording an initial transaction with or without a payment", point 1 as the from_financial_account_id for the fee.
  3. Select the to_financial_account_id as follows:
    1. For a payment_processor, use the financial_type and civicrm_entity_financial_account.account_relationship of expense. If none exists, raise an error. (We don't want to force this at config time since some payment processors may not report fees back).
    2. For a manual payment,
      1. if there is only one financial account of financial_account_type=expense, then use it
      2. if there is more than one financial_account of financial_type=expense, then an additional field will be displayed to the admin user in the Additional Details fieldset just under Fee Amount allowing them to select "Fee Account" with a drop down list of all financial_accounts of financial_type=expense, with the default selection being the one with is_default=true.
  4. status_id: Option List id for Paid (on the basis it has already been taken out of the trxn and therefore the financial_trxn.net_amount is exclusive of the fee).
  5. set civicrm_financial_item.contact_id to the domain or system owner contact id (see CRM-9897).

...

  1. Financial Items (ie edits to contributions, memberships and event purchases); and
  2. Financial Transactions (eg edits to payments)

The UI may allow the user to change an existing transaction and simultaneously make a payment or refund for some or all of the amount at the same time. We will spec out what happens for the line items and financial items first, then move on to the financial transactions second. However, every accounting transaction must be balanced, so there is some interaction between the two - the total difference in the financial items has to be reflected in a corresponding entry in the civicrm_financial_trxn table.

Changes/Reversals to Line Items / Financial Items

...

  1. There may have been a change either to the financial_type for the line item that results in a new income account, or the income account within the existing financial type may have changed (though it is possible that a change in financial_type has not resulted in a change of income account). If there is a change to the line_item.financial_type_id, check via entity_financial_account.account_relationship for the "Income account is" to see if that account is different than the existing financial_item.financial_account_id. If changed, get confirmation from user, create a transaction that move the original amount from the original income account to the new income account, and proceed with rest of transaction.
    1. More specifically, if entity_financial_account.financial_account_id != financial_item.account_id, display a confirmation dialog that "The Income Account for the <line item label> has been changed from <original account name> to <new account name>. Clicking OK will move this income from the old to the new income account."
    2. If Cancel, return to edit form.
    3. If OK,
      1. create a new financial_item record the same as the old one with the new financial_account_id
      2. create a financial_trxn record with from_financial_account_id=old financial_item.account_id and to_financial_account_id=new financial_item.account_id, with amount=old financial_item.amount.
      3. create two entity_financial_trxn records connecting the new financial_trxn record to both the old and the new financial_item records
  2. If the change would result in the total of the financial_item for the line_item becoming less than zero, throw an exception and don't proceed
  3. Create a new financial_item with source_table and source_id set to the civicrm_line_item with the amount of the adjustment against the account
    1. E.g. if the original amount is 100 and the new amount is 50, then the adjustment is -50; if the original is 100 and the new amount is 125, then the adjustment is 25.
  4. If the change is negative (credit/refund) and
    1. if the financial_item was previously unpaid or part paid, if change means the original financial_item is now fully paid or overpaid, set its status to paid
    .//
    1. if the financial_item was previously paid, set the status to part paid or unpaid as appropriate
  5. else if the change is positive (increase in revenue) and
    1. if the financial_item was previously unpaid or partially paid, don't change the status of the financial_item
    since this part of spec is not concerned with recording a payment and the new income gets its own new
    1. if the financial_item
    //
    1. was previously paid, change the status to partially paid
  6. else the change is zero and nothing needs to be done. This may be the case where the account is being changed.

Items 4 - 6 above attempt to keep payment status of line items closely related to their previous status rather than deal with this for all financial items at the overall contribution record level.

Store any changes in the total amount owing for the whole price set/transaction as follows:

  1. Determine the total_difference_amount for the whole price set/transaction including any payment or refund, ie the change in the amount of the obligation: Sum of line items in current version of price set that is about to be stored minus the sum of the line items of the previous version of price set that is currently in the db.
  2. Determine the total_amount_previously_owing by adding or subtracting financial_trxn amounts for the transaction as follows:
    1. Asset: subtract (this means a deposit has been received)
    2. Liability: add (this means a payment such as a refund has been made)
    3. Accounts receivable: add (this records what is owed eg for a pay later)
    4. Accounts payable: subtract (this records what has to be paid, eg a refund that will be paid via cheque to be cut later)
    5. Revenue: add (this is the obligation of a donor, and appears in this field if an accounts receivable is being cancelled)
    6. Expense: subtract (this supports recording what is owed to a grant winner, and appears in this field if an accounts payable is being cancelled)
  3. Calculate total_amount_currently_owing = total_amount_previously_owing + total_difference_amount - payment.amount + refund.amount
  4. Record any payment being made at the time of the transaction as one, two or perhaps three financial_trxn records: against a/r amount, a regular payment, and potentially an overpayment:
    1. if total_amount_previously_owing > 0 and total_amount_currently_owing < total_amount_previously owing, (let's pay down the account receivable)
      1. if total_amount_currently_owing > 0
      2. -----
      3. if payment.amount <= total_amount_previously_owing, create one financial_trxn with from_financial_account_id = a/r account and to_financial_account_id = the asset account for the payment and financial_trxn.amount=payment.amount.
      4. if payment.amount > total_amount_previously_owing, create one financial_trxn with from_financial_account_id = a/r account and to_financial_account_id = the asset account for the payment and financial_trxn.amount=payment.amount and a second financial_trxn with from_financial_account_id = null, to_financial_account_id = the asset account for the payment and financial_trxn.amount=payment.amount - total_amount_previously_owing
    2. if total_amount_previously_owing >= 0, then record payment in financial_trxn with from_financial_account_id blank
  5. Record any refund being made at the time of the transaction as one or perhaps two financial_trxn records: against a/p amount, a regular refund, and an inappropriately large refund that creates an a/r to be paid later:
    1. if total_amount_previously_owing < 0, then
      1. if refund.amount <= - total_amount_previously_owing, create one financial_trxn with from_financial_account_id = a/p account and to_financial_account_id = the asset account for the refund and financial_trxn.amount=refund.amount
      2. if refund.amount > - total_amount_previously_owing, create one financial_trxn with from_financial_account_id = a/p account and to_financial_account_id = the asset account for the refund and financial_trxn.amount=refund.amount and a second financial_trxn with from_financial_account_id = null, to_financial_account_id = the asset account for the refund and financial_trxn.amount= total_amount_previously_owing - refund.amount
  6. Create entity_financial_item records linking financial_trxn to the financial_item records that have been created for the change transaction.
    1. The allocation of the amount of the financial_trxn should be determined by the choices of the user through the UI as per other payments.

 

  1. If this total_difference_amount is a positive number, then more money is owing from contributor, so store a new pay later transactions . Create a new financial_trxn record for the adjustment amount. Depending on invoking context and adjustment, this may be:
    1. a reduction of a refund owing amount,
    2. the elimination of a refund owing amount,
    3. a pay later a/r transaction,
    4. a pay immediate asset transaction for an online payment or,
    5. a pay immediate manually recorded payment entered at same time as changes
    It is possible for b) to be combined with c, d, or e. Store a new transaction for the appropriate case in civicrm_financial_trxn as per 1a 1 of 'Recording an initial transaction with or without a payment' above.
  2. If the result is 0, then continue / do nothing
  3. If the result is a negative number, then either less money is owing from the contributor, and / or a refund is owed to the contributor. Figure out current amount owing on whole transaction as follows:
    1. find all civicrm_financial_trxn records related to the contribution
      1. Select financial_trxn_id from civicrm_entity_financial_trxn for entity_table='civicrm_financial_item' and entity_id in (select id from civicrm_financial_item fi inner join civicrm_line_item li on fi.entity_id=li.id and fi.entity_table='civicrm_line_item' where li.contribution_id=this->contribution_id)
    2. add or subtract civicrm_financial_trxn.if total_amount from a running total_amount_owing based on the financial_account_type of civicrm_financial_trxn.to_financial_account_id:
      1. Asset: subtract (this means a deposit has been received)
      2. Liability: add (this means a payment such as a refund has been made)
      3. Accounts receivable: add (this records what is owed eg for a pay later)
      4. Accounts payable: subtract (this records what has to be paid, eg a refund that will be paid via cheque to be cut later)
      5. Revenue: add (this is the obligation of a donor, and appears in this field  if an accounts receivable is being cancelled)
      6. Expense: subtract (this supports recording what is owed to a grant winner, and appears in this field if an accounts payable is being cancelled)
      owing < 0 then a refund is owed
      1. Mark the status of all financial_items and the contribution as paid
    3. If total_amount_owing >= 0, then
      1. civicrm_financial_trxn.total_amount = total_amount_owing + total_difference_amount (which is a negative amount) 
      2. if civicrm_financial_trxn.total_amount < 0 then
      3. // we need to offset the existing civicrm_financial_trxn for accounts receivables accounts for this transaction
      4. for each civicrm_financial_trxn for accounts receivables accounts for this transaction
      5. civicrm_financial_trxn.total_amount = - total_amount_owing, to_financial_account_id = the
      6. create another new civicrm_financial_trxn record for a refund with civicrm_financial_trxn.total_amount = total_amount_owing - total_difference_amount, setting the to_financial_account_id to the
      7. if (to_distribute_amount < 0) then
      8. // pay all the owing amounts
      9. for each line_item
        1. create a civicrm_entity_financial_trxn record linking the
        2. set status to paid
      10. if (to_dis

Use that amount to change the contribution.status if necessary (if old status paid and adjustment_total>0, then new status=partly paid; if old_status=partly paid and < some calcuation to be determined using old_total and adjustment_total>, set new status=paid)

...


Creative Commons License
Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution-Share Alike 3.0 United States Licence.