Merge pull request #4093 from yashodha/CRM-15219
[civicrm-core.git] / CRM / Member / BAO / Membership.php
index a91081a1301ccc57f7618f435e331e3d24feb903..3ba09975e33010a3b4c4cdcb4dd62d9ddfe8b388 100644 (file)
@@ -317,22 +317,30 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership {
       );
     }
 
+    $params['skipLineItem'] = TRUE;
+
     //record contribution for this membership
     if (!empty($params['contribution_status_id']) && empty($params['relate_contribution_id'])) {
       $memInfo = array_merge($params, array('membership_id' => $membership->id));
       $params['contribution'] = self::recordMembershipContribution($memInfo, $ids);
     }
 
+    if (!empty($params['lineItems'])) {
+      $params['line_item'] = $params['lineItems'];
+    }
+
+    //do cleanup line  items if membership edit the Membership type.
+    if (empty($ids['contribution']) && !empty($ids['membership'])) {
+      CRM_Price_BAO_LineItem::deleteLineItems($ids['membership'], 'civicrm_membership');
+    }
+
+    if (!empty($params['line_item']) && empty($ids['contribution'])) {
+      CRM_Price_BAO_LineItem::processPriceSet($membership->id, $params['line_item'], CRM_Utils_Array::value('contribution', $params));
+    }
+
     //insert payment record for this membership
     if (!empty($params['relate_contribution_id'])) {
-      $mpDAO = new CRM_Member_DAO_MembershipPayment();
-      $mpDAO->membership_id = $membership->id;
-      $mpDAO->contribution_id = $params['relate_contribution_id'];
-      if (!($mpDAO->find(TRUE))) {
-        CRM_Utils_Hook::pre('create', 'MembershipPayment', NULL, $mpDAO);
-        $mpDAO->save();
-        CRM_Utils_Hook::post('create', 'MembershipPayment', $mpDAO->id, $mpDAO);
-      }
+      CRM_Member_BAO_MembershipPayment::create(array('membership_id' => $membership->id, 'contribution_id' => $params['relate_contribution_id']));
     }
 
     // add activity record only during create mode and renew mode
