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
{
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
{
// get sort instructions
@@ -116,4 +75,44 @@ class TransactionController extends Controller
->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');
}
public function getAccountTypes(): array
{
$type = (string)$this->get('type', 'default');
return $this->mapAccountTypes($type);
}
public function getPage(): int
{
$page = $this->convertInteger('page');
@@ -122,13 +129,6 @@ class InfiniteListRequest extends FormRequest
return $this->mapTransactionTypes($type);
}
public function getAccountTypes(): array
{
$type = (string)$this->get('type', 'default');
return $this->mapAccountTypes($type);
}
public function rules(): array
{
return [

View File

@@ -47,7 +47,7 @@ class DeleteEmptyGroups extends Command
{
$groupIds
= TransactionGroup::leftJoin('transaction_journals', 'transaction_groups.id', '=', 'transaction_journals.transaction_group_id')
->whereNull('transaction_journals.id')->get(['transaction_groups.id'])->pluck('id')->toArray()
->whereNull('transaction_journals.id')->get(['transaction_groups.id'])->pluck('id')->toArray()
;
$total = count($groupIds);

View File

@@ -74,19 +74,19 @@ class ForceDecimalSize extends Command
private string $regularExpression;
private array $tables
= [
'accounts' => ['virtual_balance'],
'auto_budgets' => ['amount'],
'available_budgets' => ['amount'],
'bills' => ['amount_min', 'amount_max'],
'budget_limits' => ['amount'],
'currency_exchange_rates' => ['rate', 'user_rate'],
'limit_repetitions' => ['amount'],
'piggy_bank_events' => ['amount'],
'piggy_bank_repetitions' => ['currentamount'],
'piggy_banks' => ['targetamount'],
'recurrences_transactions' => ['amount', 'foreign_amount'],
'transactions' => ['amount', 'foreign_amount'],
];
'accounts' => ['virtual_balance'],
'auto_budgets' => ['amount'],
'available_budgets' => ['amount'],
'bills' => ['amount_min', 'amount_max'],
'budget_limits' => ['amount'],
'currency_exchange_rates' => ['rate', 'user_rate'],
'limit_repetitions' => ['amount'],
'piggy_bank_events' => ['amount'],
'piggy_bank_repetitions' => ['currentamount'],
'piggy_banks' => ['targetamount'],
'recurrences_transactions' => ['amount', 'foreign_amount'],
'transactions' => ['amount', 'foreign_amount'],
];
/**
* Execute the console command.

View File

@@ -72,31 +72,6 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$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
{
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);
}
public function getVersion(): int
{
return $this->version;
}
private function collectAccounts(TransactionGroup $transactionGroup): Collection
{
$accounts = new Collection();
@@ -232,4 +212,24 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$webhookMessage->save();
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,10 +33,11 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
*/
trait CollectorProperties
{
public const string TEST = 'Test';
/** @var array<int, string> */
public array $sorting;
public const string TEST = 'Test';
private ?int $endRow;
private ?int $endRow;
private bool $expandGroupSearch;
private array $fields;
private bool $hasAccountInfo;
@@ -52,7 +53,7 @@ trait CollectorProperties
private ?int $page;
private array $postFilters;
private HasMany $query;
private ?int $startRow;
private ?int $startRow;
private array $stringFields;
/*
* This array is used to collect ALL tags the user may search for (using 'setTags').

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Helpers\Collector;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use Exception;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\Extensions\AccountCollection;
use FireflyIII\Helpers\Collector\Extensions\AmountCollection;
@@ -782,6 +783,35 @@ class GroupCollector implements GroupCollectorInterface
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.
*/
@@ -932,6 +962,14 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
#[\Override]
public function setSorting(array $instructions): GroupCollectorInterface
{
$this->sorting = $instructions;
return $this;
}
public function setStartRow(int $startRow): self
{
$this->startRow = $startRow;
@@ -1087,45 +1125,7 @@ class GroupCollector implements GroupCollectorInterface
// include budget ID + name (if any)
->withBudgetInformation()
// include bill ID + name (if any)
->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;
->withBillInformation();
return $this;
}

View File

@@ -285,13 +285,6 @@ interface GroupCollectorInterface
*/
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;
/**
@@ -560,6 +553,8 @@ interface GroupCollectorInterface
public function setSepaCT(string $sepaCT): self;
public function setSorting(array $instructions): self;
/**
* Set source accounts.
*/
@@ -620,6 +615,11 @@ interface GroupCollectorInterface
*/
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.
*/

View File

@@ -51,7 +51,7 @@ class NetWorth implements NetWorthInterface
private CurrencyRepositoryInterface $currencyRepos;
private User $user;
private ?UserGroup $userGroup;
private ?UserGroup $userGroup;
/**
* This method collects the user's net worth in ALL the user's currencies

View File

@@ -277,11 +277,11 @@ class IndexController extends Controller
// also calculate how much left from budgeted:
$sums['left'][$currencyId]
??= [
'amount' => '0',
'currency_id' => $budgeted['currency_id'],
'currency_symbol' => $budgeted['currency_symbol'],
'currency_decimal_places' => $budgeted['currency_decimal_places'],
];
'amount' => '0',
'currency_id' => $budgeted['currency_id'],
'currency_symbol' => $budgeted['currency_symbol'],
'currency_decimal_places' => $budgeted['currency_decimal_places'],
];
}
}

View File

@@ -192,11 +192,11 @@ class CategoryController extends Controller
$chartData[$inKey]
= [
'label' => sprintf('%s (%s)', (string)trans('firefly.earned'), $currencyInfo['currency_name']),
'entries' => [],
'type' => 'bar',
'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green
];
'label' => sprintf('%s (%s)', (string)trans('firefly.earned'), $currencyInfo['currency_name']),
'entries' => [],
'type' => 'bar',
'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green
];
// loop empty periods:
foreach (array_keys($periods) as $period) {
$label = $periods[$period];

View File

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

View File

@@ -144,7 +144,6 @@ class JavascriptController extends Controller
return response()
->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);
}
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.
*
@@ -195,37 +226,6 @@ class ReconcileController extends Controller
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:
*/

View File

@@ -122,13 +122,13 @@ class Account extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'user_id' => 'integer',
'deleted_at' => 'datetime',
'active' => 'boolean',
'encrypted' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'user_id' => 'integer',
'deleted_at' => 'datetime',
'active' => 'boolean',
'encrypted' => 'boolean',
];
protected $fillable = ['user_id', 'user_group_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban'];

View File

@@ -59,9 +59,9 @@ class AccountMeta extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
protected $fillable = ['account_id', 'name', 'data'];

View File

@@ -72,9 +72,9 @@ class AccountType extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
protected $fillable = ['type'];

View File

@@ -97,11 +97,11 @@ class Attachment extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'uploaded' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'uploaded' => 'boolean',
];
protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'md5', 'filename', 'mime', 'title', 'description', 'size', 'uploaded'];

View File

@@ -80,13 +80,13 @@ class AvailableBudget extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'start_date' => 'date',
'end_date' => 'date',
'transaction_currency_id' => 'int',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'start_date' => 'date',
'end_date' => 'date',
'transaction_currency_id' => 'int',
];
protected $fillable = ['user_id', 'user_group_id', 'transaction_currency_id', 'amount', 'start_date', 'end_date'];

