. */ declare(strict_types=1); namespace FireflyIII\Factory; use FireflyIII\Models\Account; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Services\Internal\Support\JournalServiceTrait; use FireflyIII\User; use FireflyIII\Validation\AccountValidator; use Illuminate\Database\QueryException; use Log; /** * Class TransactionFactory */ class TransactionFactory { use JournalServiceTrait; /** @var AccountValidator */ private $accountValidator; /** @var TransactionJournal */ private $journal; /** @var Account */ private $account; /** @var TransactionCurrency */ private $currency; /** @var TransactionCurrency */ private $foreignCurrency; /** @var User */ private $user; /** @var bool */ private $reconciled; /** * Constructor. */ public function __construct() { if ('testing' === config('app.env')) { Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this))); } $this->accountRepository = app(AccountRepositoryInterface::class); $this->accountValidator = app(AccountValidator::class); $this->reconciled = false; $this->foreignCurrency = null; } /** * @param bool $reconciled */ public function setReconciled(bool $reconciled): void { $this->reconciled = $reconciled; } /** * @param Account $account */ public function setAccount(Account $account): void { $this->account = $account; } /** * @param TransactionCurrency $currency */ public function setCurrency(TransactionCurrency $currency): void { $this->currency = $currency; } /** * @param TransactionCurrency $foreignCurrency |null */ public function setForeignCurrency(?TransactionCurrency $foreignCurrency): void { $this->foreignCurrency = $foreignCurrency; } /** * Create transaction with negative amount (for source accounts). * * @param string $amount * @param string|null $foreignAmount * @return Transaction|null */ public function createNegative(string $amount, ?string $foreignAmount): ?Transaction { if (null !== $foreignAmount) { $foreignAmount = app('steam')->negative($foreignAmount); } return $this->create(app('steam')->negative($amount), $foreignAmount); } /** * Create transaction with positive amount (for destination accounts). * * @param string $amount * @param string|null $foreignAmount * @return Transaction|null */ public function createPositive(string $amount, ?string $foreignAmount): ?Transaction { if (null !== $foreignAmount) { $foreignAmount = app('steam')->positive($foreignAmount); } return $this->create(app('steam')->positive($amount), $foreignAmount); } /** * @param TransactionJournal $journal */ public function setJournal(TransactionJournal $journal): void { $this->journal = $journal; } /** * @param User $user */ public function setUser(User $user): void { $this->user = $user; $this->accountRepository->setUser($user); } /** * @param string $amount * @param string|null $foreignAmount * @return Transaction|null */ private function create(string $amount, ?string $foreignAmount): ?Transaction { $result = null; $data = [ 'reconciled' => $this->reconciled, 'account_id' => $this->account->id, 'transaction_journal_id' => $this->journal->id, 'description' => null, 'transaction_currency_id' => $this->currency->id, 'amount' => $amount, 'foreign_amount' => null, 'foreign_currency_id' => null, 'identifier' => 0, ]; try { $result = Transaction::create($data); } catch (QueryException $e) { Log::error(sprintf('Could not create transaction: %s', $e->getMessage()), $data); } if (null !== $result) { Log::debug( sprintf( 'Created transaction #%d (%s %s), part of journal #%d', $result->id, $this->currency->code, $amount, $this->journal->id ) ); // do foreign currency thing. // add foreign currency info to $one and $two if necessary. if (null !== $this->foreignCurrency && null !== $foreignAmount && $this->foreignCurrency->id !== $this->currency->id ) { $result->foreign_currency_id = $this->foreignCurrency->id; $result->foreign_amount = app('steam')->negative($foreignAmount); } $result->save(); } return $result; } }