mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-14 08:11:20 +00:00
Restucturing some code.
This commit is contained in:
@@ -26,6 +26,7 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface JournalRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the amount in the account before the specified transaction took place.
|
||||
*
|
||||
|
231
app/Repositories/Journal/JournalTasker.php
Normal file
231
app/Repositories/Journal/JournalTasker.php
Normal file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
/**
|
||||
* JournalTasker.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Repositories\Journal;
|
||||
|
||||
use Crypt;
|
||||
use DB;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
|
||||
/**
|
||||
* Class JournalTasker
|
||||
*
|
||||
* @package FireflyIII\Repositories\Journal
|
||||
*/
|
||||
class JournalTasker implements JournalTaskerInterface
|
||||
{
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* JournalRepository constructor.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an overview of the transactions of a journal, tailored to the view
|
||||
* that shows a transaction (transaction/show/xx).
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTransactionsOverview(TransactionJournal $journal): array
|
||||
{
|
||||
// get all transaction data + the opposite site in one list.
|
||||
/**
|
||||
* select
|
||||
*
|
||||
* source.id,
|
||||
* source.account_id,
|
||||
* source_accounts.name as account_name,
|
||||
* source_accounts.encrypted as account_encrypted,
|
||||
* source.amount,
|
||||
* source.description,
|
||||
*
|
||||
* destination.id as destination_id,
|
||||
* destination.account_id as destination_account_id,
|
||||
* destination_accounts.name as destination_account_name,
|
||||
* destination_accounts.encrypted as destination_account_encrypted
|
||||
*
|
||||
*
|
||||
* from transactions as source
|
||||
*
|
||||
* left join transactions as destination ON source.transaction_journal_id = destination.transaction_journal_id AND source.amount = destination.amount * -1 AND source.identifier = destination.identifier
|
||||
* -- left join source account name:
|
||||
* left join accounts as source_accounts ON source.account_id = source_accounts.id
|
||||
* left join accounts as destination_accounts ON destination.account_id = destination_accounts.id
|
||||
*
|
||||
* where source.transaction_journal_id = 6600
|
||||
* and source.amount < 0
|
||||
* and source.deleted_at is null
|
||||
*/
|
||||
$set = $journal
|
||||
->transactions()// "source"
|
||||
->leftJoin(
|
||||
'transactions as destination', function (JoinClause $join) {
|
||||
$join
|
||||
->on('transactions.transaction_journal_id', '=', 'destination.transaction_journal_id')
|
||||
->where('transactions.amount', '=', DB::raw('destination.amount * -1'))
|
||||
->where('transactions.identifier', '=', DB::raw('destination.identifier'));
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as source_accounts', 'transactions.account_id', '=', 'source_accounts.id')
|
||||
->leftJoin('accounts as destination_accounts', 'destination.account_id', '=', 'destination_accounts.id')
|
||||
->where('transactions.amount', '<', 0)
|
||||
->get(
|
||||
[
|
||||
'transactions.id',
|
||||
'transactions.account_id',
|
||||
'source_accounts.name as account_name',
|
||||
'source_accounts.encrypted as account_encrypted',
|
||||
'transactions.amount',
|
||||
'transactions.description',
|
||||
'destination.id as destination_id',
|
||||
'destination.account_id as destination_account_id',
|
||||
'destination_accounts.name as destination_account_name',
|
||||
'destination_accounts.encrypted as destination_account_encrypted',
|
||||
]
|
||||
);
|
||||
|
||||
$transactions = [];
|
||||
|
||||
/** @var Transaction $entry */
|
||||
foreach ($set as $entry) {
|
||||
$sourceBalance = $this->getBalance($entry->id);
|
||||
$destinationBalance = $this->getBalance($entry->destination_id);
|
||||
$transaction = [
|
||||
'source_id' => $entry->id,
|
||||
'source_amount' => $entry->amount,
|
||||
|
||||
'description' => $entry->description,
|
||||
'source_account_id' => $entry->account_id,
|
||||
'source_account_name' => intval($entry->account_encrypted) === 1 ? Crypt::decrypt($entry->account_name) : $entry->account_name,
|
||||
'source_account_before' => $sourceBalance,
|
||||
'source_account_after' => bcadd($sourceBalance, $entry->amount),
|
||||
'destination_id' => $entry->destination_id,
|
||||
'destination_amount' => bcmul($entry->amount, '-1'),
|
||||
'destination_account_id' => $entry->destination_account_id,
|
||||
'destination_account_name' =>
|
||||
intval($entry->destination_account_encrypted) === 1 ? Crypt::decrypt($entry->destination_account_name) : $entry->destination_account_name,
|
||||
'destination_account_before' => $destinationBalance,
|
||||
'destination_account_after' => bcadd($destinationBalance, bcmul($entry->amount, '-1')),
|
||||
];
|
||||
|
||||
$transactions[] = $transaction;
|
||||
}
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collect the balance of an account before the given transaction has hit. This is tricky, because
|
||||
* the balance does not depend on the transaction itself but the journal it's part of. And of course
|
||||
* the order of transactions within the journal. So the query is pretty complex:
|
||||
*
|
||||
* @param int $transactionId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getBalance(int $transactionId): string
|
||||
{
|
||||
/*
|
||||
select
|
||||
|
||||
-- transactions.*, transaction_journals.date, transaction_journals.order, transaction_journals.id, transactions.identifier
|
||||
sum(transactions.amount)
|
||||
|
||||
from transactions
|
||||
|
||||
|
||||
and (
|
||||
-- first things first: remove all transaction journals that are newer by selecting only those that are earlier:
|
||||
or
|
||||
-- date is 03 but sorted lower: (fucntion 1)
|
||||
(
|
||||
transaction_journals.date = "2016-09-20"
|
||||
and transaction_journals.order > 2)
|
||||
or
|
||||
-- date is 03 and sort is the same but id is higher (func 2)
|
||||
(transaction_journals.date = "2016-09-20"
|
||||
and transaction_journals.order = 2
|
||||
and transaction_journals.id < 6966
|
||||
)
|
||||
-- date is 03 and sort is the same, and id is the same but identifier is 1 and not 0.(func 3)
|
||||
or
|
||||
(transaction_journals.date = "2016-09-20"
|
||||
and transaction_journals.order = 2
|
||||
and transaction_journals.id = 6966
|
||||
and transactions.identifier > 1
|
||||
)
|
||||
) -- 14048
|
||||
and transactions.id != 14048 -- just in case
|
||||
|
||||
order by transaction_journals.date DESC, transaction_journals.order ASC, transaction_journals.id DESC, transactions.identifier ASC
|
||||
*/
|
||||
// find the transaction first:
|
||||
$transaction = Transaction::find($transactionId);
|
||||
$date = $transaction->transactionJournal->date->format('Y-m-d');
|
||||
$order = intval($transaction->transactionJournal->order);
|
||||
$journalId = intval($transaction->transaction_journal_id);
|
||||
$identifier = intval($transaction->identifier);
|
||||
|
||||
// go!
|
||||
$sum
|
||||
= Transaction
|
||||
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('account_id', $transaction->account_id)
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->where('transactions.id', '!=', $transactionId)
|
||||
->where(
|
||||
function (Builder $q1) use ($date, $order, $journalId, $identifier) {
|
||||
$q1->where('transaction_journals.date', '<', $date); // date
|
||||
$q1->orWhere(
|
||||
function (Builder $q2) use ($date, $order) { // function 1
|
||||
$q2->where('transaction_journals.date', $date);
|
||||
$q2->where('transaction_journals.order', '>', $order);
|
||||
}
|
||||
);
|
||||
$q1->orWhere(
|
||||
function (Builder $q3) use ($date, $order, $journalId) { // function 2
|
||||
$q3->where('transaction_journals.date', $date);
|
||||
$q3->where('transaction_journals.order', $order);
|
||||
$q3->where('transaction_journals.id', '<', $journalId);
|
||||
}
|
||||
);
|
||||
$q1->orWhere(
|
||||
function (Builder $q4) use ($date, $order, $journalId, $identifier) { // function 3
|
||||
$q4->where('transaction_journals.date', $date);
|
||||
$q4->where('transaction_journals.order', $order);
|
||||
$q4->where('transaction_journals.id', $journalId);
|
||||
$q4->where('transactions.identifier', '>', $identifier);
|
||||
}
|
||||
);
|
||||
}
|
||||
)->sum('transactions.amount');
|
||||
|
||||
return strval($sum);
|
||||
}
|
||||
}
|
36
app/Repositories/Journal/JournalTaskerInterface.php
Normal file
36
app/Repositories/Journal/JournalTaskerInterface.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* JournalTaskerInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Repositories\Journal;
|
||||
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
|
||||
/**
|
||||
* Interface JournalTaskerInterface
|
||||
*
|
||||
* @package FireflyIII\Repositories\Journal
|
||||
*/
|
||||
interface JournalTaskerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Get an overview of the transactions of a journal, tailored to the view
|
||||
* that shows a transaction (transaction/show/xx).
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTransactionsOverview(TransactionJournal $journal): array;
|
||||
}
|
Reference in New Issue
Block a user