function testGetValues() { // $this->markTestSkipped( 'causes mysterious exit, needs fixing!' ); // Calculate membership dates based on the current date $now = time(); $year_from_now = $now + 365 * 24 * 60 * 60; $last_month = $now - 30 * 24 * 60 * 60; $year_from_last_month = $last_month + 365 * 24 * 60 * 60; $contactId = Contact::createIndividual(); $params = array('contact_id' => $contactId, 'membership_type_id' => '1', 'join_date' => date('Y-m-d'), 'start_date' => date('Y-m-d'), 'end_date' => date('Y-m-d', $year_from_now), 'source' => 'Payment', 'is_override' => 1, 'status_id' => $this->_membershipStatusID); $ids = array(); CRM_Member_BAO_Membership::create($params, $ids); $membershipId1 = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id', 'contact_id', 'Database check for created membership.'); $params = array('contact_id' => $contactId, 'membership_type_id' => '2', 'join_date' => date('Y-m-d', $last_month), 'start_date' => date('Y-m-d', $last_month), 'end_date' => date('Y-m-d', $year_from_last_month), 'source' => 'Source123', 'is_override' => 0, 'status_id' => $this->_membershipStatusID); $ids = array(); CRM_Member_BAO_Membership::create($params, $ids); $membershipId2 = $this->assertDBNotNull('CRM_Member_BAO_Membership', 'source123', 'id', 'source', 'Database check for created membership.'); $membership = array('contact_id' => $contactId); $membershipValues = array(); CRM_Member_BAO_Membership::getValues($membership, $membershipValues, true); $this->assertEquals($membershipValues[$membershipId1]['membership_id'], $membershipId1, 'Verify membership record 1 is fetched.'); $this->assertEquals($membershipValues[$membershipId2]['membership_id'], $membershipId2, 'Verify membership record 2 is fetched.'); }
public function preProcess() { //custom data related code $this->_cdType = CRM_Utils_Array::value('type', $_GET); $this->assign('cdType', FALSE); if ($this->_cdType) { $this->assign('cdType', TRUE); return CRM_Custom_Form_CustomData::preProcess($this); } parent::preProcess(); // get price set id. $this->_priceSetId = CRM_Utils_Array::value('priceSetId', $_GET); $this->set('priceSetId', $this->_priceSetId); $this->assign('priceSetId', $this->_priceSetId); // check for edit permission if (!CRM_Core_Permission::checkActionPermission('CiviMember', $this->_action)) { CRM_Core_Error::fatal(ts('You do not have permission to access this page.')); } if ($this->_action & CRM_Core_Action::DELETE) { $contributionID = CRM_Member_BAO_Membership::getMembershipContributionId($this->_id); // check delete permission for contribution if ($this->_id && $contributionID && !CRM_Core_Permission::checkActionPermission('CiviContribute', $this->_action)) { CRM_Core_Error::fatal(ts("This Membership is linked to a contribution. You must have 'delete in CiviContribute' permission in order to delete this record.")); } } if ($this->_action & CRM_Core_Action::ADD) { if (!CRM_Member_BAO_Membership::statusAvailabilty($this->_contactID)) { // all possible statuses are disabled - redirect back to contact form CRM_Core_Error::statusBounce(ts('There are no configured membership statuses. You cannot add this membership until your membership statuses are correctly configured')); } if ($this->_contactID) { //check whether contact has a current membership so we can alert user that they may want to do a renewal instead $contactMemberships = array(); $memParams = array('contact_id' => $this->_contactID); CRM_Member_BAO_Membership::getValues($memParams, $contactMemberships, TRUE); $cMemTypes = array(); foreach ($contactMemberships as $mem) { $cMemTypes[] = $mem['membership_type_id']; } if (count($cMemTypes) > 0) { $memberorgs = CRM_Member_BAO_MembershipType::getMemberOfContactByMemTypes($cMemTypes); $mems_by_org = array(); foreach ($contactMemberships as $memid => $mem) { $mem['member_of_contact_id'] = CRM_Utils_Array::value($mem['membership_type_id'], $memberorgs); if (!empty($mem['membership_end_date'])) { $mem['membership_end_date'] = CRM_Utils_Date::customformat($mem['membership_end_date']); } $mem['membership_type'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $mem['membership_type_id'], 'name', 'id'); $mem['membership_status'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipStatus', $mem['status_id'], 'label', 'id'); $mem['renewUrl'] = CRM_Utils_System::url('civicrm/contact/view/membership', "reset=1&action=renew&cid={$this->_contactID}&id={$mem['id']}&context=membership&selectedChild=member" . ($this->_mode ? '&mode=live' : '')); $mem['membershipTab'] = CRM_Utils_System::url('civicrm/contact/view', "reset=1&force=1&cid={$this->_contactID}&selectedChild=member"); $mems_by_org[$mem['member_of_contact_id']] = $mem; } $this->assign('existingContactMemberships', $mems_by_org); } } else { // In standalone mode we don't have a contact id yet so lookup will be done client-side with this script: $resources = CRM_Core_Resources::singleton(); $resources->addScriptFile('civicrm', 'templates/CRM/Member/Form/MembershipStandalone.js'); $passthru = array('typeorgs' => CRM_Member_BAO_MembershipType::getMembershipTypeOrganization(), 'memtypes' => CRM_Core_PseudoConstant::get('CRM_Member_BAO_Membership', 'membership_type_id'), 'statuses' => CRM_Core_PseudoConstant::get('CRM_Member_BAO_Membership', 'status_id')); $resources->addSetting(array('existingMems' => $passthru)); } } // when custom data is included in this page if (!empty($_POST['hidden_custom'])) { CRM_Custom_Form_CustomData::preProcess($this); CRM_Custom_Form_CustomData::buildQuickForm($this); CRM_Custom_Form_CustomData::setDefaultValues($this); } // CRM-4395, get the online pending contribution id. $this->_onlinePendingContributionId = NULL; if (!$this->_mode && $this->_id && $this->_action & CRM_Core_Action::UPDATE) { $this->_onlinePendingContributionId = CRM_Contribute_BAO_Contribution::checkOnlinePendingContribution($this->_id, 'Membership'); } $this->assign('onlinePendingContributionId', $this->_onlinePendingContributionId); $this->setPageTitle(ts('Membership')); }
/** * Calculate start date and end date for membership updates. * * Note that this function is called by the api for any membership update although it was * originally written for renewal (which feels a bit fragile but hey....). * * @param int $membershipId * @param $changeToday * @param int $membershipTypeID * If provided, overrides the membership type of the $membershipID membership. * @param int $numRenewTerms * How many membership terms are being added to end date (default is 1). * * CRM-7297 Membership Upsell - Added $membershipTypeID param to facilitate calculations of dates when membership type changes * * @return array * array fo the start date, end date and join date of the membership */ public static function getRenewalDatesForMembershipType($membershipId, $changeToday = NULL, $membershipTypeID = NULL, $numRenewTerms = 1) { $params = array('id' => $membershipId); $membershipDetails = CRM_Member_BAO_Membership::getValues($params, $values); $membershipDetails = $membershipDetails[$membershipId]; $statusID = $membershipDetails->status_id; $membershipDates = array(); if (!empty($membershipDetails->join_date)) { $membershipDates['join_date'] = CRM_Utils_Date::customFormat($membershipDetails->join_date, '%Y%m%d'); } $oldPeriodType = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $membershipId, 'membership_type_id'), 'period_type'); // CRM-7297 Membership Upsell if (is_null($membershipTypeID)) { $membershipTypeDetails = self::getMembershipTypeDetails($membershipDetails->membership_type_id); } else { $membershipTypeDetails = self::getMembershipTypeDetails($membershipTypeID); } $statusDetails = CRM_Member_BAO_MembershipStatus::getMembershipStatus($statusID); if ($statusDetails['is_current_member'] == 1) { $startDate = $membershipDetails->start_date; // CRM=7297 Membership Upsell: we need to handle null end_date in case we are switching // from a lifetime to a different membership type if (is_null($membershipDetails->end_date)) { $date = date('Y-m-d'); } else { $date = $membershipDetails->end_date; } $date = explode('-', $date); $logStartDate = date('Y-m-d', mktime(0, 0, 0, (double) $date[1], (double) ($date[2] + 1), (double) $date[0])); $date = explode('-', $logStartDate); $year = $date[0]; $month = $date[1]; $day = $date[2]; switch ($membershipTypeDetails['duration_unit']) { case 'year': //need to check if the upsell is from rolling to fixed and adjust accordingly if ($membershipTypeDetails['period_type'] == 'fixed' && $oldPeriodType == 'rolling') { $month = substr($membershipTypeDetails['fixed_period_start_day'], 0, strlen($membershipTypeDetails['fixed_period_start_day']) - 2); $day = substr($membershipTypeDetails['fixed_period_start_day'], -2); $year += 1; } else { $year = $year + $numRenewTerms * $membershipTypeDetails['duration_interval']; } break; case 'month': $month = $month + $numRenewTerms * $membershipTypeDetails['duration_interval']; break; case 'day': $day = $day + $numRenewTerms * $membershipTypeDetails['duration_interval']; break; } if ($membershipTypeDetails['duration_unit'] == 'lifetime') { $endDate = NULL; } else { $endDate = date('Y-m-d', mktime(0, 0, 0, $month, $day - 1, $year)); } $today = date('Y-m-d'); $membershipDates['today'] = CRM_Utils_Date::customFormat($today, '%Y%m%d'); $membershipDates['start_date'] = CRM_Utils_Date::customFormat($startDate, '%Y%m%d'); $membershipDates['end_date'] = CRM_Utils_Date::customFormat($endDate, '%Y%m%d'); $membershipDates['log_start_date'] = CRM_Utils_Date::customFormat($logStartDate, '%Y%m%d'); } else { $today = date('Y-m-d'); if ($changeToday) { $today = CRM_Utils_Date::processDate($changeToday, NULL, FALSE, 'Y-m-d'); } // Calculate new start/end dates when join date is today $renewalDates = self::getDatesForMembershipType($membershipTypeDetails['id'], $today, NULL, NULL, $numRenewTerms); $membershipDates['today'] = CRM_Utils_Date::customFormat($today, '%Y%m%d'); $membershipDates['start_date'] = $renewalDates['start_date']; $membershipDates['end_date'] = $renewalDates['end_date']; $membershipDates['log_start_date'] = $renewalDates['start_date']; } if (!isset($membershipDates['join_date'])) { $membershipDates['join_date'] = $membershipDates['start_date']; } return $membershipDates; }
/** * Create / update / delete membership for related contacts. * * This function will create/update/delete membership for related * contact based on 1) contact have active membership 2) that * membership is is extedned by the same relationship type to that * of the existing relationship. * * @param int $contactId * contact id. * @param array $params * array of values submitted by POST. * @param array $ids * array of ids. * @param \const|int $action which action called this function * * @param bool $active * * @throws \CRM_Core_Exception */ public static function relatedMemberships($contactId, &$params, $ids, $action = CRM_Core_Action::ADD, $active = TRUE) { // Check the end date and set the status of the relationship // accordingly. $status = self::CURRENT; $targetContact = $targetContact = CRM_Utils_Array::value('contact_check', $params, array()); $today = date('Ymd'); // If a relationship hasn't yet started, just return for now // TODO: handle edge-case of updating start_date of an existing relationship if (!empty($params['start_date'])) { $startDate = substr(CRM_Utils_Date::format($params['start_date']), 0, 8); if ($today < $startDate) { return; } } if (!empty($params['end_date'])) { $endDate = substr(CRM_Utils_Date::format($params['end_date']), 0, 8); if ($today > $endDate) { $status = self::PAST; } } if ($action & CRM_Core_Action::ADD && $status & self::PAST) { // If relationship is PAST and action is ADD, do nothing. return; } $rel = explode('_', $params['relationship_type_id']); $relTypeId = $rel[0]; if (!empty($rel[1])) { $relDirection = "_{$rel[1]}_{$rel[2]}"; } else { // this call is coming from somewhere where the direction was resolved early on (e.g an api call) // so we can assume _a_b $relDirection = "_a_b"; $targetContact = array($params['contact_id_b'] => 1); } if ($action & CRM_Core_Action::ADD || $action & CRM_Core_Action::DELETE) { $contact = $contactId; } elseif ($action & CRM_Core_Action::UPDATE) { $contact = $ids['contact']; $targetContact = array($ids['contactTarget'] => 1); } // Build the 'values' array for // 1. ContactA // 2. ContactB // This will allow us to check if either of the contacts in // relationship have active memberships. $values = array(); // 1. ContactA $values[$contact] = array('relatedContacts' => $targetContact, 'relationshipTypeId' => $relTypeId, 'relationshipTypeDirection' => $relDirection); // 2. ContactB if (!empty($targetContact)) { foreach ($targetContact as $cid => $donCare) { $values[$cid] = array('relatedContacts' => array($contact => 1), 'relationshipTypeId' => $relTypeId); $relTypeParams = array('id' => $relTypeId); $relTypeValues = array(); CRM_Contact_BAO_RelationshipType::retrieve($relTypeParams, $relTypeValues); if (CRM_Utils_Array::value('name_a_b', $relTypeValues) == CRM_Utils_Array::value('name_b_a', $relTypeValues)) { $values[$cid]['relationshipTypeDirection'] = '_a_b'; } else { $values[$cid]['relationshipTypeDirection'] = $relDirection == '_a_b' ? '_b_a' : '_a_b'; } } } // CRM-15829 UPDATES // If we're looking for active memberships we must consider pending (id: 5) ones too. // Hence we can't just call CRM_Member_BAO_Membership::getValues below with the active flag, is it would completely miss pending relatioships. // As suggested by @davecivicrm, the pending status id is fetched using the CRM_Member_PseudoConstant::membershipStatus() class and method, since these ids differ from system to system. $pendingStatusId = array_search('Pending', CRM_Member_PseudoConstant::membershipStatus()); $query = 'SELECT * FROM `civicrm_membership_status`'; if ($active) { $query .= ' WHERE `is_current_member` = 1 OR `id` = %1 '; } $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($pendingStatusId, 'Integer'))); while ($dao->fetch()) { $membershipStatusRecordIds[$dao->id] = $dao->id; } // Now get the active memberships for all the contacts. // If contact have any valid membership(s), then add it to // 'values' array. foreach ($values as $cid => $subValues) { $memParams = array('contact_id' => $cid); $memberships = array(); // CRM-15829 UPDATES // Since we want PENDING memberships as well, the $active flag needs to be set to false so that this will return all memberships and we can then filter the memberships based on the status IDs recieved above. CRM_Member_BAO_Membership::getValues($memParams, $memberships, FALSE, TRUE); // CRM-15829 UPDATES // filter out the memberships returned by CRM_Member_BAO_Membership::getValues based on the status IDs fetched on line ~1462 foreach ($memberships as $key => $membership) { if (!isset($memberships[$key]['status_id'])) { continue; } $membershipStatusId = $memberships[$key]['status_id']; if (!isset($membershipStatusRecordIds[$membershipStatusId])) { unset($memberships[$key]); } } if (empty($memberships)) { continue; } //get ownerMembershipIds for related Membership //this is to handle memberships being deleted and recreated if (!empty($memberships['owner_membership_ids'])) { $ownerMemIds[$cid] = $memberships['owner_membership_ids']; unset($memberships['owner_membership_ids']); } $values[$cid]['memberships'] = $memberships; } $deceasedStatusId = array_search('Deceased', CRM_Member_PseudoConstant::membershipStatus()); // done with 'values' array. // Finally add / edit / delete memberships for the related contacts foreach ($values as $cid => $details) { if (!array_key_exists('memberships', $details)) { continue; } $relatedContacts = array_keys(CRM_Utils_Array::value('relatedContacts', $details, array())); $mainRelatedContactId = reset($relatedContacts); foreach ($details['memberships'] as $membershipId => $membershipValues) { $relTypeIds = array(); if ($action & CRM_Core_Action::DELETE) { // Delete memberships of the related contacts only if relationship type exists for membership type $query = "\nSELECT relationship_type_id, relationship_direction\n FROM civicrm_membership_type\n WHERE id = {$membershipValues['membership_type_id']}"; $dao = CRM_Core_DAO::executeQuery($query); $relTypeDirs = array(); while ($dao->fetch()) { $relTypeId = $dao->relationship_type_id; $relDirection = $dao->relationship_direction; } $relTypeIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $relTypeId); if (in_array($values[$cid]['relationshipTypeId'], $relTypeIds) && !empty($membershipValues['owner_membership_id']) && !empty($values[$mainRelatedContactId]['memberships'][$membershipValues['owner_membership_id']])) { CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipValues['owner_membership_id'], $membershipValues['membership_contact_id']); } continue; } if ($action & CRM_Core_Action::UPDATE && $status & self::PAST && $membershipValues['owner_membership_id']) { // If relationship is PAST and action is UPDATE // then delete the RELATED membership CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipValues['owner_membership_id'], $membershipValues['membership_contact_id']); continue; } // add / edit the memberships for related // contacts. // Get the Membership Type Details. $membershipType = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipValues['membership_type_id']); // Check if contact's relationship type exists in membership type $relTypeDirs = array(); if (!empty($membershipType['relationship_type_id'])) { $relTypeIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $membershipType['relationship_type_id']); } if (!empty($membershipType['relationship_direction'])) { $relDirections = explode(CRM_Core_DAO::VALUE_SEPARATOR, $membershipType['relationship_direction']); } foreach ($relTypeIds as $key => $value) { $relTypeDirs[] = $value . '_' . $relDirections[$key]; } $relTypeDir = $details['relationshipTypeId'] . $details['relationshipTypeDirection']; if (in_array($relTypeDir, $relTypeDirs)) { // Check if relationship being created/updated is // similar to that of membership type's // relationship. $membershipValues['owner_membership_id'] = $membershipId; unset($membershipValues['id']); unset($membershipValues['membership_contact_id']); unset($membershipValues['contact_id']); unset($membershipValues['membership_id']); foreach ($details['relatedContacts'] as $relatedContactId => $donCare) { $membershipValues['contact_id'] = $relatedContactId; if ($deceasedStatusId && CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $relatedContactId, 'is_deceased')) { $membershipValues['status_id'] = $deceasedStatusId; $membershipValues['skipStatusCal'] = TRUE; } foreach (array('join_date', 'start_date', 'end_date') as $dateField) { if (!empty($membershipValues[$dateField])) { $membershipValues[$dateField] = CRM_Utils_Date::processDate($membershipValues[$dateField]); } } if ($action & CRM_Core_Action::UPDATE) { //if updated relationship is already related to contact don't delete existing inherited membership if (in_array($relTypeId, $relTypeIds) && !empty($values[$relatedContactId]['memberships']) && !empty($ownerMemIds) && in_array($membershipValues['owner_membership_id'], $ownerMemIds[$relatedContactId])) { continue; } //delete the membership record for related //contact before creating new membership record. CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId, $relatedContactId); } // check whether we have some related memberships still available $query = "\nSELECT count(*)\n FROM civicrm_membership\n LEFT JOIN civicrm_membership_status ON (civicrm_membership_status.id = civicrm_membership.status_id)\n WHERE membership_type_id = {$membershipValues['membership_type_id']} AND owner_membership_id = {$membershipValues['owner_membership_id']}\n AND is_current_member = 1"; $result = CRM_Core_DAO::singleValueQuery($query); if ($result < CRM_Utils_Array::value('max_related', $membershipValues, PHP_INT_MAX)) { CRM_Member_BAO_Membership::create($membershipValues, CRM_Core_DAO::$_nullArray); } } } elseif ($action & CRM_Core_Action::UPDATE) { // if action is update and updated relationship do // not match with the existing // membership=>relationship then we need to // change the status of the membership record to expired for // previous relationship -- CRM-12078. // CRM-16087 we need to pass ownerMembershipId to isRelatedMembershipExpired function if (empty($params['relationship_ids']) && !empty($params['id'])) { $relIds = array($params['id']); } else { $relIds = CRM_Utils_Array::value('relationship_ids', $params); } if (self::isRelatedMembershipExpired($relTypeIds, $contactId, $mainRelatedContactId, $relTypeId, $relIds) && !empty($membershipValues['owner_membership_id']) && !empty($values[$mainRelatedContactId]['memberships'][$membershipValues['owner_membership_id']])) { $membershipValues['status_id'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipStatus', 'Expired', 'id', 'label'); $type = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $membershipValues['membership_type_id'], 'name', 'id'); CRM_Member_BAO_Membership::add($membershipValues); CRM_Core_Session::setStatus(ts("Inherited membership {$type} status was changed to Expired due to the change in relationship type."), ts('Record Updated'), 'alert'); } } } } }
public function preProcess() { //custom data related code $this->_cdType = CRM_Utils_Array::value('type', $_GET); $this->assign('cdType', FALSE); if ($this->_cdType) { $this->assign('cdType', TRUE); return CRM_Custom_Form_CustomData::preProcess($this); } // get price set id. $this->_priceSetId = CRM_Utils_Array::value('priceSetId', $_GET); $this->set('priceSetId', $this->_priceSetId); $this->assign('priceSetId', $this->_priceSetId); // action $this->_action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 'add'); $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this); $this->_contactID = CRM_Utils_Request::retrieve('cid', 'Positive', $this); $this->_processors = array(); CRM_Core_Resources::singleton()->addSetting(array('ids' => array('contact' => $this->_contactID))); // check for edit permission if (!CRM_Core_Permission::checkActionPermission('CiviMember', $this->_action)) { CRM_Core_Error::fatal(ts('You do not have permission to access this page')); } if ($this->_action & CRM_Core_Action::DELETE) { $contributionID = CRM_Member_BAO_Membership::getMembershipContributionId($this->_id); // check delete permission for contribution if ($this->_id && $contributionID && !CRM_Core_Permission::checkActionPermission('CiviContribute', $this->_action)) { CRM_Core_Error::fatal(ts("This Membership is linked to a contribution. You must have 'delete in CiviContribute' permission in order to delete this record.")); } } $this->_context = CRM_Utils_Request::retrieve('context', 'String', $this); $this->assign('context', $this->_context); if ($this->_id) { $this->_memType = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $this->_id, 'membership_type_id'); $this->_membershipIDs[] = $this->_id; } $this->_mode = CRM_Utils_Request::retrieve('mode', 'String', $this); $this->assign('membershipMode', $this->_mode); if ($this->_mode) { $this->_paymentProcessor = array('billing_mode' => 1); $validProcessors = array(); $processors = CRM_Core_PseudoConstant::paymentProcessor(FALSE, FALSE, 'billing_mode IN ( 1, 3 )'); foreach ($processors as $ppID => $label) { $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($ppID, $this->_mode); if ($paymentProcessor['payment_processor_type'] == 'PayPal' && !$paymentProcessor['user_name']) { continue; } elseif ($paymentProcessor['payment_processor_type'] == 'Dummy' && $this->_mode == 'live') { continue; } else { $paymentObject = CRM_Core_Payment::singleton($this->_mode, $paymentProcessor, $this); $error = $paymentObject->checkConfig(); if (empty($error)) { $validProcessors[$ppID] = $label; } $paymentObject = NULL; } } if (empty($validProcessors)) { CRM_Core_Error::fatal(ts('Could not find valid payment processor for this page')); } else { $this->_processors = $validProcessors; } // also check for billing information // get the billing location type $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id', array(), 'validate'); // CRM-8108 remove ts around Billing location type //$this->_bltID = array_search( ts('Billing'), $locationTypes ); $this->_bltID = array_search('Billing', $locationTypes); if (!$this->_bltID) { CRM_Core_Error::fatal(ts('Please set a location type of %1', array(1 => 'Billing'))); } $this->set('bltID', $this->_bltID); $this->assign('bltID', $this->_bltID); $this->_fields = array(); CRM_Core_Payment_Form::setCreditCardFields($this); // this required to show billing block $this->assign_by_ref('paymentProcessor', $paymentProcessor); $this->assign('hidePayPalExpress', TRUE); } if ($this->_action & CRM_Core_Action::ADD) { if (!CRM_Member_BAO_Membership::statusAvailabilty($this->_contactID)) { // all possible statuses are disabled - redirect back to contact form CRM_Core_Error::statusBounce(ts('There are no configured membership statuses. You cannot add this membership until your membership statuses are correctly configured')); } if ($this->_contactID) { //check whether contact has a current membership so we can alert user that they may want to do a renewal instead $contactMemberships = array(); $memParams = array('contact_id' => $this->_contactID); CRM_Member_BAO_Membership::getValues($memParams, $contactMemberships, TRUE); $cMemTypes = array(); foreach ($contactMemberships as $mem) { $cMemTypes[] = $mem['membership_type_id']; } if (count($cMemTypes) > 0) { $memberorgs = CRM_Member_BAO_MembershipType::getMemberOfContactByMemTypes($cMemTypes); $mems_by_org = array(); foreach ($contactMemberships as $memid => $mem) { $mem['member_of_contact_id'] = CRM_Utils_Array::value($mem['membership_type_id'], $memberorgs); if (CRM_Utils_Array::value('membership_end_date', $mem)) { $mem['membership_end_date'] = CRM_Utils_Date::customformat($mem['membership_end_date']); } $mem['membership_type'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $mem['membership_type_id'], 'name', 'id'); $mem['membership_status'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipStatus', $mem['status_id'], 'label', 'id'); if ($this->_mode) { $mem['renewUrl'] = CRM_Utils_System::url('civicrm/contact/view/membership', "reset=1&action=renew&cid={$this->_contactID}&id={$mem['id']}&context=membership&selectedChild=member&mode=live"); } else { $mem['renewUrl'] = CRM_Utils_System::url('civicrm/contact/view/membership', "reset=1&action=renew&cid={$this->_contactID}&id={$mem['id']}&context=membership&selectedChild=member"); } $mem['membershipTab'] = CRM_Utils_System::url('civicrm/contact/view', "reset=1&force=1&cid={$this->_contactID}&selectedChild=member"); $mems_by_org[$mem['member_of_contact_id']] = $mem; } $resources = CRM_Core_Resources::singleton(); $resources->addSetting(array('existingMems' => array('memberorgs' => $mems_by_org))); $resources->addScriptFile('civicrm', 'templates/CRM/Member/Form/Membership.js'); } } else { $resources = CRM_Core_Resources::singleton(); $resources->addScriptFile('civicrm', 'templates/CRM/Member/Form/MembershipStandalone.js'); $statuses = array(); $membershipStatus = new CRM_Member_DAO_MembershipStatus(); $membershipStatus->is_current_member = 1; $membershipStatus->find(); $membershipStatus->selectAdd(); $membershipStatus->selectAdd('id'); while ($membershipStatus->fetch()) { $statuses[$membershipStatus->id] = $membershipStatus->label; } $membershipStatus->free(); $passthru = array('typeorgs' => CRM_Member_BAO_MembershipType::getMembershipTypeOrganization(), 'memtypes' => CRM_Member_BAO_MembershipType::getMembershipTypes(FALSE), 'statuses' => $statuses); $resources->addSetting(array('existingMems' => $passthru)); } } // when custom data is included in this page if (CRM_Utils_Array::value('hidden_custom', $_POST)) { CRM_Custom_Form_CustomData::preProcess($this); CRM_Custom_Form_CustomData::buildQuickForm($this); CRM_Custom_Form_CustomData::setDefaultValues($this); } // CRM-4395, get the online pending contribution id. $this->_onlinePendingContributionId = NULL; if (!$this->_mode && $this->_id && $this->_action & CRM_Core_Action::UPDATE) { $this->_onlinePendingContributionId = CRM_Contribute_BAO_Contribution::checkOnlinePendingContribution($this->_id, 'Membership'); } $this->assign('onlinePendingContributionId', $this->_onlinePendingContributionId); $this->_fromEmails = CRM_Core_BAO_Email::getFromEmail(); // Set title if ($this->_contactID) { $displayName = CRM_Contact_BAO_Contact::displayName($this->_contactID); // Check if this is default domain contact CRM-10482 if (CRM_Contact_BAO_Contact::checkDomainContact($this->_contactID)) { $displayName .= ' (' . ts('default organization') . ')'; } // omitting contactImage from title for now since the summary overlay css doesn't work outside of our crm-container CRM_Utils_System::setTitle(ts('Membership for') . ' ' . $displayName); } parent::preProcess(); }
/** * Get contact membership record. * * This api is used for finding an existing membership record. * This api will also return the mebership records for the contacts * having mebership based on the relationship with the direct members. * * @param Array $params key/value pairs for contact_id and some * options affecting the desired results; has legacy support * for just passing the contact_id itself as the argument * * @return Array of all found membership property values. * @access public */ function civicrm_membership_contact_get(&$params) { _civicrm_initialize(); $activeOnly = false; if (is_array($params)) { $contactID = CRM_Utils_Array::value('contact_id', $params); $activeOnly = CRM_Utils_Array::value('active_only', $params, false); if ($activeOnly == 1) { $activeOnly = true; } else { $activeOnly = false; } } elseif (CRM_Utils_Rule::integer($params)) { $contactID = $params; } else { return civicrm_create_error('Paramers can be only of type array or integer'); } if (empty($contactID)) { return civicrm_create_error('Invalid value for ContactID.'); } // get the membership for the given contact ID require_once 'CRM/Member/BAO/Membership.php'; $membership = array('contact_id' => $contactID); $membershipValues = array(); CRM_Member_BAO_Membership::getValues($membership, $membershipValues, $activeOnly); $recordCount = 0; if (empty($membershipValues)) { # No results is NOT an error! # return civicrm_create_error('No memberships for this contact.'); $membershipValues['record_count'] = $recordCount; return $membershipValues; } $members[$contactID] = array(); $relationships = array(); foreach ($membershipValues as $membershipId => $values) { // populate the membership type name for the membership type id require_once 'CRM/Member/BAO/MembershipType.php'; $membershipType = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($values['membership_type_id']); $membershipValues[$membershipId]['membership_name'] = $membershipType['name']; if (CRM_Utils_Array::value('relationship_type_id', $membershipType)) { $relationships[$membershipType['relationship_type_id']] = $membershipId; } // populating relationship type name. require_once 'CRM/Contact/BAO/RelationshipType.php'; $relationshipType = new CRM_Contact_BAO_RelationshipType(); $relationshipType->id = CRM_Utils_Array::value('relationship_type_id', $membershipType); if ($relationshipType->find(true)) { $membershipValues[$membershipId]['relationship_name'] = $relationshipType->name_a_b; } require_once 'CRM/Core/BAO/CustomGroup.php'; $groupTree =& CRM_Core_BAO_CustomGroup::getTree('Membership', CRM_Core_DAO::$_nullObject, $membershipId, false, $values['membership_type_id']); $groupTree = CRM_Core_BAO_CustomGroup::formatGroupTree($groupTree, 1, CRM_Core_DAO::$_nullObject); $defaults = array(); CRM_Core_BAO_CustomGroup::setDefaults($groupTree, $defaults); if (!empty($defaults)) { foreach ($defaults as $key => $val) { $membershipValues[$membershipId][$key] = $val; } } $recordCount++; } $members[$contactID] = $membershipValues; // populating contacts in members array based on their relationship with direct members. require_once 'CRM/Contact/BAO/Relationship.php'; if (!empty($relationships)) { foreach ($relationships as $relTypeId => $membershipId) { // As members are not direct members, there should not be // membership id in the result array. unset($membershipValues[$membershipId]['id']); $relationship = new CRM_Contact_BAO_Relationship(); $relationship->contact_id_b = $contactID; $relationship->relationship_type_id = $relTypeId; if ($relationship->find()) { while ($relationship->fetch()) { clone $relationship; $membershipValues[$membershipId]['contact_id'] = $relationship->contact_id_a; $members[$contactID][$relationship->contact_id_a] = $membershipValues[$membershipId]; } } $recordCount++; } } $members['record_count'] = $recordCount; return $members; }
/** * Function to create / update / delete membership for related contacts. * * This function will create/update/delete membership for related * contact based on 1) contact have active membership 2) that * membership is is extedned by the same relationship type to that * of the existing relationship. * * @param $contactId Int contact id * @param $params array array of values submitted by POST * @param $ids array array of ids * @param $action which action called this function * * @static * */ static function relatedMemberships($contactId, &$params, $ids, $action = CRM_Core_Action::ADD, $active = TRUE) { // Check the end date and set the status of the relationship // accrodingly. $status = self::CURRENT; if (!empty($params['end_date'])) { $endDate = CRM_Utils_Date::setDateDefaults(CRM_Utils_Date::format($params['end_date']), NULL, 'Ymd'); $today = date('Ymd'); if ($today > $endDate) { $status = self::PAST; } } if ($action & CRM_Core_Action::ADD && $status & self::PAST) { // if relationship is PAST and action is ADD, no qustion // of creating RELATED membership and return back to // calling method return; } $rel = explode('_', $params['relationship_type_id']); $relTypeId = $rel[0]; $relDirection = "_{$rel[1]}_{$rel[2]}"; $targetContact = array(); if ($action & CRM_Core_Action::ADD || $action & CRM_Core_Action::DELETE) { $contact = $contactId; $targetContact = CRM_Utils_Array::value('contact_check', $params); } elseif ($action & CRM_Core_Action::UPDATE) { $contact = $ids['contact']; $targetContact = array($ids['contactTarget'] => 1); } // Build the 'values' array for // 1. ContactA // 2. ContactB // This will allow us to check if either of the contacts in // relationship have active memberships. $values = array(); // 1. ContactA $values[$contact] = array('relatedContacts' => $targetContact, 'relationshipTypeId' => $relTypeId, 'relationshipTypeDirection' => $relDirection); // 2. ContactB if (!empty($targetContact)) { foreach ($targetContact as $cid => $donCare) { $values[$cid] = array('relatedContacts' => array($contact => 1), 'relationshipTypeId' => $relTypeId); $relTypeParams = array('id' => $relTypeId); $relTypeValues = array(); CRM_Contact_BAO_RelationshipType::retrieve($relTypeParams, $relTypeValues); if (CRM_Utils_Array::value('name_a_b', $relTypeValues) == CRM_Utils_Array::value('name_b_a', $relTypeValues)) { $values[$cid]['relationshipTypeDirection'] = '_a_b'; } else { $values[$cid]['relationshipTypeDirection'] = $relDirection == '_a_b' ? '_b_a' : '_a_b'; } } } // Now get the active memberships for all the contacts. // If contact have any valid membership(s), then add it to // 'values' array. foreach ($values as $cid => $subValues) { $memParams = array('contact_id' => $cid); $memberships = array(); CRM_Member_BAO_Membership::getValues($memParams, $memberships, $active); if (empty($memberships)) { continue; } $values[$cid]['memberships'] = $memberships; } $deceasedStatusId = array_search('Deceased', CRM_Member_PseudoConstant::membershipStatus()); // done with 'values' array. // Finally add / edit / delete memberships for the related contacts foreach ($values as $cid => $details) { if (!array_key_exists('memberships', $details)) { continue; } $mainRelatedContactId = key(CRM_Utils_Array::value('relatedContacts', $details, array())); foreach ($details['memberships'] as $membershipId => $membershipValues) { $relTypeIds = array(); if ($action & CRM_Core_Action::DELETE) { // Delete memberships of the related contacts only if relationship type exists for membership type $query = "\nSELECT relationship_type_id, relationship_direction\n FROM civicrm_membership_type\n WHERE id = {$membershipValues['membership_type_id']}"; $dao = CRM_Core_DAO::executeQuery($query); $relTypeDirs = array(); while ($dao->fetch()) { $relTypeId = $dao->relationship_type_id; $relDirection = $dao->relationship_direction; } $relTypeIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $relTypeId); if (in_array($values[$cid]['relationshipTypeId'], $relTypeIds)) { CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId, $mainRelatedContactId); } continue; } if ($action & CRM_Core_Action::UPDATE && $status & self::PAST && $membershipValues['owner_membership_id']) { // If relationship is PAST and action is UPDATE // then delete the RELATED membership CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipValues['owner_membership_id'], $membershipValues['membership_contact_id']); continue; } // add / edit the memberships for related // contacts. // Get the Membership Type Details. $membershipType = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipValues['membership_type_id']); // Check if contact's relationship type exists in membership type $relTypeDirs = array(); if (CRM_Utils_Array::value('relationship_type_id', $membershipType)) { $relTypeIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $membershipType['relationship_type_id']); } if (CRM_Utils_Array::value('relationship_direction', $membershipType)) { $relDirections = explode(CRM_Core_DAO::VALUE_SEPARATOR, $membershipType['relationship_direction']); } foreach ($relTypeIds as $key => $value) { $relTypeDirs[] = $value . '_' . $relDirections[$key]; } $relTypeDir = $details['relationshipTypeId'] . $details['relationshipTypeDirection']; if (in_array($relTypeDir, $relTypeDirs)) { // Check if relationship being created/updated is // similar to that of membership type's // relationship. $membershipValues['owner_membership_id'] = $membershipId; unset($membershipValues['id']); unset($membershipValues['membership_contact_id']); unset($membershipValues['contact_id']); unset($membershipValues['membership_id']); foreach ($details['relatedContacts'] as $relatedContactId => $donCare) { $membershipValues['contact_id'] = $relatedContactId; if ($deceasedStatusId && CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $relatedContactId, 'is_deceased')) { $membershipValues['status_id'] = $deceasedStatusId; $membershipValues['skipStatusCal'] = TRUE; } foreach (array('join_date', 'start_date', 'end_date') as $dateField) { if (CRM_Utils_Array::value($dateField, $membershipValues)) { $membershipValues[$dateField] = CRM_Utils_Date::processDate($membershipValues[$dateField]); } } if ($action & CRM_Core_Action::UPDATE) { //delete the membership record for related //contact before creating new membership record. CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId, $relatedContactId); } // check whether we have some related memberships still available $query = "\nSELECT count(*)\n FROM civicrm_membership\n LEFT JOIN civicrm_membership_status ON (civicrm_membership_status.id = civicrm_membership.status_id)\n WHERE membership_type_id = {$membershipValues['membership_type_id']} AND owner_membership_id = {$membershipValues['owner_membership_id']}\n AND is_current_member = 1"; $result = CRM_Core_DAO::singleValueQuery($query); if ($result < CRM_Utils_Array::value('max_related', $membershipValues, PHP_INT_MAX)) { CRM_Member_BAO_Membership::create($membershipValues, CRM_Core_DAO::$_nullArray); } } } elseif ($action & CRM_Core_Action::UPDATE) { // if action is update and updated relationship do // not match with the existing // membership=>relationship then we need to // delete the membership record created for // previous relationship. if (self::isDeleteRelatedMembership($relTypeIds, $contactId, $mainRelatedContactId, $relTypeId, CRM_Utils_Array::value('relationship_ids', $params))) { CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId, $mainRelatedContactId); } } } } }
/** * When we copied apiv3 from api v2 we brought across some custom behaviours - in the case of * membership a complicated return array is constructed. The original * behaviour made contact_id a required field. We still need to keep this for v3 when contact_id * is passed in as part of the reasonable expectation developers have that we will keep the api * as stable as possible * * @param array $params parameters passed into get function * @return array result for calling function */ function _civicrm_api3_membership_get_customv2behaviour(&$params, $membershipTypeId, $activeOnly) { // get the membership for the given contact ID $membershipParams = array('contact_id' => $params['contact_id']); if ($membershipTypeId) { $membershipParams['membership_type_id'] = $membershipTypeId; } $membershipValues = array(); CRM_Member_BAO_Membership::getValues($membershipParams, $membershipValues, $activeOnly); return $membershipValues; }
/** * Get conatct membership record. * * This api is used for finding an existing membership record. * This api will also return the mebership records for the contacts * having mebership based on the relationship with the direct members. * * @param Int $contactID ID of a contact * * @return Array of all found membership property values. * @access public */ function crm_get_contact_memberships($contactID) { _crm_initialize(); if (empty($contactID)) { return _crm_error('Invalid value for ContactID.'); } // get the membership for the given contact ID require_once 'CRM/Member/BAO/Membership.php'; $membership = array('contact_id' => $contactID); $membershipValues = array(); CRM_Member_BAO_Membership::getValues($membership, $membershipValues); if (empty($membershipValues)) { return _crm_error('No memberships for this contact.'); } foreach ($membershipValues as $membershipId => $values) { // populate the membership type name for the membership type id require_once 'CRM/Member/BAO/MembershipType.php'; $membershipType = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($values['membership_type_id']); $membershipValues[$membershipId]['membership_name'] = $membershipType['name']; $relationships[$membershipType['relationship_type_id']] = $membershipId; // populating relationship type name. require_once 'CRM/Contact/BAO/RelationshipType.php'; $relationshipType = new CRM_Contact_BAO_RelationshipType(); $relationshipType->id = $membershipType['relationship_type_id']; if ($relationshipType->find(true)) { $membershipValues[$membershipId]['relationship_name'] = $relationshipType->name_a_b; } } $members[$contactID] = $membershipValues; // populating contacts in members array based on their relationship with direct members. require_once 'CRM/Contact/BAO/Relationship.php'; foreach ($relationships as $relTypeId => $membershipId) { // As members are not direct members, there should not be // membership id in the result array. unset($membershipValues[$membershipId]['id']); $relationship = new CRM_Contact_BAO_Relationship(); $relationship->contact_id_b = $contactID; $relationship->relationship_type_id = $relTypeId; if ($relationship->find()) { while ($relationship->fetch()) { clone $relationship; $membershipValues[$membershipId]['contact_id'] = $relationship->contact_id_a; $members[$contactID][$relationship->contact_id_a] = $membershipValues[$membershipId]; } } } return $members; }
/** * Process the form. * * @return void */ public function postProcess() { $params = $this->controller->exportValues($this->_name); $status = NULL; // now set the values for the billing location. foreach ($this->_fields as $name => $value) { $fields[$name] = 1; } $fields["email-{$this->_bltID}"] = 1; $processorParams = array(); foreach ($params as $key => $val) { $key = str_replace('billing_', '', $key); list($key) = explode('-', $key); $processorParams[$key] = $val; } $processorParams['state_province'] = CRM_Core_PseudoConstant::stateProvince($params["billing_state_province_id-{$this->_bltID}"], FALSE); $processorParams['country'] = CRM_Core_PseudoConstant::country($params["billing_country_id-{$this->_bltID}"], FALSE); $processorParams['month'] = $processorParams['credit_card_exp_date']['M']; $processorParams['year'] = $processorParams['credit_card_exp_date']['Y']; $processorParams['subscriptionId'] = $this->_subscriptionDetails->subscription_id; $processorParams['amount'] = $this->_subscriptionDetails->amount; $updateSubscription = $this->_paymentProcessorObj->updateSubscriptionBillingInfo($message, $processorParams); if (is_a($updateSubscription, 'CRM_Core_Error')) { CRM_Core_Error::displaySessionError($updateSubscription); } elseif ($updateSubscription) { $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_subscriptionDetails->contact_id, 'contact_type'); $contact =& CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $this->_subscriptionDetails->contact_id, NULL, NULL, $ctype); // build tpl params if ($this->_subscriptionDetails->membership_id) { $inputParams = array('id' => $this->_subscriptionDetails->membership_id); CRM_Member_BAO_Membership::getValues($inputParams, $tplParams); $tplParams = $tplParams[$this->_subscriptionDetails->membership_id]; $tplParams['membership_status'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipStatus', $tplParams['status_id']); $tplParams['membershipType'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $tplParams['membership_type_id']); $status = ts('Billing details for your automatically renewed %1 membership have been updated.', array(1 => $tplParams['membershipType'])); $msgTitle = ts('Details Updated'); $msgType = 'success'; } else { $status = ts('Billing details for the recurring contribution of %1, every %2 %3 have been updated.', array(1 => $this->_subscriptionDetails->amount, 2 => $this->_subscriptionDetails->frequency_interval, 3 => $this->_subscriptionDetails->frequency_unit)); $msgTitle = ts('Details Updated'); $msgType = 'success'; $tplParams = array('recur_frequency_interval' => $this->_subscriptionDetails->frequency_interval, 'recur_frequency_unit' => $this->_subscriptionDetails->frequency_unit, 'amount' => $this->_subscriptionDetails->amount); } // format new address for display $addressParts = array("street_address", "city", "postal_code", "state_province", "country"); foreach ($addressParts as $part) { $addressParts[$part] = CRM_Utils_Array::value($part, $processorParams); } $tplParams['address'] = CRM_Utils_Address::format($addressParts); // format old address to store in activity details $this->_defaults["state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvince($this->_defaults["state_province-{$this->_bltID}"], FALSE); $this->_defaults["country-{$this->_bltID}"] = CRM_Core_PseudoConstant::country($this->_defaults["country-{$this->_bltID}"], FALSE); $addressParts = array("street_address", "city", "postal_code", "state_province", "country"); foreach ($addressParts as $part) { $key = "{$part}-{$this->_bltID}"; $addressParts[$part] = CRM_Utils_Array::value($key, $this->_defaults); } $this->_defaults['address'] = CRM_Utils_Address::format($addressParts); // format new billing name $name = $processorParams['first_name']; if (!empty($processorParams['middle_name'])) { $name .= " {$processorParams['middle_name']}"; } $name .= ' ' . $processorParams['last_name']; $name = trim($name); $tplParams['billingName'] = $name; // format old billing name $name = $this->_defaults['first_name']; if (!empty($this->_defaults['middle_name'])) { $name .= " {$this->_defaults['middle_name']}"; } $name .= ' ' . $this->_defaults['last_name']; $name = trim($name); $this->_defaults['billingName'] = $name; $message .= "\n<br/><br/>New Billing Name and Address\n<br/>==============================\n<br/>{$tplParams['billingName']}\n<br/>{$tplParams['address']}\n\n<br/><br/>Previous Billing Name and Address\n<br/>==================================\n<br/>{$this->_defaults['billingName']}\n<br/>{$this->_defaults['address']}"; $activityParams = array('source_contact_id' => $this->_subscriptionDetails->contact_id, 'activity_type_id' => CRM_Core_OptionGroup::getValue('activity_type', 'Update Recurring Contribution Billing Details', 'name'), 'subject' => ts('Recurring Contribution Billing Details Updated'), 'details' => $message, 'activity_date_time' => date('YmdHis'), 'status_id' => CRM_Core_OptionGroup::getValue('activity_status', 'Completed', 'name')); $session = CRM_Core_Session::singleton(); $cid = $session->get('userID'); if ($cid) { $activityParams['target_contact_id'][] = $activityParams['source_contact_id']; $activityParams['source_contact_id'] = $cid; } CRM_Activity_BAO_Activity::create($activityParams); // send notification if ($this->_subscriptionDetails->contribution_page_id) { CRM_Core_DAO::commonRetrieveAll('CRM_Contribute_DAO_ContributionPage', 'id', $this->_subscriptionDetails->contribution_page_id, $value, array('title', 'receipt_from_name', 'receipt_from_email')); $receiptFrom = '"' . CRM_Utils_Array::value('receipt_from_name', $value[$this->_subscriptionDetails->contribution_page_id]) . '" <' . $value[$this->_subscriptionDetails->contribution_page_id]['receipt_from_email'] . '>'; } else { $domainValues = CRM_Core_BAO_Domain::getNameAndEmail(); $receiptFrom = "{$domainValues['0']} <{$domainValues['1']}>"; } list($donorDisplayName, $donorEmail) = CRM_Contact_BAO_Contact::getContactDetails($this->_subscriptionDetails->contact_id); $tplParams['contact'] = array('display_name' => $donorDisplayName); $date = CRM_Utils_Date::format($processorParams['credit_card_exp_date']); $tplParams['credit_card_exp_date'] = CRM_Utils_Date::mysqlToIso($date); $tplParams['credit_card_number'] = CRM_Utils_System::mungeCreditCard($processorParams['credit_card_number']); $tplParams['credit_card_type'] = $processorParams['credit_card_type']; $sendTemplateParams = array('groupName' => $this->_subscriptionDetails->membership_id ? 'msg_tpl_workflow_membership' : 'msg_tpl_workflow_contribution', 'valueName' => $this->_subscriptionDetails->membership_id ? 'membership_autorenew_billing' : 'contribution_recurring_billing', 'contactId' => $this->_subscriptionDetails->contact_id, 'tplParams' => $tplParams, 'isTest' => $this->_subscriptionDetails->is_test, 'PDFFilename' => 'receipt.pdf', 'from' => $receiptFrom, 'toName' => $donorDisplayName, 'toEmail' => $donorEmail); list($sent) = CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams); } else { $status = ts('There was some problem updating the billing details.'); $msgTitle = ts('Update Error'); $msgType = 'error'; } $session = CRM_Core_Session::singleton(); $userID = $session->get('userID'); if ($userID && $status) { $session->setStatus($status, $msgTitle, $msgType); } elseif (!$userID) { if ($status) { CRM_Utils_System::setUFMessage($status); } $result = (int) ($updateSubscription && isset($ctype)); if (isset($tplParams)) { $session->set('resultParams', $tplParams); } return CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/subscriptionstatus', "reset=1&task=billing&result={$result}")); } }
/** * Function to process the form * * @access public * * @return None */ public function postProcess() { $status = $message = NULL; $cancelSubscription = TRUE; $params = $this->controller->exportValues($this->_name); if ($this->_selfService) { // for self service force sending-request & notify if ($this->_paymentProcessorObj->isSupported('cancelSubscription')) { $params['send_cancel_request'] = 1; } if ($this->_donorEmail) { $params['is_notify'] = 1; } } if (CRM_Utils_Array::value('send_cancel_request', $params) == 1) { $cancelParams = array('subscriptionId' => $this->_subscriptionDetails->subscription_id); $cancelSubscription = $this->_paymentProcessorObj->cancelSubscription($message, $cancelParams); } if (is_a($cancelSubscription, 'CRM_Core_Error')) { CRM_Core_Error::displaySessionError($cancelSubscription); } elseif ($cancelSubscription) { $activityParams = array('subject' => $this->_mid ? ts('Auto-renewal membership cancelled') : ts('Recurring contribution cancelled'), 'details' => $message); $cancelStatus = CRM_Contribute_BAO_ContributionRecur::cancelRecurContribution($this->_subscriptionDetails->recur_id, CRM_Core_DAO::$_nullObject, $activityParams); if ($cancelStatus) { $tplParams = array(); if ($this->_mid) { $inputParams = array('id' => $this->_mid); CRM_Member_BAO_Membership::getValues($inputParams, $tplParams); $tplParams = $tplParams[$this->_mid]; $tplParams['membership_status'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipStatus', $tplParams['status_id']); $tplParams['membershipType'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $tplParams['membership_type_id']); $status = ts('The automatic renewal of your %1 membership has been cancelled as requested. This does not affect the status of your membership - you will receive a separate notification when your membership is up for renewal.', array(1 => $tplParams['membershipType'])); $msgTitle = 'Membership Renewal Cancelled'; $msgType = 'info'; } else { $tplParams['recur_frequency_interval'] = $this->_subscriptionDetails->frequency_interval; $tplParams['recur_frequency_unit'] = $this->_subscriptionDetails->frequency_unit; $tplParams['amount'] = $this->_subscriptionDetails->amount; $tplParams['contact'] = array('display_name' => $this->_donorDisplayName); $status = ts('The recurring contribution of %1, every %2 %3 has been cancelled.', array(1 => $this->_subscriptionDetails->amount, 2 => $this->_subscriptionDetails->frequency_interval, 3 => $this->_subscriptionDetails->frequency_unit)); $msgTitle = 'Contribution Cancelled'; $msgType = 'success'; } if (CRM_Utils_Array::value('is_notify', $params) == 1) { if ($this->_subscriptionDetails->contribution_page_id) { CRM_Core_DAO::commonRetrieveAll('CRM_Contribute_DAO_ContributionPage', 'id', $this->_subscriptionDetails->contribution_page_id, $value, array('title', 'receipt_from_name', 'receipt_from_email')); $receiptFrom = '"' . CRM_Utils_Array::value('receipt_from_name', $value[$this->_subscriptionDetails->contribution_page_id]) . '" <' . $value[$this->_subscriptionDetails->contribution_page_id]['receipt_from_email'] . '>'; } else { $domainValues = CRM_Core_BAO_Domain::getNameAndEmail(); $receiptFrom = "{$domainValues['0']} <{$domainValues['1']}>"; } // send notification $sendTemplateParams = array('groupName' => $this->_mode == 'auto_renew' ? 'msg_tpl_workflow_membership' : 'msg_tpl_workflow_contribution', 'valueName' => $this->_mode == 'auto_renew' ? 'membership_autorenew_cancelled' : 'contribution_recurring_cancelled', 'contactId' => $this->_subscriptionDetails->contact_id, 'tplParams' => $tplParams, 'PDFFilename' => 'receipt.pdf', 'from' => $receiptFrom, 'toName' => $this->_donorDisplayName, 'toEmail' => $this->_donorEmail); list($sent) = CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams); } } else { $msgType = 'error'; $msgTitle = ts('Error'); if ($params['send_cancel_request'] == 1) { $status = ts('Recurring contribution was cancelled successfully by the processor, but could not be marked as cancelled in the database.'); } else { $status = ts('Recurring contribution could not be cancelled in the database.'); } } } else { $status = ts('The recurring contribution could not be cancelled.'); $msgTitle = 'Error Cancelling Contribution'; $msgType = 'error'; } $session = CRM_Core_Session::singleton(); $userID = $session->get('userID'); if ($userID && $status) { $session->setStatus($status, $msgTitle, $msgType); } elseif (!$userID) { if ($status) { CRM_Utils_System::setUFMessage($status); } // keep result as 1, since we not displaying anything on the redirected page anyway return CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/subscriptionstatus', "reset=1&task=cancel&result=1")); } }
/** * Function to create / update / delete membership for related contacts. * * This function will create/update/delete membership for related * contact based on 1) contact have active membership 2) that * membership is is extedned by the same relationship type to that * of the existing relationship. * * @param $contactId Int contact id * @param $params array array of values submitted by POST * @param $ids array array of ids * @param $action which action called this function * * @static * */ static function relatedMemberships($contactId, &$params, $ids, $action = CRM_Core_Action::ADD, $active = true) { // Check the end date and set the status of the relationship // accrodingly. $status = self::CURRENT; if (!empty($params['end_date'])) { $endDate = CRM_Utils_Date::setDateDefaults($params['end_date'], null, 'Ymd'); $today = date('Ymd'); if ($today > $endDate) { $status = self::PAST; } } if ($action & CRM_Core_Action::ADD && $status & self::PAST) { // if relationship is PAST and action is ADD, no qustion // of creating RELATED membership and return back to // calling method return; } $rel = explode("_", $params['relationship_type_id']); $relTypeId = $rel[0]; $relDirection = "_{$rel[1]}_{$rel[2]}"; $targetContact = array(); if ($action & CRM_Core_Action::ADD || $action & CRM_Core_Action::DELETE) { $contact = $contactId; $targetContact = CRM_Utils_Array::value('contact_check', $params); } else { if ($action & CRM_Core_Action::UPDATE) { $contact = $ids['contact']; $targetContact = array($ids['contactTarget'] => 1); } } // Build the 'values' array for // 1. ContactA // 2. ContactB // This will allow us to check if either of the contacts in // relationship have active memberships. $values = array(); // 1. ContactA $values[$contact] = array('relatedContacts' => $targetContact, 'relationshipTypeId' => $relTypeId, 'relationshipTypeDirection' => $relDirection); // 2. ContactB if (!empty($targetContact)) { foreach ($targetContact as $cid => $donCare) { $values[$cid] = array('relatedContacts' => array($contact => 1), 'relationshipTypeId' => $relTypeId); $relTypeParams = array('id' => $relTypeId); $relTypeValues = array(); require_once 'CRM/Contact/BAO/RelationshipType.php'; CRM_Contact_BAO_RelationshipType::retrieve($relTypeParams, $relTypeValues); if (CRM_Utils_Array::value('name_a_b', $relTypeValues) == CRM_Utils_Array::value('name_b_a', $relTypeValues)) { $values[$cid]['relationshipTypeDirection'] = '_a_b'; } else { $values[$cid]['relationshipTypeDirection'] = $relDirection == '_a_b' ? '_b_a' : '_a_b'; } } } // Now get the active memberships for all the contacts. // If contact have any valid membership(s), then add it to // 'values' array. foreach ($values as $cid => $subValues) { $memParams = array('contact_id' => $cid); $memberships = array(); require_once 'CRM/Member/BAO/Membership.php'; CRM_Member_BAO_Membership::getValues($memParams, $memberships, $active); if (empty($memberships)) { continue; } $values[$cid]['memberships'] = $memberships; } // done with 'values' array. // Finally add / edit / delete memberships for the related contacts foreach ($values as $cid => $details) { if (!array_key_exists('memberships', $details)) { continue; } require_once 'CRM/Member/BAO/MembershipType.php'; foreach ($details['memberships'] as $membershipId => $membershipValues) { if ($action & CRM_Core_Action::DELETE) { // delete memberships of the related contacts. CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId); continue; } if ($action & CRM_Core_Action::UPDATE && $status & self::PAST && $membershipValues['owner_membership_id']) { // If relationship is PAST and action is UPDATE // then delete the RELATED membership CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipValues['owner_membership_id'], $membershipValues['membership_contact_id']); continue; } // add / edit the memberships for related // contacts. // Get the Membership Type Details. $membershipType = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipValues['membership_type_id']); if ("{$details['relationshipTypeId']}{$details['relationshipTypeDirection']}" == CRM_Utils_Array::value('relationship_type_id', $membershipType) . "_" . CRM_Utils_Array::value('relationship_direction', $membershipType)) { // Check if relationship being created/updated is // similar to that of membership type's // relationship. $membershipValues['owner_membership_id'] = $membershipId; unset($membershipValues['id']); unset($membershipValues['membership_contact_id']); unset($membershipValues['contact_id']); unset($membershipValues['membership_id']); foreach ($details['relatedContacts'] as $relatedContactId => $donCare) { $membershipValues['contact_id'] = $relatedContactId; if ($action & CRM_Core_Action::UPDATE) { //delete the membership record for related //contact before creating new membership record. CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId, $relatedContactId); } CRM_Member_BAO_Membership::create($membershipValues, CRM_Core_DAO::$_nullArray); } } else { if ($action & CRM_Core_Action::UPDATE) { // if action is update and updated relationship do // not match with the existing // membership=>relationship then we need to // delete the membership record created for // previous relationship. CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId, $ids['contactTarget']); } } } } }
/** * Build the form * * @access public * @return void */ public function buildQuickForm() { if ($this->_action & CRM_Core_Action::DELETE) { // Check if any contributions created for the recurring record $recurringIds = array($this->_id); $contributionCount = CRM_Contribute_BAO_ContributionRecur::getCount($recurringIds); if (isset($contributionCount[$this->_id]) && $contributionCount[$this->_id] > 0) { $this->assign('contributionCount', $contributionCount[$this->_id]); } $this->addButtons(array(array('type' => 'next', 'name' => ts('Delete'), 'spacing' => ' ', 'isDefault' => TRUE), array('type' => 'cancel', 'name' => ts('Cancel')))); return; } //need to assign custom data type to the template $this->assign('customDataType', 'ContributionRecur'); $this->assign('entityID', $this->_id); $attributes = CRM_Core_DAO::getAttribute('CRM_Contribute_DAO_ContributionRecur'); $cid = CRM_Utils_Request::retrieve('cid', 'Integer', $this); $id = CRM_Utils_Request::retrieve('crid', 'Integer', $this); $this->_paymentProcessors = $this->getValidProcessors(); $offlineRecurPaymentProcessors = array(); foreach ($this->_paymentProcessors as $processor) { if (!empty($processor['is_recur']) && !empty($processor['object']) && $processor['object']->supports('EditRecurringContribution') && $processor['is_test'] == 0) { $offlineRecurPaymentProcessors[$processor['id']] = $processor['name']; } } $paymentProcessor = $this->add('select', 'payment_processor_id', ts('Payment Processor'), array('' => ts('- select -')) + $offlineRecurPaymentProcessors, TRUE, NULL); $trxnId = $this->add('text', 'trxn_id', ts('Transaction ID'), array('class' => 'twelve')); $processorid = $this->add('text', 'processor_id', ts('Processor ID'), array('class' => 'twelve')); $financialType = $this->add('select', 'financial_type_id', ts('Financial Type'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::financialType(), TRUE, NULL); $contributionStatus = $this->add('select', 'contribution_status_id', ts('Status'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::contributionStatus(), TRUE, NULL); // Get contact memberships $contactMembershipsList = $contactMemberships = array(); $memParams = array('contact_id' => $this->_contactID); CRM_Member_BAO_Membership::getValues($memParams, $contactMembershipsList, TRUE); if (count($contactMembershipsList) > 0) { foreach ($contactMembershipsList as $memid => $mem) { $statusANDType = CRM_Member_BAO_Membership::getStatusANDTypeValues($memid); $contactMemberships[$memid] = $statusANDType[$memid]['membership_type'] . ' / ' . $statusANDType[$memid]['status'] . ' / ' . $mem['start_date'] . ' / ' . $mem['end_date']; } } if ($this->_action == 1) { $memberships = $this->add('select', 'membership_id', ts('Membership'), array('' => ts('- select -')) + $contactMemberships, FALSE, NULL); } $totalAmount = $this->addMoney('amount', ts('Amount'), TRUE, NULL, TRUE, 'currency', NULL, FALSE); $paymentInstrument = $this->add('select', 'payment_instrument_id', ts('Paid By'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(), TRUE, NULL); $frequencyUnit = $this->add('select', 'frequency_unit', NULL, array('' => ts('- select -')) + CRM_Core_OptionGroup::values('recur_frequency_units', FALSE, FALSE, FALSE, NULL, 'name'), TRUE, NULL); $frequencyInterval = $this->add('text', 'frequency_interval', ts('Every'), array('maxlength' => 2, 'size' => 2), TRUE); // add dates $this->addDateTime('start_date', ts('Start Date'), TRUE, array('formatType' => 'activityDateTime')); $this->addDateTime('end_date', ts('End Date'), FALSE, array('formatType' => 'activityDateTime')); $this->addDateTime('cancel_date', ts('Cancel Date'), FALSE, array('formatType' => 'activityDateTime')); $this->addDateTime('next_sched_contribution_date', ts('Next Scheduled Contribution Date'), FALSE, array('formatType' => 'activityDateTime')); $cycleDay = $this->add('text', 'cycle_day', ts('Cycle day'), array('maxlength' => 2, 'size' => 2), TRUE); // Move recurring record to another contact/membership // Field for moving contribution to another contact/membership if (!empty($this->_id)) { $this->addEntityRef('contact_id', ts('Contact'), array('create' => TRUE, 'api' => array('extra' => array('email'))), TRUE); $this->addElement('text', 'contact_name', 'Contact', array('size' => 50, 'maxlength' => 255)); $this->addElement('hidden', 'selected_cid', 'selected_cid'); $this->addElement('checkbox', 'move_recurring_record', ts('Move Recurring Record?')); $this->addElement('checkbox', 'move_existing_contributions', ts('Move Existing Contributions?')); // Get memberships of the contact // This will allow the recur record to be attached to a different membership of the same contact $existingMemberships = array('' => ts('- select -')) + $contactMemberships; // Remove current membership during move if ($existingMemberships[$this->_membershipID]) { unset($existingMemberships[$this->_membershipID]); } $this->add('select', 'membership_record', ts('Membership'), $existingMemberships, FALSE); $this->assign('show_move_membership_field', 1); } // build associated contributions $associatedContributions = array(); $contributions = new CRM_Contribute_DAO_Contribution(); $contributions->contribution_recur_id = $this->_id; while ($contributions->find(TRUE)) { $associatedContributions[$contributions->id]['total_amount'] = $contributions->total_amount; $associatedContributions[$contributions->id]['financial_type'] = CRM_Contribute_PseudoConstant::financialType($contributions->financial_type_id); $associatedContributions[$contributions->id]['contribution_source'] = $contributions->source; $associatedContributions[$contributions->id]['receive_date'] = $contributions->receive_date; $associatedContributions[$contributions->id]['contribution_status'] = CRM_Contribute_PseudoConstant::contributionStatus($contributions->contribution_status_id); } $this->assign('associatedContributions', $associatedContributions); $this->addButtons(array(array('type' => 'upload', 'name' => ts('Save'), 'isDefault' => TRUE), array('type' => 'cancel', 'name' => ts('Cancel')))); }
/** * Function to calculate start date and end date for renewal membership * * @param int $membershipId * * @return Array array fo the start date, end date and join date of the membership * @static */ function getRenewalDatesForMembershipType($membershipId, $changeToday = null) { require_once 'CRM/Member/BAO/Membership.php'; require_once 'CRM/Member/BAO/MembershipStatus.php'; $params = array('id' => $membershipId); $membership =& new CRM_Member_BAO_Membership(); //$membership->copyValues( $params ); $membership->id = $membershipId; $membership->find(true); $membershipDetails = CRM_Member_BAO_Membership::getValues($params, $values); $statusID = $membershipDetails[$membershipId]->status_id; $membershipTypeDetails = self::getMembershipTypeDetails($membershipDetails[$membershipId]->membership_type_id); $statusDetails = CRM_Member_BAO_MembershipStatus::getMembershipStatus($statusID); if ($statusDetails['is_current_member'] == 1) { $startDate = $membershipDetails[$membershipId]->start_date; $date = explode('-', $membershipDetails[$membershipId]->end_date); $logStartDate = date('Y-m-d', mktime(0, 0, 0, (double) $date[1], (double) ($date[2] + 1), (double) $date[0])); $date = explode('-', $logStartDate); $year = $date[0]; $month = $date[1]; $day = $date[2]; switch ($membershipTypeDetails['duration_unit']) { case 'year': $year = $year + $membershipTypeDetails['duration_interval']; break; case 'month': $month = $month + $membershipTypeDetails['duration_interval']; break; case 'day': $day = $day + $membershipTypeDetails['duration_interval']; break; } if ($membershipTypeDetails['duration_unit'] == 'lifetime') { $endDate = null; } else { $endDate = date('Y-m-d', mktime(0, 0, 0, $month, $day - 1, $year)); } $today = date('Y-m-d'); } else { $today = CRM_Utils_Date::getToday($changeToday); $rollover = false; if ($membershipTypeDetails['period_type'] == 'rolling') { $startDate = $logStartDate = $today; } else { if ($membershipTypeDetails['period_type'] == 'fixed') { // Renewing expired membership is two step process. // 1. Renew the start date // 2. Renew the end date // 1. $date = explode('-', $membershipDetails[$membershipId]->start_date); $yearValue = date('Y'); $startDate = $logStartDate = date('Y-m-d', mktime(0, 0, 0, (double) $date[1], (double) $date[2], $yearValue)); // before moving to the step 2, check if TODAY is in // rollover window. $rolloverDay = substr($membershipTypeDetails['fixed_period_rollover_day'], -2); $rolloverMonth = substr($membershipTypeDetails['fixed_period_rollover_day'], 0, -2); $fixedStartMonth = substr($membershipTypeDetails['fixed_period_start_day'], 0, -2); if ($rolloverMonth - $fixedStartMonth < 0) { $rolloverDate = date('Ymd', mktime(0, 0, 0, (double) $rolloverMonth, (double) $rolloverDay, $yearValue + 1)); } else { $rolloverDate = date('Ymd', mktime(0, 0, 0, (double) $rolloverMonth, (double) $rolloverDay, $yearValue)); } if (CRM_Utils_Date::isoToMysql($today) > $rolloverDate) { $rollover = true; } } } // 2. $date = explode('-', $startDate); $year = (double) $date[0]; $month = (double) $date[1]; $day = (double) $date[2]; switch ($membershipTypeDetails['duration_unit']) { case 'year': $year = $year + $membershipTypeDetails['duration_interval']; if ($rollover) { $year = $year + $membershipTypeDetails['duration_interval']; } break; case 'month': $month = $month + $membershipTypeDetails['duration_interval']; if ($rollover) { $month = $month + $membershipTypeDetails['duration_interval']; } break; case 'day': $day = $day + $membershipTypeDetails['duration_interval']; if ($rollover) { $day = $day + $membershipTypeDetails['duration_interval']; } break; } if ($membershipTypeDetails['duration_unit'] == 'lifetime') { $endDate = null; } else { $endDate = date('Y-m-d', mktime(0, 0, 0, $month, $day - 1, $year)); } } $membershipDates = array(); $membershipDates['today'] = CRM_Utils_Date::customFormat($today, '%Y%m%d'); $membershipDates['start_date'] = CRM_Utils_Date::customFormat($startDate, '%Y%m%d'); $membershipDates['end_date'] = CRM_Utils_Date::customFormat($endDate, '%Y%m%d'); if (CRM_Utils_Array::value("renewal_reminder_day", $membershipTypeDetails)) { $date = explode('-', $endDate); $year = $date[0]; $month = $date[1]; $day = $date[2]; $day = $day - $membershipTypeDetails["renewal_reminder_day"]; $reminderDate = date('Y-m-d', mktime(0, 0, 0, $month, $day - 1, $year)); $membershipDates['reminder_date'] = CRM_Utils_Date::customFormat($reminderDate, '%Y%m%d'); } $membershipDates['log_start_date'] = CRM_Utils_Date::customFormat($logStartDate, '%Y%m%d'); return $membershipDates; }