Skip to content

Commit

Permalink
Merge pull request #25036 from colemanw/renameFinancialTypeAccount
Browse files Browse the repository at this point in the history
EntityFinancialAccount - A tale of two BAO classes
  • Loading branch information
eileenmcnaughton authored Nov 23, 2022
2 parents d614a7d + bb33fc6 commit 19a207f
Show file tree
Hide file tree
Showing 20 changed files with 291 additions and 303 deletions.
6 changes: 3 additions & 3 deletions CRM/Contribute/BAO/Contribution.php
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ public static function getToFinancialAccount($contribution, $params) {
return CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($params['payment_processor_id'], NULL, 'civicrm_payment_processor');
}
if (!empty($params['payment_instrument_id'])) {
return CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($contribution['payment_instrument_id']);
return CRM_Financial_BAO_EntityFinancialAccount::getInstrumentFinancialAccount($contribution['payment_instrument_id']);
}
else {
$relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('financial_account_type', NULL, " AND v.name LIKE 'Asset' "));
Expand Down Expand Up @@ -3104,11 +3104,11 @@ public static function recordFinancialAccounts(&$params, CRM_Contribute_DAO_Cont
]);
}
elseif (!empty($params['payment_instrument_id'])) {
$params['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($params['payment_instrument_id']);
$params['to_financial_account_id'] = CRM_Financial_BAO_EntityFinancialAccount::getInstrumentFinancialAccount($params['payment_instrument_id']);
}
// dev/financial#160 - If this is a contribution update, also check for an existing payment_instrument_id.
elseif ($isUpdate && $params['prevContribution']->payment_instrument_id) {
$params['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount((int) $params['prevContribution']->payment_instrument_id);
$params['to_financial_account_id'] = CRM_Financial_BAO_EntityFinancialAccount::getInstrumentFinancialAccount((int) $params['prevContribution']->payment_instrument_id);
}
else {
$relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('financial_account_type', NULL, " AND v.name LIKE 'Asset' "));
Expand Down
2 changes: 1 addition & 1 deletion CRM/Core/BAO/OptionValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public static function add(&$params, $ids = []) {
'account_relationship' => $relationTypeId,
'financial_account_id' => $params['financial_account_id'],
];
CRM_Financial_BAO_FinancialTypeAccount::add($params);
CRM_Financial_BAO_EntityFinancialAccount::add($params);
}
}
return $optionValue;
Expand Down
2 changes: 1 addition & 1 deletion CRM/Core/CodeGen/GenerateData.php
Original file line number Diff line number Diff line change
Expand Up @@ -2181,7 +2181,7 @@ private function addAccountingEntries() {
$select = 'SELECT contribution.id contribution_id, cli.id as line_item_id, contribution.contact_id, contribution.receive_date, contribution.total_amount, contribution.currency, cli.label,
cli.financial_type_id, cefa.financial_account_id, contribution.payment_instrument_id, contribution.check_number, contribution.trxn_id';
$where = 'WHERE cefa.account_relationship = 1';
$financialAccountId = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount(4);
$financialAccountId = CRM_Financial_BAO_EntityFinancialAccount::getInstrumentFinancialAccount(4);
foreach ($components as $component) {
if ($component == 'contribution') {
$from = 'FROM `civicrm_contribution` contribution';
Expand Down
251 changes: 251 additions & 0 deletions CRM/Financial/BAO/EntityFinancialAccount.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,257 @@
*/
class CRM_Financial_BAO_EntityFinancialAccount extends CRM_Financial_DAO_EntityFinancialAccount {

/**
* Fetch object based on array of properties.
*
* @param array $params
* (reference ) an assoc array of name/value pairs.
* @param array $defaults
* (reference ) an assoc array to hold the flattened values.
*
* @param array $allValues
* @deprecated
* @return array
*/
public static function retrieve(&$params, &$defaults = [], &$allValues = []) {
$financialTypeAccount = new CRM_Financial_DAO_EntityFinancialAccount();
$financialTypeAccount->copyValues($params);
$financialTypeAccount->find();
while ($financialTypeAccount->fetch()) {
CRM_Core_DAO::storeValues($financialTypeAccount, $defaults);
$allValues[] = $defaults;
}
return $defaults;
}

/**
* Add the financial types.
*
* @param array $params
* Reference array contains the values submitted by the form.
* @param array $ids
* Reference array contains one possible value
* - entityFinancialAccount.
*
* @return CRM_Financial_DAO_EntityFinancialAccount
* @deprecated
* @throws \CRM_Core_Exception
*/
public static function add(&$params, $ids = NULL) {
// action is taken depending upon the mode
$financialTypeAccount = new CRM_Financial_DAO_EntityFinancialAccount();
if ($params['entity_table'] !== 'civicrm_financial_type') {
$financialTypeAccount->entity_id = $params['entity_id'];
$financialTypeAccount->entity_table = $params['entity_table'];
$financialTypeAccount->find(TRUE);
}
if (!empty($ids['entityFinancialAccount'])) {
$financialTypeAccount->id = $ids['entityFinancialAccount'];
$financialTypeAccount->find(TRUE);
}
$financialTypeAccount->copyValues($params);
self::validateRelationship($financialTypeAccount);
$financialTypeAccount->save();
unset(Civi::$statics['CRM_Core_PseudoConstant']['taxRates']);
return $financialTypeAccount;
}

/**
* Delete financial Types.
*
* @param int $financialTypeAccountId
* @param int $accountId
* @deprecated
* @throws \CRM_Core_Exception
*/
public static function del($financialTypeAccountId, $accountId = NULL) {
// check if financial type is present
$check = FALSE;
$relationValues = CRM_Core_PseudoConstant::get('CRM_Financial_DAO_EntityFinancialAccount', 'account_relationship');

$financialTypeId = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_EntityFinancialAccount', $financialTypeAccountId, 'entity_id');
// check dependencies
// FIXME hardcoded list = bad
$dependency = [
['Contribute', 'Contribution'],
['Contribute', 'ContributionPage'],
['Member', 'MembershipType'],
['Price', 'PriceFieldValue'],
['Grant', 'Grant'],
['Contribute', 'PremiumsProduct'],
['Contribute', 'Product'],
['Price', 'LineItem'],
];

foreach ($dependency as $name) {
$daoString = 'CRM_' . $name[0] . '_DAO_' . $name[1];
if (class_exists($daoString)) {
/** @var \CRM_Core_DAO $dao */
$dao = new $daoString();
$dao->financial_type_id = $financialTypeId;
if ($dao->find(TRUE)) {
$check = TRUE;
break;
}
}
}

if ($check) {
if ($name[1] === 'PremiumsProduct' || $name[1] === 'Product') {
CRM_Core_Session::setStatus(ts('You cannot remove an account with a %1 relationship while the Financial Type is used for a Premium.', [1 => $relationValues[$financialTypeAccountId]]));
}
else {
$accountRelationShipId = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_EntityFinancialAccount', $financialTypeAccountId, 'account_relationship');
CRM_Core_Session::setStatus(ts('You cannot remove an account with a %1 relationship because it is being referenced by one or more of the following types of records: Contributions, Contribution Pages, or Membership Types. Consider disabling this type instead if you no longer want it used.', [1 => $relationValues[$accountRelationShipId]]), NULL, 'error');
}
CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/financial/financialType/accounts', "reset=1&action=browse&aid={$accountId}"));
}

// delete from financial Type table
$financialType = new CRM_Financial_DAO_EntityFinancialAccount();
$financialType->id = $financialTypeAccountId;
$financialType->find(TRUE);
$financialType->delete();
CRM_Core_Session::setStatus(ts('Unbalanced transactions may be created if you delete the account of type: %1.', [1 => $relationValues[$financialType->account_relationship]]));
}

/**
* Financial Account for payment instrument.
*
* @param int $paymentInstrumentValue
* Payment instrument value.
*
* @return null|int
* @throws \CRM_Core_Exception
*/
public static function getInstrumentFinancialAccount($paymentInstrumentValue) {
if (!isset(\Civi::$statics[__CLASS__]['instrument_financial_accounts'][$paymentInstrumentValue])) {
$paymentInstrumentID = civicrm_api3('OptionValue', 'getvalue', [
'return' => 'id',
'value' => $paymentInstrumentValue,
'option_group_id' => "payment_instrument",
]);
$accounts = civicrm_api3('EntityFinancialAccount', 'get', [
'return' => 'financial_account_id',
'entity_table' => 'civicrm_option_value',
'entity_id' => $paymentInstrumentID,
'options' => ['limit' => 1],
'sequential' => 1,
])['values'];
if (empty($accounts)) {
\Civi::$statics[__CLASS__]['instrument_financial_accounts'][$paymentInstrumentValue] = NULL;
}
else {
\Civi::$statics[__CLASS__]['instrument_financial_accounts'][$paymentInstrumentValue] = $accounts[0]['financial_account_id'];
}
}
return \Civi::$statics[__CLASS__]['instrument_financial_accounts'][$paymentInstrumentValue];
}

/**
* Create default entity financial accounts
* for financial type
* @see https://issues.civicrm.org/jira/browse/CRM-12470
*
* @param $financialType
*
* @return array
*/
public static function createDefaultFinancialAccounts($financialType) {
$titles = [];
$financialAccountTypeID = CRM_Core_OptionGroup::values('financial_account_type', FALSE, FALSE, FALSE, NULL, 'name');
$accountRelationship = CRM_Core_OptionGroup::values('account_relationship', FALSE, FALSE, FALSE, NULL, 'name');

$relationships = [
array_search('Accounts Receivable Account is', $accountRelationship) => array_search('Asset', $financialAccountTypeID),
array_search('Expense Account is', $accountRelationship) => array_search('Expenses', $financialAccountTypeID),
array_search('Cost of Sales Account is', $accountRelationship) => array_search('Cost of Sales', $financialAccountTypeID),
array_search('Income Account is', $accountRelationship) => array_search('Revenue', $financialAccountTypeID),
];

$dao = CRM_Core_DAO::executeQuery('SELECT id, financial_account_type_id FROM civicrm_financial_account WHERE name LIKE %1',
[1 => [$financialType->name, 'String']]
);
$dao->fetch();
$existingFinancialAccount = [];
if (!$dao->N) {
$params = [
'name' => $financialType->name,
'contact_id' => CRM_Core_BAO_Domain::getDomain()->contact_id,
'financial_account_type_id' => array_search('Revenue', $financialAccountTypeID),
'description' => $financialType->description,
'account_type_code' => 'INC',
'is_active' => 1,
];
$financialAccount = CRM_Financial_BAO_FinancialAccount::add($params);
}
else {
$existingFinancialAccount[$dao->financial_account_type_id] = $dao->id;
}
$params = [
'entity_table' => 'civicrm_financial_type',
'entity_id' => $financialType->id,
];
foreach ($relationships as $key => $value) {
if (!array_key_exists($value, $existingFinancialAccount)) {
if ($accountRelationship[$key] == 'Accounts Receivable Account is') {
$params['financial_account_id'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialAccount', 'Accounts Receivable', 'id', 'name');
if (!empty($params['financial_account_id'])) {
$titles[] = 'Accounts Receivable';
}
else {
$query = "SELECT financial_account_id, name FROM civicrm_entity_financial_account
LEFT JOIN civicrm_financial_account ON civicrm_financial_account.id = civicrm_entity_financial_account.financial_account_id
WHERE account_relationship = {$key} AND entity_table = 'civicrm_financial_type' LIMIT 1";
$dao = CRM_Core_DAO::executeQuery($query);
$dao->fetch();
$params['financial_account_id'] = $dao->financial_account_id;
$titles[] = $dao->name;
}
}
elseif ($accountRelationship[$key] == 'Income Account is' && empty($existingFinancialAccount)) {
$params['financial_account_id'] = $financialAccount->id;
}
else {
$query = "SELECT id, name FROM civicrm_financial_account WHERE is_default = 1 AND financial_account_type_id = {$value}";
$dao = CRM_Core_DAO::executeQuery($query);
$dao->fetch();
$params['financial_account_id'] = $dao->id;
$titles[] = $dao->name;
}
}
else {
$params['financial_account_id'] = $existingFinancialAccount[$value];
$titles[] = $financialType->name;
}
$params['account_relationship'] = $key;
self::add($params);
}
if (!empty($existingFinancialAccount)) {
$titles = [];
}
return $titles;
}

/**
* Validate account relationship with financial account type
*
* @param CRM_Financial_DAO_EntityFinancialAccount $financialTypeAccount of CRM_Financial_DAO_EntityFinancialAccount
*
* @throws CRM_Core_Exception
*/
public static function validateRelationship($financialTypeAccount) {
$financialAccountLinks = CRM_Financial_BAO_FinancialAccount::getfinancialAccountRelations();
$financialAccountType = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialAccount', $financialTypeAccount->financial_account_id, 'financial_account_type_id');
if (CRM_Utils_Array::value($financialTypeAccount->account_relationship, $financialAccountLinks) != $financialAccountType) {
$accountRelationships = CRM_Core_PseudoConstant::get('CRM_Financial_DAO_EntityFinancialAccount', 'account_relationship');
$params = [
1 => $accountRelationships[$financialTypeAccount->account_relationship],
];
throw new CRM_Core_Exception(ts("This financial account cannot have '%1' relationship.", $params));
}
}

/**
* Whitelist of possible values for the entity_table field
*
Expand Down
2 changes: 1 addition & 1 deletion CRM/Financial/BAO/FinancialType.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public static function self_hook_civicrm_pre(\Civi\Core\Event\PreEvent $event) {
*/
public static function self_hook_civicrm_post(\Civi\Core\Event\PostEvent $event) {
if ($event->action === 'create') {
$titles = CRM_Financial_BAO_FinancialTypeAccount::createDefaultFinancialAccounts($event->object);
$titles = CRM_Financial_BAO_EntityFinancialAccount::createDefaultFinancialAccounts($event->object);
$event->object->titles = $titles;
}
if ($event->action === 'delete') {
Expand Down
Loading

0 comments on commit 19a207f

Please sign in to comment.