View File

@@ -114,36 +114,36 @@ class Bill extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'date' => 'date',
'end_date' => 'date',
'extension_date' => 'date',
'skip' => 'int',
'automatch' => 'boolean',
'active' => 'boolean',
'name_encrypted' => 'boolean',
'match_encrypted' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'date' => 'date',
'end_date' => 'date',
'extension_date' => 'date',
'skip' => 'int',
'automatch' => 'boolean',
'active' => 'boolean',
'name_encrypted' => 'boolean',
'match_encrypted' => 'boolean',
];
protected $fillable
= [
'name',
'match',
'amount_min',
'user_id',
'user_group_id',
'amount_max',
'date',
'repeat_freq',
'skip',
'automatch',
'active',
'transaction_currency_id',
'end_date',
'extension_date',
];
'name',
'match',
'amount_min',
'user_id',
'user_group_id',
'amount_max',
'date',
'repeat_freq',
'skip',
'automatch',
'active',
'transaction_currency_id',
'end_date',
'extension_date',
];
protected $hidden = ['amount_min_encrypted', 'amount_max_encrypted', 'name_encrypted', 'match_encrypted'];

View File

@@ -97,12 +97,12 @@ class Budget extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'active' => 'boolean',
'encrypted' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'active' => 'boolean',
'encrypted' => 'boolean',
];
protected $fillable = ['user_id', 'name', 'active', 'order', 'user_group_id'];

View File

@@ -74,18 +74,18 @@ class BudgetLimit extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'start_date' => 'date',
'end_date' => 'date',
'auto_budget' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'start_date' => 'date',
'end_date' => 'date',
'auto_budget' => 'boolean',
];
protected $dispatchesEvents
= [
'created' => Created::class,
'updated' => Updated::class,
'deleted' => Deleted::class,
];
'created' => Created::class,
'updated' => Updated::class,
'deleted' => Deleted::class,
];
protected $fillable = ['budget_id', 'start_date', 'end_date', 'amount', 'transaction_currency_id'];

View File

@@ -86,11 +86,11 @@ class Category extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'encrypted' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'encrypted' => 'boolean',
];
protected $fillable = ['user_id', 'user_group_id', 'name'];

View File

@@ -62,10 +62,10 @@ class Configuration extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
/** @var string The table to store the data in */
protected $table = 'configuration';

View File

@@ -72,11 +72,11 @@ class LinkType extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'editable' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'editable' => 'boolean',
];
protected $fillable = ['name', 'inward', 'outward', 'editable'];

View File

@@ -74,13 +74,13 @@ class Location extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'zoomLevel' => 'int',
'latitude' => 'float',
'longitude' => 'float',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'zoomLevel' => 'int',
'latitude' => 'float',
'longitude' => 'float',
];
protected $fillable = ['locatable_id', 'locatable_type', 'latitude', 'longitude', 'zoom_level'];

View File

@@ -69,10 +69,10 @@ class Note extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
protected $fillable = ['title', 'text', 'noteable_id', 'noteable_type'];

View File

@@ -92,15 +92,15 @@ class PiggyBank extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'startdate' => 'date',
'targetdate' => 'date',
'order' => 'int',
'active' => 'boolean',
'encrypted' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'startdate' => 'date',
'targetdate' => 'date',
'order' => 'int',
'active' => 'boolean',
'encrypted' => 'boolean',
];
protected $fillable = ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate', 'active'];

View File

@@ -63,10 +63,10 @@ class PiggyBankEvent extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'date' => 'date',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'date' => 'date',
];
protected $fillable = ['piggy_bank_id', 'transaction_journal_id', 'date', 'amount'];

View File

@@ -64,11 +64,11 @@ class PiggyBankRepetition extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'startdate' => 'date',
'targetdate' => 'date',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'startdate' => 'date',
'targetdate' => 'date',
];
protected $fillable = ['piggy_bank_id', 'startdate', 'targetdate', 'currentamount'];

View File

@@ -63,10 +63,10 @@ class Preference extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'data' => 'array',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'data' => 'array',
];
protected $fillable = ['user_id', 'data', 'name'];

View File

