Skip to content
Snippets Groups Projects
Unverified Commit 68abd618 authored by eileen's avatar eileen :8ball: Committed by GitHub
Browse files

Merge pull request #13561 from eileenmcnaughton/payment_conf

Add new Payment.sendconfirmation api
parents 6f724671 a79d2ec2
Branches
Tags
No related merge requests found
......@@ -4000,7 +4000,8 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
*
* @return mixed
*/
public static function getPaymentInfo($id, $component, $getTrxnInfo = FALSE, $usingLineTotal = FALSE) {
public static function getPaymentInfo($id, $component = 'contribution', $getTrxnInfo = FALSE, $usingLineTotal = FALSE) {
// @todo deprecate passing in component - always call with contribution.
if ($component == 'event') {
$entity = 'participant';
$entityTable = 'civicrm_participant';
......
......@@ -454,6 +454,7 @@ WHERE ceft.entity_id = %1";
return $value;
}
// @todo - deprecate passing in entity & type - just figure out contribution id FIRST
if ($entityName == 'participant') {
$contributionId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $entityId, 'contribution_id', 'participant_id');
}
......
......@@ -117,4 +117,158 @@ class CRM_Financial_BAO_Payment {
return $trxn;
}
/**
* Send an email confirming a payment that has been received.
*
* @param array $params
*
* @return array
*/
public static function sendConfirmation($params) {
$entities = self::loadRelatedEntities($params['id']);
$sendTemplateParams = array(
'groupName' => 'msg_tpl_workflow_contribution',
'valueName' => 'payment_or_refund_notification',
'PDFFilename' => ts('notification') . '.pdf',
'contactId' => $entities['contact']['id'],
'toName' => $entities['contact']['display_name'],
'toEmail' => $entities['contact']['email'],
'tplParams' => self::getConfirmationTemplateParameters($entities),
);
return CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams);
}
/**
* Load entities related to the current payment id.
*
* This gives us all the data we need to send an email confirmation but avoiding
* getting anything not tested for the confirmations. We retrieve the 'full' event as
* it has been traditionally assigned in full.
*
* @param int $id
*
* @return array
* - contact = ['id' => x, 'display_name' => y, 'email' => z]
* - event = [.... full event details......]
* - contribution = ['id' => x],
* - payment = [payment info + payment summary info]
*/
protected static function loadRelatedEntities($id) {
$entities = [];
$contributionID = (int) civicrm_api3('EntityFinancialTrxn', 'getvalue', [
'financial_trxn_id' => $id,
'entity_table' => 'civicrm_contribution',
'return' => 'entity_id',
]);
$entities['contribution'] = ['id' => $contributionID];
$entities['payment'] = array_merge(civicrm_api3('FinancialTrxn', 'getsingle', ['id' => $id]),
CRM_Contribute_BAO_Contribution::getPaymentInfo($contributionID)
);
$contactID = self::getPaymentContactID($contributionID);
list($displayName, $email) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactID);
$entities['contact'] = ['id' => $contactID, 'display_name' => $displayName, 'email' => $email];
$participantRecords = civicrm_api3('ParticipantPayment', 'get', [
'contribution_id' => $contributionID,
'api.Participant.get' => ['return' => 'event_id'],
'sequential' => 1,
])['values'];
if (!empty($participantRecords)) {
$entities['event'] = civicrm_api3('Event', 'getsingle', ['id' => $participantRecords[0]['api.Participant.get']['values'][0]['event_id']]);
}
return $entities;
}
/**
* @param int $contributionID
*
* @return int
*/
public static function getPaymentContactID($contributionID) {
$contribution = civicrm_api3('Contribution', 'getsingle', [
'id' => $contributionID ,
'return' => ['contact_id'],
]);
return (int) $contribution['contact_id'];
}
/**
* @param array $entities
* Related entities as an array keyed by the various entities.
*
* @return array
* Values required for the notification
* - contact_id
* - template_variables
* - event (DAO of event if relevant)
*/
public static function getConfirmationTemplateParameters($entities) {
$templateVariables = [
'contactDisplayName' => $entities['contact']['display_name'],
'totalAmount' => $entities['payment']['total'],
'amountOwed' => $entities['payment']['balance'],
'paymentAmount' => $entities['payment']['total_amount'],
'event' => NULL,
'component' => 'contribution',
];
if (!empty($entities['event'])) {
$templateVariables['component'] = 'event';
$templateVariables['event'] = $entities['event'];
}
return self::filterUntestedTemplateVariables($templateVariables);
}
/**
* Filter out any untested variables.
*
* This just serves to highlight if any variables are added without a unit test also being added.
*
* (if hit then add a unit test for the param & add to this array).
*
* @param array $params
*
* @return array
*/
public static function filterUntestedTemplateVariables($params) {
$testedTemplateVariables = [
'contactDisplayName',
'totalAmount',
'amountOwed',
'paymentAmount',
'event',
'component',
];
// Need to do these before switching the form over...
$todoParams = [
'isRefund',
'totalPaid',
'refundAmount',
'paymentsComplete',
'receive_date',
'paidBy',
'checkNumber',
'contributeMode',
'isAmountzero',
'billingName',
'address',
'credit_card_type',
'credit_card_number',
'credit_card_exp_date',
'isShowLocation',
'location',
'eventEmail',
'$event.participant_role',
];
$filteredParams = [];
foreach ($testedTemplateVariables as $templateVariable) {
// This will cause an a-notice if any are NOT set - by design. Ensuring
// they are set prevents leakage.
$filteredParams[$templateVariable] = $params[$templateVariable];
}
return $filteredParams;
}
}
......@@ -235,3 +235,49 @@ function _civicrm_api3_payment_cancel_spec(&$params) {
),
);
}
/**
* Send a payment confirmation.
*
* @param array $params
* Input parameters.
*
* @return array
* @throws Exception
*/
function civicrm_api3_payment_sendconfirmation($params) {
$allowedParams = [
'receipt_from_email',
'receipt_from_name',
'cc_receipt',
'bcc_receipt',
'receipt_text',
'id',
];
$input = array_intersect_key($params, array_flip($allowedParams));
// use either the contribution or membership receipt, based on whether it’s a membership-related contrib or not
$result = CRM_Financial_BAO_Payment::sendConfirmation($input);
return civicrm_api3_create_success([
$params['id'] => [
'is_sent' => $result[0],
'subject' => $result[1],
'message_txt' => $result[2],
'message_html' => $result[3],
]]);
}
/**
* Adjust Metadata for sendconfirmation action.
*
* The metadata is used for setting defaults, documentation & validation.
*
* @param array $params
* Array of parameters determined by getfields.
*/
function _civicrm_api3_payment_sendconfirmation_spec(&$params) {
$params['id'] = array(
'api.required' => 1,
'title' => ts('Payment ID'),
'type' => CRM_Utils_Type::T_INT,
);
}
......@@ -104,6 +104,39 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
));
}
/**
* Test email receipt for partial payment.
*/
public function testPaymentEmailReceipt() {
$mut = new CiviMailUtils($this);
list($lineItems, $contribution) = $this->createParticipantWithContribution();
$params = array(
'contribution_id' => $contribution['id'],
'total_amount' => 50,
);
$payment = $this->callAPISuccess('payment', 'create', $params);
$this->checkPaymentResult($payment, [
$payment['id'] => [
'from_financial_account_id' => 7,
'to_financial_account_id' => 6,
'total_amount' => 50,
'status_id' => 1,
'is_payment' => 1,
],
]);
$this->callAPISuccess('Payment', 'sendconfirmation', ['id' => $payment['id']]);
$mut->assertSubjects(['Payment Receipt - Annual CiviCRM meet']);
$mut->checkMailLog(array(
'Dear Mr. Anthony Anderson II',
'Total Fees: $ 300.00',
'This Payment Amount: $ 50.00',
'Balance Owed: $ 100.00', //150 was paid in the 1st payment.
'Event Information and Location',
));
$mut->stop();
}
/**
* Test create payment api with no line item in params
*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment