diff --git a/app/Jobs/WarnAboutBills.php b/app/Jobs/WarnAboutBills.php index 5171d8ee73..36ce43ab3b 100644 --- a/app/Jobs/WarnAboutBills.php +++ b/app/Jobs/WarnAboutBills.php @@ -25,7 +25,6 @@ declare(strict_types=1); namespace FireflyIII\Jobs; use Carbon\Carbon; -use FireflyIII\Events\RequestedReportOnJournals; use FireflyIII\Events\WarnUserAboutBill; use FireflyIII\Models\Bill; use Illuminate\Bus\Queueable; diff --git a/app/Mail/AccessTokenCreatedMail.php b/app/Mail/AccessTokenCreatedMail.php index e37762201a..8450f76298 100644 --- a/app/Mail/AccessTokenCreatedMail.php +++ b/app/Mail/AccessTokenCreatedMail.php @@ -53,6 +53,6 @@ class AccessTokenCreatedMail extends Mailable { return $this ->markdown('emails.token-created') - ->subject((string)trans('email.access_token_created_subject')); + ->subject((string) trans('email.access_token_created_subject')); } } diff --git a/app/Mail/AdminTestMail.php b/app/Mail/AdminTestMail.php index ab173a0657..023a57adc2 100644 --- a/app/Mail/AdminTestMail.php +++ b/app/Mail/AdminTestMail.php @@ -46,7 +46,7 @@ class AdminTestMail extends Mailable */ public function __construct(string $email) { - $this->email = $email; + $this->email = $email; } /** @@ -58,6 +58,6 @@ class AdminTestMail extends Mailable { return $this ->markdown('emails.admin-test') - ->subject((string)trans('email.admin_test_subject')); + ->subject((string) trans('email.admin_test_subject')); } } diff --git a/app/Mail/BillWarningMail.php b/app/Mail/BillWarningMail.php index 04dd4b4113..de7e413066 100644 --- a/app/Mail/BillWarningMail.php +++ b/app/Mail/BillWarningMail.php @@ -34,8 +34,8 @@ class BillWarningMail extends Mailable use Queueable, SerializesModels; public Bill $bill; - public string $field; public int $diff; + public string $field; /** * ConfirmEmailChangeMail constructor. @@ -46,9 +46,9 @@ class BillWarningMail extends Mailable */ public function __construct(Bill $bill, string $field, int $diff) { - $this->bill = $bill; - $this->field = $field; - $this->diff = $diff; + $this->bill = $bill; + $this->field = $field; + $this->diff = $diff; } /** diff --git a/app/Mail/ConfirmEmailChangeMail.php b/app/Mail/ConfirmEmailChangeMail.php index d0aa293fc1..4181545de4 100644 --- a/app/Mail/ConfirmEmailChangeMail.php +++ b/app/Mail/ConfirmEmailChangeMail.php @@ -51,9 +51,9 @@ class ConfirmEmailChangeMail extends Mailable */ public function __construct(string $newEmail, string $oldEmail, string $url) { - $this->newEmail = $newEmail; - $this->oldEmail = $oldEmail; - $this->url = $url; + $this->newEmail = $newEmail; + $this->oldEmail = $oldEmail; + $this->url = $url; } /** @@ -66,7 +66,7 @@ class ConfirmEmailChangeMail extends Mailable return $this //->view('emails.confirm-email-change-html') //->text('emails.confirm-email-change-text') - ->markdown('emails.confirm-email-change') + ->markdown('emails.confirm-email-change') ->subject((string) trans('email.email_change_subject')); } } diff --git a/app/Mail/NewIPAddressWarningMail.php b/app/Mail/NewIPAddressWarningMail.php index f056561051..f387f1c84d 100644 --- a/app/Mail/NewIPAddressWarningMail.php +++ b/app/Mail/NewIPAddressWarningMail.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Mail; +use Exception; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; @@ -56,11 +57,11 @@ class NewIPAddressWarningMail extends Mailable */ public function build(): self { - $this->time = now(config('app.timezone'))->isoFormat((string)trans('config.date_time_js')); + $this->time = now(config('app.timezone'))->isoFormat((string) trans('config.date_time_js')); $this->host = ''; try { $hostName = gethostbyaddr($this->ipAddress); - } catch(\Exception $e) { + } catch (Exception $e) { $hostName = $this->ipAddress; } if ($hostName !== $this->ipAddress) { @@ -69,6 +70,6 @@ class NewIPAddressWarningMail extends Mailable return $this ->markdown('emails.new-ip') - ->subject((string)trans('email.login_from_new_ip')); + ->subject((string) trans('email.login_from_new_ip')); } } diff --git a/app/Mail/RegisteredUser.php b/app/Mail/RegisteredUser.php index 20f9d91b38..1ab61c951f 100644 --- a/app/Mail/RegisteredUser.php +++ b/app/Mail/RegisteredUser.php @@ -47,7 +47,7 @@ class RegisteredUser extends Mailable */ public function __construct(string $address) { - $this->address = $address; + $this->address = $address; } /** @@ -59,6 +59,6 @@ class RegisteredUser extends Mailable { return $this ->markdown('emails.registered') - ->subject((string)trans('email.registered_subject')); + ->subject((string) trans('email.registered_subject')); } } diff --git a/app/Mail/RequestedNewPassword.php b/app/Mail/RequestedNewPassword.php index bbe68adcdc..2aedd0aa4a 100644 --- a/app/Mail/RequestedNewPassword.php +++ b/app/Mail/RequestedNewPassword.php @@ -46,7 +46,7 @@ class RequestedNewPassword extends Mailable */ public function __construct(string $url) { - $this->url = $url; + $this->url = $url; } /** @@ -58,6 +58,6 @@ class RequestedNewPassword extends Mailable { return $this ->markdown('emails.password') - ->subject((string)trans('email.reset_pw_subject')); + ->subject((string) trans('email.reset_pw_subject')); } } diff --git a/app/Mail/UndoEmailChangeMail.php b/app/Mail/UndoEmailChangeMail.php index 0c76e726a1..c4247fd8af 100644 --- a/app/Mail/UndoEmailChangeMail.php +++ b/app/Mail/UndoEmailChangeMail.php @@ -48,9 +48,9 @@ class UndoEmailChangeMail extends Mailable */ public function __construct(string $newEmail, string $oldEmail, string $url) { - $this->newEmail = $newEmail; - $this->oldEmail = $oldEmail; - $this->url = $url; + $this->newEmail = $newEmail; + $this->oldEmail = $oldEmail; + $this->url = $url; } /** @@ -62,6 +62,6 @@ class UndoEmailChangeMail extends Mailable { return $this ->markdown('emails.undo-email-change') - ->subject((string)trans('email.email_change_subject')); + ->subject((string) trans('email.email_change_subject')); } } diff --git a/app/Models/Account.php b/app/Models/Account.php index 938f6a3d57..652ef27de7 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -138,7 +138,7 @@ class Account extends Model public static function routeBinder(string $value): Account { if (auth()->check()) { - $accountId = (int)$value; + $accountId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Account $account */ @@ -266,7 +266,7 @@ class Account extends Model */ public function setVirtualBalanceAttribute($value): void { - $value = (string)$value; + $value = (string) $value; if ('' === $value) { $value = null; } diff --git a/app/Models/AccountType.php b/app/Models/AccountType.php index c2c90132d7..859ff0b710 100644 --- a/app/Models/AccountType.php +++ b/app/Models/AccountType.php @@ -49,34 +49,34 @@ use Illuminate\Support\Carbon; */ class AccountType extends Model { - /** @var string */ - public const DEFAULT = 'Default account'; - /** @var string */ - public const CASH = 'Cash account'; /** @var string */ public const ASSET = 'Asset account'; /** @var string */ - public const EXPENSE = 'Expense account'; - /** @var string */ - public const REVENUE = 'Revenue account'; - /** @var string */ - public const INITIAL_BALANCE = 'Initial balance account'; - /** @var string */ public const BENEFICIARY = 'Beneficiary account'; /** @var string */ - public const IMPORT = 'Import account'; - /** @var string */ - public const RECONCILIATION = 'Reconciliation account'; - /** @var string */ - public const LOAN = 'Loan'; - /** @var string */ - public const DEBT = 'Debt'; - /** @var string */ - public const MORTGAGE = 'Mortgage'; + public const CASH = 'Cash account'; /** @var string */ public const CREDITCARD = 'Credit card'; /** @var string */ + public const DEBT = 'Debt'; + /** @var string */ + public const DEFAULT = 'Default account'; + /** @var string */ + public const EXPENSE = 'Expense account'; + /** @var string */ + public const IMPORT = 'Import account'; + /** @var string */ + public const INITIAL_BALANCE = 'Initial balance account'; + /** @var string */ public const LIABILITY_CREDIT = 'Liability credit account'; + /** @var string */ + public const LOAN = 'Loan'; + /** @var string */ + public const MORTGAGE = 'Mortgage'; + /** @var string */ + public const RECONCILIATION = 'Reconciliation account'; + /** @var string */ + public const REVENUE = 'Revenue account'; /** * The attributes that should be casted to native types. * diff --git a/app/Models/Attachment.php b/app/Models/Attachment.php index 686ae491ce..0aeb20f065 100644 --- a/app/Models/Attachment.php +++ b/app/Models/Attachment.php @@ -111,7 +111,7 @@ class Attachment extends Model public static function routeBinder(string $value): Attachment { if (auth()->check()) { - $attachmentId = (int)$value; + $attachmentId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Attachment $attachment */ @@ -143,7 +143,7 @@ class Attachment extends Model */ public function fileName(): string { - return sprintf('at-%s.data', (string)$this->id); + return sprintf('at-%s.data', (string) $this->id); } /** diff --git a/app/Models/AvailableBudget.php b/app/Models/AvailableBudget.php index c2d514457c..8685e4ceb7 100644 --- a/app/Models/AvailableBudget.php +++ b/app/Models/AvailableBudget.php @@ -96,7 +96,7 @@ class AvailableBudget extends Model public static function routeBinder(string $value): AvailableBudget { if (auth()->check()) { - $availableBudgetId = (int)$value; + $availableBudgetId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var AvailableBudget $availableBudget */ diff --git a/app/Models/Bill.php b/app/Models/Bill.php index d0af591be6..ecd0cc1d7b 100644 --- a/app/Models/Bill.php +++ b/app/Models/Bill.php @@ -139,7 +139,7 @@ class Bill extends Model public static function routeBinder(string $value): Bill { if (auth()->check()) { - $billId = (int)$value; + $billId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Bill $bill */ @@ -184,7 +184,7 @@ class Bill extends Model */ public function setAmountMaxAttribute($value): void { - $this->attributes['amount_max'] = (string)$value; + $this->attributes['amount_max'] = (string) $value; } /** @@ -194,7 +194,7 @@ class Bill extends Model */ public function setAmountMinAttribute($value): void { - $this->attributes['amount_min'] = (string)$value; + $this->attributes['amount_min'] = (string) $value; } /** diff --git a/app/Models/Budget.php b/app/Models/Budget.php index 91a8dc6f45..96a7dce142 100644 --- a/app/Models/Budget.php +++ b/app/Models/Budget.php @@ -38,26 +38,26 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * FireflyIII\Models\Budget * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $user_id - * @property string $name - * @property bool $active - * @property bool $encrypted - * @property int $order - * @property-read Collection|Attachment[] $attachments - * @property-read int|null $attachments_count - * @property-read Collection|AutoBudget[] $autoBudgets - * @property-read int|null $auto_budgets_count - * @property-read Collection|BudgetLimit[] $budgetlimits - * @property-read int|null $budgetlimits_count - * @property-read Collection|TransactionJournal[] $transactionJournals - * @property-read int|null $transaction_journals_count - * @property-read Collection|Transaction[] $transactions - * @property-read int|null $transactions_count - * @property-read User $user + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $user_id + * @property string $name + * @property bool $active + * @property bool $encrypted + * @property int $order + * @property-read Collection|Attachment[] $attachments + * @property-read int|null $attachments_count + * @property-read Collection|AutoBudget[] $autoBudgets + * @property-read int|null $auto_budgets_count + * @property-read Collection|BudgetLimit[] $budgetlimits + * @property-read int|null $budgetlimits_count + * @property-read Collection|TransactionJournal[] $transactionJournals + * @property-read int|null $transaction_journals_count + * @property-read Collection|Transaction[] $transactions + * @property-read int|null $transactions_count + * @property-read User $user * @method static \Illuminate\Database\Eloquent\Builder|Budget newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Budget newQuery() * @method static Builder|Budget onlyTrashed() @@ -74,11 +74,11 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @method static Builder|Budget withTrashed() * @method static Builder|Budget withoutTrashed() * @mixin Eloquent - * @property string $email - * @property int|null $user_group_id + * @property string $email + * @property int|null $user_group_id * @method static \Illuminate\Database\Eloquent\Builder|Budget whereUserGroupId($value) - * @property-read Collection|\FireflyIII\Models\Note[] $notes - * @property-read int|null $notes_count + * @property-read Collection|Note[] $notes + * @property-read int|null $notes_count */ class Budget extends Model { @@ -113,7 +113,7 @@ class Budget extends Model public static function routeBinder(string $value): Budget { if (auth()->check()) { - $budgetId = (int)$value; + $budgetId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Budget $budget */ diff --git a/app/Models/BudgetLimit.php b/app/Models/BudgetLimit.php index 77bb3eee4c..2c398d4223 100644 --- a/app/Models/BudgetLimit.php +++ b/app/Models/BudgetLimit.php @@ -90,7 +90,7 @@ class BudgetLimit extends Model public static function routeBinder(string $value): BudgetLimit { if (auth()->check()) { - $budgetLimitId = (int)$value; + $budgetLimitId = (int) $value; $budgetLimit = self::where('budget_limits.id', $budgetLimitId) ->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id') ->where('budgets.user_id', auth()->user()->id) diff --git a/app/Models/Category.php b/app/Models/Category.php index f7620877a9..369ded30b0 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -104,7 +104,7 @@ class Category extends Model public static function routeBinder(string $value): Category { if (auth()->check()) { - $categoryId = (int)$value; + $categoryId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Category $category */ diff --git a/app/Models/LinkType.php b/app/Models/LinkType.php index cf6abf70a9..8f1d0f1ce7 100644 --- a/app/Models/LinkType.php +++ b/app/Models/LinkType.php @@ -93,7 +93,7 @@ class LinkType extends Model public static function routeBinder(string $value): LinkType { if (auth()->check()) { - $linkTypeId = (int)$value; + $linkTypeId = (int) $value; $linkType = self::find($linkTypeId); if (null !== $linkType) { return $linkType; diff --git a/app/Models/ObjectGroup.php b/app/Models/ObjectGroup.php index 4578efc14e..b641c1bd16 100644 --- a/app/Models/ObjectGroup.php +++ b/app/Models/ObjectGroup.php @@ -90,7 +90,7 @@ class ObjectGroup extends Model public static function routeBinder(string $value): ObjectGroup { if (auth()->check()) { - $objectGroupId = (int)$value; + $objectGroupId = (int) $value; /** @var ObjectGroup $objectGroup */ $objectGroup = self::where('object_groups.id', $objectGroupId) ->where('object_groups.user_id', auth()->user()->id)->first(); diff --git a/app/Models/PiggyBank.php b/app/Models/PiggyBank.php index 2288ae7ef6..3526816a63 100644 --- a/app/Models/PiggyBank.php +++ b/app/Models/PiggyBank.php @@ -115,7 +115,7 @@ class PiggyBank extends Model public static function routeBinder(string $value): PiggyBank { if (auth()->check()) { - $piggyBankId = (int)$value; + $piggyBankId = (int) $value; $piggyBank = self::where('piggy_banks.id', $piggyBankId) ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('accounts.user_id', auth()->user()->id)->first(['piggy_banks.*']); @@ -186,6 +186,6 @@ class PiggyBank extends Model */ public function setTargetamountAttribute($value): void { - $this->attributes['targetamount'] = (string)$value; + $this->attributes['targetamount'] = (string) $value; } } diff --git a/app/Models/PiggyBankEvent.php b/app/Models/PiggyBankEvent.php index f3b71fe2af..0429630ee8 100644 --- a/app/Models/PiggyBankEvent.php +++ b/app/Models/PiggyBankEvent.php @@ -86,7 +86,7 @@ class PiggyBankEvent extends Model */ public function setAmountAttribute($value): void { - $this->attributes['amount'] = (string)$value; + $this->attributes['amount'] = (string) $value; } /** diff --git a/app/Models/PiggyBankRepetition.php b/app/Models/PiggyBankRepetition.php index 839c15cf99..de87bac9c1 100644 --- a/app/Models/PiggyBankRepetition.php +++ b/app/Models/PiggyBankRepetition.php @@ -31,14 +31,14 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * FireflyIII\Models\PiggyBankRepetition * - * @property int $id + * @property int $id * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at - * @property int $piggy_bank_id + * @property int $piggy_bank_id * @property \Illuminate\Support\Carbon|null $startdate * @property \Illuminate\Support\Carbon|null $targetdate - * @property string $currentamount - * @property-read PiggyBank $piggyBank + * @property string $currentamount + * @property-read PiggyBank $piggyBank * @method static EloquentBuilder|PiggyBankRepetition newModelQuery() * @method static EloquentBuilder|PiggyBankRepetition newQuery() * @method static EloquentBuilder|PiggyBankRepetition onDates(Carbon $start, Carbon $target) @@ -124,6 +124,6 @@ class PiggyBankRepetition extends Model */ public function setCurrentamountAttribute($value): void { - $this->attributes['currentamount'] = (string)$value; + $this->attributes['currentamount'] = (string) $value; } } diff --git a/app/Models/Recurrence.php b/app/Models/Recurrence.php index f96ff20744..6a723f3b78 100644 --- a/app/Models/Recurrence.php +++ b/app/Models/Recurrence.php @@ -130,7 +130,7 @@ class Recurrence extends Model public static function routeBinder(string $value): Recurrence { if (auth()->check()) { - $recurrenceId = (int)$value; + $recurrenceId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Recurrence $recurrence */ diff --git a/app/Models/Rule.php b/app/Models/Rule.php index 732b3d6cd2..55bd858171 100644 --- a/app/Models/Rule.php +++ b/app/Models/Rule.php @@ -111,7 +111,7 @@ class Rule extends Model public static function routeBinder(string $value): Rule { if (auth()->check()) { - $ruleId = (int)$value; + $ruleId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Rule $rule */ diff --git a/app/Models/RuleGroup.php b/app/Models/RuleGroup.php index b88d5f7bcf..aa2a370b71 100644 --- a/app/Models/RuleGroup.php +++ b/app/Models/RuleGroup.php @@ -102,7 +102,7 @@ class RuleGroup extends Model public static function routeBinder(string $value): RuleGroup { if (auth()->check()) { - $ruleGroupId = (int)$value; + $ruleGroupId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var RuleGroup $ruleGroup */ diff --git a/app/Models/Tag.php b/app/Models/Tag.php index 8aa8b656b7..3168dd3634 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -113,7 +113,7 @@ class Tag extends Model public static function routeBinder(string $value): Tag { if (auth()->check()) { - $tagId = (int)$value; + $tagId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Tag $tag */ diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 5f2d3019e7..58d4d9a6cf 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -236,7 +236,7 @@ class Transaction extends Model */ public function setAmountAttribute($value): void { - $this->attributes['amount'] = (string)$value; + $this->attributes['amount'] = (string) $value; } /** diff --git a/app/Models/TransactionCurrency.php b/app/Models/TransactionCurrency.php index 4b2c12bb04..3af5058281 100644 --- a/app/Models/TransactionCurrency.php +++ b/app/Models/TransactionCurrency.php @@ -97,7 +97,7 @@ class TransactionCurrency extends Model public static function routeBinder(string $value): TransactionCurrency { if (auth()->check()) { - $currencyId = (int)$value; + $currencyId = (int) $value; $currency = self::find($currencyId); if (null !== $currency) { return $currency; diff --git a/app/Models/TransactionGroup.php b/app/Models/TransactionGroup.php index 10a356b41d..aac8eac199 100644 --- a/app/Models/TransactionGroup.php +++ b/app/Models/TransactionGroup.php @@ -94,7 +94,7 @@ class TransactionGroup extends Model public static function routeBinder(string $value): TransactionGroup { if (auth()->check()) { - $groupId = (int)$value; + $groupId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var TransactionGroup $group */ diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php index af8e072e96..b39283b1af 100644 --- a/app/Models/TransactionJournal.php +++ b/app/Models/TransactionJournal.php @@ -160,7 +160,7 @@ class TransactionJournal extends Model public static function routeBinder(string $value): TransactionJournal { if (auth()->check()) { - $journalId = (int)$value; + $journalId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var TransactionJournal $journal */ diff --git a/app/Models/TransactionJournalLink.php b/app/Models/TransactionJournalLink.php index f7ecd1b5d2..c37dbcdb4b 100644 --- a/app/Models/TransactionJournalLink.php +++ b/app/Models/TransactionJournalLink.php @@ -87,7 +87,7 @@ class TransactionJournalLink extends Model public static function routeBinder(string $value): TransactionJournalLink { if (auth()->check()) { - $linkId = (int)$value; + $linkId = (int) $value; $link = self::where('journal_links.id', $linkId) ->leftJoin('transaction_journals as t_a', 't_a.id', '=', 'source_id') ->leftJoin('transaction_journals as t_b', 't_b.id', '=', 'destination_id') diff --git a/app/Models/TransactionType.php b/app/Models/TransactionType.php index 6d37d908be..6a6a68b759 100644 --- a/app/Models/TransactionType.php +++ b/app/Models/TransactionType.php @@ -58,20 +58,20 @@ class TransactionType extends Model { use SoftDeletes; - /** @var string */ - public const WITHDRAWAL = 'Withdrawal'; /** @var string */ public const DEPOSIT = 'Deposit'; /** @var string */ - public const TRANSFER = 'Transfer'; + public const INVALID = 'Invalid'; + /** @var string */ + public const LIABILITY_CREDIT = 'Liability credit'; /** @var string */ public const OPENING_BALANCE = 'Opening balance'; /** @var string */ public const RECONCILIATION = 'Reconciliation'; /** @var string */ - public const INVALID = 'Invalid'; + public const TRANSFER = 'Transfer'; /** @var string */ - public const LIABILITY_CREDIT = 'Liability credit'; + public const WITHDRAWAL = 'Withdrawal'; /** @var string[] */ protected $casts = [ diff --git a/app/Models/UserRole.php b/app/Models/UserRole.php index ca51556d1c..ce16b69013 100644 --- a/app/Models/UserRole.php +++ b/app/Models/UserRole.php @@ -53,14 +53,14 @@ use Illuminate\Support\Carbon; */ class UserRole extends Model { - public const READ_ONLY = 'ro'; - public const CHANGE_TRANSACTIONS = 'change_tx'; - public const CHANGE_RULES = 'change_rules'; public const CHANGE_PIGGY_BANKS = 'change_piggies'; public const CHANGE_REPETITIONS = 'change_reps'; - public const VIEW_REPORTS = 'view_reports'; + public const CHANGE_RULES = 'change_rules'; + public const CHANGE_TRANSACTIONS = 'change_tx'; public const FULL = 'full'; public const OWNER = 'owner'; + public const READ_ONLY = 'ro'; + public const VIEW_REPORTS = 'view_reports'; protected $fillable = ['title']; /** diff --git a/app/Models/Webhook.php b/app/Models/Webhook.php index 1eb3fcb069..f036fb3abe 100644 --- a/app/Models/Webhook.php +++ b/app/Models/Webhook.php @@ -80,17 +80,17 @@ class Webhook extends Model // dont forget to update the config in firefly.php // triggers - public const TRIGGER_STORE_TRANSACTION = 100; - public const TRIGGER_UPDATE_TRANSACTION = 110; - public const TRIGGER_DESTROY_TRANSACTION = 120; - - // actions - public const RESPONSE_TRANSACTIONS = 200; + public const DELIVERY_JSON = 300; public const RESPONSE_ACCOUNTS = 210; public const RESPONSE_NONE = 220; + // actions + public const RESPONSE_TRANSACTIONS = 200; + public const TRIGGER_DESTROY_TRANSACTION = 120; + public const TRIGGER_STORE_TRANSACTION = 100; + // delivery - public const DELIVERY_JSON = 300; + public const TRIGGER_UPDATE_TRANSACTION = 110; protected $casts = [ 'active' => 'boolean', @@ -111,7 +111,7 @@ class Webhook extends Model public static function routeBinder(string $value): Webhook { if (auth()->check()) { - $webhookId = (int)$value; + $webhookId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var Webhook $webhook */ diff --git a/app/Models/WebhookAttempt.php b/app/Models/WebhookAttempt.php index 5397402480..112c5bb468 100644 --- a/app/Models/WebhookAttempt.php +++ b/app/Models/WebhookAttempt.php @@ -75,7 +75,7 @@ class WebhookAttempt extends Model public static function routeBinder(string $value): WebhookAttempt { if (auth()->check()) { - $attemptId = (int)$value; + $attemptId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var WebhookAttempt $attempt */ diff --git a/app/Models/WebhookMessage.php b/app/Models/WebhookMessage.php index 23d5b5cb93..83e3e5da3f 100644 --- a/app/Models/WebhookMessage.php +++ b/app/Models/WebhookMessage.php @@ -89,7 +89,7 @@ class WebhookMessage extends Model public static function routeBinder(string $value): WebhookMessage { if (auth()->check()) { - $messageId = (int)$value; + $messageId = (int) $value; /** @var User $user */ $user = auth()->user(); /** @var WebhookMessage $message */ diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index f027a2ec2f..0e867b4732 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -48,7 +48,6 @@ use Laravel\Passport\Client; use Laravel\Passport\Events\AccessTokenCreated; use Log; use Mail; -use Request; use Session; /** @@ -76,7 +75,7 @@ class EventServiceProvider extends ServiceProvider 'FireflyIII\Handlers\Events\UserEventHandler@checkSingleUserIsAdmin', 'FireflyIII\Handlers\Events\UserEventHandler@demoUserBackToEnglish', ], - ActuallyLoggedIn::class => [ + ActuallyLoggedIn::class => [ 'FireflyIII\Handlers\Events\UserEventHandler@storeUserIPAddress', ], DetectedNewIPAddress::class => [ @@ -137,7 +136,7 @@ class EventServiceProvider extends ServiceProvider ], // bill related events: - WarnUserAboutBill::class => [ + WarnUserAboutBill::class => [ 'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill', ], ]; @@ -171,14 +170,14 @@ class EventServiceProvider extends ServiceProvider static function (Client $oauthClient) { /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); - $user = $repository->find((int)$oauthClient->user_id); + $user = $repository->find((int) $oauthClient->user_id); if (null === $user) { Log::info('OAuth client generated but no user associated.'); return; } - $email = $user->email; + $email = $user->email; // see if user has alternative email address: $pref = app('preferences')->getForUser($user, 'remote_guard_alt_email'); diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 72a0701f5f..cdc709d178 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -198,21 +198,6 @@ class AccountRepository implements AccountRepositoryInterface return $account; } - /** - * @param Account $account - * - * @return TransactionCurrency|null - */ - public function getAccountCurrency(Account $account): ?TransactionCurrency - { - $currencyId = (int)$this->getMetaValue($account, 'currency_id'); - if ($currencyId > 0) { - return TransactionCurrency::find($currencyId); - } - - return null; - } - /** * Return account type or null if not found. * @@ -244,38 +229,6 @@ class AccountRepository implements AccountRepositoryInterface return $query->get(['accounts.*']); } - /** - * @param array $types - * @param array|null $sort - * - * @return Collection - */ - public function getAccountsByType(array $types, ?array $sort = []): Collection - { - $res = array_intersect([AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT], $types); - $query = $this->user->accounts(); - if (!empty($types)) { - $query->accountTypeIn($types); - } - - // add sort parameters. At this point they're filtered to allowed fields to sort by: - if (!empty($sort)) { - foreach ($sort as $param) { - $query->orderBy($param[0], $param[1]); - } - } - - if (empty($sort)) { - if (!empty($res)) { - $query->orderBy('accounts.order', 'ASC'); - } - $query->orderBy('accounts.active', 'DESC'); - $query->orderBy('accounts.name', 'ASC'); - } - - return $query->get(['accounts.*']); - } - /** * @param array $types * @@ -384,31 +337,6 @@ class AccountRepository implements AccountRepositoryInterface return $account->locations()->first(); } - /** - * Return meta value for account. Null if not found. - * - * @param Account $account - * @param string $field - * - * @return null|string - */ - public function getMetaValue(Account $account, string $field): ?string - { - $result = $account->accountMeta->filter( - function (AccountMeta $meta) use ($field) { - return strtolower($meta->name) === strtolower($field); - } - ); - if (0 === $result->count()) { - return null; - } - if (1 === $result->count()) { - return (string)$result->first()->data; - } - - return null; - } - /** * Get note text or null. * @@ -427,20 +355,6 @@ class AccountRepository implements AccountRepositoryInterface return $note->text; } - /** - * @param Account $account - * - * @return TransactionJournal|null - */ - public function getOpeningBalance(Account $account): ?TransactionJournal - { - return TransactionJournal - ::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transactions.account_id', $account->id) - ->transactionTypes([TransactionType::OPENING_BALANCE]) - ->first(['transaction_journals.*']); - } - /** * Returns the amount of the opening balance for this account. * @@ -463,7 +377,7 @@ class AccountRepository implements AccountRepositoryInterface return null; } - return (string)$transaction->amount; + return (string) $transaction->amount; } /** @@ -498,6 +412,20 @@ class AccountRepository implements AccountRepositoryInterface return $journal?->transactionGroup; } + /** + * @param Account $account + * + * @return TransactionJournal|null + */ + public function getOpeningBalance(Account $account): ?TransactionJournal + { + return TransactionJournal + ::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transactions.account_id', $account->id) + ->transactionTypes([TransactionType::OPENING_BALANCE]) + ->first(['transaction_journals.*']); + } + /** * @param Account $account * @@ -550,6 +478,46 @@ class AccountRepository implements AccountRepositoryInterface return $factory->create($data); } + /** + * @param Account $account + * + * @return TransactionCurrency|null + */ + public function getAccountCurrency(Account $account): ?TransactionCurrency + { + $currencyId = (int) $this->getMetaValue($account, 'currency_id'); + if ($currencyId > 0) { + return TransactionCurrency::find($currencyId); + } + + return null; + } + + /** + * Return meta value for account. Null if not found. + * + * @param Account $account + * @param string $field + * + * @return null|string + */ + public function getMetaValue(Account $account, string $field): ?string + { + $result = $account->accountMeta->filter( + function (AccountMeta $meta) use ($field) { + return strtolower($meta->name) === strtolower($field); + } + ); + if (0 === $result->count()) { + return null; + } + if (1 === $result->count()) { + return (string) $result->first()->data; + } + + return null; + } + /** * @inheritDoc */ @@ -558,8 +526,8 @@ class AccountRepository implements AccountRepositoryInterface $info = $account->transactions()->get(['transaction_currency_id', 'foreign_currency_id'])->toArray(); $currencyIds = []; foreach ($info as $entry) { - $currencyIds[] = (int)$entry['transaction_currency_id']; - $currencyIds[] = (int)$entry['foreign_currency_id']; + $currencyIds[] = (int) $entry['transaction_currency_id']; + $currencyIds[] = (int) $entry['foreign_currency_id']; } $currencyIds = array_unique($currencyIds); @@ -590,19 +558,65 @@ class AccountRepository implements AccountRepositoryInterface AccountType::MORTGAGE => [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], ]; if (array_key_exists(ucfirst($type), $sets)) { - $order = (int)$this->getAccountsByType($sets[ucfirst($type)])->max('order'); + $order = (int) $this->getAccountsByType($sets[ucfirst($type)])->max('order'); Log::debug(sprintf('Return max order of "%s" set: %d', $type, $order)); return $order; } $specials = [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION]; - $order = (int)$this->getAccountsByType($specials)->max('order'); + $order = (int) $this->getAccountsByType($specials)->max('order'); Log::debug(sprintf('Return max order of "%s" set (specials!): %d', $type, $order)); return $order; } + /** + * @param array $types + * @param array|null $sort + * + * @return Collection + */ + public function getAccountsByType(array $types, ?array $sort = []): Collection + { + $res = array_intersect([AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT], $types); + $query = $this->user->accounts(); + if (!empty($types)) { + $query->accountTypeIn($types); + } + + // add sort parameters. At this point they're filtered to allowed fields to sort by: + if (!empty($sort)) { + foreach ($sort as $param) { + $query->orderBy($param[0], $param[1]); + } + } + + if (empty($sort)) { + if (!empty($res)) { + $query->orderBy('accounts.order', 'ASC'); + } + $query->orderBy('accounts.active', 'DESC'); + $query->orderBy('accounts.name', 'ASC'); + } + + return $query->get(['accounts.*']); + } + + /** + * Returns the date of the very first transaction in this account. + * + * @param Account $account + * + * @return Carbon|null + */ + public function oldestJournalDate(Account $account): ?Carbon + { + $journal = $this->oldestJournal($account); + + return $journal?->date; + } + /** * Returns the date of the very first transaction in this account. * @@ -620,26 +634,12 @@ class AccountRepository implements AccountRepositoryInterface ->orderBy('transaction_journals.id', 'ASC') ->first(['transaction_journals.id']); if (null !== $first) { - return TransactionJournal::find((int)$first->id); + return TransactionJournal::find((int) $first->id); } return null; } - /** - * Returns the date of the very first transaction in this account. - * - * @param Account $account - * - * @return Carbon|null - */ - public function oldestJournalDate(Account $account): ?Carbon - { - $journal = $this->oldestJournal($account); - - return $journal?->date; - } - /** * @inheritDoc */ @@ -661,7 +661,7 @@ class AccountRepository implements AccountRepositoryInterface $account->order = 0; continue; } - if ($index !== (int)$account->order) { + if ($index !== (int) $account->order) { 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(); diff --git a/app/Repositories/Account/AccountTasker.php b/app/Repositories/Account/AccountTasker.php index c0702b41f1..c58ef0ed74 100644 --- a/app/Repositories/Account/AccountTasker.php +++ b/app/Repositories/Account/AccountTasker.php @@ -138,7 +138,7 @@ class AccountTasker implements AccountTaskerInterface // Obtain a list of columns $sum = []; foreach ($report['accounts'] as $accountId => $row) { - $sum[$accountId] = (float)$row['sum']; + $sum[$accountId] = (float) $row['sum']; } array_multisort($sum, SORT_ASC, $report['accounts']); @@ -146,6 +146,67 @@ class AccountTasker implements AccountTaskerInterface return $report; } + /** + * @param array $array + * + * @return array + */ + private function groupExpenseByDestination(array $array): array + { + $defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user); + /** @var CurrencyRepositoryInterface $currencyRepos */ + $currencyRepos = app(CurrencyRepositoryInterface::class); + $currencies = [$defaultCurrency->id => $defaultCurrency,]; + $report = [ + 'accounts' => [], + 'sums' => [], + ]; + + /** @var array $journal */ + foreach ($array as $journal) { + $sourceId = (int) $journal['destination_account_id']; + $currencyId = (int) $journal['currency_id']; + $key = sprintf('%s-%s', $sourceId, $currencyId); + $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepos->find($currencyId); + $report['accounts'][$key] = $report['accounts'][$key] ?? [ + 'id' => $sourceId, + 'name' => $journal['destination_account_name'], + 'sum' => '0', + 'average' => '0', + 'count' => 0, + 'currency_id' => $currencies[$currencyId]->id, + 'currency_name' => $currencies[$currencyId]->name, + 'currency_symbol' => $currencies[$currencyId]->symbol, + 'currency_code' => $currencies[$currencyId]->code, + 'currency_decimal_places' => $currencies[$currencyId]->decimal_places, + ]; + $report['accounts'][$key]['sum'] = bcadd($report['accounts'][$key]['sum'], $journal['amount']); + + Log::debug(sprintf('Sum for %s is now %s', $journal['destination_account_name'], $report['accounts'][$key]['sum'])); + + ++$report['accounts'][$key]['count']; + } + + // do averages and sums. + foreach (array_keys($report['accounts']) as $key) { + if ($report['accounts'][$key]['count'] > 1) { + $report['accounts'][$key]['average'] = bcdiv($report['accounts'][$key]['sum'], (string) $report['accounts'][$key]['count']); + } + $currencyId = $report['accounts'][$key]['currency_id']; + $report['sums'][$currencyId] = $report['sums'][$currencyId] ?? [ + 'sum' => '0', + 'currency_id' => $report['accounts'][$key]['currency_id'], + 'currency_name' => $report['accounts'][$key]['currency_name'], + 'currency_symbol' => $report['accounts'][$key]['currency_symbol'], + 'currency_code' => $report['accounts'][$key]['currency_code'], + 'currency_decimal_places' => $report['accounts'][$key]['currency_decimal_places'], + ]; + $report['sums'][$currencyId]['sum'] = bcadd($report['sums'][$currencyId]['sum'], $report['accounts'][$key]['sum']); + } + + return $report; + } + /** * @param Carbon $start * @param Carbon $end @@ -170,7 +231,7 @@ class AccountTasker implements AccountTaskerInterface // Obtain a list of columns $sum = []; foreach ($report['accounts'] as $accountId => $row) { - $sum[$accountId] = (float)$row['sum']; + $sum[$accountId] = (float) $row['sum']; } array_multisort($sum, SORT_DESC, $report['accounts']); @@ -178,75 +239,6 @@ class AccountTasker implements AccountTaskerInterface return $report; } - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param array $array - * - * @return array - */ - private function groupExpenseByDestination(array $array): array - { - $defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user); - /** @var CurrencyRepositoryInterface $currencyRepos */ - $currencyRepos = app(CurrencyRepositoryInterface::class); - $currencies = [$defaultCurrency->id => $defaultCurrency,]; - $report = [ - 'accounts' => [], - 'sums' => [], - ]; - - /** @var array $journal */ - foreach ($array as $journal) { - $sourceId = (int)$journal['destination_account_id']; - $currencyId = (int)$journal['currency_id']; - $key = sprintf('%s-%s', $sourceId, $currencyId); - $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepos->find($currencyId); - $report['accounts'][$key] = $report['accounts'][$key] ?? [ - 'id' => $sourceId, - 'name' => $journal['destination_account_name'], - 'sum' => '0', - 'average' => '0', - 'count' => 0, - 'currency_id' => $currencies[$currencyId]->id, - 'currency_name' => $currencies[$currencyId]->name, - 'currency_symbol' => $currencies[$currencyId]->symbol, - 'currency_code' => $currencies[$currencyId]->code, - 'currency_decimal_places' => $currencies[$currencyId]->decimal_places, - ]; - $report['accounts'][$key]['sum'] = bcadd($report['accounts'][$key]['sum'], $journal['amount']); - - Log::debug(sprintf('Sum for %s is now %s', $journal['destination_account_name'], $report['accounts'][$key]['sum'])); - - ++$report['accounts'][$key]['count']; - } - - // do averages and sums. - foreach (array_keys($report['accounts']) as $key) { - if ($report['accounts'][$key]['count'] > 1) { - $report['accounts'][$key]['average'] = bcdiv($report['accounts'][$key]['sum'], (string)$report['accounts'][$key]['count']); - } - $currencyId = $report['accounts'][$key]['currency_id']; - $report['sums'][$currencyId] = $report['sums'][$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $report['accounts'][$key]['currency_id'], - 'currency_name' => $report['accounts'][$key]['currency_name'], - 'currency_symbol' => $report['accounts'][$key]['currency_symbol'], - 'currency_code' => $report['accounts'][$key]['currency_code'], - 'currency_decimal_places' => $report['accounts'][$key]['currency_decimal_places'], - ]; - $report['sums'][$currencyId]['sum'] = bcadd($report['sums'][$currencyId]['sum'], $report['accounts'][$key]['sum']); - } - - return $report; - } - /** * @param array $array * @@ -265,8 +257,8 @@ class AccountTasker implements AccountTaskerInterface /** @var array $journal */ foreach ($array as $journal) { - $sourceId = (int)$journal['source_account_id']; - $currencyId = (int)$journal['currency_id']; + $sourceId = (int) $journal['source_account_id']; + $currencyId = (int) $journal['currency_id']; $key = sprintf('%s-%s', $sourceId, $currencyId); if (!array_key_exists($key, $report['accounts'])) { $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepos->find($currencyId); @@ -290,7 +282,7 @@ class AccountTasker implements AccountTaskerInterface // do averages and sums. foreach (array_keys($report['accounts']) as $key) { if ($report['accounts'][$key]['count'] > 1) { - $report['accounts'][$key]['average'] = bcdiv($report['accounts'][$key]['sum'], (string)$report['accounts'][$key]['count']); + $report['accounts'][$key]['average'] = bcdiv($report['accounts'][$key]['sum'], (string) $report['accounts'][$key]['count']); } $currencyId = $report['accounts'][$key]['currency_id']; $report['sums'][$currencyId] = $report['sums'][$currencyId] ?? [ @@ -306,4 +298,12 @@ class AccountTasker implements AccountTaskerInterface return $report; } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } } diff --git a/app/Repositories/Account/OperationsRepository.php b/app/Repositories/Account/OperationsRepository.php index 0fbbca6fed..5f7b342f80 100644 --- a/app/Repositories/Account/OperationsRepository.php +++ b/app/Repositories/Account/OperationsRepository.php @@ -56,109 +56,6 @@ class OperationsRepository implements OperationsRepositoryInterface return $this->sortByCurrency($journals, 'negative'); } - /** - * This method returns a list of all the deposit transaction journals (as arrays) set in that period - * which have the specified accounts. It's grouped per currency, with as few details in the array - * as possible. Amounts are always positive. - * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * - * @return array - */ - public function listIncome(Carbon $start, Carbon $end, ?Collection $accounts = null): array - { - $journals = $this->getTransactions($start, $end, $accounts, TransactionType::DEPOSIT); - - return $this->sortByCurrency($journals, 'positive'); - - } - - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @inheritDoc - */ - public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null - ): array { - $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); - - return $this->groupByCurrency($journals, 'negative'); - - } - - /** - * @inheritDoc - */ - public function sumExpensesByDestination( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null - ): array { - $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); - - return $this->groupByDirection($journals, 'destination', 'negative'); - } - - /** - * @inheritDoc - */ - public function sumExpensesBySource( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null - ): array { - $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); - - return $this->groupByDirection($journals, 'source', 'negative'); - } - - /** - * @inheritDoc - */ - public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null - ): array { - $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); - - return $this->groupByCurrency($journals, 'positive'); - } - - /** - * @inheritDoc - */ - public function sumIncomeByDestination( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null - ): array { - $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); - - return $this->groupByDirection($journals, 'destination', 'positive'); - } - - /** - * @inheritDoc - */ - public function sumIncomeBySource( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null - ): array { - $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); - - return $this->groupByDirection($journals, 'source', 'positive'); - } - - /** - * @inheritDoc - */ - public function sumTransfers(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array - { - $journals = $this->getTransactionsForSum(TransactionType::TRANSFER, $start, $end, $accounts, null, $currency); - - return $this->groupByEither($journals); - } - - /** * Collect transactions with some parameters * @@ -190,8 +87,8 @@ class OperationsRepository implements OperationsRepositoryInterface { $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; - $journalId = (int)$journal['transaction_journal_id']; + $currencyId = (int) $journal['currency_id']; + $journalId = (int) $journal['transaction_journal_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'currency_id' => $journal['currency_id'], @@ -203,7 +100,7 @@ class OperationsRepository implements OperationsRepositoryInterface ]; $array[$currencyId]['transaction_journals'][$journalId] = [ - 'amount' => app('steam')->$direction((string)$journal['amount']), + 'amount' => app('steam')->$direction((string) $journal['amount']), 'date' => $journal['date'], 'transaction_journal_id' => $journalId, 'budget_name' => $journal['budget_name'], @@ -223,6 +120,45 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } + /** + * This method returns a list of all the deposit transaction journals (as arrays) set in that period + * which have the specified accounts. It's grouped per currency, with as few details in the array + * as possible. Amounts are always positive. + * + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * + * @return array + */ + public function listIncome(Carbon $start, Carbon $end, ?Collection $accounts = null): array + { + $journals = $this->getTransactions($start, $end, $accounts, TransactionType::DEPOSIT); + + return $this->sortByCurrency($journals, 'positive'); + + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @inheritDoc + */ + public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + ): array + { + $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); + + return $this->groupByCurrency($journals, 'negative'); + + } + /** * @param Carbon $start * @param Carbon $end @@ -236,7 +172,8 @@ class OperationsRepository implements OperationsRepositoryInterface private function getTransactionsForSum( string $type, Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $opposing = null, ?TransactionCurrency $currency = null - ): array { + ): array + { $start->startOfDay(); $end->endOfDay(); @@ -314,7 +251,7 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'sum' => '0', 'currency_id' => $currencyId, @@ -326,7 +263,7 @@ class OperationsRepository implements OperationsRepositoryInterface $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->$direction($journal['amount'])); // also do foreign amount: - $foreignId = (int)$journal['foreign_currency_id']; + $foreignId = (int) $journal['foreign_currency_id']; if (0 !== $foreignId) { $array[$foreignId] = $array[$foreignId] ?? [ 'sum' => '0', @@ -343,6 +280,18 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } + /** + * @inheritDoc + */ + public function sumExpensesByDestination( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + ): array + { + $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); + + return $this->groupByDirection($journals, 'destination', 'negative'); + } + /** * @param array $journals * @param string $direction @@ -368,10 +317,10 @@ class OperationsRepository implements OperationsRepositoryInterface 'currency_code' => $journal['currency_code'], 'currency_decimal_places' => $journal['currency_decimal_places'], ]; - $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->$method((string)$journal['amount'])); + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->$method((string) $journal['amount'])); // also do foreign amount: - if (0 !== (int)$journal['foreign_currency_id']) { + if (0 !== (int) $journal['foreign_currency_id']) { $key = sprintf('%s-%s', $journal[$idKey], $journal['foreign_currency_id']); $array[$key] = $array[$key] ?? [ 'id' => $journal[$idKey], @@ -383,13 +332,70 @@ class OperationsRepository implements OperationsRepositoryInterface 'currency_code' => $journal['foreign_currency_code'], 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], ]; - $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->$method((string)$journal['foreign_amount'])); + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->$method((string) $journal['foreign_amount'])); } } return $array; } + /** + * @inheritDoc + */ + public function sumExpensesBySource( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + ): array + { + $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); + + return $this->groupByDirection($journals, 'source', 'negative'); + } + + /** + * @inheritDoc + */ + public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null + ): array + { + $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); + + return $this->groupByCurrency($journals, 'positive'); + } + + /** + * @inheritDoc + */ + public function sumIncomeByDestination( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null + ): array + { + $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); + + return $this->groupByDirection($journals, 'destination', 'positive'); + } + + /** + * @inheritDoc + */ + public function sumIncomeBySource( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null + ): array + { + $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); + + return $this->groupByDirection($journals, 'source', 'positive'); + } + + /** + * @inheritDoc + */ + public function sumTransfers(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array + { + $journals = $this->getTransactionsForSum(TransactionType::TRANSFER, $start, $end, $accounts, null, $currency); + + return $this->groupByEither($journals); + } + /** * @param array $journals * @@ -404,9 +410,9 @@ class OperationsRepository implements OperationsRepositoryInterface } $final = []; foreach ($return as $array) { - $array['difference_float'] = (float)$array['difference']; - $array['in_float'] = (float)$array['in']; - $array['out_float'] = (float)$array['out']; + $array['difference_float'] = (float) $array['difference']; + $array['in_float'] = (float) $array['in']; + $array['out_float'] = (float) $array['out']; $final[] = $array; } @@ -430,7 +436,7 @@ class OperationsRepository implements OperationsRepositoryInterface // source first $return[$sourceKey] = $return[$sourceKey] ?? [ - 'id' => (string)$sourceId, + 'id' => (string) $sourceId, 'name' => $journal['source_account_name'], 'difference' => '0', 'difference_float' => 0, @@ -438,13 +444,13 @@ class OperationsRepository implements OperationsRepositoryInterface 'in_float' => 0, 'out' => '0', 'out_float' => 0, - 'currency_id' => (string)$currencyId, + 'currency_id' => (string) $currencyId, 'currency_code' => $journal['currency_code'], ]; // dest next: $return[$destKey] = $return[$destKey] ?? [ - 'id' => (string)$destinationId, + 'id' => (string) $destinationId, 'name' => $journal['destination_account_name'], 'difference' => '0', 'difference_float' => 0, @@ -452,7 +458,7 @@ class OperationsRepository implements OperationsRepositoryInterface 'in_float' => 0, 'out' => '0', 'out_float' => 0, - 'currency_id' => (string)$currencyId, + 'currency_id' => (string) $currencyId, 'currency_code' => $journal['currency_code'], ]; @@ -474,7 +480,7 @@ class OperationsRepository implements OperationsRepositoryInterface // same as above: // source first $return[$sourceKey] = $return[$sourceKey] ?? [ - 'id' => (string)$sourceId, + 'id' => (string) $sourceId, 'name' => $journal['source_account_name'], 'difference' => '0', 'difference_float' => 0, @@ -482,13 +488,13 @@ class OperationsRepository implements OperationsRepositoryInterface 'in_float' => 0, 'out' => '0', 'out_float' => 0, - 'currency_id' => (string)$currencyId, + 'currency_id' => (string) $currencyId, 'currency_code' => $journal['foreign_currency_code'], ]; // dest next: $return[$destKey] = $return[$destKey] ?? [ - 'id' => (string)$destinationId, + 'id' => (string) $destinationId, 'name' => $journal['destination_account_name'], 'difference' => '0', 'difference_float' => 0, @@ -496,7 +502,7 @@ class OperationsRepository implements OperationsRepositoryInterface 'in_float' => 0, 'out' => '0', 'out_float' => 0, - 'currency_id' => (string)$currencyId, + 'currency_id' => (string) $currencyId, 'currency_code' => $journal['foreign_currency_code'], ]; // source account? money goes out! (same as above) diff --git a/app/Repositories/Attachment/AttachmentRepository.php b/app/Repositories/Attachment/AttachmentRepository.php index 6a74a5e064..b6dc30e99d 100644 --- a/app/Repositories/Attachment/AttachmentRepository.php +++ b/app/Repositories/Attachment/AttachmentRepository.php @@ -33,7 +33,6 @@ use FireflyIII\User; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Storage; -use Log; /** * Class AttachmentRepository. diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index c37c858820..e0ef3bd456 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -55,6 +55,36 @@ class BillRepository implements BillRepositoryInterface private User $user; + /** + * @inheritDoc + */ + public function billEndsWith(string $query, int $limit): Collection + { + $search = $this->user->bills(); + if ('' !== $query) { + $search->where('name', 'LIKE', sprintf('%%%s', $query)); + } + $search->orderBy('name', 'ASC') + ->where('active', true); + + return $search->take($limit)->get(); + } + + /** + * @inheritDoc + */ + public function billStartsWith(string $query, int $limit): Collection + { + $search = $this->user->bills(); + if ('' !== $query) { + $search->where('name', 'LIKE', sprintf('%s%%', $query)); + } + $search->orderBy('name', 'ASC') + ->where('active', true); + + return $search->take($limit)->get(); + } + /** * Correct order of piggies in case of issues. */ @@ -63,7 +93,7 @@ class BillRepository implements BillRepositoryInterface $set = $this->user->bills()->orderBy('order', 'ASC')->get(); $current = 1; foreach ($set as $bill) { - if ((int)$bill->order !== $current) { + if ((int) $bill->order !== $current) { $bill->order = $current; $bill->save(); } @@ -95,18 +125,6 @@ class BillRepository implements BillRepositoryInterface $this->user->bills()->delete(); } - /** - * Find a bill by ID. - * - * @param int $billId - * - * @return Bill|null - */ - public function find(int $billId): ?Bill - { - return $this->user->bills()->find($billId); - } - /** * Find bill by parameters. * @@ -118,7 +136,7 @@ class BillRepository implements BillRepositoryInterface public function findBill(?int $billId, ?string $billName): ?Bill { if (null !== $billId) { - $searchResult = $this->find((int)$billId); + $searchResult = $this->find((int) $billId); if (null !== $searchResult) { Log::debug(sprintf('Found bill based on #%d, will return it.', $billId)); @@ -126,7 +144,7 @@ class BillRepository implements BillRepositoryInterface } } if (null !== $billName) { - $searchResult = $this->findByName((string)$billName); + $searchResult = $this->findByName((string) $billName); if (null !== $searchResult) { Log::debug(sprintf('Found bill based on "%s", will return it.', $billName)); @@ -138,6 +156,18 @@ class BillRepository implements BillRepositoryInterface return null; } + /** + * Find a bill by ID. + * + * @param int $billId + * + * @return Bill|null + */ + public function find(int $billId): ?Bill + { + return $this->user->bills()->find($billId); + } + /** * Find a bill by name. * @@ -150,17 +180,6 @@ class BillRepository implements BillRepositoryInterface return $this->user->bills()->where('name', $name)->first(['bills.*']); } - /** - * @return Collection - */ - public function getActiveBills(): Collection - { - return $this->user->bills() - ->where('active', true) - ->orderBy('bills.name', 'ASC') - ->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount'),]); - } - /** * Get all attachments. * @@ -249,7 +268,7 @@ class BillRepository implements BillRepositoryInterface $set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']); if ($set->count() > 0) { $journalIds = $set->pluck('id')->toArray(); - $amount = (string)Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); + $amount = (string) Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); $sum = bcadd($sum, $amount); //Log::debug(sprintf('Total > 0, so add to sum %f, which becomes %f', $amount, $sum)); } @@ -258,6 +277,17 @@ class BillRepository implements BillRepositoryInterface return $sum; } + /** + * @return Collection + */ + public function getActiveBills(): Collection + { + return $this->user->bills() + ->where('active', true) + ->orderBy('bills.name', 'ASC') + ->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount'),]); + } + /** * Get the total amount of money paid for the users active bills in the date range given, * grouped per currency. @@ -275,10 +305,10 @@ class BillRepository implements BillRepositoryInterface foreach ($bills as $bill) { /** @var Collection $set */ $set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']); - $currencyId = (int)$bill->transaction_currency_id; + $currencyId = (int) $bill->transaction_currency_id; if ($set->count() > 0) { $journalIds = $set->pluck('id')->toArray(); - $amount = (string)Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); + $amount = (string) Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); $return[$currencyId] = $return[$currencyId] ?? '0'; $return[$currencyId] = bcadd($amount, $return[$currencyId]); //Log::debug(sprintf('Total > 0, so add to sum %f, which becomes %f (currency %d)', $amount, $return[$currencyId], $currencyId)); @@ -311,7 +341,7 @@ class BillRepository implements BillRepositoryInterface if ($total > 0) { $average = bcdiv(bcadd($bill->amount_max, $bill->amount_min), '2'); - $multi = bcmul($average, (string)$total); + $multi = bcmul($average, (string) $total); $sum = bcadd($sum, $multi); //Log::debug(sprintf('Total > 0, so add to sum %f, which becomes %f', $multi, $sum)); } @@ -320,6 +350,71 @@ class BillRepository implements BillRepositoryInterface return $sum; } + /** + * Between start and end, tells you on which date(s) the bill is expected to hit. + * + * @param Bill $bill + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getPayDatesInRange(Bill $bill, Carbon $start, Carbon $end): Collection + { + $set = new Collection; + $currentStart = clone $start; + //Log::debug(sprintf('Now at bill "%s" (%s)', $bill->name, $bill->repeat_freq)); + //Log::debug(sprintf('First currentstart is %s', $currentStart->format('Y-m-d'))); + + while ($currentStart <= $end) { + //Log::debug(sprintf('Currentstart is now %s.', $currentStart->format('Y-m-d'))); + $nextExpectedMatch = $this->nextDateMatch($bill, $currentStart); + //Log::debug(sprintf('Next Date match after %s is %s', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); + if ($nextExpectedMatch > $end) {// If nextExpectedMatch is after end, we continue + break; + } + $set->push(clone $nextExpectedMatch); + //Log::debug(sprintf('Now %d dates in set.', $set->count())); + $nextExpectedMatch->addDay(); + + //Log::debug(sprintf('Currentstart (%s) has become %s.', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); + + $currentStart = clone $nextExpectedMatch; + } + + return $set; + } + + /** + * Given a bill and a date, this method will tell you at which moment this bill expects its next + * transaction. Whether or not it is there already, is not relevant. + * + * @param Bill $bill + * @param Carbon $date + * + * @return Carbon + * @throws JsonException + */ + public function nextDateMatch(Bill $bill, Carbon $date): Carbon + { + $cache = new CacheProperties; + $cache->addProperty($bill->id); + $cache->addProperty('nextDateMatch'); + $cache->addProperty($date); + if ($cache->has()) { + return $cache->get(); + } + // find the most recent date for this bill NOT in the future. Cache this date: + $start = clone $bill->date; + + while ($start < $date) { + $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + } + $cache->store($start); + + return $start; + } + /** * Get the total amount of money due for the users active bills in the date range given. * @@ -338,13 +433,13 @@ class BillRepository implements BillRepositoryInterface $dates = $this->getPayDatesInRange($bill, $start, $end); $count = $bill->transactionJournals()->after($start)->before($end)->count(); $total = $dates->count() - $count; - $currencyId = (int)$bill->transaction_currency_id; + $currencyId = (int) $bill->transaction_currency_id; //Log::debug(sprintf('Dates = %d, journalCount = %d, total = %d', $dates->count(), $count, $total)); if ($total > 0) { $average = bcdiv(bcadd($bill->amount_max, $bill->amount_min), '2'); - $multi = bcmul($average, (string)$total); + $multi = bcmul($average, (string) $total); $return[$currencyId] = $return[$currencyId] ?? '0'; $return[$currencyId] = bcadd($return[$currencyId], $multi); //Log::debug(sprintf('Total > 0, so add to sum %f, which becomes %f (for currency %d)', $multi, $return[$currencyId], $currencyId)); @@ -378,7 +473,7 @@ class BillRepository implements BillRepositoryInterface /** @var Note $note */ $note = $bill->notes()->first(); if (null !== $note) { - return (string)$note->text; + return (string) $note->text; } return ''; @@ -403,7 +498,7 @@ class BillRepository implements BillRepositoryInterface foreach ($journals as $journal) { /** @var Transaction $transaction */ $transaction = $journal->transactions()->where('amount', '<', 0)->first(); - $currencyId = (int)$journal->transaction_currency_id; + $currencyId = (int) $journal->transaction_currency_id; $currency = $journal->transactionCurrency; $result[$currencyId] = $result[$currencyId] ?? [ 'sum' => '0', @@ -424,7 +519,7 @@ class BillRepository implements BillRepositoryInterface * @var array $arr */ foreach ($result as $currencyId => $arr) { - $result[$currencyId]['avg'] = bcdiv($arr['sum'], (string)$arr['count']); + $result[$currencyId]['avg'] = bcdiv($arr['sum'], (string) $arr['count']); } return $result; @@ -464,41 +559,6 @@ class BillRepository implements BillRepositoryInterface ); } - /** - * Between start and end, tells you on which date(s) the bill is expected to hit. - * - * @param Bill $bill - * @param Carbon $start - * @param Carbon $end - * - * @return Collection - */ - public function getPayDatesInRange(Bill $bill, Carbon $start, Carbon $end): Collection - { - $set = new Collection; - $currentStart = clone $start; - //Log::debug(sprintf('Now at bill "%s" (%s)', $bill->name, $bill->repeat_freq)); - //Log::debug(sprintf('First currentstart is %s', $currentStart->format('Y-m-d'))); - - while ($currentStart <= $end) { - //Log::debug(sprintf('Currentstart is now %s.', $currentStart->format('Y-m-d'))); - $nextExpectedMatch = $this->nextDateMatch($bill, $currentStart); - //Log::debug(sprintf('Next Date match after %s is %s', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); - if ($nextExpectedMatch > $end) {// If nextExpectedMatch is after end, we continue - break; - } - $set->push(clone $nextExpectedMatch); - //Log::debug(sprintf('Now %d dates in set.', $set->count())); - $nextExpectedMatch->addDay(); - - //Log::debug(sprintf('Currentstart (%s) has become %s.', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); - - $currentStart = clone $nextExpectedMatch; - } - - return $set; - } - /** * Return all rules for one bill * @@ -572,7 +632,7 @@ class BillRepository implements BillRepositoryInterface if (null === $transaction) { continue; } - $currencyId = (int)$journal->transaction_currency_id; + $currencyId = (int) $journal->transaction_currency_id; $currency = $journal->transactionCurrency; $result[$currencyId] = $result[$currencyId] ?? [ 'sum' => '0', @@ -593,7 +653,7 @@ class BillRepository implements BillRepositoryInterface * @var array $arr */ foreach ($result as $currencyId => $arr) { - $result[$currencyId]['avg'] = bcdiv($arr['sum'], (string)$arr['count']); + $result[$currencyId]['avg'] = bcdiv($arr['sum'], (string) $arr['count']); } return $result; @@ -609,43 +669,13 @@ class BillRepository implements BillRepositoryInterface { /** @var Transaction $transaction */ foreach ($transactions as $transaction) { - $journal = $bill->user->transactionJournals()->find((int)$transaction['transaction_journal_id']); + $journal = $bill->user->transactionJournals()->find((int) $transaction['transaction_journal_id']); $journal->bill_id = $bill->id; $journal->save(); Log::debug(sprintf('Linked journal #%d to bill #%d', $journal->id, $bill->id)); } } - /** - * Given a bill and a date, this method will tell you at which moment this bill expects its next - * transaction. Whether or not it is there already, is not relevant. - * - * @param Bill $bill - * @param Carbon $date - * - * @return Carbon - * @throws JsonException - */ - public function nextDateMatch(Bill $bill, Carbon $date): Carbon - { - $cache = new CacheProperties; - $cache->addProperty($bill->id); - $cache->addProperty('nextDateMatch'); - $cache->addProperty($date); - if ($cache->has()) { - return $cache->get(); - } - // find the most recent date for this bill NOT in the future. Cache this date: - $start = clone $bill->date; - - while ($start < $date) { - $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); - } - $cache->store($start); - - return $start; - } - /** * Given the date in $date, this method will return a moment in the future where the bill is expected to be paid. * @@ -782,35 +812,4 @@ class BillRepository implements BillRepositoryInterface return $service->update($bill, $data); } - - - /** - * @inheritDoc - */ - public function billEndsWith(string $query, int $limit): Collection - { - $search = $this->user->bills(); - if ('' !== $query) { - $search->where('name', 'LIKE', sprintf('%%%s', $query)); - } - $search->orderBy('name', 'ASC') - ->where('active', true); - - return $search->take($limit)->get(); - } - - /** - * @inheritDoc - */ - public function billStartsWith(string $query, int $limit): Collection - { - $search = $this->user->bills(); - if ('' !== $query) { - $search->where('name', 'LIKE', sprintf('%s%%', $query)); - } - $search->orderBy('name', 'ASC') - ->where('active', true); - - return $search->take($limit)->get(); - } } diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index 5d4acb4fe8..fcae8ee822 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -35,11 +35,6 @@ use Illuminate\Support\Collection; interface BillRepositoryInterface { - /** - * Add correct order to bills. - */ - public function correctOrder(): void; - /** * @param string $query * @param int $limit @@ -56,6 +51,11 @@ interface BillRepositoryInterface */ public function billStartsWith(string $query, int $limit): Collection; + /** + * Add correct order to bills. + */ + public function correctOrder(): void; + /** * @param Bill $bill * diff --git a/app/Repositories/Budget/AvailableBudgetRepository.php b/app/Repositories/Budget/AvailableBudgetRepository.php index 690e9ca75b..0c45754e0e 100644 --- a/app/Repositories/Budget/AvailableBudgetRepository.php +++ b/app/Repositories/Budget/AvailableBudgetRepository.php @@ -124,7 +124,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface ->where('start_date', $start->format('Y-m-d')) ->where('end_date', $end->format('Y-m-d'))->first(); if (null !== $availableBudget) { - $amount = (string)$availableBudget->amount; + $amount = (string) $availableBudget->amount; } return $amount; diff --git a/app/Repositories/Budget/BudgetLimitRepository.php b/app/Repositories/Budget/BudgetLimitRepository.php index cb4df10b1c..1881ab741e 100644 --- a/app/Repositories/Budget/BudgetLimitRepository.php +++ b/app/Repositories/Budget/BudgetLimitRepository.php @@ -147,6 +147,22 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface ->where('end_date', $end->format('Y-m-d'))->first(); } + /** + * @param TransactionCurrency $currency + * @param Carbon|null $start + * @param Carbon|null $end + * + * @return Collection + */ + public function getAllBudgetLimitsByCurrency(TransactionCurrency $currency, Carbon $start = null, Carbon $end = null): Collection + { + return $this->getAllBudgetLimits($start, $end)->filter( + static function (BudgetLimit $budgetLimit) use ($currency) { + return $budgetLimit->transaction_currency_id === $currency->id; + } + ); + } + /** * @param Carbon|null $start * @param Carbon|null $end @@ -215,22 +231,6 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface )->get(['budget_limits.*']); } - /** - * @param TransactionCurrency $currency - * @param Carbon|null $start - * @param Carbon|null $end - * - * @return Collection - */ - public function getAllBudgetLimitsByCurrency(TransactionCurrency $currency, Carbon $start = null, Carbon $end = null): Collection - { - return $this->getAllBudgetLimits($start, $end)->filter( - static function (BudgetLimit $budgetLimit) use ($currency) { - return $budgetLimit->transaction_currency_id === $currency->id; - } - ); - } - /** * @param Budget $budget * @param Carbon|null $start @@ -318,7 +318,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface $currency->save(); // find the budget: - $budget = $this->user->budgets()->find((int)$data['budget_id']); + $budget = $this->user->budgets()->find((int) $data['budget_id']); if (null === $budget) { throw new FireflyException('200004: Budget does not exist.'); } diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index fc62a77cae..b2c7bef655 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -50,6 +50,36 @@ class BudgetRepository implements BudgetRepositoryInterface { private User $user; + /** + * @inheritDoc + */ + public function budgetEndsWith(string $query, int $limit): Collection + { + $search = $this->user->budgets(); + if ('' !== $query) { + $search->where('name', 'LIKE', sprintf('%%%s', $query)); + } + $search->orderBy('order', 'ASC') + ->orderBy('name', 'ASC')->where('active', true); + + return $search->take($limit)->get(); + } + + /** + * @inheritDoc + */ + public function budgetStartsWith(string $query, int $limit): Collection + { + $search = $this->user->budgets(); + if ('' !== $query) { + $search->where('name', 'LIKE', sprintf('%s%%', $query)); + } + $search->orderBy('order', 'ASC') + ->orderBy('name', 'ASC')->where('active', true); + + return $search->take($limit)->get(); + } + /** * @return bool */ @@ -76,6 +106,17 @@ class BudgetRepository implements BudgetRepositoryInterface return true; } + /** + * @return Collection + */ + public function getActiveBudgets(): Collection + { + return $this->user->budgets()->where('active', true) + ->orderBy('order', 'ASC') + ->orderBy('name', 'ASC') + ->get(); + } + /** * @param Budget $budget * @@ -98,14 +139,23 @@ class BudgetRepository implements BudgetRepositoryInterface $budgets = $this->getBudgets(); /** @var Budget $budget */ foreach ($budgets as $budget) { - DB::table('budget_transaction')->where('budget_id', (int)$budget->id)->delete(); - DB::table('budget_transaction_journal')->where('budget_id', (int)$budget->id)->delete(); - RecurrenceTransactionMeta::where('name', 'budget_id')->where('value', (string)$budget->id)->delete(); - RuleAction::where('action_type', 'set_budget')->where('action_value', (string)$budget->id)->delete(); + DB::table('budget_transaction')->where('budget_id', (int) $budget->id)->delete(); + DB::table('budget_transaction_journal')->where('budget_id', (int) $budget->id)->delete(); + RecurrenceTransactionMeta::where('name', 'budget_id')->where('value', (string) $budget->id)->delete(); + RuleAction::where('action_type', 'set_budget')->where('action_value', (string) $budget->id)->delete(); $budget->delete(); } } + /** + * @return Collection + */ + public function getBudgets(): Collection + { + return $this->user->budgets()->orderBy('order', 'ASC') + ->orderBy('name', 'ASC')->get(); + } + /** * @inheritDoc */ @@ -117,18 +167,6 @@ class BudgetRepository implements BudgetRepositoryInterface } } - /** - * Find a budget or return NULL - * - * @param int|null $budgetId |null - * - * @return Budget|null - */ - public function find(int $budgetId = null): ?Budget - { - return $this->user->budgets()->find($budgetId); - } - /** * @param int|null $budgetId * @param string|null $budgetName @@ -139,10 +177,10 @@ class BudgetRepository implements BudgetRepositoryInterface { Log::debug('Now in findBudget()'); Log::debug(sprintf('Searching for budget with ID #%d...', $budgetId)); - $result = $this->find((int)$budgetId); + $result = $this->find((int) $budgetId); if (null === $result && null !== $budgetName && '' !== $budgetName) { Log::debug(sprintf('Searching for budget with name %s...', $budgetName)); - $result = $this->findByName((string)$budgetName); + $result = $this->findByName((string) $budgetName); } if (null !== $result) { Log::debug(sprintf('Found budget #%d: %s', $result->id, $result->name)); @@ -152,6 +190,18 @@ class BudgetRepository implements BudgetRepositoryInterface return $result; } + /** + * Find a budget or return NULL + * + * @param int|null $budgetId |null + * + * @return Budget|null + */ + public function find(int $budgetId = null): ?Budget + { + return $this->user->budgets()->find($budgetId); + } + /** * Find budget by name. * @@ -187,17 +237,6 @@ class BudgetRepository implements BudgetRepositoryInterface return null; } - /** - * @return Collection - */ - public function getActiveBudgets(): Collection - { - return $this->user->budgets()->where('active', true) - ->orderBy('order', 'ASC') - ->orderBy('name', 'ASC') - ->get(); - } - /** * @inheritDoc */ @@ -219,23 +258,6 @@ class BudgetRepository implements BudgetRepositoryInterface ); } - /** - * @inheritDoc - */ - public function getAutoBudget(Budget $budget): ?AutoBudget - { - return $budget->autoBudgets()->first(); - } - - /** - * @return Collection - */ - public function getBudgets(): Collection - { - return $this->user->budgets()->orderBy('order', 'ASC') - ->orderBy('name', 'ASC')->get(); - } - /** * Get all budgets with these ID's. * @@ -258,9 +280,17 @@ class BudgetRepository implements BudgetRepositoryInterface ->orderBy('name', 'ASC')->where('active', 0)->get(); } - public function getMaxOrder(): int + /** + * @inheritDoc + */ + public function getNoteText(Budget $budget): ?string { - return (int)$this->user->budgets()->max('order'); + $note = $budget->notes()->first(); + if (null === $note) { + return null; + } + + return $note->text; } /** @@ -325,8 +355,8 @@ class BudgetRepository implements BudgetRepositoryInterface } // set notes - if(array_key_exists('notes', $data)) { - $this->setNoteText($newBudget, (string)$data['notes']); + if (array_key_exists('notes', $data)) { + $this->setNoteText($newBudget, (string) $data['notes']); } if (!array_key_exists('auto_budget_type', $data) || !array_key_exists('auto_budget_amount', $data) || !array_key_exists('auto_budget_period', $data)) { @@ -350,10 +380,10 @@ class BudgetRepository implements BudgetRepositoryInterface $repos = app(CurrencyRepositoryInterface::class); $currency = null; if (array_key_exists('currency_id', $data)) { - $currency = $repos->find((int)$data['currency_id']); + $currency = $repos->find((int) $data['currency_id']); } if (array_key_exists('currency_code', $data)) { - $currency = $repos->findByCode((string)$data['currency_code']); + $currency = $repos->findByCode((string) $data['currency_code']); } if (null === $currency) { $currency = app('amount')->getDefaultCurrencyByUser($this->user); @@ -387,6 +417,38 @@ class BudgetRepository implements BudgetRepositoryInterface return $newBudget; } + public function getMaxOrder(): int + { + return (int) $this->user->budgets()->max('order'); + } + + /** + * @param Budget $budget + * @param string $text + * @return void + */ + private function setNoteText(Budget $budget, string $text): void + { + $dbNote = $budget->notes()->first(); + if ('' !== $text) { + if (null === $dbNote) { + $dbNote = new Note; + $dbNote->noteable()->associate($budget); + } + $dbNote->text = trim($text); + $dbNote->save(); + + return; + } + if (null !== $dbNote) { + try { + $dbNote->delete(); + } catch (Exception $e) { // @phpstan-ignore-line + // @ignoreException + } + } + } + /** * @param Budget $budget * @param array $data @@ -406,8 +468,8 @@ class BudgetRepository implements BudgetRepositoryInterface if (array_key_exists('active', $data)) { $budget->active = $data['active']; } - if(array_key_exists('notes', $data)) { - $this->setNoteText($budget, (string)$data['notes']); + if (array_key_exists('notes', $data)) { + $this->setNoteText($budget, (string) $data['notes']); } $budget->save(); @@ -476,6 +538,14 @@ class BudgetRepository implements BudgetRepositoryInterface } } + /** + * @inheritDoc + */ + public function getAutoBudget(Budget $budget): ?AutoBudget + { + return $budget->autoBudgets()->first(); + } + /** * @param Budget $budget * @param array $data @@ -499,8 +569,8 @@ class BudgetRepository implements BudgetRepositoryInterface // set or update the currency. if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { $repos = app(CurrencyRepositoryInterface::class); - $currencyId = (int)($data['currency_id'] ?? 0); - $currencyCode = (string)($data['currency_code'] ?? ''); + $currencyId = (int) ($data['currency_id'] ?? 0); + $currencyCode = (string) ($data['currency_code'] ?? ''); $currency = $repos->find($currencyId); if (null === $currency) { $currency = $repos->findByCodeNull($currencyCode); @@ -524,74 +594,4 @@ class BudgetRepository implements BudgetRepositoryInterface $autoBudget->save(); } - - /** - * @inheritDoc - */ - public function getNoteText(Budget $budget): ?string - { - $note = $budget->notes()->first(); - if (null === $note) { - return null; - } - - return $note->text; - } - - /** - * @param Budget $budget - * @param string $text - * @return void - */ - private function setNoteText(Budget $budget, string $text): void - { - $dbNote = $budget->notes()->first(); - if ('' !== $text) { - if (null === $dbNote) { - $dbNote = new Note; - $dbNote->noteable()->associate($budget); - } - $dbNote->text = trim($text); - $dbNote->save(); - - return; - } - if (null !== $dbNote) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - } - } - - /** - * @inheritDoc - */ - public function budgetEndsWith(string $query, int $limit): Collection - { - $search = $this->user->budgets(); - if ('' !== $query) { - $search->where('name', 'LIKE', sprintf('%%%s', $query)); - } - $search->orderBy('order', 'ASC') - ->orderBy('name', 'ASC')->where('active', true); - - return $search->take($limit)->get(); - } - - /** - * @inheritDoc - */ - public function budgetStartsWith(string $query, int $limit): Collection - { - $search = $this->user->budgets(); - if ('' !== $query) { - $search->where('name', 'LIKE', sprintf('%s%%', $query)); - } - $search->orderBy('order', 'ASC') - ->orderBy('name', 'ASC')->where('active', true); - - return $search->take($limit)->get(); - } } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index 35d469c828..d06d560530 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -34,17 +34,27 @@ use Illuminate\Support\Collection; */ interface BudgetRepositoryInterface { + /** + * @param string $query + * @param int $limit + * + * @return Collection + */ + public function budgetEndsWith(string $query, int $limit): Collection; + + /** + * @param string $query + * @param int $limit + * + * @return Collection + */ + public function budgetStartsWith(string $query, int $limit): Collection; + /** * @return bool */ public function cleanupBudgets(): bool; - /** - * @param Budget $budget - * @return string|null - */ - public function getNoteText(Budget $budget): ?string; - /** * @param Budget $budget * @@ -140,6 +150,12 @@ interface BudgetRepositoryInterface */ public function getMaxOrder(): int; + /** + * @param Budget $budget + * @return string|null + */ + public function getNoteText(Budget $budget): ?string; + /** * @param string $query * @param int $limit @@ -175,20 +191,4 @@ interface BudgetRepositoryInterface */ public function update(Budget $budget, array $data): Budget; - /** - * @param string $query - * @param int $limit - * - * @return Collection - */ - public function budgetEndsWith(string $query, int $limit): Collection; - - /** - * @param string $query - * @param int $limit - * - * @return Collection - */ - public function budgetStartsWith(string $query, int $limit): Collection; - } diff --git a/app/Repositories/Budget/NoBudgetRepository.php b/app/Repositories/Budget/NoBudgetRepository.php index eb2dd385f9..9a0d1df208 100644 --- a/app/Repositories/Budget/NoBudgetRepository.php +++ b/app/Repositories/Budget/NoBudgetRepository.php @@ -61,7 +61,7 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface /** @var array $journal */ foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $data[$currencyId] = $data[$currencyId] ?? [ 'id' => 0, @@ -133,12 +133,12 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface /** @var TransactionCurrency $currency */ $currency = $currencies[$code]; $return[] = [ - 'currency_id' => (string)$currency['id'], + 'currency_id' => (string) $currency['id'], 'currency_code' => $code, 'currency_name' => $currency['name'], 'currency_symbol' => $currency['symbol'], 'currency_decimal_places' => $currency['decimal_places'], - 'amount' => number_format((float)$spent, $currency['decimal_places'], '.', ''), + 'amount' => number_format((float) $spent, $currency['decimal_places'], '.', ''), ]; } @@ -176,7 +176,7 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'sum' => '0', 'currency_id' => $currencyId, diff --git a/app/Repositories/Budget/OperationsRepository.php b/app/Repositories/Budget/OperationsRepository.php index 52b9648fb5..94d44d4923 100644 --- a/app/Repositories/Budget/OperationsRepository.php +++ b/app/Repositories/Budget/OperationsRepository.php @@ -200,6 +200,19 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } + /** + * @return Collection + */ + private function getBudgets(): Collection + { + /** @var BudgetRepositoryInterface $repos */ + $repos = app(BudgetRepositoryInterface::class); + + return $repos->getActiveBudgets(); + } + + /** @noinspection MoreThanThreeArgumentsInspection */ + /** * @param User $user */ @@ -208,8 +221,6 @@ class OperationsRepository implements OperationsRepositoryInterface $this->user = $user; } - /** @noinspection MoreThanThreeArgumentsInspection */ - /** * @param Collection $budgets * @param Collection $accounts @@ -371,17 +382,6 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } - /** - * @return Collection - */ - private function getBudgets(): Collection - { - /** @var BudgetRepositoryInterface $repos */ - $repos = app(BudgetRepositoryInterface::class); - - return $repos->getActiveBudgets(); - } - /** * For now, simply refer to whichever repository holds this function. * See reference nr. 14 diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 9d31f1a852..030bbc63e6 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -46,6 +46,32 @@ class CategoryRepository implements CategoryRepositoryInterface { private User $user; + /** + * @inheritDoc + */ + public function categoryEndsWith(string $query, int $limit): Collection + { + $search = $this->user->categories(); + if ('' !== $query) { + $search->where('name', 'LIKE', sprintf('%%%s', $query)); + } + + return $search->take($limit)->get(); + } + + /** + * @inheritDoc + */ + public function categoryStartsWith(string $query, int $limit): Collection + { + $search = $this->user->categories(); + if ('' !== $query) { + $search->where('name', 'LIKE', sprintf('%s%%', $query)); + } + + return $search->take($limit)->get(); + } + /** * @param Category $category * @@ -78,6 +104,44 @@ class CategoryRepository implements CategoryRepositoryInterface } } + /** + * Returns a list of all the categories belonging to a user. + * + * @return Collection + */ + public function getCategories(): Collection + { + return $this->user->categories()->with(['attachments'])->orderBy('name', 'ASC')->get(); + } + + /** + * @param int|null $categoryId + * @param string|null $categoryName + * + * @return Category|null + * @throws FireflyException + */ + public function findCategory(?int $categoryId, ?string $categoryName): ?Category + { + Log::debug('Now in findCategory()'); + Log::debug(sprintf('Searching for category with ID #%d...', $categoryId)); + $result = $this->find((int) $categoryId); + if (null === $result) { + Log::debug(sprintf('Searching for category with name %s...', $categoryName)); + $result = $this->findByName((string) $categoryName); + if (null === $result && '' !== (string) $categoryName) { + // create it! + $result = $this->store(['name' => $categoryName]); + } + } + if (null !== $result) { + Log::debug(sprintf('Found category #%d: %s', $result->id, $result->name)); + } + Log::debug(sprintf('Found category result is null? %s', var_export(null === $result, true))); + + return $result; + } + /** * Find a category or return NULL * @@ -103,31 +167,54 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param int|null $categoryId - * @param string|null $categoryName + * @param array $data * - * @return Category|null + * @return Category * @throws FireflyException */ - public function findCategory(?int $categoryId, ?string $categoryName): ?Category + public function store(array $data): Category { - Log::debug('Now in findCategory()'); - Log::debug(sprintf('Searching for category with ID #%d...', $categoryId)); - $result = $this->find((int)$categoryId); - if (null === $result) { - Log::debug(sprintf('Searching for category with name %s...', $categoryName)); - $result = $this->findByName((string)$categoryName); - if (null === $result && '' !== (string)$categoryName) { - // create it! - $result = $this->store(['name' => $categoryName]); - } - } - if (null !== $result) { - Log::debug(sprintf('Found category #%d: %s', $result->id, $result->name)); - } - Log::debug(sprintf('Found category result is null? %s', var_export(null === $result, true))); + /** @var CategoryFactory $factory */ + $factory = app(CategoryFactory::class); + $factory->setUser($this->user); - return $result; + $category = $factory->findOrCreate(null, $data['name']); + + if (null === $category) { + throw new FireflyException(sprintf('400003: Could not store new category with name "%s"', $data['name'])); + } + + if (array_key_exists('notes', $data) && '' === $data['notes']) { + $this->removeNotes($category); + } + if (array_key_exists('notes', $data) && '' !== $data['notes']) { + $this->updateNotes($category, $data['notes']); + } + + return $category; + + } + + /** + * @param Category $category + */ + public function removeNotes(Category $category): void + { + $category->notes()->delete(); + } + + /** + * @inheritDoc + */ + public function updateNotes(Category $category, string $notes): void + { + $dbNote = $category->notes()->first(); + if (null === $dbNote) { + $dbNote = new Note; + $dbNote->noteable()->associate($category); + } + $dbNote->text = trim($notes); + $dbNote->save(); } /** @@ -158,6 +245,43 @@ class CategoryRepository implements CategoryRepositoryInterface return $firstJournalDate; } + /** + * @param Category $category + * + * @return Carbon|null + */ + private function getFirstJournalDate(Category $category): ?Carbon + { + $query = $category->transactionJournals()->orderBy('date', 'ASC'); + $result = $query->first(['transaction_journals.*']); + + if (null !== $result) { + return $result->date; + } + + return null; + } + + /** + * @param Category $category + * + * @return Carbon|null + */ + private function getFirstTransactionDate(Category $category): ?Carbon + { + // check transactions: + $query = $category->transactions() + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->orderBy('transaction_journals.date', 'ASC'); + + $lastTransaction = $query->first(['transaction_journals.*']); + if (null !== $lastTransaction) { + return new Carbon($lastTransaction->date); + } + + return null; + } + /** * @inheritDoc */ @@ -191,16 +315,6 @@ class CategoryRepository implements CategoryRepositoryInterface return $this->user->categories()->whereIn('id', $categoryIds)->get(); } - /** - * Returns a list of all the categories belonging to a user. - * - * @return Collection - */ - public function getCategories(): Collection - { - return $this->user->categories()->with(['attachments'])->orderBy('name', 'ASC')->get(); - } - /** * @inheritDoc */ @@ -243,134 +357,6 @@ class CategoryRepository implements CategoryRepositoryInterface return $lastJournalDate; } - /** - * @param Category $category - */ - public function removeNotes(Category $category): void - { - $category->notes()->delete(); - } - - /** - * @param string $query - * @param int $limit - * - * @return Collection - */ - public function searchCategory(string $query, int $limit): Collection - { - $search = $this->user->categories(); - if ('' !== $query) { - $search->where('name', 'LIKE', sprintf('%%%s%%', $query)); - } - - return $search->take($limit)->get(); - } - - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param array $data - * - * @return Category - * @throws FireflyException - */ - public function store(array $data): Category - { - /** @var CategoryFactory $factory */ - $factory = app(CategoryFactory::class); - $factory->setUser($this->user); - - $category = $factory->findOrCreate(null, $data['name']); - - if (null === $category) { - throw new FireflyException(sprintf('400003: Could not store new category with name "%s"', $data['name'])); - } - - if (array_key_exists('notes', $data) && '' === $data['notes']) { - $this->removeNotes($category); - } - if (array_key_exists('notes', $data) && '' !== $data['notes']) { - $this->updateNotes($category, $data['notes']); - } - - return $category; - - } - - /** - * @param Category $category - * @param array $data - * - * @return Category - * @throws Exception - */ - public function update(Category $category, array $data): Category - { - /** @var CategoryUpdateService $service */ - $service = app(CategoryUpdateService::class); - $service->setUser($this->user); - - return $service->update($category, $data); - } - - /** - * @inheritDoc - */ - public function updateNotes(Category $category, string $notes): void - { - $dbNote = $category->notes()->first(); - if (null === $dbNote) { - $dbNote = new Note; - $dbNote->noteable()->associate($category); - } - $dbNote->text = trim($notes); - $dbNote->save(); - } - - /** - * @param Category $category - * - * @return Carbon|null - */ - private function getFirstJournalDate(Category $category): ?Carbon - { - $query = $category->transactionJournals()->orderBy('date', 'ASC'); - $result = $query->first(['transaction_journals.*']); - - if (null !== $result) { - return $result->date; - } - - return null; - } - - /** - * @param Category $category - * - * @return Carbon|null - */ - private function getFirstTransactionDate(Category $category): ?Carbon - { - // check transactions: - $query = $category->transactions() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->orderBy('transaction_journals.date', 'ASC'); - - $lastTransaction = $query->first(['transaction_journals.*']); - if (null !== $lastTransaction) { - return new Carbon($lastTransaction->date); - } - - return null; - } - /** * @param Category $category * @param Collection $accounts @@ -422,28 +408,42 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @inheritDoc + * @param string $query + * @param int $limit + * + * @return Collection */ - public function categoryEndsWith(string $query, int $limit): Collection + public function searchCategory(string $query, int $limit): Collection { $search = $this->user->categories(); if ('' !== $query) { - $search->where('name', 'LIKE', sprintf('%%%s', $query)); + $search->where('name', 'LIKE', sprintf('%%%s%%', $query)); } return $search->take($limit)->get(); } /** - * @inheritDoc + * @param User $user */ - public function categoryStartsWith(string $query, int $limit): Collection + public function setUser(User $user): void { - $search = $this->user->categories(); - if ('' !== $query) { - $search->where('name', 'LIKE', sprintf('%s%%', $query)); - } + $this->user = $user; + } - return $search->take($limit)->get(); + /** + * @param Category $category + * @param array $data + * + * @return Category + * @throws Exception + */ + public function update(Category $category, array $data): Category + { + /** @var CategoryUpdateService $service */ + $service = app(CategoryUpdateService::class); + $service->setUser($this->user); + + return $service->update($category, $data); } } diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php index e633a6544c..d26dd08bf3 100644 --- a/app/Repositories/Category/CategoryRepositoryInterface.php +++ b/app/Repositories/Category/CategoryRepositoryInterface.php @@ -34,6 +34,22 @@ use Illuminate\Support\Collection; interface CategoryRepositoryInterface { + /** + * @param string $query + * @param int $limit + * + * @return Collection + */ + public function categoryEndsWith(string $query, int $limit): Collection; + + /** + * @param string $query + * @param int $limit + * + * @return Collection + */ + public function categoryStartsWith(string $query, int $limit): Collection; + /** * @param Category $category * @@ -134,22 +150,6 @@ interface CategoryRepositoryInterface */ public function searchCategory(string $query, int $limit): Collection; - /** - * @param string $query - * @param int $limit - * - * @return Collection - */ - public function categoryEndsWith(string $query, int $limit): Collection; - - /** - * @param string $query - * @param int $limit - * - * @return Collection - */ - public function categoryStartsWith(string $query, int $limit): Collection; - /** * @param User $user */ diff --git a/app/Repositories/Category/NoCategoryRepository.php b/app/Repositories/Category/NoCategoryRepository.php index d24e528f8b..10d86f127b 100644 --- a/app/Repositories/Category/NoCategoryRepository.php +++ b/app/Repositories/Category/NoCategoryRepository.php @@ -60,7 +60,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'categories' => [], 'currency_id' => $currencyId, @@ -72,13 +72,13 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface // info about the non-existent category: $array[$currencyId]['categories'][0] = $array[$currencyId]['categories'][0] ?? [ 'id' => 0, - 'name' => (string)trans('firefly.noCategory'), + 'name' => (string) trans('firefly.noCategory'), 'transaction_journals' => [], ]; // add journal to array: // only a subset of the fields. - $journalId = (int)$journal['transaction_journal_id']; + $journalId = (int) $journal['transaction_journal_id']; $array[$currencyId]['categories'][0]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->negative($journal['amount']), @@ -113,7 +113,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'categories' => [], 'currency_id' => $currencyId, @@ -126,12 +126,12 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface // info about the non-existent category: $array[$currencyId]['categories'][0] = $array[$currencyId]['categories'][0] ?? [ 'id' => 0, - 'name' => (string)trans('firefly.noCategory'), + 'name' => (string) trans('firefly.noCategory'), 'transaction_journals' => [], ]; // add journal to array: // only a subset of the fields. - $journalId = (int)$journal['transaction_journal_id']; + $journalId = (int) $journal['transaction_journal_id']; $array[$currencyId]['categories'][0]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->positive($journal['amount']), @@ -173,7 +173,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'sum' => '0', 'currency_id' => $currencyId, @@ -210,7 +210,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'sum' => '0', 'currency_id' => $currencyId, @@ -241,7 +241,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'sum' => '0', 'currency_id' => $currencyId, diff --git a/app/Repositories/Category/OperationsRepository.php b/app/Repositories/Category/OperationsRepository.php index 7c72218355..510de53ef9 100644 --- a/app/Repositories/Category/OperationsRepository.php +++ b/app/Repositories/Category/OperationsRepository.php @@ -70,9 +70,9 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; - $categoryId = (int)$journal['category_id']; - $categoryName = (string)$journal['category_name']; + $currencyId = (int) $journal['currency_id']; + $categoryId = (int) $journal['category_id']; + $categoryName = (string) $journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { @@ -98,7 +98,7 @@ class OperationsRepository implements OperationsRepositoryInterface // add journal to array: // only a subset of the fields. - $journalId = (int)$journal['transaction_journal_id']; + $journalId = (int) $journal['transaction_journal_id']; $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->negative($journal['amount']), 'date' => $journal['date'], @@ -116,6 +116,16 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } + /** + * Returns a list of all the categories belonging to a user. + * + * @return Collection + */ + private function getCategories(): Collection + { + return $this->user->categories()->get(); + } + /** * This method returns a list of all the deposit transaction journals (as arrays) set in that period * which have the specified category set to them. It's grouped per currency, with as few details in the array @@ -147,13 +157,13 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; - $categoryId = (int)$journal['category_id']; - $categoryName = (string)$journal['category_name']; + $currencyId = (int) $journal['currency_id']; + $categoryId = (int) $journal['category_id']; + $categoryName = (string) $journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { - $categoryName = (string)trans('firefly.no_category'); + $categoryName = (string) trans('firefly.no_category'); } // info about the currency: @@ -175,7 +185,7 @@ class OperationsRepository implements OperationsRepositoryInterface // add journal to array: // only a subset of the fields. - $journalId = (int)$journal['transaction_journal_id']; + $journalId = (int) $journal['transaction_journal_id']; $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->positive($journal['amount']), 'date' => $journal['date'], @@ -192,6 +202,138 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } + /** + * @inheritDoc + */ + public function listTransferredIn(Carbon $start, Carbon $end, Collection $accounts, ?Collection $categories = null): array + { + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) + ->setDestinationAccounts($accounts)->excludeSourceAccounts($accounts); + if (null !== $categories && $categories->count() > 0) { + $collector->setCategories($categories); + } + if (null === $categories || (null !== $categories && 0 === $categories->count())) { + $collector->setCategories($this->getCategories()); + } + $collector->withCategoryInformation()->withAccountInformation()->withBudgetInformation(); + $journals = $collector->getExtractedJournals(); + $array = []; + + foreach ($journals as $journal) { + $currencyId = (int) $journal['currency_id']; + $categoryId = (int) $journal['category_id']; + $categoryName = (string) $journal['category_name']; + + // catch "no category" entries. + if (0 === $categoryId) { + continue; + } + + // info about the currency: + $array[$currencyId] = $array[$currencyId] ?? [ + 'categories' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; + + // info about the categories: + $array[$currencyId]['categories'][$categoryId] = $array[$currencyId]['categories'][$categoryId] ?? [ + 'id' => $categoryId, + 'name' => $categoryName, + 'transaction_journals' => [], + ]; + + // add journal to array: + // only a subset of the fields. + $journalId = (int) $journal['transaction_journal_id']; + $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ + 'amount' => app('steam')->positive($journal['amount']), + 'date' => $journal['date'], + 'source_account_id' => $journal['source_account_id'], + 'category_name' => $journal['category_name'], + 'source_account_name' => $journal['source_account_name'], + 'destination_account_id' => $journal['destination_account_id'], + 'destination_account_name' => $journal['destination_account_name'], + 'description' => $journal['description'], + 'transaction_group_id' => $journal['transaction_group_id'], + ]; + + } + + return $array; + } + + /** + * @inheritDoc + */ + public function listTransferredOut(Carbon $start, Carbon $end, Collection $accounts, ?Collection $categories = null): array + { + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) + ->setSourceAccounts($accounts)->excludeDestinationAccounts($accounts); + if (null !== $categories && $categories->count() > 0) { + $collector->setCategories($categories); + } + if (null === $categories || (null !== $categories && 0 === $categories->count())) { + $collector->setCategories($this->getCategories()); + } + $collector->withCategoryInformation()->withAccountInformation()->withBudgetInformation(); + $journals = $collector->getExtractedJournals(); + $array = []; + + foreach ($journals as $journal) { + $currencyId = (int) $journal['currency_id']; + $categoryId = (int) $journal['category_id']; + $categoryName = (string) $journal['category_name']; + + // catch "no category" entries. + if (0 === $categoryId) { + continue; + } + + // info about the currency: + $array[$currencyId] = $array[$currencyId] ?? [ + 'categories' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; + + // info about the categories: + $array[$currencyId]['categories'][$categoryId] = $array[$currencyId]['categories'][$categoryId] ?? [ + 'id' => $categoryId, + 'name' => $categoryName, + 'transaction_journals' => [], + ]; + + // add journal to array: + // only a subset of the fields. + $journalId = (int) $journal['transaction_journal_id']; + $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ + 'amount' => app('steam')->negative($journal['amount']), + 'date' => $journal['date'], + 'source_account_id' => $journal['source_account_id'], + 'category_name' => $journal['category_name'], + 'source_account_name' => $journal['source_account_name'], + 'destination_account_id' => $journal['destination_account_id'], + 'destination_account_name' => $journal['destination_account_name'], + 'description' => $journal['description'], + 'transaction_group_id' => $journal['transaction_group_id'], + ]; + + } + + return $array; + } + /** * @param User $user */ @@ -229,14 +371,14 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'sum' => '0', 'currency_id' => $currencyId, 'currency_name' => $journal['currency_name'], 'currency_symbol' => $journal['currency_symbol'], 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => (int)$journal['currency_decimal_places'], + 'currency_decimal_places' => (int) $journal['currency_decimal_places'], ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'])); } @@ -272,7 +414,7 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'sum' => '0', 'currency_id' => $currencyId, @@ -315,7 +457,7 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'sum' => '0', 'currency_id' => $currencyId, @@ -329,146 +471,4 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } - - /** - * Returns a list of all the categories belonging to a user. - * - * @return Collection - */ - private function getCategories(): Collection - { - return $this->user->categories()->get(); - } - - /** - * @inheritDoc - */ - public function listTransferredIn(Carbon $start, Carbon $end, Collection $accounts, ?Collection $categories = null): array - { - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) - ->setDestinationAccounts($accounts)->excludeSourceAccounts($accounts); - if (null !== $categories && $categories->count() > 0) { - $collector->setCategories($categories); - } - if (null === $categories || (null !== $categories && 0 === $categories->count())) { - $collector->setCategories($this->getCategories()); - } - $collector->withCategoryInformation()->withAccountInformation()->withBudgetInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; - - foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; - $categoryId = (int)$journal['category_id']; - $categoryName = (string)$journal['category_name']; - - // catch "no category" entries. - if (0 === $categoryId) { - continue; - } - - // info about the currency: - $array[$currencyId] = $array[$currencyId] ?? [ - 'categories' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; - - // info about the categories: - $array[$currencyId]['categories'][$categoryId] = $array[$currencyId]['categories'][$categoryId] ?? [ - 'id' => $categoryId, - 'name' => $categoryName, - 'transaction_journals' => [], - ]; - - // add journal to array: - // only a subset of the fields. - $journalId = (int)$journal['transaction_journal_id']; - $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ - 'amount' => app('steam')->positive($journal['amount']), - 'date' => $journal['date'], - 'source_account_id' => $journal['source_account_id'], - 'category_name' => $journal['category_name'], - 'source_account_name' => $journal['source_account_name'], - 'destination_account_id' => $journal['destination_account_id'], - 'destination_account_name' => $journal['destination_account_name'], - 'description' => $journal['description'], - 'transaction_group_id' => $journal['transaction_group_id'], - ]; - - } - - return $array; - } - - /** - * @inheritDoc - */ - public function listTransferredOut(Carbon $start, Carbon $end, Collection $accounts, ?Collection $categories = null): array - { - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) - ->setSourceAccounts($accounts)->excludeDestinationAccounts($accounts); - if (null !== $categories && $categories->count() > 0) { - $collector->setCategories($categories); - } - if (null === $categories || (null !== $categories && 0 === $categories->count())) { - $collector->setCategories($this->getCategories()); - } - $collector->withCategoryInformation()->withAccountInformation()->withBudgetInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; - - foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; - $categoryId = (int)$journal['category_id']; - $categoryName = (string)$journal['category_name']; - - // catch "no category" entries. - if (0 === $categoryId) { - continue; - } - - // info about the currency: - $array[$currencyId] = $array[$currencyId] ?? [ - 'categories' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; - - // info about the categories: - $array[$currencyId]['categories'][$categoryId] = $array[$currencyId]['categories'][$categoryId] ?? [ - 'id' => $categoryId, - 'name' => $categoryName, - 'transaction_journals' => [], - ]; - - // add journal to array: - // only a subset of the fields. - $journalId = (int)$journal['transaction_journal_id']; - $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ - 'amount' => app('steam')->negative($journal['amount']), - 'date' => $journal['date'], - 'source_account_id' => $journal['source_account_id'], - 'category_name' => $journal['category_name'], - 'source_account_name' => $journal['source_account_name'], - 'destination_account_id' => $journal['destination_account_id'], - 'destination_account_name' => $journal['destination_account_name'], - 'description' => $journal['description'], - 'transaction_group_id' => $journal['transaction_group_id'], - ]; - - } - - return $array; - } } diff --git a/app/Repositories/Category/OperationsRepositoryInterface.php b/app/Repositories/Category/OperationsRepositoryInterface.php index 38eab4b695..0f24e11ad5 100644 --- a/app/Repositories/Category/OperationsRepositoryInterface.php +++ b/app/Repositories/Category/OperationsRepositoryInterface.php @@ -47,6 +47,20 @@ interface OperationsRepositoryInterface */ public function listExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array; + /** + * This method returns a list of all the deposit transaction journals (as arrays) set in that period + * which have the specified category set to them. It's grouped per currency, with as few details in the array + * as possible. Amounts are always positive. + * + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories + * + * @return array + */ + public function listIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array; + /** * This method returns a list of all the transfer transaction journals (as arrays) set in that period * which have the specified category set to them, transferred INTO the listed accounts. @@ -55,7 +69,7 @@ interface OperationsRepositoryInterface * * @param Carbon $start * @param Carbon $end - * @param Collection $accounts + * @param Collection $accounts * @param Collection|null $categories * * @return array @@ -70,27 +84,13 @@ interface OperationsRepositoryInterface * * @param Carbon $start * @param Carbon $end - * @param Collection $accounts + * @param Collection $accounts * @param Collection|null $categories * * @return array */ public function listTransferredOut(Carbon $start, Carbon $end, Collection $accounts, ?Collection $categories = null): array; - /** - * This method returns a list of all the deposit transaction journals (as arrays) set in that period - * which have the specified category set to them. It's grouped per currency, with as few details in the array - * as possible. Amounts are always positive. - * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories - * - * @return array - */ - public function listIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array; - /** * @param User $user */ diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index 456008442b..204aa9af0a 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -48,19 +48,6 @@ class CurrencyRepository implements CurrencyRepositoryInterface { private User $user; - /** - * @param TransactionCurrency $currency - * - * @return int - */ - public function countJournals(TransactionCurrency $currency): int - { - $count = $currency->transactions()->whereNull('deleted_at')->count() + $currency->transactionJournals()->whereNull('deleted_at')->count(); - - // also count foreign: - return $count + Transaction::where('foreign_currency_id', $currency->id)->count(); - } - /** * @param TransactionCurrency $currency * @@ -98,7 +85,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface } // is being used in accounts: - $meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((string)$currency->id))->count(); + $meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((string) $currency->id))->count(); if ($meta > 0) { Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta)); @@ -127,7 +114,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface $meta = AccountMeta ::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') ->whereNull('accounts.deleted_at') - ->where('account_meta.name', 'currency_id')->where('account_meta.data', json_encode((int)$currency->id))->count(); + ->where('account_meta.name', 'currency_id')->where('account_meta.data', json_encode((int) $currency->id))->count(); if ($meta > 0) { Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta)); @@ -163,6 +150,27 @@ class CurrencyRepository implements CurrencyRepositoryInterface return null; } + /** + * @param TransactionCurrency $currency + * + * @return int + */ + public function countJournals(TransactionCurrency $currency): int + { + $count = $currency->transactions()->whereNull('deleted_at')->count() + $currency->transactionJournals()->whereNull('deleted_at')->count(); + + // also count foreign: + return $count + Transaction::where('foreign_currency_id', $currency->id)->count(); + } + + /** + * @return Collection + */ + public function getAll(): Collection + { + return TransactionCurrency::orderBy('code', 'ASC')->get(); + } + /** * @param TransactionCurrency $currency * @@ -192,40 +200,6 @@ class CurrencyRepository implements CurrencyRepositoryInterface $currency->save(); } - /** - * @param TransactionCurrency $currency - * Enables a currency - */ - public function enable(TransactionCurrency $currency): void - { - $currency->enabled = true; - $currency->save(); - } - - /** - * Find by ID, return NULL if not found. - * - * @param int $currencyId - * - * @return TransactionCurrency|null - */ - public function find(int $currencyId): ?TransactionCurrency - { - return TransactionCurrency::find($currencyId); - } - - /** - * Find by currency code, return NULL if unfound. - * - * @param string $currencyCode - * - * @return TransactionCurrency|null - */ - public function findByCode(string $currencyCode): ?TransactionCurrency - { - return TransactionCurrency::where('code', $currencyCode)->first(); - } - /** * Find by currency code, return NULL if unfound. * Used in Import Currency! @@ -333,10 +307,10 @@ class CurrencyRepository implements CurrencyRepositoryInterface public function findCurrencyNull(?int $currencyId, ?string $currencyCode): ?TransactionCurrency { Log::debug('Now in findCurrencyNull()'); - $result = $this->find((int)$currencyId); + $result = $this->find((int) $currencyId); if (null === $result) { Log::debug(sprintf('Searching for currency with code %s...', $currencyCode)); - $result = $this->findByCode((string)$currencyCode); + $result = $this->findByCode((string) $currencyCode); } if (null !== $result && false === $result->enabled) { Log::debug(sprintf('Also enabled currency %s', $result->code)); @@ -347,19 +321,45 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @return Collection + * Find by ID, return NULL if not found. + * + * @param int $currencyId + * + * @return TransactionCurrency|null */ - public function get(): Collection + public function find(int $currencyId): ?TransactionCurrency { - return TransactionCurrency::where('enabled', true)->orderBy('code', 'ASC')->get(); + return TransactionCurrency::find($currencyId); + } + + /** + * Find by currency code, return NULL if unfound. + * + * @param string $currencyCode + * + * @return TransactionCurrency|null + */ + public function findByCode(string $currencyCode): ?TransactionCurrency + { + return TransactionCurrency::where('code', $currencyCode)->first(); + } + + /** + * @param TransactionCurrency $currency + * Enables a currency + */ + public function enable(TransactionCurrency $currency): void + { + $currency->enabled = true; + $currency->save(); } /** * @return Collection */ - public function getAll(): Collection + public function get(): Collection { - return TransactionCurrency::orderBy('code', 'ASC')->get(); + return TransactionCurrency::where('enabled', true)->orderBy('code', 'ASC')->get(); } /** diff --git a/app/Repositories/Journal/JournalAPIRepository.php b/app/Repositories/Journal/JournalAPIRepository.php index 7bee05f256..ea86e6f1e2 100644 --- a/app/Repositories/Journal/JournalAPIRepository.php +++ b/app/Repositories/Journal/JournalAPIRepository.php @@ -69,9 +69,9 @@ class JournalAPIRepository implements JournalAPIRepositoryInterface return $set->each( static function (Attachment $attachment) use ($disk) { - $notes = $attachment->notes()->first(); + $notes = $attachment->notes()->first(); $attachment->file_exists = $disk->exists($attachment->fileName()); - $attachment->notes = $notes ? $notes->text : ''; + $attachment->notes = $notes ? $notes->text : ''; return $attachment; } diff --git a/app/Repositories/Journal/JournalCLIRepository.php b/app/Repositories/Journal/JournalCLIRepository.php index 8f35ff4b22..70e8ac9850 100644 --- a/app/Repositories/Journal/JournalCLIRepository.php +++ b/app/Repositories/Journal/JournalCLIRepository.php @@ -190,7 +190,7 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface } // return when something else: - $return = (string)$value; + $return = (string) $value; try { $cache->store($return); } catch (Exception $e) { // @phpstan-ignore-line @@ -232,8 +232,8 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface $journalIds = []; /** @var stdClass $row */ foreach ($result as $row) { - if ((int)$row->transaction_count > 2) { - $journalIds[] = (int)$row->id; + if ((int) $row->transaction_count > 2) { + $journalIds[] = (int) $row->id; } } $journalIds = array_unique($journalIds); diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index ab33d71f2f..c8bdf649ac 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -143,7 +143,7 @@ class JournalRepository implements JournalRepositoryInterface // saves on queries: $amount = $journal->transactions()->where('amount', '>', 0)->get()->sum('amount'); - $amount = (string)$amount; + $amount = (string) $amount; $cache->store($amount); return $amount; diff --git a/app/Repositories/LinkType/LinkTypeRepository.php b/app/Repositories/LinkType/LinkTypeRepository.php index 1b23de45ef..c7ecd437c7 100644 --- a/app/Repositories/LinkType/LinkTypeRepository.php +++ b/app/Repositories/LinkType/LinkTypeRepository.php @@ -80,30 +80,6 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return true; } - /** - * @param int $linkTypeId - * - * @return LinkType|null - */ - public function find(int $linkTypeId): ?LinkType - { - return LinkType::find($linkTypeId); - } - - /** - * @param string|null $name - * - * @return LinkType|null - */ - public function findByName(string $name = null): ?LinkType - { - if (null === $name) { - return null; - } - - return LinkType::where('name', $name)->first(); - } - /** * Check if link exists between journals. * @@ -121,24 +97,6 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return $count + $opposingCount > 0; } - /** - * See if such a link already exists (and get it). - * - * @param LinkType $linkType - * @param TransactionJournal $inward - * @param TransactionJournal $outward - * - * @return TransactionJournalLink|null - */ - public function findSpecificLink(LinkType $linkType, TransactionJournal $inward, TransactionJournal $outward): ?TransactionJournalLink - { - return TransactionJournalLink - ::where('link_type_id', $linkType->id) - ->where('source_id', $inward->id) - ->where('destination_id', $outward->id)->first(); - - } - /** * @return Collection */ @@ -188,6 +146,16 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return $query->get(['journal_links.*']); } + public function getLink(TransactionJournal $one, TransactionJournal $two): ?TransactionJournalLink + { + $left = TransactionJournalLink::whereDestinationId($one->id)->whereSourceId($two->id)->first(); + if (null !== $left) { + return $left; + } + + return TransactionJournalLink::whereDestinationId($two->id)->whereSourceId($one->id)->first(); + } + /** * Return list of existing connections. * @@ -245,7 +213,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface */ public function storeLink(array $information, TransactionJournal $inward, TransactionJournal $outward): ?TransactionJournalLink { - $linkType = $this->find((int)($information['link_type_id'] ?? 0)); + $linkType = $this->find((int) ($information['link_type_id'] ?? 0)); if (null === $linkType) { $linkType = $this->findByName($information['link_type_name']); @@ -277,11 +245,96 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface $link->save(); // make note in noteable: - $this->setNoteText($link, (string)$information['notes']); + $this->setNoteText($link, (string) $information['notes']); return $link; } + /** + * @param int $linkTypeId + * + * @return LinkType|null + */ + public function find(int $linkTypeId): ?LinkType + { + return LinkType::find($linkTypeId); + } + + /** + * @param string|null $name + * + * @return LinkType|null + */ + public function findByName(string $name = null): ?LinkType + { + if (null === $name) { + return null; + } + + return LinkType::where('name', $name)->first(); + } + + /** + * See if such a link already exists (and get it). + * + * @param LinkType $linkType + * @param TransactionJournal $inward + * @param TransactionJournal $outward + * + * @return TransactionJournalLink|null + */ + public function findSpecificLink(LinkType $linkType, TransactionJournal $inward, TransactionJournal $outward): ?TransactionJournalLink + { + return TransactionJournalLink + ::where('link_type_id', $linkType->id) + ->where('source_id', $inward->id) + ->where('destination_id', $outward->id)->first(); + + } + + /** + * @param TransactionJournalLink $link + * @param string $text + * + * @throws Exception + */ + private function setNoteText(TransactionJournalLink $link, string $text): void + { + $dbNote = $link->notes()->first(); + if ('' !== $text) { + if (null === $dbNote) { + $dbNote = new Note(); + $dbNote->noteable()->associate($link); + } + $dbNote->text = trim($text); + $dbNote->save(); + + return; + } + if (null !== $dbNote && '' === $text) { + try { + $dbNote->delete(); + } catch (Exception $e) { // @phpstan-ignore-line + // @ignoreException + } + } + + } + + /** + * @inheritDoc + */ + public function switchLinkById(int $linkId): bool + { + /** @var TransactionJournalLink $link */ + $link = TransactionJournalLink::find($linkId); + if (null !== $link && $link->source->user->id === $this->user->id) { + $this->switchLink($link); + } + + return true; + } + /** * @param TransactionJournalLink $link * @@ -305,13 +358,13 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface */ public function update(LinkType $linkType, array $data): LinkType { - if (array_key_exists('name', $data) && '' !== (string)$data['name']) { + if (array_key_exists('name', $data) && '' !== (string) $data['name']) { $linkType->name = $data['name']; } - if (array_key_exists('inward', $data) && '' !== (string)$data['inward']) { + if (array_key_exists('inward', $data) && '' !== (string) $data['inward']) { $linkType->inward = $data['inward']; } - if (array_key_exists('outward', $data) && '' !== (string)$data['outward']) { + if (array_key_exists('outward', $data) && '' !== (string) $data['outward']) { $linkType->outward = $data['outward']; } $linkType->save(); @@ -350,57 +403,4 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return $journalLink; } - - /** - * @param TransactionJournalLink $link - * @param string $text - * - * @throws Exception - */ - private function setNoteText(TransactionJournalLink $link, string $text): void - { - $dbNote = $link->notes()->first(); - if ('' !== $text) { - if (null === $dbNote) { - $dbNote = new Note(); - $dbNote->noteable()->associate($link); - } - $dbNote->text = trim($text); - $dbNote->save(); - - return; - } - if (null !== $dbNote && '' === $text) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - } - - } - - public function getLink(TransactionJournal $one, TransactionJournal $two): ?TransactionJournalLink - { - $left = TransactionJournalLink::whereDestinationId($one->id)->whereSourceId($two->id)->first(); - if (null !== $left) { - return $left; - } - - return TransactionJournalLink::whereDestinationId($two->id)->whereSourceId($one->id)->first(); - } - - /** - * @inheritDoc - */ - public function switchLinkById(int $linkId): bool - { - /** @var TransactionJournalLink $link */ - $link = TransactionJournalLink::find($linkId); - if (null !== $link && $link->source->user->id === $this->user->id) { - $this->switchLink($link); - } - - return true; - } } diff --git a/app/Repositories/ObjectGroup/CreatesObjectGroups.php b/app/Repositories/ObjectGroup/CreatesObjectGroups.php index 69fadd48d0..da4f22897b 100644 --- a/app/Repositories/ObjectGroup/CreatesObjectGroups.php +++ b/app/Repositories/ObjectGroup/CreatesObjectGroups.php @@ -67,7 +67,7 @@ trait CreatesObjectGroups */ protected function getObjectGroupMaxOrder(): int { - return (int)$this->user->objectGroups()->max('order'); + return (int) $this->user->objectGroups()->max('order'); } /** diff --git a/app/Repositories/ObjectGroup/ObjectGroupRepository.php b/app/Repositories/ObjectGroup/ObjectGroupRepository.php index b86efc0bb4..72758404d7 100644 --- a/app/Repositories/ObjectGroup/ObjectGroupRepository.php +++ b/app/Repositories/ObjectGroup/ObjectGroupRepository.php @@ -52,6 +52,17 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface } } + /** + * @inheritDoc + */ + public function get(): Collection + { + return $this->user->objectGroups() + ->with(['piggyBanks', 'bills']) + ->orderBy('order', 'ASC') + ->orderBy('title', 'ASC')->get(); + } + /** * @inheritDoc */ @@ -81,17 +92,6 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface $objectGroup->delete(); } - /** - * @inheritDoc - */ - public function get(): Collection - { - return $this->user->objectGroups() - ->with(['piggyBanks', 'bills']) - ->orderBy('order', 'ASC') - ->orderBy('title', 'ASC')->get(); - } - /** * @inheritDoc */ @@ -118,7 +118,7 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface $index = 1; /** @var ObjectGroup $objectGroup */ foreach ($list as $objectGroup) { - if ($index !== (int)$objectGroup->order) { + if ($index !== (int) $objectGroup->order) { Log::debug( sprintf('objectGroup #%d ("%s"): order should %d be but is %d.', $objectGroup->id, $objectGroup->title, $index, $objectGroup->order) ); @@ -151,12 +151,38 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface return $dbQuery->take($limit)->get(['object_groups.*']); } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @inheritDoc + */ + public function update(ObjectGroup $objectGroup, array $data): ObjectGroup + { + if (array_key_exists('title', $data)) { + $objectGroup->title = $data['title']; + } + + if (array_key_exists('order', $data)) { + $this->setOrder($objectGroup, (int) $data['order']); + } + + $objectGroup->save(); + + return $objectGroup; + } + /** * @inheritDoc */ public function setOrder(ObjectGroup $objectGroup, int $newOrder): ObjectGroup { - $oldOrder = (int)$objectGroup->order; + $oldOrder = (int) $objectGroup->order; if ($newOrder > $oldOrder) { $this->user->objectGroups()->where('object_groups.order', '<=', $newOrder)->where('object_groups.order', '>', $oldOrder) @@ -179,30 +205,4 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface return $objectGroup; } - - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @inheritDoc - */ - public function update(ObjectGroup $objectGroup, array $data): ObjectGroup - { - if (array_key_exists('title', $data)) { - $objectGroup->title = $data['title']; - } - - if (array_key_exists('order', $data)) { - $this->setOrder($objectGroup, (int)$data['order']); - } - - $objectGroup->save(); - - return $objectGroup; - } } diff --git a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php index 1a84c1fd33..99f093f9a5 100644 --- a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php +++ b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php @@ -127,21 +127,6 @@ trait ModifiesPiggyBanks return bccomp($amount, $savedSoFar) <= 0; } - /** - * @param PiggyBank $piggyBank - * @param string $amount - * - * @return PiggyBankEvent - */ - public function createEvent(PiggyBank $piggyBank, string $amount): PiggyBankEvent - { - if (0 === bccomp('0', $amount)) { - return new PiggyBankEvent; - } - - return PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]); - } - /** * @param PiggyBank $piggyBank * @param string $amount @@ -195,6 +180,21 @@ trait ModifiesPiggyBanks return true; } + /** + * @param PiggyBank $piggyBank + * @param string $amount + * + * @return PiggyBankEvent + */ + public function createEvent(PiggyBank $piggyBank, string $amount): PiggyBankEvent + { + if (0 === bccomp('0', $amount)) { + return new PiggyBankEvent; + } + + return PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]); + } + /** * @inheritDoc */ @@ -205,23 +205,6 @@ trait ModifiesPiggyBanks return $piggyBank; } - /** - * Correct order of piggies in case of issues. - */ - public function resetOrder(): void - { - $set = $this->user->piggyBanks()->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']); - $current = 1; - foreach ($set as $piggyBank) { - if ((int) $piggyBank->order !== $current) { - Log::debug(sprintf('Piggy bank #%d ("%s") was at place %d but should be on %d', $piggyBank->id, $piggyBank->name, $piggyBank->order, $current)); - $piggyBank->order = $current; - $piggyBank->save(); - } - $current++; - } - } - /** * @param PiggyBank $piggyBank * @param string $amount @@ -262,34 +245,6 @@ trait ModifiesPiggyBanks } - /** - * @inheritDoc - */ - public function setOrder(PiggyBank $piggyBank, int $newOrder): bool - { - $oldOrder = (int) $piggyBank->order; - Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder)); - if ($newOrder > $oldOrder) { - $this->user->piggyBanks()->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder) - ->where('piggy_banks.id', '!=', $piggyBank->id) - ->decrement('piggy_banks.order'); - $piggyBank->order = $newOrder; - Log::debug(sprintf('Order of piggy #%d ("%s") is now %d', $piggyBank->id, $piggyBank->name, $newOrder)); - $piggyBank->save(); - - return true; - } - - $this->user->piggyBanks()->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder) - ->where('piggy_banks.id', '!=', $piggyBank->id) - ->increment('piggy_banks.order'); - $piggyBank->order = $newOrder; - Log::debug(sprintf('Order of piggy #%d ("%s") is now %d', $piggyBank->id, $piggyBank->name, $newOrder)); - $piggyBank->save(); - - return true; - } - /** * @param array $data * @@ -349,6 +304,82 @@ trait ModifiesPiggyBanks return $piggyBank; } + /** + * Correct order of piggies in case of issues. + */ + public function resetOrder(): void + { + $set = $this->user->piggyBanks()->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']); + $current = 1; + foreach ($set as $piggyBank) { + if ((int) $piggyBank->order !== $current) { + Log::debug(sprintf('Piggy bank #%d ("%s") was at place %d but should be on %d', $piggyBank->id, $piggyBank->name, $piggyBank->order, $current)); + $piggyBank->order = $current; + $piggyBank->save(); + } + $current++; + } + } + + /** + * @inheritDoc + */ + public function setOrder(PiggyBank $piggyBank, int $newOrder): bool + { + $oldOrder = (int) $piggyBank->order; + Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder)); + if ($newOrder > $oldOrder) { + $this->user->piggyBanks()->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder) + ->where('piggy_banks.id', '!=', $piggyBank->id) + ->decrement('piggy_banks.order'); + $piggyBank->order = $newOrder; + Log::debug(sprintf('Order of piggy #%d ("%s") is now %d', $piggyBank->id, $piggyBank->name, $newOrder)); + $piggyBank->save(); + + return true; + } + + $this->user->piggyBanks()->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder) + ->where('piggy_banks.id', '!=', $piggyBank->id) + ->increment('piggy_banks.order'); + $piggyBank->order = $newOrder; + Log::debug(sprintf('Order of piggy #%d ("%s") is now %d', $piggyBank->id, $piggyBank->name, $newOrder)); + $piggyBank->save(); + + return true; + } + + /** + * @param PiggyBank $piggyBank + * @param string $note + * + * @return bool + */ + private function updateNote(PiggyBank $piggyBank, string $note): bool + { + if ('' === $note) { + $dbNote = $piggyBank->notes()->first(); + if (null !== $dbNote) { + try { + $dbNote->delete(); + } catch (Exception $e) { // @phpstan-ignore-line + // @ignoreException + } + } + + return true; + } + $dbNote = $piggyBank->notes()->first(); + if (null === $dbNote) { + $dbNote = new Note; + $dbNote->noteable()->associate($piggyBank); + } + $dbNote->text = trim($note); + $dbNote->save(); + + return true; + } + /** * @param PiggyBank $piggyBank * @param array $data @@ -416,37 +447,6 @@ trait ModifiesPiggyBanks return $piggyBank; } - /** - * @param PiggyBank $piggyBank - * @param string $note - * - * @return bool - */ - private function updateNote(PiggyBank $piggyBank, string $note): bool - { - if ('' === $note) { - $dbNote = $piggyBank->notes()->first(); - if (null !== $dbNote) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - } - - return true; - } - $dbNote = $piggyBank->notes()->first(); - if (null === $dbNote) { - $dbNote = new Note; - $dbNote->noteable()->associate($piggyBank); - } - $dbNote->text = trim($note); - $dbNote->save(); - - return true; - } - /** * @param PiggyBank $piggyBank * @param array $data diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index 62acee3803..dce7b7adc0 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -54,6 +54,37 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface $this->user->piggyBanks()->delete(); } + /** + * @param int|null $piggyBankId + * @param string|null $piggyBankName + * + * @return PiggyBank|null + */ + public function findPiggyBank(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank + { + Log::debug('Searching for piggy information.'); + + if (null !== $piggyBankId) { + $searchResult = $this->find((int) $piggyBankId); + if (null !== $searchResult) { + Log::debug(sprintf('Found piggy based on #%d, will return it.', $piggyBankId)); + + return $searchResult; + } + } + if (null !== $piggyBankName) { + $searchResult = $this->findByName((string) $piggyBankName); + if (null !== $searchResult) { + Log::debug(sprintf('Found piggy based on "%s", will return it.', $piggyBankName)); + + return $searchResult; + } + } + Log::debug('Found nothing'); + + return null; + } + /** * @param int $piggyBankId * @@ -76,37 +107,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return $this->user->piggyBanks()->where('piggy_banks.name', $name)->first(['piggy_banks.*']); } - /** - * @param int|null $piggyBankId - * @param string|null $piggyBankName - * - * @return PiggyBank|null - */ - public function findPiggyBank(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank - { - Log::debug('Searching for piggy information.'); - - if (null !== $piggyBankId) { - $searchResult = $this->find((int)$piggyBankId); - if (null !== $searchResult) { - Log::debug(sprintf('Found piggy based on #%d, will return it.', $piggyBankId)); - - return $searchResult; - } - } - if (null !== $piggyBankName) { - $searchResult = $this->findByName((string)$piggyBankName); - if (null !== $searchResult) { - Log::debug(sprintf('Found piggy based on "%s", will return it.', $piggyBankName)); - - return $searchResult; - } - } - Log::debug('Found nothing'); - - return null; - } - /** * @inheritDoc */ @@ -142,7 +142,17 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return '0'; } - return (string)$rep->currentamount; + return (string) $rep->currentamount; + } + + /** + * @param PiggyBank $piggyBank + * + * @return PiggyBankRepetition|null + */ + public function getRepetition(PiggyBank $piggyBank): ?PiggyBankRepetition + { + return $piggyBank->piggyBankRepetitions()->first(); } /** @@ -210,11 +220,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface // currency of the account + the piggy bank currency are almost the same. // which amount from the transaction matches? $amount = null; - if ((int)$source->transaction_currency_id === (int)$currency->id) { + if ((int) $source->transaction_currency_id === (int) $currency->id) { Log::debug('Use normal amount'); $amount = app('steam')->$operator($source->amount); } - if ((int)$source->foreign_currency_id === (int)$currency->id) { + if ((int) $source->foreign_currency_id === (int) $currency->id) { Log::debug('Use foreign amount'); $amount = app('steam')->$operator($source->foreign_amount); } @@ -225,7 +235,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface } Log::debug(sprintf('The currency is %s and the amount is %s', $currency->code, $amount)); - $room = bcsub((string)$piggyBank->targetamount, (string)$repetition->currentamount); + $room = bcsub((string) $piggyBank->targetamount, (string) $repetition->currentamount); $compare = bcmul($repetition->currentamount, '-1'); Log::debug(sprintf('Will add/remove %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name)); @@ -248,7 +258,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return $compare; } - return (string)$amount; + return (string) $amount; } /** @@ -256,7 +266,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface */ public function getMaxOrder(): int { - return (int)$this->user->piggyBanks()->max('piggy_banks.order'); + return (int) $this->user->piggyBanks()->max('piggy_banks.order'); } /** @@ -277,14 +287,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return $note->text; } - /** - * @return Collection - */ - public function getPiggyBanks(): Collection - { - return $this->user->piggyBanks()->with(['account', 'objectGroups'])->orderBy('order', 'ASC')->get(); - } - /** * Also add amount in name. * @@ -307,13 +309,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface } /** - * @param PiggyBank $piggyBank - * - * @return PiggyBankRepetition|null + * @return Collection */ - public function getRepetition(PiggyBank $piggyBank): ?PiggyBankRepetition + public function getPiggyBanks(): Collection { - return $piggyBank->piggyBankRepetitions()->first(); + return $this->user->piggyBanks()->with(['account', 'objectGroups'])->orderBy('order', 'ASC')->get(); } /** @@ -338,7 +338,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface // more than 1 month to go and still need money to save: if ($diffInMonths > 0 && 1 === bccomp($remainingAmount, '0')) { - $savePerMonth = bcdiv($remainingAmount, (string)$diffInMonths); + $savePerMonth = bcdiv($remainingAmount, (string) $diffInMonths); } // less than 1 month to go but still need money to save: diff --git a/app/Repositories/Recurring/RecurringRepository.php b/app/Repositories/Recurring/RecurringRepository.php index 40ab69cb05..e1ba67d01d 100644 --- a/app/Repositories/Recurring/RecurringRepository.php +++ b/app/Repositories/Recurring/RecurringRepository.php @@ -107,6 +107,22 @@ class RecurringRepository implements RecurringRepositoryInterface ->get(); } + /** + * @inheritDoc + */ + public function getBillId(RecurrenceTransaction $recTransaction): ?int + { + $return = null; + /** @var RecurrenceTransactionMeta $meta */ + foreach ($recTransaction->recurrenceTransactionMeta as $meta) { + if ('bill_id' === $meta->name) { + $return = (int) $meta->value; + } + } + + return $return; + } + /** * Get the budget ID from a recurring transaction transaction. * @@ -120,7 +136,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $meta */ foreach ($recTransaction->recurrenceTransactionMeta as $meta) { if ('budget_id' === $meta->name) { - $return = (int)$meta->value; + $return = (int) $meta->value; } } @@ -140,7 +156,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $meta */ foreach ($recTransaction->recurrenceTransactionMeta as $meta) { if ('category_id' === $meta->name) { - $return = (int)$meta->value; + $return = (int) $meta->value; } } @@ -160,7 +176,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $meta */ foreach ($recTransaction->recurrenceTransactionMeta as $meta) { if ('category_name' === $meta->name) { - $return = (string)$meta->value; + $return = (string) $meta->value; } } @@ -206,7 +222,7 @@ class RecurringRepository implements RecurringRepositoryInterface return TransactionJournalMeta::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') ->where('transaction_journals.user_id', $this->user->id) ->where('journal_meta.name', '=', 'recurrence_id') - ->where('journal_meta.data', '=', json_encode((string)$recurrence->id)) + ->where('journal_meta.data', '=', json_encode((string) $recurrence->id)) ->get(['journal_meta.transaction_journal_id'])->pluck('transaction_journal_id')->toArray(); } @@ -222,51 +238,12 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var Note $note */ $note = $recurrence->notes()->first(); if (null !== $note) { - return (string)$note->text; + return (string) $note->text; } return ''; } - /** - * Generate events in the date range. - * - * @param RecurrenceRepetition $repetition - * @param Carbon $start - * @param Carbon $end - * - * @return array - * - */ - public function getOccurrencesInRange(RecurrenceRepetition $repetition, Carbon $start, Carbon $end): array - { - $occurrences = []; - $mutator = clone $start; - $mutator->startOfDay(); - $skipMod = $repetition->repetition_skip + 1; - Log::debug(sprintf('Calculating occurrences for rep type "%s"', $repetition->repetition_type)); - Log::debug(sprintf('Mutator is now: %s', $mutator->format('Y-m-d'))); - - if ('daily' === $repetition->repetition_type) { - $occurrences = $this->getDailyInRange($mutator, $end, $skipMod); - } - if ('weekly' === $repetition->repetition_type) { - $occurrences = $this->getWeeklyInRange($mutator, $end, $skipMod, $repetition->repetition_moment); - } - if ('monthly' === $repetition->repetition_type) { - $occurrences = $this->getMonthlyInRange($mutator, $end, $skipMod, $repetition->repetition_moment); - } - if ('ndom' === $repetition->repetition_type) { - $occurrences = $this->getNdomInRange($mutator, $end, $skipMod, $repetition->repetition_moment); - } - if ('yearly' === $repetition->repetition_type) { - $occurrences = $this->getYearlyInRange($mutator, $end, $skipMod, $repetition->repetition_moment); - } - - // filter out all the weekend days: - return $this->filterWeekends($repetition, $occurrences); - } - /** * @param RecurrenceTransaction $transaction * @@ -278,7 +255,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $metaEntry */ foreach ($meta as $metaEntry) { if ('piggy_bank_id' === $metaEntry->name) { - return (int)$metaEntry->value; + return (int) $metaEntry->value; } } @@ -320,11 +297,11 @@ class RecurringRepository implements RecurringRepositoryInterface ->whereNull('transaction_journals.deleted_at') ->where('transaction_journals.user_id', $this->user->id) ->where('name', 'recurrence_id') - ->where('data', json_encode((string)$recurrence->id)) + ->where('data', json_encode((string) $recurrence->id)) ->get()->pluck('transaction_journal_id')->toArray(); $search = []; foreach ($journalMeta as $journalId) { - $search[] = (int)$journalId; + $search[] = (int) $journalId; } /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -349,12 +326,12 @@ class RecurringRepository implements RecurringRepositoryInterface ->whereNull('transaction_journals.deleted_at') ->where('transaction_journals.user_id', $this->user->id) ->where('name', 'recurrence_id') - ->where('data', json_encode((string)$recurrence->id)) + ->where('data', json_encode((string) $recurrence->id)) ->get()->pluck('transaction_journal_id')->toArray(); $search = []; foreach ($journalMeta as $journalId) { - $search[] = (int)$journalId; + $search[] = (int) $journalId; } if (empty($search)) { @@ -449,6 +426,27 @@ class RecurringRepository implements RecurringRepositoryInterface return $this->filterMaxDate($repeatUntil, $occurrences); } + /** + * @param Carbon|null $max + * @param array $occurrences + * + * @return array + */ + private function filterMaxDate(?Carbon $max, array $occurrences): array + { + if (null === $max) { + return $occurrences; + } + $filtered = []; + foreach ($occurrences as $date) { + if ($date->lte($max)) { + $filtered[] = $date; + } + } + + return $filtered; + } + /** * Parse the repetition in a string that is user readable. * @@ -464,25 +462,25 @@ class RecurringRepository implements RecurringRepositoryInterface $pref = app('preferences')->getForUser($this->user, 'language', config('firefly.default_language', 'en_US')); $language = $pref->data; if ('daily' === $repetition->repetition_type) { - return (string)trans('firefly.recurring_daily', [], $language); + return (string) trans('firefly.recurring_daily', [], $language); } if ('weekly' === $repetition->repetition_type) { $dayOfWeek = trans(sprintf('config.dow_%s', $repetition->repetition_moment), [], $language); if ($repetition->repetition_skip > 0) { - return (string)trans('firefly.recurring_weekly_skip', ['weekday' => $dayOfWeek, 'skip' => $repetition->repetition_skip + 1], $language); + return (string) trans('firefly.recurring_weekly_skip', ['weekday' => $dayOfWeek, 'skip' => $repetition->repetition_skip + 1], $language); } - return (string)trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek], $language); + return (string) trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek], $language); } if ('monthly' === $repetition->repetition_type) { if ($repetition->repetition_skip > 0) { - return (string)trans( + return (string) trans( 'firefly.recurring_monthly_skip', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip + 1], $language ); } - return (string)trans( + return (string) trans( 'firefly.recurring_monthly', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], $language ); } @@ -491,7 +489,7 @@ class RecurringRepository implements RecurringRepositoryInterface // first part is number of week, second is weekday. $dayOfWeek = trans(sprintf('config.dow_%s', $parts[1]), [], $language); - return (string)trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $parts[0]], $language); + return (string) trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $parts[0]], $language); } if ('yearly' === $repetition->repetition_type) { // @@ -499,9 +497,9 @@ class RecurringRepository implements RecurringRepositoryInterface $repDate = Carbon::createFromFormat('Y-m-d', $repetition->repetition_moment); $diffInYears = $today->diffInYears($repDate); $repDate->addYears($diffInYears); // technically not necessary. - $string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js')); + $string = $repDate->isoFormat((string) trans('config.month_and_day_no_year_js')); - return (string)trans('firefly.recurring_yearly', ['date' => $string], $language); + return (string) trans('firefly.recurring_yearly', ['date' => $string], $language); } return ''; @@ -558,16 +556,16 @@ class RecurringRepository implements RecurringRepositoryInterface public function totalTransactions(Recurrence $recurrence, RecurrenceRepetition $repetition): int { // if repeat = null just return 0. - if (null === $recurrence->repeat_until && 0 === (int)$recurrence->repetitions) { + if (null === $recurrence->repeat_until && 0 === (int) $recurrence->repetitions) { return 0; } // expect X transactions then stop. Return that number - if (null === $recurrence->repeat_until && 0 !== (int)$recurrence->repetitions) { - return (int)$recurrence->repetitions; + if (null === $recurrence->repeat_until && 0 !== (int) $recurrence->repetitions) { + return (int) $recurrence->repetitions; } // need to calculate, this depends on the repetition: - if (null !== $recurrence->repeat_until && 0 === (int)$recurrence->repetitions) { + if (null !== $recurrence->repeat_until && 0 === (int) $recurrence->repetitions) { $occurrences = $this->getOccurrencesInRange($repetition, $recurrence->first_date ?? today(), $recurrence->repeat_until); return count($occurrences); @@ -576,6 +574,45 @@ class RecurringRepository implements RecurringRepositoryInterface return 0; } + /** + * Generate events in the date range. + * + * @param RecurrenceRepetition $repetition + * @param Carbon $start + * @param Carbon $end + * + * @return array + * + */ + public function getOccurrencesInRange(RecurrenceRepetition $repetition, Carbon $start, Carbon $end): array + { + $occurrences = []; + $mutator = clone $start; + $mutator->startOfDay(); + $skipMod = $repetition->repetition_skip + 1; + Log::debug(sprintf('Calculating occurrences for rep type "%s"', $repetition->repetition_type)); + Log::debug(sprintf('Mutator is now: %s', $mutator->format('Y-m-d'))); + + if ('daily' === $repetition->repetition_type) { + $occurrences = $this->getDailyInRange($mutator, $end, $skipMod); + } + if ('weekly' === $repetition->repetition_type) { + $occurrences = $this->getWeeklyInRange($mutator, $end, $skipMod, $repetition->repetition_moment); + } + if ('monthly' === $repetition->repetition_type) { + $occurrences = $this->getMonthlyInRange($mutator, $end, $skipMod, $repetition->repetition_moment); + } + if ('ndom' === $repetition->repetition_type) { + $occurrences = $this->getNdomInRange($mutator, $end, $skipMod, $repetition->repetition_moment); + } + if ('yearly' === $repetition->repetition_type) { + $occurrences = $this->getYearlyInRange($mutator, $end, $skipMod, $repetition->repetition_moment); + } + + // filter out all the weekend days: + return $this->filterWeekends($repetition, $occurrences); + } + /** * Update a recurring transaction. * @@ -592,41 +629,4 @@ class RecurringRepository implements RecurringRepositoryInterface return $service->update($recurrence, $data); } - - /** - * @param Carbon|null $max - * @param array $occurrences - * - * @return array - */ - private function filterMaxDate(?Carbon $max, array $occurrences): array - { - if (null === $max) { - return $occurrences; - } - $filtered = []; - foreach ($occurrences as $date) { - if ($date->lte($max)) { - $filtered[] = $date; - } - } - - return $filtered; - } - - /** - * @inheritDoc - */ - public function getBillId(RecurrenceTransaction $recTransaction): ?int - { - $return = null; - /** @var RecurrenceTransactionMeta $meta */ - foreach ($recTransaction->recurrenceTransactionMeta as $meta) { - if ('bill_id' === $meta->name) { - $return = (int)$meta->value; - } - } - - return $return; - } } diff --git a/app/Repositories/Recurring/RecurringRepositoryInterface.php b/app/Repositories/Recurring/RecurringRepositoryInterface.php index 037791c4a6..08ceab085a 100644 --- a/app/Repositories/Recurring/RecurringRepositoryInterface.php +++ b/app/Repositories/Recurring/RecurringRepositoryInterface.php @@ -64,6 +64,15 @@ interface RecurringRepositoryInterface */ public function getAll(): Collection; + /** + * Get the category from a recurring transaction transaction. + * + * @param RecurrenceTransaction $recTransaction + * + * @return null|int + */ + public function getBillId(RecurrenceTransaction $recTransaction): ?int; + /** * Get the budget ID from a recurring transaction transaction. * @@ -82,15 +91,6 @@ interface RecurringRepositoryInterface */ public function getCategoryId(RecurrenceTransaction $recTransaction): ?int; - /** - * Get the category from a recurring transaction transaction. - * - * @param RecurrenceTransaction $recTransaction - * - * @return null|int - */ - public function getBillId(RecurrenceTransaction $recTransaction): ?int; - /** * Get the category from a recurring transaction transaction. * diff --git a/app/Repositories/Rule/RuleRepository.php b/app/Repositories/Rule/RuleRepository.php index b709156db8..60a3f579f0 100644 --- a/app/Repositories/Rule/RuleRepository.php +++ b/app/Repositories/Rule/RuleRepository.php @@ -76,7 +76,7 @@ class RuleRepository implements RuleRepositoryInterface public function duplicate(Rule $rule): Rule { $newRule = $rule->replicate(); - $newRule->title = (string)trans('firefly.rule_copy_of', ['title' => $rule->title]); + $newRule->title = (string) trans('firefly.rule_copy_of', ['title' => $rule->title]); $newRule->save(); // replicate all triggers @@ -135,7 +135,7 @@ class RuleRepository implements RuleRepositoryInterface */ public function getHighestOrderInRuleGroup(RuleGroup $ruleGroup): int { - return (int)$ruleGroup->rules()->max('order'); + return (int) $ruleGroup->rules()->max('order'); } /** @@ -253,43 +253,6 @@ class RuleRepository implements RuleRepositoryInterface return $filtered; } - /** - * @inheritDoc - */ - public function maxOrder(RuleGroup $ruleGroup): int - { - return (int)$ruleGroup->rules()->max('order'); - } - - /** - * @inheritDoc - */ - public function moveRule(Rule $rule, RuleGroup $ruleGroup, int $order): Rule - { - if ($rule->rule_group_id !== $ruleGroup->id) { - $rule->rule_group_id = $ruleGroup->id; - } - $rule->save(); - $rule->refresh(); - $this->setOrder($rule, $order); - - return $rule; - } - - /** - * @param RuleGroup $ruleGroup - * - * @return bool - */ - public function resetRuleOrder(RuleGroup $ruleGroup): bool - { - $groupRepository = app(RuleGroupRepositoryInterface::class); - $groupRepository->setUser($ruleGroup->user); - $groupRepository->resetRuleOrder($ruleGroup); - - return true; - } - /** * @inheritDoc */ @@ -305,42 +268,6 @@ class RuleRepository implements RuleRepositoryInterface return $search->take($limit)->get(['id', 'title', 'description']); } - /** - * @inheritDoc - */ - public function setOrder(Rule $rule, int $newOrder): void - { - $oldOrder = (int)$rule->order; - $groupId = (int)$rule->rule_group_id; - $maxOrder = $this->maxOrder($rule->ruleGroup); - $newOrder = $newOrder > $maxOrder ? $maxOrder + 1 : $newOrder; - Log::debug(sprintf('New order will be %d', $newOrder)); - - if ($newOrder > $oldOrder) { - $this->user->rules() - ->where('rules.rule_group_id', $groupId) - ->where('rules.order', '<=', $newOrder) - ->where('rules.order', '>', $oldOrder) - ->where('rules.id', '!=', $rule->id) - ->decrement('rules.order'); - $rule->order = $newOrder; - Log::debug(sprintf('Order of rule #%d ("%s") is now %d', $rule->id, $rule->title, $newOrder)); - $rule->save(); - - return; - } - - $this->user->rules() - ->where('rules.rule_group_id', $groupId) - ->where('rules.order', '>=', $newOrder) - ->where('rules.order', '<', $oldOrder) - ->where('rules.id', '!=', $rule->id) - ->increment('rules.order'); - $rule->order = $newOrder; - Log::debug(sprintf('Order of rule #%d ("%s") is now %d', $rule->id, $rule->title, $newOrder)); - $rule->save(); - } - /** * @param User $user */ @@ -403,104 +330,6 @@ class RuleRepository implements RuleRepositoryInterface return $rule; } - /** - * @param Rule $rule - * @param array $values - * - * @return RuleAction - */ - public function storeAction(Rule $rule, array $values): RuleAction - { - $ruleAction = new RuleAction; - $ruleAction->rule()->associate($rule); - $ruleAction->order = $values['order']; - $ruleAction->active = $values['active']; - $ruleAction->stop_processing = $values['stop_processing']; - $ruleAction->action_type = $values['action']; - $ruleAction->action_value = $values['value'] ?? ''; - $ruleAction->save(); - - return $ruleAction; - } - - /** - * @param Rule $rule - * @param array $values - * - * @return RuleTrigger - */ - public function storeTrigger(Rule $rule, array $values): RuleTrigger - { - $ruleTrigger = new RuleTrigger; - $ruleTrigger->rule()->associate($rule); - $ruleTrigger->order = $values['order']; - $ruleTrigger->active = $values['active']; - $ruleTrigger->stop_processing = $values['stop_processing']; - $ruleTrigger->trigger_type = $values['action']; - $ruleTrigger->trigger_value = $values['value'] ?? ''; - $ruleTrigger->save(); - - return $ruleTrigger; - } - - /** - * @param Rule $rule - * @param array $data - * - * @return Rule - */ - public function update(Rule $rule, array $data): Rule - { - // update rule: - $fields = [ - 'title', - 'description', - 'strict', - 'rule_group_id', - 'active', - 'stop_processing', - ]; - foreach ($fields as $field) { - if (array_key_exists($field, $data)) { - $rule->$field = $data[$field]; - } - } - $rule->save(); - $rule->refresh(); - $group = $rule->ruleGroup; - // update the order: - $this->resetRuleOrder($group); - if (array_key_exists('order', $data)) { - $this->moveRule($rule, $group, (int)$data['order']); - } - - - // update the triggers: - if (array_key_exists('trigger', $data) && 'update-journal' === $data['trigger']) { - $this->setRuleTrigger('update-journal', $rule); - } - if (array_key_exists('trigger', $data) && 'store-journal' === $data['trigger']) { - $this->setRuleTrigger('store-journal', $rule); - } - if (array_key_exists('triggers', $data)) { - // delete triggers: - $rule->ruleTriggers()->where('trigger_type', '!=', 'user_action')->delete(); - - // recreate triggers: - $this->storeTriggers($rule, $data); - } - - if (array_key_exists('actions', $data)) { - // delete triggers: - $rule->ruleActions()->delete(); - - // recreate actions: - $this->storeActions($rule, $data); - } - - return $rule; - } - /** * @param string $moment * @param Rule $rule @@ -525,6 +354,64 @@ class RuleRepository implements RuleRepositoryInterface $trigger->save(); } + /** + * @param RuleGroup $ruleGroup + * + * @return bool + */ + public function resetRuleOrder(RuleGroup $ruleGroup): bool + { + $groupRepository = app(RuleGroupRepositoryInterface::class); + $groupRepository->setUser($ruleGroup->user); + $groupRepository->resetRuleOrder($ruleGroup); + + return true; + } + + /** + * @inheritDoc + */ + public function setOrder(Rule $rule, int $newOrder): void + { + $oldOrder = (int) $rule->order; + $groupId = (int) $rule->rule_group_id; + $maxOrder = $this->maxOrder($rule->ruleGroup); + $newOrder = $newOrder > $maxOrder ? $maxOrder + 1 : $newOrder; + Log::debug(sprintf('New order will be %d', $newOrder)); + + if ($newOrder > $oldOrder) { + $this->user->rules() + ->where('rules.rule_group_id', $groupId) + ->where('rules.order', '<=', $newOrder) + ->where('rules.order', '>', $oldOrder) + ->where('rules.id', '!=', $rule->id) + ->decrement('rules.order'); + $rule->order = $newOrder; + Log::debug(sprintf('Order of rule #%d ("%s") is now %d', $rule->id, $rule->title, $newOrder)); + $rule->save(); + + return; + } + + $this->user->rules() + ->where('rules.rule_group_id', $groupId) + ->where('rules.order', '>=', $newOrder) + ->where('rules.order', '<', $oldOrder) + ->where('rules.id', '!=', $rule->id) + ->increment('rules.order'); + $rule->order = $newOrder; + Log::debug(sprintf('Order of rule #%d ("%s") is now %d', $rule->id, $rule->title, $newOrder)); + $rule->save(); + } + + /** + * @inheritDoc + */ + public function maxOrder(RuleGroup $ruleGroup): int + { + return (int) $ruleGroup->rules()->max('order'); + } + /** * @param Rule $rule * @param array $data @@ -553,6 +440,26 @@ class RuleRepository implements RuleRepositoryInterface return true; } + /** + * @param Rule $rule + * @param array $values + * + * @return RuleTrigger + */ + public function storeTrigger(Rule $rule, array $values): RuleTrigger + { + $ruleTrigger = new RuleTrigger; + $ruleTrigger->rule()->associate($rule); + $ruleTrigger->order = $values['order']; + $ruleTrigger->active = $values['active']; + $ruleTrigger->stop_processing = $values['stop_processing']; + $ruleTrigger->trigger_type = $values['action']; + $ruleTrigger->trigger_value = $values['value'] ?? ''; + $ruleTrigger->save(); + + return $ruleTrigger; + } + /** * @param Rule $rule * @param array $data @@ -579,4 +486,97 @@ class RuleRepository implements RuleRepositoryInterface return true; } + + /** + * @param Rule $rule + * @param array $values + * + * @return RuleAction + */ + public function storeAction(Rule $rule, array $values): RuleAction + { + $ruleAction = new RuleAction; + $ruleAction->rule()->associate($rule); + $ruleAction->order = $values['order']; + $ruleAction->active = $values['active']; + $ruleAction->stop_processing = $values['stop_processing']; + $ruleAction->action_type = $values['action']; + $ruleAction->action_value = $values['value'] ?? ''; + $ruleAction->save(); + + return $ruleAction; + } + + /** + * @param Rule $rule + * @param array $data + * + * @return Rule + */ + public function update(Rule $rule, array $data): Rule + { + // update rule: + $fields = [ + 'title', + 'description', + 'strict', + 'rule_group_id', + 'active', + 'stop_processing', + ]; + foreach ($fields as $field) { + if (array_key_exists($field, $data)) { + $rule->$field = $data[$field]; + } + } + $rule->save(); + $rule->refresh(); + $group = $rule->ruleGroup; + // update the order: + $this->resetRuleOrder($group); + if (array_key_exists('order', $data)) { + $this->moveRule($rule, $group, (int) $data['order']); + } + + + // update the triggers: + if (array_key_exists('trigger', $data) && 'update-journal' === $data['trigger']) { + $this->setRuleTrigger('update-journal', $rule); + } + if (array_key_exists('trigger', $data) && 'store-journal' === $data['trigger']) { + $this->setRuleTrigger('store-journal', $rule); + } + if (array_key_exists('triggers', $data)) { + // delete triggers: + $rule->ruleTriggers()->where('trigger_type', '!=', 'user_action')->delete(); + + // recreate triggers: + $this->storeTriggers($rule, $data); + } + + if (array_key_exists('actions', $data)) { + // delete triggers: + $rule->ruleActions()->delete(); + + // recreate actions: + $this->storeActions($rule, $data); + } + + return $rule; + } + + /** + * @inheritDoc + */ + public function moveRule(Rule $rule, RuleGroup $ruleGroup, int $order): Rule + { + if ($rule->rule_group_id !== $ruleGroup->id) { + $rule->rule_group_id = $ruleGroup->id; + } + $rule->save(); + $rule->refresh(); + $this->setOrder($rule, $order); + + return $rule; + } } diff --git a/app/Repositories/RuleGroup/RuleGroupRepository.php b/app/Repositories/RuleGroup/RuleGroupRepository.php index 9bdb1f4d33..2c0b109b13 100644 --- a/app/Repositories/RuleGroup/RuleGroupRepository.php +++ b/app/Repositories/RuleGroup/RuleGroupRepository.php @@ -99,6 +99,108 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface return true; } + /** + * @return bool + */ + public function resetOrder(): bool + { + $set = $this->user + ->ruleGroups() + ->whereNull('deleted_at') + ->orderBy('order', 'ASC') + ->orderBy('title', 'DESC') + ->get(); + $count = 1; + /** @var RuleGroup $entry */ + foreach ($set as $entry) { + if ($entry->order !== $count) { + $entry->order = $count; + $entry->save(); + } + + // also update rules in group. + $this->resetRuleOrder($entry); + + ++$count; + } + + return true; + } + + /** + * @param RuleGroup $ruleGroup + * + * @return bool + */ + public function resetRuleOrder(RuleGroup $ruleGroup): bool + { + $set = $ruleGroup->rules() + ->orderBy('order', 'ASC') + ->orderBy('title', 'DESC') + ->orderBy('updated_at', 'DESC') + ->get(['rules.*']); + $count = 1; + /** @var Rule $entry */ + foreach ($set as $entry) { + if ((int) $entry->order !== $count) { + Log::debug(sprintf('Rule #%d was on spot %d but must be on spot %d', $entry->id, $entry->order, $count)); + $entry->order = $count; + $entry->save(); + } + $this->resetRuleActionOrder($entry); + $this->resetRuleTriggerOrder($entry); + + ++$count; + } + + return true; + } + + /** + * @param Rule $rule + */ + private function resetRuleActionOrder(Rule $rule): void + { + $actions = $rule->ruleActions() + ->orderBy('order', 'ASC') + ->orderBy('active', 'DESC') + ->orderBy('action_type', 'ASC') + ->get(); + $index = 1; + /** @var RuleAction $action */ + foreach ($actions as $action) { + if ((int) $action->order !== $index) { + $action->order = $index; + $action->save(); + Log::debug(sprintf('Rule action #%d was on spot %d but must be on spot %d', $action->id, $action->order, $index)); + } + $index++; + } + } + + /** + * @param Rule $rule + */ + private function resetRuleTriggerOrder(Rule $rule): void + { + $triggers = $rule->ruleTriggers() + ->orderBy('order', 'ASC') + ->orderBy('active', 'DESC') + ->orderBy('trigger_type', 'ASC') + ->get(); + $index = 1; + /** @var RuleTrigger $trigger */ + foreach ($triggers as $trigger) { + $order = (int) $trigger->order; + if ($order !== $index) { + $trigger->order = $index; + $trigger->save(); + Log::debug(sprintf('Rule trigger #%d was on spot %d but must be on spot %d', $trigger->id, $order, $index)); + } + $index++; + } + } + /** * @inheritDoc */ @@ -112,6 +214,14 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } } + /** + * @return Collection + */ + public function get(): Collection + { + return $this->user->ruleGroups()->orderBy('order', 'ASC')->get(); + } + /** * @param int $ruleGroupId * @@ -132,14 +242,6 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface return $this->user->ruleGroups()->where('title', $title)->first(); } - /** - * @return Collection - */ - public function get(): Collection - { - return $this->user->ruleGroups()->orderBy('order', 'ASC')->get(); - } - /** * @return Collection */ @@ -249,7 +351,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface { $entry = $this->user->ruleGroups()->max('order'); - return (int)$entry; + return (int) $entry; } /** @@ -321,64 +423,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface */ public function maxOrder(): int { - return (int)$this->user->ruleGroups()->where('active', true)->max('order'); - } - - /** - * @return bool - */ - public function resetOrder(): bool - { - $set = $this->user - ->ruleGroups() - ->whereNull('deleted_at') - ->orderBy('order', 'ASC') - ->orderBy('title', 'DESC') - ->get(); - $count = 1; - /** @var RuleGroup $entry */ - foreach ($set as $entry) { - if ($entry->order !== $count) { - $entry->order = $count; - $entry->save(); - } - - // also update rules in group. - $this->resetRuleOrder($entry); - - ++$count; - } - - return true; - } - - /** - * @param RuleGroup $ruleGroup - * - * @return bool - */ - public function resetRuleOrder(RuleGroup $ruleGroup): bool - { - $set = $ruleGroup->rules() - ->orderBy('order', 'ASC') - ->orderBy('title', 'DESC') - ->orderBy('updated_at', 'DESC') - ->get(['rules.*']); - $count = 1; - /** @var Rule $entry */ - foreach ($set as $entry) { - if ((int)$entry->order !== $count) { - Log::debug(sprintf('Rule #%d was on spot %d but must be on spot %d', $entry->id, $entry->order, $count)); - $entry->order = $count; - $entry->save(); - } - $this->resetRuleActionOrder($entry); - $this->resetRuleTriggerOrder($entry); - - ++$count; - } - - return true; + return (int) $this->user->ruleGroups()->where('active', true)->max('order'); } /** @@ -396,32 +441,6 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface return $search->take($limit)->get(['id', 'title', 'description']); } - /** - * @inheritDoc - */ - public function setOrder(RuleGroup $ruleGroup, int $newOrder): void - { - $oldOrder = (int)$ruleGroup->order; - - if ($newOrder > $oldOrder) { - $this->user->ruleGroups()->where('rule_groups.order', '<=', $newOrder)->where('rule_groups.order', '>', $oldOrder) - ->where('rule_groups.id', '!=', $ruleGroup->id) - ->decrement('order'); - $ruleGroup->order = $newOrder; - Log::debug(sprintf('Order of group #%d ("%s") is now %d', $ruleGroup->id, $ruleGroup->title, $newOrder)); - $ruleGroup->save(); - - return; - } - - $this->user->ruleGroups()->where('rule_groups.order', '>=', $newOrder)->where('rule_groups.order', '<', $oldOrder) - ->where('rule_groups.id', '!=', $ruleGroup->id) - ->increment('order'); - $ruleGroup->order = $newOrder; - Log::debug(sprintf('Order of group #%d ("%s") is now %d', $ruleGroup->id, $ruleGroup->title, $newOrder)); - $ruleGroup->save(); - } - /** * @param User $user */ @@ -455,6 +474,32 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface return $newRuleGroup; } + /** + * @inheritDoc + */ + public function setOrder(RuleGroup $ruleGroup, int $newOrder): void + { + $oldOrder = (int) $ruleGroup->order; + + if ($newOrder > $oldOrder) { + $this->user->ruleGroups()->where('rule_groups.order', '<=', $newOrder)->where('rule_groups.order', '>', $oldOrder) + ->where('rule_groups.id', '!=', $ruleGroup->id) + ->decrement('order'); + $ruleGroup->order = $newOrder; + Log::debug(sprintf('Order of group #%d ("%s") is now %d', $ruleGroup->id, $ruleGroup->title, $newOrder)); + $ruleGroup->save(); + + return; + } + + $this->user->ruleGroups()->where('rule_groups.order', '>=', $newOrder)->where('rule_groups.order', '<', $oldOrder) + ->where('rule_groups.id', '!=', $ruleGroup->id) + ->increment('order'); + $ruleGroup->order = $newOrder; + Log::debug(sprintf('Order of group #%d ("%s") is now %d', $ruleGroup->id, $ruleGroup->title, $newOrder)); + $ruleGroup->save(); + } + /** * @param RuleGroup $ruleGroup * @param array $data @@ -476,56 +521,11 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface // order if (array_key_exists('order', $data) && $ruleGroup->order !== $data['order']) { $this->resetOrder(); - $this->setOrder($ruleGroup, (int)$data['order']); + $this->setOrder($ruleGroup, (int) $data['order']); } $ruleGroup->save(); return $ruleGroup; } - - /** - * @param Rule $rule - */ - private function resetRuleActionOrder(Rule $rule): void - { - $actions = $rule->ruleActions() - ->orderBy('order', 'ASC') - ->orderBy('active', 'DESC') - ->orderBy('action_type', 'ASC') - ->get(); - $index = 1; - /** @var RuleAction $action */ - foreach ($actions as $action) { - if ((int)$action->order !== $index) { - $action->order = $index; - $action->save(); - Log::debug(sprintf('Rule action #%d was on spot %d but must be on spot %d', $action->id, $action->order, $index)); - } - $index++; - } - } - - /** - * @param Rule $rule - */ - private function resetRuleTriggerOrder(Rule $rule): void - { - $triggers = $rule->ruleTriggers() - ->orderBy('order', 'ASC') - ->orderBy('active', 'DESC') - ->orderBy('trigger_type', 'ASC') - ->get(); - $index = 1; - /** @var RuleTrigger $trigger */ - foreach ($triggers as $trigger) { - $order = (int)$trigger->order; - if ($order !== $index) { - $trigger->order = $index; - $trigger->save(); - Log::debug(sprintf('Rule trigger #%d was on spot %d but must be on spot %d', $trigger->id, $order, $index)); - } - $index++; - } - } } diff --git a/app/Repositories/Tag/OperationsRepository.php b/app/Repositories/Tag/OperationsRepository.php index 10f15b7f7f..76ba6fff8d 100644 --- a/app/Repositories/Tag/OperationsRepository.php +++ b/app/Repositories/Tag/OperationsRepository.php @@ -70,7 +70,7 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; $listedJournals = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'tags' => [], 'currency_id' => $currencyId, @@ -82,9 +82,9 @@ class OperationsRepository implements OperationsRepositoryInterface // may have multiple tags: foreach ($journal['tags'] as $tag) { - $tagId = (int)$tag['id']; - $tagName = (string)$tag['name']; - $journalId = (int)$journal['transaction_journal_id']; + $tagId = (int) $tag['id']; + $tagName = (string) $tag['name']; + $journalId = (int) $journal['transaction_journal_id']; if (in_array($journalId, $listedJournals, true)) { continue; @@ -114,6 +114,16 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } + /** + * @return Collection + */ + private function getTags(): Collection + { + $repository = app(TagRepositoryInterface::class); + + return $repository->get(); + } + /** * This method returns a list of all the deposit transaction journals (as arrays) set in that period * which have the specified tag(s) set to them. It's grouped per currency, with as few details in the array @@ -146,7 +156,7 @@ class OperationsRepository implements OperationsRepositoryInterface $listedJournals = []; foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ 'tags' => [], 'currency_id' => $currencyId, @@ -158,9 +168,9 @@ class OperationsRepository implements OperationsRepositoryInterface // may have multiple tags: foreach ($journal['tags'] as $tag) { - $tagId = (int)$tag['id']; - $tagName = (string)$tag['name']; - $journalId = (int)$journal['transaction_journal_id']; + $tagId = (int) $tag['id']; + $tagName = (string) $tag['name']; + $journalId = (int) $journal['transaction_journal_id']; if (in_array($journalId, $listedJournals, true)) { continue; @@ -172,7 +182,7 @@ class OperationsRepository implements OperationsRepositoryInterface 'name' => $tagName, 'transaction_journals' => [], ]; - $journalId = (int)$journal['transaction_journal_id']; + $journalId = (int) $journal['transaction_journal_id']; $array[$currencyId]['tags'][$tagId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->positive($journal['amount']), 'date' => $journal['date'], @@ -229,14 +239,4 @@ class OperationsRepository implements OperationsRepositoryInterface { throw new FireflyException(sprintf('%s is not yet implemented.', __METHOD__)); } - - /** - * @return Collection - */ - private function getTags(): Collection - { - $repository = app(TagRepositoryInterface::class); - - return $repository->get(); - } } diff --git a/app/Repositories/Tag/TagRepository.php b/app/Repositories/Tag/TagRepository.php index 616932d492..aa65cb596e 100644 --- a/app/Repositories/Tag/TagRepository.php +++ b/app/Repositories/Tag/TagRepository.php @@ -81,6 +81,14 @@ class TagRepository implements TagRepositoryInterface } } + /** + * @return Collection + */ + public function get(): Collection + { + return $this->user->tags()->orderBy('tag', 'ASC')->get(); + } + /** * @param Tag $tag * @param Carbon $start @@ -134,14 +142,6 @@ class TagRepository implements TagRepositoryInterface return null; } - /** - * @return Collection - */ - public function get(): Collection - { - return $this->user->tags()->orderBy('tag', 'ASC')->get(); - } - /** * @inheritDoc */ @@ -162,14 +162,6 @@ class TagRepository implements TagRepositoryInterface ); } - /** - * @inheritDoc - */ - public function getLocation(Tag $tag): ?Location - { - return $tag->locations()->first(); - } - /** * @param int|null $year * @@ -338,7 +330,7 @@ class TagRepository implements TagRepositoryInterface /** @var array $journal */ foreach ($journals as $journal) { - $currencyId = (int)$journal['currency_id']; + $currencyId = (int) $journal['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ 'currency_id' => $currencyId, 'currency_name' => $journal['currency_name'], @@ -352,7 +344,7 @@ class TagRepository implements TagRepositoryInterface ]; // add amount to correct type: - $amount = app('steam')->positive((string)$journal['amount']); + $amount = app('steam')->positive((string) $journal['amount']); $type = $journal['transaction_type_type']; if (TransactionType::WITHDRAWAL === $type) { $amount = bcmul($amount, '-1'); @@ -373,7 +365,7 @@ class TagRepository implements TagRepositoryInterface TransactionType::OPENING_BALANCE => '0', ]; // add foreign amount to correct type: - $amount = app('steam')->positive((string)$journal['foreign_amount']); + $amount = app('steam')->positive((string) $journal['foreign_amount']); $type = $journal['transaction_type_type']; if (TransactionType::WITHDRAWAL === $type) { $amount = bcmul($amount, '-1'); @@ -458,4 +450,12 @@ class TagRepository implements TagRepositoryInterface return $tag; } + /** + * @inheritDoc + */ + public function getLocation(Tag $tag): ?Location + { + return $tag->locations()->first(); + } + } diff --git a/app/Repositories/TransactionGroup/TransactionGroupRepository.php b/app/Repositories/TransactionGroup/TransactionGroupRepository.php index f8a1985832..938d6c0b07 100644 --- a/app/Repositories/TransactionGroup/TransactionGroupRepository.php +++ b/app/Repositories/TransactionGroup/TransactionGroupRepository.php @@ -56,6 +56,18 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface { private User $user; + /** + * @inheritDoc + */ + public function countAttachments(int $journalId): int + { + /** @var TransactionJournal $journal */ + $journal = $this->user->transactionJournals()->find($journalId); + + return $journal->attachments()->count(); + + } + /** * @param TransactionGroup $group */ @@ -80,6 +92,56 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface return $result; } + /** + * @param TransactionJournal $journal + * + * @return array + */ + private function expandJournal(TransactionJournal $journal): array + { + $array = $journal->toArray(); + $array['transactions'] = []; + $array['meta'] = $journal->transactionJournalMeta->toArray(); + $array['tags'] = $journal->tags->toArray(); + $array['categories'] = $journal->categories->toArray(); + $array['budgets'] = $journal->budgets->toArray(); + $array['notes'] = $journal->notes->toArray(); + $array['locations'] = []; + $array['attachments'] = $journal->attachments->toArray(); + $array['links'] = []; + $array['piggy_bank_events'] = $journal->piggyBankEvents->toArray(); + + /** @var Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + $array['transactions'][] = $this->expandTransaction($transaction); + } + + return $array; + } + + /** + * @param Transaction $transaction + * + * @return array + */ + private function expandTransaction(Transaction $transaction): array + { + $array = $transaction->toArray(); + $array['account'] = $transaction->account->toArray(); + $array['budgets'] = []; + $array['categories'] = []; + + foreach ($transaction->categories as $category) { + $array['categories'][] = $category->toArray(); + } + + foreach ($transaction->budgets as $budget) { + $array['budgets'][] = $budget->toArray(); + } + + return $array; + } + /** * Find a transaction group by its ID. * @@ -112,11 +174,11 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface $result = []; /** @var Attachment $attachment */ foreach ($set as $attachment) { - $journalId = (int)$attachment->attachable_id; + $journalId = (int) $attachment->attachable_id; $result[$journalId] = $result[$journalId] ?? []; $current = $attachment->toArray(); $current['file_exists'] = true; - $current['notes'] = $repository->getNoteText($attachment); + $current['notes'] = $repository->getNoteText($attachment); $current['journal_title'] = $attachment->attachable->description; // @phpstan-ignore-line $result[$journalId][] = $current; @@ -159,7 +221,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface 'link' => $entry->outward, 'group' => $entry->destination->transaction_group_id, 'description' => $entry->destination->description, - 'editable' => 1===$entry->editable, + 'editable' => 1 === $entry->editable, 'amount' => $amount, 'foreign_amount' => $foreignAmount, ]; @@ -172,7 +234,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface 'link' => $entry->inward, 'group' => $entry->source->transaction_group_id, 'description' => $entry->source->description, - 'editable' => 1===$entry->editable, + 'editable' => 1 === $entry->editable, 'amount' => $amount, 'foreign_amount' => $foreignAmount, ]; @@ -182,6 +244,56 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface return $return; } + /** + * @param TransactionJournal $journal + * + * @return string + */ + private function getFormattedAmount(TransactionJournal $journal): string + { + /** @var Transaction $transaction */ + $transaction = $journal->transactions->first(); + $currency = $transaction->transactionCurrency; + $type = $journal->transactionType->type; + $amount = app('steam')->positive($transaction->amount); + $return = ''; + if (TransactionType::WITHDRAWAL === $type) { + $return = app('amount')->formatAnything($currency, app('steam')->negative($amount)); + } + if (TransactionType::WITHDRAWAL !== $type) { + $return = app('amount')->formatAnything($currency, $amount); + + } + + return $return; + } + + /** + * @param TransactionJournal $journal + * + * @return string + */ + private function getFormattedForeignAmount(TransactionJournal $journal): string + { + /** @var Transaction $transaction */ + $transaction = $journal->transactions->first(); + if (null === $transaction->foreign_amount) { + return ''; + } + $currency = $transaction->foreignCurrency; + $type = $journal->transactionType->type; + $amount = app('steam')->positive($transaction->foreign_amount); + $return = ''; + if (TransactionType::WITHDRAWAL === $type) { + $return = app('amount')->formatAnything($currency, app('steam')->negative($amount)); + } + if (TransactionType::WITHDRAWAL !== $type) { + $return = app('amount')->formatAnything($currency, $amount); + } + + return $return; + } + /** * @inheritDoc */ @@ -299,7 +411,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface $currencyCode = app('preferences')->getForUser($this->user, 'currencyPreference', 'EUR')->data; $currency = TransactionCurrency::where('code', $currencyCode)->first(); } - $journalId = (int)$row->transaction_journal_id; + $journalId = (int) $row->transaction_journal_id; $return[$journalId] = $return[$journalId] ?? []; $return[$journalId][] = [ @@ -390,116 +502,4 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface return $service->update($transactionGroup, $data); } - - /** - * @param TransactionJournal $journal - * - * @return array - */ - private function expandJournal(TransactionJournal $journal): array - { - $array = $journal->toArray(); - $array['transactions'] = []; - $array['meta'] = $journal->transactionJournalMeta->toArray(); - $array['tags'] = $journal->tags->toArray(); - $array['categories'] = $journal->categories->toArray(); - $array['budgets'] = $journal->budgets->toArray(); - $array['notes'] = $journal->notes->toArray(); - $array['locations'] = []; - $array['attachments'] = $journal->attachments->toArray(); - $array['links'] = []; - $array['piggy_bank_events'] = $journal->piggyBankEvents->toArray(); - - /** @var Transaction $transaction */ - foreach ($journal->transactions as $transaction) { - $array['transactions'][] = $this->expandTransaction($transaction); - } - - return $array; - } - - /** - * @param Transaction $transaction - * - * @return array - */ - private function expandTransaction(Transaction $transaction): array - { - $array = $transaction->toArray(); - $array['account'] = $transaction->account->toArray(); - $array['budgets'] = []; - $array['categories'] = []; - - foreach ($transaction->categories as $category) { - $array['categories'][] = $category->toArray(); - } - - foreach ($transaction->budgets as $budget) { - $array['budgets'][] = $budget->toArray(); - } - - return $array; - } - - /** - * @param TransactionJournal $journal - * - * @return string - */ - private function getFormattedAmount(TransactionJournal $journal): string - { - /** @var Transaction $transaction */ - $transaction = $journal->transactions->first(); - $currency = $transaction->transactionCurrency; - $type = $journal->transactionType->type; - $amount = app('steam')->positive($transaction->amount); - $return = ''; - if (TransactionType::WITHDRAWAL === $type) { - $return = app('amount')->formatAnything($currency, app('steam')->negative($amount)); - } - if (TransactionType::WITHDRAWAL !== $type) { - $return = app('amount')->formatAnything($currency, $amount); - - } - - return $return; - } - - /** - * @param TransactionJournal $journal - * - * @return string - */ - private function getFormattedForeignAmount(TransactionJournal $journal): string - { - /** @var Transaction $transaction */ - $transaction = $journal->transactions->first(); - if (null === $transaction->foreign_amount) { - return ''; - } - $currency = $transaction->foreignCurrency; - $type = $journal->transactionType->type; - $amount = app('steam')->positive($transaction->foreign_amount); - $return = ''; - if (TransactionType::WITHDRAWAL === $type) { - $return = app('amount')->formatAnything($currency, app('steam')->negative($amount)); - } - if (TransactionType::WITHDRAWAL !== $type) { - $return = app('amount')->formatAnything($currency, $amount); - } - - return $return; - } - - /** - * @inheritDoc - */ - public function countAttachments(int $journalId): int - { - /** @var TransactionJournal $journal */ - $journal = $this->user->transactionJournals()->find($journalId); - - return $journal->attachments()->count(); - - } } diff --git a/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php b/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php index fc01fc13d6..fed0bca69c 100644 --- a/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php +++ b/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php @@ -36,6 +36,13 @@ use Illuminate\Support\Collection; */ interface TransactionGroupRepositoryInterface { + /** + * @param int $journalId + * + * @return int + */ + public function countAttachments(int $journalId): int; + /** * @param TransactionGroup $group */ @@ -86,13 +93,6 @@ interface TransactionGroupRepositoryInterface */ public function getLocation(int $journalId): ?Location; - /** - * @param int $journalId - * - * @return int - */ - public function countAttachments(int $journalId): int; - /** * Return object with all found meta field things as Carbon objects. * diff --git a/app/Repositories/TransactionType/TransactionTypeRepository.php b/app/Repositories/TransactionType/TransactionTypeRepository.php index d5aa7c9dc0..68db902f6f 100644 --- a/app/Repositories/TransactionType/TransactionTypeRepository.php +++ b/app/Repositories/TransactionType/TransactionTypeRepository.php @@ -33,18 +33,6 @@ use Log; class TransactionTypeRepository implements TransactionTypeRepositoryInterface { - /** - * @param string $type - * - * @return TransactionType|null - */ - public function findByType(string $type): ?TransactionType - { - $search = ucfirst($type); - - return TransactionType::whereType($search)->first(); - } - /** * @param TransactionType|null $type * @param string|null $typeString @@ -69,6 +57,18 @@ class TransactionTypeRepository implements TransactionTypeRepositoryInterface return $search; } + /** + * @param string $type + * + * @return TransactionType|null + */ + public function findByType(string $type): ?TransactionType + { + $search = ucfirst($type); + + return TransactionType::whereType($search)->first(); + } + /** * @param string $query * @param int $limit diff --git a/app/Repositories/User/UserRepository.php b/app/Repositories/User/UserRepository.php index c5daeccac5..d841a6bc46 100644 --- a/app/Repositories/User/UserRepository.php +++ b/app/Repositories/User/UserRepository.php @@ -39,39 +39,6 @@ use Str; */ class UserRepository implements UserRepositoryInterface { - /** - * @return Collection - */ - public function all(): Collection - { - return User::orderBy('id', 'DESC')->get(['users.*']); - } - - /** - * @param User $user - * @param string $role - * - * @return bool - */ - public function attachRole(User $user, string $role): bool - { - $roleObject = Role::where('name', $role)->first(); - if (null === $roleObject) { - Log::error(sprintf('Could not find role "%s" in attachRole()', $role)); - - return false; - } - - try { - $user->roles()->attach($roleObject); - } catch (QueryException $e) { - // don't care - Log::error(sprintf('Query exception when giving user a role: %s', $e->getMessage())); - } - - return true; - } - /** * This updates the users email address and records some things so it can be confirmed or undone later. * The user is blocked until the change is confirmed. @@ -144,6 +111,14 @@ class UserRepository implements UserRepositoryInterface return $this->all()->count(); } + /** + * @return Collection + */ + public function all(): Collection + { + return User::orderBy('id', 'DESC')->get(['users.*']); + } + /** * @param string $name * @param string $displayName @@ -173,6 +148,22 @@ class UserRepository implements UserRepositoryInterface return true; } + /** + * @inheritDoc + */ + public function deleteEmptyGroups(): void + { + $groups = UserGroup::get(); + /** @var UserGroup $group */ + foreach ($groups as $group) { + $count = $group->groupMemberships()->count(); + if (0 === $count) { + Log::info(sprintf('Deleted empty group #%d ("%s")', $group->id, $group->title)); + $group->delete(); + } + } + } + /** * @param int $userId * @@ -203,16 +194,6 @@ class UserRepository implements UserRepositoryInterface return User::orderBy('id', 'ASC')->first(); } - /** - * @param string $role - * - * @return Role|null - */ - public function getRole(string $role): ?Role - { - return Role::where('name', $role)->first(); - } - /** * @param User $user * @@ -243,7 +224,7 @@ class UserRepository implements UserRepositoryInterface // two factor: $return['has_2fa'] = $user->mfa_secret !== null; $return['is_admin'] = $this->hasRole($user, 'owner'); - $return['blocked'] = 1 === (int)$user->blocked; + $return['blocked'] = 1 === (int) $user->blocked; $return['blocked_code'] = $user->blocked_code; $return['accounts'] = $user->accounts()->count(); $return['journals'] = $user->transactionJournals()->count(); @@ -284,21 +265,6 @@ class UserRepository implements UserRepositoryInterface return false; } - /** - * Remove any role the user has. - * - * @param User $user - * @param string $role - */ - public function removeRole(User $user, string $role): void - { - $roleObj = $this->getRole($role); - if (null === $roleObj) { - return; - } - $user->roles()->detach($roleObj->id); - } - /** * Set MFA code. * @@ -334,6 +300,31 @@ class UserRepository implements UserRepositoryInterface return $user; } + /** + * @param User $user + * @param string $role + * + * @return bool + */ + public function attachRole(User $user, string $role): bool + { + $roleObject = Role::where('name', $role)->first(); + if (null === $roleObject) { + Log::error(sprintf('Could not find role "%s" in attachRole()', $role)); + + return false; + } + + try { + $user->roles()->attach($roleObject); + } catch (QueryException $e) { + // don't care + Log::error(sprintf('Query exception when giving user a role: %s', $e->getMessage())); + } + + return true; + } + /** * @param User $user */ @@ -402,18 +393,27 @@ class UserRepository implements UserRepositoryInterface } /** - * @inheritDoc + * Remove any role the user has. + * + * @param User $user + * @param string $role */ - public function deleteEmptyGroups(): void + public function removeRole(User $user, string $role): void { - $groups = UserGroup::get(); - /** @var UserGroup $group */ - foreach ($groups as $group) { - $count = $group->groupMemberships()->count(); - if (0 === $count) { - Log::info(sprintf('Deleted empty group #%d ("%s")', $group->id, $group->title)); - $group->delete(); - } + $roleObj = $this->getRole($role); + if (null === $roleObj) { + return; } + $user->roles()->detach($roleObj->id); + } + + /** + * @param string $role + * + * @return Role|null + */ + public function getRole(string $role): ?Role + { + return Role::where('name', $role)->first(); } } diff --git a/app/Repositories/User/UserRepositoryInterface.php b/app/Repositories/User/UserRepositoryInterface.php index 6d087cfa43..410162b2e4 100644 --- a/app/Repositories/User/UserRepositoryInterface.php +++ b/app/Repositories/User/UserRepositoryInterface.php @@ -39,11 +39,6 @@ interface UserRepositoryInterface */ public function all(): Collection; - /** - * - */ - public function deleteEmptyGroups(): void; - /** * Gives a user a role. * @@ -100,6 +95,11 @@ interface UserRepositoryInterface */ public function createRole(string $name, string $displayName, string $description): Role; + /** + * + */ + public function deleteEmptyGroups(): void; + /** * @param User $user * diff --git a/app/Rules/BelongsUser.php b/app/Rules/BelongsUser.php index 027b6b8dbe..e8050c4d27 100644 --- a/app/Rules/BelongsUser.php +++ b/app/Rules/BelongsUser.php @@ -58,7 +58,7 @@ class BelongsUser implements Rule */ public function message(): string { - return (string)trans('validation.belongs_user'); + return (string) trans('validation.belongs_user'); } /** @@ -77,19 +77,19 @@ class BelongsUser implements Rule if (!auth()->check()) { return true; } - $attribute = (string)$attribute; + $attribute = (string) $attribute; Log::debug(sprintf('Going to validate %s', $attribute)); return match ($attribute) { - 'piggy_bank_id' => $this->validatePiggyBankId((int)$value), + 'piggy_bank_id' => $this->validatePiggyBankId((int) $value), 'piggy_bank_name' => $this->validatePiggyBankName($value), - 'bill_id' => $this->validateBillId((int)$value), - 'transaction_journal_id' => $this->validateJournalId((int)$value), + 'bill_id' => $this->validateBillId((int) $value), + 'transaction_journal_id' => $this->validateJournalId((int) $value), 'bill_name' => $this->validateBillName($value), - 'budget_id' => $this->validateBudgetId((int)$value), - 'category_id' => $this->validateCategoryId((int)$value), + 'budget_id' => $this->validateBudgetId((int) $value), + 'category_id' => $this->validateCategoryId((int) $value), 'budget_name' => $this->validateBudgetName($value), - 'source_id', 'destination_id' => $this->validateAccountId((int)$value), + 'source_id', 'destination_id' => $this->validateAccountId((int) $value), default => throw new FireflyException(sprintf('Rule BelongUser cannot handle "%s"', $attribute)), }; } @@ -161,7 +161,7 @@ class BelongsUser implements Rule } $count = 0; foreach ($objects as $object) { - $objectValue = trim((string)$object->$field); + $objectValue = trim((string) $object->$field); Log::debug(sprintf('Comparing object "%s" with value "%s"', $objectValue, $value)); if ($objectValue === $value) { $count++; diff --git a/app/Rules/IsAssetAccountId.php b/app/Rules/IsAssetAccountId.php index ebf1659cd3..f30a327b58 100644 --- a/app/Rules/IsAssetAccountId.php +++ b/app/Rules/IsAssetAccountId.php @@ -53,7 +53,7 @@ class IsAssetAccountId implements Rule */ public function passes($attribute, $value): bool { - $accountId = (int)$value; + $accountId = (int) $value; $account = Account::with('accountType')->find($accountId); if (null === $account) { return false; diff --git a/app/Rules/IsBoolean.php b/app/Rules/IsBoolean.php index f2157f1abd..cf8331948f 100644 --- a/app/Rules/IsBoolean.php +++ b/app/Rules/IsBoolean.php @@ -39,7 +39,7 @@ class IsBoolean implements Rule */ public function message(): string { - return (string)trans('validation.boolean'); + return (string) trans('validation.boolean'); } /** diff --git a/app/Rules/IsDateOrTime.php b/app/Rules/IsDateOrTime.php index 6eee28a3c7..cd888864b5 100644 --- a/app/Rules/IsDateOrTime.php +++ b/app/Rules/IsDateOrTime.php @@ -44,7 +44,7 @@ class IsDateOrTime implements Rule */ public function message() { - return (string)trans('validation.date_or_time'); + return (string) trans('validation.date_or_time'); } /** @@ -57,7 +57,7 @@ class IsDateOrTime implements Rule */ public function passes($attribute, $value): bool { - $value = (string)$value; + $value = (string) $value; if ('' === $value) { return false; } diff --git a/app/Rules/IsTransferAccount.php b/app/Rules/IsTransferAccount.php index 16897ed59a..27103b1c8d 100644 --- a/app/Rules/IsTransferAccount.php +++ b/app/Rules/IsTransferAccount.php @@ -41,7 +41,7 @@ class IsTransferAccount implements Rule */ public function message(): string { - return (string)trans('validation.not_transfer_account'); + return (string) trans('validation.not_transfer_account'); } /** @@ -60,15 +60,15 @@ class IsTransferAccount implements Rule $validator->setTransactionType(TransactionType::TRANSFER); $validator->setUser(auth()->user()); - $validAccount = $validator->validateSource(['name' => (string)$value,]); + $validAccount = $validator->validateSource(['name' => (string) $value,]); if (true === $validAccount) { Log::debug('Found account based on name. Return true.'); // found by name, use repos to return. return true; } - $validAccount = $validator->validateSource(['id' => (int)$value,]); - Log::debug(sprintf('Search by id (%d), result is %s.', (int)$value, var_export($validAccount, true))); + $validAccount = $validator->validateSource(['id' => (int) $value,]); + Log::debug(sprintf('Search by id (%d), result is %s.', (int) $value, var_export($validAccount, true))); return false !== $validAccount; } diff --git a/app/Rules/IsValidAttachmentModel.php b/app/Rules/IsValidAttachmentModel.php index d2e0349693..1b6ec0dd56 100644 --- a/app/Rules/IsValidAttachmentModel.php +++ b/app/Rules/IsValidAttachmentModel.php @@ -85,7 +85,7 @@ class IsValidAttachmentModel implements Rule */ public function message(): string { - return (string)trans('validation.model_id_invalid'); + return (string) trans('validation.model_id_invalid'); } /** @@ -118,7 +118,7 @@ class IsValidAttachmentModel implements Rule } $method = $methods[$this->model]; - return $this->$method((int)$value); + return $this->$method((int) $value); } /** @@ -229,6 +229,6 @@ class IsValidAttachmentModel implements Rule $repository = app(JournalAPIRepositoryInterface::class); $repository->setUser(auth()->user()); - return null !== $repository->findTransaction((int)$value); + return null !== $repository->findTransaction((int) $value); } } diff --git a/app/Rules/IsValidBulkClause.php b/app/Rules/IsValidBulkClause.php index 7a8bda7692..9b35893fb8 100644 --- a/app/Rules/IsValidBulkClause.php +++ b/app/Rules/IsValidBulkClause.php @@ -42,7 +42,7 @@ class IsValidBulkClause implements Rule public function __construct(string $type) { $this->rules = config(sprintf('bulk.%s', $type)); - $this->error = (string)trans('firefly.belongs_user'); + $this->error = (string) trans('firefly.belongs_user'); } /** @@ -61,7 +61,7 @@ class IsValidBulkClause implements Rule */ public function passes($attribute, $value): bool { - $result = $this->basicValidation((string)$value); + $result = $this->basicValidation((string) $value); if (false === $result) { return false; } @@ -81,14 +81,14 @@ class IsValidBulkClause implements Rule try { $array = json_decode($value, true, 8, JSON_THROW_ON_ERROR); } catch (JsonException $e) { - $this->error = (string)trans('validation.json'); + $this->error = (string) trans('validation.json'); return false; } $clauses = ['where', 'update']; foreach ($clauses as $clause) { if (!array_key_exists($clause, $array)) { - $this->error = (string)trans(sprintf('validation.missing_%s', $clause)); + $this->error = (string) trans(sprintf('validation.missing_%s', $clause)); return false; } @@ -98,7 +98,7 @@ class IsValidBulkClause implements Rule */ foreach ($array[$clause] as $arrayKey => $arrayValue) { if (!array_key_exists($arrayKey, $this->rules[$clause])) { - $this->error = (string)trans(sprintf('validation.invalid_%s_key', $clause)); + $this->error = (string) trans(sprintf('validation.invalid_%s_key', $clause)); return false; } diff --git a/app/Rules/LessThanPiggyTarget.php b/app/Rules/LessThanPiggyTarget.php index e19589ea74..9e4567ec55 100644 --- a/app/Rules/LessThanPiggyTarget.php +++ b/app/Rules/LessThanPiggyTarget.php @@ -38,7 +38,7 @@ class LessThanPiggyTarget implements Rule */ public function message(): string { - return (string)trans('validation.current_target_amount'); + return (string) trans('validation.current_target_amount'); } /** diff --git a/app/Rules/UniqueAccountNumber.php b/app/Rules/UniqueAccountNumber.php index f8b4102c6b..94a2354a43 100644 --- a/app/Rules/UniqueAccountNumber.php +++ b/app/Rules/UniqueAccountNumber.php @@ -72,7 +72,7 @@ class UniqueAccountNumber implements Rule */ public function message(): string { - return (string)trans('validation.unique_account_number_for_user'); + return (string) trans('validation.unique_account_number_for_user'); } /** diff --git a/app/Rules/UniqueIban.php b/app/Rules/UniqueIban.php index e6e37f98de..ae94b4f528 100644 --- a/app/Rules/UniqueIban.php +++ b/app/Rules/UniqueIban.php @@ -69,7 +69,7 @@ class UniqueIban implements Rule */ public function message(): string { - return (string)trans('validation.unique_iban_for_user'); + return (string) trans('validation.unique_iban_for_user'); } /** diff --git a/app/Rules/ValidJournals.php b/app/Rules/ValidJournals.php index 888e5697c7..e9575a4bc8 100644 --- a/app/Rules/ValidJournals.php +++ b/app/Rules/ValidJournals.php @@ -42,7 +42,7 @@ class ValidJournals implements Rule */ public function message(): string { - return (string)trans('validation.invalid_selection'); + return (string) trans('validation.invalid_selection'); } /** diff --git a/app/Rules/ValidRecurrenceRepetitionType.php b/app/Rules/ValidRecurrenceRepetitionType.php index 6f1655f8e5..bbe95af3b2 100644 --- a/app/Rules/ValidRecurrenceRepetitionType.php +++ b/app/Rules/ValidRecurrenceRepetitionType.php @@ -40,7 +40,7 @@ class ValidRecurrenceRepetitionType implements Rule */ public function message(): string { - return (string)trans('validation.valid_recurrence_rep_type'); + return (string) trans('validation.valid_recurrence_rep_type'); } /** @@ -54,7 +54,7 @@ class ValidRecurrenceRepetitionType implements Rule */ public function passes($attribute, $value): bool { - $value = (string)$value; + $value = (string) $value; if ('daily' === $value) { return true; } diff --git a/app/Rules/ValidRecurrenceRepetitionValue.php b/app/Rules/ValidRecurrenceRepetitionValue.php index 14ba5cca50..f9a4f8b50f 100644 --- a/app/Rules/ValidRecurrenceRepetitionValue.php +++ b/app/Rules/ValidRecurrenceRepetitionValue.php @@ -43,7 +43,7 @@ class ValidRecurrenceRepetitionValue implements Rule */ public function message(): string { - return (string)trans('validation.valid_recurrence_rep_type'); + return (string) trans('validation.valid_recurrence_rep_type'); } /** @@ -57,7 +57,7 @@ class ValidRecurrenceRepetitionValue implements Rule */ public function passes($attribute, $value): bool { - $value = (string)$value; + $value = (string) $value; if ('daily' === $value) { return true; @@ -93,7 +93,7 @@ class ValidRecurrenceRepetitionValue implements Rule */ private function validateMonthly(string $value): bool { - $dayOfMonth = (int)substr($value, 8); + $dayOfMonth = (int) substr($value, 8); return $dayOfMonth > 0 && $dayOfMonth < 32; } @@ -110,8 +110,8 @@ class ValidRecurrenceRepetitionValue implements Rule if (2 !== count($parameters)) { return false; } - $nthDay = (int)($parameters[0] ?? 0.0); - $dayOfWeek = (int)($parameters[1] ?? 0.0); + $nthDay = (int) ($parameters[0] ?? 0.0); + $dayOfWeek = (int) ($parameters[1] ?? 0.0); if ($nthDay < 1 || $nthDay > 5) { return false; } @@ -126,7 +126,7 @@ class ValidRecurrenceRepetitionValue implements Rule */ private function validateWeekly(string $value): bool { - $dayOfWeek = (int)substr($value, 7); + $dayOfWeek = (int) substr($value, 7); return $dayOfWeek > 0 && $dayOfWeek < 8; } diff --git a/app/Services/FireflyIIIOrg/Update/UpdateRequest.php b/app/Services/FireflyIIIOrg/Update/UpdateRequest.php index 9d5deae09b..a569d497cc 100644 --- a/app/Services/FireflyIIIOrg/Update/UpdateRequest.php +++ b/app/Services/FireflyIIIOrg/Update/UpdateRequest.php @@ -46,7 +46,7 @@ class UpdateRequest implements UpdateRequestInterface Log::debug(sprintf('Now in getUpdateInformation(%s)', $channel)); $information = [ 'level' => 'error', - 'message' => (string)trans('firefly.unknown_error'), + 'message' => (string) trans('firefly.unknown_error'), ]; // try get array from update server: @@ -76,7 +76,7 @@ class UpdateRequest implements UpdateRequestInterface 'version' => config('firefly.version'), 'date' => Carbon::today()->startOfDay(), 'level' => 'error', - 'message' => (string)trans('firefly.unknown_error'), + 'message' => (string) trans('firefly.unknown_error'), ]; $uri = config('firefly.update_endpoint'); @@ -101,12 +101,12 @@ class UpdateRequest implements UpdateRequestInterface if (200 !== $res->getStatusCode()) { Log::error(sprintf('Response status from server is %d.', $res->getStatusCode())); - Log::error((string)$res->getBody()); + Log::error((string) $res->getBody()); $return['message'] = sprintf('Error: %d', $res->getStatusCode()); return $return; } - $body = (string)$res->getBody(); + $body = (string) $res->getBody(); try { $json = json_decode($body, true, 512, JSON_THROW_ON_ERROR); @@ -144,7 +144,7 @@ class UpdateRequest implements UpdateRequestInterface Log::debug('Now in parseResult()', $information); $return = [ 'level' => 'error', - 'message' => (string)trans('firefly.unknown_error'), + 'message' => (string) trans('firefly.unknown_error'), ]; $current = config('firefly.version'); $latest = $information['version']; @@ -155,7 +155,7 @@ class UpdateRequest implements UpdateRequestInterface // -1: you're running a newer version: if (-1 === $compare) { $return['level'] = 'info'; - $return['message'] = (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]); + $return['message'] = (string) trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]); Log::debug('User is running a newer version', $return); return $return; @@ -163,7 +163,7 @@ class UpdateRequest implements UpdateRequestInterface // running the current version: if (0 === $compare) { $return['level'] = 'info'; - $return['message'] = (string)trans('firefly.update_current_version_alert', ['version' => $current]); + $return['message'] = (string) trans('firefly.update_current_version_alert', ['version' => $current]); Log::debug('User is the current version.', $return); return $return; @@ -177,10 +177,10 @@ class UpdateRequest implements UpdateRequestInterface // it's still very fresh, and user wants a stable release: if ($diff <= $expectedDiff) { $return['level'] = 'info'; - $return['message'] = (string)trans( + $return['message'] = (string) trans( 'firefly.just_new_release', ['version' => $latest, - 'date' => $released->isoFormat((string)trans('config.month_and_day_js')), + 'date' => $released->isoFormat((string) trans('config.month_and_day_js')), 'days' => $expectedDiff, ] ); @@ -191,12 +191,12 @@ class UpdateRequest implements UpdateRequestInterface // its been around for a while: $return['level'] = 'success'; - $return['message'] = (string)trans( + $return['message'] = (string) trans( 'firefly.update_new_version_alert', [ 'your_version' => $current, 'new_version' => $latest, - 'date' => $released->isoFormat((string)trans('config.month_and_day_js'))] + 'date' => $released->isoFormat((string) trans('config.month_and_day_js'))] ); Log::debug('New release is old enough.'); diff --git a/app/Services/Internal/Destroy/AccountDestroyService.php b/app/Services/Internal/Destroy/AccountDestroyService.php index aed55bb705..ee5aafe5b0 100644 --- a/app/Services/Internal/Destroy/AccountDestroyService.php +++ b/app/Services/Internal/Destroy/AccountDestroyService.php @@ -41,7 +41,7 @@ use stdClass; class AccountDestroyService { /** - * @param Account $account + * @param Account $account * @param Account|null $moveTo * * @return void @@ -87,7 +87,7 @@ class AccountDestroyService ->where('transaction_types.type', TransactionType::OPENING_BALANCE) ->get(['transactions.transaction_journal_id']); if ($set->count() > 0) { - $journalId = (int)$set->first()->transaction_journal_id; + $journalId = (int) $set->first()->transaction_journal_id; Log::debug(sprintf('Found opening balance journal with ID #%d', $journalId)); // get transactions with this journal (should be just one): @@ -133,8 +133,8 @@ class AccountDestroyService $user = $account->user; /** @var stdClass $row */ foreach ($collection as $row) { - if ((int)$row->the_count > 1) { - $journalId = (int)$row->transaction_journal_id; + if ((int) $row->the_count > 1) { + $journalId = (int) $row->transaction_journal_id; $journal = $user->transactionJournals()->find($journalId); if (null !== $journal) { Log::debug(sprintf('Deleted journal #%d because it has the same source as destination.', $journal->id)); @@ -192,7 +192,7 @@ class AccountDestroyService /** @var RecurrenceDestroyService $destroyService */ $destroyService = app(RecurrenceDestroyService::class); foreach ($recurrences as $recurrenceId) { - $destroyService->destroyById((int)$recurrenceId); + $destroyService->destroyById((int) $recurrenceId); } } diff --git a/app/Services/Internal/Destroy/BudgetDestroyService.php b/app/Services/Internal/Destroy/BudgetDestroyService.php index f1335cd7c1..e7b1deb515 100644 --- a/app/Services/Internal/Destroy/BudgetDestroyService.php +++ b/app/Services/Internal/Destroy/BudgetDestroyService.php @@ -52,10 +52,10 @@ class BudgetDestroyService } // also delete all relations between categories and transaction journals: - DB::table('budget_transaction_journal')->where('budget_id', (int)$budget->id)->delete(); + DB::table('budget_transaction_journal')->where('budget_id', (int) $budget->id)->delete(); // also delete all relations between categories and transactions: - DB::table('budget_transaction')->where('budget_id', (int)$budget->id)->delete(); + DB::table('budget_transaction')->where('budget_id', (int) $budget->id)->delete(); // also delete all budget limits $budget->budgetlimits()->delete(); diff --git a/app/Services/Internal/Destroy/CategoryDestroyService.php b/app/Services/Internal/Destroy/CategoryDestroyService.php index adb3f92f2c..63c97ec7a2 100644 --- a/app/Services/Internal/Destroy/CategoryDestroyService.php +++ b/app/Services/Internal/Destroy/CategoryDestroyService.php @@ -46,9 +46,9 @@ class CategoryDestroyService } // also delete all relations between categories and transaction journals: - DB::table('category_transaction_journal')->where('category_id', (int)$category->id)->delete(); + DB::table('category_transaction_journal')->where('category_id', (int) $category->id)->delete(); // also delete all relations between categories and transactions: - DB::table('category_transaction')->where('category_id', (int)$category->id)->delete(); + DB::table('category_transaction')->where('category_id', (int) $category->id)->delete(); } } diff --git a/app/Services/Internal/Support/AccountServiceTrait.php b/app/Services/Internal/Support/AccountServiceTrait.php index e760f29d5e..1f19611704 100644 --- a/app/Services/Internal/Support/AccountServiceTrait.php +++ b/app/Services/Internal/Support/AccountServiceTrait.php @@ -146,7 +146,7 @@ trait AccountServiceTrait $data[$field] = 1; } - $factory->crud($account, $field, (string)$data[$field]); + $factory->crud($account, $field, (string) $data[$field]); } } } @@ -192,7 +192,7 @@ trait AccountServiceTrait */ public function validOBData(array $data): bool { - $data['opening_balance'] = (string)($data['opening_balance'] ?? ''); + $data['opening_balance'] = (string) ($data['opening_balance'] ?? ''); if ('' !== $data['opening_balance'] && 0 === bccomp($data['opening_balance'], '0')) { $data['opening_balance'] = ''; } @@ -512,6 +512,63 @@ trait AccountServiceTrait return $group; } + /** + * See reference nr. 99 + * + * @param TransactionGroup $group + * + * @return TransactionJournal + * @throws FireflyException + */ + private function getObJournal(TransactionGroup $group): TransactionJournal + { + /** @var TransactionJournal $journal */ + $journal = $group->transactionJournals()->first(); + if (null === $journal) { + throw new FireflyException(sprintf('Group #%d has no OB journal', $group->id)); + } + + return $journal; + } + + /** + * See reference nr. 98 + * + * @param TransactionJournal $journal + * @param Account $account + * + * @return Transaction + * @throws FireflyException + */ + private function getOBTransaction(TransactionJournal $journal, Account $account): Transaction + { + /** @var Transaction $transaction */ + $transaction = $journal->transactions()->where('account_id', '!=', $account->id)->first(); + if (null === $transaction) { + throw new FireflyException(sprintf('Could not get OB transaction for journal #%d', $journal->id)); + } + + return $transaction; + } + + /** + * @param TransactionJournal $journal + * @param Account $account + * + * @return Transaction + * @throws FireflyException + */ + private function getNotOBTransaction(TransactionJournal $journal, Account $account): Transaction + { + /** @var Transaction $transaction */ + $transaction = $journal->transactions()->where('account_id', $account->id)->first(); + if (null === $transaction) { + throw new FireflyException(sprintf('Could not get non-OB transaction for journal #%d', $journal->id)); + } + + return $transaction; + } + /** * Update or create the opening balance group. * Since opening balance and date can still be empty strings, it may fail. @@ -667,61 +724,4 @@ trait AccountServiceTrait return $group; } - - /** - * See reference nr. 99 - * - * @param TransactionGroup $group - * - * @return TransactionJournal - * @throws FireflyException - */ - private function getObJournal(TransactionGroup $group): TransactionJournal - { - /** @var TransactionJournal $journal */ - $journal = $group->transactionJournals()->first(); - if (null === $journal) { - throw new FireflyException(sprintf('Group #%d has no OB journal', $group->id)); - } - - return $journal; - } - - /** - * See reference nr. 98 - * - * @param TransactionJournal $journal - * @param Account $account - * - * @return Transaction - * @throws FireflyException - */ - private function getOBTransaction(TransactionJournal $journal, Account $account): Transaction - { - /** @var Transaction $transaction */ - $transaction = $journal->transactions()->where('account_id', '!=', $account->id)->first(); - if (null === $transaction) { - throw new FireflyException(sprintf('Could not get OB transaction for journal #%d', $journal->id)); - } - - return $transaction; - } - - /** - * @param TransactionJournal $journal - * @param Account $account - * - * @return Transaction - * @throws FireflyException - */ - private function getNotOBTransaction(TransactionJournal $journal, Account $account): Transaction - { - /** @var Transaction $transaction */ - $transaction = $journal->transactions()->where('account_id', $account->id)->first(); - if (null === $transaction) { - throw new FireflyException(sprintf('Could not get non-OB transaction for journal #%d', $journal->id)); - } - - return $transaction; - } } diff --git a/app/Services/Internal/Support/CreditRecalculateService.php b/app/Services/Internal/Support/CreditRecalculateService.php index 20d9ba78db..e67346304d 100644 --- a/app/Services/Internal/Support/CreditRecalculateService.php +++ b/app/Services/Internal/Support/CreditRecalculateService.php @@ -205,7 +205,7 @@ class CreditRecalculateService $factory->crud($account, 'start_of_debt', $startOfDebt); // get direction of liability: - $direction = (string)$this->repository->getMetaValue($account, 'liability_direction'); + $direction = (string) $this->repository->getMetaValue($account, 'liability_direction'); // now loop all transactions (except opening balance and credit thing) $transactions = $account->transactions()->get(); @@ -246,7 +246,7 @@ class CreditRecalculateService // to a credit-liability doesn't increase the amount (yet) if ( $type === TransactionType::WITHDRAWAL - && (int)$account->id === (int)$transaction->account_id + && (int) $account->id === (int) $transaction->account_id && 1 === bccomp($transaction->amount, '0') && 'credit' === $direction ) { @@ -258,7 +258,7 @@ class CreditRecalculateService // likewise deposit into a credit debt does not change the amount if ( $type === TransactionType::DEPOSIT - && (int)$account->id === (int)$transaction->account_id + && (int) $account->id === (int) $transaction->account_id && -1 === bccomp($transaction->amount, '0') && 'credit' === $direction ) { diff --git a/app/Services/Internal/Support/JournalServiceTrait.php b/app/Services/Internal/Support/JournalServiceTrait.php index 3d60e2add8..f9907647f5 100644 --- a/app/Services/Internal/Support/JournalServiceTrait.php +++ b/app/Services/Internal/Support/JournalServiceTrait.php @@ -98,7 +98,7 @@ trait JournalServiceTrait $search = null; // first attempt, find by ID. if (null !== $data['id']) { - $search = $this->accountRepository->find((int)$data['id']); + $search = $this->accountRepository->find((int) $data['id']); if (null !== $search && in_array($search->accountType->type, $types, true)) { Log::debug( sprintf('Found "account_id" object: #%d, "%s" of type %s', $search->id, $search->name, $search->accountType->type) @@ -109,32 +109,6 @@ trait JournalServiceTrait return $search; } - /** - * @param Account|null $account - * @param array $data - * @param array $types - * - * @return Account|null - */ - private function findAccountByName(?Account $account, array $data, array $types): ?Account - { - // second attempt, find by name. - if (null === $account && null !== $data['name']) { - // find by preferred type. - $source = $this->accountRepository->findByName($data['name'], [$types[0]]); - // or any expected type. - $source = $source ?? $this->accountRepository->findByName($data['name'], $types); - - if (null !== $source) { - Log::debug(sprintf('Found "account_name" object: #%d, %s', $source->id, $source->name)); - - $account = $source; - } - } - - return $account; - } - /** * @param Account|null $account * @param array $data @@ -175,10 +149,10 @@ trait JournalServiceTrait if (null === $account && null !== $data['number'] && '' !== (string) $data['number']) { Log::debug(sprintf('Searching for account number "%s".', $data['number'])); // find by preferred type. - $source = $this->accountRepository->findByAccountNumber((string)$data['number'], [$types[0]]); + $source = $this->accountRepository->findByAccountNumber((string) $data['number'], [$types[0]]); // or any expected type. - $source = $source ?? $this->accountRepository->findByAccountNumber((string)$data['number'], $types); + $source = $source ?? $this->accountRepository->findByAccountNumber((string) $data['number'], $types); if (null !== $source) { Log::debug(sprintf('Found account: #%d, %s', $source->id, $source->name)); @@ -190,6 +164,32 @@ trait JournalServiceTrait return $account; } + /** + * @param Account|null $account + * @param array $data + * @param array $types + * + * @return Account|null + */ + private function findAccountByName(?Account $account, array $data, array $types): ?Account + { + // second attempt, find by name. + if (null === $account && null !== $data['name']) { + // find by preferred type. + $source = $this->accountRepository->findByName($data['name'], [$types[0]]); + // or any expected type. + $source = $source ?? $this->accountRepository->findByName($data['name'], $types); + + if (null !== $source) { + Log::debug(sprintf('Found "account_name" object: #%d, %s', $source->id, $source->name)); + + $account = $source; + } + } + + return $account; + } + /** * @param Account|null $account * @param array $data @@ -218,12 +218,12 @@ trait JournalServiceTrait throw new FireflyException(sprintf('TransactionFactory: Cannot create asset account with these values: %s', json_encode($data))); } // fix name of account if only IBAN is given: - if ('' === (string)$data['name'] && '' !== (string)$data['iban']) { + if ('' === (string) $data['name'] && '' !== (string) $data['iban']) { Log::debug(sprintf('Account name is now IBAN ("%s")', $data['iban'])); $data['name'] = $data['iban']; } // fix name of account if only number is given: - if ('' === (string)$data['name'] && '' !== (string)$data['number']) { + if ('' === (string) $data['name'] && '' !== (string) $data['number']) { Log::debug(sprintf('Account name is now account number ("%s")', $data['number'])); $data['name'] = $data['number']; } @@ -379,7 +379,7 @@ trait JournalServiceTrait */ protected function storeNotes(TransactionJournal $journal, ?string $notes): void { - $notes = (string)$notes; + $notes = (string) $notes; $note = $journal->notes()->first(); if ('' !== $notes) { if (null === $note) { @@ -422,7 +422,7 @@ trait JournalServiceTrait } Log::debug('Start of loop.'); foreach ($tags as $string) { - $string = (string)$string; + $string = (string) $string; Log::debug(sprintf('Now at tag "%s"', $string)); if ('' !== $string) { $tag = $this->tagFactory->findOrCreate($string); diff --git a/app/Services/Internal/Support/RecurringTransactionTrait.php b/app/Services/Internal/Support/RecurringTransactionTrait.php index 73fa6604aa..f08d099fd0 100644 --- a/app/Services/Internal/Support/RecurringTransactionTrait.php +++ b/app/Services/Internal/Support/RecurringTransactionTrait.php @@ -144,7 +144,7 @@ trait RecurringTransactionTrait if (!$validator->validateDestination(['id' => $destination->id])) { throw new FireflyException(sprintf('Destination invalid: %s', $validator->destError)); } - if (array_key_exists('foreign_amount', $array) && '' === (string)$array['foreign_amount']) { + if (array_key_exists('foreign_amount', $array) && '' === (string) $array['foreign_amount']) { unset($array['foreign_amount']); } // See reference nr. 100 @@ -156,25 +156,25 @@ trait RecurringTransactionTrait 'source_id' => $source->id, 'destination_id' => $destination->id, 'amount' => $array['amount'], - 'foreign_amount' => array_key_exists('foreign_amount', $array) ? (string)$array['foreign_amount'] : null, + 'foreign_amount' => array_key_exists('foreign_amount', $array) ? (string) $array['foreign_amount'] : null, 'description' => $array['description'], ] ); $transaction->save(); if (array_key_exists('budget_id', $array)) { - $this->setBudget($transaction, (int)$array['budget_id']); + $this->setBudget($transaction, (int) $array['budget_id']); } if (array_key_exists('bill_id', $array)) { - $this->setBill($transaction, (int)$array['bill_id']); + $this->setBill($transaction, (int) $array['bill_id']); } if (array_key_exists('category_id', $array)) { - $this->setCategory($transaction, (int)$array['category_id']); + $this->setCategory($transaction, (int) $array['category_id']); } // same for piggy bank if (array_key_exists('piggy_bank_id', $array)) { - $this->updatePiggyBank($transaction, (int)$array['piggy_bank_id']); + $this->updatePiggyBank($transaction, (int) $array['piggy_bank_id']); } if (array_key_exists('tags', $array) && is_array($array['tags'])) { @@ -194,14 +194,14 @@ trait RecurringTransactionTrait protected function findAccount(array $expectedTypes, ?int $accountId, ?string $accountName): Account { $result = null; - $accountId = (int)$accountId; - $accountName = (string)$accountName; + $accountId = (int) $accountId; + $accountName = (string) $accountName; /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $repository->setUser($this->user); // if user has submitted an account ID, search for it. - $result = $repository->find((int)$accountId); + $result = $repository->find((int) $accountId); if (null !== $result) { return $result; } diff --git a/app/Services/Internal/Update/AccountUpdateService.php b/app/Services/Internal/Update/AccountUpdateService.php index 1e92b4a4a2..0529a75430 100644 --- a/app/Services/Internal/Update/AccountUpdateService.php +++ b/app/Services/Internal/Update/AccountUpdateService.php @@ -89,7 +89,7 @@ class AccountUpdateService // find currency, or use default currency instead. if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { - $currency = $this->getCurrency((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null)); + $currency = $this->getCurrency((int) ($data['currency_id'] ?? null), (string) ($data['currency_code'] ?? null)); unset($data['currency_code'], $data['currency_id']); $data['currency_id'] = $currency->id; } @@ -108,7 +108,7 @@ class AccountUpdateService // update note: if (array_key_exists('notes', $data) && null !== $data['notes']) { - $this->updateNote($account, (string)$data['notes']); + $this->updateNote($account, (string) $data['notes']); } // update preferences if inactive: @@ -135,7 +135,7 @@ class AccountUpdateService $account->active = $data['active']; } if (array_key_exists('iban', $data)) { - $account->iban = app('steam')->filterSpaces((string)$data['iban']); + $account->iban = app('steam')->filterSpaces((string) $data['iban']); } // set liability, but account must already be a liability. @@ -149,7 +149,7 @@ class AccountUpdateService // set liability, alternative method used in v1 layout: if ($this->isLiability($account) && array_key_exists('account_type_id', $data)) { - $type = AccountType::find((int)$data['account_type_id']); + $type = AccountType::find((int) $data['account_type_id']); if (null !== $type && in_array($type->type, config('firefly.valid_liabilities'), true)) { $account->account_type_id = $type->id; @@ -210,7 +210,7 @@ class AccountUpdateService return $account; } // get account type ID's because a join and an update is hard: - $oldOrder = (int)$account->order; + $oldOrder = (int) $account->order; $newOrder = $data['order']; Log::debug(sprintf('Order is set to be updated from %s to %s', $oldOrder, $newOrder)); $list = $this->getTypeIds([AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT]); @@ -248,7 +248,7 @@ class AccountUpdateService foreach ($array as $type) { /** @var AccountType $type */ $type = AccountType::whereType($type)->first(); - $return[] = (int)$type->id; + $return[] = (int) $type->id; } return $return; @@ -357,12 +357,12 @@ class AccountUpdateService $array = $preference->data; Log::debug('Old array is: ', $array); Log::debug(sprintf('Must remove : %d', $account->id)); - $removeAccountId = (int)$account->id; + $removeAccountId = (int) $account->id; $new = []; foreach ($array as $value) { - if ((int)$value !== $removeAccountId) { + if ((int) $value !== $removeAccountId) { Log::debug(sprintf('Will include: %d', $value)); - $new[] = (int)$value; + $new[] = (int) $value; } } Log::debug('Final new array is', $new); diff --git a/app/Services/Internal/Update/BillUpdateService.php b/app/Services/Internal/Update/BillUpdateService.php index a25e723937..b90530a05e 100644 --- a/app/Services/Internal/Update/BillUpdateService.php +++ b/app/Services/Internal/Update/BillUpdateService.php @@ -56,7 +56,7 @@ class BillUpdateService if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { $factory = app(TransactionCurrencyFactory::class); - $currency = $factory->find((int)($data['currency_id'] ?? null), $data['currency_code'] ?? null) ?? + $currency = $factory->find((int) ($data['currency_id'] ?? null), $data['currency_code'] ?? null) ?? app('amount')->getDefaultCurrencyByUser($bill->user); // enable the currency if it isn't. @@ -78,14 +78,14 @@ class BillUpdateService ]; // update note: if (array_key_exists('notes', $data)) { - $this->updateNote($bill, (string)$data['notes']); + $this->updateNote($bill, (string) $data['notes']); } // update order. if (array_key_exists('order', $data)) { // update the order of the piggy bank: - $oldOrder = (int)$bill->order; - $newOrder = (int)($data['order'] ?? $oldOrder); + $oldOrder = (int) $bill->order; + $newOrder = (int) ($data['order'] ?? $oldOrder); if ($oldOrder !== $newOrder) { $this->updateOrder($bill, $oldOrder, $newOrder); } @@ -117,7 +117,7 @@ class BillUpdateService } if (array_key_exists('object_group_id', $data)) { // try also with ID: - $objectGroupId = (int)($data['object_group_id'] ?? 0); + $objectGroupId = (int) ($data['object_group_id'] ?? 0); if (0 !== $objectGroupId) { $objectGroup = $this->findObjectGroupById($objectGroupId); if (null !== $objectGroup) { @@ -144,20 +144,20 @@ class BillUpdateService */ private function updateBillProperties(Bill $bill, array $data): Bill { - if (array_key_exists('name', $data) && '' !== (string)$data['name']) { + if (array_key_exists('name', $data) && '' !== (string) $data['name']) { $bill->name = $data['name']; } - if (array_key_exists('amount_min', $data) && '' !== (string)$data['amount_min']) { + if (array_key_exists('amount_min', $data) && '' !== (string) $data['amount_min']) { $bill->amount_min = $data['amount_min']; } - if (array_key_exists('amount_max', $data) && '' !== (string)$data['amount_max']) { + if (array_key_exists('amount_max', $data) && '' !== (string) $data['amount_max']) { $bill->amount_max = $data['amount_max']; } - if (array_key_exists('date', $data) && '' !== (string)$data['date']) { + if (array_key_exists('date', $data) && '' !== (string) $data['date']) { $bill->date = $data['date']; } - if (array_key_exists('repeat_freq', $data) && '' !== (string)$data['repeat_freq']) { + if (array_key_exists('repeat_freq', $data) && '' !== (string) $data['repeat_freq']) { $bill->repeat_freq = $data['repeat_freq']; } if (array_key_exists('skip', $data)) { @@ -166,10 +166,10 @@ class BillUpdateService if (array_key_exists('active', $data)) { $bill->active = $data['active']; } - if(array_key_exists('end_date', $data)) { + if (array_key_exists('end_date', $data)) { $bill->end_date = $data['end_date']; } - if(array_key_exists('extension_date', $data)) { + if (array_key_exists('extension_date', $data)) { $bill->extension_date = $data['extension_date']; } diff --git a/app/Services/Internal/Update/CurrencyUpdateService.php b/app/Services/Internal/Update/CurrencyUpdateService.php index f84a1b78f2..4c6219d97c 100644 --- a/app/Services/Internal/Update/CurrencyUpdateService.php +++ b/app/Services/Internal/Update/CurrencyUpdateService.php @@ -40,15 +40,15 @@ class CurrencyUpdateService */ public function update(TransactionCurrency $currency, array $data): TransactionCurrency { - if (array_key_exists('code', $data) && '' !== (string)$data['code']) { + if (array_key_exists('code', $data) && '' !== (string) $data['code']) { $currency->code = $data['code']; } - if (array_key_exists('symbol', $data) && '' !== (string)$data['symbol']) { + if (array_key_exists('symbol', $data) && '' !== (string) $data['symbol']) { $currency->symbol = $data['symbol']; } - if (array_key_exists('name', $data) && '' !== (string)$data['name']) { + if (array_key_exists('name', $data) && '' !== (string) $data['name']) { $currency->name = $data['name']; } diff --git a/app/Services/Internal/Update/GroupCloneService.php b/app/Services/Internal/Update/GroupCloneService.php index cd6bb7e107..92386d9365 100644 --- a/app/Services/Internal/Update/GroupCloneService.php +++ b/app/Services/Internal/Update/GroupCloneService.php @@ -48,7 +48,7 @@ class GroupCloneService $newGroup = $group->replicate(); $newGroup->save(); foreach ($group->transactionJournals as $journal) { - $this->cloneJournal($journal, $newGroup, (int)$group->id); + $this->cloneJournal($journal, $newGroup, (int) $group->id); } return $newGroup; diff --git a/app/Services/Internal/Update/JournalUpdateService.php b/app/Services/Internal/Update/JournalUpdateService.php index d16d0b8ac4..61ed19b2f2 100644 --- a/app/Services/Internal/Update/JournalUpdateService.php +++ b/app/Services/Internal/Update/JournalUpdateService.php @@ -215,7 +215,7 @@ class JournalUpdateService $validator->setTransactionType($expectedType); $validator->setUser($this->transactionJournal->user); - $result = $validator->validateSource(['id' =>$sourceId]); + $result = $validator->validateSource(['id' => $sourceId]); Log::debug(sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true))); // See reference nr. 95 @@ -359,7 +359,7 @@ class JournalUpdateService } $sourceInfo = [ - 'id' => (int)($this->data['source_id'] ?? null), + 'id' => (int) ($this->data['source_id'] ?? null), 'name' => $this->data['source_name'] ?? null, 'iban' => $this->data['source_iban'] ?? null, 'number' => $this->data['source_number'] ?? null, @@ -424,7 +424,7 @@ class JournalUpdateService } $destInfo = [ - 'id' => (int)($this->data['destination_id'] ?? null), + 'id' => (int) ($this->data['destination_id'] ?? null), 'name' => $this->data['destination_name'] ?? null, 'iban' => $this->data['destination_iban'] ?? null, 'number' => $this->data['destination_number'] ?? null, @@ -487,8 +487,8 @@ class JournalUpdateService ) && TransactionType::WITHDRAWAL === $type ) { - $billId = (int)($this->data['bill_id'] ?? 0); - $billName = (string)($this->data['bill_name'] ?? ''); + $billId = (int) ($this->data['bill_id'] ?? 0); + $billName = (string) ($this->data['bill_name'] ?? ''); $bill = $this->billRepository->findBill($billId, $billName); $this->transactionJournal->bill_id = $bill?->id; Log::debug('Updated bill ID'); @@ -502,7 +502,7 @@ class JournalUpdateService */ private function updateField(string $fieldName): void { - if (array_key_exists($fieldName, $this->data) && '' !== (string)$this->data[$fieldName]) { + if (array_key_exists($fieldName, $this->data) && '' !== (string) $this->data[$fieldName]) { $value = $this->data[$fieldName]; if ('date' === $fieldName) { @@ -579,7 +579,7 @@ class JournalUpdateService { // update notes. if ($this->hasFields(['notes'])) { - $notes = '' === (string)$this->data['notes'] ? null : $this->data['notes']; + $notes = '' === (string) $this->data['notes'] ? null : $this->data['notes']; $this->storeNotes($this->transactionJournal, $notes); } } @@ -636,7 +636,7 @@ class JournalUpdateService foreach ($this->metaDate as $field) { if ($this->hasFields([$field])) { try { - $value = '' === (string)$this->data[$field] ? null : new Carbon($this->data[$field]); + $value = '' === (string) $this->data[$field] ? null : new Carbon($this->data[$field]); } catch (Exception $e) { // @phpstan-ignore-line Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage())); diff --git a/app/Services/Internal/Update/RecurrenceUpdateService.php b/app/Services/Internal/Update/RecurrenceUpdateService.php index 9fa6af232f..f099d2ec09 100644 --- a/app/Services/Internal/Update/RecurrenceUpdateService.php +++ b/app/Services/Internal/Update/RecurrenceUpdateService.php @@ -78,7 +78,7 @@ class RecurrenceUpdateService $recurrence->repetitions = 0; } if (array_key_exists('nr_of_repetitions', $info)) { - if (0 !== (int)$info['nr_of_repetitions']) { + if (0 !== (int) $info['nr_of_repetitions']) { $recurrence->repeat_until = null; } $recurrence->repetitions = $info['nr_of_repetitions']; @@ -257,7 +257,7 @@ class RecurrenceUpdateService unset($current['currency_id'], $current['currency_code']); } if (null !== $currency) { - $current['currency_id'] = (int)$currency->id; + $current['currency_id'] = (int) $currency->id; } if (array_key_exists('foreign_currency_id', $current) || array_key_exists('foreign_currency_code', $current)) { $foreignCurrency = $currencyFactory->find($current['foreign_currency_id'] ?? null, $currency['foreign_currency_code'] ?? null); @@ -266,7 +266,7 @@ class RecurrenceUpdateService unset($current['foreign_currency_id'], $currency['foreign_currency_code']); } if (null !== $foreignCurrency) { - $current['foreign_currency_id'] = (int)$foreignCurrency->id; + $current['foreign_currency_id'] = (int) $foreignCurrency->id; } // update fields @@ -287,27 +287,27 @@ class RecurrenceUpdateService } // update meta data if (array_key_exists('budget_id', $current)) { - $this->setBudget($match, (int)$current['budget_id']); + $this->setBudget($match, (int) $current['budget_id']); } if (array_key_exists('bill_id', $current)) { - $this->setBill($match, (int)$current['bill_id']); + $this->setBill($match, (int) $current['bill_id']); } // reset category if name is set but empty: // can be removed when v1 is retired. - if (array_key_exists('category_name', $current) && '' === (string)$current['category_name']) { + if (array_key_exists('category_name', $current) && '' === (string) $current['category_name']) { $current['category_name'] = null; $current['category_id'] = 0; } if (array_key_exists('category_id', $current)) { - $this->setCategory($match, (int)$current['category_id']); + $this->setCategory($match, (int) $current['category_id']); } if (array_key_exists('tags', $current) && is_array($current['tags'])) { $this->updateTags($match, $current['tags']); } if (array_key_exists('piggy_bank_id', $current)) { - $this->updatePiggyBank($match, (int)$current['piggy_bank_id']); + $this->updatePiggyBank($match, (int) $current['piggy_bank_id']); } } } diff --git a/app/Services/Password/PwndVerifierV2.php b/app/Services/Password/PwndVerifierV2.php index 6ebdae729b..8c286f08c7 100644 --- a/app/Services/Password/PwndVerifierV2.php +++ b/app/Services/Password/PwndVerifierV2.php @@ -62,7 +62,7 @@ class PwndVerifierV2 implements Verifier try { $client = new Client(); $res = $client->request('GET', $uri, $opt); - } catch (GuzzleException | RequestException $e) { + } catch (GuzzleException|RequestException $e) { Log::error(sprintf('Could not verify password security: %s', $e->getMessage())); return true; diff --git a/app/Services/Webhook/StandardWebhookSender.php b/app/Services/Webhook/StandardWebhookSender.php index 673d299912..94e7f7b78f 100644 --- a/app/Services/Webhook/StandardWebhookSender.php +++ b/app/Services/Webhook/StandardWebhookSender.php @@ -59,7 +59,7 @@ class StandardWebhookSender implements WebhookSenderInterface try { $signature = $signatureGenerator->generate($this->message); - } catch(FireflyException $e) { + } catch (FireflyException $e) { Log::error('Did not send message because of a Firefly III Exception.'); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); diff --git a/app/Support/Binder/EitherConfigKey.php b/app/Support/Binder/EitherConfigKey.php index 512fdfa0f2..476ac8613e 100644 --- a/app/Support/Binder/EitherConfigKey.php +++ b/app/Support/Binder/EitherConfigKey.php @@ -53,7 +53,7 @@ class EitherConfigKey // triggers and actions: 'firefly.rule-actions', 'firefly.context-rule-actions', - 'search.operators' + 'search.operators', ]; /** diff --git a/app/Support/Cronjobs/RecurringCronjob.php b/app/Support/Cronjobs/RecurringCronjob.php index 665a15bc27..18abc6347b 100644 --- a/app/Support/Cronjobs/RecurringCronjob.php +++ b/app/Support/Cronjobs/RecurringCronjob.php @@ -42,7 +42,7 @@ class RecurringCronjob extends AbstractCronjob Log::debug(sprintf('Now in %s', __METHOD__)); /** @var Configuration $config */ $config = app('fireflyconfig')->get('last_rt_job', 0); - $lastTime = (int)$config->data; + $lastTime = (int) $config->data; $diff = time() - $lastTime; $diffForHumans = Carbon::now()->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true); @@ -95,8 +95,8 @@ class RecurringCronjob extends AbstractCronjob $this->jobSucceeded = true; $this->message = 'Recurring transactions cron job fired successfully.'; - app('fireflyconfig')->set('last_rt_job', (int)$this->date->format('U')); - Log::info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int)$this->date->format('U'))); + app('fireflyconfig')->set('last_rt_job', (int) $this->date->format('U')); + Log::info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int) $this->date->format('U'))); Log::info('Done with recurring cron job task.'); } } diff --git a/app/Support/Http/Controllers/RuleManagement.php b/app/Support/Http/Controllers/RuleManagement.php index c83608c32a..2144fa036d 100644 --- a/app/Support/Http/Controllers/RuleManagement.php +++ b/app/Support/Http/Controllers/RuleManagement.php @@ -55,7 +55,7 @@ trait RuleManagement [ 'oldAction' => $oldAction['type'], 'oldValue' => $oldAction['value'], - 'oldChecked' => 1 === (int)($oldAction['stop_processing'] ?? '0'), + 'oldChecked' => 1 === (int) ($oldAction['stop_processing'] ?? '0'), 'count' => $index + 1, ] )->render(); @@ -84,7 +84,7 @@ trait RuleManagement foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); @@ -100,7 +100,7 @@ trait RuleManagement [ 'oldTrigger' => OperatorQuerySearch::getRootOperator($oldTrigger['type']), 'oldValue' => $oldTrigger['value'], - 'oldChecked' => 1 === (int)($oldTrigger['stop_processing'] ?? '0'), + 'oldChecked' => 1 === (int) ($oldTrigger['stop_processing'] ?? '0'), 'count' => $index + 1, 'triggers' => $triggers, ] @@ -130,7 +130,7 @@ trait RuleManagement foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); @@ -167,8 +167,8 @@ trait RuleManagement $repository = app(RuleGroupRepositoryInterface::class); if (0 === $repository->count()) { $data = [ - 'title' => (string)trans('firefly.default_rule_group_name'), - 'description' => (string)trans('firefly.default_rule_group_description'), + 'title' => (string) trans('firefly.default_rule_group_name'), + 'description' => (string) trans('firefly.default_rule_group_description'), 'active' => true, ]; diff --git a/app/Support/Http/Controllers/UserNavigation.php b/app/Support/Http/Controllers/UserNavigation.php index a9c3508cf1..72dd2829ee 100644 --- a/app/Support/Http/Controllers/UserNavigation.php +++ b/app/Support/Http/Controllers/UserNavigation.php @@ -54,7 +54,7 @@ trait UserNavigation final protected function getPreviousUri(string $identifier): string { Log::debug(sprintf('Trying to retrieve URL stored under "%s"', $identifier)); - $url = (string)session($identifier); + $url = (string) session($identifier); Log::debug(sprintf('The URL is %s', $url)); return app('steam')->getSafeUrl($url, route('index')); diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index 1b7388957e..75905e221b 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -340,17 +340,17 @@ class Navigation // define period to increment $increment = 'addDay'; $format = $this->preferredCarbonFormat($start, $end); - $displayFormat = (string)trans('config.month_and_day_js', [], $locale); + $displayFormat = (string) trans('config.month_and_day_js', [], $locale); // increment by month (for year) if ($start->diffInMonths($end) > 1) { $increment = 'addMonth'; - $displayFormat = (string)trans('config.month_js'); + $displayFormat = (string) trans('config.month_js'); } // increment by year (for multi year) if ($start->diffInMonths($end) > 12) { $increment = 'addYear'; - $displayFormat = (string)trans('config.year_js'); + $displayFormat = (string) trans('config.year_js'); } $begin = clone $start; $entries = []; @@ -397,23 +397,23 @@ class Navigation { $date = clone $theDate; $formatMap = [ - '1D' => (string)trans('config.specific_day_js'), - 'daily' => (string)trans('config.specific_day_js'), - 'custom' => (string)trans('config.specific_day_js'), - '1W' => (string)trans('config.week_in_year_js'), - 'week' => (string)trans('config.week_in_year_js'), - 'weekly' => (string)trans('config.week_in_year_js'), - '1M' => (string)trans('config.month_js'), - 'month' => (string)trans('config.month_js'), - 'monthly' => (string)trans('config.month_js'), - '1Y' => (string)trans('config.year_js'), - 'year' => (string)trans('config.year_js'), - 'yearly' => (string)trans('config.year_js'), - '6M' => (string)trans('config.half_year_js'), + '1D' => (string) trans('config.specific_day_js'), + 'daily' => (string) trans('config.specific_day_js'), + 'custom' => (string) trans('config.specific_day_js'), + '1W' => (string) trans('config.week_in_year_js'), + 'week' => (string) trans('config.week_in_year_js'), + 'weekly' => (string) trans('config.week_in_year_js'), + '1M' => (string) trans('config.month_js'), + 'month' => (string) trans('config.month_js'), + 'monthly' => (string) trans('config.month_js'), + '1Y' => (string) trans('config.year_js'), + 'year' => (string) trans('config.year_js'), + 'yearly' => (string) trans('config.year_js'), + '6M' => (string) trans('config.half_year_js'), ]; if (array_key_exists($repeatFrequency, $formatMap)) { - return $date->isoFormat((string)$formatMap[$repeatFrequency]); + return $date->isoFormat((string) $formatMap[$repeatFrequency]); } if ('3M' === $repeatFrequency || 'quarter' === $repeatFrequency) { $quarter = ceil($theDate->month / 3); @@ -440,13 +440,13 @@ class Navigation public function preferredCarbonLocalizedFormat(Carbon $start, Carbon $end): string { $locale = app('steam')->getLocale(); - $format = (string)trans('config.month_and_day_js', [], $locale); + $format = (string) trans('config.month_and_day_js', [], $locale); if ($start->diffInMonths($end) > 1) { - $format = (string)trans('config.month_js', [], $locale); + $format = (string) trans('config.month_js', [], $locale); } if ($start->diffInMonths($end) > 12) { - $format = (string)trans('config.year_js', [], $locale); + $format = (string) trans('config.year_js', [], $locale); } return $format; diff --git a/app/Support/Repositories/Recurring/CalculateXOccurrences.php b/app/Support/Repositories/Recurring/CalculateXOccurrences.php index e8ff1fc664..166fa78fcc 100644 --- a/app/Support/Repositories/Recurring/CalculateXOccurrences.php +++ b/app/Support/Repositories/Recurring/CalculateXOccurrences.php @@ -77,7 +77,7 @@ trait CalculateXOccurrences $mutator = clone $date; $total = 0; $attempts = 0; - $dayOfMonth = (int)$moment; + $dayOfMonth = (int) $moment; if ($mutator->day > $dayOfMonth) { // day has passed already, add a month. $mutator->addMonth(); @@ -155,7 +155,7 @@ trait CalculateXOccurrences // monday = 1 // sunday = 7 $mutator->addDay(); // always assume today has passed. - $dayOfWeek = (int)$moment; + $dayOfWeek = (int) $moment; if ($mutator->dayOfWeekIso > $dayOfWeek) { // day has already passed this week, add one week: $mutator->addWeek(); diff --git a/app/Support/Repositories/Recurring/CalculateXOccurrencesSince.php b/app/Support/Repositories/Recurring/CalculateXOccurrencesSince.php index b3d4c56a35..b46a5dfebc 100644 --- a/app/Support/Repositories/Recurring/CalculateXOccurrencesSince.php +++ b/app/Support/Repositories/Recurring/CalculateXOccurrencesSince.php @@ -82,7 +82,7 @@ trait CalculateXOccurrencesSince $mutator = clone $date; $total = 0; $attempts = 0; - $dayOfMonth = (int)$moment; + $dayOfMonth = (int) $moment; $dayOfMonth = 0 === $dayOfMonth ? 1 : $dayOfMonth; if ($mutator->day > $dayOfMonth) { Log::debug(sprintf('%d is after %d, add a month. Mutator is now', $mutator->day, $dayOfMonth)); @@ -169,7 +169,7 @@ trait CalculateXOccurrencesSince // sunday = 7 // Removed assumption today has passed, see issue https://github.com/firefly-iii/firefly-iii/issues/4798 //$mutator->addDay(); // always assume today has passed. - $dayOfWeek = (int)$moment; + $dayOfWeek = (int) $moment; if ($mutator->dayOfWeekIso > $dayOfWeek) { // day has already passed this week, add one week: $mutator->addWeek(); diff --git a/app/Support/Request/ConvertsDataTypes.php b/app/Support/Request/ConvertsDataTypes.php index f7399e6dba..695978ee86 100644 --- a/app/Support/Request/ConvertsDataTypes.php +++ b/app/Support/Request/ConvertsDataTypes.php @@ -41,7 +41,7 @@ trait ConvertsDataTypes */ public function integer(string $field): int { - return (int)$this->get($field); + return (int) $this->get($field); } /** @@ -53,7 +53,7 @@ trait ConvertsDataTypes */ public function string(string $field): string { - return $this->clearString((string)($this->get($field) ?? ''), false); + return $this->clearString((string) ($this->get($field) ?? ''), false); } /** @@ -131,7 +131,7 @@ trait ConvertsDataTypes */ public function stringWithNewlines(string $field): string { - return $this->clearString((string)($this->get($field) ?? '')); + return $this->clearString((string) ($this->get($field) ?? '')); } /** @@ -180,28 +180,6 @@ trait ConvertsDataTypes return false; } - /** - * Return date or NULL. - * - * @param string $field - * - * @return Carbon|null - */ - protected function getCarbonDate(string $field): ?Carbon - { - $result = null; - try { - $result = $this->get($field) ? new Carbon($this->get($field)) : null; - } catch (InvalidFormatException $e) { - // @ignoreException - } - if (null === $result) { - Log::debug(sprintf('Exception when parsing date "%s".', $this->get($field))); - } - - return $result; - } - /** * @param string|null $string * @@ -245,7 +223,7 @@ trait ConvertsDataTypes return null; } - return (float)$res; + return (float) $res; } /** @@ -269,6 +247,28 @@ trait ConvertsDataTypes return $return; } + /** + * Return date or NULL. + * + * @param string $field + * + * @return Carbon|null + */ + protected function getCarbonDate(string $field): ?Carbon + { + $result = null; + try { + $result = $this->get($field) ? new Carbon($this->get($field)) : null; + } catch (InvalidFormatException $e) { + // @ignoreException + } + if (null === $result) { + Log::debug(sprintf('Exception when parsing date "%s".', $this->get($field))); + } + + return $result; + } + /** * Parse to integer * @@ -285,7 +285,7 @@ trait ConvertsDataTypes return null; } - return (int)$string; + return (int) $string; } /** @@ -301,12 +301,12 @@ trait ConvertsDataTypes return null; } - $value = (string)$this->get($field); + $value = (string) $this->get($field); if ('' === $value) { return null; } - return (int)$value; + return (int) $value; } } diff --git a/app/Support/Search/AccountSearch.php b/app/Support/Search/AccountSearch.php index 5a111c40ea..4fe9758d27 100644 --- a/app/Support/Search/AccountSearch.php +++ b/app/Support/Search/AccountSearch.php @@ -37,14 +37,13 @@ class AccountSearch implements GenericSearchInterface /** @var string */ public const SEARCH_ALL = 'all'; /** @var string */ - public const SEARCH_NAME = 'name'; - /** @var string */ public const SEARCH_IBAN = 'iban'; /** @var string */ - public const SEARCH_NUMBER = 'number'; - /** @var string */ public const SEARCH_ID = 'id'; - + /** @var string */ + public const SEARCH_NAME = 'name'; + /** @var string */ + public const SEARCH_NUMBER = 'number'; private string $field; private string $query; private array $types; @@ -62,11 +61,11 @@ class AccountSearch implements GenericSearchInterface public function search(): Collection { - $searchQuery = $this->user->accounts() - ->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id') - ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->whereIn('account_types.type', $this->types); - $like = sprintf('%%%s%%', $this->query); + $searchQuery = $this->user->accounts() + ->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id') + ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->whereIn('account_types.type', $this->types); + $like = sprintf('%%%s%%', $this->query); $originalQuery = $this->query; switch ($this->field) { default: @@ -88,7 +87,7 @@ class AccountSearch implements GenericSearchInterface ); break; case self::SEARCH_ID: - $searchQuery->where('accounts.id', '=', (int)$originalQuery); + $searchQuery->where('accounts.id', '=', (int) $originalQuery); break; case self::SEARCH_NAME: $searchQuery->where('accounts.name', 'LIKE', $like); diff --git a/app/Support/Search/OperatorQuerySearch.php b/app/Support/Search/OperatorQuerySearch.php index 8e1a9d9449..a5df8dbcdb 100644 --- a/app/Support/Search/OperatorQuerySearch.php +++ b/app/Support/Search/OperatorQuerySearch.php @@ -170,73 +170,6 @@ class OperatorQuerySearch implements SearchInterface $this->collector->setSearchWords($this->words); } - /** - * @inheritDoc - * @codeCoverageIgnore - */ - public function searchTime(): float - { - return microtime(true) - $this->startTime; - } - - /** - * @inheritDoc - */ - public function searchTransactions(): LengthAwarePaginator - { - if (empty($this->getWords()) && empty($this->getOperators())) { - return new LengthAwarePaginator([], 0, 5, 1); - } - - return $this->collector->getPaginatedGroups(); - } - - /** - * @param Carbon $date - */ - public function setDate(Carbon $date): void - { - $this->date = $date; - } - - /** - * @param int $limit - */ - public function setLimit(int $limit): void - { - $this->limit = $limit; - $this->collector->setLimit($this->limit); - } - - /** - * @inheritDoc - * @codeCoverageIgnore - */ - public function setPage(int $page): void - { - $this->page = $page; - $this->collector->setPage($this->page); - } - - /** - * @inheritDoc - * @codeCoverageIgnore - */ - public function setUser(User $user): void - { - $this->accountRepository->setUser($user); - $this->billRepository->setUser($user); - $this->categoryRepository->setUser($user); - $this->budgetRepository->setUser($user); - $this->tagRepository->setUser($user); - $this->collector = app(GroupCollectorInterface::class); - $this->collector->setUser($user); - $this->collector->withAccountInformation()->withCategoryInformation()->withBudgetInformation(); - - $this->setLimit((int) app('preferences')->getForUser($user, 'listPageSize', 50)->data); - - } - /** * @param Node $searchNode * @@ -1152,14 +1085,6 @@ class OperatorQuerySearch implements SearchInterface ]; } - /** - * @return array - */ - public function getWords(): array - { - return $this->words; - } - /** * @param array $range * @@ -1199,46 +1124,6 @@ class OperatorQuerySearch implements SearchInterface } } - /** - * @param string $field - * @param array $range - * @return void - * @throws FireflyException - */ - private function setExactObjectDateParams(string $field,array $range): void - { - /** - * @var string $key - * @var Carbon|string $value - */ - foreach ($range as $key => $value) { - switch ($key) { - default: - throw new FireflyException(sprintf('Cannot handle key "%s" in setExactObjectDateParams()', $key)); - case 'exact': - Log::debug(sprintf('Set %s_is_exact value "%s"',$field, $value->format('Y-m-d'))); - $this->collector->setObjectRange($value, clone $value, $field); - $this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); - break; - case 'year': - Log::debug(sprintf('Set %s_is_exact YEAR value "%s"', $field, $value)); - $this->collector->objectYearIs($value, $field); - $this->operators->push(['type' => sprintf('%s_on_year', $field), 'value' => $value,]); - break; - case 'month': - Log::debug(sprintf('Set %s_is_exact MONTH value "%s"', $field, $value)); - $this->collector->objectMonthIs($value, $field); - $this->operators->push(['type' => sprintf('%s_on_month', $field), 'value' => $value,]); - break; - case 'day': - Log::debug(sprintf('Set %s_is_exact DAY value "%s"', $field, $value)); - $this->collector->objectDayIs($value, $field); - $this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]); - break; - } - } - } - /** * @param array $range * @@ -1277,6 +1162,85 @@ class OperatorQuerySearch implements SearchInterface } } + /** + * @param array $range + * + * @throws FireflyException + */ + private function setDateAfterParams(array $range) + { + /** + * @var string $key + * @var Carbon|string $value + */ + foreach ($range as $key => $value) { + switch ($key) { + default: + throw new FireflyException(sprintf('Cannot handle key "%s" in setDateAfterParams()', $key)); + case 'exact': + $this->collector->setAfter($value); + $this->operators->push(['type' => 'date_after', 'value' => $value->format('Y-m-d'),]); + break; + case 'year': + Log::debug(sprintf('Set date_is_after YEAR value "%s"', $value)); + $this->collector->yearAfter($value); + $this->operators->push(['type' => 'date_after_year', 'value' => $value,]); + break; + case 'month': + Log::debug(sprintf('Set date_is_after MONTH value "%s"', $value)); + $this->collector->monthAfter($value); + $this->operators->push(['type' => 'date_after_month', 'value' => $value,]); + break; + case 'day': + Log::debug(sprintf('Set date_is_after DAY value "%s"', $value)); + $this->collector->dayAfter($value); + $this->operators->push(['type' => 'date_after_day', 'value' => $value,]); + break; + } + } + } + + /** + * @param string $field + * @param array $range + * @return void + * @throws FireflyException + */ + private function setExactMetaDateParams(string $field, array $range): void + { + Log::debug('Now in setExactMetaDateParams()'); + /** + * @var string $key + * @var Carbon|string $value + */ + foreach ($range as $key => $value) { + switch ($key) { + default: + throw new FireflyException(sprintf('Cannot handle key "%s" in setExactMetaDateParams()', $key)); + case 'exact': + Log::debug(sprintf('Set %s_is_exact value "%s"', $field, $value->format('Y-m-d'))); + $this->collector->setMetaDateRange($value, $value, $field); + $this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); + break; + case 'year': + Log::debug(sprintf('Set %s_is_exact YEAR value "%s"', $field, $value)); + $this->collector->metaYearIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_year', $field), 'value' => $value,]); + break; + case 'month': + Log::debug(sprintf('Set %s_is_exact MONTH value "%s"', $field, $value)); + $this->collector->metaMonthIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_month', $field), 'value' => $value,]); + break; + case 'day': + Log::debug(sprintf('Set %s_is_exact DAY value "%s"', $field, $value)); + $this->collector->metaDayIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]); + break; + } + } + } + /** * @param string $field * @param array $range @@ -1356,11 +1320,12 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param array $range - * + * @param string $field + * @param array $range + * @return void * @throws FireflyException */ - private function setDateAfterParams(array $range) + private function setExactObjectDateParams(string $field, array $range): void { /** * @var string $key @@ -1369,63 +1334,26 @@ class OperatorQuerySearch implements SearchInterface foreach ($range as $key => $value) { switch ($key) { default: - throw new FireflyException(sprintf('Cannot handle key "%s" in setDateAfterParams()', $key)); + throw new FireflyException(sprintf('Cannot handle key "%s" in setExactObjectDateParams()', $key)); case 'exact': - $this->collector->setAfter($value); - $this->operators->push(['type' => 'date_after', 'value' => $value->format('Y-m-d'),]); + Log::debug(sprintf('Set %s_is_exact value "%s"', $field, $value->format('Y-m-d'))); + $this->collector->setObjectRange($value, clone $value, $field); + $this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); break; case 'year': - Log::debug(sprintf('Set date_is_after YEAR value "%s"', $value)); - $this->collector->yearAfter($value); - $this->operators->push(['type' => 'date_after_year', 'value' => $value,]); + Log::debug(sprintf('Set %s_is_exact YEAR value "%s"', $field, $value)); + $this->collector->objectYearIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_year', $field), 'value' => $value,]); break; case 'month': - Log::debug(sprintf('Set date_is_after MONTH value "%s"', $value)); - $this->collector->monthAfter($value); - $this->operators->push(['type' => 'date_after_month', 'value' => $value,]); + Log::debug(sprintf('Set %s_is_exact MONTH value "%s"', $field, $value)); + $this->collector->objectMonthIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_month', $field), 'value' => $value,]); break; case 'day': - Log::debug(sprintf('Set date_is_after DAY value "%s"', $value)); - $this->collector->dayAfter($value); - $this->operators->push(['type' => 'date_after_day', 'value' => $value,]); - break; - } - } - } - - /** - * @param array $range - * - * @throws FireflyException - */ - private function setObjectDateAfterParams(string $field, array $range) - { - /** - * @var string $key - * @var Carbon|string $value - */ - foreach ($range as $key => $value) { - switch ($key) { - default: - throw new FireflyException(sprintf('Cannot handle key "%s" in setDateAfterParams()', $key)); - case 'exact': - $this->collector->setObjectAfter($value, $field); - $this->operators->push(['type' => sprintf('%s_after', $field), 'value' => $value->format('Y-m-d'),]); - break; - case 'year': - Log::debug(sprintf('Set date_is_after YEAR value "%s"', $value)); - $this->collector->objectYearAfter($value, $field); - $this->operators->push(['type' => sprintf('%s_after_year', $field), 'value' => $value,]); - break; - case 'month': - Log::debug(sprintf('Set date_is_after MONTH value "%s"', $value)); - $this->collector->objectMonthAfter($value, $field); - $this->operators->push(['type' => sprintf('%s_after_month', $field), 'value' => $value,]); - break; - case 'day': - Log::debug(sprintf('Set date_is_after DAY value "%s"', $value)); - $this->collector->objectDayAfter($value, $field); - $this->operators->push(['type' => sprintf('%s_after_day', $field), 'value' => $value,]); + Log::debug(sprintf('Set %s_is_exact DAY value "%s"', $field, $value)); + $this->collector->objectDayIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]); break; } } @@ -1470,14 +1398,12 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param string $field - * @param array $range - * @return void + * @param array $range + * * @throws FireflyException */ - private function setExactMetaDateParams(string $field, array $range): void + private function setObjectDateAfterParams(string $field, array $range) { - Log::debug('Now in setExactMetaDateParams()'); /** * @var string $key * @var Carbon|string $value @@ -1485,28 +1411,102 @@ class OperatorQuerySearch implements SearchInterface foreach ($range as $key => $value) { switch ($key) { default: - throw new FireflyException(sprintf('Cannot handle key "%s" in setExactMetaDateParams()', $key)); + throw new FireflyException(sprintf('Cannot handle key "%s" in setDateAfterParams()', $key)); case 'exact': - Log::debug(sprintf('Set %s_is_exact value "%s"', $field, $value->format('Y-m-d'))); - $this->collector->setMetaDateRange($value, $value, $field); - $this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); + $this->collector->setObjectAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after', $field), 'value' => $value->format('Y-m-d'),]); break; case 'year': - Log::debug(sprintf('Set %s_is_exact YEAR value "%s"', $field, $value)); - $this->collector->metaYearIs($value, $field); - $this->operators->push(['type' => sprintf('%s_on_year', $field), 'value' => $value,]); + Log::debug(sprintf('Set date_is_after YEAR value "%s"', $value)); + $this->collector->objectYearAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_year', $field), 'value' => $value,]); break; case 'month': - Log::debug(sprintf('Set %s_is_exact MONTH value "%s"', $field, $value)); - $this->collector->metaMonthIs($value, $field); - $this->operators->push(['type' => sprintf('%s_on_month', $field), 'value' => $value,]); + Log::debug(sprintf('Set date_is_after MONTH value "%s"', $value)); + $this->collector->objectMonthAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_month', $field), 'value' => $value,]); break; case 'day': - Log::debug(sprintf('Set %s_is_exact DAY value "%s"', $field, $value)); - $this->collector->metaDayIs($value, $field); - $this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]); + Log::debug(sprintf('Set date_is_after DAY value "%s"', $value)); + $this->collector->objectDayAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_day', $field), 'value' => $value,]); break; } } } + + /** + * @inheritDoc + * @codeCoverageIgnore + */ + public function searchTime(): float + { + return microtime(true) - $this->startTime; + } + + /** + * @inheritDoc + */ + public function searchTransactions(): LengthAwarePaginator + { + if (empty($this->getWords()) && empty($this->getOperators())) { + return new LengthAwarePaginator([], 0, 5, 1); + } + + return $this->collector->getPaginatedGroups(); + } + + /** + * @return array + */ + public function getWords(): array + { + return $this->words; + } + + /** + * @param Carbon $date + */ + public function setDate(Carbon $date): void + { + $this->date = $date; + } + + /** + * @inheritDoc + * @codeCoverageIgnore + */ + public function setPage(int $page): void + { + $this->page = $page; + $this->collector->setPage($this->page); + } + + /** + * @inheritDoc + * @codeCoverageIgnore + */ + public function setUser(User $user): void + { + $this->accountRepository->setUser($user); + $this->billRepository->setUser($user); + $this->categoryRepository->setUser($user); + $this->budgetRepository->setUser($user); + $this->tagRepository->setUser($user); + $this->collector = app(GroupCollectorInterface::class); + $this->collector->setUser($user); + $this->collector->withAccountInformation()->withCategoryInformation()->withBudgetInformation(); + + $this->setLimit((int) app('preferences')->getForUser($user, 'listPageSize', 50)->data); + + } + + /** + * @param int $limit + */ + public function setLimit(int $limit): void + { + $this->limit = $limit; + $this->collector->setLimit($this->limit); + } } diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 88c13ab849..baf71b7cc2 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -43,53 +43,6 @@ use Str; class Steam { - /** - * Returns the previous URL but refuses to send you to specific URLs. - * - * - outside domain - * - to JS files, API or JSON routes - * - * Uses the session's previousUrl() function as inspired by GitHub user @z1r0- - * - * session()->previousUrl() uses getSafeUrl() so we can safely return it: - * - * @return string - */ - public function getSafePreviousUrl(): string - { - //Log::debug(sprintf('getSafePreviousUrl: "%s"', session()->previousUrl())); - return session()->previousUrl() ?? route('index'); - } - - /** - * Make sure URL is safe. - * - * @param string $unknownUrl - * @param string $safeUrl - * - * @return string - */ - public function getSafeUrl(string $unknownUrl, string $safeUrl): string - { - //Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl)); - $returnUrl = $safeUrl; - $unknownHost = parse_url($unknownUrl, PHP_URL_HOST); - $safeHost = parse_url($safeUrl, PHP_URL_HOST); - - if (null !== $unknownHost && $unknownHost === $safeHost) { - $returnUrl = $unknownUrl; - } - - // URL must not lead to weird pages - $forbiddenWords = ['jscript', 'json', 'debug', 'serviceworker', 'offline', 'delete', '/login', '/attachments/view']; - if (Str::contains($returnUrl, $forbiddenWords)) { - $returnUrl = $safeUrl; - } - - return $returnUrl; - } - - /** * @param Account $account * @param Carbon $date @@ -391,6 +344,65 @@ class Steam return $return; } + /** + * @param string $string + * + * @return string + */ + public function filterSpaces(string $string): string + { + $search = [ + "\u{0001}", // start of heading + "\u{0002}", // start of text + "\u{0003}", // end of text + "\u{0004}", // end of transmission + "\u{0005}", // enquiry + "\u{0006}", // ACK + "\u{0007}", // BEL + "\u{0008}", // backspace + "\u{000E}", // shift out + "\u{000F}", // shift in + "\u{0010}", // data link escape + "\u{0011}", // DC1 + "\u{0012}", // DC2 + "\u{0013}", // DC3 + "\u{0014}", // DC4 + "\u{0015}", // NAK + "\u{0016}", // SYN + "\u{0017}", // ETB + "\u{0018}", // CAN + "\u{0019}", // EM + "\u{001A}", // SUB + "\u{001B}", // escape + "\u{001C}", // file separator + "\u{001D}", // group separator + "\u{001E}", // record separator + "\u{001F}", // unit separator + "\u{007F}", // DEL + "\u{00A0}", // non-breaking space + "\u{1680}", // ogham space mark + "\u{180E}", // mongolian vowel separator + "\u{2000}", // en quad + "\u{2001}", // em quad + "\u{2002}", // en space + "\u{2003}", // em space + "\u{2004}", // three-per-em space + "\u{2005}", // four-per-em space + "\u{2006}", // six-per-em space + "\u{2007}", // figure space + "\u{2008}", // punctuation space + "\u{2009}", // thin space + "\u{200A}", // hair space + "\u{200B}", // zero width space + "\u{202F}", // narrow no-break space + "\u{3000}", // ideographic space + "\u{FEFF}", // zero width no -break space + "\x20", // plain old normal space + ]; + + return str_replace($search, '', $string); + } + /** * @param array $accounts * @@ -463,6 +475,52 @@ class Steam ]; } + /** + * Returns the previous URL but refuses to send you to specific URLs. + * + * - outside domain + * - to JS files, API or JSON routes + * + * Uses the session's previousUrl() function as inspired by GitHub user @z1r0- + * + * session()->previousUrl() uses getSafeUrl() so we can safely return it: + * + * @return string + */ + public function getSafePreviousUrl(): string + { + //Log::debug(sprintf('getSafePreviousUrl: "%s"', session()->previousUrl())); + return session()->previousUrl() ?? route('index'); + } + + /** + * Make sure URL is safe. + * + * @param string $unknownUrl + * @param string $safeUrl + * + * @return string + */ + public function getSafeUrl(string $unknownUrl, string $safeUrl): string + { + //Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl)); + $returnUrl = $safeUrl; + $unknownHost = parse_url($unknownUrl, PHP_URL_HOST); + $safeHost = parse_url($safeUrl, PHP_URL_HOST); + + if (null !== $unknownHost && $unknownHost === $safeHost) { + $returnUrl = $unknownUrl; + } + + // URL must not lead to weird pages + $forbiddenWords = ['jscript', 'json', 'debug', 'serviceworker', 'offline', 'delete', '/login', '/attachments/view']; + if (Str::contains($returnUrl, $forbiddenWords)) { + $returnUrl = $safeUrl; + } + + return $returnUrl; + } + /** * @param string $amount * @@ -505,9 +563,9 @@ class Steam if ($mantis < 0) { $post += abs((int) $mantis); } - return number_format((float)$value, $post, '.', ''); + return number_format((float) $value, $post, '.', ''); } - return number_format((float)$value, 0, '.', ''); + return number_format((float) $value, 0, '.', ''); } /** @@ -573,63 +631,4 @@ class Steam return $amount; } - - /** - * @param string $string - * - * @return string - */ - public function filterSpaces(string $string): string - { - $search = [ - "\u{0001}", // start of heading - "\u{0002}", // start of text - "\u{0003}", // end of text - "\u{0004}", // end of transmission - "\u{0005}", // enquiry - "\u{0006}", // ACK - "\u{0007}", // BEL - "\u{0008}", // backspace - "\u{000E}", // shift out - "\u{000F}", // shift in - "\u{0010}", // data link escape - "\u{0011}", // DC1 - "\u{0012}", // DC2 - "\u{0013}", // DC3 - "\u{0014}", // DC4 - "\u{0015}", // NAK - "\u{0016}", // SYN - "\u{0017}", // ETB - "\u{0018}", // CAN - "\u{0019}", // EM - "\u{001A}", // SUB - "\u{001B}", // escape - "\u{001C}", // file separator - "\u{001D}", // group separator - "\u{001E}", // record separator - "\u{001F}", // unit separator - "\u{007F}", // DEL - "\u{00A0}", // non-breaking space - "\u{1680}", // ogham space mark - "\u{180E}", // mongolian vowel separator - "\u{2000}", // en quad - "\u{2001}", // em quad - "\u{2002}", // en space - "\u{2003}", // em space - "\u{2004}", // three-per-em space - "\u{2005}", // four-per-em space - "\u{2006}", // six-per-em space - "\u{2007}", // figure space - "\u{2008}", // punctuation space - "\u{2009}", // thin space - "\u{200A}", // hair space - "\u{200B}", // zero width space - "\u{202F}", // narrow no-break space - "\u{3000}", // ideographic space - "\u{FEFF}", // zero width no -break space - "\x20", // plain old normal space - ]; - - return str_replace($search, '', $string); - } } diff --git a/app/Support/Twig/TransactionGroupTwig.php b/app/Support/Twig/TransactionGroupTwig.php index 31e9c558b1..2c0a38fbb4 100644 --- a/app/Support/Twig/TransactionGroupTwig.php +++ b/app/Support/Twig/TransactionGroupTwig.php @@ -96,7 +96,7 @@ class TransactionGroupTwig extends AbstractExtension $colored = false; } - $result = app('amount')->formatFlat($array['currency_symbol'], (int)$array['currency_decimal_places'], $amount, $colored); + $result = app('amount')->formatFlat($array['currency_symbol'], (int) $array['currency_decimal_places'], $amount, $colored); if ($type === TransactionType::TRANSFER) { $result = sprintf('%s', $result); } @@ -151,7 +151,7 @@ class TransactionGroupTwig extends AbstractExtension if ($type === TransactionType::TRANSFER) { $colored = false; } - $result = app('amount')->formatFlat($array['foreign_currency_symbol'], (int)$array['foreign_currency_decimal_places'], $amount, $colored); + $result = app('amount')->formatFlat($array['foreign_currency_symbol'], (int) $array['foreign_currency_decimal_places'], $amount, $colored); if ($type === TransactionType::TRANSFER) { $result = sprintf('%s', $result); } @@ -203,7 +203,7 @@ class TransactionGroupTwig extends AbstractExtension if ($type === TransactionType::TRANSFER) { $colored = false; } - $result = app('amount')->formatFlat($currency->symbol, (int)$currency->decimal_places, $amount, $colored); + $result = app('amount')->formatFlat($currency->symbol, (int) $currency->decimal_places, $amount, $colored); if ($type === TransactionType::TRANSFER) { $result = sprintf('%s', $result); } @@ -246,7 +246,7 @@ class TransactionGroupTwig extends AbstractExtension if ($type === TransactionType::TRANSFER) { $colored = false; } - $result = app('amount')->formatFlat($currency->symbol, (int)$currency->decimal_places, $amount, $colored); + $result = app('amount')->formatFlat($currency->symbol, (int) $currency->decimal_places, $amount, $colored); if ($type === TransactionType::TRANSFER) { $result = sprintf('%s', $result); }