@@ -104,19 +104,19 @@ class Recurrence extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'title' => 'string',
'id' => 'int',
'description' => 'string',
'first_date' => 'date',
'repeat_until' => 'date',
'latest_date' => 'date',
'repetitions' => 'int',
'active' => 'bool',
'apply_rules' => 'bool',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'title' => 'string',
'id' => 'int',
'description' => 'string',
'first_date' => 'date',
'repeat_until' => 'date',
'latest_date' => 'date',
'repetitions' => 'int',
'active' => 'bool',
'apply_rules' => 'bool',
];
protected $fillable
= ['user_id', 'transaction_type_id', 'title', 'description', 'first_date', 'repeat_until', 'latest_date', 'repetitions', 'apply_rules', 'active'];

View File

@@ -67,12 +67,12 @@ class RecurrenceMeta extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'name' => 'string',
'value' => 'string',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'name' => 'string',
'value' => 'string',
];
protected $fillable = ['recurrence_id', 'name', 'value'];

View File

@@ -76,14 +76,14 @@ class RecurrenceRepetition extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'repetition_type' => 'string',
'repetition_moment' => 'string',
'repetition_skip' => 'int',
'weekend' => 'int',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'repetition_type' => 'string',
'repetition_moment' => 'string',
'repetition_skip' => 'int',
'weekend' => 'int',
];
protected $fillable = ['recurrence_id', 'weekend', 'repetition_type', 'repetition_moment', 'repetition_skip'];

View File

@@ -91,25 +91,25 @@ class RecurrenceTransaction extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'amount' => 'string',
'foreign_amount' => 'string',
'description' => 'string',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'amount' => 'string',
'foreign_amount' => 'string',
'description' => 'string',
];
protected $fillable
= [
'recurrence_id',
'transaction_currency_id',
'foreign_currency_id',
'source_id',
'destination_id',
'amount',
'foreign_amount',
'description',
];
'recurrence_id',
'transaction_currency_id',
'foreign_currency_id',
'source_id',
'destination_id',
'amount',
'foreign_amount',
'description',
];
/** @var string The table to store the data in */
protected $table = 'recurrences_transactions';

View File

@@ -67,12 +67,12 @@ class RecurrenceTransactionMeta extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'name' => 'string',
'value' => 'string',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'name' => 'string',
'value' => 'string',
];
protected $fillable = ['rt_id', 'name', 'value'];

View File

@@ -62,9 +62,9 @@ class Role extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
protected $fillable = ['name', 'display_name', 'description'];

View File

@@ -95,15 +95,15 @@ class Rule extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
'id' => 'int',
'strict' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
'id' => 'int',
'strict' => 'boolean',
];
protected $fillable = ['rule_group_id', 'order', 'active', 'title', 'description', 'user_id', 'strict'];

View File

@@ -66,12 +66,12 @@ class RuleAction extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
];
protected $fillable = ['rule_id', 'action_type', 'action_value', 'order', 'active', 'stop_processing'];

View File

@@ -85,13 +85,13 @@ class RuleGroup extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'active' => 'boolean',
'stop_processing' => 'boolean',
'order' => 'int',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'active' => 'boolean',
'stop_processing' => 'boolean',
'order' => 'int',
];
protected $fillable = ['user_id', 'user_group_id', 'stop_processing', 'order', 'title', 'description', 'active'];

View File

@@ -66,12 +66,12 @@ class RuleTrigger extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
];
protected $fillable = ['rule_id', 'trigger_type', 'trigger_value', 'order', 'active', 'stop_processing'];

View File

@@ -93,14 +93,14 @@ class Tag extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'date' => 'date',
'zoomLevel' => 'int',
'latitude' => 'float',
'longitude' => 'float',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'date' => 'date',
'zoomLevel' => 'int',
'latitude' => 'float',
'longitude' => 'float',
];
protected $fillable = ['user_id', 'user_group_id', 'tag', 'date', 'description', 'tagMode'];

View File

