+--------------------------------------------------------------------+
*/
+use Civi\Api4\ContributionRecur;
+
/**
* Class CRM_Contribute_BAO_ContributionRecurTest
* @group headless
use CRMTraits_Financial_OrderTrait;
+ protected $isValidateFinancialsOnPostAssert = TRUE;
+
/**
* Set up for test.
*
- * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
- public function setUp() {
+ public function setUp(): void {
parent::setUp();
- $this->_ids['payment_processor'] = $this->paymentProcessorCreate();
+ $this->ids['payment_processor'] = $this->paymentProcessorCreate();
$this->_params = [
'contact_id' => $this->individualCreate(),
'amount' => 3.00,
'failure_retry_date' => NULL,
'auto_renew' => 0,
'currency' => 'USD',
- 'payment_processor_id' => $this->_ids['payment_processor'],
+ 'payment_processor_id' => $this->ids['payment_processor'],
'is_email_receipt' => 1,
'financial_type_id' => 1,
'payment_instrument_id' => 1,
*
* @throws \CRM_Core_Exception
*/
- public function teardown() {
+ public function teardown():void {
$this->quickCleanUpFinancialEntities();
}
*
* @throws \CRM_Core_Exception
*/
- public function testFindSave() {
+ public function testFindSave(): void {
$contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params);
$dao = new CRM_Contribute_BAO_ContributionRecur();
$dao->id = $contributionRecur['id'];
*
* @throws \CRM_Core_Exception
*/
- public function testCancelRecur() {
+ public function testCancelRecur(): void {
$contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params);
CRM_Contribute_BAO_ContributionRecur::cancelRecurContribution(['id' => $contributionRecur['id']]);
}
/**
* Test checking if contribution recur object can allow for changes to financial types.
*
- * @throws \CRM_Core_Exception
+ * @throws \CRM_Core_Exception|\CiviCRM_API3_Exception
*/
- public function testSupportFinancialTypeChange() {
+ public function testSupportFinancialTypeChange(): void {
$contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params);
$this->callAPISuccess('Contribution', 'create', [
'contribution_recur_id' => $contributionRecur['id'],
*
* @throws \CRM_Core_Exception
*/
- public function testUpdateRecur() {
+ public function testUpdateRecur(): void {
$createParams = $this->_params;
$createParams['currency'] = 'XAU';
$contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $createParams);
* @throws \CiviCRM_API3_Exception
* @throws \Civi\API\Exception\UnauthorizedException
*/
- public function testGetTemplateContributionMatchTest1() {
+ public function testGetTemplateContributionMatchTest1(): void {
$contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params);
// Create a first contrib
$firstContrib = $this->callAPISuccess('Contribution', 'create', [
* @throws \CiviCRM_API3_Exception
* @throws \Civi\API\Exception\UnauthorizedException
*/
- public function testGetTemplateContributionMatchTest() {
+ public function testGetTemplateContributionMatchTest(): void {
$params = $this->_params;
$params['is_test'] = 1;
$contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $params);
}
/**
- * Test that is_template contribution is used where available
+ * Check whether template contribution is created based on the first contribution.
+ *
+ * There are three contributions created. Each of them with a different value at a custom field.
+ * The first contribution created should be copied as a template contribution.
+ * The other two should not be used as a template.
+ *
+ * Then we delete the template contribution and make sure a new one exists.
+ * At that time the second contribution should be used a template as that is the most recent one (according to the date).
*
* @throws \API_Exception
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
* @throws \Civi\API\Exception\UnauthorizedException
*/
- public function testGetTemplateContributionNewTemplate() {
+ public function testCreateTemplateContributionFromFirstContributionTest(): void {
+ $custom_group = $this->customGroupCreate(['extends' => 'Contribution', 'name' => 'template']);
+ $custom_field = $this->customFieldCreate(['custom_group_id' => $custom_group['id'], 'name' => 'field']);
+
+ $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params);
+ // Create a first test contrib
+ $date = new DateTime();
+ $firstContrib = $this->callAPISuccess('Contribution', 'create', [
+ 'contribution_recur_id' => $contributionRecur['id'],
+ 'total_amount' => '3.00',
+ 'financial_type_id' => 1,
+ 'payment_instrument_id' => 1,
+ 'currency' => 'USD',
+ 'contact_id' => $this->_params['contact_id'],
+ 'contribution_status_id' => 1,
+ 'receive_date' => $date->format('YmdHis'),
+ 'custom_' . $custom_field['id'] => 'First Contribution',
+ ]);
+ $date->modify('+2 days');
+ $secondContrib = $this->callAPISuccess('Contribution', 'create', [
+ 'contribution_recur_id' => $contributionRecur['id'],
+ 'total_amount' => '3.00',
+ 'financial_type_id' => 1,
+ 'payment_instrument_id' => 1,
+ 'currency' => 'USD',
+ 'contact_id' => $this->_params['contact_id'],
+ 'contribution_status_id' => 1,
+ 'receive_date' => $date->format('YmdHis'),
+ 'custom_' . $custom_field['id'] => 'Second and most recent Contribution',
+ ]);
+
+ $date->modify('-1 week');
+ $thirdContrib = $this->callAPISuccess('Contribution', 'create', [
+ 'contribution_recur_id' => $contributionRecur['id'],
+ 'total_amount' => '3.00',
+ 'financial_type_id' => 1,
+ 'payment_instrument_id' => 1,
+ 'currency' => 'USD',
+ 'contact_id' => $this->_params['contact_id'],
+ 'contribution_status_id' => 1,
+ 'receive_date' => $date->format('YmdHis'),
+ 'custom_' . $custom_field['id'] => 'Third Contribution',
+ ]);
+
+ // Make sure a template contribution exists.
+ $templateContributionId = CRM_Contribute_BAO_ContributionRecur::ensureTemplateContributionExists($contributionRecur['id']);
+ $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecur['id']);
+ $templateContribution = \Civi\Api4\Contribution::get(FALSE)
+ ->addSelect('*', 'custom.*')
+ ->addWhere('contribution_recur_id', '=', $contributionRecur['id'])
+ ->addWhere('is_template', '=', 1)
+ ->addWhere('is_test', '=', 0)
+ ->addOrderBy('id', 'DESC')
+ ->execute();
+
+ $this->assertNotEquals($firstContrib['id'], $fetchedTemplate['id']);
+ $this->assertNotEquals($secondContrib['id'], $fetchedTemplate['id']);
+ $this->assertNotEquals($thirdContrib['id'], $fetchedTemplate['id']);
+ $this->assertEquals($templateContributionId, $fetchedTemplate['id']);
+ $this->assertTrue($fetchedTemplate['is_template']);
+ $this->assertFalse($fetchedTemplate['is_test']);
+ $this->assertEquals(1, $templateContribution->count());
+ $templateContribution = $templateContribution->first();
+ $this->assertNotNull($templateContribution['template.field']);
+ $this->assertEquals('Second and most recent Contribution', $templateContribution['template.field']);
+ }
+
+ /**
+ * Test that is_template contribution is used where available
+ *
+ * @throws \API_Exception
+ * @throws \CiviCRM_API3_Exception
+ * @throws \Civi\API\Exception\UnauthorizedException
+ */
+ public function testGetTemplateContributionNewTemplate(): void {
$contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params);
// Create the template
$templateContrib = $this->callAPISuccess('Contribution', 'create', [
/**
* Test to check if correct membership is auto renewed.
*
- * @throws \CRM_Core_Exception
+ * @throws \CRM_Core_Exception|\CiviCRM_API3_Exception
*/
- public function testAutoRenewalWhenOneMemberIsDeceased() {
+ public function testAutoRenewalWhenOneMemberIsDeceased(): void {
$contactId1 = $this->individualCreate();
$contactId2 = $this->individualCreate();
$membershipOrganizationId = $this->organizationCreate();
]);
// create membership type
- $membershipTypeId1 = $this->callAPISuccess('MembershipType', 'create', [
+ $membershipTypeId1 = (int) $this->callAPISuccess('MembershipType', 'create', [
'domain_id' => 1,
'member_of_contact_id' => $membershipOrganizationId,
'financial_type_id' => 'Member Dues',
'name' => 'Parent',
])['id'];
- $membershipTypeID = $this->callAPISuccess('MembershipType', 'create', [
+ $membershipTypeID = (int) $this->callAPISuccess('MembershipType', 'create', [
'domain_id' => 1,
'member_of_contact_id' => $membershipOrganizationId,
'financial_type_id' => 'Member Dues',
foreach ($priceFields as $priceField) {
$lineItems = [];
- $contactId = array_search($priceField['membership_type_id'], $contactIDs);
+ $contactId = array_search((int) $priceField['membership_type_id'], $contactIDs, TRUE);
$lineItems[1] = [
'price_field_id' => $priceField['priceFieldID'],
'price_field_value_id' => $priceField['priceFieldValueID'],
'is_deceased' => 1,
]);
- // We delete latest membership payment and line item.
- $lineItemId = $this->callAPISuccessGetValue('LineItem', [
- 'contribution_id' => $contribution['id'],
- 'entity_id' => $membershipId2,
- 'entity_table' => 'civicrm_membership',
- 'return' => 'id',
- ]);
-
- // No api to delete membership payment.
- CRM_Core_DAO::executeQuery('
- DELETE FROM civicrm_membership_payment
- WHERE contribution_id = %1
- AND membership_id = %2
- ', [
- 1 => [$contribution['id'], 'Integer'],
- 2 => [$membershipId2, 'Integer'],
- ]);
-
- $this->callAPISuccess('LineItem', 'delete', [
- 'id' => $lineItemId,
- ]);
-
// set membership recurring to null.
$this->callAPISuccess('Membership', 'create', [
'id' => $membershipId2,
'contribution_recur_id' => NULL,
]);
+ $this->callAPISuccess('Contribution', 'delete', ['id' => $contribution['id']]);
+ unset($params['line_items'][1]);
+ $params['total_amount'] = 100;
+ $params['line_items'][0]['params']['id'] = $membershipId1;
+ $params['api.Payment.create']['total_amount'] = 100;
+
+ $order = $this->callAPISuccess('Order', 'create', $params);
+
// check line item and membership payment count.
$this->validateAllCounts($membershipId1, 5);
$this->validateAllCounts($membershipId2, 4);
// record next subsequent payment (6th payment).
$this->callAPISuccess('Contribution', 'repeattransaction', [
- 'original_contribution_id' => $contributionId,
+ 'original_contribution_id' => $order['id'],
'contribution_status_id' => 'Completed',
'total_amount' => '100',
]);
*
* @throws \CRM_Core_Exception
*/
- public function validateAllCounts($membershipId, $count) {
+ public function validateAllCounts(int $membershipId, int $count): void {
$memPayParams = [
'membership_id' => $membershipId,
];
$lineItemParams = [
'entity_id' => $membershipId,
'entity_table' => 'civicrm_membership',
+ 'contribution_id' => ['>' => 0],
];
$this->callAPISuccessGetCount('LineItem', $lineItemParams, $count);
$this->callAPISuccessGetCount('MembershipPayment', $memPayParams, $count);
* we want Nov 31.
*
* @param int $offset
- * @param int $year Optional input year to start
- * @param int $month Optional input month to start
+ * @param int|null $year Optional input year to start
+ * @param int|null $month Optional input month to start
*
* @return array
* ['year' => int, 'month' => int]
*/
- private function getYearAndMonthFromOffset(int $offset, int $year = NULL, int $month = NULL) {
+ private function getYearAndMonthFromOffset(int $offset, int $year = NULL, int $month = NULL): array {
$dateInfo = [
- 'year' => $year ?? date('Y'),
- 'month' => ($month ?? date('m')) + $offset,
+ 'year' => $year ?? (int) date('Y'),
+ 'month' => ($month ?? (int) date('m')) + $offset,
];
if ($dateInfo['month'] > 12) {
$dateInfo['year']++;
/**
* Test getYearAndMonthFromOffset
+ *
* @dataProvider yearMonthProvider
*
* @param array $input
* @param array $expected
*/
- public function testGetYearAndMonthFromOffset($input, $expected) {
+ public function testGetYearAndMonthFromOffset(array $input, array $expected): void {
$this->assertEquals($expected, $this->getYearAndMonthFromOffset($input[0], $input[1], $input[2]));
}
/**
* data provider for testGetYearAndMonthFromOffset
*/
- public function yearMonthProvider() {
+ public function yearMonthProvider(): array {
return [
// input = offset, year, current month
['input' => [4, 2020, 1], 'output' => ['year' => '2020', 'month' => '05']],
];
}
+ /**
+ * Test Recurring Contribution Email Receipt Flag
+ *
+ * @throws \CRM_Core_Exception
+ */
+ public function testContributionEmailReceipt(): void {
+ $createParams = $this->_params;
+ unset($createParams['trxn_id'], $createParams['invoice_id']);
+
+ // pass null value to is_email_receipt
+ $createParams['is_email_receipt'] = NULL;
+ $recurring1 = $this->callAPISuccess('ContributionRecur', 'create', $createParams);
+ $recurring1Get = $this->callAPISuccess('ContributionRecur', 'getsingle', ['id' => $recurring1['id']]);
+ // default is_email_receipt column value is 1
+ $this->assertEquals('1', $recurring1Get['is_email_receipt']);
+
+ // pass empty value to is_email_receipt
+ $createParams['is_email_receipt'] = '';
+ $recurring2 = $this->callAPISuccess('ContributionRecur', 'create', $createParams);
+ $recurring2 = ContributionRecur::get(FALSE)->addWhere('id', '=', $recurring2['id'])->addSelect('is_email_receipt')->execute()->first();
+ $this->assertEquals(NULL, $recurring2['is_email_receipt']);
+
+ // Pass 0 value to is_email_receipt.
+ $createParams['is_email_receipt'] = 0;
+ $recurring3 = $this->callAPISuccess('ContributionRecur', 'create', $createParams);
+ $recurring3Get = $this->callAPISuccess('ContributionRecur', 'getsingle', ['id' => $recurring3['id']]);
+ $this->assertEquals('0', $recurring3Get['is_email_receipt']);
+ }
+
}