Line items are added from default price set on recurring contributions for financial types with tax accounts.
Steps to reproduce, verified on dmaster.demo.civicrm.org
- Create a Membership type with required autorenewal
- Enable Tax & Invoicing
- Create a Sales Tax account, at any rate, and assign it to the "Member Dues" Financial type.
- Configure a Contribution Page to sign up for the membership, using the "Member Dues" Financial type.
- Sign up for a membership using the Contribution page.
- Using the created recurring contribution id, call the Contribution.repeattransaction API to simulate the membership autorenewal like a payment processor supporting recurring contributions
- Inspect the resulting contribution records using the Order.get API
Expected Results
Two orders that are identical apart from dates and IDs
Actual Results
The second order has two line items. The second line item will be for the price field in the default price set (field 1 / set 1 unless you've somehow changed it), and will be for the same amount as the total of the contribution.
On additional attempts to repeat the transaction, the system crashes due to a DB constraint violation and rolls back the database transaction, losing the records of any contributions processed so far.
Why does this happen?
When CRM_Contribute_BAO_Contribution::add
calls CRM_Contribute_BAO_Contribution::checkTaxAmount
, this method checks if the financial type has tax applied and calls CRM_Price_BAO_LineItem::getLineItemArray
if so, regardless of whether there are any line items already.
Proposed Solution
Move the calls to CRM_Price_BAO_LineItem::getLineItemArray
out of CRM_Contribute_BAO_Contribution::checkTaxAmount
and into CRM_Contribute_BAO_Contribution::add
, and only call it if there's no line_item array present already. See discussion at https://chat.civicrm.org/civicrm/pl/9iuqyx9fp3dexnupuxfefsj4ke
Agileware Ref: CIVICRM-1617