Code removal. The code removed from these classes must move to respective services.

This commit is contained in:
James Cole 2018-02-22 20:07:14 +01:00
parent 4e923057ae
commit b627d42160
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
16 changed files with 431 additions and 665 deletions

View File

@ -25,6 +25,7 @@ namespace FireflyIII\Factory;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Services\Internal\Support\BillServiceTrait;
use FireflyIII\User;
/**
@ -32,6 +33,7 @@ use FireflyIII\User;
*/
class BillFactory
{
use BillServiceTrait;
/** @var BillRepositoryInterface */
private $repository;
/** @var User */
@ -86,4 +88,37 @@ class BillFactory
}
/**
* @param array $data
*
* @return Bill|null
*/
public function store(array $data): ?Bill
{
$matchArray = explode(',', $data['match']);
$matchArray = array_unique($matchArray);
$match = join(',', $matchArray);
/** @var Bill $bill */
$bill = Bill::create(
[
'name' => $data['name'],
'match' => $match,
'amount_min' => $data['amount_min'],
'user_id' => $this->user->id,
'amount_max' => $data['amount_max'],
'date' => $data['date'],
'repeat_freq' => $data['repeat_freq'],
'skip' => $data['skip'],
'automatch' => $data['automatch'],
'active' => $data['active'],
]
);
// update note:
if (isset($data['notes'])) {
$this->updateNote($bill, $data['notes']);
}
}
}

View File

