/** * Add or update a Contribution. * * @param array $params * Input parameters. * * @throws API_Exception * @return array * Api result array */ function civicrm_api3_contribution_create(&$params) { $values = array(); _civicrm_api3_custom_format_params($params, $values, 'Contribution'); $params = array_merge($params, $values); if (!empty($params['id']) && !empty($params['contribution_status_id'])) { $error = array(); //throw error for invalid status change such as setting completed back to pending //@todo this sort of validation belongs in the BAO not the API - if it is not an OK // action it needs to be blocked there. If it is Ok through a form it needs to be OK through the api CRM_Contribute_BAO_Contribution::checkStatusValidation(NULL, $params, $error); if (array_key_exists('contribution_status_id', $error)) { throw new API_Exception($error['contribution_status_id']); } } if (!empty($params['id']) && !empty($params['financial_type_id'])) { $error = array(); CRM_Contribute_BAO_Contribution::checkFinancialTypeChange($params['financial_type_id'], $params['id'], $error); if (array_key_exists('financial_type_id', $error)) { throw new API_Exception($error['financial_type_id']); } } _civicrm_api3_contribution_create_legacy_support_45($params); // Make sure tax calculation is handled via api. $params = CRM_Contribute_BAO_Contribution::checkTaxAmount($params); return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params, 'Contribution'); }
/** * Add or update a Contribution. * * @param array $params * Input parameters. * * @throws API_Exception * @return array * Api result array */ function civicrm_api3_contribution_create(&$params) { $values = array(); _civicrm_api3_custom_format_params($params, $values, 'Contribution'); $params = array_merge($params, $values); if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) { if (empty($params['id'])) { $op = CRM_Core_Action::ADD; } else { if (empty($params['financial_type_id'])) { $params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $params['id'], 'financial_type_id'); } $op = CRM_Core_Action::UPDATE; } CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($types, $op); if (!in_array($params['financial_type_id'], array_keys($types))) { return civicrm_api3_create_error('You do not have permission to create this contribution'); } } if (!empty($params['id']) && !empty($params['contribution_status_id'])) { $error = array(); //throw error for invalid status change such as setting completed back to pending //@todo this sort of validation belongs in the BAO not the API - if it is not an OK // action it needs to be blocked there. If it is Ok through a form it needs to be OK through the api CRM_Contribute_BAO_Contribution::checkStatusValidation(NULL, $params, $error); if (array_key_exists('contribution_status_id', $error)) { throw new API_Exception($error['contribution_status_id']); } } if (!empty($params['id']) && !empty($params['financial_type_id'])) { $error = array(); CRM_Contribute_BAO_Contribution::checkFinancialTypeChange($params['financial_type_id'], $params['id'], $error); if (array_key_exists('financial_type_id', $error)) { throw new API_Exception($error['financial_type_id']); } } _civicrm_api3_contribution_create_legacy_support_45($params); // Make sure tax calculation is handled via api. // @todo this belongs in the BAO NOT the api. $params = CRM_Contribute_BAO_Contribution::checkTaxAmount($params); return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params, 'Contribution'); }
/** * Takes an associative array and creates a contribution object. * * the function extract all the params it needs to initialize the create a * contribution object. the params array could contain additional unused name/value * pairs * * @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|void */ public static function add(&$params, $ids = array()) { if (empty($params)) { return NULL; } //per http://wiki.civicrm.org/confluence/display/CRM/Database+layer we are moving away from $ids array $contributionID = CRM_Utils_Array::value('contribution', $ids, CRM_Utils_Array::value('id', $params)); $duplicates = array(); if (self::checkDuplicate($params, $duplicates, $contributionID)) { $error = CRM_Core_Error::singleton(); $d = implode(', ', $duplicates); $error->push(CRM_Core_Error::DUPLICATE_CONTRIBUTION, 'Fatal', array($d), "Duplicate error - existing contribution record(s) have a matching Transaction ID or Invoice ID. Contribution record ID(s) are: {$d}"); return $error; } // first clean up all the money fields $moneyFields = array('total_amount', 'net_amount', 'fee_amount', 'non_deductible_amount'); //if priceset is used, no need to cleanup money if (!empty($params['skipCleanMoney'])) { unset($moneyFields[0]); } foreach ($moneyFields as $field) { if (isset($params[$field])) { $params[$field] = CRM_Utils_Rule::cleanMoney($params[$field]); } } //set defaults in create mode if (!$contributionID) { CRM_Core_DAO::setCreateDefaults($params, self::getDefaults()); } $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); //if contribution is created with cancelled or refunded status, add credit note id if (!empty($params['contribution_status_id'])) { // @todo - should we include Chargeback? If so use self::isContributionStatusNegative($params['contribution_status_id']) 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(); } } } else { // Since the fee amount is expecting this (later on) ensure it is always set. // It would only not be set for an update where it is unchanged. $params['contribution_status_id'] = civicrm_api3('Contribution', 'getvalue', array('id' => $contributionID, 'return' => 'contribution_status_id')); } if (!$contributionID && CRM_Utils_Array::value('membership_id', $params) && self::checkContributeSettings('deferred_revenue_enabled')) { $memberStartDate = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $params['membership_id'], 'start_date'); if ($memberStartDate) { $params['revenue_recognition_date'] = date('Ymd', strtotime($memberStartDate)); } } self::calculateMissingAmountParams($params, $contributionID); if (!empty($params['payment_instrument_id'])) { $paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument('name'); if ($params['payment_instrument_id'] != array_search('Check', $paymentInstruments)) { $params['check_number'] = 'null'; } } $setPrevContribution = TRUE; // CRM-13964 partial payment if (!empty($params['partial_payment_total']) && !empty($params['partial_amount_pay'])) { $partialAmtTotal = $params['partial_payment_total']; $partialAmtPay = $params['partial_amount_pay']; $params['total_amount'] = $partialAmtTotal; if ($partialAmtPay < $partialAmtTotal) { $params['contribution_status_id'] = CRM_Core_OptionGroup::getValue('contribution_status', 'Partially paid', 'name'); $params['is_pay_later'] = 0; $setPrevContribution = FALSE; } } if ($contributionID && $setPrevContribution) { $params['prevContribution'] = self::getOriginalContribution($contributionID); } // CRM-16189 CRM_Financial_BAO_FinancialAccount::checkFinancialTypeHasDeferred($params, $contributionID); if ($contributionID && !empty($params['revenue_recognition_date']) && !empty($params['prevContribution']) && !($contributionStatus[$params['prevContribution']->contribution_status_id] == 'Pending') && !self::allowUpdateRevenueRecognitionDate($contributionID)) { unset($params['revenue_recognition_date']); } if (!isset($params['tax_amount']) && $setPrevContribution && (isset($params['total_amount']) || isset($params['financial_type_id']))) { $params = CRM_Contribute_BAO_Contribution::checkTaxAmount($params); } if ($contributionID) { CRM_Utils_Hook::pre('edit', 'Contribution', $contributionID, $params); } else { CRM_Utils_Hook::pre('create', 'Contribution', NULL, $params); } $contribution = new CRM_Contribute_BAO_Contribution(); $contribution->copyValues($params); $contribution->id = $contributionID; if (empty($contribution->id)) { // (only) on 'create', make sure that a valid currency is set (CRM-16845) if (!CRM_Utils_Rule::currencyCode($contribution->currency)) { $contribution->currency = CRM_Core_Config::singleton()->defaultCurrency; } } $result = $contribution->save(); // Add financial_trxn details as part of fix for CRM-4724 $contribution->trxn_result_code = CRM_Utils_Array::value('trxn_result_code', $params); $contribution->payment_processor = CRM_Utils_Array::value('payment_processor', $params); //add Account details $params['contribution'] = $contribution; self::recordFinancialAccounts($params); if (self::isUpdateToRecurringContribution($params)) { CRM_Contribute_BAO_ContributionRecur::updateOnNewPayment(!empty($params['contribution_recur_id']) ? $params['contribution_recur_id'] : $params['prevContribution']->contribution_recur_id, $contributionStatus[$params['contribution_status_id']]); } CRM_Contact_BAO_GroupContactCache::opportunisticCacheFlush(); if ($contributionID) { CRM_Utils_Hook::post('edit', 'Contribution', $contribution->id, $contribution); } else { CRM_Utils_Hook::post('create', 'Contribution', $contribution->id, $contribution); } return $result; }
/** * Create or update a line_item. * * @param array $params * Array of property name/value pairs to insert in new 'line_item' * * @return array * api result array */ function civicrm_api3_line_item_create($params) { $params = CRM_Contribute_BAO_Contribution::checkTaxAmount($params, TRUE); return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params); }