use Civi\Api4\PriceFieldValue;
use Civi\Api4\PriceSet;
use Civi\Api4\WorkflowMessage;
+use Civi\Test;
use Civi\WorkflowMessage\GenericWorkflowMessage;
use Civi\WorkflowMessage\WorkflowMessageExample;
* Get the examples this class is able to deliver.
*/
public function getExamples(): iterable {
- $workflows = ['contribution_online_receipt', 'contribution_offline_receipt', 'contribution_invoice_receipt'];
+ $workflows = ['contribution_online_receipt', 'contribution_offline_receipt', 'contribution_invoice_receipt', 'payment_or_refund_notification'];
+ $defaultCurrency = \Civi::settings()->get('defaultCurrency');
+ $currencies = [$defaultCurrency => $defaultCurrency, 'EUR' => 'EUR', 'CAD' => 'CAD'];
foreach ($workflows as $workflow) {
+ foreach ($currencies as $currency) {
+ yield [
+ 'name' => 'workflow/' . $workflow . '/basic_' . $currency,
+ 'title' => ts('Completed Contribution') . ' : ' . $currency,
+ 'tags' => $workflow === 'contribution_offline_receipt' ? ['phpunit', 'preview'] : ['preview'],
+ 'workflow' => $workflow,
+ ];
+ }
yield [
- 'name' => 'workflow/' . $workflow . '/basic_eur',
- 'title' => ts('Completed Contribution') . ' : ' . 'EUR',
- 'tags' => $workflow === 'contribution_offline_receipt' ? ['phpunit', 'preview'] : ['preview'],
- 'workflow' => $workflow,
- ];
- yield [
- 'name' => 'workflow/' . $workflow . '/' . 'basic_cad',
- 'title' => ts('Completed Contribution') . ' : ' . 'CAD',
+ 'name' => 'workflow/' . $workflow . '/' . 'partially paid' . $currency,
+ 'title' => ts('Partially Paid Contribution') . ' : ' . $currency,
'tags' => ['preview'],
'workflow' => $workflow,
- 'contribution_params' => ['currency' => 'CAD'],
+ 'is_show_line_items' => TRUE,
+ 'contribution_params' => ['contribution_status_id' => \CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Partially paid')],
];
$priceSet = $this->getNonQuickConfigPriceSet();
if ($priceSet) {
* @throws \Civi\API\Exception\UnauthorizedException
*/
private function addExampleData(GenericWorkflowMessage $messageTemplate, $example): void {
- $messageTemplate->setContact(\Civi\Test::example('entity/Contact/Barb'));
- $contribution = \Civi\Test::example('entity/Contribution/Euro5990/completed');
+ $messageTemplate->setContact(Test::example('entity/Contact/Barb'));
+ $contribution = Test::example('entity/Contribution/Euro5990/completed');
+ $example['currency'] = $example['currency'] ?? \Civi::settings()->get('defaultCurrency');
if (isset($example['contribution_params'])) {
$contribution = array_merge($contribution, $example['contribution_params']);
}
$contribution['contribution_status_id:name'] = \CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $contribution['contribution_status_id']);
$contribution['contribution_status_id:label'] = \CRM_Core_PseudoConstant::getLabel('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $contribution['contribution_status_id']);
-
+ if ($contribution['contribution_status_id:name'] === 'Partially paid') {
+ $contribution['paid_amount'] = round($contribution['total_amount'] / 2, 2);
+ }
+ elseif ($contribution['contribution_status_id:name'] === 'Pending' || $contribution['contribution_status_id:name'] === 'Refunded') {
+ $contribution['paid_amount'] = 0;
+ }
+ else {
+ $contribution['paid_amount'] = $contribution['total_amount'];
+ }
+ $contribution['balance_amount'] = $contribution['total_amount'] - $contribution['paid_amount'];
+ if ($contribution['contribution_status_id:name'] === 'Refunded') {
+ $contribution['balance_amount'] = 0;
+ }
+ $contribution['net_amount'] = $contribution['total_amount'] - $contribution['fee_amount'];
$mockOrder = new CRM_Financial_BAO_Order();
$mockOrder->setTemplateContributionID(50);
$messageTemplate->setContribution($contribution);
$messageTemplate->setOrder($mockOrder);
$messageTemplate->setContribution($contribution);
+ $financialTrxn = [
+ 'trxn_date' => date('Y-m-d H:i:s'),
+ 'total_amount' => $contribution['contribution_status_id:name'] === 'Refunded' ? -$contribution['total_amount'] : $contribution['paid_amount'],
+ 'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_FinancialTrxn', 'payment_instrument_id', 'Credit Card'),
+ 'card_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_FinancialTrxn', 'card_type_id', 'Visa'),
+ 'pan_truncation' => 5679,
+ ];
+ $financialTrxn['payment_instrument_id:label'] = \CRM_Core_PseudoConstant::getLabel('CRM_Financial_BAO_FinancialTrxn', 'payment_instrument_id', $financialTrxn['payment_instrument_id']);
+ $financialTrxn['payment_instrument_id:name'] = \CRM_Core_PseudoConstant::getName('CRM_Financial_BAO_FinancialTrxn', 'payment_instrument_id', $financialTrxn['payment_instrument_id']);
+ $financialTrxn['card_type_id:label'] = \CRM_Core_PseudoConstant::getLabel('CRM_Financial_BAO_FinancialTrxn', 'card_type_id', $financialTrxn['card_type_id']);
+ $financialTrxn['card_type_id:name'] = \CRM_Core_PseudoConstant::getName('CRM_Financial_BAO_FinancialTrxn', 'card_type_id', $financialTrxn['card_type_id']);
+
+ $messageTemplate->setFinancialTrxn($financialTrxn);
}
/**
use Civi\Api4\Membership;
/**
- * @method array getContribution()
* @method int|null getContributionID()
- * @method $this setContributionID(?int $contributionId)
+ * @method $this setContributionID(?int $contributionID)
+ * @method int|null getFinancialTrxnID()
+ * @method $this setFinancialTrxnID(?int $financialTrxnID)
*/
trait CRM_Contribute_WorkflowMessage_ContributionTrait {
/**
*/
public $contribution;
+ /**
+ * @return array|null
+ */
+ public function getContribution(): ?array {
+ return $this->contribution;
+ }
+
+ /**
+ * Optional financial transaction (payment).
+ *
+ * @var array|null
+ *
+ * @scope tokenContext as financial_trxn
+ */
+ public $financialTrxn;
+
/**
* @var int
* @scope tokenContext as contributionId, tplParams as contributionID
*/
public $contributionID;
+ /**
+ * @var int
+ * @scope tokenContext as financial_trxnId
+ */
+ public $financialTrxnID;
+
/**
* Is the site configured such that tax should be displayed.
*
return $this;
}
+ /**
+ * Set contribution object.
+ *
+ * @param array $financialTrxn
+ *
+ * @return $this
+ */
+ public function setFinancialTrxn(array $financialTrxn): self {
+ $this->financialTrxn = $financialTrxn;
+ if (!empty($financialTrxn['id'])) {
+ $this->financialTrxnID = $financialTrxn['id'];
+ }
+ return $this;
+ }
+
/**
* Set order object.
*
--- /dev/null
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved. |
+ | |
+ | This work is published under the GNU AGPLv3 license with some |
+ | permitted exceptions and without any warranty. For full license |
+ | and copyright information, see https://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+use Civi\WorkflowMessage\GenericWorkflowMessage;
+
+/**
+ * Receipt sent when confirming contribution add payment.
+ *
+ * @method int getEventID()
+ *
+ * @support template-only
+ * @see CRM_Financial_BAO_Payment::sendConfirmation()
+ */
+class CRM_Contribute_WorkflowMessage_PaymentOrRefundNotification extends GenericWorkflowMessage {
+ use CRM_Contribute_WorkflowMessage_ContributionTrait;
+ public const WORKFLOW = 'payment_or_refund_notification';
+
+ /**
+ * @var int
+ *
+ * @scope tokenContext as eventId, tplParams as eventID
+ */
+ public $eventID;
+
+}
* @internal
*/
protected function getEventTokenValues(int $eventID = NULL): array {
+ if (!$eventID) {
+ return [];
+ }
$cacheKey = __CLASS__ . 'event_tokens' . $eventID . '_' . CRM_Core_I18n::getLocale();
if ($this->checkPermissions) {
$cacheKey .= '__' . CRM_Core_Session::getLoggedInContactID();
$entities = self::loadRelatedEntities($params['id']);
$sendTemplateParams = [
- 'groupName' => 'msg_tpl_workflow_contribution',
'workflow' => '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),
+ 'modelProps' => array_filter([
+ 'contributionID' => $entities['contribution']['id'],
+ 'contactID' => $entities['contact']['id'],
+ 'financialTrxnID' => $params['id'],
+ 'eventID' => $entities['event']['id'] ?? NULL,
+ 'participantID' => $entities['participant']['id'] ?? NULL,
+ ]),
];
if (!empty($params['from']) && !empty($params['check_permissions'])) {
// Filter from against permitted emails.
'sequential' => 1,
])['values'];
if (!empty($participantRecords)) {
- $entities['event'] = civicrm_api3('Event', 'getsingle', ['id' => $participantRecords[0]['api.Participant.get']['values'][0]['event_id']]);
+ $entities['participant'] = $participantRecords[0]['api.Participant.get']['values'][0];
+ $entities['event'] = civicrm_api3('Event', 'getsingle', ['id' => $entities['participant']['event_id']]);
if (!empty($entities['event']['is_show_location'])) {
$locationParams = [
'entity_id' => $entities['event']['id'],
* @param array $entities
* Related entities as an array keyed by the various entities.
*
+ * @deprecated these template variables no longer used in the core template
+ * from 5.69 - stop assigning them.
+ *
* @return array
* Values required for the notification
* - contact_id
return 'FinancialTrxn';
}
+ /**
+ * @return array
+ */
+ public function getCurrencyFieldName(): array {
+ return ['currency'];
+ }
+
}
<tr>
<td>
{assign var="greeting" value="{contact.email_greeting_display}"}{if $greeting}<p>{$greeting},</p>{/if}
- {if $isRefund}
+ {if {financial_trxn.total_amount|raw} < 0}
<p>{ts}A refund has been issued based on changes in your registration selections.{/ts}</p>
{else}
<p>{ts}Below you will find a receipt for this payment.{/ts}</p>
- {if $paymentsComplete}
+ {if !{contribution.balance_amount|boolean}}
<p>{ts}Thank you for completing this contribution.{/ts}</p>
{/if}
{/if}
<tr>
<td>
<table style="border: 1px solid #999; margin: 1em 0em 1em; border-collapse: collapse; width:100%;">
- {if $isRefund}
+ {if {financial_trxn.total_amount|raw} < 0}
<tr>
<th {$headerStyle}>{ts}Refund Details{/ts}</th>
</tr>
{ts}This Refund Amount{/ts}
</td>
<td {$valueStyle}>
- {$refundAmount|crmMoney:$currency}
+ {financial_trxn.total_amount}
</td>
</tr>
{else}
{ts}This Payment Amount{/ts}
</td>
<td {$valueStyle}>
- {$paymentAmount|crmMoney:$currency}
+ {financial_trxn.total_amount}
</td>
</tr>
{/if}
- {if $receive_date}
+ {if {financial_trxn.trxn_date|boolean}}
<tr>
<td {$labelStyle}>
{ts}Transaction Date{/ts}
</td>
<td {$valueStyle}>
- {$receive_date|crmDate}
+ {financial_trxn.trxn_date}
</td>
</tr>
{/if}
- {if !empty($trxn_id)}
+ {if {financial_trxn.trxn_id|boolean}}
<tr>
<td {$labelStyle}>
{ts}Transaction #{/ts}
</td>
<td {$valueStyle}>
- {$trxn_id}
+ {financial_trxn.trxn_id}
</td>
</tr>
{/if}
- {if !empty($paidBy)}
+ {if {financial_trxn.payment_instrument_id|boolean}}
<tr>
<td {$labelStyle}>
{ts}Paid By{/ts}
</td>
<td {$valueStyle}>
- {$paidBy}
+ {financial_trxn.payment_instrument_id:label}
</td>
</tr>
{/if}
- {if !empty($checkNumber)}
+ {if {financial_trxn.check_number|boolean}}
<tr>
<td {$labelStyle}>
{ts}Check Number{/ts}
</td>
<td {$valueStyle}>
- {$checkNumber}
+ {financial_trxn.check_number}
</td>
</tr>
{/if}
<tr>
<th {$headerStyle}>{ts}Contribution Details{/ts}</th>
</tr>
- {if $totalAmount}
+ {if {contribution.total_amount|boolean}}
<tr>
<td {$labelStyle}>
{ts}Total Fee{/ts}
</td>
<td {$valueStyle}>
- {$totalAmount|crmMoney:$currency}
+ {contribution.total_amount}
</td>
</tr>
{/if}
- {if $totalPaid}
+ {if {contribution.paid_amount|boolean}}
<tr>
<td {$labelStyle}>
{ts}Total Paid{/ts}
</td>
<td {$valueStyle}>
- {$totalPaid|crmMoney:$currency}
+ {contribution.paid_amount}
</td>
</tr>
{/if}
- {if $amountOwed}
+ {if {contribution.balance_amount|boolean}}
<tr>
<td {$labelStyle}>
{ts}Balance Owed{/ts}
</td>
<td {$valueStyle}>
- {$amountOwed|crmMoney:$currency}
- </td> {* This will be zero after final payment. *}
+ {contribution.balance_amount}
+ </td>
</tr>
{/if}
</table>
<td>
<table style="border: 1px solid #999; margin: 1em 0em 1em; border-collapse: collapse; width:100%;">
{if !empty($billingName) || !empty($address)}
- <tr>
- <th {$headerStyle}>
- {ts}Billing Name and Address{/ts}
- </th>
- </tr>
- <tr>
- <td colspan="2" {$valueStyle}>
+ <tr>
+ <th {$headerStyle}>
+ {ts}Billing Name and Address{/ts}
+ </th>
+ </tr>
+ <tr>
+ <td colspan="2" {$valueStyle}>
{if !empty($billingName)}{$billingName}{/if}<br />
{if !empty($address)}{$address|nl2br}{/if}
- </td>
- </tr>
- {/if}
- {if !empty($credit_card_number)}
- <tr>
- <th {$headerStyle}>
- {ts}Credit Card Information{/ts}
- </th>
- </tr>
- <tr>
- <td colspan="2" {$valueStyle}>
- {$credit_card_type}<br />
- {$credit_card_number}<br />
- {ts}Expires:{/ts} {$credit_card_exp_date|truncate:7:''|crmDate}
- </td>
- </tr>
+ </td>
+ </tr>
+ {/if}
+ {if {financial_trxn.pan_truncation|boolean}}
+ <tr>
+ <th {$headerStyle}>
+ {ts}Credit Card Information{/ts}
+ </th>
+ </tr>
+ <tr>
+ <td colspan="2" {$valueStyle}>
+ {financial_trxn.card_type_id:label}<br />
+ ************{financial_trxn.pan_truncation}<br />
+ </td>
+ </tr>
{/if}
- {if $component eq 'event'}
- <tr>
- <th {$headerStyle}>
- {ts}Event Information and Location{/ts}
- </th>
- </tr>
- <tr>
- <td colspan="2" {$valueStyle}>
- {$event.event_title}<br />
- {$event.event_start_date|crmDate}{if $event.event_end_date}-{if $event.event_end_date|crmDate:"%Y%m%d" == $event.event_start_date|crmDate:"%Y%m%d"}{$event.event_end_date|crmDate:0:1}{else}{$event.event_end_date|crmDate}{/if}{/if}
- </td>
- </tr>
+ {if {event.id|boolean}}
+ <tr>
+ <th {$headerStyle}>
+ {ts}Event Information and Location{/ts}
+ </th>
+ </tr>
+ <tr>
+ <td colspan="2" {$valueStyle}>
+ {event.event_title}<br />
+ {event.start_date|crmDate}{if {event.end_date|boolean}}-{if '{event.end_date|crmDate:"%Y%m%d"}' === '{event.start_date|crmDate:"%Y%m%d"}'}{event.end_date|crmDate:"Time"}{else}{event.end_date}{/if}{/if}
+ </td>
+ </tr>
- {if !empty($event.participant_role)}
- <tr>
- <td {$labelStyle}>
- {ts}Participant Role{/ts}
- </td>
- <td {$valueStyle}>
- {$event.participant_role}
- </td>
- </tr>
- {/if}
+ {if {participant.role_id|boolean}}
+ <tr>
+ <td {$labelStyle}>
+ {ts}Participant Role{/ts}
+ </td>
+ <td {$valueStyle}>
+ {participant.role_id:label}
+ </td>
+ </tr>
+ {/if}
- {if !empty($isShowLocation)}
- <tr>
- <td colspan="2" {$valueStyle}>
- {$location.address.1.display|nl2br}
- </td>
- </tr>
- {/if}
+ {if {event.is_show_location|boolean}}
+ <tr>
+ <td colspan="2" {$valueStyle}>
+ {event.location}
+ </td>
+ </tr>
+ {/if}
+ {if {event.loc_block_id.phone_id.phone|boolean} || {event.loc_block_id.email_id.email|boolean}}
+ <tr>
+ <td colspan="2" {$labelStyle}>
+ {ts}Event Contacts:{/ts}
+ </td>
+ </tr>
- {if !empty($location.phone.1.phone) || !empty($location.email.1.email)}
- <tr>
- <td colspan="2" {$labelStyle}>
- {ts}Event Contacts:{/ts}
+ {if {event.loc_block_id.phone_id.phone|boolean}}
+ <tr>
+ <td {$labelStyle}>
+ {if {event.loc_block_id.phone_id.phone_type_id|boolean}}
+ {event.loc_block_id.phone_id.phone_type_id:label}
+ {else}
+ {ts}Phone{/ts}
+ {/if}
+ </td>
+ <td {$valueStyle}>
+ {event.loc_block_id.phone_id.phone} {if {event.loc_block_id.phone_id.phone_ext|boolean}} {ts}ext.{/ts} {event.loc_block_id.phone_id.phone_ext}{/if}
+ </td>
+ </tr>
+ {/if}
+ {if {event.loc_block_id.phone_2_id.phone|boolean}}
+ <tr>
+ <td {$labelStyle}>
+ {if {event.loc_block_id.phone_2_id.phone_type_id|boolean}}
+ {event.loc_block_id.phone_2_id.phone_type_id:label}
+ {else}
+ {ts}Phone{/ts}
+ {/if}
+ </td>
+ <td {$valueStyle}>
+ {event.loc_block_id.phone_2_id.phone} {if {event.loc_block_id.phone_2_id.phone_ext|boolean}} {ts}ext.{/ts} {event.loc_block_id.phone_2_id.phone_ext}{/if}
+ </td>
+ </tr>
+ {/if}
+
+ {if {event.loc_block_id.email_id.email|boolean}}
+ <tr>
+ <td {$labelStyle}>
+ {ts}Email{/ts}
+ </td>
+ <td {$valueStyle}>
+ {event.loc_block_id.email_id.email}
+ </td>
+ </tr>
+ {/if}
+
+ {if {event.loc_block_id.email_2_id.email|boolean}}
+ <tr>
+ <td {$labelStyle}>
+ {ts}Email{/ts}
+ </td>
+ <td {$valueStyle}>
+ {event.loc_block_id.email_2_id.email}
+ </td>
+ </tr>
+ {/if}
+ {/if}
+
+ {/if}
+ </table>
</td>
</tr>
- {foreach from=$location.phone item=phone}
- {if $phone.phone}
- <tr>
- <td {$labelStyle}>
- {if $phone.phone_type}
- {$phone.phone_type_display}
- {else}
- {ts}Phone{/ts}
- {/if}
- </td>
- <td {$valueStyle}>
- {$phone.phone} {if $phone.phone_ext} {ts}ext.{/ts} {$phone.phone_ext}{/if}
- </td>
- </tr>
- {/if}
- {/foreach}
- {foreach from=$location.email item=eventEmail}
- {if $eventEmail.email}
- <tr>
- <td {$labelStyle}>
- {ts}Email{/ts}
- </td>
- <td {$valueStyle}>
- {$eventEmail.email}
- </td>
- </tr>
- {/if}
- {/foreach}
- {/if} {*phone block close*}
- {/if}
</table>
- </td>
- </tr>
-
- </table>
-
</body>
</html>
-{if $isRefund}{ts}Refund Notification{/ts}{else}{ts}Payment Receipt{/ts}{/if}{if $component eq 'event'} - {$event.title}{/if} - {contact.display_name}
+{if {financial_trxn.total_amount|raw} < 0}{ts}Refund Notification{/ts}{else}{ts}Payment Receipt{/ts}{/if}{if {event.title|boolean}} - {event.title}{/if} - {contact.display_name}