@ -61,61 +61,6 @@ class StoredJournalEventHandler
$this->ruleGroupRepository = $ruleGroupRepository;
}
/**
* This method connects a new transfer to a piggy bank.
*
* @param StoredTransactionJournal $event
*
* @return bool
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function connectToPiggyBank(StoredTransactionJournal $event): bool
{
$journal = $event->journal;
$piggyBankId = $event->piggyBankId;
$piggyBank = $this->repository->find($piggyBankId);
// is a transfer?
if (!$this->journalRepository->isTransfer($journal)) {
Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id));
return true;
}
// piggy exists?
if (null === $piggyBank) {
Log::error(sprintf('There is no piggy bank with ID #%d', $piggyBankId));
return true;
}
// repetition exists?
$repetition = $this->repository->getRepetition($piggyBank, $journal->date);
if (null === $repetition->id) {
Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d')));
return true;
}
// get the amount
$amount = $this->repository->getExactAmount($piggyBank, $repetition, $journal);
if (0 === bccomp($amount, '0')) {
Log::debug('Amount is zero, will not create event.');
return true;
}
// update amount
$this->repository->addAmountToRepetition($repetition, $amount);
$event = $this->repository->createEventWithJournal($piggyBank, $amount, $journal);
Log::debug(sprintf('Created piggy bank event #%d', $event->id));
return true;
}
/**
* This method grabs all the users rules and processes them.
*

View File

@ -31,6 +31,7 @@ use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Services\Internal\Update\JournalUpdateService;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Log;
@ -137,30 +138,35 @@ class BulkController extends Controller
*/
public function update(BulkEditJournalRequest $request, JournalRepositoryInterface $repository)
{
/** @var JournalUpdateService $service */
$service = app(JournalUpdateService::class);
$journalIds = $request->get('journals');
$ignoreCategory = intval($request->get('ignore_category')) === 1;
$ignoreBudget = intval($request->get('ignore_budget')) === 1;
$ignoreTags = intval($request->get('ignore_tags')) === 1;
$count = 0;
if (is_array($journalIds)) {
foreach ($journalIds as $journalId) {
$journal = $repository->find(intval($journalId));
if (!is_null($journal)) {
// TODO need to move this to update service.
$count++;
Log::debug(sprintf('Found journal #%d', $journal->id));
// update category if not told to ignore
if ($ignoreCategory === false) {
Log::debug(sprintf('Set category to %s', $request->string('category')));
$repository->updateCategory($journal, $request->string('category'));
$service->updateCategory($journal, $request->string('category'));
}
// update budget if not told to ignore (and is withdrawal)
if ($ignoreBudget === false) {
Log::debug(sprintf('Set budget to %d', $request->integer('budget_id')));
$repository->updateBudget($journal, $request->integer('budget_id'));
$service->updateBudget($journal, $request->integer('budget_id'));
}
if ($ignoreTags === false) {
Log::debug(sprintf('Set tags to %s', $request->string('budget_id')));
$repository->updateTags($journal, explode(',', $request->string('tags')));
$service->updateTags($journal, explode(',', $request->string('tags')));
}
// update tags if not told to ignore (and is withdrawal)
}

View File

@ -22,7 +22,8 @@ declare(strict_types=1);
namespace FireflyIII\Http\Requests;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Rules\UniqueIban;
/**
* Class AccountFormRequest.
@ -67,25 +68,14 @@ class AccountFormRequest extends Request
*/
public function rules()
{
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$accountRoles = join(',', config('firefly.accountRoles'));
$types = join(',', array_keys(config('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = join(',', array_keys(config('firefly.ccTypes')));
$nameRule = 'required|min:1|uniqueAccountForUser';
$idRule = '';
if (null !== $repository->find(intval($this->get('id')))->id) {
$idRule = 'belongsToUser:accounts';
$nameRule = 'required|min:1|uniqueAccountForUser:' . intval($this->get('id'));
}
return [
'id' => $idRule,
'name' => $nameRule,
$rules = [
'name' => 'required|min:1|uniqueAccountForUser',
'openingBalance' => 'numeric|required_with:openingBalanceDate|nullable',
'openingBalanceDate' => 'date|required_with:openingBalance|nullable',
'iban' => 'iban|nullable',
'iban' => ['iban', 'nullable', new UniqueIban(null)],
'BIC' => 'bic|nullable',
'virtualBalance' => 'numeric|nullable',
'currency_id' => 'exists:transaction_currencies,id',
@ -98,5 +88,16 @@ class AccountFormRequest extends Request
'amount_currency_id_virtualBalance' => 'exists:transaction_currencies,id',
'what' => 'in:' . $types,
];
/** @var Account $account */
$account = $this->route()->parameter('account');
if (!is_null($account)) {
// add rules:
$rules['id'] = 'belongsToUser:accounts';
$rules['name'] = 'required|min:1|uniqueAccountForUser:' . intval($this->get('id'));
$rules['iban'] = ['iban', 'nullable', new UniqueIban($account)];
}
return $rules;
}
}

View File

@ -77,7 +77,6 @@ class EventServiceProvider extends ServiceProvider
// is a Transaction Journal related event.
'FireflyIII\Events\StoredTransactionJournal' => [
'FireflyIII\Handlers\Events\StoredJournalEventHandler@scanBills',
'FireflyIII\Handlers\Events\StoredJournalEventHandler@connectToPiggyBank',
'FireflyIII\Handlers\Events\StoredJournalEventHandler@processRules',
],
// is a Transaction Journal related event.

View File

@ -23,42 +23,29 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Account;
use Carbon\Carbon;
use DB;
use Exception;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Category;
use FireflyIII\Models\Note;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
use FireflyIII\Services\Internal\Update\AccountUpdateService;
use FireflyIII\Services\Internal\Update\JournalUpdateService;
use FireflyIII\User;
use Log;
/**
* Class AccountRepository.
*/
class AccountRepository implements AccountRepositoryInterface
{
use FindAccountsTrait;
/** @var User */
private $user;
/** @var array */
private $validAssetFields = ['accountRole', 'accountNumber', 'currency_id', 'BIC'];
use FindAccountsTrait;
/** @var array */
private $validCCFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber', 'currency_id', 'BIC'];
/** @var array */
private $validFields = ['accountNumber', 'currency_id', 'BIC'];
/**
* Moved here from account CRUD.
*
* @param array $types
*
* @return int
@ -239,6 +226,8 @@ class AccountRepository implements AccountRepositoryInterface
* @param array $data
*
* @return Account
* @throws FireflyException
* @throws Exception
*/
public function store(array $data): Account
{
@ -254,6 +243,8 @@ class AccountRepository implements AccountRepositoryInterface
* @param Account $account
* @param array $data
*
* @throws FireflyException
* @throws Exception
* @return Account
*/
public function update(Account $account, array $data): Account
@ -270,90 +261,16 @@ class AccountRepository implements AccountRepositoryInterface
* @param array $data
*
* @return TransactionJournal
* @throws FireflyException
* @throws Exception
*/
public function updateReconciliation(TransactionJournal $journal, array $data): TransactionJournal
{
// update journal
// update actual journal:
$data['amount'] = strval($data['amount']);
// unlink all categories, recreate them:
$journal->categories()->detach();
$this->storeCategoryWithJournal($journal, strval($data['category']));
// update amounts
/** @var Transaction $transaction */
foreach ($journal->transactions as $transaction) {
$transaction->amount = bcmul($data['amount'], '-1');
if (AccountType::ASSET === $transaction->account->accountType->type) {
$transaction->amount = $data['amount'];
}
$transaction->save();
}
$journal->save();
// update tags:
if (isset($data['tags']) && is_array($data['tags'])) {
$this->updateTags($journal, $data['tags']);
}
/** @var JournalUpdateService $service */
$service = app(JournalUpdateService::class);
$journal = $service->update($journal, $data);
return $journal;
}
/**
* @param TransactionJournal $journal
* @param string $category
*/
protected function storeCategoryWithJournal(TransactionJournal $journal, string $category)
{
if (strlen($category) > 0) {
$category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $journal->user_id]);
$journal->categories()->save($category);
}
}
/**
* @param TransactionJournal $journal
* @param array $array
*
* @return bool
*/
protected function updateTags(TransactionJournal $journal, array $array): bool
{
// create tag repository
/** @var TagRepositoryInterface $tagRepository */
$tagRepository = app(TagRepositoryInterface::class);
// find or create all tags:
$tags = [];
$ids = [];
foreach ($array as $name) {
if (strlen(trim($name)) > 0) {
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
$tags[] = $tag;
$ids[] = $tag->id;
}
}
// delete all tags connected to journal not in this array:
if (count($ids) > 0) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete();
}
// if count is zero, delete them all:
if (0 === count($ids)) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete();
}
// connect each tag to journal (if not yet connected):
/** @var Tag $tag */
foreach ($tags as $tag) {
Log::debug(sprintf('Will try to connect tag #%d to journal #%d.', $tag->id, $journal->id));
$tagRepository->connect($journal, $tag);
}
return true;
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Account;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\User;
@ -44,6 +45,7 @@ trait FindAccountsTrait
*/
public function find(int $accountId): Account
{
/** @var Account $account */
$account = $this->user->accounts()->find($accountId);
if (null === $account) {
return new Account;
@ -56,6 +58,7 @@ trait FindAccountsTrait
* @param string $number
* @param array $types
*
* @deprecated
* @return Account
*/
public function findByAccountNumber(string $number, array $types): Account
@ -83,6 +86,7 @@ trait FindAccountsTrait
* @param string $iban
* @param array $types
*
* @deprecated
* @return Account
*/
public function findByIban(string $iban, array $types): Account
@ -213,15 +217,15 @@ trait FindAccountsTrait
* @return Account
*
* @throws FireflyException
* @throws \Exception
*/
public function getCashAccount(): Account
{
$type = AccountType::where('type', AccountType::CASH)->first();
$account = Account::firstOrCreateEncrypted(
['user_id' => $this->user->id, 'account_type_id' => $type->id, 'name' => 'Cash account']
);
$account->active = true;
$account->save();
$type = AccountType::where('type', AccountType::CASH)->first();
/** @var AccountFactory $factory */
$factory = app(AccountFactory::class);
$factory->setUser($this->user);
$account = $factory->findOrCreate('Cash account', $type->type);
return $account;
}
@ -232,6 +236,7 @@ trait FindAccountsTrait
* @return Account|null
*
* @throws FireflyException
* @throws \Exception
*/
public function getReconciliation(Account $account): ?Account
{
@ -247,23 +252,12 @@ trait FindAccountsTrait
return $account;
}
}
// assume nothing was found. create it!
$data = [
'accountType' => 'reconcile',
'name' => $name,
'iban' => null,
'virtualBalance' => '0',
'active' => true,
];
$account = $this->storeAccount($data);
/** @var AccountFactory $factory */
$factory = app(AccountFactory::class);
$factory->setUser($account->user);
$account = $factory->findOrCreate($name, $type->type);
return $account;
}
/**
* @param array $data
*
* @return Account
*/
abstract protected function storeAccount(array $data): Account;
}

View File

@ -24,18 +24,19 @@ namespace FireflyIII\Repositories\Bill;
use Carbon\Carbon;
use DB;
use FireflyIII\Factory\BillFactory;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Note;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Services\Internal\Destroy\BillDestroyService;
use FireflyIII\Services\Internal\Update\BillUpdateService;
use FireflyIII\Support\CacheProperties;
use FireflyIII\User;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Log;
use Navigation;
/**
* Class BillRepository.
@ -54,7 +55,9 @@ class BillRepository implements BillRepositoryInterface
*/
public function destroy(Bill $bill): bool
{
$bill->delete();
/** @var BillDestroyService $service */
$service = app(BillDestroyService::class);
$service->destroy($bill);
return true;
}
@ -103,12 +106,8 @@ class BillRepository implements BillRepositoryInterface
/** @var Collection $set */
$set = $this->user->bills()
->where('active', 1)
->get(
[
'bills.*',
DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount'),
]
)->sortBy('name');
->sortBy('name')
->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount'),]);
return $set;
}
@ -221,6 +220,7 @@ class BillRepository implements BillRepositoryInterface
* @param Carbon $end
*
* @return string
* @throws \FireflyIII\Exceptions\FireflyException
*/
public function getBillsUnpaidInRange(Carbon $start, Carbon $end): string
{
@ -302,6 +302,7 @@ class BillRepository implements BillRepositoryInterface
* @param Carbon $end
*
* @return Collection
* @throws \FireflyIII\Exceptions\FireflyException
*/
public function getPayDatesInRange(Bill $bill, Carbon $start, Carbon $end): Collection
{
@ -418,11 +419,11 @@ class BillRepository implements BillRepositoryInterface
while ($start < $date) {
Log::debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d'), $date->format('Y-m-d')));
$start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
$start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
Log::debug('Start is now ' . $start->format('Y-m-d'));
}
$end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
Log::debug('nextDateMatch: Final start is ' . $start->format('Y-m-d'));
Log::debug('nextDateMatch: Matching end is ' . $end->format('Y-m-d'));
@ -455,11 +456,11 @@ class BillRepository implements BillRepositoryInterface
while ($start < $date) {
Log::debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d'), $date->format('Y-m-d')));
$start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
$start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
Log::debug('Start is now ' . $start->format('Y-m-d'));
}
$end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
// see if the bill was paid in this period.
$journalCount = $bill->transactionJournals()->before($end)->after($start)->count();
@ -468,7 +469,7 @@ class BillRepository implements BillRepositoryInterface
// this period had in fact a bill. The new start is the current end, and we create a new end.
Log::debug(sprintf('Journal count is %d, so start becomes %s', $journalCount, $end->format('Y-m-d')));
$start = clone $end;
$end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
}
Log::debug('nextExpectedMatch: Final start is ' . $start->format('Y-m-d'));
Log::debug('nextExpectedMatch: Matching end is ' . $end->format('Y-m-d'));
@ -479,9 +480,12 @@ class BillRepository implements BillRepositoryInterface
}
/**
* TODO move to a service.
*
* @param Bill $bill
* @param TransactionJournal $journal
*
* @deprecated
* @return bool
*/
public function scan(Bill $bill, TransactionJournal $journal): bool
@ -533,30 +537,11 @@ class BillRepository implements BillRepositoryInterface
*/
public function store(array $data): Bill
{
$matchArray = explode(',', $data['match']);
$matchArray = array_unique($matchArray);
$match = join(',', $matchArray);
/** @var BillFactory $factory */
$factory = app(BillFactory::class);
$factory->setUser($this->user);
$bill = $factory->store($data);
/** @var Bill $bill */
$bill = Bill::create(
[
'name' => $data['name'],
'match' => $match,
'amount_min' => $data['amount_min'],
'user_id' => $this->user->id,
'amount_max' => $data['amount_max'],
'date' => $data['date'],
'repeat_freq' => $data['repeat_freq'],
'skip' => $data['skip'],
'automatch' => $data['automatch'],
'active' => $data['active'],
]
);
// update note:
if (isset($data['notes'])) {
$this->updateNote($bill, $data['notes']);
}
return $bill;
}
@ -569,27 +554,10 @@ class BillRepository implements BillRepositoryInterface
*/
public function update(Bill $bill, array $data): Bill
{
$matchArray = explode(',', $data['match']);
$matchArray = array_unique($matchArray);
$match = join(',', $matchArray);
/** @var BillUpdateService $service */
$service = app(BillUpdateService::class);
$bill->name = $data['name'];
$bill->match = $match;
$bill->amount_min = $data['amount_min'];
$bill->amount_max = $data['amount_max'];
$bill->date = $data['date'];
$bill->repeat_freq = $data['repeat_freq'];
$bill->skip = $data['skip'];
$bill->automatch = $data['automatch'];
$bill->active = $data['active'];
$bill->save();
// update note:
if (isset($data['notes']) && null !== $data['notes']) {
$this->updateNote($bill, strval($data['notes']));
}
return $bill;
return $service->update($bill, $data);
}
/**
@ -629,31 +597,4 @@ class BillRepository implements BillRepositoryInterface
return $wordMatch;
}
/**
* @param Bill $bill
* @param string $note
*
* @return bool
*/
protected function updateNote(Bill $bill, string $note): bool
{
if (0 === strlen($note)) {
$dbNote = $bill->notes()->first();
if (null !== $dbNote) {
$dbNote->delete();
}
return true;
}
$dbNote = $bill->notes()->first();
if (null === $dbNote) {
$dbNote = new Note();
$dbNote->noteable()->associate($bill);
}
$dbNote->text = trim($note);
$dbNote->save();
return true;
}
}

View File

@ -22,16 +22,16 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Journal;
use Carbon\Carbon;
use DB;
use Exception;
use FireflyIII\Factory\TransactionJournalFactory;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Note;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
use FireflyIII\Services\Internal\Update\JournalUpdateService;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
@ -109,7 +109,9 @@ class JournalRepository implements JournalRepositoryInterface
*/
public function destroy(TransactionJournal $journal): bool
{
$journal->delete();
/** @var JournalDestroyService $service */
$service = app(JournalDestroyService::class);
$service->destroy($journal);
return true;
}
@ -229,31 +231,6 @@ class JournalRepository implements JournalRepositoryInterface
return $set;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function isTransfer(TransactionJournal $journal): bool
{
return TransactionType::TRANSFER === $journal->transactionType->type;
}
/**
* Mark journal as completed and return it.
*
* @param TransactionJournal $journal
*
* @return TransactionJournal
*/
public function markCompleted(TransactionJournal $journal): TransactionJournal
{
$journal->completed = true;
$journal->save();
return $journal;
}
/**
* @param Transaction $transaction
*
@ -311,109 +288,11 @@ class JournalRepository implements JournalRepositoryInterface
*/
public function store(array $data): TransactionJournal
{
// find transaction type.
/** @var TransactionType $transactionType */
$transactionType = TransactionType::where('type', ucfirst($data['what']))->first();
$accounts = $this->storeAccounts($this->user, $transactionType, $data);
$data = $this->verifyNativeAmount($data, $accounts);
$amount = strval($data['amount']);
$dateString = $data['date'];
if ($data['date'] instanceof Carbon) {
$dateString = $data['date']->format('Y-m-d 00:00:00');
}
$journal = new TransactionJournal(
[
'user_id' => $this->user->id,
'transaction_type_id' => $transactionType->id,
'transaction_currency_id' => $data['currency_id'], // no longer used.
'description' => $data['description'],
'completed' => 0,
'date' => $dateString,
]
);
$journal->save();
/** @var TransactionJournalFactory $factory */
$factory = app(TransactionJournalFactory::class);
$factory->setUser($this->user);
// store stuff:
$this->storeCategoryWithJournal($journal, strval($data['category']));
$this->storeBudgetWithJournal($journal, $data['budget_id']);
// store two transactions:
$one = [
'journal' => $journal,
'account' => $accounts['source'],
'amount' => bcmul($amount, '-1'),
'transaction_currency_id' => $data['currency_id'],
'foreign_amount' => null === $data['foreign_amount'] ? null : bcmul(strval($data['foreign_amount']), '-1'),
'foreign_currency_id' => $data['foreign_currency_id'],
'description' => null,
'category' => null,
'budget' => null,
'identifier' => 0,
];
$this->storeTransaction($one);
$two = [
'journal' => $journal,
'account' => $accounts['destination'],
'amount' => $amount,
'transaction_currency_id' => $data['currency_id'],
'foreign_amount' => $data['foreign_amount'],
'foreign_currency_id' => $data['foreign_currency_id'],
'description' => null,
'category' => null,
'budget' => null,
'identifier' => 0,
];
$this->storeTransaction($two);
// store tags
if (isset($data['tags']) && is_array($data['tags'])) {
$this->saveTags($journal, $data['tags']);
}
// update note:
if (isset($data['notes'])) {
$this->updateNote($journal, $data['notes']);
}
foreach ($data as $key => $value) {
if (in_array($key, $this->validMetaFields)) {
$journal->setMeta($key, $value);
continue;
}
Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id));
}
$journal->completed = 1;
$journal->save();
return $journal;
}
/**
* Store a new transaction journal based on the values given.
*
* @param array $values
*
* @return TransactionJournal
*/
public function storeBasic(array $values): TransactionJournal
{
return TransactionJournal::create($values);
}
/**
* Store a new transaction based on the values given.
*
* @param array $values
*
* @return Transaction
*/
public function storeBasicTransaction(array $values): Transaction
{
return Transaction::create($values);
return $factory->create($data);
}
/**
@ -423,201 +302,14 @@ class JournalRepository implements JournalRepositoryInterface
* @return TransactionJournal
*
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \FireflyIII\Exceptions\FireflyException
* @throws Exception
*/
public function update(TransactionJournal $journal, array $data): TransactionJournal
{
// update actual journal:
$journal->description = $data['description'];
$journal->date = $data['date'];
$accounts = $this->storeAccounts($this->user, $journal->transactionType, $data);
$data = $this->verifyNativeAmount($data, $accounts);
$data['amount'] = strval($data['amount']);
$data['foreign_amount'] = null === $data['foreign_amount'] ? null : strval($data['foreign_amount']);
/** @var JournalUpdateService $service */
$service = app(JournalUpdateService::class);
// unlink all categories, recreate them:
$journal->categories()->detach();
$journal->budgets()->detach();
$this->storeCategoryWithJournal($journal, strval($data['category']));
$this->storeBudgetWithJournal($journal, $data['budget_id']);
// negative because source loses money.
$this->updateSourceTransaction($journal, $accounts['source'], $data);
// positive because destination gets money.
$this->updateDestinationTransaction($journal, $accounts['destination'], $data);
$journal->save();
// update tags:
if (isset($data['tags']) && is_array($data['tags'])) {
$this->updateTags($journal, $data['tags']);
}
// update note:
if (isset($data['notes']) && null !== $data['notes']) {
$this->updateNote($journal, strval($data['notes']));
}
// update meta fields:
$result = $journal->save();
if ($result) {
foreach ($data as $key => $value) {
if (in_array($key, $this->validMetaFields)) {
$journal->setMeta($key, $value);
continue;
}
Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id));
}
return $journal;
}
return $journal;
return $service->update($journal, $data);
}
/**
* @param TransactionJournal $journal
* @param int $budgetId
*
* @return TransactionJournal
*/
public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal
{
if ($budgetId === 0) {
$journal->budgets()->detach();
$journal->save();
return $journal;
}
$this->storeBudgetWithJournal($journal, $budgetId);
return $journal;
}
/**
* @param TransactionJournal $journal
* @param string $category
*
* @return TransactionJournal
*/
public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal
{
Log::debug(sprintf('In updateCategory("%s")', $category));
$journal->categories()->detach();
if (strlen($category) === 0) {
return $journal;
}
$this->storeCategoryWithJournal($journal, $category);
return $journal;
}
/**
* Same as above but for transaction journal with multiple transactions.
*
* @param TransactionJournal $journal
* @param array $data
*
* @return TransactionJournal
*/
public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal
{
// update actual journal:
$journal->description = $data['journal_description'];
$journal->date = $data['date'];
$journal->save();
Log::debug(sprintf('Updated split journal #%d', $journal->id));
// unlink all categories:
$journal->categories()->detach();
$journal->budgets()->detach();
// update note:
if (isset($data['notes']) && null !== $data['notes']) {
$this->updateNote($journal, strval($data['notes']));
}
// update meta fields:
$result = $journal->save();
if ($result) {
foreach ($data as $key => $value) {
if (in_array($key, $this->validMetaFields)) {
$journal->setMeta($key, $value);
continue;
}
Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id));
}
}
// update tags:
if (isset($data['tags']) && is_array($data['tags'])) {
$this->updateTags($journal, $data['tags']);
}
// delete original transactions, and recreate them.
$journal->transactions()->delete();
// store each transaction.
$identifier = 0;
Log::debug(sprintf('Count %d transactions in updateSplitJournal()', count($data['transactions'])));
foreach ($data['transactions'] as $transaction) {
Log::debug(sprintf('Split journal update split transaction %d', $identifier));
$transaction = $this->appendTransactionData($transaction, $data);
$this->storeSplitTransaction($journal, $transaction, $identifier);
++$identifier;
}
$journal->save();
return $journal;
}
/**
* Update tags.
*
* @param TransactionJournal $journal
* @param array $array
*
* @return bool
*/
public function updateTags(TransactionJournal $journal, array $array): bool
{
// create tag repository
/** @var TagRepositoryInterface $tagRepository */
$tagRepository = app(TagRepositoryInterface::class);
// find or create all tags:
$tags = [];
$ids = [];
foreach ($array as $name) {
if (strlen(trim($name)) > 0) {
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
$tags[] = $tag;
$ids[] = $tag->id;
}
}
// delete all tags connected to journal not in this array:
if (count($ids) > 0) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete();
}
// if count is zero, delete them all:
if (0 === count($ids)) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete();
}
// connect each tag to journal (if not yet connected):
/** @var Tag $tag */
foreach ($tags as $tag) {
Log::debug(sprintf('Will try to connect tag #%d to journal #%d.', $tag->id, $journal->id));
$tagRepository->connect($journal, $tag);
}
return true;
}
}

