Uploaded image for project: 'CiviCRM'
  1. CiviCRM
  2. CRM-13965

Record additional payments or refunds for pending-pay later OR partially paid event registrations

    Details

    • Type: New Feature
    • Status: Done/Fixed
    • Priority: Major
    • Resolution: Fixed/Completed
    • Affects Version/s: 4.5
    • Fix Version/s: 4.5
    • Component/s: CiviContribute, CiviEvent
    • Labels:
      None

      Description

      -------------
      Summary
      -------------
      Back-office staff may:

      • Record one or more additional payments against "Partially paid" or "Pending pay later" registrations - until the registration fee is completely paid.
      • Participants may be sent receipts for each payment
      • Payments will be recorded as financial transactions against the original contribution record.
      • View existing payments (financial transactions)
      • When balance owing is 0, contribution status will be updated to Completed. Participant status can be set in payment form but default behavior is to set it to 'Registered' when balance owing is 0.
      • Record a refund (used when registration selections are changed and fee was overpaid - see CRM-13973).

      ---------------------
      Implementation
      ----------------------
      1. Implement BAO function which calculates 'amount owing' or 'refund due' for a given participant record.

      • SUM(line_item.line_total) for all line_item rows linked to the participant row MINUS SUM(financial_trxn.total_amount) for all financial_trxn rows linked to the contribution associated with the participant row AND where financial_trxn.status_id = 1 (Completed).
      • Positive number = Amount Owed,
      • Negative number = Refund Due


      2. Metadata changes
      2.1 Define two new activity types

      • Payment. Reserved=True, Component=CiviContribute, Description="Additional payment recorded for event or membership fee."
      • Refund. Reserved=True, Component=CiviContribute, Description="Refund recorded for event or membership fee."

      2.2 Define new participant status: 'Pending refund'

      • Status is 'Counted', Class='Positive', Reserved=TRUE, Visibility=Admin, Active=TRUE
      • Add to civicrm_data
      • Insert in upgrades

      2.3 Define new contribution status: 'Pending refund'

      • Reserved=TRUE, Active=TRUE
      • Add to civicrm_data
      • Insert in upgrades

      Add all new statuses to civicrm_data.tpl
      Insert new statuses in upgrades


      3. Implement a new form for submitting a Financial Transaction against an existing contribution linked to a participant (e.g an event registration)

          • IMPORTANT ***: Going forward we want to use the same form for applying payments against a Partially Paid membership contribution, so the form class should be structured to support conditional 'integration' with other component transactions.

      3.1 Form elements

      • Form elements are a subset of fields exposed in Contribution form (CRM_Contribute_Form_Contribution), but this is a basic create-only form so we'll make a new form class which only handles this case.
      • For this project, the form will always create a financial_trxn (payment or refund) against a partially paid contribution linked to the passed-in participant record. Participant Name (contact display_name) and event title + date are read-only elements on the top of the form.
      • URL params for contact id and participant id are required / passed to the form.
      • All form fields are columns in financial_trxn table EXCEPT for "Send Receipt" and "Receipt From".
      • add a text area to the form for purpose to provide optional email_text - shown conditionally if [x] Send Receipt checked
      • Form labels, required fields and layout are shown in the attached screenshot - RecordEventPayment.png (ignore the dark gray bars / extra space below Payment Amount). Change submit button title to "Record Payment" (not shown on screenshot).

      UPDATE: Please ignore the Financial Type field shown on the screenshot. Financial Type is not relevant to additional payments.

      • For 'Refund Due' case:
      • Payment Amount label => Refund Amount
      • Form block title = New Event Refund
      • Page title = Refund for $displayName
      • Additional client-side form behavior (same as contribution form Additional Details): Net Amount = Payment Amount - Fee Amount

      3.2 Pre process

      • Amount Owed OR Refund Due for this participant should be calculated during preProcess. This value should be the default for the Payment Amount/Refund Due field AND displayed next to the amount input box.
      • If related participant (contact) does not have a valid email address, display status re: can not send a receipt and hide the Send Receipt and From fields (same as for contribution form).

      3.3 Form rules

      • If amount owed, payment amount must be < = Amount Owed
      • If refund due, refund amount must = Refund Due (we do not want to support 'partially refunded' participant records at this point).
      • Net Amount = Payment Amount (OR Refund Amount) - Fee Amount

      3.4 Post Process
      NOTE: Use existing Financial Trxn / Financial Item BAO's as much as possible. Do not put transaction process logic in the form class (create new BAO(s) if necessary).

      • Insert new financial_trxn and entity_financial_trxn (keyed to contribution row). Financial Trxn status is completed. Payment instrument, check number, financial type etc are stored per form values.

      ------------------
      For Payments
      ------------------

      • If total paid is equal to amount owed:
      • update related financial_item row statuses to Paid
      • update related contribution status to Completed
      • update related participant status to Registered

      ------------------
      For Refunds
      ------------------

      • update related contribution status to Completed (from 'Pending refund')
      • update related participant status to Registered (from 'Pending refund')
      • If [x] Send Receipt is checked, we need a new function / message template for sending Payment/Refund Receipts. I've attached a 'text' version for this. In the interest of keeping the template simple, I'd suggest using this for event payments / refunds only (and implementing another new message template when support of partial membership payments is implemented).
      • For Payments - create new activity (type = Payment) for the new payment action. Data pattern similar to Contribution activity:
        Source Contact = logged in user's contact
        Target Contact = payee contact
        Subject = "$paymentAmount - Offline payment for $eventTitle
      • For Refunds - create new activity (type = Refund) for the new payment action. Data pattern similar to Contribution activity:
        Source Contact = logged in user's contact
        Target Contact = payee contact
        Subject = "$refundAmount - Offline refund for $eventTitle
      • Cancel on form should return to last form or page that the user was on. Successful submit should return to contact's Event tab in most cases. If the form is accessed via Find Participants, then return to the search form with session key (search results s/b preserved if possible).


      4. Live Mode (submit credit card payment) - Payments only

      • This mode is available if one or more of the required processor(s) enabled (allowBackofficeCreditCard - same rules as contribution form class). This is NOT available for 'Pending refund' contributions / participant records.
      • Extend the non-credit-card form class, adding in credit card and billing fields (see attached screenshot SubmitCCEventPayment.png)
      • Submit button title for this mode is 'Submit Credit Card Payment' (not shown on screenshot)
      • Post process invokes selected processor plugin to submit the payment. Rules for entity updates same as above.
      • Activity subject in LIVE mode = "$paymentAmount - Submit credit card payment for $eventTitle


      5. Modifications to Edit Participant and View Participant forms
      5.1 Change both forms to separate the table of "Fees" (Total, Paid, Owed) from the "Selections" (line items). See screenshots EditRegistrationPartiallyPaid.png and ViewParticipantPartiallyPaid.png for layout changes.

      5.2 If 'Amount Paid' is > 0, add "view payments" link to the Fees table (text link and link on Amount Paid amount value). Clicking link loads a new jQuery dialog pop-up which displays payments already made against the associated contribution (e.g. financial_trxn records). We need to filter the financial_trxn rows to only show actual payments (not transfers to AR account etc.). I think we can do this by only showing transactions where the "TO ACCOUNT" financial_account_type_id is 'Asset' (check with Pradeep to confirm this).

      See ViewPaymentsPopup.PNG screenshot for table elements and layout.


      6. Expose "Record Payment" button / action link for Participant records with "Partially paid" status.

      Users should be able to navigate to 'New Event Payment' form from the following buttons and action links:

      • Add a "Record Payment" button to participant edit AND participant view form IF participant status is 'Partially paid' or 'Pending pay later' (see screenshot EditRegistrationPartiallyPaid.png; ViewParticipantPartiallyPaid.png). Button click goes to new Financial Transaction form (passing contact id and participant id).
      • Add a 'Record Payment' action link to the Participant selector actions IF participant status for that row is 'Partially paid' or 'Pending pay later' (this should be available from contact's Events tab as well as Find Participants / Events Dashboard). Same behavior as 'Record Payment' button.


      7. Expose "Record Refund" button / action link for Participant record with "Pending refund" status

      Users should be able to navigate to 'New Event Refund' form from the following buttons and action links:

      • Add a "Record Refund" button to participant edit AND participant view form IF participant status is 'Partially paid'. Button click goes to new Financial Transaction form (passing contact id and participant id).
      • Add a 'Record Refund' action link to the Participant selector actions IF participant status for that row is 'Pending refund' (this should be available from contact's Events tab as well as Find Participants / Events Dashboard). Same behavior as 'Record Refund' button.


      8. Tests
      8.1 Extend existing Event (participant) and Financial BAO tests to cover recording 'additional payments' for a participant record. Check for expected participant and contribution status changes as well as expected new activity record.

      8.2 Create web-test which covers the additional payments flow (both additional payment for total owing and additional payment for part of total owing).


      9. Scheduled Reminders
      9.1 Admins should be able to schedule reminders for participants whose status is Partially paid, and include tokens to display the participant's Total Fees and Balance.

      NOTE: The ability to target Partially paid should happen automatically once the new participant status option value is added.

      {event.fee_amount}

      is already available and will display the Total Fees.

      • Add a new token for display of participant's balance - {event.balance}

        Attachments

        1. Additional Payment or Refund Msg Template.rtf
          6 kB
          David Greenberg
        2. AdditionalPaymentReceipt_test1.txt
          5 kB
          David Greenberg
        3. EditRegistrationPartiallyPaid.PNG
          123 kB
          David Greenberg
        4. RecordEventPayment.PNG
          95 kB
          David Greenberg
        5. SubmitCCEventPayment.PNG
          124 kB
          David Greenberg
        6. ViewParticipantPartiallyPaid.PNG
          99 kB
          David Greenberg
        7. ViewParticipantWithRefund-test.PNG
          82 kB
          David Greenberg
        8. ViewPaymentsPopup.PNG
          28 kB
          David Greenberg

          Activity

            People

            • Assignee:
              dgg David Greenberg
              Reporter:
              dgg David Greenberg
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - 0 minutes
                0m
                Logged:
                Time Spent - 1 week, 1 day
                1w 1d