/** * Takes an associative array and creates a contribution object. * * @param array $params * (reference ) an assoc array of name/value pairs. * @param array $ids * The array that holds all the db ids. * * @return CRM_Contribute_BAO_Contribution */ public static function create(&$params, $ids = array()) { $dateFields = array('receive_date', 'cancel_date', 'receipt_date', 'thankyou_date'); foreach ($dateFields as $df) { if (isset($params[$df])) { $params[$df] = CRM_Utils_Date::isoToMysql($params[$df]); } } //if contribution is created with cancelled or refunded status, add credit note id if (!empty($params['contribution_status_id'])) { $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); if ($params['contribution_status_id'] == array_search('Refunded', $contributionStatus) || $params['contribution_status_id'] == array_search('Cancelled', $contributionStatus)) { if (empty($params['creditnote_id']) || $params['creditnote_id'] == "null") { $params['creditnote_id'] = self::createCreditNoteId(); } } } $transaction = new CRM_Core_Transaction(); $contribution = self::add($params, $ids); if (is_a($contribution, 'CRM_Core_Error')) { $transaction->rollback(); return $contribution; } $params['contribution_id'] = $contribution->id; if (!empty($params['custom']) && is_array($params['custom'])) { CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_contribution', $contribution->id); } $session = CRM_Core_Session::singleton(); if (!empty($params['note'])) { $noteParams = array('entity_table' => 'civicrm_contribution', 'note' => $params['note'], 'entity_id' => $contribution->id, 'contact_id' => $session->get('userID'), 'modified_date' => date('Ymd')); if (!$noteParams['contact_id']) { $noteParams['contact_id'] = $params['contact_id']; } CRM_Core_BAO_Note::add($noteParams); } // make entry in batch entity batch table if (!empty($params['batch_id'])) { // in some update cases we need to get extra fields - ie an update that doesn't pass in all these params $titleFields = array('contact_id', 'total_amount', 'currency', 'financial_type_id'); $retrieveRequired = 0; foreach ($titleFields as $titleField) { if (!isset($contribution->{$titleField})) { $retrieveRequired = 1; break; } } if ($retrieveRequired == 1) { $contribution->find(TRUE); } } CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution); $transaction->commit(); // check if activity record exist for this contribution, if // not add activity $activity = new CRM_Activity_DAO_Activity(); $activity->source_record_id = $contribution->id; $activity->activity_type_id = CRM_Core_OptionGroup::getValue('activity_type', 'Contribution', 'name'); if (!$activity->find(TRUE)) { if (empty($contribution->contact_id)) { $contribution->find(TRUE); } CRM_Activity_BAO_Activity::addActivity($contribution, 'Offline'); } else { // CRM-13237 : if activity record found, update it with campaign id of contribution CRM_Core_DAO::setFieldValue('CRM_Activity_BAO_Activity', $activity->id, 'campaign_id', $contribution->campaign_id); } // do not add to recent items for import, CRM-4399 if (empty($params['skipRecentView'])) { $url = CRM_Utils_System::url('civicrm/contact/view/contribution', "action=view&reset=1&id={$contribution->id}&cid={$contribution->contact_id}&context=home"); // in some update cases we need to get extra fields - ie an update that doesn't pass in all these params $titleFields = array('contact_id', 'total_amount', 'currency', 'financial_type_id'); $retrieveRequired = 0; foreach ($titleFields as $titleField) { if (!isset($contribution->{$titleField})) { $retrieveRequired = 1; break; } } if ($retrieveRequired == 1) { $contribution->find(TRUE); } $contributionTypes = CRM_Contribute_PseudoConstant::financialType(); $title = CRM_Contact_BAO_Contact::displayName($contribution->contact_id) . ' - (' . CRM_Utils_Money::format($contribution->total_amount, $contribution->currency) . ' ' . ' - ' . $contributionTypes[$contribution->financial_type_id] . ')'; $recentOther = array(); if (CRM_Core_Permission::checkActionPermission('CiviContribute', CRM_Core_Action::UPDATE)) { $recentOther['editUrl'] = CRM_Utils_System::url('civicrm/contact/view/contribution', "action=update&reset=1&id={$contribution->id}&cid={$contribution->contact_id}&context=home"); } if (CRM_Core_Permission::checkActionPermission('CiviContribute', CRM_Core_Action::DELETE)) { $recentOther['deleteUrl'] = CRM_Utils_System::url('civicrm/contact/view/contribution', "action=delete&reset=1&id={$contribution->id}&cid={$contribution->contact_id}&context=home"); } // add the recently created Contribution CRM_Utils_Recent::add($title, $url, $contribution->id, 'Contribution', $contribution->contact_id, NULL, $recentOther); } return $contribution; }
/** * Process the contribution. * * @param CRM_Core_Form $form * @param array $params * @param array $result * @param array $contributionParams * Parameters to be passed to contribution create action. * This differs from params in that we are currently adding params to it and 1) ensuring they are being * passed consistently & 2) documenting them here. * - contact_id * - line_item * - is_test * - campaign_id * - contribution_page_id * - source * - payment_type_id * - thankyou_date (not all forms will set this) * * @param CRM_Financial_DAO_FinancialType $financialType * @param bool $online * Is the form a front end form? If so set a bunch of unpredictable things that should be passed in from the form. * * @param int $billingLocationID * ID of billing location type. * @param bool $isRecur * Is this recurring? * * @return \CRM_Contribute_DAO_Contribution * @throws \Exception */ public static function processFormContribution(&$form, $params, $result, $contributionParams, $financialType, $online, $billingLocationID, $isRecur) { $transaction = new CRM_Core_Transaction(); $contactID = $contributionParams['contact_id']; $isEmailReceipt = !empty($form->_values['is_email_receipt']); $isSeparateMembershipPayment = empty($params['separate_membership_payment']) ? FALSE : TRUE; $pledgeID = !empty($params['pledge_id']) ? $params['pledge_id'] : CRM_Utils_Array::value('pledge_id', $form->_values); if (!$isSeparateMembershipPayment && !empty($form->_values['pledge_block_id']) && (!empty($params['is_pledge']) || $pledgeID)) { $isPledge = TRUE; } else { $isPledge = FALSE; } // add these values for the recurringContrib function ,CRM-10188 $params['financial_type_id'] = $financialType->id; $contributionParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $billingLocationID); //@todo - this is being set from the form to resolve CRM-10188 - an // eNotice caused by it not being set @ the front end // however, we then get it being over-written with null for backend contributions // a better fix would be to set the values in the respective forms rather than require // a function being shared by two forms to deal with their respective values // moving it to the BAO & not taking the $form as a param would make sense here. if (!isset($params['is_email_receipt']) && $isEmailReceipt) { $params['is_email_receipt'] = $isEmailReceipt; } $params['is_recur'] = $isRecur; $recurringContributionID = self::processRecurringContribution($form, $params, $contactID, $financialType); $nonDeductibleAmount = self::getNonDeductibleAmount($params, $financialType, $online); $now = date('YmdHis'); $receiptDate = CRM_Utils_Array::value('receipt_date', $params); if ($isEmailReceipt) { $receiptDate = $now; } if (isset($params['amount'])) { $contributionParams = array_merge(self::getContributionParams($params, $financialType->id, $nonDeductibleAmount, TRUE, $result, $receiptDate, $recurringContributionID), $contributionParams); $contribution = CRM_Contribute_BAO_Contribution::add($contributionParams); $invoiceSettings = Civi::settings()->get('contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); if ($invoicing) { $dataArray = array(); // @todo - interrogate the line items passed in on the params array. // No reason to assume line items will be set on the form. foreach ($form->_lineItem as $lineItemKey => $lineItemValue) { foreach ($lineItemValue as $key => $value) { if (isset($value['tax_amount']) && isset($value['tax_rate'])) { if (isset($dataArray[$value['tax_rate']])) { $dataArray[$value['tax_rate']] = $dataArray[$value['tax_rate']] + CRM_Utils_Array::value('tax_amount', $value); } else { $dataArray[$value['tax_rate']] = CRM_Utils_Array::value('tax_amount', $value); } } } } $smarty = CRM_Core_Smarty::singleton(); $smarty->assign('dataArray', $dataArray); $smarty->assign('totalTaxAmount', $params['tax_amount']); } if (is_a($contribution, 'CRM_Core_Error')) { $message = CRM_Core_Error::getMessages($contribution); CRM_Core_Error::fatal($message); } // lets store it in the form variable so postProcess hook can get to this and use it $form->_contributionID = $contribution->id; } // process soft credit / pcp params first CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($params, $form); //CRM-13981, processing honor contact into soft-credit contribution CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution); //handle pledge stuff. if ($isPledge) { if ($pledgeID) { //when user doing pledge payments. //update the schedule when payment(s) are made $amount = $params['amount']; $pledgePaymentParams = array(); foreach ($params['pledge_amount'] as $paymentId => $dontCare) { $scheduledAmount = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_PledgePayment', $paymentId, 'scheduled_amount', 'id'); $pledgePayment = $amount >= $scheduledAmount ? $scheduledAmount : $amount; if ($pledgePayment > 0) { $pledgePaymentParams[] = array('id' => $paymentId, 'contribution_id' => $contribution->id, 'status_id' => $contribution->contribution_status_id, 'actual_amount' => $pledgePayment); $amount -= $pledgePayment; } } if ($amount > 0 && count($pledgePaymentParams)) { $pledgePaymentParams[count($pledgePaymentParams) - 1]['actual_amount'] += $amount; } foreach ($pledgePaymentParams as $p) { CRM_Pledge_BAO_PledgePayment::add($p); } //update pledge status according to the new payment statuses CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($pledgeID); } else { //when user creating pledge record. $pledgeParams = array(); $pledgeParams['contact_id'] = $contribution->contact_id; $pledgeParams['installment_amount'] = $pledgeParams['actual_amount'] = $contribution->total_amount; $pledgeParams['contribution_id'] = $contribution->id; $pledgeParams['contribution_page_id'] = $contribution->contribution_page_id; $pledgeParams['financial_type_id'] = $contribution->financial_type_id; $pledgeParams['frequency_interval'] = $params['pledge_frequency_interval']; $pledgeParams['installments'] = $params['pledge_installments']; $pledgeParams['frequency_unit'] = $params['pledge_frequency_unit']; if ($pledgeParams['frequency_unit'] == 'month') { $pledgeParams['frequency_day'] = intval(date("d")); } else { $pledgeParams['frequency_day'] = 1; } $pledgeParams['create_date'] = $pledgeParams['start_date'] = $pledgeParams['scheduled_date'] = date("Ymd"); $pledgeParams['status_id'] = $contribution->contribution_status_id; $pledgeParams['max_reminders'] = $form->_values['max_reminders']; $pledgeParams['initial_reminder_day'] = $form->_values['initial_reminder_day']; $pledgeParams['additional_reminder_day'] = $form->_values['additional_reminder_day']; $pledgeParams['is_test'] = $contribution->is_test; $pledgeParams['acknowledge_date'] = date('Ymd'); $pledgeParams['original_installment_amount'] = $pledgeParams['installment_amount']; //inherit campaign from contirb page. $pledgeParams['campaign_id'] = CRM_Utils_Array::value('campaign_id', $contributionParams); $pledge = CRM_Pledge_BAO_Pledge::create($pledgeParams); $form->_params['pledge_id'] = $pledge->id; //send acknowledgment email. only when pledge is created if ($pledge->id) { //build params to send acknowledgment. $pledgeParams['id'] = $pledge->id; $pledgeParams['receipt_from_name'] = $form->_values['receipt_from_name']; $pledgeParams['receipt_from_email'] = $form->_values['receipt_from_email']; //scheduled amount will be same as installment_amount. $pledgeParams['scheduled_amount'] = $pledgeParams['installment_amount']; //get total pledge amount. $pledgeParams['total_pledge_amount'] = $pledge->amount; CRM_Pledge_BAO_Pledge::sendAcknowledgment($form, $pledgeParams); } } } if ($online && $contribution) { CRM_Core_BAO_CustomValueTable::postProcess($params, 'civicrm_contribution', $contribution->id, 'Contribution'); } elseif ($contribution) { //handle custom data. $params['contribution_id'] = $contribution->id; if (!empty($params['custom']) && is_array($params['custom']) && !is_a($contribution, 'CRM_Core_Error')) { CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_contribution', $contribution->id); } } // Save note if ($contribution && !empty($params['contribution_note'])) { $noteParams = array('entity_table' => 'civicrm_contribution', 'note' => $params['contribution_note'], 'entity_id' => $contribution->id, 'contact_id' => $contribution->contact_id, 'modified_date' => date('Ymd')); CRM_Core_BAO_Note::add($noteParams, array()); } if (isset($params['related_contact'])) { $contactID = $params['related_contact']; } elseif (isset($params['cms_contactID'])) { $contactID = $params['cms_contactID']; } //create contribution activity w/ individual and target //activity w/ organisation contact id when onbelf, CRM-4027 $targetContactID = NULL; if (!empty($params['hidden_onbehalf_profile'])) { $targetContactID = $contribution->contact_id; $contribution->contact_id = $contactID; } // create an activity record if ($contribution) { CRM_Activity_BAO_Activity::addActivity($contribution, NULL, $targetContactID); } $transaction->commit(); // CRM-13074 - create the CMSUser after the transaction is completed as it // is not appropriate to delete a valid contribution if a user create problem occurs CRM_Contribute_BAO_Contribution_Utils::createCMSUser($params, $contactID, 'email-' . $billingLocationID); return $contribution; }
/** * Process the contribution. * * @param CRM_Core_Form $form * @param array $params * @param array $result * @param int $contactID * @param bool $pending * @param bool $isAdditionalAmount * * @return \CRM_Contribute_BAO_Contribution */ public static function processContribution(&$form, $params, $result, $contactID, $pending = FALSE, $isAdditionalAmount = FALSE) { $transaction = new CRM_Core_Transaction(); $now = date('YmdHis'); $receiptDate = NULL; if (!empty($form->_values['event']['is_email_confirm'])) { $receiptDate = $now; } //CRM-4196 if ($isAdditionalAmount) { $params['amount_level'] = $params['amount_level'] . ts(' (multiple participants)') . CRM_Core_DAO::VALUE_SEPARATOR; } $contribParams = array('contact_id' => $contactID, 'financial_type_id' => !empty($form->_values['event']['financial_type_id']) ? $form->_values['event']['financial_type_id'] : $params['financial_type_id'], 'receive_date' => $now, 'total_amount' => $params['amount'], 'tax_amount' => $params['tax_amount'], 'amount_level' => $params['amount_level'], 'invoice_id' => $params['invoiceID'], 'currency' => $params['currencyID'], 'source' => !empty($params['participant_source']) ? $params['participant_source'] : $params['description'], 'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0), 'campaign_id' => CRM_Utils_Array::value('campaign_id', $params)); if (empty($params['is_pay_later'])) { $contribParams['payment_instrument_id'] = 1; } if (!$pending && $result) { $contribParams += array('fee_amount' => CRM_Utils_Array::value('fee_amount', $result), 'net_amount' => CRM_Utils_Array::value('net_amount', $result, $params['amount']), 'trxn_id' => $result['trxn_id'], 'receipt_date' => $receiptDate); } $allStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); $contribParams['contribution_status_id'] = array_search('Completed', $allStatuses); if ($pending) { $contribParams['contribution_status_id'] = array_search('Pending', $allStatuses); } $contribParams['is_test'] = 0; if ($form->_action & CRM_Core_Action::PREVIEW || CRM_Utils_Array::value('mode', $params) == 'test') { $contribParams['is_test'] = 1; } $contribID = NULL; if (!empty($contribParams['invoice_id'])) { $contribID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contribParams['invoice_id'], 'id', 'invoice_id'); } $ids = array(); if ($contribID) { $ids['contribution'] = $contribID; $contribParams['id'] = $contribID; } if (CRM_Contribute_BAO_Contribution::checkContributeSettings('deferred_revenue_enabled')) { $eventStartDate = CRM_Utils_Array::value('start_date', CRM_Utils_Array::value('event', $form->_values)); if ($eventStartDate) { $contribParams['revenue_recognition_date'] = date('Ymd', strtotime($eventStartDate)); } } //create an contribution address // The concept of contributeMode is deprecated. Elsewhere we use the function processBillingAddress() - although // currently that is only inherited by back-office forms. if ($form->_contributeMode != 'notify' && empty($params['is_pay_later'])) { $contribParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID); } $contribParams['payment_processor'] = CRM_Utils_Array::value('payment_processor', $params); $contribParams['skipLineItem'] = 1; // create contribution record $contribution = CRM_Contribute_BAO_Contribution::add($contribParams, $ids); // CRM-11124 CRM_Event_BAO_Participant::createDiscountTrxn($form->_eventId, $contribParams, NULL, CRM_Price_BAO_PriceSet::parseFirstPriceSetValueIDFromParams($params)); // process soft credit / pcp pages if (!empty($params['pcp_made_through_id'])) { CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($params, $form); CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution); } $transaction->commit(); return $contribution; }