diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php index d44a48bd66..c37375e8ab 100644 --- a/app/Factory/TransactionJournalFactory.php +++ b/app/Factory/TransactionJournalFactory.php @@ -207,6 +207,12 @@ class TransactionJournalFactory Log::debug('Now calling getAccount for the destination.'); $destinationAccount = $this->getAccount($type->type, 'destination', $destInfo); Log::debug('Done with getAccount(2x)'); + + // this is the moment for a reconciliation sanity check (again). + if (TransactionType::RECONCILIATION === $type->type) { + [$sourceAccount, $destinationAccount] = $this->reconciliationSanityCheck($sourceAccount, $destinationAccount); + } + $currency = $this->getCurrencyByAccount($type->type, $currency, $sourceAccount, $destinationAccount); $foreignCurrency = $this->compareCurrencies($currency, $foreignCurrency); $foreignCurrency = $this->getForeignByAccount($type->type, $foreignCurrency, $destinationAccount); @@ -597,4 +603,33 @@ class TransactionJournalFactory $this->piggyRepository->setUser($this->user); $this->accountRepository->setUser($this->user); } + + /** + * @param Account|null $sourceAccount + * @param Account|null $destinationAccount + * @return array + */ + private function reconciliationSanityCheck(?Account $sourceAccount, ?Account $destinationAccount): array + { + Log::debug(sprintf('Now in %s', __METHOD__)); + if (null !== $sourceAccount && null !== $destinationAccount) { + Log::debug('Both accounts exist, simply return them.'); + return [$sourceAccount, $destinationAccount]; + } + if (null !== $sourceAccount && null === $destinationAccount) { + Log::debug('Destination account is NULL, source account is not.'); + $account = $this->accountRepository->getReconciliation($sourceAccount); + Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type)); + return [$sourceAccount, $account]; + } + + if (null === $sourceAccount && null !== $destinationAccount) { + Log::debug('Source account is NULL, destination account is not.'); + $account = $this->accountRepository->getReconciliation($destinationAccount); + Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type)); + return [$account, $destinationAccount]; + } + Log::debug('Unused fallback'); + return [$sourceAccount, $destinationAccount]; + } } diff --git a/app/Services/Internal/Support/JournalServiceTrait.php b/app/Services/Internal/Support/JournalServiceTrait.php index 24777d11e1..f52d5be1b8 100644 --- a/app/Services/Internal/Support/JournalServiceTrait.php +++ b/app/Services/Internal/Support/JournalServiceTrait.php @@ -54,11 +54,11 @@ trait JournalServiceTrait * @param string $direction * @param array $data * - * @return Account + * @return Account|null * @codeCoverageIgnore * @throws FireflyException */ - protected function getAccount(string $transactionType, string $direction, array $data): Account + protected function getAccount(string $transactionType, string $direction, array $data): ?Account { // some debug logging: Log::debug(sprintf('Now in getAccount(%s)', $direction), $data); @@ -228,10 +228,11 @@ trait JournalServiceTrait $data['name'] = $data['number']; } // if name is still NULL, return NULL. - if (null === $data['name']) { + if ('' === (string)$data['name']) { + Log::debug('Account name is still NULL, return NULL.'); return null; } - $data['name'] = $data['name'] ?? '(no name)'; + //$data['name'] = $data['name'] ?? '(no name)'; $account = $this->accountRepository->store( [ @@ -273,11 +274,11 @@ trait JournalServiceTrait private function getCashAccount(?Account $account, array $data, array $types): ?Account { // return cash account. - if (null === $account && null === $data['name'] + if (null === $account && '' === (string) $data['name'] && in_array(AccountType::CASH, $types, true)) { $account = $this->accountRepository->getCashAccount(); } - + Log::debug('Cannot return cash account, return input instead.'); return $account; } diff --git a/app/Validation/Account/ReconciliationValidation.php b/app/Validation/Account/ReconciliationValidation.php index 68b59ac53d..3e8d2962be 100644 --- a/app/Validation/Account/ReconciliationValidation.php +++ b/app/Validation/Account/ReconciliationValidation.php @@ -85,6 +85,8 @@ trait ReconciliationValidation // is expected to be "positive", i.e. the money flows from the // source to the asset account that is the destination. if (null === $accountId && null === $accountName) { + Log::debug('The source is valid because ID and name are NULL.'); + $this->source = new Account; return true; } diff --git a/app/Validation/TransactionValidation.php b/app/Validation/TransactionValidation.php index e13afab2d7..407e66dbde 100644 --- a/app/Validation/TransactionValidation.php +++ b/app/Validation/TransactionValidation.php @@ -152,7 +152,7 @@ trait TransactionValidation */ protected function sanityCheckReconciliation(Validator $validator, string $transactionType, int $index, array $source, array $destination): void { - Log::debug('sanityCheckReconciliation'); + Log::debug('Now in sanityCheckReconciliation'); if (TransactionType::RECONCILIATION === ucfirst($transactionType) && null === $source['id'] && null === $source['name'] && null === $destination['id'] && null === $destination['name'] ) { diff --git a/resources/lang/en_US/validation.php b/resources/lang/en_US/validation.php index 191940fedc..006c462b8d 100644 --- a/resources/lang/en_US/validation.php +++ b/resources/lang/en_US/validation.php @@ -194,6 +194,8 @@ return [ 'withdrawal_dest_need_data' => 'Need to get a valid destination account ID and/or valid destination account name to continue.', 'withdrawal_dest_bad_data' => 'Could not find a valid destination account when searching for ID ":id" or name ":name".', + 'reconciliation_source_bad_data' => 'Could not find a valid reconciliation account when searching for ID ":id" or name ":name".', + 'generic_source_bad_data' => 'Could not find a valid source account when searching for ID ":id" or name ":name".', 'deposit_source_need_data' => 'Need to get a valid source account ID and/or valid source account name to continue.',