Fix bug in tax calculation when recurring overrides with a different value
authorEileen McNaughton <emcnaughton@wikimedia.org>
Wed, 1 Mar 2023 22:48:36 +0000 (11:48 +1300)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Wed, 1 Mar 2023 23:56:46 +0000 (12:56 +1300)
CRM/Contribute/BAO/Contribution.php
tests/phpunit/api/v3/ContributionTest.php

index d1d7afe8774400c169a1858735b2eb8ff303b42b..87784ecc73e8d5cb558f3b477a546b1d0bc91889 100644 (file)
@@ -2162,20 +2162,29 @@ LEFT JOIN  civicrm_contribution contribution ON ( componentPayment.contribution_
    * Gaps in the above (
    *
    * @param array $input
-   *    Keys are all optional, if not supplied the template contribution's values are used.
-   *    The template contribution is either the actual template or the latest added contribution
-   *    for the ContributionRecur specified in $contributionParams['contribution_recur_id'].
    *    - total_amount
    *    - financial_type_id
    *    - campaign_id
    *
+   *    These keys are all optional, and are combined with the values from the contribution_recur
+   *    record to override values from the template contribution. Overrides are
+   *    subject to the following limitations
+   *    1) the campaign id & is_test always apply (is_test is available on the recurring but not as input)
+   *    2) the total amount & financial type ID overrides ONLY apply if the contribution has
+   *    only one line item.
+   *
+   *    The template contribution is derived from a contribution linked to
+   *    the recurring contribution record. A true template contribution is only used
+   *    as a template and is_template is set to TRUE. If this cannot be found the latest added contribution
+   *    is used.
+   *
    * @param array $contributionParams
    *
    * @return bool|array
    * @throws \CRM_Core_Exception
    * @throws \Civi\API\Exception\UnauthorizedException
    * @todo
-   *  1) many processors still call repeattransaction with contribution_status_id = Completed
+   *
    *  2) repeattransaction code is current munged into completeTransaction code for historical bad coding reasons
    *  3) Repeat transaction duplicates rather than calls Order.create
    *  4) Use of payment.create still limited - completetransaction is more common.
@@ -2192,7 +2201,7 @@ LEFT JOIN  civicrm_contribution contribution ON ( componentPayment.contribution_
     $contributionParams['line_item'] = $templateContribution['line_item'];
     $contributionParams['status_id'] = 'Pending';
 
-    foreach (['contact_id', 'campaign_id', 'financial_type_id', 'currency', 'source', 'amount_level', 'address_id', 'on_behalf', 'source_contact_id', 'tax_amount', 'contribution_page_id', 'total_amount'] as $fieldName) {
+    foreach (['contact_id', 'campaign_id', 'financial_type_id', 'currency', 'source', 'amount_level', 'address_id', 'on_behalf', 'source_contact_id', 'contribution_page_id', 'total_amount'] as $fieldName) {
       if (isset($templateContribution[$fieldName])) {
         $contributionParams[$fieldName] = $templateContribution[$fieldName];
       }
index f41051ef5f1dd0cdd88fdbd59e752f6aa2b6d067..31d78c24c4cfdac995ec2d44da8ddabab678ef68 100644 (file)
@@ -4788,12 +4788,10 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
    * Test Repeat Transaction Contribution with Tax amount.
    *
    * https://lab.civicrm.org/dev/core/issues/806
-   *
-   * @throws \CRM_Core_Exception
    */
   public function testRepeatContributionWithTaxAmount(): void {
     $this->enableTaxAndInvoicing();
-    $financialType = $this->callAPISuccess('financial_type', 'create', [
+    $financialType = $this->callAPISuccess('FinancialType', 'create', [
       'name' => 'Test taxable financial Type',
       'is_reserved' => 0,
       'is_active' => 1,
@@ -4806,7 +4804,7 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
         'financial_type_id' => $financialType['id'],
       ]
     );
-    $this->callAPISuccess('contribution', 'repeattransaction', [
+    $this->callAPISuccess('Contribution', 'repeattransaction', [
       'original_contribution_id' => $contribution['id'],
       'contribution_status_id' => 'Completed',
       'trxn_id' => 'test',
@@ -4824,9 +4822,21 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
       $this->assertEquals($lineItem['line_total'], $taxExclusiveAmount);
     }
     $this->callAPISuccessGetCount('Contribution', [], 2);
+    $this->callAPISuccess('ContributionRecur', 'create', [
+      'id' => $contribution['contribution_recur_id'],
+      'amount' => 200,
+    ]);
+    $this->callAPISuccess('Contribution', 'repeattransaction', [
+      'original_contribution_id' => $contribution['id'],
+      'contribution_status_id' => 'Completed',
+      'trxn_id' => 'test-2',
+    ]);
+    $contribution = $this->callAPISuccessGetSingle('Contribution', ['sequential' => 1, 'trxn_id' => 'test-2', 'return' => ['total_amount', 'tax_amount']]);
+    $this->assertEquals(200, $contribution['total_amount']);
+    $this->assertEquals(18.18, $contribution['tax_amount']);
   }
 
-  public function testGetCurrencyOptions() {
+  public function testGetCurrencyOptions(): void {
     $result = $this->callAPISuccess('Contribution', 'getoptions', [
       'field' => 'currency',
     ]);