/** * Cancel Recurring contribution. * * @param integer $recurId recur contribution id. * @param array $objects an array of objects that is to be cancelled like * contribution, membership, event. At least contribution object is a must. * * @return true / false. * @access public * @static */ static function cancelRecurContribution($recurId, $objects) { if (!$recurId) { return false; } require_once 'CRM/Contribute/PseudoConstant.php'; $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(null, 'name'); $canceledId = array_search('Cancelled', $contributionStatus); $recur = new CRM_Contribute_DAO_ContributionRecur(); $recur->id = $recurId; $recur->whereAdd("contribution_status_id != {$canceledId}"); if ($recur->find(true)) { require_once 'CRM/Core/Transaction.php'; $transaction = new CRM_Core_Transaction(); $recur->contribution_status_id = $canceledId; $recur->start_date = CRM_Utils_Date::isoToMysql($recur->start_date); $recur->create_date = CRM_Utils_Date::isoToMysql($recur->create_date); $recur->modified_date = CRM_Utils_Date::isoToMysql($recur->modified_date); $recur->cancel_date = date('YmdHis'); $recur->save(); require_once 'CRM/Core/Payment/BaseIPN.php'; $baseIPN = new CRM_Core_Payment_BaseIPN(); return $baseIPN->cancelled($objects, $transaction); } return false; }
/** * Cancel Recurring contribution. * * @param int $recurId * Recur contribution id. * @param array $objects * An array of objects that is to be cancelled like. * contribution, membership, event. At least contribution object is a must. * * @param array $activityParams * * @return bool */ public static function cancelRecurContribution($recurId, $objects, $activityParams = array()) { if (!$recurId) { return FALSE; } $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); $canceledId = array_search('Cancelled', $contributionStatus); $recur = new CRM_Contribute_DAO_ContributionRecur(); $recur->id = $recurId; $recur->whereAdd("contribution_status_id != {$canceledId}"); if ($recur->find(TRUE)) { $transaction = new CRM_Core_Transaction(); $recur->contribution_status_id = $canceledId; $recur->start_date = CRM_Utils_Date::isoToMysql($recur->start_date); $recur->create_date = CRM_Utils_Date::isoToMysql($recur->create_date); $recur->modified_date = CRM_Utils_Date::isoToMysql($recur->modified_date); $recur->cancel_date = date('YmdHis'); $recur->save(); $dao = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($recurId); if ($dao && $dao->recur_id) { $details = CRM_Utils_Array::value('details', $activityParams); if ($dao->auto_renew && $dao->membership_id) { // its auto-renewal membership mode $membershipTypes = CRM_Member_PseudoConstant::membershipType(); $membershipType = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $dao->membership_id, 'membership_type_id'); $membershipType = CRM_Utils_Array::value($membershipType, $membershipTypes); $details .= ' <br/>' . ts('Automatic renewal of %1 membership cancelled.', array(1 => $membershipType)); } else { $details .= ' <br/>' . ts('The recurring contribution of %1, every %2 %3 has been cancelled.', array(1 => $dao->amount, 2 => $dao->frequency_interval, 3 => $dao->frequency_unit)); } $activityParams = array('source_contact_id' => $dao->contact_id, 'source_record_id' => CRM_Utils_Array::value('source_record_id', $activityParams), 'activity_type_id' => CRM_Core_OptionGroup::getValue('activity_type', 'Cancel Recurring Contribution', 'name'), 'subject' => CRM_Utils_Array::value('subject', $activityParams, ts('Recurring contribution cancelled')), 'details' => $details, '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); } // if there are associated objects, cancel them as well if ($objects == CRM_Core_DAO::$_nullObject) { $transaction->commit(); return TRUE; } else { $baseIPN = new CRM_Core_Payment_BaseIPN(); return $baseIPN->cancelled($objects, $transaction); } } else { // if already cancelled, return true $recur->whereAdd(); $recur->whereAdd("contribution_status_id = {$canceledId}"); if ($recur->find(TRUE)) { return TRUE; } } return FALSE; }
function _process_csv($csv_array, $csv_name, $mail_date) { $this->_addToSummary("Processing {$csv_name}"); foreach ($csv_array as $row) { $this->_addToSummary(null); // insert blank line. // check if this is a blank line if (count($row) <= 1) { continue; } $subscriptionId = $row[0]; $subscriptionStatus = $row[1]; $paymentNum = $row[2]; $totalRecurrences = $row[3]; $transactionId = $row[4]; $amount = $row[5]; $currency = $row[6]; $custFirstName = $row[8]; $custLastName = $row[9]; $contributionStatus = $row[10]; $recur = new CRM_Contribute_DAO_ContributionRecur(); $first_contribution = new CRM_Contribute_DAO_Contribution(); // If this is the first payment, load recurring contribution and update if ($paymentNum == 1) { // Load contribution using SubscriptionID as trxn_id $first_contribution->trxn_id = $subscriptionId; if (!$first_contribution->find(true)) { $this->_addToSummary("THE RECURRING TRANSACTION FOR SUBSCRIPTION {$subscriptionId} COULD NOT BE FOUND. A TRANSACTION HAS OCCURED THAT WAS NOT EXPECTED. PLEASE REVIEW {$csv_name}."); continue; } // Load recurring contribution from contribution $recur->id = $first_contribution->contribution_recur_id; if (!$recur->find(true)) { $this->_addToSummary("INITIAL RECURRING CONTRIBUTION NOT FOUND FOR {$subscriptionId}. PLEASE REVIEW {$csv_name}"); continue; } $recur->start_date = $mail_date; $recur->processor_id = $subscriptionId; $recur->trxn_id = $subscriptionId; $recur->contribution_status_id = _CRM_PROCESS_AUTHORIZE_REPORT_STATUS_CURRENT; // update transaction id for contribution $first_contribution->trxn_id = $transactionId; $first_contribution->receive_date = $mail_date; $first_contribution->contribution_status_id = $this->_get_contribution_status($contributionStatus); // load contribution page $contribution_page = new CRM_Contribute_DAO_ContributionPage(); $contribution_page->id = $first_contribution->contribution_page_id; if (!$contribution_page->find(true)) { $this->_addToSummary("COULD NOT FIND CONTRIBUTION PAGE FOR {$subscriptionId}. PLEASE REVIEW {$csv_name}"); continue; } // is there an email receipt if ($contribution_page->is_email_receipt) { $first_contribution->receipt_date = date('YmdHis'); } } else { $recur->processor_id = $subscriptionId; if (!$recur->find(true)) { $this->_addToSummary("THE RECURRING TRANSACTION FOR SUBSCRIPTION {$subscriptionId} COULD NOT BE FOUND. A TRANSACTION HAS OCCURED THAT WAS NOT EXPECTED. PLEASE REVIEW {$csv_name}."); continue; } $recur->modified_date = $mail_date; // load first contribution $first_contribution->contribution_recur_id = $recur->id; $first_contribution->orderBy('receive_date'); $first_contribution->limit(1); if (!$first_contribution->find(true)) { $this->_addToSummary("CONTRIBUTION RECORD FOR SUBSCRIPTION {$subscriptonId} COULD NOT BE FOUND. PLEASE REVIEW {$csv_name}"); continue; } // load contribution page $contribution_page = new CRM_Contribute_DAO_ContributionPage(); $contribution_page->id = $first_contribution->contribution_page_id; if (!$contribution_page->find(true)) { $this->_addToSummary("COULD NOT FIND CONTRIBUTION PAGE FOR {$subscriptionId}. PLEASE REVIEW {$csv_name}"); continue; } } // is this valid for failed transactions also? if ($amount != $recur->amount) { $this->_addToSummary("AN UNEXPECTED AMOUNT WAS RECEIVED FOR SUBSCRIPTION {$subscriptionId}. SKIPPING THIS TRANSACTION. PLEASE REVIEW {$csv_name}"); continue; } // Verify contact exists if (!$recur->contact_id) { // assuming if contact_id is set, contact exists $this->_addToSummary("NO USER IS ASSOCIATED WITH THE CONTRIBUTION FOR SUBSCRIPTION {$subscrptionId}, EXPECTED '{$custFirstName} {$custLastName}'. PLEASE REVIEW {$csv_name}"); continue; } // Verify number of recurrences if ($recur->installments != $totalRecurrences) { $this->_addToSummary("SUBSCRIPTION {$subscriptionId} EXPECTS {$recur->installments}, OFFERED {$totalRecurrences}. PLEASE REVIEW {$csv_name}"); continue; } // Check if this contribution is complete if (!empty($recur->end_date) && $recur->end_date != '0000-00-00 00:00:00') { $this->_addToSummary("SUBSCRIPTION {$subscriptionId} IS MARKED AS COMPLETE. PLEASE REVIEW {$csv_name}"); continue; } if (!empty($recur->cancel_date) && $recur->cancel_date != '0000-00-00 00:00:00') { $this->_addToSummary("SUBSCRIPTION {$subscriptionId} IS MARKED AS CANCELLED. PLEASE REVIEW {$csv_name}"); continue; } if ($paymentNum == $totalRecurrences) { $recur->end_date = $mail_date; $recur->contribution_status_id = _CRM_PROCESS_AUTHORIZE_REPORT_STATUS_COMPLETE; } if ($contributionStatus != CRM_Core_Payment_AuthorizeNet::AUTH_APPROVED) { $recur->failure_count++; } CRM_Core_DAO::transaction('BEGIN'); if (!$recur->save()) { $this->_addToSummary("THE RECURRING CONTRIBUTION COULD NOT BE UPDATED. PLEASE REVIEW {$csv_name} FOR subscription_id={$subscription_id}"); CRM_Core_DAO::transaction('ROLLBACK'); continue; } $this->_addToSummary("The recurring transaction has been updated."); if ($paymentNum == 1) { // update first contribution if (!$first_contribution->save()) { $this->_addToSummary("THE CONTRIBUTION COULD NOT BE UPDATED. PLEASE REVIEW {$csv_name} FOR subscription_id={$subscription_id}"); CRM_Core_DAO::transaction('ROLLBACK'); continue; } // copy $first_contribution to $contribution for use later $contribution = $first_contribution; } else { // create a contribution and then get it processed $contribution = new CRM_Contribute_DAO_Contribution(); // make sure that the transaction doesn't already exist $contribution->trxn_id = $transactionId; if ($contribution->find()) { $this->_addToSummary("THE TRANSACTION {$transaction_id} ALREADY EXISTS IN CIVICRM. PLEASE REVIEW {$csv_name} FOR subscription_id={$subscription_id}"); CRM_Core_DAO::transaction('ROLLBACK'); continue; } $contribution->contribution_recur_id = $recur->id; $contribution->receive_date = $mail_date; $contribution->total_amount = $amount; $contribution->net_amount = $amount; $contribution->trxn_id = $transactionId; $contribution->currency = $currency; $contribution->contribution_status_id = $this->_get_contribution_status($contributionStatus); $contribution->contact_id = $first_contribution->contact_id; $contribution->contribution_type_id = $first_contribution->contribution_type_id; $contribution->contribution_page_id = $first_contribution->contribution_page_id; $contribution->payment_instrument_id = $first_contribution->payment_instrument_id; $contribution->is_test = $first_contribution->is_test; $contribution->invoice_id = md5(uniqid(rand(), true)); if ($contribution_page->is_email_receipt) { $contribution->receipt_date = date('YmdHis'); } if (!$contribution->save()) { $this->_addToSummary("THE CONTRIBUTION COULD NOT BE SAVED. PLEASE REVIEW {$csv_name} FOR subscription_id={$subscription_id}"); CRM_Core_DAO::transaction('ROLLBACK'); continue; } } $this->_addToSummary('Contribution saved'); // create the transaction record $trxnParams = array('entity_table' => 'civicrm_contribution', 'entity_id' => $contribution->id, 'trxn_date' => $mail_date, 'trxn_type' => 'Debit', 'total_amount' => $amount, 'fee_amount' => $contribution->fee_amount, 'net_amount' => $contribution->net_amount, 'currency' => $contribution->currency, 'payment_processor' => 'AuthNet_AIM', 'trxn_id' => $contribution->trxn_id); require_once 'CRM/Contribute/BAO/FinancialTrxn.php'; $trxn =& CRM_Contribute_BAO_FinancialTrxn::create($trxnParams); if (is_a($trxn, 'CRM_Core_Error')) { $this->_addToSummary("A TRANSACTION RECORD COULD NOT BE CREATED. PLEASE REVIEW {$csv_name} FOR subscription_id={$subscription_id}"); CRM_Core_DAO::transaction('ROLLBACK'); continue; } else { $this->_addToSummary("Transaction record created."); } // get the title of the contribution page $title = $contribution_page->title; // format the money require_once 'CRM/Utils/Money.php'; $formattedAmount = CRM_Utils_Money::format($amount, $contribution->currency); CRM_Core_DAO::transaction('COMMIT'); // get the contribution type require_once 'CRM/Contribute/BAO/ContributionType.php'; $contribution_type_name = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionType', $contribution->contribution_type_id, 'name'); // create an activity history record $ahParams = array('entity_table' => 'civicrm_contact', 'entity_id' => $recur->contact_id, 'activity_type' => $contribution_type_name, 'module' => 'CiviContribute', 'callback' => 'CRM_Contribute_Page_Contribution::details', 'activity_id' => $contribution->id, 'activity_summary' => "{$formattedAmount} - {$title} (online)", 'activity_date' => $mail_date); require_once 'api/History.php'; if (is_a(crm_create_activity_history($ahParams), 'CRM_Core_Error')) { $this->_addToSummary("AN ACTIVITY HISTORY RECORD COULD NOT BE CREATED."); } else { $this->_addToSummary("Activity History record created."); } $this->_addToSummary("Transaction {$transactionId} has been processed."); $first_contribution->free(); $contribution_page->free(); $contribution->free(); $recur->free(); $trxn->free(); } $this->_addToSummary("Done processing {$csv_name}"); $this->_addToSummary(''); }