View File

@ -118,22 +118,6 @@ interface JournalRepositoryInterface
*/
public function getTransactionsById(array $transactionIds): Collection;
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function isTransfer(TransactionJournal $journal): bool;
/**
* Mark journal as completed and return it.
*
* @param TransactionJournal $journal
*
* @return TransactionJournal
*/
public function markCompleted(TransactionJournal $journal): TransactionJournal;
/**
* @param Transaction $transaction
*
@ -161,24 +145,6 @@ interface JournalRepositoryInterface
*/
public function store(array $data): TransactionJournal;
/**
* Store a new transaction journal based on the values given.
*
* @param array $values
*
* @return TransactionJournal
*/
public function storeBasic(array $values): TransactionJournal;
/**
* Store a new transaction based on the values given.
*
* @param array $values
*
* @return Transaction
*/
public function storeBasicTransaction(array $values): Transaction;
/**
* @param TransactionJournal $journal
* @param array $data
@ -186,36 +152,4 @@ interface JournalRepositoryInterface
* @return TransactionJournal
*/
public function update(TransactionJournal $journal, array $data): TransactionJournal;
/**
* @param TransactionJournal $journal
* @param int $budgetId
*
* @return TransactionJournal
*/
public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal;
/**
* @param TransactionJournal $journal
* @param string $category
*
* @return TransactionJournal
*/
public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal;
/**
* @param TransactionJournal $journal
* @param array $data
*
* @return TransactionJournal
*/
public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal;
/**
* @param TransactionJournal $journal
* @param array $tags
*
* @return bool
*/
public function updateTags(TransactionJournal $journal, array $tags): bool;
}

