mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Fixes #398
This commit is contained in:
@@ -19,6 +19,7 @@ use FireflyIII\Models\TransactionJournal;
|
|||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TagRepository
|
* Class TagRepository
|
||||||
@@ -54,11 +55,14 @@ class TagRepository implements TagRepositoryInterface
|
|||||||
* Already connected:
|
* Already connected:
|
||||||
*/
|
*/
|
||||||
if ($journal->tags()->find($tag->id)) {
|
if ($journal->tags()->find($tag->id)) {
|
||||||
|
Log::error(sprintf('Cannot find tag #%d', $tag->id));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($tag->tagMode) {
|
switch ($tag->tagMode) {
|
||||||
case 'nothing':
|
case 'nothing':
|
||||||
|
Log::debug(sprintf('Tag #%d connected', $tag->id));
|
||||||
$journal->tags()->save($tag);
|
$journal->tags()->save($tag);
|
||||||
$journal->save();
|
$journal->save();
|
||||||
|
|
||||||
@@ -184,22 +188,23 @@ class TagRepository implements TagRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
protected function connectAdvancePayment(TransactionJournal $journal, Tag $tag): bool
|
protected function connectAdvancePayment(TransactionJournal $journal, Tag $tag): bool
|
||||||
{
|
{
|
||||||
/** @var TransactionType $transfer */
|
$type = $journal->transactionType->type;
|
||||||
$transfer = TransactionType::whereType(TransactionType::TRANSFER)->first();
|
$withdrawals = $tag->transactionJournals()
|
||||||
/** @var TransactionType $withdrawal */
|
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
|
||||||
$withdrawal = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
|
->where('transaction_types.type', TransactionType::WITHDRAWAL)->count();
|
||||||
/** @var TransactionType $deposit */
|
$deposits = $tag->transactionJournals()
|
||||||
$deposit = TransactionType::whereType(TransactionType::DEPOSIT)->first();
|
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
|
||||||
|
->where('transaction_types.type', TransactionType::DEPOSIT)->count();
|
||||||
|
|
||||||
$withdrawals = $tag->transactionJournals()->where('transaction_type_id', $withdrawal->id)->count();
|
if ($type === TransactionType::TRANSFER) { // advance payments cannot accept transfers:
|
||||||
$deposits = $tag->transactionJournals()->where('transaction_type_id', $deposit->id)->count();
|
Log::error(sprintf('Journal #%d is a transfer and cannot connect to tag #%d', $journal->id, $tag->id));
|
||||||
|
|
||||||
if ($journal->transaction_type_id == $transfer->id) { // advance payments cannot accept transfers:
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the first transaction to be attached to this tag is attached just like that:
|
// the first transaction to be attached to this tag is attached just like that:
|
||||||
if ($withdrawals < 1 && $deposits < 1) {
|
if ($withdrawals < 1 && $deposits < 1) {
|
||||||
|
Log::debug(sprintf('Tag #%d has 0 withdrawals and 0 deposits so its fine.', $tag->id));
|
||||||
$journal->tags()->save($tag);
|
$journal->tags()->save($tag);
|
||||||
$journal->save();
|
$journal->save();
|
||||||
|
|
||||||
@@ -207,12 +212,16 @@ class TagRepository implements TagRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if withdrawal and already has a withdrawal, return false:
|
// if withdrawal and already has a withdrawal, return false:
|
||||||
if ($journal->transaction_type_id == $withdrawal->id && $withdrawals == 1) {
|
if ($type === TransactionType::WITHDRAWAL && $withdrawals > 0) {
|
||||||
|
Log::error(sprintf('Journal #%d is a withdrawal but tag already has %d withdrawal(s).', $journal->id, $withdrawals));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if already has transaction journals, must match ALL asset account id's:
|
// if already has transaction journals, must match ALL asset account id's:
|
||||||
if ($deposits > 0 || $withdrawals == 1) {
|
if ($deposits > 0 || $withdrawals == 1) {
|
||||||
|
Log::debug('Need to match all asset accounts.');
|
||||||
|
|
||||||
return $this->matchAll($journal, $tag);
|
return $this->matchAll($journal, $tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,28 +238,39 @@ class TagRepository implements TagRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
protected function connectBalancingAct(TransactionJournal $journal, Tag $tag): bool
|
protected function connectBalancingAct(TransactionJournal $journal, Tag $tag): bool
|
||||||
{
|
{
|
||||||
/** @var TransactionType $withdrawal */
|
$type = $journal->transactionType->type;
|
||||||
$withdrawal = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
|
$withdrawals = $tag->transactionJournals()
|
||||||
$withdrawals = $tag->transactionJournals()->where('transaction_type_id', $withdrawal->id)->count();
|
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
|
||||||
/** @var TransactionType $transfer */
|
->where('transaction_types.type', TransactionType::WITHDRAWAL)->count();
|
||||||
$transfer = TransactionType::whereType(TransactionType::TRANSFER)->first();
|
$transfers = $tag->transactionJournals()
|
||||||
$transfers = $tag->transactionJournals()->where('transaction_type_id', $transfer->id)->count();
|
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
|
||||||
|
->where('transaction_types.type', TransactionType::TRANSFER)->count();
|
||||||
|
|
||||||
|
|
||||||
|
Log::debug(sprintf('Journal #%d is a %s', $journal->id, $type));
|
||||||
|
|
||||||
// only if this is the only withdrawal.
|
// only if this is the only withdrawal.
|
||||||
if ($journal->transaction_type_id == $withdrawal->id && $withdrawals < 1) {
|
if ($type === TransactionType::WITHDRAWAL && $withdrawals < 1) {
|
||||||
|
Log::debug('Will connect this journal because it is the only withdrawal in this tag.');
|
||||||
$journal->tags()->save($tag);
|
$journal->tags()->save($tag);
|
||||||
$journal->save();
|
$journal->save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// and only if this is the only transfer
|
// and only if this is the only transfer
|
||||||
if ($journal->transaction_type_id == $transfer->id && $transfers < 1) {
|
if ($type === TransactionType::TRANSFER && $transfers < 1) {
|
||||||
|
Log::debug('Will connect this journal because it is the only transfer in this tag.');
|
||||||
$journal->tags()->save($tag);
|
$journal->tags()->save($tag);
|
||||||
$journal->save();
|
$journal->save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Log::error(
|
||||||
|
sprintf(
|
||||||
|
'Tag #%d has %d withdrawals and %d transfers and cannot contain %s #%d',
|
||||||
|
$tag->id, $withdrawals, $transfers, $type, $journal->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// ignore expense
|
// ignore expense
|
||||||
return false;
|
return false;
|
||||||
@@ -267,28 +287,42 @@ class TagRepository implements TagRepositoryInterface
|
|||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function matchAll(TransactionJournal $journal, Tag $tag): bool
|
private function matchAll(TransactionJournal $journal, Tag $tag): bool
|
||||||
{
|
{
|
||||||
$checkSources = join(',', TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray());
|
$journalSources = join(',', TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray());
|
||||||
$checkDestinations = join(',', TransactionJournal::destinationAccountList($journal)->pluck('id')->toArray());
|
$journalDestinations = join(',', TransactionJournal::destinationAccountList($journal)->pluck('id')->toArray());
|
||||||
|
$match = true;
|
||||||
|
$journals = $tag->transactionJournals()->get(['transaction_journals.*']);
|
||||||
|
|
||||||
$match = true;
|
Log::debug(sprintf('Tag #%d has %d journals to verify:', $tag->id, $journals->count()));
|
||||||
/** @var TransactionJournal $check */
|
|
||||||
foreach ($tag->transactionjournals as $check) {
|
/** @var TransactionJournal $original */
|
||||||
|
foreach ($journals as $original) {
|
||||||
// $checkAccount is the source_account for a withdrawal
|
// $checkAccount is the source_account for a withdrawal
|
||||||
// $checkAccount is the destination_account for a deposit
|
// $checkAccount is the destination_account for a deposit
|
||||||
$thisSources = join(',', TransactionJournal::sourceAccountList($check)->pluck('id')->toArray());
|
$originalSources = join(',', TransactionJournal::sourceAccountList($original)->pluck('id')->toArray());
|
||||||
$thisDestinations = join(',', TransactionJournal::destinationAccountList($check)->pluck('id')->toArray());
|
$originalDestinations = join(',', TransactionJournal::destinationAccountList($original)->pluck('id')->toArray());
|
||||||
|
|
||||||
|
if ($original->isWithdrawal() && $originalSources !== $journalDestinations) {
|
||||||
|
Log::debug(sprintf('Original journal #%d is a withdrawal.', $original->id));
|
||||||
|
Log::debug(sprintf('Journal #%d must have these destination accounts: %s', $journal->id, $originalSources));
|
||||||
|
Log::debug(sprintf('Journal #%d actually these destination accounts: %s', $journal->id, $journalDestinations));
|
||||||
|
Log::debug('So match is FALSE');
|
||||||
|
|
||||||
if ($check->isWithdrawal() && $thisSources !== $checkSources) {
|
|
||||||
$match = false;
|
$match = false;
|
||||||
}
|
}
|
||||||
if ($check->isDeposit() && $thisDestinations !== $checkDestinations) {
|
if ($original->isDeposit() && $originalDestinations !== $journalSources) {
|
||||||
|
Log::debug(sprintf('Original journal #%d is a deposit.', $original->id));
|
||||||
|
Log::debug(sprintf('Journal #%d must have these destination accounts: %s', $journal->id, $originalSources));
|
||||||
|
Log::debug(sprintf('Journal #%d actually these destination accounts: %s', $journal->id, $journalDestinations));
|
||||||
|
Log::debug('So match is FALSE');
|
||||||
|
|
||||||
$match = false;
|
$match = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if ($match) {
|
if ($match) {
|
||||||
|
Log::debug(sprintf('Match is true, connect journal #%d with tag #%d.', $journal->id, $tag->id));
|
||||||
$journal->tags()->save($tag);
|
$journal->tags()->save($tag);
|
||||||
$journal->save();
|
$journal->save();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user