3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
12 use Civi\Api4\ContributionRecur
;
15 * Class CRM_Contribute_BAO_ContributionRecurTest
18 class CRM_Contribute_BAO_ContributionRecurTest
extends CiviUnitTestCase
{
20 use CRMTraits_Financial_OrderTrait
;
22 protected $isValidateFinancialsOnPostAssert = TRUE;
27 * @throws \CiviCRM_API3_Exception
29 public function setUp(): void
{
31 $this->ids
['payment_processor'] = $this->paymentProcessorCreate();
33 'contact_id' => $this->individualCreate(),
35 'frequency_unit' => 'week',
36 'frequency_interval' => 1,
38 'start_date' => 'yesterday',
39 'create_date' => 'yesterday',
40 'modified_date' => 'yesterday',
41 'cancel_date' => NULL,
42 'end_date' => '+ 2 weeks',
43 'processor_id' => '643411460836',
44 'trxn_id' => 'e0d0808e26f3e661c6c18eb7c039d363',
45 'invoice_id' => 'e0d0808e26f3e661c6c18eb7c039d363',
46 'contribution_status_id' => 1,
49 'next_sched_contribution_date' => '+ 1 week',
51 'failure_retry_date' => NULL,
54 'payment_processor_id' => $this->ids
['payment_processor'],
55 'is_email_receipt' => 1,
56 'financial_type_id' => 1,
57 'payment_instrument_id' => 1,
58 'campaign_id' => NULL,
65 * @throws \CRM_Core_Exception
67 public function teardown():void
{
68 $this->quickCleanUpFinancialEntities();
72 * Test that an object can be retrieved & saved (per CRM-14986).
74 * This has been causing a DB error so we are checking for absence of error
76 * @throws \CRM_Core_Exception
78 public function testFindSave(): void
{
79 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params
);
80 $dao = new CRM_Contribute_BAO_ContributionRecur();
81 $dao->id
= $contributionRecur['id'];
83 $dao->is_email_receipt
= 0;
88 * Test cancellation works per CRM-14986.
90 * We are checking for absence of error.
92 * @throws \CRM_Core_Exception
94 public function testCancelRecur(): void
{
95 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params
);
96 CRM_Contribute_BAO_ContributionRecur
::cancelRecurContribution(['id' => $contributionRecur['id']]);
100 * Test checking if contribution recur object can allow for changes to financial types.
102 * @throws \CRM_Core_Exception|\CiviCRM_API3_Exception
104 public function testSupportFinancialTypeChange(): void
{
105 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params
);
106 $this->callAPISuccess('Contribution', 'create', [
107 'contribution_recur_id' => $contributionRecur['id'],
108 'total_amount' => '3.00',
109 'financial_type_id' => 1,
110 'payment_instrument_id' => 1,
112 'contact_id' => $this->individualCreate(),
113 'contribution_status_id' => 1,
114 'receive_date' => 'yesterday',
116 $this->assertTrue(CRM_Contribute_BAO_ContributionRecur
::supportsFinancialTypeChange($contributionRecur['id']));
120 * Test we don't change unintended fields on API edit
122 * @throws \CRM_Core_Exception
124 public function testUpdateRecur(): void
{
125 $createParams = $this->_params
;
126 $createParams['currency'] = 'XAU';
127 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $createParams);
129 'id' => $contributionRecur['id'],
130 'end_date' => '+ 4 weeks',
132 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $editParams);
133 $dao = new CRM_Contribute_BAO_ContributionRecur();
134 $dao->id
= $contributionRecur['id'];
136 $this->assertEquals('XAU', $dao->currency
, 'Edit clobbered recur currency');
140 * Check test contributions aren't picked up as template for non-test recurs
142 * @throws \API_Exception
143 * @throws \CRM_Core_Exception
144 * @throws \CiviCRM_API3_Exception
145 * @throws \Civi\API\Exception\UnauthorizedException
147 public function testGetTemplateContributionMatchTest1(): void
{
148 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params
);
149 // Create a first contrib
150 $firstContrib = $this->callAPISuccess('Contribution', 'create', [
151 'contribution_recur_id' => $contributionRecur['id'],
152 'total_amount' => '3.00',
153 'financial_type_id' => 1,
154 'payment_instrument_id' => 1,
156 'contact_id' => $this->individualCreate(),
157 'contribution_status_id' => 1,
158 'receive_date' => 'yesterday',
160 // Create a test contrib - should not be picked up as template for non-test recur
161 $this->callAPISuccess('Contribution', 'create', [
162 'contribution_recur_id' => $contributionRecur['id'],
163 'total_amount' => '3.00',
164 'financial_type_id' => 1,
165 'payment_instrument_id' => 1,
167 'contact_id' => $this->individualCreate(),
168 'contribution_status_id' => 1,
169 'receive_date' => 'yesterday',
172 $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur
::getTemplateContribution($contributionRecur['id']);
173 $this->assertEquals($firstContrib['id'], $fetchedTemplate['id']);
177 * Check non-test contributions aren't picked up as template for test recurs
179 * @throws \API_Exception
180 * @throws \CRM_Core_Exception
181 * @throws \CiviCRM_API3_Exception
182 * @throws \Civi\API\Exception\UnauthorizedException
184 public function testGetTemplateContributionMatchTest(): void
{
185 $params = $this->_params
;
186 $params['is_test'] = 1;
187 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $params);
188 // Create a first test contrib
189 $firstContrib = $this->callAPISuccess('Contribution', 'create', [
190 'contribution_recur_id' => $contributionRecur['id'],
191 'total_amount' => '3.00',
192 'financial_type_id' => 1,
193 'payment_instrument_id' => 1,
195 'contact_id' => $this->individualCreate(),
196 'contribution_status_id' => 1,
197 'receive_date' => 'yesterday',
200 // Create a non-test contrib - should not be picked up as template for non-test recur
201 // This shouldn't occur - a live contrib against a test recur, but that's not the point...
202 $this->callAPISuccess('Contribution', 'create', [
203 'contribution_recur_id' => $contributionRecur['id'],
204 'total_amount' => '3.00',
205 'financial_type_id' => 1,
206 'payment_instrument_id' => 1,
208 'contact_id' => $this->individualCreate(),
209 'contribution_status_id' => 1,
210 'receive_date' => 'yesterday',
213 $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur
::getTemplateContribution($contributionRecur['id']);
214 $this->assertEquals($firstContrib['id'], $fetchedTemplate['id']);
218 * Check whether template contribution is created based on the first contribution.
220 * There are three contributions created. Each of them with a different value at a custom field.
221 * The first contribution created should be copied as a template contribution.
222 * The other two should not be used as a template.
224 * Then we delete the template contribution and make sure a new one exists.
225 * At that time the second contribution should be used a template as that is the most recent one (according to the date).
227 * @throws \API_Exception
228 * @throws \CRM_Core_Exception
229 * @throws \CiviCRM_API3_Exception
230 * @throws \Civi\API\Exception\UnauthorizedException
232 public function testCreateTemplateContributionFromFirstContributionTest(): void
{
233 $custom_group = $this->customGroupCreate(['extends' => 'Contribution', 'name' => 'template']);
234 $custom_field = $this->customFieldCreate(['custom_group_id' => $custom_group['id'], 'name' => 'field']);
236 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params
);
237 // Create a first test contrib
238 $date = new DateTime();
239 $firstContrib = $this->callAPISuccess('Contribution', 'create', [
240 'contribution_recur_id' => $contributionRecur['id'],
241 'total_amount' => '3.00',
242 'financial_type_id' => 1,
243 'payment_instrument_id' => 1,
245 'contact_id' => $this->_params
['contact_id'],
246 'contribution_status_id' => 1,
247 'receive_date' => $date->format('YmdHis'),
248 'custom_' . $custom_field['id'] => 'First Contribution',
250 $date->modify('+2 days');
251 $secondContrib = $this->callAPISuccess('Contribution', 'create', [
252 'contribution_recur_id' => $contributionRecur['id'],
253 'total_amount' => '3.00',
254 'financial_type_id' => 1,
255 'payment_instrument_id' => 1,
257 'contact_id' => $this->_params
['contact_id'],
258 'contribution_status_id' => 1,
259 'receive_date' => $date->format('YmdHis'),
260 'custom_' . $custom_field['id'] => 'Second and most recent Contribution',
263 $date->modify('-1 week');
264 $thirdContrib = $this->callAPISuccess('Contribution', 'create', [
265 'contribution_recur_id' => $contributionRecur['id'],
266 'total_amount' => '3.00',
267 'financial_type_id' => 1,
268 'payment_instrument_id' => 1,
270 'contact_id' => $this->_params
['contact_id'],
271 'contribution_status_id' => 1,
272 'receive_date' => $date->format('YmdHis'),
273 'custom_' . $custom_field['id'] => 'Third Contribution',
276 // Make sure a template contribution exists.
277 $templateContributionId = CRM_Contribute_BAO_ContributionRecur
::ensureTemplateContributionExists($contributionRecur['id']);
278 $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur
::getTemplateContribution($contributionRecur['id']);
279 $templateContribution = \Civi\Api4\Contribution
::get(FALSE)
280 ->addSelect('*', 'custom.*')
281 ->addWhere('contribution_recur_id', '=', $contributionRecur['id'])
282 ->addWhere('is_template', '=', 1)
283 ->addWhere('is_test', '=', 0)
284 ->addOrderBy('id', 'DESC')
287 $this->assertNotEquals($firstContrib['id'], $fetchedTemplate['id']);
288 $this->assertNotEquals($secondContrib['id'], $fetchedTemplate['id']);
289 $this->assertNotEquals($thirdContrib['id'], $fetchedTemplate['id']);
290 $this->assertEquals($templateContributionId, $fetchedTemplate['id']);
291 $this->assertTrue($fetchedTemplate['is_template']);
292 $this->assertFalse($fetchedTemplate['is_test']);
293 $this->assertEquals(1, $templateContribution->count());
294 $templateContribution = $templateContribution->first();
295 $this->assertNotNull($templateContribution['template.field']);
296 $this->assertEquals('Second and most recent Contribution', $templateContribution['template.field']);
297 $this->callAPISuccess('CustomField', 'delete', ['id' => $custom_field['id']]);
298 $this->callAPISuccess('CustomGroup', 'delete', ['id' => $custom_group['id']]);
302 * Test that is_template contribution is used where available
304 * @throws \API_Exception
305 * @throws \CiviCRM_API3_Exception
306 * @throws \Civi\API\Exception\UnauthorizedException
308 public function testGetTemplateContributionNewTemplate(): void
{
309 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params
);
310 // Create the template
311 $templateContrib = $this->callAPISuccess('Contribution', 'create', [
312 'contribution_recur_id' => $contributionRecur['id'],
313 'total_amount' => '3.00',
314 'financial_type_id' => 1,
315 'source' => 'Template Contribution',
316 'payment_instrument_id' => 1,
318 'contact_id' => $this->individualCreate(),
319 'contribution_status_id' => 1,
320 'receive_date' => 'yesterday',
323 // Create another normal contrib
324 $this->callAPISuccess('Contribution', 'create', [
325 'contribution_recur_id' => $contributionRecur['id'],
326 'total_amount' => '3.00',
327 'financial_type_id' => 1,
328 'source' => 'Non-template Contribution',
329 'payment_instrument_id' => 1,
331 'contact_id' => $this->individualCreate(),
332 'contribution_status_id' => 1,
333 'receive_date' => 'yesterday',
335 $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur
::getTemplateContribution($contributionRecur['id']);
336 // Fetched template should be the is_template, not the latest contrib
337 $this->assertEquals($fetchedTemplate['id'], $templateContrib['id']);
339 $repeatContribution = $this->callAPISuccess('Contribution', 'repeattransaction', [
340 'contribution_status_id' => 'Completed',
341 'contribution_recur_id' => $contributionRecur['id'],
343 $this->assertEquals('Template Contribution', $repeatContribution['values'][$repeatContribution['id']]['source']);
344 $this->assertEquals('AUD', $repeatContribution['values'][$repeatContribution['id']]['currency']);
348 * Test to check if correct membership is auto renewed.
350 * @throws \CRM_Core_Exception|\CiviCRM_API3_Exception
352 public function testAutoRenewalWhenOneMemberIsDeceased(): void
{
353 $contactId1 = $this->individualCreate();
354 $contactId2 = $this->individualCreate();
355 $membershipOrganizationId = $this->organizationCreate();
357 $this->createExtraneousContribution();
358 $this->callAPISuccess('Contribution', 'create', [
359 'contact_id' => $contactId1,
360 'receive_date' => '2010-01-20',
361 'financial_type_id' => 'Member Dues',
362 'contribution_status_id' => 'Completed',
363 'total_amount' => 150,
366 // create membership type
367 $membershipTypeId1 = (int) $this->callAPISuccess('MembershipType', 'create', [
369 'member_of_contact_id' => $membershipOrganizationId,
370 'financial_type_id' => 'Member Dues',
371 'duration_unit' => 'month',
372 'duration_interval' => 1,
373 'period_type' => 'rolling',
374 'minimum_fee' => 100,
378 $membershipTypeID = (int) $this->callAPISuccess('MembershipType', 'create', [
380 'member_of_contact_id' => $membershipOrganizationId,
381 'financial_type_id' => 'Member Dues',
382 'duration_unit' => 'month',
383 'duration_interval' => 1,
384 'period_type' => 'rolling',
390 $contactId1 => $membershipTypeId1,
391 $contactId2 => $membershipTypeID,
394 $contributionRecurId = $this->callAPISuccess('contribution_recur', 'create', $this->_params
)['id'];
396 $priceFields = CRM_Price_BAO_PriceSet
::getDefaultPriceSet('membership');
398 // prepare order api params.
400 'contact_id' => $contactId1,
401 'receive_date' => '2010-01-20',
402 'financial_type_id' => 'Member Dues',
403 'contribution_recur_id' => $contributionRecurId,
404 'total_amount' => 150,
405 'api.Payment.create' => ['total_amount' => 150],
408 foreach ($priceFields as $priceField) {
410 $contactId = array_search((int) $priceField['membership_type_id'], $contactIDs, TRUE);
412 'price_field_id' => $priceField['priceFieldID'],
413 'price_field_value_id' => $priceField['priceFieldValueID'],
414 'label' => $priceField['label'],
415 'field_title' => $priceField['label'],
417 'unit_price' => $priceField['amount'],
418 'line_total' => $priceField['amount'],
419 'financial_type_id' => $priceField['financial_type_id'],
420 'entity_table' => 'civicrm_membership',
421 'membership_type_id' => $priceField['membership_type_id'],
423 $params['line_items'][] = [
424 'line_item' => $lineItems,
426 'contact_id' => $contactId,
427 'membership_type_id' => $priceField['membership_type_id'],
428 'source' => 'Payment',
429 'join_date' => date('Y-m', strtotime('1 month ago')) . '-28',
430 'start_date' => date('Y-m') . '-28',
431 'contribution_recur_id' => $contributionRecurId,
432 'status_id' => 'Pending',
437 $order = $this->callAPISuccess('Order', 'create', $params);
438 $contributionId = $order['id'];
439 $membershipId1 = $this->callAPISuccessGetValue('Membership', [
440 'contact_id' => $contactId1,
441 'membership_type_id' => $membershipTypeId1,
445 $membershipId2 = $this->callAPISuccessGetValue('Membership', [
446 'contact_id' => $contactId2,
447 'membership_type_id' => $membershipTypeID,
451 // First renewal (2nd payment).
452 $this->callAPISuccess('Contribution', 'repeattransaction', [
453 'original_contribution_id' => $contributionId,
454 'contribution_status_id' => 'Completed',
457 // Second Renewal (3rd payment).
458 $this->callAPISuccess('Contribution', 'repeattransaction', [
459 'original_contribution_id' => $contributionId,
460 'contribution_status_id' => 'Completed',
463 // Third renewal (4th payment).
464 $this->callAPISuccess('Contribution', 'repeattransaction', ['original_contribution_id' => $contributionId, 'contribution_status_id' => 'Completed']);
466 // check line item and membership payment count.
467 $this->validateAllCounts($membershipId1, 4);
468 $this->validateAllCounts($membershipId2, 4);
470 $expectedDate = $this->getYearAndMonthFromOffset(4);
471 // check membership end date.
472 foreach ([$membershipId1, $membershipId2] as $mId) {
473 $endDate = $this->callAPISuccessGetValue('Membership', [
475 'return' => 'end_date',
477 $this->assertEquals("{$expectedDate['year']}-{$expectedDate['month']}-27", $endDate, ts('End date incorrect.'));
480 // At this moment Contact 2 is deceased, but we wait until payment is recorded in civi before marking the contact deceased.
481 // At payment Gateway we update the amount from 150 to 100
482 // IPN is recorded for subsequent payment (5th payment).
483 $contribution = $this->callAPISuccess('Contribution', 'repeattransaction', [
484 'original_contribution_id' => $contributionId,
485 'contribution_status_id' => 'Completed',
486 'total_amount' => '100',
489 // now we mark the contact2 as deceased.
490 $this->callAPISuccess('Contact', 'create', [
495 // set membership recurring to null.
496 $this->callAPISuccess('Membership', 'create', [
497 'id' => $membershipId2,
498 'contribution_recur_id' => NULL,
501 $this->callAPISuccess('Contribution', 'delete', ['id' => $contribution['id']]);
502 unset($params['line_items'][1]);
503 $params['total_amount'] = 100;
504 $params['line_items'][0]['params']['id'] = $membershipId1;
505 $params['api.Payment.create']['total_amount'] = 100;
507 $order = $this->callAPISuccess('Order', 'create', $params);
509 // check line item and membership payment count.
510 $this->validateAllCounts($membershipId1, 5);
511 $this->validateAllCounts($membershipId2, 4);
513 $checkAgainst = $this->callAPISuccessGetSingle('Membership', [
514 'id' => $membershipId2,
515 'return' => ['end_date', 'status_id'],
518 // record next subsequent payment (6th payment).
519 $this->callAPISuccess('Contribution', 'repeattransaction', [
520 'original_contribution_id' => $order['id'],
521 'contribution_status_id' => 'Completed',
522 'total_amount' => '100',
525 // check membership id 1 is renewed
526 $endDate = $this->callAPISuccessGetValue('Membership', [
527 'id' => $membershipId1,
528 'return' => 'end_date',
530 $expectedDate = $this->getYearAndMonthFromOffset(6);
531 $this->assertEquals("{$expectedDate['year']}-{$expectedDate['month']}-27", $endDate, ts('End date incorrect.'));
532 // check line item and membership payment count.
533 $this->validateAllCounts($membershipId1, 6);
534 $this->validateAllCounts($membershipId2, 4);
536 // check if membership status and end date is not changed.
537 $membership2 = $this->callAPISuccessGetSingle('Membership', [
538 'id' => $membershipId2,
539 'return' => ['end_date', 'status_id'],
541 $this->assertSame($membership2, $checkAgainst);
545 * Check line item and membership payment count.
547 * @param int $membershipId
550 * @throws \CRM_Core_Exception
552 public function validateAllCounts(int $membershipId, int $count): void
{
554 'membership_id' => $membershipId,
557 'entity_id' => $membershipId,
558 'entity_table' => 'civicrm_membership',
559 'contribution_id' => ['>' => 0],
561 $this->callAPISuccessGetCount('LineItem', $lineItemParams, $count);
562 $this->callAPISuccessGetCount('MembershipPayment', $memPayParams, $count);
566 * Given a number of months offset, get the year and month.
567 * Note the way php arithmetic works, using strtotime('+x months') doesn't
568 * work because it will roll over the day accounting for different number
569 * of days in the month, but we want the same day of the month, x months
571 * e.g. July 31 + 4 months will return Dec 1 if using php functions, but
575 * @param int|null $year Optional input year to start
576 * @param int|null $month Optional input month to start
579 * ['year' => int, 'month' => int]
581 private function getYearAndMonthFromOffset(int $offset, int $year = NULL, int $month = NULL): array {
583 'year' => $year ??
(int) date('Y'),
584 'month' => ($month ??
(int) date('m')) +
$offset,
586 if ($dateInfo['month'] > 12) {
588 $dateInfo['month'] -= 12;
590 if ($dateInfo['month'] < 10) {
591 $dateInfo['month'] = "0{$dateInfo['month']}";
598 * Test getYearAndMonthFromOffset
600 * @dataProvider yearMonthProvider
602 * @param array $input
603 * @param array $expected
605 public function testGetYearAndMonthFromOffset(array $input, array $expected): void
{
606 $this->assertEquals($expected, $this->getYearAndMonthFromOffset($input[0], $input[1], $input[2]));
610 * data provider for testGetYearAndMonthFromOffset
612 public function yearMonthProvider(): array {
614 // input = offset, year, current month
615 ['input' => [4, 2020, 1], 'output' => ['year' => '2020', 'month' => '05']],
616 ['input' => [6, 2020, 1], 'output' => ['year' => '2020', 'month' => '07']],
617 ['input' => [4, 2020, 2], 'output' => ['year' => '2020', 'month' => '06']],
618 ['input' => [6, 2020, 2], 'output' => ['year' => '2020', 'month' => '08']],
619 ['input' => [4, 2020, 3], 'output' => ['year' => '2020', 'month' => '07']],
620 ['input' => [6, 2020, 3], 'output' => ['year' => '2020', 'month' => '09']],
621 ['input' => [4, 2020, 4], 'output' => ['year' => '2020', 'month' => '08']],
622 ['input' => [6, 2020, 4], 'output' => ['year' => '2020', 'month' => '10']],
623 ['input' => [4, 2020, 5], 'output' => ['year' => '2020', 'month' => '09']],
624 ['input' => [6, 2020, 5], 'output' => ['year' => '2020', 'month' => '11']],
625 ['input' => [4, 2020, 6], 'output' => ['year' => '2020', 'month' => '10']],
626 ['input' => [6, 2020, 6], 'output' => ['year' => '2020', 'month' => '12']],
627 ['input' => [4, 2020, 7], 'output' => ['year' => '2020', 'month' => '11']],
628 ['input' => [6, 2020, 7], 'output' => ['year' => '2021', 'month' => '01']],
629 ['input' => [4, 2020, 8], 'output' => ['year' => '2020', 'month' => '12']],
630 ['input' => [6, 2020, 8], 'output' => ['year' => '2021', 'month' => '02']],
631 ['input' => [4, 2020, 9], 'output' => ['year' => '2021', 'month' => '01']],
632 ['input' => [6, 2020, 9], 'output' => ['year' => '2021', 'month' => '03']],
633 ['input' => [4, 2020, 10], 'output' => ['year' => '2021', 'month' => '02']],
634 ['input' => [6, 2020, 10], 'output' => ['year' => '2021', 'month' => '04']],
635 ['input' => [4, 2020, 11], 'output' => ['year' => '2021', 'month' => '03']],
636 ['input' => [6, 2020, 11], 'output' => ['year' => '2021', 'month' => '05']],
637 ['input' => [4, 2020, 12], 'output' => ['year' => '2021', 'month' => '04']],
638 ['input' => [6, 2020, 12], 'output' => ['year' => '2021', 'month' => '06']],
643 * Test Recurring Contribution Email Receipt Flag
645 * @throws \CRM_Core_Exception
647 public function testContributionEmailReceipt(): void
{
648 $createParams = $this->_params
;
649 unset($createParams['trxn_id'], $createParams['invoice_id']);
651 // pass null value to is_email_receipt
652 $createParams['is_email_receipt'] = NULL;
653 $recurring1 = $this->callAPISuccess('ContributionRecur', 'create', $createParams);
654 $recurring1Get = $this->callAPISuccess('ContributionRecur', 'getsingle', ['id' => $recurring1['id']]);
655 // default is_email_receipt column value is 1
656 $this->assertEquals('1', $recurring1Get['is_email_receipt']);
658 // pass empty value to is_email_receipt
659 $createParams['is_email_receipt'] = '';
660 $recurring2 = $this->callAPISuccess('ContributionRecur', 'create', $createParams);
661 $recurring2 = ContributionRecur
::get(FALSE)->addWhere('id', '=', $recurring2['id'])->addSelect('is_email_receipt')->execute()->first();
662 $this->assertEquals(NULL, $recurring2['is_email_receipt']);
664 // Pass 0 value to is_email_receipt.
665 $createParams['is_email_receipt'] = 0;
666 $recurring3 = $this->callAPISuccess('ContributionRecur', 'create', $createParams);
667 $recurring3Get = $this->callAPISuccess('ContributionRecur', 'getsingle', ['id' => $recurring3['id']]);
668 $this->assertEquals('0', $recurring3Get['is_email_receipt']);