@@ -99,28 +99,28 @@ class Transaction extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'identifier' => 'int',
'encrypted' => 'boolean', // model does not have these fields though
'bill_name_encrypted' => 'boolean',
'reconciled' => 'boolean',
'date' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'identifier' => 'int',
'encrypted' => 'boolean', // model does not have these fields though
'bill_name_encrypted' => 'boolean',
'reconciled' => 'boolean',
'date' => 'datetime',
];
protected $fillable
= [
'account_id',
'transaction_journal_id',
'description',
'amount',
'identifier',
'transaction_currency_id',
'foreign_currency_id',
'foreign_amount',
'reconciled',
];
'account_id',
'transaction_journal_id',
'description',
'amount',
'identifier',
'transaction_currency_id',
'foreign_currency_id',
'foreign_amount',
'reconciled',
];
protected $hidden = ['encrypted'];

View File

@@ -89,12 +89,12 @@ class TransactionCurrency extends Model
public ?bool $userGroupEnabled;
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'decimal_places' => 'int',
'enabled' => 'bool',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'decimal_places' => 'int',
'enabled' => 'bool',
];
protected $fillable = ['name', 'code', 'symbol', 'decimal_places', 'enabled'];

View File

@@ -78,13 +78,13 @@ class TransactionGroup extends Model
protected $casts
= [
'id' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'title' => 'string',
'date' => 'datetime',
];
'id' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'title' => 'string',
'date' => 'datetime',
];
protected $fillable = ['user_id', 'user_group_id', 'title'];

View File

@@ -138,32 +138,32 @@ class TransactionJournal extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'date' => 'datetime',
'interest_date' => 'date',
'book_date' => 'date',
'process_date' => 'date',
'order' => 'int',
'tag_count' => 'int',
'encrypted' => 'boolean',
'completed' => 'boolean',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'date' => 'datetime',
'interest_date' => 'date',
'book_date' => 'date',
'process_date' => 'date',
'order' => 'int',
'tag_count' => 'int',
'encrypted' => 'boolean',
'completed' => 'boolean',
];
protected $fillable
= [
'user_id',
'user_group_id',
'transaction_type_id',
'bill_id',
'tag_count',
'transaction_currency_id',
'description',
'completed',
'order',
'date',
];
'user_id',
'user_group_id',
'transaction_type_id',
'bill_id',
'tag_count',
'transaction_currency_id',
'description',
'completed',
'order',
'date',
];
protected $hidden = ['encrypted'];

View File

@@ -71,9 +71,9 @@ class TransactionJournalLink extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/** @var string The table to store the data in */
protected $table = 'journal_links';

View File

@@ -69,10 +69,10 @@ class TransactionJournalMeta extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
protected $fillable = ['transaction_journal_id', 'name', 'data', 'hash'];

View File

@@ -73,10 +73,10 @@ class TransactionType extends Model
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
protected $fillable = ['type'];
/**

View File

@@ -202,7 +202,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
$availableBudget->user()->associate($this->user);
$availableBudget->transactionCurrency()->associate($currency);
$availableBudget->start_date = $start->startOfDay()->format('Y-m-d'); // @phpstan-ignore-line
$availableBudget->end_date = $end->endOfDay()->format('Y-m-d'); // @phpstan-ignore-line
$availableBudget->end_date = $end->endOfDay()->format('Y-m-d'); // @phpstan-ignore-line
}
$availableBudget->amount = $amount;
$availableBudget->save();

View File

@@ -75,9 +75,9 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface
$journalId = (int)$journal['transaction_journal_id'];
$array[$currencyId]['categories'][0]['transaction_journals'][$journalId]
= [
'amount' => app('steam')->negative($journal['amount']),
'date' => $journal['date'],
];
'amount' => app('steam')->negative($journal['amount']),
'date' => $journal['date'],
];
}
return $array;
@@ -128,9 +128,9 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface
$journalId = (int)$journal['transaction_journal_id'];
$array[$currencyId]['categories'][0]['transaction_journals'][$journalId]
= [
'amount' => app('steam')->positive($journal['amount']),
'date' => $journal['date'],
];
'amount' => app('steam')->positive($journal['amount']),
'date' => $journal['date'],
];
}
return $array;

View File

@@ -39,6 +39,17 @@ class AccountRepository implements AccountRepositoryInterface
{
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
{
$dbQuery = $this->userGroup
@@ -161,6 +172,71 @@ class AccountRepository implements AccountRepositoryInterface
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
{
$res = array_intersect([AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT], $types);
@@ -187,20 +263,6 @@ class AccountRepository implements AccountRepositoryInterface
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
{
// search by group, not by user
@@ -226,66 +288,4 @@ class AccountRepository implements AccountRepositoryInterface
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
{
public function countAccounts(array $types): int;
public function find(int $accountId): ?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 countAccounts(array $types): int;
/**
* Used in the infinite accounts list.
*/
@@ -63,14 +63,14 @@ interface AccountRepositoryInterface
*/
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 setUser(User $user): void;
public function setUserGroup(UserGroup $userGroup): void;
/**
* Reset order types of the mentioned accounts.
*/
public function resetAccountOrder(): void;
}

