Various code cleanup.

This commit is contained in:
James Cole
2024-03-06 07:16:01 +01:00
parent 0597255c08
commit fd2edf3b23
61 changed files with 567 additions and 566 deletions

2
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,2 @@
# code owners for this Firefly III related repository
* @JC5 @SDx3

View File

@@ -35,47 +35,6 @@ use Illuminate\Http\JsonResponse;
*/ */
class TransactionController extends Controller class TransactionController extends Controller
{ {
public function list(ListRequest $request): JsonResponse
{
// collect transactions:
$pageSize = $this->parameters->get('limit');
$page = $request->getPage();
$page = max($page, 1);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUserGroup(auth()->user()->userGroup)
->withAPIInformation()
->setLimit($pageSize)
->setPage($page)
->setTypes($request->getTransactionTypes())
;
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
if (null !== $start) {
$collector->setStart($start);
}
if (null !== $end) {
$collector->setEnd($end);
}
$paginator = $collector->getPaginatedGroups();
$params = $request->buildParams($pageSize);
$paginator->setPath(
sprintf(
'%s?%s',
route('api.v2.transactions.list'),
$params
)
);
return response()
->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer()))
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function infiniteList(InfiniteListRequest $request): JsonResponse public function infiniteList(InfiniteListRequest $request): JsonResponse
{ {
// get sort instructions // get sort instructions
@@ -116,4 +75,44 @@ class TransactionController extends Controller
->header('Content-Type', self::CONTENT_TYPE) ->header('Content-Type', self::CONTENT_TYPE)
; ;
} }
public function list(ListRequest $request): JsonResponse
{
// collect transactions:
$pageSize = $this->parameters->get('limit');
$page = $request->getPage();
$page = max($page, 1);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUserGroup(auth()->user()->userGroup)
->withAPIInformation()
->setLimit($pageSize)
->setPage($page)
->setTypes($request->getTransactionTypes())
;
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
if (null !== $start) {
$collector->setStart($start);
}
if (null !== $end) {
$collector->setEnd($end);
}
$paginator = $collector->getPaginatedGroups();
$params = $request->buildParams($pageSize);
$paginator->setPath(
sprintf(
'%s?%s',
route('api.v2.transactions.list'),
$params
)
);
return response()
->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer()))
->header('Content-Type', self::CONTENT_TYPE);
}
} }

View File

@@ -83,6 +83,13 @@ class InfiniteListRequest extends FormRequest
return $this->getCarbonDate('end'); return $this->getCarbonDate('end');
} }
public function getAccountTypes(): array
{
$type = (string)$this->get('type', 'default');
return $this->mapAccountTypes($type);
}
public function getPage(): int public function getPage(): int
{ {
$page = $this->convertInteger('page'); $page = $this->convertInteger('page');
@@ -122,13 +129,6 @@ class InfiniteListRequest extends FormRequest
return $this->mapTransactionTypes($type); return $this->mapTransactionTypes($type);
} }
public function getAccountTypes(): array
{
$type = (string)$this->get('type', 'default');
return $this->mapAccountTypes($type);
}
public function rules(): array public function rules(): array
{ {
return [ return [

View File

@@ -72,31 +72,6 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$this->run(); $this->run();
} }
public function getVersion(): int
{
return $this->version;
}
public function setObjects(Collection $objects): void
{
$this->objects = $objects;
}
public function setTrigger(int $trigger): void
{
$this->trigger = $trigger;
}
public function setUser(User $user): void
{
$this->user = $user;
}
public function setWebhooks(Collection $webhooks): void
{
$this->webhooks = $webhooks;
}
private function getWebhooks(): Collection private function getWebhooks(): Collection
{ {
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']); return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
@@ -206,6 +181,11 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$this->storeMessage($webhook, $basicMessage); $this->storeMessage($webhook, $basicMessage);
} }
public function getVersion(): int
{
return $this->version;
}
private function collectAccounts(TransactionGroup $transactionGroup): Collection private function collectAccounts(TransactionGroup $transactionGroup): Collection
{ {
$accounts = new Collection(); $accounts = new Collection();
@@ -232,4 +212,24 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$webhookMessage->save(); $webhookMessage->save();
app('log')->debug(sprintf('Stored new webhook message #%d', $webhookMessage->id)); app('log')->debug(sprintf('Stored new webhook message #%d', $webhookMessage->id));
} }
public function setObjects(Collection $objects): void
{
$this->objects = $objects;
}
public function setTrigger(int $trigger): void
{
$this->trigger = $trigger;
}
public function setUser(User $user): void
{
$this->user = $user;
}
public function setWebhooks(Collection $webhooks): void
{
$this->webhooks = $webhooks;
}
} }

View File

@@ -33,9 +33,10 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
*/ */
trait CollectorProperties trait CollectorProperties
{ {
public const string TEST = 'Test';
/** @var array<int, string> */ /** @var array<int, string> */
public array $sorting; public array $sorting;
public const string TEST = 'Test';
private ?int $endRow; private ?int $endRow;
private bool $expandGroupSearch; private bool $expandGroupSearch;
private array $fields; private array $fields;

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Helpers\Collector;
use Carbon\Carbon; use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException; use Carbon\Exceptions\InvalidFormatException;
use Exception;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\Extensions\AccountCollection; use FireflyIII\Helpers\Collector\Extensions\AccountCollection;
use FireflyIII\Helpers\Collector\Extensions\AmountCollection; use FireflyIII\Helpers\Collector\Extensions\AmountCollection;
@@ -782,6 +783,35 @@ class GroupCollector implements GroupCollectorInterface
return $currentCollection; return $currentCollection;
} }
#[\Override]
public function sortCollection(Collection $collection): Collection
{
/**
* @var string $field
* @var string $direction
*/
foreach ($this->sorting as $field => $direction) {
$func = 'ASC' === $direction ? 'sortBy' : 'sortByDesc';
$collection = $collection->{$func}(function (array $product, int $key) use ($field) { // @phpstan-ignore-line
// depends on $field:
if ('description' === $field) {
if (1 === count($product['transactions'])) {
return array_values($product['transactions'])[0][$field];
}
if (count($product['transactions']) > 1) {
return $product['title'];
}
return 'zzz';
}
exit('here we are');
});
}
return $collection;
}
/** /**
* Same as getGroups but everything is in a paginator. * Same as getGroups but everything is in a paginator.
*/ */
@@ -932,6 +962,14 @@ class GroupCollector implements GroupCollectorInterface
return $this; return $this;
} }
#[\Override]
public function setSorting(array $instructions): GroupCollectorInterface
{
$this->sorting = $instructions;
return $this;
}
public function setStartRow(int $startRow): self public function setStartRow(int $startRow): self
{ {
$this->startRow = $startRow; $this->startRow = $startRow;
@@ -1087,45 +1125,7 @@ class GroupCollector implements GroupCollectorInterface
// include budget ID + name (if any) // include budget ID + name (if any)
->withBudgetInformation() ->withBudgetInformation()
// include bill ID + name (if any) // include bill ID + name (if any)
->withBillInformation() ->withBillInformation();
;
return $this;
}
#[\Override]
public function sortCollection(Collection $collection): Collection
{
/**
* @var string $field
* @var string $direction
*/
foreach ($this->sorting as $field => $direction) {
$func = 'ASC' === $direction ? 'sortBy' : 'sortByDesc';
$collection = $collection->{$func}(function (array $product, int $key) use ($field) { // @phpstan-ignore-line
// depends on $field:
if ('description' === $field) {
if (1 === count($product['transactions'])) {
return array_values($product['transactions'])[0][$field];
}
if (count($product['transactions']) > 1) {
return $product['title'];
}
return 'zzz';
}
exit('here we are');
});
}
return $collection;
}
#[\Override]
public function setSorting(array $instructions): GroupCollectorInterface
{
$this->sorting = $instructions;
return $this; return $this;
} }

View File

@@ -285,13 +285,6 @@ interface GroupCollectorInterface
*/ */
public function getPaginatedGroups(): LengthAwarePaginator; public function getPaginatedGroups(): LengthAwarePaginator;
public function setSorting(array $instructions): self;
/**
* Sort the collection on a column.
*/
public function sortCollection(Collection $collection): Collection;
public function hasAnyTag(): self; public function hasAnyTag(): self;
/** /**
@@ -560,6 +553,8 @@ interface GroupCollectorInterface
public function setSepaCT(string $sepaCT): self; public function setSepaCT(string $sepaCT): self;
public function setSorting(array $instructions): self;
/** /**
* Set source accounts. * Set source accounts.
*/ */
@@ -620,6 +615,11 @@ interface GroupCollectorInterface
*/ */
public function setXorAccounts(Collection $accounts): self; public function setXorAccounts(Collection $accounts): self;
/**
* Sort the collection on a column.
*/
public function sortCollection(Collection $collection): Collection;
/** /**
* Automatically include all stuff required to make API calls work. * Automatically include all stuff required to make API calls work.
*/ */

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use Exception;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;

View File

@@ -144,7 +144,6 @@ class JavascriptController extends Controller
return response() return response()
->view('v2.javascript.variables', $data) ->view('v2.javascript.variables', $data)
->header('Content-Type', 'text/javascript') ->header('Content-Type', 'text/javascript');
;
} }
} }

View File

@@ -139,6 +139,37 @@ class ReconcileController extends Controller
return response()->json($return); return response()->json($return);
} }
private function processJournal(Account $account, TransactionCurrency $currency, array $journal, string $amount): string
{
$toAdd = '0';
app('log')->debug(sprintf('User submitted %s #%d: "%s"', $journal['transaction_type_type'], $journal['transaction_journal_id'], $journal['description']));
// not much magic below we need to cover using tests.
if ($account->id === $journal['source_account_id']) {
if ($currency->id === $journal['currency_id']) {
$toAdd = $journal['amount'];
}
if (null !== $journal['foreign_currency_id'] && $journal['foreign_currency_id'] === $currency->id) {
$toAdd = $journal['foreign_amount'];
}
}
if ($account->id === $journal['destination_account_id']) {
if ($currency->id === $journal['currency_id']) {
$toAdd = bcmul($journal['amount'], '-1');
}
if (null !== $journal['foreign_currency_id'] && $journal['foreign_currency_id'] === $currency->id) {
$toAdd = bcmul($journal['foreign_amount'], '-1');
}
}
app('log')->debug(sprintf('Going to add %s to %s', $toAdd, $amount));
$amount = bcadd($amount, $toAdd);
app('log')->debug(sprintf('Result is %s', $amount));
return $amount;
}
/** /**
* Returns a list of transactions in a modal. * Returns a list of transactions in a modal.
* *
@@ -195,37 +226,6 @@ class ReconcileController extends Controller
return response()->json(['html' => $html, 'startBalance' => $startBalance, 'endBalance' => $endBalance]); return response()->json(['html' => $html, 'startBalance' => $startBalance, 'endBalance' => $endBalance]);
} }
private function processJournal(Account $account, TransactionCurrency $currency, array $journal, string $amount): string
{
$toAdd = '0';
app('log')->debug(sprintf('User submitted %s #%d: "%s"', $journal['transaction_type_type'], $journal['transaction_journal_id'], $journal['description']));
// not much magic below we need to cover using tests.
if ($account->id === $journal['source_account_id']) {
if ($currency->id === $journal['currency_id']) {
$toAdd = $journal['amount'];
}
if (null !== $journal['foreign_currency_id'] && $journal['foreign_currency_id'] === $currency->id) {
$toAdd = $journal['foreign_amount'];
}
}
if ($account->id === $journal['destination_account_id']) {
if ($currency->id === $journal['currency_id']) {
$toAdd = bcmul($journal['amount'], '-1');
}
if (null !== $journal['foreign_currency_id'] && $journal['foreign_currency_id'] === $currency->id) {
$toAdd = bcmul($journal['foreign_amount'], '-1');
}
}
app('log')->debug(sprintf('Going to add %s to %s', $toAdd, $amount));
$amount = bcadd($amount, $toAdd);
app('log')->debug(sprintf('Result is %s', $amount));
return $amount;
}
/** /**
* "fix" amounts to make it easier on the reconciliation overview: * "fix" amounts to make it easier on the reconciliation overview:
*/ */