View File

@ -231,7 +231,7 @@ trait SupportJournalsTrait
protected function verifyNativeAmount(array $data, array $accounts): array
{
/** @var TransactionType $transactionType */
$transactionType = TransactionType::where('type', ucfirst($data['what']))->first();
$transactionType = TransactionType::where('type', ucfirst($data['type']))->first();
$submittedCurrencyId = $data['currency_id'];
$data['foreign_amount'] = null;
$data['foreign_currency_id'] = null;

89
app/Rules/UniqueIban.php Normal file
View File

@ -0,0 +1,89 @@
<?php
/**
* UniqueIban.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Rules;
use FireflyIII\Models\Account;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Collection;
/**
* Class UniqueIban
*/
class UniqueIban implements Rule
{
/** @var Account */
private $account;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct(?Account $account)
{
$this->account = $account;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return trans('validation.unique_iban_for_user');
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
*
* @return bool
*/
public function passes($attribute, $value)
{
if (!auth()->check()) {
return true; // @codeCoverageIgnore
}
$query = auth()->user()->accounts();
if (!is_null($this->account)) {
$query->where('accounts.id', '!=', $this->account->id);
}
/** @var Collection $accounts */
$accounts = $query->get();
/** @var Account $account */
foreach ($accounts as $account) {
if ($account->iban === $value) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,46 @@
<?php
/**
* BillDestroyService.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Internal\Destroy;
use Exception;
use FireflyIII\Models\Bill;
/**
* Class BillDestroyService
*/
class BillDestroyService
{
/**
* @param Bill $bill
*/
public function destroy(Bill $bill): void
{
try {
$bill->delete();
} catch (Exception $e) {
// don't care.
}
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* JournalDestroyService.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Internal\Destroy;
use FireflyIII\Models\TransactionJournal;
/**
* Class JournalDestroyService
*/
class JournalDestroyService
{
/**
* @param TransactionJournal $journal
*/
public function destroy(TransactionJournal $journal): void {
}
}

View File

@ -0,0 +1,62 @@
<?php
/**
* BillServiceTrait.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Internal\Support;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Note;
/**
* Trait BillServiceTrait
*
* @package FireflyIII\Services\Internal\Support
*/
trait BillServiceTrait
{
/**
* @param Bill $bill
* @param string $note
*
* @return bool
*/
public function updateNote(Bill $bill, string $note): bool
{
if (0 === strlen($note)) {
$dbNote = $bill->notes()->first();
if (null !== $dbNote) {
$dbNote->delete();
}
return true;
}
$dbNote = $bill->notes()->first();
if (null === $dbNote) {
$dbNote = new Note();
$dbNote->noteable()->associate($bill);
}
$dbNote->text = trim($note);
$dbNote->save();
return true;
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* BillUpdateService.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Internal\Update;
use FireflyIII\Models\Bill;
use FireflyIII\Services\Internal\Support\BillServiceTrait;
/**
* Class BillUpdateService
*/
class BillUpdateService
{
use BillServiceTrait;
/**
* @param Bill $bill
* @param array $data
*/
public function update(Bill $bill, array $data): Bill
{
$matchArray = explode(',', $data['match']);
$matchArray = array_unique($matchArray);
$match = join(',', $matchArray);
$bill->name = $data['name'];
$bill->match = $match;
$bill->amount_min = $data['amount_min'];
$bill->amount_max = $data['amount_max'];
$bill->date = $data['date'];
$bill->repeat_freq = $data['repeat_freq'];
$bill->skip = $data['skip'];
$bill->automatch = $data['automatch'];
$bill->active = $data['active'];
$bill->save();
// update note:
if (isset($data['notes']) && null !== $data['notes']) {
$this->updateNote($bill, strval($data['notes']));
}
return $bill;
}
}