View File

@@ -146,10 +146,10 @@ class UniqueIban implements ValidationRule
}
$query
= auth()->user()
->accounts()
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('accounts.iban', $iban)
->whereIn('account_types.type', $typesArray)
->accounts()
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('accounts.iban', $iban)
->whereIn('account_types.type', $typesArray)
;
if (null !== $this->account) {

View File

@@ -39,7 +39,7 @@ class RemoteUserGuard implements Guard
{
protected Application $application;
protected UserProvider $provider;
protected ?User $user;
protected ?User $user;
/**
* Create a new authentication guard.

View File

@@ -566,13 +566,13 @@ trait PeriodOverview
}
$entries[]
= [
'title' => $title,
'route' => route('transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
'total_transactions' => count($spent) + count($earned) + count($transferred),
'spent' => $this->groupByCurrency($spent),
'earned' => $this->groupByCurrency($earned),
'transferred' => $this->groupByCurrency($transferred),
];
'title' => $title,
'route' => route('transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
'total_transactions' => count($spent) + count($earned) + count($transferred),
'spent' => $this->groupByCurrency($spent),
'earned' => $this->groupByCurrency($earned),
'transferred' => $this->groupByCurrency($transferred),
];
}
return $entries;

View File

@@ -213,16 +213,16 @@ class BudgetReportGenerator
// make sum information:
$this->report['sums'][$currencyId]
??= [
'budgeted' => '0',
'spent' => '0',
'left' => '0',
'overspent' => '0',
'currency_id' => $currencyId,
'currency_code' => $limitCurrency->code,
'currency_name' => $limitCurrency->name,
'currency_symbol' => $limitCurrency->symbol,
'currency_decimal_places' => $limitCurrency->decimal_places,
];
'budgeted' => '0',
'spent' => '0',
'left' => '0',
'overspent' => '0',
'currency_id' => $currencyId,
'currency_code' => $limitCurrency->code,
'currency_name' => $limitCurrency->name,
'currency_symbol' => $limitCurrency->symbol,
'currency_decimal_places' => $limitCurrency->decimal_places,
];
$this->report['sums'][$currencyId]['budgeted'] = bcadd($this->report['sums'][$currencyId]['budgeted'], $limit->amount);
$this->report['sums'][$currencyId]['spent'] = bcadd($this->report['sums'][$currencyId]['spent'], $spent);
$this->report['sums'][$currencyId]['left'] = bcadd($this->report['sums'][$currencyId]['left'], bcadd($limit->amount, $spent));

View File

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

View File

@@ -47,7 +47,7 @@ use Illuminate\Support\Facades\DB;
class TransactionGroupTransformer extends AbstractTransformer
{
private array $accountTypes = []; // account types collection.
private ExchangeRateConverter $converter; // collection of all journals and some important meta-data.
private ExchangeRateConverter $converter; // collection of all journals and some important meta-data.
private array $currencies = [];
private TransactionCurrency $default; // collection of all currencies for this transformer.
private array $journals = [];

View File

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