$participantId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $contributionId, 'participant_id', 'contribution_id');
}
+ // load related memberships on basis of $contributionDAO object
+ $membershipIDs = array();
+ $contributionDAO->loadRelatedMembershipObjects($membershipIDs);
+
// build params for recording financial trxn entry
$params['contribution'] = $contributionDAO;
$params = array_merge($defaults, $params);
}
}
+ // update membership details
+ if (!empty($contributionDAO->_relatedObjects['membership'])) {
+ self::updateMembershipBasedOnCompletionOfContribution(
+ $contributionDAO,
+ $contributionDAO->_relatedObjects['membership'],
+ $contributionId,
+ $trxnsData['trxn_date']
+ );
+ }
+
// update financial item statuses
$baseTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contributionId);
$sqlFinancialItemUpdate = "
}
if (!empty($memberships)) {
- foreach ($memberships as $membershipTypeIdKey => $membership) {
- if ($membership) {
- $membershipParams = array(
- 'id' => $membership->id,
- 'contact_id' => $membership->contact_id,
- 'is_test' => $membership->is_test,
- 'membership_type_id' => $membership->membership_type_id,
- 'membership_activity_status' => 'Completed',
- );
-
- $currentMembership = CRM_Member_BAO_Membership::getContactMembership($membershipParams['contact_id'],
- $membershipParams['membership_type_id'],
- $membershipParams['is_test'],
- $membershipParams['id']
- );
-
- // CRM-8141 update the membership type with the value recorded in log when membership created/renewed
- // this picks up membership type changes during renewals
- // @todo this is almost certainly an obsolete sql call, the pre-change
- // membership is accessible via $this->_relatedObjects
- $sql = "
-SELECT membership_type_id
-FROM civicrm_membership_log
-WHERE membership_id={$membershipParams['id']}
-ORDER BY id DESC
-LIMIT 1;";
- $dao = CRM_Core_DAO::executeQuery($sql);
- if ($dao->fetch()) {
- if (!empty($dao->membership_type_id)) {
- $membershipParams['membership_type_id'] = $dao->membership_type_id;
- }
- }
- $dao->free();
-
- if (CRM_Core_PseudoConstant::getLabel('CRM_Contribute_BAO_Contribution', 'contribution_status_id', CRM_Utils_Array::value('contribution_status_id', $input)) === 'Pending') {
- $membershipParams['num_terms'] = 0;
- }
- else {
- $membershipParams['num_terms'] = $contribution->getNumTermsByContributionAndMembershipType(
- $membershipParams['membership_type_id'],
- $primaryContributionID
- );
- // @todo remove all this stuff in favour of letting the api call further down handle in
- // (it is a duplication of what the api does).
- $dates = array_fill_keys(array('join_date', 'start_date', 'end_date'), NULL);
- if ($currentMembership) {
- /*
- * Fixed FOR CRM-4433
- * In BAO/Membership.php(renewMembership function), we skip the extend membership date and status
- * when Contribution mode is notify and membership is for renewal )
- */
- CRM_Member_BAO_Membership::fixMembershipStatusBeforeRenew($currentMembership, $changeDate);
-
- // @todo - we should pass membership_type_id instead of null here but not
- // adding as not sure of testing
- $dates = CRM_Member_BAO_MembershipType::getRenewalDatesForMembershipType($membershipParams['id'],
- $changeDate, NULL, $membershipParams['num_terms']
- );
-
- $dates['join_date'] = $currentMembership['join_date'];
- }
-
- //get the status for membership.
- $calcStatus = CRM_Member_BAO_MembershipStatus::getMembershipStatusByDate($dates['start_date'],
- $dates['end_date'],
- $dates['join_date'],
- 'today',
- TRUE,
- $membershipParams['membership_type_id'],
- $membershipParams
- );
-
- unset($dates['end_date']);
- $membershipParams['status_id'] = CRM_Utils_Array::value('id', $calcStatus, 'New');
- //we might be renewing membership,
- //so make status override false.
- $membershipParams['is_override'] = FALSE;
- }
- //CRM-17723 - reset static $relatedContactIds array()
- // @todo move it to Civi Statics.
- $var = TRUE;
- CRM_Member_BAO_Membership::createRelatedMemberships($var, $var, TRUE);
- civicrm_api3('Membership', 'create', $membershipParams);
- }
- }
+ self::updateMembershipBasedOnCompletionOfContribution(
+ $contribution,
+ $memberships,
+ $primaryContributionID,
+ $changeDate,
+ CRM_Core_PseudoConstant::getLabel('CRM_Contribute_BAO_Contribution', 'contribution_status_id', CRM_Utils_Array::value('contribution_status_id', $input))
+ );
}
}
else {
return FALSE;
}
+ /**
+ * Update the memberships associated with a contribution if it has been completed.
+ *
+ * Note that the way in which $memberships are loaded as objects is pretty messy & I think we could just
+ * load them in this function. Code clean up would compensate for any minor performance implication.
+ *
+ * @param array $memberships
+ * @param int $primaryContributionID
+ * @param string $changeDate
+ * @param string $contributionStatus
+ * This shouldn't be required but historical function overload by repeattransaction probably requires it.
+ *
+ * @todo investigate completely bypassing this function if $contributionStatus != Completed.
+ */
+ protected static function updateMembershipBasedOnCompletionOfContribution($contribution, $memberships, $primaryContributionID, $changeDate, $contributionStatus = 'Completed') {
+ foreach ($memberships as $membershipTypeIdKey => $membership) {
+ if ($membership) {
+ $membershipParams = array(
+ 'id' => $membership->id,
+ 'contact_id' => $membership->contact_id,
+ 'is_test' => $membership->is_test,
+ 'membership_type_id' => $membership->membership_type_id,
+ 'membership_activity_status' => 'Completed',
+ );
+
+ $currentMembership = CRM_Member_BAO_Membership::getContactMembership($membershipParams['contact_id'],
+ $membershipParams['membership_type_id'],
+ $membershipParams['is_test'],
+ $membershipParams['id']
+ );
+
+ // CRM-8141 update the membership type with the value recorded in log when membership created/renewed
+ // this picks up membership type changes during renewals
+ // @todo this is almost certainly an obsolete sql call, the pre-change
+ // membership is accessible via $this->_relatedObjects
+ $sql = "
+SELECT membership_type_id
+FROM civicrm_membership_log
+WHERE membership_id={$membershipParams['id']}
+ORDER BY id DESC
+LIMIT 1;";
+ $dao = CRM_Core_DAO::executeQuery($sql);
+ if ($dao->fetch()) {
+ if (!empty($dao->membership_type_id)) {
+ $membershipParams['membership_type_id'] = $dao->membership_type_id;
+ }
+ }
+ $dao->free();
+
+ // Unclear why this is here but this function is overloaded by repeattransaction.
+ if ($contributionStatus === 'Pending') {
+ $membershipParams['num_terms'] = 0;
+ }
+ else {
+ $membershipParams['num_terms'] = $contribution->getNumTermsByContributionAndMembershipType(
+ $membershipParams['membership_type_id'],
+ $primaryContributionID
+ );
+ // @todo remove all this stuff in favour of letting the api call further down handle in
+ // (it is a duplication of what the api does).
+ $dates = array_fill_keys(array(
+ 'join_date',
+ 'start_date',
+ 'end_date',
+ ), NULL);
+ if ($currentMembership) {
+ /*
+ * Fixed FOR CRM-4433
+ * In BAO/Membership.php(renewMembership function), we skip the extend membership date and status
+ * when Contribution mode is notify and membership is for renewal )
+ */
+ CRM_Member_BAO_Membership::fixMembershipStatusBeforeRenew($currentMembership, $changeDate);
+
+ // @todo - we should pass membership_type_id instead of null here but not
+ // adding as not sure of testing
+ $dates = CRM_Member_BAO_MembershipType::getRenewalDatesForMembershipType($membershipParams['id'],
+ $changeDate, NULL, $membershipParams['num_terms']
+ );
+ $dates['join_date'] = $currentMembership['join_date'];
+ }
+
+ //get the status for membership.
+ $calcStatus = CRM_Member_BAO_MembershipStatus::getMembershipStatusByDate($dates['start_date'],
+ $dates['end_date'],
+ $dates['join_date'],
+ 'today',
+ TRUE,
+ $membershipParams['membership_type_id'],
+ $membershipParams
+ );
+
+ unset($dates['end_date']);
+ $membershipParams['status_id'] = CRM_Utils_Array::value('id', $calcStatus, 'New');
+ //we might be renewing membership,
+ //so make status override false.
+ $membershipParams['is_override'] = FALSE;
+ }
+ //CRM-17723 - reset static $relatedContactIds array()
+ // @todo move it to Civi Statics.
+ $var = TRUE;
+ CRM_Member_BAO_Membership::createRelatedMemberships($var, $var, TRUE);
+ civicrm_api3('Membership', 'create', $membershipParams);
+ }
+ }
+ }
+
/**
* Assign Test Value.
*
$this->assertEquals(-25, $payment['balance']);
}
+ /**
+ * Test the submit function of the membership form for partial payment.
+ */
+ public function testSubmitPartialPayment() {
+ // Step 1: submit a partial payment for a membership via backoffice
+ $form = $this->getForm();
+ $form->preProcess();
+ $this->mut = new CiviMailUtils($this, TRUE);
+ $this->createLoggedInUser();
+ $priceSet = $this->callAPISuccess('PriceSet', 'Get', array("extends" => "CiviMember"));
+ $form->set('priceSetId', $priceSet['id']);
+ $partiallyPaidAmount = 25;
+ CRM_Price_BAO_PriceSet::buildPriceSet($form);
+ $params = array(
+ 'cid' => $this->_individualId,
+ 'join_date' => date('m/d/Y', time()),
+ 'start_date' => '',
+ 'end_date' => '',
+ // This format reflects the 23 being the organisation & the 25 being the type.
+ 'membership_type_id' => array(23, $this->membershipTypeAnnualFixedID),
+ 'record_contribution' => 1,
+ 'total_amount' => $partiallyPaidAmount,
+ 'receive_date' => date('m/d/Y', time()),
+ 'receive_date_time' => '08:36PM',
+ 'payment_instrument_id' => array_search('Check', $this->paymentInstruments),
+ 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Partially paid'),
+ 'financial_type_id' => '2', //Member dues, see data.xml
+ 'payment_processor_id' => $this->_paymentProcessorID,
+ );
+ $form->_contactID = $this->_individualId;
+ $form->testSubmit($params);
+ $membership = $this->callAPISuccessGetSingle('Membership', array('contact_id' => $this->_individualId));
+ // check the membership status after partial payment, if its Pending
+ $this->assertEquals(array_search('Pending', CRM_Member_PseudoConstant::membershipStatus()), $membership['status_id']);
+ $contribution = $this->callAPISuccessGetSingle('Contribution', array(
+ 'contact_id' => $this->_individualId,
+ ));
+ $this->assertEquals('Partially paid', $contribution['contribution_status']);
+ // $this->assertEquals(50.00, $contribution['total_amount']);
+ // $this->assertEquals(25.00, $contribution['net_amount']);
+
+ // Step 2: submit the other half of the partial payment
+ // via AdditionalPayment form to complete the related contribution
+ $form = new CRM_Contribute_Form_AdditionalPayment();
+ $submitParams = array(
+ 'contribution_id' => $contribution['contribution_id'],
+ 'contact_id' => $this->_individualId,
+ 'total_amount' => $partiallyPaidAmount,
+ 'currency' => 'USD',
+ 'financial_type_id' => 2,
+ 'receive_date' => '04/21/2015',
+ 'receive_date_time' => '11:27PM',
+ 'trxn_date' => '2017-04-11 13:05:11',
+ 'payment_processor_id' => 0,
+ 'payment_instrument_id' => array_search('Check', $this->paymentInstruments),
+ 'check_number' => 'check-12345',
+ );
+ $form->cid = $this->_individualId;
+ $form->testSubmit($submitParams);
+ $membership = $this->callAPISuccessGetSingle('Membership', array('contact_id' => $this->_individualId));
+ // check the membership status after additional payment, if its changed to 'New'
+ $this->assertEquals(array_search('New', CRM_Member_PseudoConstant::membershipStatus()), $membership['status_id']);
+
+ // check the contribution status and net amount after additional payment
+ $contribution = $this->callAPISuccessGetSingle('Contribution', array(
+ 'contact_id' => $this->_individualId,
+ ));
+ $this->assertEquals('Completed', $contribution['contribution_status']);
+ // $this->assertEquals(50.00, $contribution['total_amount']);
+ // $this->assertEquals(50.00, $contribution['net_amount']);
+ }
+
/**
* Test the submit function of the membership form.
*/