Skip to content

Instantly share code, notes, and snippets.

@christianwach
Last active May 6, 2021 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christianwach/ac8e8460c7f488a9a31f30a2c74eefc6 to your computer and use it in GitHub Desktop.
Save christianwach/ac8e8460c7f488a9a31f30a2c74eefc6 to your computer and use it in GitHub Desktop.
Order API & Payment API mismatches
Using CiviCRM Sample Data (where "financial_type_id=5" is a Taxable Financial Type and "financial_type_id=2" is not)
Call Order.create with these params:
[params] => Array
(
[contact_id] => 206
[financial_type_id] => 5 <----- Taxable Financial Type.
[payment_instrument_id] => 4
[trxn_id] => WooCommerce Order - 1859
[invoice_id] => 1859_woocommerce
[receive_date] => 2021-05-05 23:24:02
[contribution_status_id] => Pending
[total_amount] => 109.69 <----- Total amount includes tax.
[tax_amount] => 9.69 <----- Taxable part of total.
[source] => Shop
[campaign_id] => 3
[note] => Fundraiser Dinner Ticket x 1, Student Membership x 1
[line_items] => Array
(
[20] => Array
(
[line_item] => Array
(
[0] => Array
(
[price_field_id] => 1
[unit_price] => 50.00
[qty] => 1
[line_total] => 50.00
[tax_amount] => 9.69
[label] => Fundraiser Dinner Ticket
[financial_type_id] => 5 <----- Taxable Financial Type.
)
)
)
[21] => Array
(
[params] => Array
(
[membership_type_id] => 2
[source] => Shop
[contact_id] => 206
[skipStatusCal] => 1
[status_id] => Pending
)
[line_item] => Array
(
[0] => Array
(
[price_field_id] => 1
[unit_price] => 50.00
[qty] => 1
[line_total] => 50.00
[tax_amount] => 0.00
[label] => Student Membership
[financial_type_id] => 2 <----- Non-taxable Financial Type.
[entity_table] => civicrm_membership
[membership_type_id] => 2
)
)
)
)
)
The result returned by the API call looks good:
[result] => Array
(
[is_error] => 0
[version] => 3
[count] => 1
[id] => 104
[values] => Array
(
[104] => Array
(
[id] => 104
[contact_id] => 206
[financial_type_id] => 5 <----- Taxable Financial Type.
[contribution_page_id] =>
[payment_instrument_id] => 4
[receive_date] => 20210505232402
[non_deductible_amount] =>
[total_amount] => 109.69 <----- Okay.
[fee_amount] => 0
[net_amount] => 109.69 <----- Okay.
[trxn_id] => WooCommerce Order - 1859
[invoice_id] => 1859_woocommerce
[invoice_number] => INV_104
[currency] => USD
[cancel_date] =>
[cancel_reason] =>
[receipt_date] =>
[thankyou_date] =>
[source] => Shop
[amount_level] =>
[contribution_recur_id] =>
[is_test] =>
[is_pay_later] =>
[contribution_status_id] => 2
[address_id] =>
[check_number] =>
[campaign_id] => 3
[creditnote_id] =>
[tax_amount] => 9.69 <----- Okay.
[revenue_recognition_date] =>
[is_template] =>
[contribution_type_id] => 5
)
)
)
Now do a trivial update to the Contribution, e.g. the Source:
$result = civicrm_api3('Contribution', 'create', [
'financial_type_id' => 5, // Happens to be a Taxable Financial Type but need not be.
'contact_id' => 206,
'id' => 103,
'source' => "Something",
]);
Retrieve Contribution via API Explorer.
The "total_amount" and "net_amount" have been recalculated.
(The "tax_amount" and "financial_type_id" are missing in API3 but not API4.)
{
"is_error": 0,
"version": 3,
"count": 1,
"id": 104,
"values": [
{
"contact_id": "206",
"contribution_id": "104",
"currency": "USD",
"contribution_recur_id": "",
"contribution_status_id": "2",
"contribution_campaign_id": "1",
"payment_instrument_id": "4",
"receive_date": "2021-05-05 23:24:02",
"non_deductible_amount": "0.00",
"total_amount": "119.38", <----- This seems to have been recalculated. Where is "tax_amount"?
"fee_amount": "0.00",
"net_amount": "100.00", <----- This seems to have been recalculated.
"trxn_id": "WooCommerce Order - 1859",
"invoice_id": "1859_woocommerce",
"invoice_number": "INV_104",
"contribution_cancel_date": "",
"cancel_reason": "",
"receipt_date": "",
"thankyou_date": "",
"contribution_source": "Shop",
"amount_level": "",
"is_test": "0",
"is_pay_later": "0",
"contribution_check_number": "",
"civicrm_value_donor_information_3_id": "12",
"custom_6": "",
"custom_5": "",
"contribution_recur_status": "Pending",
"payment_instrument": "Check",
"contribution_status": "Pending",
"check_number": "",
"instrument_id": "4",
"cancel_date": "",
"id": "104"
}
]
}
Doesn't seem right. So, what's raw data?
mysql> SELECT `financial_type_id`, `total_amount`, `fee_amount`, `net_amount`, `tax_amount` FROM `civicrm_contribution` WHERE id = '104';
+-------------------+--------------+------------+------------+------------+
| financial_type_id | total_amount | fee_amount | net_amount | tax_amount |
+-------------------+--------------+------------+------------+------------+
| 5 | 119.38 | 0.00 | 100.00 | 19.38 |
+-------------------+--------------+------------+------------+------------+
Yup, confirms recalculation.
Now check the Line Items via the API Explorer.
The non-taxable Line Item now has (total Tax x 2) added.
{
"is_error": 0,
"version": 3,
"count": 2,
"values": [
{
"id": "107",
"entity_table": "civicrm_membership",
"entity_id": "34",
"contribution_id": "104",
"price_field_id": "1",
"label": "Fundraiser Dinner Ticket",
"qty": "1.00",
"unit_price": "50.00",
"line_total": "50.00", <----- Okay.
"financial_type_id": "5", <----- Taxable Financial Type.
"non_deductible_amount": "0.00",
"tax_amount": "9.69", <----- Okay.
"contribution_type_id": "5"
},
{
"id": "108",
"entity_table": "civicrm_membership",
"entity_id": "34",
"contribution_id": "104",
"price_field_id": "1",
"label": "Student Membership",
"qty": "1.00",
"unit_price": "50.00",
"line_total": "50.00", <----- Okay.
"financial_type_id": "2", <----- Non-taxable Financial Type.
"non_deductible_amount": "0.00",
"tax_amount": "19.38", <----- Uh oh.
"contribution_type_id": "2"
}
]
}
Error confirmed in database:
mysql> select `financial_type_id`, `line_total`, `unit_price`, `tax_amount` FROM civicrm_line_item WHERE contribution_id = '104';
+-------------------+------------+------------+------------+
| financial_type_id | line_total | unit_price | tax_amount |
+-------------------+------------+------------+------------+
| 5 | 50.00 | 50.00 | 9.69 |
| 2 | 50.00 | 50.00 | 19.38 |
+-------------------+------------+------------+------------+
Using CiviCRM Sample Data (where "financial_type_id=5" is a Taxable Financial Type and "financial_type_id=2" is not)
Call Order.create with these params:
[params] => Array
(
[contact_id] => 208
[financial_type_id] => 2 <----- Non-taxable Financial Type.
[payment_instrument_id] => 4
[trxn_id] => WooCommerce Order - 1861
[invoice_id] => 1861_woocommerce
[receive_date] => 2021-05-06 08:48:53
[contribution_status_id] => Pending
[total_amount] => 109.69 <----- Total amount includes tax.
[tax_amount] => 9.69 <----- Taxable part of total.
[source] => Shop
[campaign_id] => 3
[note] => Fundraiser Dinner Ticket x 1, Student Membership x 1
[line_items] => Array
(
[26] => Array
(
[line_item] => Array
(
[0] => Array
(
[price_field_id] => 1
[unit_price] => 50.00
[qty] => 1
[line_total] => 50.00
[tax_amount] => 9.69
[label] => Fundraiser Dinner Ticket
[financial_type_id] => 5 <----- Taxable Financial Type.
)
)
)
[27] => Array
(
[params] => Array
(
[membership_type_id] => 2
[source] => Shop
[contact_id] => 208
[skipStatusCal] => 1
[status_id] => Pending
)
[line_item] => Array
(
[0] => Array
(
[price_field_id] => 1
[unit_price] => 50.00
[qty] => 1
[line_total] => 50.00
[tax_amount] => 0.00
[label] => Student Membership
[financial_type_id] => 2 <----- Non-taxable Financial Type.
[entity_table] => civicrm_membership
[membership_type_id] => 2
)
)
)
)
)
The result returned by the API call looks good:
[result] => Array
(
[is_error] => 0
[version] => 3
[count] => 1
[id] => 106
[values] => Array
(
[106] => Array
(
[id] => 106
[contact_id] => 208
[financial_type_id] => 2 <----- Non-taxable Financial Type.
[contribution_page_id] =>
[payment_instrument_id] => 4
[receive_date] => 20210506084853
[non_deductible_amount] =>
[total_amount] => 109.69 <----- Okay.
[fee_amount] => 0
[net_amount] => 109.69 <----- Okay.
[trxn_id] => WooCommerce Order - 1861
[invoice_id] => 1861_woocommerce
[invoice_number] => INV_106
[currency] => USD
[cancel_date] =>
[cancel_reason] =>
[receipt_date] =>
[thankyou_date] =>
[source] => Shop
[amount_level] =>
[contribution_recur_id] =>
[is_test] =>
[is_pay_later] =>
[contribution_status_id] => 2
[address_id] =>
[check_number] =>
[campaign_id] => 3
[creditnote_id] =>
[tax_amount] => 9.69 <----- Okay.
[revenue_recognition_date] =>
[is_template] =>
[contribution_type_id] => 2
)
)
)
Now do a trivial update to the Contribution, e.g. the Source:
$result = civicrm_api3('Contribution', 'create', [
'financial_type_id' => 2, // Happens to be a Non-taxable Financial Type but need not be.
'contact_id' => 206,
'id' => 103,
'source' => "Something",
]);
Retrieve Contribution via API Explorer.
The "total_amount" and "net_amount" have been recalculated to exclude the Tax.
(The "tax_amount" and "financial_type_id" are missing in API3 but not API4.)
{
"is_error": 0,
"version": 3,
"count": 1,
"id": 106,
"values": [
{
"contact_id": "208",
"contribution_id": "106",
"currency": "USD",
"contribution_recur_id": "",
"contribution_status_id": "2",
"contribution_campaign_id": "1",
"payment_instrument_id": "4",
"receive_date": "2021-05-06 08:48:53",
"non_deductible_amount": "0.00",
"total_amount": "100.00", <----- This seems to have been recalculated. Where is "tax_amount"?
"fee_amount": "0.00",
"net_amount": "100.00", <----- This seems to have been recalculated.
"trxn_id": "WooCommerce Order - 1861",
"invoice_id": "1861_woocommerce",
"invoice_number": "INV_106",
"contribution_cancel_date": "",
"cancel_reason": "",
"receipt_date": "",
"thankyou_date": "",
"contribution_source": "Shop",
"amount_level": "",
"is_test": "0",
"is_pay_later": "0",
"contribution_check_number": "",
"civicrm_value_donor_information_3_id": "16",
"custom_6": "",
"custom_5": "",
"contribution_recur_status": "Pending",
"payment_instrument": "Check",
"contribution_status": "Pending",
"check_number": "",
"instrument_id": "4",
"cancel_date": "",
"id": "106"
}
]
}
Doesn't seem right. So, what's raw data?
mysql> SELECT `financial_type_id`, `total_amount`, `fee_amount`, `net_amount`, `tax_amount` FROM `civicrm_contribution` WHERE id = '106';
+-------------------+--------------+------------+------------+------------+
| financial_type_id | total_amount | fee_amount | net_amount | tax_amount |
+-------------------+--------------+------------+------------+------------+
| 2 | 100.00 | 0.00 | 100.00 | NULL |
+-------------------+--------------+------------+------------+------------+
Yup, confirms recalculation.
Now check the Line Items via the API Explorer:
{
"is_error": 0,
"version": 3,
"count": 2,
"values": [
{
"id": "111",
"entity_table": "civicrm_membership",
"entity_id": "36",
"contribution_id": "106",
"price_field_id": "1",
"label": "Fundraiser Dinner Ticket",
"qty": "1.00",
"unit_price": "50.00",
"line_total": "50.00", <----- Okay.
"financial_type_id": "5", <----- Taxable Financial Type.
"non_deductible_amount": "0.00",
"tax_amount": "9.69", <----- Okay.
"contribution_type_id": "5"
},
{
"id": "112",
"entity_table": "civicrm_membership",
"entity_id": "36",
"contribution_id": "106",
"price_field_id": "1",
"label": "Student Membership",
"qty": "1.00",
"unit_price": "50.00",
"line_total": "50.00", <----- Okay.
"financial_type_id": "2", <----- Non-taxable Financial Type.
"non_deductible_amount": "0.00",
"tax_amount": "0.00", <----- Okay.
"contribution_type_id": "2"
}
]
}
Line Item data integrity confirmed:
mysql> select `financial_type_id`, `line_total`, `unit_price`, `tax_amount` FROM civicrm_line_item WHERE contribution_id = '106';
+-------------------+------------+------------+------------+
| financial_type_id | line_total | unit_price | tax_amount |
+-------------------+------------+------------+------------+
| 5 | 50.00 | 50.00 | 9.69 |
| 2 | 50.00 | 50.00 | 0.00 |
+-------------------+------------+------------+------------+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment