mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-12-28 01:41:14 -06:00
Add the ability to make transfers to and from liability accounts.
This commit is contained in:
parent
c55b80f467
commit
07cfba1b3a
@ -121,13 +121,9 @@ class TransactionFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log::debug(sprintf('Source type is "%s", destination type is "%s"', $sourceAccount->accountType->type, $destinationAccount->accountType->type));
|
Log::debug(sprintf('Source type is "%s", destination type is "%s"', $sourceAccount->accountType->type, $destinationAccount->accountType->type));
|
||||||
// throw big fat error when source type === dest type and it's not a transfer or reconciliation.
|
|
||||||
if ($sourceAccount->accountType->type === $destinationAccount->accountType->type && $journal->transactionType->type !== TransactionType::TRANSFER) {
|
// based on the source type, destination type and transaction type, the system can start throwing FireflyExceptions.
|
||||||
throw new FireflyException(sprintf('Source and destination account cannot be both of the type "%s"', $destinationAccount->accountType->type));
|
$this->validateTransaction($sourceAccount->accountType->type, $destinationAccount->accountType->type, $journal->transactionType->type);
|
||||||
}
|
|
||||||
if ($sourceAccount->accountType->type !== AccountType::ASSET && $destinationAccount->accountType->type !== AccountType::ASSET) {
|
|
||||||
throw new FireflyException('At least one of the accounts must be an asset account.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$source = $this->create(
|
$source = $this->create(
|
||||||
[
|
[
|
||||||
@ -194,5 +190,29 @@ class TransactionFactory
|
|||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sourceType
|
||||||
|
* @param string $destinationType
|
||||||
|
* @param string $transactionType
|
||||||
|
*
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function validateTransaction(string $sourceType, string $destinationType, string $transactionType): void
|
||||||
|
{
|
||||||
|
// throw big fat error when source type === dest type and it's not a transfer or reconciliation.
|
||||||
|
if ($sourceType === $destinationType && $transactionType !== TransactionType::TRANSFER) {
|
||||||
|
throw new FireflyException(sprintf('Source and destination account cannot be both of the type "%s"', $destinationType));
|
||||||
|
}
|
||||||
|
// source must be in this list AND dest must be in this list:
|
||||||
|
$list = [AccountType::DEFAULT, AccountType::ASSET, AccountType::DEBT, AccountType::MORTGAGE, AccountType::LOAN, AccountType::MORTGAGE];
|
||||||
|
if (
|
||||||
|
!\in_array($sourceType, $list, true) &&
|
||||||
|
!\in_array($destinationType, $list, true)) {
|
||||||
|
throw new FireflyException(sprintf('At least one of the accounts must be an asset account (%s, %s).', $sourceType, $destinationType));
|
||||||
|
}
|
||||||
|
// either of these must be asset or default account.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ class JavascriptController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function accounts(AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository): Response
|
public function accounts(AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository): Response
|
||||||
{
|
{
|
||||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::DEBT,AccountType::LOAN,AccountType::MORTGAGE, AccountType::CREDITCARD]);
|
||||||
$preference = app('preferences')->get('currencyPreference', config('firefly.default_currency', 'EUR'));
|
$preference = app('preferences')->get('currencyPreference', config('firefly.default_currency', 'EUR'));
|
||||||
/** @noinspection NullPointerExceptionInspection */
|
/** @noinspection NullPointerExceptionInspection */
|
||||||
$default = $currencyRepository->findByCodeNull($preference->data);
|
$default = $currencyRepository->findByCodeNull($preference->data);
|
||||||
|
@ -247,7 +247,7 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
$result = $query->get(['accounts.*']);
|
$result = $query->get(['accounts.*']);
|
||||||
$result = $result->sortBy(
|
$result = $result->sortBy(
|
||||||
function (Account $account) {
|
function (Account $account) {
|
||||||
return strtolower($account->name);
|
return sprintf('%02d', $account->account_type_id) . strtolower($account->name);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -66,19 +66,27 @@ class ExpandedForm
|
|||||||
/** @var CurrencyRepositoryInterface $currencyRepos */
|
/** @var CurrencyRepositoryInterface $currencyRepos */
|
||||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||||
|
|
||||||
$assetAccounts = $repository->getActiveAccountsByType([AccountType::ASSET, AccountType::DEFAULT]);
|
$accountList = $repository->getActiveAccountsByType(
|
||||||
|
[AccountType::ASSET, AccountType::DEFAULT, AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN,]
|
||||||
|
);
|
||||||
|
$liabilityTypes = [AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN];
|
||||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||||
$grouped = [];
|
$grouped = [];
|
||||||
// group accounts:
|
// group accounts:
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($assetAccounts as $account) {
|
foreach ($accountList as $account) {
|
||||||
$balance = app('steam')->balance($account, new Carbon);
|
$balance = app('steam')->balance($account, new Carbon);
|
||||||
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
|
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
|
||||||
$currency = $currencyRepos->findNull($currencyId);
|
$currency = $currencyRepos->findNull($currencyId);
|
||||||
$role = $repository->getMetaValue($account, 'accountRole');
|
$role = $repository->getMetaValue($account, 'accountRole');
|
||||||
if ('' === $role) {
|
if ('' === $role && !\in_array($account->accountType->type, $liabilityTypes, true)) {
|
||||||
$role = 'no_account_type'; // @codeCoverageIgnore
|
$role = 'no_account_type'; // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\in_array($account->accountType->type, $liabilityTypes, true)) {
|
||||||
|
$role = 'l_' . $account->accountType->type; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
$currency = $defaultCurrency;
|
$currency = $defaultCurrency;
|
||||||
}
|
}
|
||||||
@ -192,12 +200,13 @@ class ExpandedForm
|
|||||||
/** @var CurrencyRepositoryInterface $currencyRepos */
|
/** @var CurrencyRepositoryInterface $currencyRepos */
|
||||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||||
|
|
||||||
$assetAccounts = $repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]);
|
$accountList = $repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT, AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN,]);
|
||||||
|
$liabilityTypes = [AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN];
|
||||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||||
$grouped = [];
|
$grouped = [];
|
||||||
// group accounts:
|
// group accounts:
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($assetAccounts as $account) {
|
foreach ($accountList as $account) {
|
||||||
$balance = app('steam')->balance($account, new Carbon);
|
$balance = app('steam')->balance($account, new Carbon);
|
||||||
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
|
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
|
||||||
$currency = $currencyRepos->findNull($currencyId);
|
$currency = $currencyRepos->findNull($currencyId);
|
||||||
@ -205,6 +214,11 @@ class ExpandedForm
|
|||||||
if ('' === $role) {
|
if ('' === $role) {
|
||||||
$role = 'no_account_type'; // @codeCoverageIgnore
|
$role = 'no_account_type'; // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\in_array($account->accountType->type, $liabilityTypes, true)) {
|
||||||
|
$role = 'l_' . $account->accountType->type; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
$currency = $defaultCurrency;
|
$currency = $defaultCurrency;
|
||||||
}
|
}
|
||||||
|
@ -593,7 +593,6 @@ return [
|
|||||||
'invalid_convert_selection' => 'The account you have selected is already used in this transaction or does not exist.',
|
'invalid_convert_selection' => 'The account you have selected is already used in this transaction or does not exist.',
|
||||||
'source_or_dest_invalid' => 'Cannot find the correct transaction details. Conversion is not possible.',
|
'source_or_dest_invalid' => 'Cannot find the correct transaction details. Conversion is not possible.',
|
||||||
|
|
||||||
|
|
||||||
// create new stuff:
|
// create new stuff:
|
||||||
'create_new_withdrawal' => 'Create new withdrawal',
|
'create_new_withdrawal' => 'Create new withdrawal',
|
||||||
'create_new_deposit' => 'Create new deposit',
|
'create_new_deposit' => 'Create new deposit',
|
||||||
@ -816,12 +815,17 @@ return [
|
|||||||
'perm-delete-many' => 'Deleting many items in one go can be very disruptive. Please be cautious.',
|
'perm-delete-many' => 'Deleting many items in one go can be very disruptive. Please be cautious.',
|
||||||
'mass_deleted_transactions_success' => 'Deleted :amount transaction(s).',
|
'mass_deleted_transactions_success' => 'Deleted :amount transaction(s).',
|
||||||
'mass_edited_transactions_success' => 'Updated :amount transaction(s)',
|
'mass_edited_transactions_success' => 'Updated :amount transaction(s)',
|
||||||
|
'opt_group_' => '(no account type)',
|
||||||
'opt_group_no_account_type' => '(no account type)',
|
'opt_group_no_account_type' => '(no account type)',
|
||||||
'opt_group_defaultAsset' => 'Default asset accounts',
|
'opt_group_defaultAsset' => 'Default asset accounts',
|
||||||
'opt_group_savingAsset' => 'Savings accounts',
|
'opt_group_savingAsset' => 'Savings accounts',
|
||||||
'opt_group_sharedAsset' => 'Shared asset accounts',
|
'opt_group_sharedAsset' => 'Shared asset accounts',
|
||||||
'opt_group_ccAsset' => 'Credit cards',
|
'opt_group_ccAsset' => 'Credit cards',
|
||||||
'opt_group_cashWalletAsset' => 'Cash wallets',
|
'opt_group_cashWalletAsset' => 'Cash wallets',
|
||||||
|
'opt_group_l_Loan' => 'Liability: Loan',
|
||||||
|
'opt_group_l_Debt' => 'Liability: Debt',
|
||||||
|
'opt_group_l_Mortgage' => 'Liability: Mortgage',
|
||||||
|
'opt_group_l_Credit card' => 'Liability: Credit card',
|
||||||
'notes' => 'Notes',
|
'notes' => 'Notes',
|
||||||
'unknown_journal_error' => 'Could not store the transaction. Please check the log files.',
|
'unknown_journal_error' => 'Could not store the transaction. Please check the log files.',
|
||||||
|
|
||||||
|
@ -50,8 +50,8 @@ return [
|
|||||||
'source_account' => 'Source account',
|
'source_account' => 'Source account',
|
||||||
'destination_account' => 'Destination account',
|
'destination_account' => 'Destination account',
|
||||||
'journal_destination_id' => 'Asset account (destination)',
|
'journal_destination_id' => 'Asset account (destination)',
|
||||||
'asset_destination_account' => 'Asset account (destination)',
|
'asset_destination_account' => 'Destination account',
|
||||||
'asset_source_account' => 'Asset account (source)',
|
'asset_source_account' => 'Source account',
|
||||||
'journal_description' => 'Description',
|
'journal_description' => 'Description',
|
||||||
'note' => 'Notes',
|
'note' => 'Notes',
|
||||||
'split_journal' => 'Split this transaction',
|
'split_journal' => 'Split this transaction',
|
||||||
|
@ -7,8 +7,20 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
||||||
<base href="{{ route('index') }}/">
|
<base href="{{ route('index') }}/">
|
||||||
<link rel="stylesheet" href="css/app.css?v={{ FF_VERSION }}" type="text/css" media="all"/>
|
|
||||||
|
{# CSS things #}
|
||||||
|
|
||||||
|
{# libraries #}
|
||||||
|
<link href="css/google-fonts.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
<link href="lib/bs/css/bootstrap.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
<link href="lib/fa/css/font-awesome.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
<link href="css/daterangepicker.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
|
||||||
|
{# the theme #}
|
||||||
<link href="lib/adminlte/css/AdminLTE.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
<link href="lib/adminlte/css/AdminLTE.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
<link href="lib/adminlte/css/skins/skin-blue-light.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
|
||||||
|
{# Firefly III customisations #}
|
||||||
<link href="css/firefly.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
<link href="css/firefly.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
|
||||||
{# favicons #}
|
{# favicons #}
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
{{ ExpandedForm.text('description') }}
|
{{ ExpandedForm.text('description') }}
|
||||||
|
|
||||||
{# SELECTABLE SOURCE ACCOUNT ONLY FOR WITHDRAWALS AND TRANSFERS #}
|
{# SELECTABLE SOURCE ACCOUNT ONLY FOR WITHDRAWALS AND TRANSFERS #}
|
||||||
{{ ExpandedForm.activeAssetAccountList('source_id', null, {label: trans('form.asset_source_account')}) }}
|
{{ ExpandedForm.activeAssetAccountList('source_id', null, {label: trans('form.asset_source_account') }) }}
|
||||||
|
|
||||||
{# FREE FORMAT SOURCE ACCOUNT ONLY FOR DEPOSITS #}
|
{# FREE FORMAT SOURCE ACCOUNT ONLY FOR DEPOSITS #}
|
||||||
{{ ExpandedForm.text('source_name', null, {label: trans('form.revenue_account')}) }}
|
{{ ExpandedForm.text('source_name', null, {label: trans('form.revenue_account')}) }}
|
||||||
|
Loading…
Reference in New Issue
Block a user