/** * @param array $submittedValues * * @param int $action * Action constant * - CRM_Core_Action::UPDATE * * @param $pledgePaymentID * * @return array * @throws \Exception */ protected function submit($submittedValues, $action, $pledgePaymentID) { $softParams = $softIDs = array(); $pId = $contribution = $isRelatedId = FALSE; $this->_params = $submittedValues; $this->beginPostProcess(); if (!empty($submittedValues['price_set_id']) && $action & CRM_Core_Action::UPDATE) { $line = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'contribution'); $lineID = key($line); $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', CRM_Utils_Array::value('price_field_id', $line[$lineID]), 'price_set_id'); $quickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config'); // Why do we do this? Seems like a like a wrapper for old functionality - but single line price sets & quick // config should be treated the same. if ($quickConfig) { CRM_Price_BAO_LineItem::deleteLineItems($this->_id, 'civicrm_contribution'); } } // Process price set and get total amount and line items. $lineItem = array(); $priceSetId = CRM_Utils_Array::value('price_set_id', $submittedValues); if (empty($priceSetId) && !$this->_id) { $this->_priceSetId = $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', 'default_contribution_amount', 'id', 'name'); $this->_priceSet = current(CRM_Price_BAO_PriceSet::getSetDetail($priceSetId)); $fieldID = key($this->_priceSet['fields']); $fieldValueId = key($this->_priceSet['fields'][$fieldID]['options']); $this->_priceSet['fields'][$fieldID]['options'][$fieldValueId]['amount'] = $submittedValues['total_amount']; $submittedValues['price_' . $fieldID] = 1; } // Every contribution has a price-set - the only reason it shouldn't be set is if we are dealing with // quick config (very very arguably) & yet we see that this could still be quick config so this should be understood // as a point of fragility rather than a logical 'if' clause. if ($priceSetId) { CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'], $submittedValues, $lineItem[$priceSetId]); // Unset tax amount for offline 'is_quick_config' contribution. // @todo WHY - quick config was conceived as a quick way to configure contribution forms. // this is an example of 'other' functionality being hung off it. if ($this->_priceSet['is_quick_config'] && !array_key_exists($submittedValues['financial_type_id'], CRM_Core_PseudoConstant::getTaxRates())) { unset($submittedValues['tax_amount']); } $submittedValues['total_amount'] = CRM_Utils_Array::value('amount', $submittedValues); } if ($this->_id) { if ($this->_compId) { if ($this->_context == 'participant') { $pId = $this->_compId; } elseif ($this->_context == 'membership') { $isRelatedId = TRUE; } else { $pId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $this->_id, 'participant_id', 'contribution_id'); } } else { $contributionDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); if (array_key_exists('membership', $contributionDetails)) { $isRelatedId = TRUE; } elseif (array_key_exists('participant', $contributionDetails)) { $pId = $contributionDetails['participant']; } } } if (!$priceSetId && !empty($submittedValues['total_amount']) && $this->_id) { // CRM-10117 update the line items for participants. // @todo - if we are completing a contribution then the api call // civicrm_api3('Contribution', 'completetransaction') should take care of // all associated updates rather than replicating them on the form layer. if ($pId) { $entityTable = 'participant'; $entityID = $pId; $isRelatedId = FALSE; $participantParams = array('fee_amount' => $submittedValues['total_amount'], 'id' => $entityID); CRM_Event_BAO_Participant::add($participantParams); if (empty($this->_lineItems)) { $this->_lineItems[] = CRM_Price_BAO_LineItem::getLineItems($entityID, 'participant', 1); } } else { $entityTable = 'contribution'; $entityID = $this->_id; } $lineItems = CRM_Price_BAO_LineItem::getLineItems($entityID, $entityTable, NULL, TRUE, $isRelatedId); foreach (array_keys($lineItems) as $id) { $lineItems[$id]['id'] = $id; } $itemId = key($lineItems); if ($itemId && !empty($lineItems[$itemId]['price_field_id'])) { $this->_priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id'); } // @todo see above - new functionality has been inappropriately added to the quick config concept // and new functionality has been added onto the form layer rather than the BAO :-( if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) { //CRM-16833: Ensure tax is applied only once for membership conribution, when status changed.(e.g Pending to Completed). $componentDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); if (!(CRM_Utils_Array::value('membership', $componentDetails) || CRM_Utils_Array::value('participant', $componentDetails))) { if (!($this->_action & CRM_Core_Action::UPDATE && $this->_defaults['contribution_status_id'] != $submittedValues['contribution_status_id'])) { $lineItems[$itemId]['unit_price'] = $lineItems[$itemId]['line_total'] = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('total_amount', $submittedValues)); } } // Update line total and total amount with tax on edit. $financialItemsId = CRM_Core_PseudoConstant::getTaxRates(); if (array_key_exists($submittedValues['financial_type_id'], $financialItemsId)) { $lineItems[$itemId]['tax_rate'] = $financialItemsId[$submittedValues['financial_type_id']]; } else { $lineItems[$itemId]['tax_rate'] = $lineItems[$itemId]['tax_amount'] = ""; $submittedValues['tax_amount'] = 'null'; } if ($lineItems[$itemId]['tax_rate']) { $lineItems[$itemId]['tax_amount'] = $lineItems[$itemId]['tax_rate'] / 100 * $lineItems[$itemId]['line_total']; $submittedValues['total_amount'] = $lineItems[$itemId]['line_total'] + $lineItems[$itemId]['tax_amount']; $submittedValues['tax_amount'] = $lineItems[$itemId]['tax_amount']; } } // CRM-10117 update the line items for participants. if (!empty($lineItems[$itemId]['price_field_id'])) { $lineItem[$this->_priceSetId] = $lineItems; } } $isQuickConfig = 0; if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) { $isQuickConfig = 1; } //CRM-11529 for quick config back office transactions //when financial_type_id is passed in form, update the //line items with the financial type selected in form // NOTE that this IS still a legitimate use of 'quick-config' for contributions under the current DB but // we should look at having a price field per contribution type & then there would be little reason // for the back-office contribution form postProcess to know if it is a quick-config form. if ($isQuickConfig && !empty($submittedValues['financial_type_id']) && CRM_Utils_Array::value($this->_priceSetId, $lineItem)) { foreach ($lineItem[$this->_priceSetId] as &$values) { $values['financial_type_id'] = $submittedValues['financial_type_id']; } } if (!isset($submittedValues['total_amount'])) { $submittedValues['total_amount'] = CRM_Utils_Array::value('total_amount', $this->_values); } $this->assign('lineItem', !empty($lineItem) && !$isQuickConfig ? $lineItem : FALSE); $isEmpty = array_keys(array_flip($submittedValues['soft_credit_contact_id'])); if ($this->_id && count($isEmpty) == 1 && key($isEmpty) == NULL) { //Delete existing soft credit records if soft credit list is empty on update CRM_Contribute_BAO_ContributionSoft::del(array('contribution_id' => $this->_id, 'pcp_id' => 0)); } // set the contact, when contact is selected if (!empty($submittedValues['contact_id'])) { $this->_contactID = $submittedValues['contact_id']; } $formValues = $submittedValues; // Credit Card Contribution. if ($this->_mode) { $paramsSetByPaymentProcessingSubsystem = array('trxn_id', 'payment_instrument_id', 'contribution_status_id', 'cancel_date', 'cancel_reason'); foreach ($paramsSetByPaymentProcessingSubsystem as $key) { if (isset($formValues[$key])) { unset($formValues[$key]); } } $contribution = $this->processCreditCard($formValues, $lineItem, $this->_contactID); foreach ($paramsSetByPaymentProcessingSubsystem as $key) { $formValues[$key] = $contribution->{$key}; } } else { // Offline Contribution. $submittedValues = $this->unsetCreditCardFields($submittedValues); // get the required field value only. $params = $ids = array(); $params['contact_id'] = $this->_contactID; $params['currency'] = $this->getCurrency($submittedValues); //format soft-credit/pcp param first CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($submittedValues, $this); $params = array_merge($params, $submittedValues); $fields = array('financial_type_id', 'contribution_status_id', 'payment_instrument_id', 'cancel_reason', 'source', 'check_number'); foreach ($fields as $f) { $params[$f] = CRM_Utils_Array::value($f, $formValues); } // CRM-5740 if priceset is used, no need to cleanup money. if ($priceSetId) { $params['skipCleanMoney'] = 1; } $dates = array('receive_date', 'receipt_date', 'cancel_date'); foreach ($dates as $d) { $params[$d] = CRM_Utils_Date::processDate($formValues[$d], $formValues[$d . '_time'], TRUE); } if (!empty($formValues['is_email_receipt'])) { $params['receipt_date'] = date("Y-m-d"); } if ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Cancelled', 'name') || $params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Refunded', 'name')) { if (CRM_Utils_System::isNull(CRM_Utils_Array::value('cancel_date', $params))) { $params['cancel_date'] = date('YmdHis'); } } else { $params['cancel_date'] = $params['cancel_reason'] = 'null'; } // Set is_pay_later flag for back-office offline Pending status contributions CRM-8996 // else if contribution_status is changed to Completed is_pay_later flag is changed to 0, CRM-15041 if ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name')) { $params['is_pay_later'] = 1; } elseif ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Completed', 'name')) { $params['is_pay_later'] = 0; } $ids['contribution'] = $params['id'] = $this->_id; // Add Additional common information to formatted params. CRM_Contribute_Form_AdditionalInfo::postProcessCommon($formValues, $params, $this); if ($pId) { $params['contribution_mode'] = 'participant'; $params['participant_id'] = $pId; $params['skipLineItem'] = 1; } elseif ($isRelatedId) { $params['contribution_mode'] = 'membership'; } $params['line_item'] = $lineItem; $params['payment_processor_id'] = $params['payment_processor'] = CRM_Utils_Array::value('id', $this->_paymentProcessor); if (isset($submittedValues['tax_amount'])) { $params['tax_amount'] = $submittedValues['tax_amount']; } //create contribution. if ($isQuickConfig) { $params['is_quick_config'] = 1; } $params['non_deductible_amount'] = $this->calculateNonDeductibleAmount($params, $formValues); // we are already handling note below, so to avoid duplicate notes against $contribution if (!empty($params['note']) && !empty($submittedValues['note'])) { unset($params['note']); } $contribution = CRM_Contribute_BAO_Contribution::create($params, $ids); // process associated membership / participant, CRM-4395 if ($contribution->id && $action & CRM_Core_Action::UPDATE) { $this->statusMessage[] = $this->updateRelatedComponent($contribution->id, $contribution->contribution_status_id, CRM_Utils_Array::value('contribution_status_id', $this->_values), $contribution->receive_date); } array_unshift($this->statusMessage, ts('The contribution record has been saved.')); $this->invoicingPostProcessHook($submittedValues, $action, $lineItem); //send receipt mail. if ($contribution->id && !empty($formValues['is_email_receipt'])) { $formValues['contact_id'] = $this->_contactID; $formValues['contribution_id'] = $contribution->id; $formValues += CRM_Contribute_BAO_ContributionSoft::getSoftContribution($contribution->id); // to get 'from email id' for send receipt $this->fromEmailId = $formValues['from_email_address']; if (CRM_Contribute_Form_AdditionalInfo::emailReceipt($this, $formValues)) { $this->statusMessage[] = ts('A receipt has been emailed to the contributor.'); } } $this->statusMessageTitle = ts('Saved'); } if ($contribution->id && isset($formValues['product_name'][0])) { CRM_Contribute_Form_AdditionalInfo::processPremium($submittedValues, $contribution->id, $this->_premiumID, $this->_options); } if ($contribution->id && !empty($submittedValues['note'])) { CRM_Contribute_Form_AdditionalInfo::processNote($submittedValues, $this->_contactID, $contribution->id, $this->_noteID); } CRM_Core_Session::setStatus(implode(' ', $this->statusMessage), $this->statusMessageTitle, 'success'); CRM_Contribute_BAO_Contribution::updateRelatedPledge($action, $pledgePaymentID, $contribution->id, CRM_Utils_Array::value('option_type', $formValues) == 2 ? TRUE : FALSE, $formValues['total_amount'], CRM_Utils_Array::value('total_amount', $this->_defaults), $formValues['contribution_status_id'], CRM_Utils_Array::value('contribution_status_id', $this->_defaults)); return $contribution; }
/** * Process the form submission. */ public function postProcess() { $sendReceipt = $pId = $contribution = $isRelatedId = FALSE; $softParams = $softIDs = array(); if ($this->_action & CRM_Core_Action::DELETE) { CRM_Contribute_BAO_Contribution::deleteContribution($this->_id); CRM_Core_Session::singleton()->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_contactID}&selectedChild=contribute")); return; } // Get the submitted form values. $submittedValues = $this->controller->exportValues($this->_name); if (!empty($submittedValues['price_set_id']) && $this->_action & CRM_Core_Action::UPDATE) { $line = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'contribution'); $lineID = key($line); $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', CRM_Utils_Array::value('price_field_id', $line[$lineID]), 'price_set_id'); $quickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config'); if ($quickConfig) { CRM_Price_BAO_LineItem::deleteLineItems($this->_id, 'civicrm_contribution'); } } // Process price set and get total amount and line items. $lineItem = array(); $priceSetId = CRM_Utils_Array::value('price_set_id', $submittedValues); if (empty($priceSetId) && !$this->_id) { $this->_priceSetId = $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', 'default_contribution_amount', 'id', 'name'); $this->_priceSet = current(CRM_Price_BAO_PriceSet::getSetDetail($priceSetId)); $fieldID = key($this->_priceSet['fields']); $fieldValueId = key($this->_priceSet['fields'][$fieldID]['options']); $this->_priceSet['fields'][$fieldID]['options'][$fieldValueId]['amount'] = $submittedValues['total_amount']; $submittedValues['price_' . $fieldID] = 1; } if ($priceSetId) { CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'], $submittedValues, $lineItem[$priceSetId]); // Unset tax amount for offline 'is_quick_config' contribution. if ($this->_priceSet['is_quick_config'] && !array_key_exists($submittedValues['financial_type_id'], CRM_Core_PseudoConstant::getTaxRates())) { unset($submittedValues['tax_amount']); } $submittedValues['total_amount'] = CRM_Utils_Array::value('amount', $submittedValues); } if ($this->_id) { if ($this->_compId) { if ($this->_context == 'participant') { $pId = $this->_compId; } elseif ($this->_context == 'membership') { $isRelatedId = TRUE; } else { $pId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $this->_id, 'participant_id', 'contribution_id'); } } else { $contributionDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); if (array_key_exists('membership', $contributionDetails)) { $isRelatedId = TRUE; } elseif (array_key_exists('participant', $contributionDetails)) { $pId = $contributionDetails['participant']; } } } if (!$priceSetId && !empty($submittedValues['total_amount']) && $this->_id) { // CRM-10117 update the line items for participants. if ($pId) { $entityTable = 'participant'; $entityID = $pId; $isRelatedId = FALSE; $participantParams = array('fee_amount' => $submittedValues['total_amount'], 'id' => $entityID); CRM_Event_BAO_Participant::add($participantParams); if (empty($this->_lineItems)) { $this->_lineItems[] = CRM_Price_BAO_LineItem::getLineItems($entityID, 'participant', 1); } } else { $entityTable = 'contribution'; $entityID = $this->_id; } $lineItems = CRM_Price_BAO_LineItem::getLineItems($entityID, $entityTable, NULL, TRUE, $isRelatedId); foreach (array_keys($lineItems) as $id) { $lineItems[$id]['id'] = $id; } $itemId = key($lineItems); if ($itemId && !empty($lineItems[$itemId]['price_field_id'])) { $this->_priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id'); } if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) { $lineItems[$itemId]['unit_price'] = $lineItems[$itemId]['line_total'] = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('total_amount', $submittedValues)); // Update line total and total amount with tax on edit. $financialItemsId = CRM_Core_PseudoConstant::getTaxRates(); if (array_key_exists($submittedValues['financial_type_id'], $financialItemsId)) { $lineItems[$itemId]['tax_rate'] = $financialItemsId[$submittedValues['financial_type_id']]; } else { $lineItems[$itemId]['tax_rate'] = $lineItems[$itemId]['tax_amount'] = ""; $submittedValues['tax_amount'] = 'null'; } if ($lineItems[$itemId]['tax_rate']) { $lineItems[$itemId]['tax_amount'] = $lineItems[$itemId]['tax_rate'] / 100 * $lineItems[$itemId]['line_total']; $submittedValues['total_amount'] = $lineItems[$itemId]['line_total'] + $lineItems[$itemId]['tax_amount']; $submittedValues['tax_amount'] = $lineItems[$itemId]['tax_amount']; } } // CRM-10117 update the line items for participants. if (!empty($lineItems[$itemId]['price_field_id'])) { $lineItem[$this->_priceSetId] = $lineItems; } } $isQuickConfig = 0; if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) { $isQuickConfig = 1; } //CRM-11529 for quick config back office transactions //when financial_type_id is passed in form, update the //line items with the financial type selected in form if ($isQuickConfig && !empty($submittedValues['financial_type_id']) && CRM_Utils_Array::value($this->_priceSetId, $lineItem)) { foreach ($lineItem[$this->_priceSetId] as &$values) { $values['financial_type_id'] = $submittedValues['financial_type_id']; } } if (!isset($submittedValues['total_amount'])) { $submittedValues['total_amount'] = CRM_Utils_Array::value('total_amount', $this->_values); } $this->assign('lineItem', !empty($lineItem) && !$isQuickConfig ? $lineItem : FALSE); if (!empty($submittedValues['pcp_made_through_id'])) { $pcp = array(); $fields = array('pcp_made_through_id', 'pcp_display_in_roll', 'pcp_roll_nickname', 'pcp_personal_note'); foreach ($fields as $f) { $pcp[$f] = CRM_Utils_Array::value($f, $submittedValues); } } $isEmpty = array_keys(array_flip($submittedValues['soft_credit_contact_id'])); if ($this->_id && count($isEmpty) == 1 && key($isEmpty) == NULL) { //Delete existing soft credit records if soft credit list is empty on update CRM_Contribute_BAO_ContributionSoft::del(array('contribution_id' => $this->_id)); } else { //build soft credit params foreach ($submittedValues['soft_credit_contact_id'] as $key => $val) { if ($val && $submittedValues['soft_credit_amount'][$key]) { $softParams[$key]['contact_id'] = $val; $softParams[$key]['amount'] = CRM_Utils_Rule::cleanMoney($submittedValues['soft_credit_amount'][$key]); $softParams[$key]['soft_credit_type_id'] = $submittedValues['soft_credit_type'][$key]; if (!empty($submittedValues['soft_credit_id'][$key])) { $softIDs[] = $softParams[$key]['id'] = $submittedValues['soft_credit_id'][$key]; } } } } // set the contact, when contact is selected if (!empty($submittedValues['contact_id'])) { $this->_contactID = $submittedValues['contact_id']; } // Credit Card Contribution. if ($this->_mode) { $this->processCreditCard($submittedValues, $lineItem); } else { // Offline Contribution. $submittedValues = $this->unsetCreditCardFields($submittedValues); // get the required field value only. $formValues = $submittedValues; $params = $ids = array(); $params['contact_id'] = $this->_contactID; $params['currency'] = $this->getCurrency($submittedValues); $fields = array('financial_type_id', 'contribution_status_id', 'payment_instrument_id', 'cancel_reason', 'source', 'check_number'); foreach ($fields as $f) { $params[$f] = CRM_Utils_Array::value($f, $formValues); } if (!empty($pcp)) { $params['pcp'] = $pcp; } if (!empty($softParams)) { $params['soft_credit'] = $softParams; $params['soft_credit_ids'] = $softIDs; } // CRM-5740 if priceset is used, no need to cleanup money. if ($priceSetId) { $params['skipCleanMoney'] = 1; } $dates = array('receive_date', 'receipt_date', 'cancel_date'); foreach ($dates as $d) { $params[$d] = CRM_Utils_Date::processDate($formValues[$d], $formValues[$d . '_time'], TRUE); } if (!empty($formValues['is_email_receipt'])) { $params['receipt_date'] = date("Y-m-d"); } if ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Cancelled', 'name') || $params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Refunded', 'name')) { if (CRM_Utils_System::isNull(CRM_Utils_Array::value('cancel_date', $params))) { $params['cancel_date'] = date('Y-m-d'); } } else { $params['cancel_date'] = $params['cancel_reason'] = 'null'; } // Set is_pay_later flag for back-office offline Pending status contributions CRM-8996 // else if contribution_status is changed to Completed is_pay_later flag is changed to 0, CRM-15041 if ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name')) { $params['is_pay_later'] = 1; } elseif ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Completed', 'name')) { $params['is_pay_later'] = 0; } $ids['contribution'] = $params['id'] = $this->_id; // Add Additional common information to formatted params. CRM_Contribute_Form_AdditionalInfo::postProcessCommon($formValues, $params, $this); if ($pId) { $params['contribution_mode'] = 'participant'; $params['participant_id'] = $pId; $params['skipLineItem'] = 1; } elseif ($isRelatedId) { $params['contribution_mode'] = 'membership'; } $params['line_item'] = $lineItem; $params['payment_processor_id'] = $params['payment_processor'] = CRM_Utils_Array::value('id', $this->_paymentProcessor); if (isset($submittedValues['tax_amount'])) { $params['tax_amount'] = $submittedValues['tax_amount']; } //create contribution. if ($isQuickConfig) { $params['is_quick_config'] = 1; } // CRM-11956 // if non_deductible_amount exists i.e. Additional Details field set was opened [and staff typed something] - // if non_deductible_amount does NOT exist - then calculate it depending on: // $ContributionType->is_deductible and whether there is a product (premium). if (empty($params['non_deductible_amount'])) { $contributionType = new CRM_Financial_DAO_FinancialType(); $contributionType->id = $params['financial_type_id']; if (!$contributionType->find(TRUE)) { CRM_Core_Error::fatal('Could not find a system table'); } if ($contributionType->is_deductible) { if (isset($formValues['product_name'][0])) { $selectProduct = $formValues['product_name'][0]; } // if there is a product - compare the value to the contribution amount if (isset($selectProduct)) { $productDAO = new CRM_Contribute_DAO_Product(); $productDAO->id = $selectProduct; $productDAO->find(TRUE); // product value exceeds contribution amount if ($params['total_amount'] < $productDAO->price) { $params['non_deductible_amount'] = $params['total_amount']; } else { $params['non_deductible_amount'] = $productDAO->price; } } else { $params['non_deductible_amount'] = '0.00'; } } else { $params['non_deductible_amount'] = $params['total_amount']; } } $contribution = CRM_Contribute_BAO_Contribution::create($params, $ids); // process associated membership / participant, CRM-4395 $relatedComponentStatusMsg = NULL; if ($contribution->id && $this->_action & CRM_Core_Action::UPDATE) { $relatedComponentStatusMsg = $this->updateRelatedComponent($contribution->id, $contribution->contribution_status_id, CRM_Utils_Array::value('contribution_status_id', $this->_values), $contribution->receive_date); } //process note if ($contribution->id && isset($formValues['note'])) { CRM_Contribute_Form_AdditionalInfo::processNote($formValues, $this->_contactID, $contribution->id, $this->_noteID); } //process premium if ($contribution->id && isset($formValues['product_name'][0])) { CRM_Contribute_Form_AdditionalInfo::processPremium($formValues, $contribution->id, $this->_premiumID, $this->_options); } // assign tax calculation for contribution receipts $taxRate = array(); $getTaxDetails = FALSE; $invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); if ($invoicing) { if ($this->_action & CRM_Core_Action::ADD) { $line = $lineItem; } elseif ($this->_action & CRM_Core_Action::UPDATE) { $line = $this->_lineItems; } foreach ($line as $key => $value) { foreach ($value as $v) { if (isset($taxRate[(string) CRM_Utils_Array::value('tax_rate', $v)])) { $taxRate[(string) $v['tax_rate']] = $taxRate[(string) $v['tax_rate']] + CRM_Utils_Array::value('tax_amount', $v); } else { if (isset($v['tax_rate'])) { $taxRate[(string) $v['tax_rate']] = CRM_Utils_Array::value('tax_amount', $v); $getTaxDetails = TRUE; } } } } } if ($invoicing) { if ($this->_action & CRM_Core_Action::UPDATE) { if (isset($submittedValues['tax_amount'])) { $totalTaxAmount = $submittedValues['tax_amount']; } else { $totalTaxAmount = $this->_values['tax_amount']; } $this->assign('totalTaxAmount', $totalTaxAmount); $this->assign('dataArray', $taxRate); } else { if (!empty($submittedValues['price_set_id'])) { $this->assign('totalTaxAmount', $submittedValues['tax_amount']); $this->assign('getTaxDetails', $getTaxDetails); $this->assign('dataArray', $taxRate); $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings)); } else { $this->assign('totalTaxAmount', CRM_Utils_Array::value('tax_amount', $submittedValues)); } } } //send receipt mail. if ($contribution->id && !empty($formValues['is_email_receipt'])) { $formValues['contact_id'] = $this->_contactID; $formValues['contribution_id'] = $contribution->id; $formValues += CRM_Contribute_BAO_ContributionSoft::getSoftContribution($contribution->id); // to get 'from email id' for send receipt $this->fromEmailId = $formValues['from_email_address']; $sendReceipt = CRM_Contribute_Form_AdditionalInfo::emailReceipt($this, $formValues); } $pledgePaymentId = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_PledgePayment', $contribution->id, 'id', 'contribution_id'); //update pledge payment status. if ($this->_ppID && $contribution->id && $this->_action & CRM_Core_Action::ADD || $pledgePaymentId && $this->_action & CRM_Core_Action::UPDATE) { if ($this->_ppID) { //store contribution id in payment record. CRM_Core_DAO::setFieldValue('CRM_Pledge_DAO_PledgePayment', $this->_ppID, 'contribution_id', $contribution->id); } else { $this->_ppID = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_PledgePayment', $contribution->id, 'id', 'contribution_id'); $this->_pledgeID = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_PledgePayment', $contribution->id, 'pledge_id', 'contribution_id'); } $adjustTotalAmount = FALSE; if (CRM_Utils_Array::value('option_type', $formValues) == 2) { $adjustTotalAmount = TRUE; } $updatePledgePaymentStatus = FALSE; //do only if either the status or the amount has changed if ($this->_action & CRM_Core_Action::ADD) { $updatePledgePaymentStatus = TRUE; } elseif ($this->_action & CRM_Core_Action::UPDATE && ($this->_defaults['contribution_status_id'] != $formValues['contribution_status_id'] || $this->_defaults['total_amount'] != $formValues['total_amount'])) { $updatePledgePaymentStatus = TRUE; } if ($updatePledgePaymentStatus) { CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($this->_pledgeID, array($this->_ppID), $contribution->contribution_status_id, NULL, $contribution->total_amount, $adjustTotalAmount); } } $statusMsg = ts('The contribution record has been saved.'); if (!empty($formValues['is_email_receipt']) && $sendReceipt) { $statusMsg .= ' ' . ts('A receipt has been emailed to the contributor.'); } if ($relatedComponentStatusMsg) { $statusMsg .= ' ' . $relatedComponentStatusMsg; } CRM_Core_Session::setStatus($statusMsg, ts('Saved'), 'success'); //Offline Contribution ends. } $session = CRM_Core_Session::singleton(); $buttonName = $this->controller->getButtonName(); if ($this->_context == 'standalone') { if ($buttonName == $this->getButtonName('upload', 'new')) { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contribute/add', 'reset=1&action=add&context=standalone')); } else { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_contactID}&selectedChild=contribute")); } } elseif ($this->_context == 'contribution' && $this->_mode && $buttonName == $this->getButtonName('upload', 'new')) { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view/contribution', "reset=1&action=add&context={$this->_context}&cid={$this->_contactID}&mode={$this->_mode}")); } elseif ($buttonName == $this->getButtonName('upload', 'new')) { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view/contribution', "reset=1&action=add&context={$this->_context}&cid={$this->_contactID}")); } //store contribution ID if not yet set (on create) if (empty($this->_id) && !empty($contribution->id)) { $this->_id = $contribution->id; } }
/** * Function to build the form * * @return void * @access public */ public function buildQuickForm() { if ($this->_cdType) { CRM_Custom_Form_CustomData::buildQuickForm($this); return; } // build price set form. $buildPriceSet = FALSE; if (empty($this->_lineItems) && ($this->_priceSetId || CRM_Utils_Array::value('price_set_id', $_POST))) { $buildPriceSet = TRUE; $getOnlyPriceSetElements = TRUE; if (!$this->_priceSetId) { $this->_priceSetId = $_POST['price_set_id']; $getOnlyPriceSetElements = FALSE; } $this->set('priceSetId', $this->_priceSetId); CRM_Price_BAO_PriceSet::buildPriceSet($this); // get only price set form elements. if ($getOnlyPriceSetElements) { return; } } // use to build form during form rule. $this->assign('buildPriceSet', $buildPriceSet); $showAdditionalInfo = FALSE; $defaults = $this->_values; $additionalDetailFields = array('note', 'thankyou_date', 'invoice_id', 'non_deductible_amount', 'fee_amount', 'net_amount'); foreach ($additionalDetailFields as $key) { if (!empty($defaults[$key])) { $defaults['hidden_AdditionalDetail'] = 1; break; } } $honorFields = array('honor_type_id', 'honor_prefix_id', 'honor_first_name', 'honor_lastname', 'honor_email'); foreach ($honorFields as $key) { if (!empty($defaults[$key])) { $defaults['hidden_Honoree'] = 1; break; } } //check for honoree pane. if ($this->_ppID && CRM_Utils_Array::value('honor_contact_id', $this->_pledgeValues)) { $defaults['hidden_Honoree'] = 1; } if ($this->_productDAO) { if ($this->_productDAO->product_id) { $defaults['hidden_Premium'] = 1; } } if ($this->_noteID && isset($this->_values['note'])) { $defaults['hidden_AdditionalDetail'] = 1; } $paneNames = array(ts('Additional Details') => 'AdditionalDetail', ts('Honoree Information') => 'Honoree'); //Add Premium pane only if Premium is exists. $dao = new CRM_Contribute_DAO_Product(); $dao->is_active = 1; if ($dao->find(TRUE)) { $paneNames[ts('Premium Information')] = 'Premium'; } $ccPane = NULL; if ($this->_mode) { if (CRM_Utils_Array::value('payment_type', $this->_processors) & CRM_Core_Payment::PAYMENT_TYPE_DIRECT_DEBIT) { $ccPane = array(ts('Direct Debit Information') => 'DirectDebit'); } else { $ccPane = array(ts('Credit Card Information') => 'CreditCard'); } } if (is_array($ccPane)) { $paneNames = array_merge($ccPane, $paneNames); } $buildRecurBlock = FALSE; foreach ($paneNames as $name => $type) { $urlParams = "snippet=4&formType={$type}"; if ($this->_mode) { $urlParams .= "&mode={$this->_mode}"; } $open = 'false'; if ($type == 'CreditCard' || $type == 'DirectDebit') { $open = 'true'; } $allPanes[$name] = array('url' => CRM_Utils_System::url('civicrm/contact/view/contribution', $urlParams), 'open' => $open, 'id' => $type); // see if we need to include this paneName in the current form if ($this->_formType == $type || CRM_Utils_Array::value("hidden_{$type}", $_POST) || CRM_Utils_Array::value("hidden_{$type}", $defaults)) { $showAdditionalInfo = TRUE; $allPanes[$name]['open'] = 'true'; } if ($type == 'CreditCard') { $buildRecurBlock = TRUE; $this->add('hidden', 'hidden_CreditCard', 1); CRM_Core_Payment_Form::buildCreditCard($this, TRUE); } elseif ($type == 'DirectDebit') { $buildRecurBlock = TRUE; $this->add('hidden', 'hidden_DirectDebit', 1); CRM_Core_Payment_Form::buildDirectDebit($this, TRUE); } else { $additionalInfoFormFunction = 'build' . $type; CRM_Contribute_Form_AdditionalInfo::$additionalInfoFormFunction($this); } } if (empty($this->_recurPaymentProcessors)) { $buildRecurBlock = FALSE; } if ($buildRecurBlock) { CRM_Contribute_Form_Contribution_Main::buildRecur($this); $this->setDefaults(array('is_recur' => 0)); } $this->assign('buildRecurBlock', $buildRecurBlock); $qfKey = $this->controller->_key; $this->assign('qfKey', $qfKey); $this->assign('allPanes', $allPanes); $this->assign('showAdditionalInfo', $showAdditionalInfo); if ($this->_formType) { $this->assign('formType', $this->_formType); return; } $this->applyFilter('__ALL__', 'trim'); if ($this->_action & CRM_Core_Action::DELETE) { $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 and subtype to the template $this->assign('customDataType', 'Contribution'); $this->assign('customDataSubType', $this->_contributionType); $this->assign('entityID', $this->_id); if ($this->_context == 'standalone') { CRM_Contact_Form_NewContact::buildQuickForm($this); } $attributes = CRM_Core_DAO::getAttribute('CRM_Contribute_DAO_Contribution'); $financialType = $this->add('select', 'financial_type_id', ts('Financial Type'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::financialType(), TRUE, array('onChange' => "CRM.buildCustomData( 'Contribution', this.value );")); if (!$this->_mode) { $paymentInstrument = $this->add('select', 'payment_instrument_id', ts('Paid By'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(), TRUE, array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")); } $trxnId = $this->add('text', 'trxn_id', ts('Transaction ID'), $attributes['trxn_id']); //add receipt for offline contribution $this->addElement('checkbox', 'is_email_receipt', ts('Send Receipt?')); $this->add('select', 'from_email_address', ts('Receipt From'), $this->_fromEmails); $status = CRM_Contribute_PseudoConstant::contributionStatus(); // suppressing contribution statuses that are NOT relevant to pledges (CRM-5169) $statusName = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); if ($this->_ppID) { foreach (array('Cancelled', 'Failed', 'In Progress') as $suppress) { unset($status[CRM_Utils_Array::key($suppress, $statusName)]); } } elseif (!$this->_ppID && $this->_id || !$this->_id) { $suppressFlag = FALSE; if ($this->_id) { $componentDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); if (CRM_Utils_Array::value('membership', $componentDetails) || CRM_Utils_Array::value('participant', $componentDetails)) { $suppressFlag = TRUE; } } if (!$suppressFlag) { foreach (array('Overdue', 'In Progress') as $suppress) { unset($status[CRM_Utils_Array::key($suppress, $statusName)]); } } else { unset($status[CRM_Utils_Array::key('Overdue', $statusName)]); } } if ($this->_id) { $contributionStatus = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->_id, 'contribution_status_id'); $name = CRM_Utils_Array::value($contributionStatus, $statusName); switch ($name) { case 'Completed': case 'Cancelled': case 'Refunded': unset($status[CRM_Utils_Array::key('In Progress', $statusName)]); unset($status[CRM_Utils_Array::key('Pending', $statusName)]); unset($status[CRM_Utils_Array::key('Failed', $statusName)]); break; case 'Pending': case 'In Progress': unset($status[CRM_Utils_Array::key('Refunded', $statusName)]); break; case 'Failed': foreach (array('Pending', 'Refunded', 'Completed', 'In Progress', 'Cancelled') as $suppress) { unset($status[CRM_Utils_Array::key($suppress, $statusName)]); } break; } } else { unset($status[CRM_Utils_Array::key('Refunded', $statusName)]); } $this->add('select', 'contribution_status_id', ts('Contribution Status'), $status, FALSE); // add various dates $this->addDateTime('receive_date', ts('Received'), FALSE, array('formatType' => 'activityDateTime')); if ($this->_online) { $this->assign('hideCalender', TRUE); } $checkNumber = $this->add('text', 'check_number', ts('Check Number'), $attributes['check_number']); $this->addDateTime('receipt_date', ts('Receipt Date'), FALSE, array('formatType' => 'activityDateTime')); $this->addDateTime('cancel_date', ts('Cancelled / Refunded Date'), FALSE, array('formatType' => 'activityDateTime')); $this->add('textarea', 'cancel_reason', ts('Cancellation / Refund Reason'), $attributes['cancel_reason']); $recurJs = NULL; if ($buildRecurBlock) { $recurJs = array('onChange' => "buildRecurBlock( this.value ); return false;"); } $element = $this->add('select', 'payment_processor_id', ts('Payment Processor'), $this->_processors, NULL, $recurJs); if ($this->_online) { $element->freeze(); } $totalAmount = NULL; if (empty($this->_lineItems)) { $buildPriceSet = FALSE; $priceSets = CRM_Price_BAO_PriceSet::getAssoc(FALSE, 'CiviContribute'); if (!empty($priceSets) && !$this->_ppID) { $buildPriceSet = TRUE; } // don't allow price set for contribution if it is related to participant, or if it is a pledge payment // and if we already have line items for that participant. CRM-5095 if ($buildPriceSet && $this->_id) { $componentDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); $pledgePaymentId = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_PledgePayment', $this->_id, 'id', 'contribution_id'); if ($pledgePaymentId) { $buildPriceSet = FALSE; } if ($participantID = CRM_Utils_Array::value('participant', $componentDetails)) { $participantLI = CRM_Price_BAO_LineItem::getLineItems($participantID); if (!CRM_Utils_System::isNull($participantLI)) { $buildPriceSet = FALSE; } } } $hasPriceSets = FALSE; if ($buildPriceSet) { $hasPriceSets = TRUE; $element = $this->add('select', 'price_set_id', ts('Choose price set'), array('' => ts('Choose price set')) + $priceSets, NULL, array('onchange' => "buildAmount( this.value );")); if ($this->_online && !($this->_action & CRM_Core_Action::UPDATE)) { $element->freeze(); } } $this->assign('hasPriceSets', $hasPriceSets); $currencyFreeze = FALSE; if (!($this->_action & CRM_Core_Action::UPDATE)) { if ($this->_online || $this->_ppID) { $attributes['total_amount'] = array_merge($attributes['total_amount'], array('READONLY' => TRUE, 'style' => "background-color:#EBECE4")); $optionTypes = array('1' => ts('Adjust Pledge Payment Schedule?'), '2' => ts('Adjust Total Pledge Amount?')); $this->addRadio('option_type', NULL, $optionTypes, array(), '<br/>'); $currencyFreeze = TRUE; } } $totalAmount = $this->addMoney('total_amount', ts('Total Amount'), $hasPriceSets ? FALSE : TRUE, $attributes['total_amount'], TRUE, 'currency', NULL, $currencyFreeze); } $this->add('text', 'source', ts('Source'), CRM_Utils_Array::value('source', $attributes)); //CRM-7362 --add campaigns. CRM_Campaign_BAO_Campaign::addCampaign($this, CRM_Utils_Array::value('campaign_id', $this->_values)); CRM_Contribute_Form_SoftCredit::buildQuickForm($this); $js = NULL; if (!$this->_mode) { $js = array('onclick' => "return verify( );"); } $mailingInfo = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME, 'mailing_backend'); $this->assign('outBound_option', $mailingInfo['outBound_option']); $this->addButtons(array(array('type' => 'upload', 'name' => ts('Save'), 'js' => $js, 'isDefault' => TRUE), array('type' => 'upload', 'name' => ts('Save and New'), 'js' => $js, 'subName' => 'new'), array('type' => 'cancel', 'name' => ts('Cancel')))); // if status is Cancelled freeze Amount, Payment Instrument, Check #, Financial Type, // Net and Fee Amounts are frozen in AdditionalInfo::buildAdditionalDetail if ($this->_id && $this->_values['contribution_status_id'] == array_search('Cancelled', $statusName)) { if ($totalAmount) { $totalAmount->freeze(); } $checkNumber->freeze(); $paymentInstrument->freeze(); $trxnId->freeze(); $financialType->freeze(); } $this->addFormRule(array('CRM_Contribute_Form_Contribution', 'formRule'), $this); if ($this->_action & CRM_Core_Action::VIEW) { $this->freeze(); } }
/** * @param array $submittedValues * * @param int $action * Action constant * - CRM_Core_Action::UPDATE * * @param $pledgePaymentID * * @return array * @throws \Exception */ protected function submit($submittedValues, $action, $pledgePaymentID) { $softParams = $softIDs = array(); $pId = $contribution = $isRelatedId = FALSE; if (!empty($submittedValues['price_set_id']) && $action & CRM_Core_Action::UPDATE) { $line = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'contribution'); $lineID = key($line); $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', CRM_Utils_Array::value('price_field_id', $line[$lineID]), 'price_set_id'); $quickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config'); if ($quickConfig) { CRM_Price_BAO_LineItem::deleteLineItems($this->_id, 'civicrm_contribution'); } } // Process price set and get total amount and line items. $lineItem = array(); $priceSetId = CRM_Utils_Array::value('price_set_id', $submittedValues); if (empty($priceSetId) && !$this->_id) { $this->_priceSetId = $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', 'default_contribution_amount', 'id', 'name'); $this->_priceSet = current(CRM_Price_BAO_PriceSet::getSetDetail($priceSetId)); $fieldID = key($this->_priceSet['fields']); $fieldValueId = key($this->_priceSet['fields'][$fieldID]['options']); $this->_priceSet['fields'][$fieldID]['options'][$fieldValueId]['amount'] = $submittedValues['total_amount']; $submittedValues['price_' . $fieldID] = 1; } if ($priceSetId) { CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'], $submittedValues, $lineItem[$priceSetId]); // Unset tax amount for offline 'is_quick_config' contribution. if ($this->_priceSet['is_quick_config'] && !array_key_exists($submittedValues['financial_type_id'], CRM_Core_PseudoConstant::getTaxRates())) { unset($submittedValues['tax_amount']); } $submittedValues['total_amount'] = CRM_Utils_Array::value('amount', $submittedValues); } if ($this->_id) { if ($this->_compId) { if ($this->_context == 'participant') { $pId = $this->_compId; } elseif ($this->_context == 'membership') { $isRelatedId = TRUE; } else { $pId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $this->_id, 'participant_id', 'contribution_id'); } } else { $contributionDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); if (array_key_exists('membership', $contributionDetails)) { $isRelatedId = TRUE; } elseif (array_key_exists('participant', $contributionDetails)) { $pId = $contributionDetails['participant']; } } } if (!$priceSetId && !empty($submittedValues['total_amount']) && $this->_id) { // CRM-10117 update the line items for participants. if ($pId) { $entityTable = 'participant'; $entityID = $pId; $isRelatedId = FALSE; $participantParams = array('fee_amount' => $submittedValues['total_amount'], 'id' => $entityID); CRM_Event_BAO_Participant::add($participantParams); if (empty($this->_lineItems)) { $this->_lineItems[] = CRM_Price_BAO_LineItem::getLineItems($entityID, 'participant', 1); } } else { $entityTable = 'contribution'; $entityID = $this->_id; } $lineItems = CRM_Price_BAO_LineItem::getLineItems($entityID, $entityTable, NULL, TRUE, $isRelatedId); foreach (array_keys($lineItems) as $id) { $lineItems[$id]['id'] = $id; } $itemId = key($lineItems); if ($itemId && !empty($lineItems[$itemId]['price_field_id'])) { $this->_priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id'); } if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) { $lineItems[$itemId]['unit_price'] = $lineItems[$itemId]['line_total'] = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('total_amount', $submittedValues)); // Update line total and total amount with tax on edit. $financialItemsId = CRM_Core_PseudoConstant::getTaxRates(); if (array_key_exists($submittedValues['financial_type_id'], $financialItemsId)) { $lineItems[$itemId]['tax_rate'] = $financialItemsId[$submittedValues['financial_type_id']]; } else { $lineItems[$itemId]['tax_rate'] = $lineItems[$itemId]['tax_amount'] = ""; $submittedValues['tax_amount'] = 'null'; } if ($lineItems[$itemId]['tax_rate']) { $lineItems[$itemId]['tax_amount'] = $lineItems[$itemId]['tax_rate'] / 100 * $lineItems[$itemId]['line_total']; $submittedValues['total_amount'] = $lineItems[$itemId]['line_total'] + $lineItems[$itemId]['tax_amount']; $submittedValues['tax_amount'] = $lineItems[$itemId]['tax_amount']; } } // CRM-10117 update the line items for participants. if (!empty($lineItems[$itemId]['price_field_id'])) { $lineItem[$this->_priceSetId] = $lineItems; } } $isQuickConfig = 0; if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) { $isQuickConfig = 1; } //CRM-11529 for quick config back office transactions //when financial_type_id is passed in form, update the //line items with the financial type selected in form if ($isQuickConfig && !empty($submittedValues['financial_type_id']) && CRM_Utils_Array::value($this->_priceSetId, $lineItem)) { foreach ($lineItem[$this->_priceSetId] as &$values) { $values['financial_type_id'] = $submittedValues['financial_type_id']; } } if (!isset($submittedValues['total_amount'])) { $submittedValues['total_amount'] = CRM_Utils_Array::value('total_amount', $this->_values); } $this->assign('lineItem', !empty($lineItem) && !$isQuickConfig ? $lineItem : FALSE); if (!empty($submittedValues['pcp_made_through_id'])) { $pcp = array(); $fields = array('pcp_made_through_id', 'pcp_display_in_roll', 'pcp_roll_nickname', 'pcp_personal_note'); foreach ($fields as $f) { $pcp[$f] = CRM_Utils_Array::value($f, $submittedValues); } } $isEmpty = array_keys(array_flip($submittedValues['soft_credit_contact_id'])); if ($this->_id && count($isEmpty) == 1 && key($isEmpty) == NULL) { //Delete existing soft credit records if soft credit list is empty on update CRM_Contribute_BAO_ContributionSoft::del(array('contribution_id' => $this->_id)); } else { //build soft credit params foreach ($submittedValues['soft_credit_contact_id'] as $key => $val) { if ($val && $submittedValues['soft_credit_amount'][$key]) { $softParams[$key]['contact_id'] = $val; $softParams[$key]['amount'] = CRM_Utils_Rule::cleanMoney($submittedValues['soft_credit_amount'][$key]); $softParams[$key]['soft_credit_type_id'] = $submittedValues['soft_credit_type'][$key]; if (!empty($submittedValues['soft_credit_id'][$key])) { $softIDs[] = $softParams[$key]['id'] = $submittedValues['soft_credit_id'][$key]; } } } } // set the contact, when contact is selected if (!empty($submittedValues['contact_id'])) { $this->_contactID = $submittedValues['contact_id']; } $formValues = $submittedValues; // Credit Card Contribution. if ($this->_mode) { $paramsSetByPaymentProcessingSubsystem = array('trxn_id', 'payment_instrument_id', 'contribution_status_id', 'cancel_date', 'cancel_reason'); foreach ($paramsSetByPaymentProcessingSubsystem as $key) { if (isset($formValues[$key])) { unset($formValues[$key]); } } $contribution = $this->processCreditCard($formValues, $lineItem, $this->_contactID); foreach ($paramsSetByPaymentProcessingSubsystem as $key) { $formValues[$key] = $contribution->{$key}; } } else { // Offline Contribution. $submittedValues = $this->unsetCreditCardFields($submittedValues); // get the required field value only. $params = $ids = array(); $params['contact_id'] = $this->_contactID; $params['currency'] = $this->getCurrency($submittedValues); $fields = array('financial_type_id', 'contribution_status_id', 'payment_instrument_id', 'cancel_reason', 'source', 'check_number'); foreach ($fields as $f) { $params[$f] = CRM_Utils_Array::value($f, $formValues); } if (!empty($pcp)) { $params['pcp'] = $pcp; } if (!empty($softParams)) { $params['soft_credit'] = $softParams; $params['soft_credit_ids'] = $softIDs; } // CRM-5740 if priceset is used, no need to cleanup money. if ($priceSetId) { $params['skipCleanMoney'] = 1; } $dates = array('receive_date', 'receipt_date', 'cancel_date'); foreach ($dates as $d) { $params[$d] = CRM_Utils_Date::processDate($formValues[$d], $formValues[$d . '_time'], TRUE); } if (!empty($formValues['is_email_receipt'])) { $params['receipt_date'] = date("Y-m-d"); } if ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Cancelled', 'name') || $params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Refunded', 'name')) { if (CRM_Utils_System::isNull(CRM_Utils_Array::value('cancel_date', $params))) { $params['cancel_date'] = date('Y-m-d'); } } else { $params['cancel_date'] = $params['cancel_reason'] = 'null'; } // Set is_pay_later flag for back-office offline Pending status contributions CRM-8996 // else if contribution_status is changed to Completed is_pay_later flag is changed to 0, CRM-15041 if ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name')) { $params['is_pay_later'] = 1; } elseif ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Completed', 'name')) { $params['is_pay_later'] = 0; } $ids['contribution'] = $params['id'] = $this->_id; // Add Additional common information to formatted params. CRM_Contribute_Form_AdditionalInfo::postProcessCommon($formValues, $params, $this); if ($pId) { $params['contribution_mode'] = 'participant'; $params['participant_id'] = $pId; $params['skipLineItem'] = 1; } elseif ($isRelatedId) { $params['contribution_mode'] = 'membership'; } $params['line_item'] = $lineItem; $params['payment_processor_id'] = $params['payment_processor'] = CRM_Utils_Array::value('id', $this->_paymentProcessor); if (isset($submittedValues['tax_amount'])) { $params['tax_amount'] = $submittedValues['tax_amount']; } //create contribution. if ($isQuickConfig) { $params['is_quick_config'] = 1; } $params['non_deductible_amount'] = $this->calculateNonDeductibleAmount($params, $formValues); $contribution = CRM_Contribute_BAO_Contribution::create($params, $ids); // process associated membership / participant, CRM-4395 if ($contribution->id && $action & CRM_Core_Action::UPDATE) { $this->statusMessage[] = $this->updateRelatedComponent($contribution->id, $contribution->contribution_status_id, CRM_Utils_Array::value('contribution_status_id', $this->_values), $contribution->receive_date); } array_unshift($this->statusMessage, ts('The contribution record has been saved.')); $this->invoicingPostProcessHook($submittedValues, $action, $lineItem); //send receipt mail. if ($contribution->id && !empty($formValues['is_email_receipt'])) { $formValues['contact_id'] = $this->_contactID; $formValues['contribution_id'] = $contribution->id; $formValues += CRM_Contribute_BAO_ContributionSoft::getSoftContribution($contribution->id); // to get 'from email id' for send receipt $this->fromEmailId = $formValues['from_email_address']; if (CRM_Contribute_Form_AdditionalInfo::emailReceipt($this, $formValues)) { $this->statusMessage[] = ts('A receipt has been emailed to the contributor.'); } } $this->statusMessageTitle = ts('Saved'); } if ($contribution->id && !empty($formValues['product_name'][0])) { CRM_Contribute_Form_AdditionalInfo::processPremium($submittedValues, $contribution->id, $this->_premiumID, $this->_options); } if ($contribution->id && isset($submittedValues['note'])) { CRM_Contribute_Form_AdditionalInfo::processNote($submittedValues, $this->_contactID, $contribution->id, $this->_noteID); } CRM_Core_Session::setStatus(implode(' ', $this->statusMessage), $this->statusMessageTitle, 'success'); CRM_Contribute_BAO_Contribution::updateRelatedPledge($action, $pledgePaymentID, $contribution->id, CRM_Utils_Array::value('option_type', $formValues) == 2 ? TRUE : FALSE, $formValues['total_amount'], CRM_Utils_Array::value('total_amount', $this->_defaults), $formValues['contribution_status_id'], CRM_Utils_Array::value('contribution_status_id', $this->_defaults)); return $contribution; }
/** * Function to build the form * * @return None * @access public */ public function buildQuickForm() { if ($this->_cdType) { return CRM_Custom_Form_CustomData::buildQuickForm($this); } // build price set form. $buildPriceSet = false; if (empty($this->_lineItems) && ($this->_priceSetId || CRM_Utils_Array::value('price_set_id', $_POST))) { $buildPriceSet = true; $getOnlyPriceSetElements = true; if (!$this->_priceSetId) { $this->_priceSetId = $_POST['price_set_id']; $getOnlyPriceSetElements = false; } $this->set('priceSetId', $this->_priceSetId); require_once 'CRM/Price/BAO/Set.php'; CRM_Price_BAO_Set::buildPriceSet($this); // get only price set form elements. if ($getOnlyPriceSetElements) { return; } } // use to build form during form rule. $this->assign('buildPriceSet', $buildPriceSet); $showAdditionalInfo = false; require_once 'CRM/Contribute/Form/AdditionalInfo.php'; $defaults = $this->_values; $additionalDetailFields = array('note', 'thankyou_date', 'invoice_id', 'non_deductible_amount', 'fee_amount', 'net_amount'); foreach ($additionalDetailFields as $key) { if (!empty($defaults[$key])) { $defaults['hidden_AdditionalDetail'] = 1; break; } } $honorFields = array('honor_type_id', 'honor_prefix_id', 'honor_first_name', 'honor_lastname', 'honor_email'); foreach ($honorFields as $key) { if (!empty($defaults[$key])) { $defaults['hidden_Honoree'] = 1; break; } } //check for honoree pane. if ($this->_ppID && CRM_Utils_Array::value('honor_contact_id', $this->_pledgeValues)) { $defaults['hidden_Honoree'] = 1; } if ($this->_productDAO) { if ($this->_productDAO->product_id) { $defaults['hidden_Premium'] = 1; } } if ($this->_noteID && isset($this->_values['note'])) { $defaults['hidden_AdditionalDetail'] = 1; } $paneNames = array('Additional Details' => 'AdditionalDetail', 'Honoree Information' => 'Honoree'); //Add Premium pane only if Premium is exists. require_once 'CRM/Contribute/DAO/Product.php'; $dao =& new CRM_Contribute_DAO_Product(); $dao->is_active = 1; if ($dao->find(true)) { $paneNames['Premium Information'] = 'Premium'; } $ccPane = null; if ($this->_mode) { if ($this->_processors['payment_type'] & CRM_Core_Payment::PAYMENT_TYPE_DIRECT_DEBIT) { $ccPane = array(ts('Direct Debit Information') => 'DirectDebit'); } else { $ccPane = array('Credit Card Information' => 'CreditCard'); } } if (is_array($ccPane)) { $paneNames = array_merge($ccPane, $paneNames); } foreach ($paneNames as $name => $type) { $urlParams = "snippet=4&formType={$type}"; if ($this->_mode) { $urlParams .= "&mode={$this->_mode}"; } $open = 'false'; if ($type == 'CreditCard' || $type == 'DirectDebit') { $open = 'true'; } $allPanes[$name] = array('url' => CRM_Utils_System::url('civicrm/contact/view/contribution', $urlParams), 'open' => $open, 'id' => $type); // see if we need to include this paneName in the current form if ($this->_formType == $type || CRM_Utils_Array::value("hidden_{$type}", $_POST) || CRM_Utils_Array::value("hidden_{$type}", $defaults)) { $showAdditionalInfo = true; $allPanes[$name]['open'] = 'true'; } if ($type == 'CreditCard') { $this->add('hidden', 'hidden_CreditCard', 1); CRM_Core_Payment_Form::buildCreditCard($this, true); } else { if ($type == 'DirectDebit') { $this->add('hidden', 'hidden_DirectDebit', 1); CRM_Core_Payment_Form::buildDirectDebit($this, true); } else { eval('CRM_Contribute_Form_AdditionalInfo::build' . $type . '( $this );'); } } } $this->assign('allPanes', $allPanes); $this->assign('showAdditionalInfo', $showAdditionalInfo); if ($this->_formType) { $this->assign('formType', $this->_formType); return; } $this->applyFilter('__ALL__', 'trim'); if ($this->_action & CRM_Core_Action::DELETE) { $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 and subtype to the template $this->assign('customDataType', 'Contribution'); $this->assign('customDataSubType', $this->_contributionType); $this->assign('entityID', $this->_id); if ($this->_context == 'standalone') { require_once 'CRM/Contact/Form/NewContact.php'; CRM_Contact_Form_NewContact::buildQuickForm($this); } $attributes = CRM_Core_DAO::getAttribute('CRM_Contribute_DAO_Contribution'); $element =& $this->add('select', 'contribution_type_id', ts('Contribution Type'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::contributionType(), true, array('onChange' => "buildCustomData( 'Contribution', this.value );")); if ($this->_online) { $element->freeze(); } if (!$this->_mode) { $element =& $this->add('select', 'payment_instrument_id', ts('Paid By'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(), false, array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")); if ($this->_online) { $element->freeze(); } } $element =& $this->add('text', 'trxn_id', ts('Transaction ID'), $attributes['trxn_id']); if ($this->_online) { $element->freeze(); } else { $this->addRule('trxn_id', ts('This Transaction ID already exists in the database. Include the account number for checks.'), 'objectExists', array('CRM_Contribute_DAO_Contribution', $this->_id, 'trxn_id')); } //add receipt for offline contribution $this->addElement('checkbox', 'is_email_receipt', ts('Send Receipt?'), null, array('onclick' => "return showHideByValue('is_email_receipt','','receiptDate','table-row','radio',true);")); $status = CRM_Contribute_PseudoConstant::contributionStatus(); // supressing contribution statuses that are NOT relevant to pledges (CRM-5169) if ($this->_ppID) { foreach (array('Cancelled', 'Failed', 'In Progress') as $supress) { unset($status[CRM_Utils_Array::key($supress, $status)]); } } $this->add('select', 'contribution_status_id', ts('Contribution Status'), $status, false, array('onClick' => "if (this.value != 3) status(); else return false", 'onChange' => "return showHideByValue('contribution_status_id','3','cancelInfo','table-row','select',false);")); // add various dates $this->addDate('receive_date', ts('Received'), false, array('formatType' => 'activityDate')); if ($this->_online) { $this->assign("hideCalender", true); } $element =& $this->add('text', 'check_number', ts('Check Number'), $attributes['check_number']); if ($this->_online) { $element->freeze(); } $this->addDate('receipt_date', ts('Receipt Date'), false, array('formatType' => 'activityDate')); $this->addDate('cancel_date', ts('Cancelled Date'), false, array('formatType' => 'activityDate')); $this->add('textarea', 'cancel_reason', ts('Cancellation Reason'), $attributes['cancel_reason']); $element =& $this->add('select', 'payment_processor_id', ts('Payment Processor'), $this->_processors); if ($this->_online) { $element->freeze(); } if (empty($this->_lineItems)) { $buildPriceSet = false; require_once 'CRM/Price/BAO/Set.php'; $priceSets = CRM_Price_BAO_Set::getAssoc(false, 'CiviContribute'); if (!empty($priceSets) && !$this->_ppID) { $buildPriceSet = true; } // don't allow price set for contribution if it is related to participant, // and if we already have line items for that participant. CRM-5095 if ($buildPriceSet && $this->_id) { $componentDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); if ($participantID = CRM_Utils_Array::value('participant', $componentDetails)) { require_once 'CRM/Price/BAO/LineItem.php'; $participantLI = CRM_Price_BAO_LineItem::getLineItems($participantID); if (!CRM_Utils_System::isNull($participantLI)) { $buildPriceSet = false; } } } $hasPriceSets = false; if ($buildPriceSet) { $hasPriceSets = true; $element =& $this->add('select', 'price_set_id', ts('Choose price set'), array('' => ts('Choose price set')) + $priceSets, null, array('onchange' => "buildAmount( this.value );")); if ($this->_online) { $element->freeze(); } } $this->assign('hasPriceSets', $hasPriceSets); $element =& $this->add('text', 'total_amount', ts('Total Amount'), $attributes['total_amount'], $hasPriceSets ? false : true); $this->addRule('total_amount', ts('Please enter a valid amount.'), 'money'); if ($this->_online || $this->_ppID) { $element->freeze(); } } $element =& $this->add('text', 'source', ts('Source'), CRM_Utils_Array::value('source', $attributes)); if ($this->_online) { $element->freeze(); } $dataUrl = CRM_Utils_System::url("civicrm/ajax/contactlist", "reset=1&context=softcredit&id={$this->_id}", false, null, false); $this->assign('dataUrl', $dataUrl); $this->addElement('text', 'soft_credit_to', ts('Soft Credit To')); $this->addElement('hidden', 'soft_contact_id', '', array('id' => 'soft_contact_id')); if (CRM_Utils_Array::value('pcp_made_through_id', $defaults) && $this->_action & CRM_Core_Action::UPDATE) { $ele = $this->addElement('select', 'pcp_made_through_id', ts('Personal Campaign Page'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::pcPage()); $ele->freeze(); $this->addElement('checkbox', 'pcp_display_in_roll', ts('Honor Roll?'), null, array('onclick' => "return showHideByValue('pcp_display_in_roll','','nameID|nickID|personalNoteID','table-row','radio',false);")); $this->addElement('text', 'pcp_roll_nickname', ts('Nickname')); $this->addElement('textarea', 'pcp_personal_note', ts('Personal Note')); } $js = null; if (!$this->_mode) { $js = array('onclick' => "return verify( );"); } require_once "CRM/Core/BAO/Preferences.php"; $mailingInfo =& CRM_Core_BAO_Preferences::mailingPreferences(); $this->assign('outBound_option', $mailingInfo['outBound_option']); $this->addButtons(array(array('type' => 'upload', 'name' => ts('Save'), 'js' => $js, 'isDefault' => true), array('type' => 'upload', 'name' => ts('Save and New'), 'js' => $js, 'subName' => 'new'), array('type' => 'cancel', 'name' => ts('Cancel')))); $this->addFormRule(array('CRM_Contribute_Form_Contribution', 'formRule'), $this); if ($this->_action & CRM_Core_Action::VIEW) { $this->freeze(); } }