View File

@@ -39,6 +39,17 @@ class AccountRepository implements AccountRepositoryInterface
{ {
use UserGroupTrait; use UserGroupTrait;
#[\Override]
public function countAccounts(array $types): int
{
$query = $this->userGroup->accounts();
if (0 !== count($types)) {
$query->accountTypeIn($types);
}
return $query->count();
}
public function findByAccountNumber(string $number, array $types): ?Account public function findByAccountNumber(string $number, array $types): ?Account
{ {
$dbQuery = $this->userGroup $dbQuery = $this->userGroup
@@ -161,6 +172,71 @@ class AccountRepository implements AccountRepositoryInterface
return $query->get(['accounts.*']); return $query->get(['accounts.*']);
} }
#[\Override]
public function getAccountsInOrder(array $types, array $sort, int $startRow, int $endRow): Collection
{
$query = $this->userGroup->accounts();
if (0 !== count($types)) {
$query->accountTypeIn($types);
}
$query->skip($startRow);
$query->take($endRow - $startRow);
// add sort parameters. At this point they're filtered to allowed fields to sort by:
if (0 !== count($sort)) {
foreach ($sort as $label => $direction) {
$query->orderBy(sprintf('accounts.%s', $label), $direction);
}
}
if (0 === count($sort)) {
$query->orderBy('accounts.order', 'ASC');
$query->orderBy('accounts.active', 'DESC');
$query->orderBy('accounts.name', 'ASC');
}
return $query->get(['accounts.*']);
}
public function getActiveAccountsByType(array $types): Collection
{
$query = $this->userGroup->accounts();
if (0 !== count($types)) {
$query->accountTypeIn($types);
}
$query->where('active', true);
$query->orderBy('accounts.account_type_id', 'ASC');
$query->orderBy('accounts.order', 'ASC');
$query->orderBy('accounts.name', 'ASC');
return $query->get(['accounts.*']);
}
public function resetAccountOrder(): void
{
$sets = [
[AccountType::DEFAULT, AccountType::ASSET],
[AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE],
];
foreach ($sets as $set) {
$list = $this->getAccountsByType($set);
$index = 1;
foreach ($list as $account) {
if (false === $account->active) {
$account->order = 0;
continue;
}
if ($index !== (int)$account->order) {
app('log')->debug(sprintf('Account #%d ("%s"): order should %d be but is %d.', $account->id, $account->name, $index, $account->order));
$account->order = $index;
$account->save();
}
++$index;
}
}
}
public function getAccountsByType(array $types, ?array $sort = []): Collection public function getAccountsByType(array $types, ?array $sort = []): Collection
{ {
$res = array_intersect([AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT], $types); $res = array_intersect([AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT], $types);
@@ -187,20 +263,6 @@ class AccountRepository implements AccountRepositoryInterface
return $query->get(['accounts.*']); return $query->get(['accounts.*']);
} }
public function getActiveAccountsByType(array $types): Collection
{
$query = $this->userGroup->accounts();
if (0 !== count($types)) {
$query->accountTypeIn($types);
}
$query->where('active', true);
$query->orderBy('accounts.account_type_id', 'ASC');
$query->orderBy('accounts.order', 'ASC');
$query->orderBy('accounts.name', 'ASC');
return $query->get(['accounts.*']);
}
public function searchAccount(string $query, array $types, int $limit): Collection public function searchAccount(string $query, array $types, int $limit): Collection
{ {
// search by group, not by user // search by group, not by user
@@ -226,66 +288,4 @@ class AccountRepository implements AccountRepositoryInterface
return $dbQuery->take($limit)->get(['accounts.*']); return $dbQuery->take($limit)->get(['accounts.*']);
} }
public function resetAccountOrder(): void
{
$sets = [
[AccountType::DEFAULT, AccountType::ASSET],
[AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE],
];
foreach ($sets as $set) {
$list = $this->getAccountsByType($set);
$index = 1;
foreach ($list as $account) {
if (false === $account->active) {
$account->order = 0;
continue;
}
if ($index !== (int)$account->order) {
app('log')->debug(sprintf('Account #%d ("%s"): order should %d be but is %d.', $account->id, $account->name, $index, $account->order));
$account->order = $index;
$account->save();
}
++$index;
}
}
}
#[\Override]
public function getAccountsInOrder(array $types, array $sort, int $startRow, int $endRow): Collection
{
$query = $this->userGroup->accounts();
if (0 !== count($types)) {
$query->accountTypeIn($types);
}
$query->skip($startRow);
$query->take($endRow - $startRow);
// add sort parameters. At this point they're filtered to allowed fields to sort by:
if (0 !== count($sort)) {
foreach ($sort as $label => $direction) {
$query->orderBy(sprintf('accounts.%s', $label), $direction);
}
}
if (0 === count($sort)) {
$query->orderBy('accounts.order', 'ASC');
$query->orderBy('accounts.active', 'DESC');
$query->orderBy('accounts.name', 'ASC');
}
return $query->get(['accounts.*']);
}
#[\Override]
public function countAccounts(array $types): int
{
$query = $this->userGroup->accounts();
if (0 !== count($types)) {
$query->accountTypeIn($types);
}
return $query->count();
}
} }

