Proposal - make future recurring contribution instances modifiable (from CRM-13839) (not necessarily in core)
Currently each contribution in a recurring contribution series is generated based on the most recent completed contribution in that series. In some cases there is a desire to alter it as time goes on - with requests to change
- line items
- custom fields
- soft credits
- link to the contribution page
The main function to retrieve the template is CRM_Contribute_BAO_ContributionRecur::getTemplateContribution (not everything happens in there now but maybe one day).
Current possible overrides are both from input when calling repeattransaction and from editing the contribution_recur record and mainly cover campaign_id, payment_instrument_id and financial_type_id (when there is a single line item & it's type matches the contribution).
There are 2 main possible approaches:
- deal with line items, ignore other items for now
- look at a data format that stores the whole template
Line items only This is the approach determined in CRM-13839.
The JIRA issue suggests that for each contribution_recur record there will be line items recorded in civicrm_line_item referring to the contribution_recur table rather than the contribution table. These would be editable through a form and would form the template for future items.
An alternative in this general approach that feels less risky is to alter the getTemplateContribution such that IF line items are in the line_item table against the contribution_recur they are used, otherwise do as existing. The code for the alter form would be put in an extension that may eventually ship enabled with core.
There is an advantage in ALWAYS creating the line items & template in general as the recur can wind up with no associated contributions & then there is no template. However, I worry about the reliance on them existing in CRM-13839. The original proposal includes an upgrade script & creating them when the recurring is created. I'd feel better about only processing them if-exist in core & testing the approach more in an extension.
Template for all items The limit of the line items only approach is that ... it only deals with line items.
An alternate would be so simply store the entire template as json in a custom field attached to the recurring contribution. There are some risks/ complexities here (how do we deal with price fields or price values that are deleted, can we block that without an FK - assuming line item otherwise has an FK) but it DOES provide a path to dealing with all the types of date. Since CRM-13839 was logged Veda has done work on making custom data work on recurring contributions (& more recently all entities work with custom data) & we have better support for json data storage via the api now too.
The field could be set to 'view_only' and managed via a special form.
What goes in an extension vs core
It feels almost a given that we would add a hook to CRM_Contribute_BAO_ContributionRecur::getTemplateContribution - we would need to ensure the data format is flexible enough to grow from the current limited template (line items mainly) returned from that function to a more complete one.
Any other forms / manipulation could be implemented in an extension. It is possible that the extension would become part of the core offering at some point (shipping enabled on new installs) - this provides us a path to experiment more flexibly while planning to deprecate some of our pain in future. In order to facilite this & to make it something that can be collaborated on I would suggest the extension is stand alone & implements this specific functionality - allowing it to be used regardless of the processor or indeed of whether the processor is processing manual/pay later payments