compucorp / uk.co.compucorp.membershipextras

Membership Extras for CiviCRM
Other
5 stars 8 forks source link

BASW-928: Use recurring contribution data to create autorenewal contributions #441

Closed omarabuhussein closed 1 year ago

omarabuhussein commented 2 years ago

Overview

Changing how contributions are created after autorenewal, so they use data from the recurring contribution instead of the previous term last contribution. The specific fields we are now copying from the payment plan instead of the last term contribution are:

The reason behind this, is that sometimes contributions might be changed manually by users, or sometimes a contribution might be paid let's say with "credit card" payment method , where the original payment plan was paid by "direct debit" payment method. Thus the recurring contribution is more accurate place to get such information, instead of using the last contribution which is subject to manual changes.

The only things we still copy from the previous contribution are :

given that such kind of data doesn't exist on the recurring contribution.

As part of this change, I also changed the "Source" field so it is set to "Offline Autorenewal: " instead of copying the old source, given that in cases such as using an importer, it doesn't make sense to keep copying the source over and over, also having the source set to contain "Autorenewal" should help in the future to identify renewal issues in case they happen.

Before

Last Contribution data are used to create the new contributions after offline autorenewal.

image

we can see that the data from the last contributing got used.

After

Recurring contribution data are used to create the new contributions after offline autorenewal.

image

2022-09-15 18_44_42-asasas dsadsa$ _ cc139

2022-09-15 18_45_57-asasas dsadsa$ _ cc139

we can see that we now use the data from the recurring contribution instead, also the "source" field is set to "Offline Autorenewal: " instead of being copied from the previous contribution.

Update 1

An issue with soft contributions creation and renewal is also discovered, where when you try to create a payment plan with soft contribution, or try to renew a payment plan that already has a soft contribution throw the following error:

Sep 20 09:29:27  [error] $Fatal Error Details = Array
(
    [callback] => Array
        (
            [0] => CRM_Core_Error
            [1] => exceptionHandler
        )

    [code] => -1
    [message] => DB Error: unknown error
    [mode] => 16
    [debug_info] => INSERT INTO `civicrm_contribution_soft` (`currency` ) VALUES ('GBP' )  [nativecode=1364 ** Field 'contribution_id' doesn't have a default value]
    [type] => DB_Error
    [user_info] => INSERT INTO `civicrm_contribution_soft` (`currency` ) VALUES ('GBP' )  [nativecode=1364 ** Field 'contribution_id' doesn't have a default value]
    [to_string] => [db_error: message="DB Error: unknown error" code=-1 mode=callback callback=CRM_Core_Error::exceptionHandler prefix="" info="INSERT INTO `civicrm_contribution_soft` (`currency` ) VALUES ('GBP' )  [nativecode=1364 ** Field 'contribution_id' doesn't have a default value]"]
)

which probably was never caught before because we rarely use Soft Contributions with Payment plans, given it it is something that our clients use and no one raised an issue about it before.

The cause of this error is that CiviCMR expects soft contributions to be in form of "array of arrays" https://github.com/civicrm/civicrm-core/blob/5.39.1/CRM/Contribute/BAO/ContributionSoft.php#L67-L68 given that it is possible to have more than one soft contribution, I fixed this by ensuring that soft_credit parameter used in the Contribution API is an array of arrays, but given that in Membership context, you cannot have more than one soft contribution, this array of arrays will only contain one array in it.

I also removed the code that tries to add the Soft Contribution using CRM_Contribute_BAO_ContributionSoft::add() method:

    $contributionSoftParams = CRM_Utils_Array::value('soft_credit', $params);
    if (!empty($contributionSoftParams)) {
      $contributionSoftParams['contribution_id'] = $contribution->id;
      $contributionSoftParams['currency'] = $contribution->currency;
      $contributionSoftParams['amount'] = $contribution->total_amount;
      CRM_Contribute_BAO_ContributionSoft::add($contributionSoftParams);
    }

given that passing soft_credit paramter to the Contribution API is enough to create the needed soft contributions.