View File

@@ -35,6 +35,8 @@ use Illuminate\Support\Collection;
*/ */
interface AccountRepositoryInterface interface AccountRepositoryInterface
{ {
public function countAccounts(array $types): int;
public function find(int $accountId): ?Account; public function find(int $accountId): ?Account;
public function findByAccountNumber(string $number, array $types): ?Account; public function findByAccountNumber(string $number, array $types): ?Account;
@@ -49,8 +51,6 @@ interface AccountRepositoryInterface
public function getAccountsByType(array $types, ?array $sort = []): Collection; public function getAccountsByType(array $types, ?array $sort = []): Collection;
public function countAccounts(array $types): int;
/** /**
* Used in the infinite accounts list. * Used in the infinite accounts list.
*/ */
@@ -63,14 +63,14 @@ interface AccountRepositoryInterface
*/ */
public function getMetaValue(Account $account, string $field): ?string; public function getMetaValue(Account $account, string $field): ?string;
/**
* Reset order types of the mentioned accounts.
*/
public function resetAccountOrder(): void;
public function searchAccount(string $query, array $types, int $limit): Collection; public function searchAccount(string $query, array $types, int $limit): Collection;
public function setUser(User $user): void; public function setUser(User $user): void;
public function setUserGroup(UserGroup $userGroup): void; public function setUserGroup(UserGroup $userGroup): void;
/**
* Reset order types of the mentioned accounts.
*/
public function resetAccountOrder(): void;
} }

View File

@@ -72,9 +72,9 @@ class OperatorQuerySearch implements SearchInterface
private GroupCollectorInterface $collector; private GroupCollectorInterface $collector;
private CurrencyRepositoryInterface $currencyRepository; private CurrencyRepositoryInterface $currencyRepository;
private array $excludeTags; private array $excludeTags;
private array $includeTags;
// added to fix #8632
private array $includeAnyTags; private array $includeAnyTags;
// added to fix #8632
private array $includeTags;
private array $invalidOperators; private array $invalidOperators;
private int $limit; private int $limit;
private Collection $operators; private Collection $operators;

View File

@@ -824,8 +824,7 @@ class FireflyValidator extends Validator
->where('trigger', $trigger) ->where('trigger', $trigger)
->where('response', $response) ->where('response', $response)
->where('delivery', $delivery) ->where('delivery', $delivery)
->where('url', $url)->count() ->where('url', $url)->count();
;
} }
return false; return false;