Skip to content

Commit

Permalink
Merge pull request #21036 from eileenmcnaughton/act_mon
Browse files Browse the repository at this point in the history
Reconcile contribution amount tokens
  • Loading branch information
eileenmcnaughton authored Aug 6, 2021
2 parents a70b9fa + 17b6f17 commit e586838
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 51 deletions.
63 changes: 13 additions & 50 deletions CRM/Contribute/Tokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
*/

use Civi\ActionSchedule\Event\MailingQueryEvent;
use Civi\Token\AbstractTokenSubscriber;
use Civi\Token\TokenProcessor;
use Civi\Token\TokenRow;

Expand All @@ -23,7 +22,7 @@
* At time of writing, we don't have any particularly special tokens -- we just
* do some basic formatting based on the corresponding DB field.
*/
class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
class CRM_Contribute_Tokens extends CRM_Core_EntityTokens {

/**
* @return string
Expand Down Expand Up @@ -59,6 +58,7 @@ protected function getPassthruTokens(): array {
'total_amount',
'fee_amount',
'net_amount',
'non_deductible_amount',
'trxn_id',
'invoice_id',
'currency',
Expand Down Expand Up @@ -155,49 +155,31 @@ public function alterActionScheduleQuery(MailingQueryEvent $e): void {

/**
* @inheritDoc
* @throws \CRM_Core_Exception
*/
public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL) {
$actionSearchResult = $row->context['actionSearchResult'];
$fieldValue = $actionSearchResult->{"contrib_$field"} ?? NULL;

if (in_array($field, ['total_amount', 'fee_amount', 'net_amount'])) {
if (array_key_exists($field, $this->getPseudoTokens())) {
$split = explode(':', $field);
return $row->tokens($entity, $field, $this->getPseudoValue($split[0], $split[1], $actionSearchResult->{"contrib_$split[0]"} ?? NULL));
}
if ($this->isMoneyField($field)) {
return $row->format('text/plain')->tokens($entity, $field,
\CRM_Utils_Money::format($fieldValue, $actionSearchResult->contrib_currency));
}
elseif ($cfID = \CRM_Core_BAO_CustomField::getKeyID($field)) {
$row->customToken($entity, $cfID, $actionSearchResult->entity_id);
}
elseif (array_key_exists($field, $this->getPseudoTokens())) {
$split = explode(':', $field);
$row->tokens($entity, $field, $this->getPseudoValue($split[0], $split[1], $actionSearchResult->{"contrib_$split[0]"} ?? NULL));
}
elseif (in_array($field, array_keys($this->getBasicTokens()))) {
$row->tokens($entity, $field, $fieldValue);
if ($this->isDateField($field)) {
return $row->format('text/plain')->tokens($entity, $field, \CRM_Utils_Date::customFormat($fieldValue));
}
elseif (!array_key_exists($field, CRM_Contribute_BAO_Contribution::fields())) {
if ($this->isDateField($field)) {
$row->format('text/plain')->tokens($entity, $field, \CRM_Utils_Date::customFormat($fieldValue));
}
else {
$row->format('text/plain')->tokens($entity, $field, $fieldValue);
}
if ($cfID = \CRM_Core_BAO_CustomField::getKeyID($field)) {
$row->customToken($entity, $cfID, $actionSearchResult->entity_id);
}
else {
$row->dbToken($entity, $field, 'CRM_Contribute_BAO_Contribution', $field, $fieldValue);
$row->format('text/plain')->tokens($entity, $field, (string) $fieldValue);
}
}

/**
* Is the given field a date field.
*
* @param string $fieldName
*
* @return bool
*/
public function isDateField($fieldName): bool {
return $this->getFieldMetadata()[$fieldName]['type'] === (\CRM_Utils_Type::T_DATE + \CRM_Utils_Type::T_TIME);
}

/**
* Get the value for the relevant pseudo field.
*
Expand All @@ -220,23 +202,4 @@ public function getPseudoValue(string $realField, string $pseudoKey, $fieldValue
return (string) $fieldValue;
}

/**
* Get the metadata for the available fields.
*
* @return array
*/
protected function getFieldMetadata(): array {
if (empty($this->fieldMetadata)) {
$baoName = $this->getBAOName();
$fields = (array) $baoName::fields();
// re-index by real field name. I originally wanted to use apiv4
// getfields - but it returns different stuff for 'type' and
// does not return 'pseudoconstant' as a key so for now...
foreach ($fields as $details) {
$this->fieldMetadata[$details['name']] = $details;
}
}
return $this->fieldMetadata;
}

}
78 changes: 78 additions & 0 deletions CRM/Core/EntityTokens.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?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\Token\AbstractTokenSubscriber;
use Civi\Token\TokenRow;

/**
* Class CRM_Core_EntityTokens
*
* Parent class for generic entity token functionality.
*
* WARNING - this class is highly likely to be temporary and
* to be consolidated with the TokenTrait and / or the
* AbstractTokenSubscriber in future. It is being used to clarify
* functionality but should NOT be used from outside of core tested code.
*/
class CRM_Core_EntityTokens extends AbstractTokenSubscriber {

/**
* This is required for the parent - it will be filled out.
*
* @inheritDoc
*/
public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL) {
}

/**
* Is the given field a date field.
*
* @param string $fieldName
*
* @return bool
*/
public function isDateField(string $fieldName): bool {
return $this->getFieldMetadata()[$fieldName]['type'] === (\CRM_Utils_Type::T_DATE + \CRM_Utils_Type::T_TIME);
}

/**
* Is the given field a date field.
*
* @param string $fieldName
*
* @return bool
*/
public function isMoneyField(string $fieldName): bool {
return $this->getFieldMetadata()[$fieldName]['type'] === (\CRM_Utils_Type::T_MONEY);
}

/**
* Get the metadata for the available fields.
*
* @return array
*/
protected function getFieldMetadata(): array {
if (empty($this->fieldMetadata)) {
$baoName = $this->getBAOName();

$fields = (array) $baoName::fields();
// re-index by real field name. I originally wanted to use apiv4
// getfields - but it returns different stuff for 'type' and
// does not return 'pseudoconstant' as a key so for now...
foreach ($fields as $details) {
$this->fieldMetadata[$details['name']] = $details;
}
}
return $this->fieldMetadata;
}

}
1 change: 1 addition & 0 deletions Civi/Token/TokenRow.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ public function customToken($entity, $customFieldID, $entityID) {
* @throws \CRM_Core_Exception
*/
public function dbToken($tokenEntity, $tokenField, $baoName, $baoField, $fieldValue) {
\CRM_Core_Error::deprecatedFunctionWarning('no alternative');
if ($fieldValue === NULL || $fieldValue === '') {
return $this->tokens($tokenEntity, $tokenField, '');
}
Expand Down
15 changes: 14 additions & 1 deletion tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public function addAliceDues(): void {
'contact_id' => $this->contacts['alice']['id'],
'receive_date' => date('Ymd', strtotime($this->targetDate)),
'total_amount' => '100',
'currency' => 'EUR',
'financial_type_id' => 1,
'non_deductible_amount' => '10',
'fee_amount' => '5',
Expand Down Expand Up @@ -276,7 +277,11 @@ public function testTokenRendering(): void {
financial type label = {contribution.financial_type_id:label}
payment instrument id = {contribution.payment_instrument_id}
payment instrument name = {contribution.payment_instrument_id:name}
payment instrument label = {contribution.payment_instrument_id:label}';
payment instrument label = {contribution.payment_instrument_id:label}
non_deductible_amount = {contribution.non_deductible_amount}
total_amount = {contribution.total_amount}
net_amount = {contribution.net_amount}
fee_amount = {contribution.fee_amount}';

$this->schedule->save();
$this->callAPISuccess('job', 'send_reminder', []);
Expand All @@ -296,6 +301,10 @@ public function testTokenRendering(): void {
'payment instrument id = 4',
'payment instrument name = Check',
'payment instrument label = Check',
'non_deductible_amount = € 10.00',
'total_amount = € 100.00',
'net_amount = € 95.00',
'fee_amount = € 5.00',
];
$this->mut->checkMailLog($expected);

Expand Down Expand Up @@ -324,6 +333,10 @@ public function testTokenRendering(): void {
'payment instrument label = Check',
'legacy source SSF',
'source SSF',
'non_deductible_amount = € 10.00',
'total_amount = € 100.00',
'net_amount = € 95.00',
'fee_amount = € 5.00',
];
foreach ($expected as $string) {
$this->assertStringContainsString($string, $contributionDetails[$this->contacts['alice']['id']]['html']);
Expand Down

0 comments on commit e586838

Please sign in to comment.