Enabling more than one payment methods for checks
Some organizations have more than one bank account that they deposit checks into. It would be appropriate to configure one payment method / payment instrument for each of these bank accounts so that a different Financial Account can be created for each.
Unfortunately, there are a number of places in core that bake in the idea that there is only ever a single payment method for checks. While we have worked around this with an extension that uses an override (specifically of this line: https://github.com/civicrm/civicrm-core/blob/master/CRM/Core/Payment/Manual.php#L95), JMA would like to remove this deficiency, or at least limitation, or core.
Here are some notes from Monish on implementation ideas. We'd like to get approval here, potentially after refinement, before we start.
- Add hook to add/override payment fields against respective payment instrument.
https://github.com/civicrm/civicrm-core/blob/master/CRM/Core/Payment.php#L609 this would be the place to add the new hook say: CRM_Utils_Hook::extendPaymentFields($paymentInstrumentID, &$paymentFields);
Another place to extend metadata via hook https://github.com/civicrm/civicrm-core/blob/master/CRM/Core/Payment.php#L724
- Change the hardcoded name ‘Check’ in various places, on basis of which check number information is fetched. In order to generalise it, we need to have a UI where we can define payment fields against each payment instrument. In that way it will be easy to gather payment information for a given payment instrument otherwise it will be a problem when the existing PI (payment instrument) name or value is changed like it occurred in case of Check PI whose name was changed to cheque.
Places where Check name was explicitly called (found using grep -irn "'Check'" CRM/ ):
`
CRM//Financial/Page/AJAX.php:371: if (row[
financialItem->id][$columnKey] == 'Check') {
CRM//Financial/Form/PaymentEdit.php:178: elseif ($paymentInstrumentName == 'Check') {
CRM//Contribute/BAO/Contribution.php:4140: if ($paidByName == 'Check') {
CRM//Contribute/Form/Contribution.php:649: $checkPaymentID = array_search('Check', CRM_Contribute_PseudoConstant::paymentInstrument('name'));
CRM//Contribute/BAO/Contribution.php:185: if ($params['payment_instrument_id'] != array_search('Check', $paymentInstruments)) {
And there are various other places (that hard to find using grep) which have an exclusive condition on payment instrument type where that is using in fetching particular payment field(s) for them.
In order to generalise the flow, we should have
2.1. a separate UI to say 'New Payment Instrument' form 2.2. This UI should have basic payment instrument fields, label, value and a section called payment fields where one can add multiple payment fields against that payment instrument and also select the html type. Say for CC, pan_truncation and card_type_id is text and select field respectively. It could be pretty much similar to the 'New Custom field' form where we can choose name, html type and data type.
- Upon submission it will save the data in uf_join.module_data as
INSERT INTO civicrm_uf_join
( is_active
, module
, entity_table
, entity_id
, weight
, uf_group_id
, module_data
)
VALUES ( '1', 'payment_instrument', 'civicrm_option_value', '17', '1', '', {"check_number":"ABC123"})
- After declaring the payment fields, it will render them in backoffice contribution/membership/event forms when the appropriate payment method is selected.
- To avoid a schema change, on submit the payment information could be stored in civicrm_financial_trxn.payment_data in serialised format. Obviously there are alternatives, such as doing the work to support custom fields on civicrm_financial_trxn, even though much of the existing custom field code would be problematic when applied to a table never exposed through search or directly through forms (closest is payments).
- Handle install and upgrade to adapt this new change
- Make changes across financial core files to fetch payment field
- Add UTs
So main objective: enable more than one payment method to be of type check, and thus prompt the display on view and create/edit of the check number field.