@@ -428,7 +436,7 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership {
    * @param int $membershipId membership id
    * @param int $contactId contact id
    *
-   * @param const $action
+   * @param integer $action
    *
    * @return Array    array of contact_id of all related contacts.
    * @static
@@ -717,7 +725,7 @@ INNER JOIN  civicrm_membership_type type ON ( type.id = membership.membership_ty
    * @param boolean $thankPage thank you page
    * @param null $isTest
    *
-   * @return bool|mixed
+   * @return bool Is this a separate membership payment
    * @internal param int $pageId contribution page id
    * @internal param bool $memContactId contact who is to be
    * checked for having a current membership for a particular membership
@@ -978,8 +986,11 @@ INNER JOIN  civicrm_membership_type type ON ( type.id = membership.membership_ty
     }
 
     //avoid pending membership as current membership: CRM-3027
-    $pendingStatusId = array_search('Pending', CRM_Member_PseudoConstant::membershipStatus());
-    $dao->whereAdd("status_id != $pendingStatusId");
+    $statusIds[] = array_search('Pending', CRM_Member_PseudoConstant::membershipStatus());
+    if (!$membershipId) {
+      $statusIds[] = array_search('Cancelled', CRM_Member_PseudoConstant::membershipStatus());
+    }
+    $dao->whereAdd('status_id NOT IN ( ' . implode(',',  $statusIds) . ')');
 
     // order by start date to find most recent membership first, CRM-4545
     $dao->orderBy('start_date DESC');
@@ -1236,7 +1247,7 @@ AND civicrm_membership.is_test = %2";
    *
    * @param array $membershipParams array of membership fields
    * @param int $contactID contact id
-   * @param object $form form object
+   * @param CRM_Contribute_Form_Contribution_Confirm $form Confirmation form object
    *
    * @param $premiumParams
    * @param null $customFieldsFormatted
@@ -1244,27 +1255,24 @@ AND civicrm_membership.is_test = %2";
    *
    * @param array $membershipDetails
    *
-   * @param array $membershipTypeID
+   * @param array $membershipTypeIDs
    *
    * @param bool $isPaidMembership
-   * @param integer $membershipID
+   * @param array $membershipID
    *
    * @param $isProcessSeparateMembershipTransaction
    *
    * @param $defaultContributionTypeID
-   *
+   * @param array $membershipLineItems Line items specific to membership payment that is separate to contribution
    * @throws CRM_Core_Exception
-   * @internal param \isProcessSeparateMembershipTransaction $bool $
-   *
-   * @internal param $singleMembershipTypeID
    *
    * @return void
    * @access public
    */
   public static function postProcessMembership($membershipParams, $contactID, &$form, $premiumParams,
-    $customFieldsFormatted = NULL, $includeFieldTypes = NULL, $membershipDetails, $membershipTypeID, $isPaidMembership, $membershipID,
-    $isProcessSeparateMembershipTransaction, $defaultContributionTypeID) {
-    $result      = NULL;
+    $customFieldsFormatted = NULL, $includeFieldTypes = NULL, $membershipDetails, $membershipTypeIDs, $isPaidMembership, $membershipID,
+    $isProcessSeparateMembershipTransaction, $defaultContributionTypeID, $membershipLineItems) {
+    $result      = $membershipContribution = NULL;
     $isTest      = CRM_Utils_Array::value('is_test', $membershipParams, FALSE);
     $errors = $createdMemberships = array();
 
@@ -1288,7 +1296,8 @@ AND civicrm_membership.is_test = %2";
 
     if ($isProcessSeparateMembershipTransaction) {
       try {
-        $membershipContribution = self::processSecondaryFinancialTransaction($contactID, $form, $membershipDetails, $membershipParams, $isTest);
+        $lineItems = $form->_lineItem = $membershipLineItems;
+        $membershipContribution = self::processSecondaryFinancialTransaction($contactID, $form, $membershipParams, $isTest, $membershipLineItems, CRM_Utils_Array::value('minimum_fee', $membershipDetails, 0), CRM_Utils_Array::value('financial_type_id', $membershipDetails));
       }
       catch (CRM_Core_Exception $e) {
         $errors[2] = $e->getMessage();
@@ -1297,36 +1306,36 @@ AND civicrm_membership.is_test = %2";
     }
 
     $membership = NULL;
-    if (!empty($membershipContribution) && !is_a($membershipContribution, 'CRM_Core_Error')) { {
+    if (!empty($membershipContribution) && !is_a($membershipContribution, 'CRM_Core_Error')) {
       $membershipContributionID = $membershipContribution->id;
     }
-      //@todo - why is this nested so deep? it seems like it could be just set on the calling function on the form layer
-      if (isset($membershipParams['onbehalf']) && !empty($membershipParams['onbehalf']['member_campaign_id'])) {
-        $form->_params['campaign_id'] = $membershipParams['onbehalf']['member_campaign_id'];
+
+    //@todo - why is this nested so deep? it seems like it could be just set on the calling function on the form layer
+    if (isset($membershipParams['onbehalf']) && !empty($membershipParams['onbehalf']['member_campaign_id'])) {
+      $form->_params['campaign_id'] = $membershipParams['onbehalf']['member_campaign_id'];
+    }
+    //@todo it should no longer be possible for it to get to this point & membership to not be an array
+    if (is_array($membershipTypeIDs) && !empty($membershipContributionID)) {
+      $typesTerms = CRM_Utils_Array::value('types_terms', $membershipParams, array());
+      foreach ($membershipTypeIDs as $memType) {
+        $numTerms = CRM_Utils_Array::value($memType, $typesTerms, 1);
+        $createdMemberships[$memType] = self::createOrRenewMembership($membershipParams, $contactID, $customFieldsFormatted, $membershipID, $memType, $isTest, $numTerms, $membershipContribution, $form);
       }
-      //!!B
-      if (is_array($membershipTypeID)) {
-        $typesTerms = CRM_Utils_Array::value('types_terms', $membershipParams, array());
-        foreach ($membershipTypeID as $memType) {
-          $numTerms = CRM_Utils_Array::value($memType, $typesTerms, 1);
-          $createdMemberships[$memType] = self::createOrRenewMembership($membershipParams, $contactID, $customFieldsFormatted, $membershipID, $memType, $isTest, $numTerms, $membershipContribution, $form);
-        }
-        if ($form->_priceSetId && !empty($form->_useForMember) && !empty($form->_lineItem)) {
-          foreach ($form->_lineItem[$form->_priceSetId] as & $priceFieldOp) {
-            if (!empty($priceFieldOp['membership_type_id']) &&
-              isset($createdMemberships[$priceFieldOp['membership_type_id']])
-            ) {
-              $membershipOb = $createdMemberships[$priceFieldOp['membership_type_id']];
-              $priceFieldOp['start_date'] = $membershipOb->start_date ? CRM_Utils_Date::customFormat($membershipOb->start_date, '%d%f %b, %Y') : '-';
-              $priceFieldOp['end_date'] = $membershipOb->end_date ? CRM_Utils_Date::customFormat($membershipOb->end_date, '%d%f %b, %Y') : '-';
-            }
-            else {
-              $priceFieldOp['start_date'] = $priceFieldOp['end_date'] = 'N/A';
-            }
+      if ($form->_priceSetId && !empty($form->_useForMember) && !empty($form->_lineItem)) {
+        foreach ($form->_lineItem[$form->_priceSetId] as & $priceFieldOp) {
+          if (!empty($priceFieldOp['membership_type_id']) &&
+            isset($createdMemberships[$priceFieldOp['membership_type_id']])
+          ) {
+            $membershipOb = $createdMemberships[$priceFieldOp['membership_type_id']];
+            $priceFieldOp['start_date'] = $membershipOb->start_date ? CRM_Utils_Date::customFormat($membershipOb->start_date, '%B %E%f, %Y') : '-';
+            $priceFieldOp['end_date'] = $membershipOb->end_date ? CRM_Utils_Date::customFormat($membershipOb->end_date, '%B %E%f, %Y') : '-';
+          }
+          else {
+            $priceFieldOp['start_date'] = $priceFieldOp['end_date'] = 'N/A';
           }
-          $form->_values['lineItem'] = $form->_lineItem;
-          $form->assign('lineItem', $form->_lineItem);
         }
+        $form->_values['lineItem'] = $form->_lineItem;
+        $form->assign('lineItem', $form->_lineItem);
       }
     }
 
@@ -1485,7 +1494,7 @@ AND civicrm_membership.is_test = %2";
    * then status will be updated based on existing start and end
    * dates and log will be added for the status change.
    *
-   * @param  array  $currentMembership   referance to the array
+   * @param  array  $currentMembership   reference to the array
    *                                     containing all values of
    *                                     the current membership
    * @param  array  $changeToday         array of month, day, year
@@ -2086,21 +2095,22 @@ INNER JOIN  civicrm_contact contact ON ( contact.id = membership.contact_id AND
    * Where a second separate financial transaction is supported we will process it here
    *
    * @param $contactID
-   * @param $form
-   * @param $membershipDetails
+   * @param CRM_Contribute_Form_Contribution_Confirm $form
    * @param $tempParams
-   * @param $errors
    * @param $isTest
    *
+   * @param $lineItems
+   * @param $minimumFee
+   * @param $financialTypeID
+   *
+   * @throws CRM_Core_Exception
    * @throws Exception
-   * @internal param $minimumFee
+   * @internal param $membershipDetails
    * @return CRM_Contribute_BAO_Contribution
    */
-  public static function processSecondaryFinancialTransaction($contactID, &$form, $membershipDetails, $tempParams, $isTest) {
-    $minimumFee = CRM_Utils_Array::value('minimum_fee', $membershipDetails);
-    $lineItems = $form->_lineItem = $form->_memLineItem;
+  public static function processSecondaryFinancialTransaction($contactID, &$form, $tempParams, $isTest, $lineItems, $minimumFee, $financialTypeID) {
     $contributionType = new CRM_Financial_DAO_FinancialType();
-    $contributionType->id = CRM_Utils_Array::value('financial_type_id', $membershipDetails);
+    $contributionType->id = $financialTypeID;
     if (!$contributionType->find(TRUE)) {
       CRM_Core_Error::fatal(ts("Could not find a system table"));
     }
@@ -2136,15 +2146,18 @@ INNER JOIN  civicrm_contact contact ON ( contact.id = membership.contact_id AND
       $form->set('membership_trx_id', $result['trxn_id']);
       $form->set('membership_amount', $minimumFee);
 
+      $form->assign('membership_trx_id', $result['trxn_id']);
+      $form->assign('membership_amount', $minimumFee);
+
       // we don't need to create the user twice, so lets disable cms_create_account
       // irrespective of the value, CRM-2888
       $tempParams['cms_create_account'] = 0;
 
-      $pending = $form->_params['is_pay_later'] ? ((CRM_Utils_Array::value('minimum_fee', $membershipDetails, 0) > 0.0) ? TRUE : FALSE) : FALSE;
+      $pending = $form->_params['is_pay_later'] ? (($minimumFee > 0.0) ? TRUE : FALSE) : FALSE;
 
       //set this variable as we are not creating pledge for
       //separate membership payment contribution.
-      //so for differentiating membership contributon from
+      //so for differentiating membership contribution from
       //main contribution.
       $form->_params['separate_membership_payment'] = 1;
       $membershipContribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($form,
@@ -2194,10 +2207,10 @@ INNER JOIN  civicrm_contact contact ON ( contact.id = membership.contact_id AND
       $membershipID
     );
 
-    // update recurring id for membership record
-    self::updateRecurMembership($membership, $membershipContribution);
-
     if (!empty($membershipContribution)) {
+      // update recurring id for membership record
+      self::updateRecurMembership($membership, $membershipContribution);
+
       self::linkMembershipPayment($membership, $membershipContribution);
     }
     return $membership;
@@ -2364,7 +2377,7 @@ INNER JOIN  civicrm_contact contact ON ( contact.id = membership.contact_id AND
           );
         }
 
-        return $membership;
+        return array($membership, $renewalMode, $dates);
       }
 
       // Check and fix the membership if it is STALE
@@ -2807,7 +2820,7 @@ WHERE      civicrm_membership.is_test = 0";
       'contact_id', 'total_amount', 'receive_date', 'financial_type_id',
       'payment_instrument_id', 'trxn_id', 'invoice_id', 'is_test',
       'contribution_status_id', 'check_number', 'campaign_id', 'is_pay_later',
-      'membership_id',
+      'membership_id', 'skipLineItem'
     );
     foreach ($recordContribution as $f) {
       $contributionParams[$f] = CRM_Utils_Array::value($f, $params);
@@ -2831,7 +2844,7 @@ WHERE      civicrm_membership.is_test = 0";
 
     $contribution = CRM_Contribute_BAO_Contribution::create($contributionParams, $ids);
 
-    //CRM-13981, create new soft-credit record as to record payment from differnt person for this membership
+    //CRM-13981, create new soft-credit record as to record payment from different person for this membership
     if (!empty($contributionSoftParams)) {
       $contributionSoftParams['contribution_id'] = $contribution->id;
       $contributionSoftParams['currency'] = $contribution->currency;
@@ -2845,16 +2858,7 @@ WHERE      civicrm_membership.is_test = 0";
 
     //insert payment record for this membership
     if (empty($ids['contribution']) || !empty($params['is_recur'])) {
-      $mpDAO = new CRM_Member_DAO_MembershipPayment();
-      $mpDAO->membership_id = $membershipId;
-      $mpDAO->contribution_id = $contribution->id;
-      if (!empty($params['is_recur'])) {
-        $mpDAO->find();
-      }
-
-      CRM_Utils_Hook::pre('create', 'MembershipPayment', NULL, $mpDAO);
-      $mpDAO->save();
-      CRM_Utils_Hook::post('create', 'MembershipPayment', $mpDAO->id, $mpDAO);
+      CRM_Member_BAO_MembershipPayment::create(array('membership_id' => $membershipId, 'contribution_id' => $contribution->id));
     }
     return $contribution;
   }
@@ -2913,4 +2917,34 @@ WHERE      civicrm_membership.is_test = 0";
     self::$_renewalActType = CRM_Utils_Array::key('Membership Renewal', $activityTypes);
     self::$_signupActType = CRM_Utils_Array::key('Membership Signup', $activityTypes);
   }
+
+  /**
+   * Get all Cancelled Membership(s) for a contact
+   *
+   * @param int    $contactID   contact id
+   * @param boolean  $isTest    mode of payment
+   *
+   * @return array of membership type
+   * @static
+   * @access public
+   */
+  static function getContactsCancelledMembership($contactID, $isTest = FALSE) {
+    if (!$contactID) {
+      return array();
+    }
+    $allStatus = CRM_Member_PseudoConstant::membershipStatus();
+    $query = 'SELECT membership_type_id FROM civicrm_membership WHERE contact_id = %1 AND status_id = %2 AND is_test = %3';
+    $queryParams = array(
+      1 => array($contactID, 'Integer'),
+      2 => array(array_search('Cancelled', $allStatus), 'Integer'),
+      3 => array($isTest, 'Boolean'),
+    );
+
+    $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
+    $cancelledMembershipIds = array();
+    while ($dao->fetch()) {
+      $cancelledMembershipIds[] = $dao->membership_type_id;
+    }
+    return $cancelledMembershipIds;
+  }
 }