mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
Improve mass controller and test controllers.
This commit is contained in:
@@ -124,6 +124,37 @@ class AutoCompleteController extends Controller
|
|||||||
return response()->json($return);
|
return response()->json($return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An auto-complete specifically for expense accounts, used when mass updating mostly.
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function expenseAccounts(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$search = $request->get('search');
|
||||||
|
/** @var AccountRepositoryInterface $repository */
|
||||||
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
|
|
||||||
|
// filter the account types:
|
||||||
|
$allowedAccountTypes = [AccountType::EXPENSE];
|
||||||
|
Log::debug('Now in accounts(). Filtering results.', $allowedAccountTypes);
|
||||||
|
|
||||||
|
$return = [];
|
||||||
|
$result = $repository->searchAccount((string)$search, $allowedAccountTypes);
|
||||||
|
|
||||||
|
/** @var Account $account */
|
||||||
|
foreach ($result as $account) {
|
||||||
|
$return[] = [
|
||||||
|
'id' => $account->id,
|
||||||
|
'name' => $account->name,
|
||||||
|
'type' => $account->accountType->type,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json($return);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches in the titles of all transaction journals.
|
* Searches in the titles of all transaction journals.
|
||||||
* The result is limited to the top 15 unique results.
|
* The result is limited to the top 15 unique results.
|
||||||
|
@@ -63,6 +63,8 @@ class BulkController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Edit a set of journals in bulk.
|
* Edit a set of journals in bulk.
|
||||||
*
|
*
|
||||||
|
* TODO user wont be able to tell if journal is part of split.
|
||||||
|
*
|
||||||
* @param Collection $journals
|
* @param Collection $journals
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
@@ -71,6 +73,8 @@ class BulkController extends Controller
|
|||||||
{
|
{
|
||||||
$subTitle = (string)trans('firefly.mass_bulk_journals');
|
$subTitle = (string)trans('firefly.mass_bulk_journals');
|
||||||
|
|
||||||
|
// make amounts positive.
|
||||||
|
|
||||||
// get list of budgets:
|
// get list of budgets:
|
||||||
/** @var BudgetRepositoryInterface $repository */
|
/** @var BudgetRepositoryInterface $repository */
|
||||||
$repository = app(BudgetRepositoryInterface::class);
|
$repository = app(BudgetRepositoryInterface::class);
|
||||||
|
@@ -25,23 +25,19 @@ namespace FireflyIII\Http\Controllers\Transaction;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
|
||||||
use FireflyIII\Helpers\Filter\TransactionViewFilter;
|
|
||||||
use FireflyIII\Helpers\Filter\TransferFilter;
|
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Http\Requests\MassDeleteJournalRequest;
|
use FireflyIII\Http\Requests\MassDeleteJournalRequest;
|
||||||
use FireflyIII\Http\Requests\MassEditJournalRequest;
|
use FireflyIII\Http\Requests\MassEditJournalRequest;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Transaction;
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
use FireflyIII\Transformers\TransactionTransformer;
|
use FireflyIII\Services\Internal\Update\JournalUpdateService;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Illuminate\View\View as IlluminateView;
|
use Illuminate\View\View as IlluminateView;
|
||||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
use InvalidArgumentException;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class MassController.
|
* Class MassController.
|
||||||
@@ -55,6 +51,7 @@ class MassController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* MassController constructor.
|
* MassController constructor.
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -65,7 +62,6 @@ class MassController extends Controller
|
|||||||
app('view')->share('title', (string)trans('firefly.transactions'));
|
app('view')->share('title', (string)trans('firefly.transactions'));
|
||||||
app('view')->share('mainTitleIcon', 'fa-repeat');
|
app('view')->share('mainTitleIcon', 'fa-repeat');
|
||||||
$this->repository = app(JournalRepositoryInterface::class);
|
$this->repository = app(JournalRepositoryInterface::class);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -74,11 +70,11 @@ class MassController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Mass delete transactions.
|
* Mass delete transactions.
|
||||||
*
|
*
|
||||||
* @param Collection $journals
|
* @param array $journals
|
||||||
*
|
*
|
||||||
* @return IlluminateView
|
* @return IlluminateView
|
||||||
*/
|
*/
|
||||||
public function delete(Collection $journals): IlluminateView
|
public function delete(array $journals): IlluminateView
|
||||||
{
|
{
|
||||||
$subTitle = (string)trans('firefly.mass_delete_journals');
|
$subTitle = (string)trans('firefly.mass_delete_journals');
|
||||||
|
|
||||||
@@ -103,10 +99,11 @@ class MassController extends Controller
|
|||||||
if (is_array($ids)) {
|
if (is_array($ids)) {
|
||||||
/** @var string $journalId */
|
/** @var string $journalId */
|
||||||
foreach ($ids as $journalId) {
|
foreach ($ids as $journalId) {
|
||||||
|
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
$journal = $this->repository->findNull((int)$journalId);
|
$journal = $this->repository->findNull((int)$journalId);
|
||||||
if (null !== $journal && (int)$journalId === $journal->id) {
|
if (null !== $journal && (int)$journalId === $journal->id) {
|
||||||
$this->repository->destroy($journal);
|
$this->repository->destroyJournal($journal);
|
||||||
++$count;
|
++$count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,137 +120,69 @@ class MassController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Mass edit of journals.
|
* Mass edit of journals.
|
||||||
*
|
*
|
||||||
* @param Collection $journals
|
* @param array $journals
|
||||||
*
|
*
|
||||||
* @return IlluminateView
|
* @return IlluminateView
|
||||||
*
|
|
||||||
* TODO rebuild this feature.
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
*/
|
||||||
public function edit(Collection $journals): IlluminateView
|
public function edit(array $journals): IlluminateView
|
||||||
{
|
{
|
||||||
throw new FireflyException(sprintf('The mass-editor is not available in v%s of Firefly III. Sorry about that. It will be back soon.', config('firefly.version')));
|
|
||||||
/** @var User $user */
|
|
||||||
$user = auth()->user();
|
|
||||||
$subTitle = (string)trans('firefly.mass_edit_journals');
|
$subTitle = (string)trans('firefly.mass_edit_journals');
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
|
||||||
|
// valid withdrawal sources:
|
||||||
|
$array = array_keys(config(sprintf('firefly.source_dests.%s', TransactionType::WITHDRAWAL)));
|
||||||
|
$withdrawalSources = $repository->getAccountsByType($array);
|
||||||
|
|
||||||
|
// valid deposit destinations:
|
||||||
|
$array = config(sprintf('firefly.source_dests.%s.%s', TransactionType::DEPOSIT, AccountType::REVENUE));
|
||||||
|
$depositDestinations = $repository->getAccountsByType($array);
|
||||||
|
|
||||||
/** @var BudgetRepositoryInterface $budgetRepository */
|
/** @var BudgetRepositoryInterface $budgetRepository */
|
||||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||||
$budgets = $budgetRepository->getBudgets();
|
$budgets = $budgetRepository->getBudgets();
|
||||||
|
|
||||||
|
// reverse amounts
|
||||||
|
foreach ($journals as $index => $journal) {
|
||||||
|
$journals[$index]['amount'] = app('steam')->positive($journal['amount']);
|
||||||
|
$journals[$index]['foreign_amount'] = null === $journal['foreign_amount'] ?
|
||||||
|
null : app('steam')->positive($journal['foreign_amount']);
|
||||||
|
}
|
||||||
|
|
||||||
$this->rememberPreviousUri('transactions.mass-edit.uri');
|
$this->rememberPreviousUri('transactions.mass-edit.uri');
|
||||||
|
|
||||||
/** @var TransactionTransformer $transformer */
|
return view('transactions.mass.edit', compact('journals', 'subTitle', 'withdrawalSources', 'depositDestinations', 'budgets'));
|
||||||
$transformer = app(TransactionTransformer::class);
|
|
||||||
$transformer->setParameters(new ParameterBag);
|
|
||||||
|
|
||||||
/** @var GroupCollectorInterface $collector */
|
|
||||||
$collector = app(GroupCollectorInterface::class);
|
|
||||||
$collector->setUser($user);
|
|
||||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
|
||||||
$collector->setJournals($journals);
|
|
||||||
$collector->addFilter(TransactionViewFilter::class);
|
|
||||||
$collector->addFilter(TransferFilter::class);
|
|
||||||
|
|
||||||
|
|
||||||
$collection = $collector->getTransactions();
|
|
||||||
$transactions = $collection->map(
|
|
||||||
function (Transaction $transaction) use ($transformer) {
|
|
||||||
$transformed = $transformer->transform($transaction);
|
|
||||||
// make sure amount is positive:
|
|
||||||
$transformed['amount'] = app('steam')->positive((string)$transformed['amount']);
|
|
||||||
$transformed['foreign_amount'] = app('steam')->positive((string)$transformed['foreign_amount']);
|
|
||||||
|
|
||||||
return $transformed;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return view('transactions.mass.edit', compact('transactions', 'subTitle', 'accounts', 'budgets'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mass update of journals.
|
* Mass update of journals.
|
||||||
*
|
*
|
||||||
* @param MassEditJournalRequest $request
|
* @param MassEditJournalRequest $request
|
||||||
* @param JournalRepositoryInterface $repository
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*
|
* @throws FireflyException
|
||||||
* @return mixed
|
|
||||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
|
||||||
*/
|
*/
|
||||||
public function update(MassEditJournalRequest $request, JournalRepositoryInterface $repository)
|
public function update(MassEditJournalRequest $request)
|
||||||
{
|
{
|
||||||
throw new FireflyException('Needs refactor');
|
|
||||||
$journalIds = $request->get('journals');
|
$journalIds = $request->get('journals');
|
||||||
$count = 0;
|
if (!is_array($journalIds)) {
|
||||||
if (is_array($journalIds)) {
|
// TODO something error.
|
||||||
foreach ($journalIds as $journalId) {
|
throw new FireflyException('This is not an array.'); // @codeCoverageIgnore
|
||||||
$journal = $repository->findNull((int)$journalId);
|
}
|
||||||
if (null !== $journal) {
|
$count = 0;
|
||||||
// get optional fields:
|
/** @var string $journalId */
|
||||||
$what = strtolower($this->repository->getTransactionType($journal));
|
foreach ($journalIds as $journalId) {
|
||||||
$sourceAccountId = $request->get('source_id')[$journal->id] ?? null;
|
$integer = (int)$journalId;
|
||||||
$currencyId = $request->get('transaction_currency_id')[$journal->id] ?? 1;
|
try {
|
||||||
$sourceAccountName = $request->get('source_name')[$journal->id] ?? null;
|
$this->updateJournal($integer, $request);
|
||||||
$destAccountId = $request->get('destination_id')[$journal->id] ?? null;
|
$count++;
|
||||||
$destAccountName = $request->get('destination_name')[$journal->id] ?? null;
|
} catch (FireflyException $e) { // @codeCoverageIgnore
|
||||||
$budgetId = (int)($request->get('budget_id')[$journal->id] ?? 0.0);
|
// do something with error.
|
||||||
$category = $request->get('category')[$journal->id];
|
//echo $e->getMessage();
|
||||||
$tags = $journal->tags->pluck('tag')->toArray();
|
//exit;
|
||||||
$amount = round($request->get('amount')[$journal->id], 12);
|
|
||||||
$foreignAmount = isset($request->get('foreign_amount')[$journal->id]) ? round($request->get('foreign_amount')[$journal->id], 12) : null;
|
|
||||||
$foreignCurrencyId = isset($request->get('foreign_currency_id')[$journal->id]) ?
|
|
||||||
(int)$request->get('foreign_currency_id')[$journal->id] : null;
|
|
||||||
// build data array
|
|
||||||
$data = [
|
|
||||||
'id' => $journal->id,
|
|
||||||
'what' => $what,
|
|
||||||
'description' => $request->get('description')[$journal->id],
|
|
||||||
'date' => new Carbon($request->get('date')[$journal->id]),
|
|
||||||
'bill_id' => null,
|
|
||||||
'bill_name' => null,
|
|
||||||
'notes' => $repository->getNoteText($journal),
|
|
||||||
'transactions' => [[
|
|
||||||
|
|
||||||
'category_id' => null,
|
|
||||||
'category_name' => $category,
|
|
||||||
'budget_id' => $budgetId,
|
|
||||||
'budget_name' => null,
|
|
||||||
'source_id' => (int)$sourceAccountId,
|
|
||||||
'source_name' => $sourceAccountName,
|
|
||||||
'destination_id' => (int)$destAccountId,
|
|
||||||
'destination_name' => $destAccountName,
|
|
||||||
'amount' => $amount,
|
|
||||||
'identifier' => 0,
|
|
||||||
'reconciled' => false,
|
|
||||||
'currency_id' => (int)$currencyId,
|
|
||||||
'currency_code' => null,
|
|
||||||
'description' => null,
|
|
||||||
'foreign_amount' => $foreignAmount,
|
|
||||||
'foreign_currency_id' => $foreignCurrencyId,
|
|
||||||
'foreign_currency_code' => null,
|
|
||||||
]],
|
|
||||||
'currency_id' => $foreignCurrencyId,
|
|
||||||
'tags' => $tags,
|
|
||||||
'interest_date' => $journal->interest_date,
|
|
||||||
'book_date' => $journal->book_date,
|
|
||||||
'process_date' => $journal->process_date,
|
|
||||||
|
|
||||||
];
|
|
||||||
// call repository update function.
|
|
||||||
$repository->update($journal, $data);
|
|
||||||
|
|
||||||
// trigger rules
|
|
||||||
event(new UpdatedTransactionGroup($group));
|
|
||||||
|
|
||||||
++$count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
session()->flash('success', (string)trans('firefly.mass_edited_transactions_success', ['amount' => $count]));
|
session()->flash('success', (string)trans('firefly.mass_edited_transactions_success', ['amount' => $count]));
|
||||||
|
|
||||||
@@ -261,4 +190,106 @@ class MassController extends Controller
|
|||||||
return redirect($this->getPreviousUri('transactions.mass-edit.uri'));
|
return redirect($this->getPreviousUri('transactions.mass-edit.uri'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $journalId
|
||||||
|
* @param MassEditJournalRequest $request
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function updateJournal(int $journalId, MassEditJournalRequest $request): void
|
||||||
|
{
|
||||||
|
$journal = $this->repository->findNull($journalId);
|
||||||
|
if (null === $journal) {
|
||||||
|
throw new FireflyException(sprintf('Trying to edit non-existent or deleted journal #%d', $journalId)); // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
$service = app(JournalUpdateService::class);
|
||||||
|
// for each field, call the update service.
|
||||||
|
$service->setTransactionJournal($journal);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'date' => $this->getDateFromRequest($request, $journal->id, 'date'),
|
||||||
|
'description' => $this->getStringFromRequest($request, $journal->id, 'description'),
|
||||||
|
'source_id' => $this->getIntFromRequest($request, $journal->id, 'source_id'),
|
||||||
|
'source_name' => $this->getStringFromRequest($request, $journal->id, 'source_name'),
|
||||||
|
'destination_id' => $this->getIntFromRequest($request, $journal->id, 'destination_id'),
|
||||||
|
'destination_name' => $this->getStringFromRequest($request, $journal->id, 'destination_name'),
|
||||||
|
'budget_id' => $this->getIntFromRequest($request, $journal->id, 'budget_id'),
|
||||||
|
'category_name' => $this->getStringFromRequest($request, $journal->id, 'category'),
|
||||||
|
'amount' => $this->getStringFromRequest($request, $journal->id, 'amount'),
|
||||||
|
'foreign_amount' => $this->getStringFromRequest($request, $journal->id, 'foreign_amount'),
|
||||||
|
];
|
||||||
|
Log::debug(sprintf('Will update journal #%d with data.', $journal->id), $data);
|
||||||
|
|
||||||
|
// call service to update.
|
||||||
|
$service->setData($data);
|
||||||
|
$service->update();
|
||||||
|
// trigger rules
|
||||||
|
event(new UpdatedTransactionGroup($journal->transactionGroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param MassEditJournalRequest $request
|
||||||
|
* @param int $journalId
|
||||||
|
* @param string $string
|
||||||
|
* @return int|null
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
private function getIntFromRequest(MassEditJournalRequest $request, int $journalId, string $string): ?int
|
||||||
|
{
|
||||||
|
$value = $request->get($string);
|
||||||
|
if (!is_array($value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!isset($value[$journalId])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)$value[$journalId];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param MassEditJournalRequest $request
|
||||||
|
* @param int $journalId
|
||||||
|
* @param string $string
|
||||||
|
* @return string|null
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
private function getStringFromRequest(MassEditJournalRequest $request, int $journalId, string $string): ?string
|
||||||
|
{
|
||||||
|
$value = $request->get($string);
|
||||||
|
if (!is_array($value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!isset($value[$journalId])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string)$value[$journalId];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param MassEditJournalRequest $request
|
||||||
|
* @param int $journalId
|
||||||
|
* @param string $string
|
||||||
|
* @return Carbon|null
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
private function getDateFromRequest(MassEditJournalRequest $request, int $journalId, string $string): ?Carbon
|
||||||
|
{
|
||||||
|
$value = $request->get($string);
|
||||||
|
if (!is_array($value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!isset($value[$journalId])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$carbon = Carbon::parse($value[$journalId]);
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
$e->getMessage();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $carbon;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -41,7 +41,7 @@ class ShowController extends Controller
|
|||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConvertController constructor.
|
* ShowController constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -81,8 +81,29 @@ class ShowController extends Controller
|
|||||||
$groupArray = $transformer->transformObject($transactionGroup);
|
$groupArray = $transformer->transformObject($transactionGroup);
|
||||||
|
|
||||||
// do some amount calculations:
|
// do some amount calculations:
|
||||||
|
$amounts = $this->getAmounts($groupArray);
|
||||||
|
|
||||||
|
|
||||||
|
$events = $this->repository->getPiggyEvents($transactionGroup);
|
||||||
|
$attachments = $this->repository->getAttachments($transactionGroup);
|
||||||
|
$links = $this->repository->getLinks($transactionGroup);
|
||||||
|
|
||||||
|
return view(
|
||||||
|
'transactions.show', compact(
|
||||||
|
'transactionGroup', 'amounts', 'first', 'type', 'subTitle', 'splits', 'groupArray',
|
||||||
|
'events', 'attachments', 'links', 'message'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $group
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getAmounts(array $group): array
|
||||||
|
{
|
||||||
$amounts = [];
|
$amounts = [];
|
||||||
foreach ($groupArray['transactions'] as $transaction) {
|
foreach ($group['transactions'] as $transaction) {
|
||||||
$symbol = $transaction['currency_symbol'];
|
$symbol = $transaction['currency_symbol'];
|
||||||
if (!isset($amounts[$symbol])) {
|
if (!isset($amounts[$symbol])) {
|
||||||
$amounts[$symbol] = [
|
$amounts[$symbol] = [
|
||||||
@@ -106,15 +127,6 @@ class ShowController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$events = $this->repository->getPiggyEvents($transactionGroup);
|
return $amounts;
|
||||||
$attachments = $this->repository->getAttachments($transactionGroup);
|
|
||||||
$links = $this->repository->getLinks($transactionGroup);
|
|
||||||
|
|
||||||
return view(
|
|
||||||
'transactions.show', compact(
|
|
||||||
'transactionGroup', 'amounts', 'first', 'type', 'subTitle', 'splits', 'groupArray',
|
|
||||||
'events', 'attachments', 'links', 'message'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -53,6 +53,7 @@ class MassEditJournalRequest extends Request
|
|||||||
'description.*' => 'required|min:1,max:255',
|
'description.*' => 'required|min:1,max:255',
|
||||||
'source_id.*' => 'numeric|belongsToUser:accounts,id',
|
'source_id.*' => 'numeric|belongsToUser:accounts,id',
|
||||||
'destination_id.*' => 'numeric|belongsToUser:accounts,id',
|
'destination_id.*' => 'numeric|belongsToUser:accounts,id',
|
||||||
|
'journals.*' => 'numeric|belongsToUser:transaction_journals,id',
|
||||||
'revenue_account' => 'max:255',
|
'revenue_account' => 'max:255',
|
||||||
'expense_account' => 'max:255',
|
'expense_account' => 'max:255',
|
||||||
];
|
];
|
||||||
|
@@ -131,7 +131,6 @@ class JournalUpdateService
|
|||||||
public function update(): void
|
public function update(): void
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Now in JournalUpdateService for journal #%d.', $this->transactionJournal->id));
|
Log::debug(sprintf('Now in JournalUpdateService for journal #%d.', $this->transactionJournal->id));
|
||||||
|
|
||||||
// can we update account data using the new type?
|
// can we update account data using the new type?
|
||||||
if ($this->hasValidAccounts()) {
|
if ($this->hasValidAccounts()) {
|
||||||
Log::info('-- account info is valid, now update.');
|
Log::info('-- account info is valid, now update.');
|
||||||
@@ -142,7 +141,6 @@ class JournalUpdateService
|
|||||||
$this->updateType();
|
$this->updateType();
|
||||||
$this->transactionJournal->refresh();
|
$this->transactionJournal->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
// find and update bill, if possible.
|
// find and update bill, if possible.
|
||||||
$this->updateBill();
|
$this->updateBill();
|
||||||
|
|
||||||
@@ -276,6 +274,7 @@ class JournalUpdateService
|
|||||||
if (null === $this->sourceTransaction) {
|
if (null === $this->sourceTransaction) {
|
||||||
$this->sourceTransaction = $this->transactionJournal->transactions()->with(['account'])->where('amount', '<', 0)->first();
|
$this->sourceTransaction = $this->transactionJournal->transactions()->with(['account'])->where('amount', '<', 0)->first();
|
||||||
}
|
}
|
||||||
|
Log::debug(sprintf('getSourceTransaction: %s', $this->sourceTransaction->amount));
|
||||||
|
|
||||||
return $this->sourceTransaction;
|
return $this->sourceTransaction;
|
||||||
}
|
}
|
||||||
@@ -447,9 +446,14 @@ class JournalUpdateService
|
|||||||
$sourceTransaction->account()->associate($source);
|
$sourceTransaction->account()->associate($source);
|
||||||
$sourceTransaction->save();
|
$sourceTransaction->save();
|
||||||
|
|
||||||
$destinationTransaction = $this->getDestinationTransaction();
|
$destTransaction = $this->getDestinationTransaction();
|
||||||
$destinationTransaction->account()->associate($destination);
|
$destTransaction->account()->associate($destination);
|
||||||
$destinationTransaction->save();
|
$destTransaction->save();
|
||||||
|
|
||||||
|
// refresh transactions.
|
||||||
|
$this->sourceTransaction->refresh();
|
||||||
|
$this->destinationTransaction->refresh();
|
||||||
|
|
||||||
|
|
||||||
Log::debug(sprintf('Will set source to #%d ("%s")', $source->id, $source->name));
|
Log::debug(sprintf('Will set source to #%d ("%s")', $source->id, $source->name));
|
||||||
Log::debug(sprintf('Will set dest to #%d ("%s")', $destination->id, $destination->name));
|
Log::debug(sprintf('Will set dest to #%d ("%s")', $destination->id, $destination->name));
|
||||||
@@ -468,14 +472,20 @@ class JournalUpdateService
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Updated amount to %s', $amount));
|
|
||||||
$sourceTransaction = $this->getSourceTransaction();
|
$sourceTransaction = $this->getSourceTransaction();
|
||||||
$sourceTransaction->amount = app('steam')->negative($value);
|
$sourceTransaction->amount = app('steam')->negative($amount);
|
||||||
$sourceTransaction->save();
|
$sourceTransaction->save();
|
||||||
|
|
||||||
$destinationTransaction = $this->getDestinationTransaction();
|
|
||||||
$destinationTransaction->amount = app('steam')->positive($value);
|
$destTransaction = $this->getDestinationTransaction();
|
||||||
$destinationTransaction->save();
|
$destTransaction->amount = app('steam')->positive($amount);
|
||||||
|
$destTransaction->save();
|
||||||
|
|
||||||
|
|
||||||
|
// refresh transactions.
|
||||||
|
$this->sourceTransaction->refresh();
|
||||||
|
$this->destinationTransaction->refresh();
|
||||||
|
Log::debug(sprintf('Updated amount to "%s"', $amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -518,6 +528,10 @@ class JournalUpdateService
|
|||||||
$dest = $this->getDestinationTransaction();
|
$dest = $this->getDestinationTransaction();
|
||||||
$dest->transaction_currency_id = $currency->id;
|
$dest->transaction_currency_id = $currency->id;
|
||||||
$dest->save();
|
$dest->save();
|
||||||
|
|
||||||
|
// refresh transactions.
|
||||||
|
$this->sourceTransaction->refresh();
|
||||||
|
$this->destinationTransaction->refresh();
|
||||||
Log::debug(sprintf('Updated currency to #%d (%s)', $currency->id, $currency->code));
|
Log::debug(sprintf('Updated currency to #%d (%s)', $currency->id, $currency->code));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -572,6 +586,10 @@ class JournalUpdateService
|
|||||||
|
|
||||||
Log::debug(sprintf('Update foreign info to %s (#%d) %s', $foreignCurrency->code, $foreignCurrency->id, $foreignAmount));
|
Log::debug(sprintf('Update foreign info to %s (#%d) %s', $foreignCurrency->code, $foreignCurrency->id, $foreignAmount));
|
||||||
|
|
||||||
|
// refresh transactions.
|
||||||
|
$this->sourceTransaction->refresh();
|
||||||
|
$this->destinationTransaction->refresh();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ('0' === $amount) {
|
if ('0' === $amount) {
|
||||||
@@ -585,6 +603,10 @@ class JournalUpdateService
|
|||||||
Log::debug(sprintf('Foreign amount is "%s" so remove foreign amount info.', $amount));
|
Log::debug(sprintf('Foreign amount is "%s" so remove foreign amount info.', $amount));
|
||||||
}
|
}
|
||||||
Log::info('Not enough info to update foreign currency info.');
|
Log::info('Not enough info to update foreign currency info.');
|
||||||
|
|
||||||
|
// refresh transactions.
|
||||||
|
$this->sourceTransaction->refresh();
|
||||||
|
$this->destinationTransaction->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -22,8 +22,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Support\Binder;
|
namespace FireflyIII\Support\Binder;
|
||||||
|
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
use Illuminate\Routing\Route;
|
use Illuminate\Routing\Route;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,24 +39,38 @@ class JournalList implements BinderInterface
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value, Route $route): Collection
|
public static function routeBinder(string $value, Route $route): array
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$list = array_unique(array_map('\intval', explode(',', $value)));
|
$list = self::parseList($value);
|
||||||
if (0 === count($list)) {
|
|
||||||
throw new NotFoundHttpException; // @codeCoverageIgnore
|
// get the journals by using the collector.
|
||||||
|
/** @var GroupCollectorInterface $collector */
|
||||||
|
$collector = app(GroupCollectorInterface::class);
|
||||||
|
$collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]);
|
||||||
|
$collector->withCategoryInformation()->withBudgetInformation()->withTagInformation()->withAccountInformation();
|
||||||
|
$collector->setJournalIds($list);
|
||||||
|
$result = $collector->getExtractedJournals();
|
||||||
|
if (0 === count($result)) {
|
||||||
|
throw new NotFoundHttpException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var \Illuminate\Support\Collection $collection */
|
return $result;
|
||||||
$collection = auth()->user()->transactionJournals()
|
|
||||||
->whereIn('transaction_journals.id', $list)
|
|
||||||
->where('transaction_journals.completed', 1)
|
|
||||||
->get(['transaction_journals.*']);
|
|
||||||
|
|
||||||
if ($collection->count() > 0) {
|
|
||||||
return $collection;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
throw new NotFoundHttpException;
|
throw new NotFoundHttpException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected static function parseList(string $value): array
|
||||||
|
{
|
||||||
|
$list = array_unique(array_map('\intval', explode(',', $value)));
|
||||||
|
if (0 === count($list)) {
|
||||||
|
throw new NotFoundHttpException; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,78 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* SimpleJournalList.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\Support\Binder;
|
|
||||||
|
|
||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
|
||||||
use FireflyIII\Models\TransactionType;
|
|
||||||
use Illuminate\Routing\Route;
|
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class SimpleJournalList
|
|
||||||
*/
|
|
||||||
class SimpleJournalList implements BinderInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $value
|
|
||||||
* @param Route $route
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
* @throws NotFoundHttpException
|
|
||||||
*/
|
|
||||||
public static function routeBinder(string $value, Route $route): array
|
|
||||||
{
|
|
||||||
if (auth()->check()) {
|
|
||||||
$list = self::parseList($value);
|
|
||||||
|
|
||||||
// get the journals by using the collector.
|
|
||||||
/** @var GroupCollectorInterface $collector */
|
|
||||||
$collector = app(GroupCollectorInterface::class);
|
|
||||||
$collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]);
|
|
||||||
$collector->withCategoryInformation()->withBudgetInformation()->withTagInformation();
|
|
||||||
$collector->setJournalIds($list);
|
|
||||||
$result = $collector->getExtractedJournals();
|
|
||||||
if (0 === count($result)) {
|
|
||||||
throw new NotFoundHttpException;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
throw new NotFoundHttpException;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $value
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected static function parseList(string $value): array
|
|
||||||
{
|
|
||||||
$list = array_unique(array_map('\intval', explode(',', $value)));
|
|
||||||
if (0 === count($list)) {
|
|
||||||
throw new NotFoundHttpException; // @codeCoverageIgnore
|
|
||||||
}
|
|
||||||
|
|
||||||
return $list;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -58,7 +58,6 @@ use FireflyIII\Support\Binder\CurrencyCode;
|
|||||||
use FireflyIII\Support\Binder\Date;
|
use FireflyIII\Support\Binder\Date;
|
||||||
use FireflyIII\Support\Binder\ImportProvider;
|
use FireflyIII\Support\Binder\ImportProvider;
|
||||||
use FireflyIII\Support\Binder\JournalList;
|
use FireflyIII\Support\Binder\JournalList;
|
||||||
use FireflyIII\Support\Binder\SimpleJournalList;
|
|
||||||
use FireflyIII\Support\Binder\TagList;
|
use FireflyIII\Support\Binder\TagList;
|
||||||
use FireflyIII\Support\Binder\TagOrId;
|
use FireflyIII\Support\Binder\TagOrId;
|
||||||
use FireflyIII\Support\Binder\UnfinishedJournal;
|
use FireflyIII\Support\Binder\UnfinishedJournal;
|
||||||
@@ -398,7 +397,6 @@ return [
|
|||||||
'journalList' => JournalList::class,
|
'journalList' => JournalList::class,
|
||||||
'categoryList' => CategoryList::class,
|
'categoryList' => CategoryList::class,
|
||||||
'tagList' => TagList::class,
|
'tagList' => TagList::class,
|
||||||
'simpleJournalList' => SimpleJournalList::class,
|
|
||||||
|
|
||||||
// others
|
// others
|
||||||
'fromCurrencyCode' => CurrencyCode::class,
|
'fromCurrencyCode' => CurrencyCode::class,
|
||||||
|
40
public/v1/js/ff/transactions/mass/edit.js
vendored
40
public/v1/js/ff/transactions/mass/edit.js
vendored
@@ -18,22 +18,20 @@
|
|||||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** global: what */
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// description
|
// description
|
||||||
if ($('input[name^="description["]').length > 0) {
|
if ($('input[name^="description["]').length > 0) {
|
||||||
console.log('descr');
|
console.log('Description.');
|
||||||
var journalNames = new Bloodhound({
|
var journalNames = new Bloodhound({
|
||||||
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
|
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
|
||||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||||
prefetch: {
|
prefetch: {
|
||||||
url: 'json/transaction-journals/all?uid=' + uid,
|
url: 'json/transaction-journals/all?uid=' + uid,
|
||||||
filter: function (list) {
|
filter: function (list) {
|
||||||
return $.map(list, function (name) {
|
return $.map(list, function (obj) {
|
||||||
return {name: name};
|
return obj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -41,8 +39,8 @@ $(document).ready(function () {
|
|||||||
url: 'json/transaction-journals/all?search=%QUERY&uid=' + uid,
|
url: 'json/transaction-journals/all?search=%QUERY&uid=' + uid,
|
||||||
wildcard: '%QUERY',
|
wildcard: '%QUERY',
|
||||||
filter: function (list) {
|
filter: function (list) {
|
||||||
return $.map(list, function (name) {
|
return $.map(list, function (obj) {
|
||||||
return {name: name};
|
return obj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,15 +50,15 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
// destination account names:
|
// destination account names:
|
||||||
if ($('input[name^="destination_name["]').length > 0) {
|
if ($('input[name^="destination_name["]').length > 0) {
|
||||||
|
console.log('Destination.');
|
||||||
var destNames = new Bloodhound({
|
var destNames = new Bloodhound({
|
||||||
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
|
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
|
||||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||||
prefetch: {
|
prefetch: {
|
||||||
url: 'json/expense-accounts?uid=' + uid,
|
url: 'json/expense-accounts?uid=' + uid,
|
||||||
filter: function (list) {
|
filter: function (list) {
|
||||||
return $.map(list, function (name) {
|
return $.map(list, function (obj) {
|
||||||
return {name: name};
|
return obj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -68,8 +66,8 @@ $(document).ready(function () {
|
|||||||
url: 'json/expense-accounts?search=%QUERY&uid=' + uid,
|
url: 'json/expense-accounts?search=%QUERY&uid=' + uid,
|
||||||
wildcard: '%QUERY',
|
wildcard: '%QUERY',
|
||||||
filter: function (list) {
|
filter: function (list) {
|
||||||
return $.map(list, function (name) {
|
return $.map(list, function (obj) {
|
||||||
return {name: name};
|
return obj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,15 +78,15 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
// source account name
|
// source account name
|
||||||
if ($('input[name^="source_name["]').length > 0) {
|
if ($('input[name^="source_name["]').length > 0) {
|
||||||
|
console.log('Source.');
|
||||||
var sourceNames = new Bloodhound({
|
var sourceNames = new Bloodhound({
|
||||||
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
|
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
|
||||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||||
prefetch: {
|
prefetch: {
|
||||||
url: 'json/revenue-accounts?uid=' + uid,
|
url: 'json/revenue-accounts?uid=' + uid,
|
||||||
filter: function (list) {
|
filter: function (list) {
|
||||||
return $.map(list, function (name) {
|
return $.map(list, function (obj) {
|
||||||
return {name: name};
|
return obj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -96,8 +94,8 @@ $(document).ready(function () {
|
|||||||
url: 'json/revenue-accounts?search=%QUERY&uid=' + uid,
|
url: 'json/revenue-accounts?search=%QUERY&uid=' + uid,
|
||||||
wildcard: '%QUERY',
|
wildcard: '%QUERY',
|
||||||
filter: function (list) {
|
filter: function (list) {
|
||||||
return $.map(list, function (name) {
|
return $.map(list, function (obj) {
|
||||||
return {name: name};
|
return obj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,8 +111,8 @@ $(document).ready(function () {
|
|||||||
prefetch: {
|
prefetch: {
|
||||||
url: 'json/categories?uid=' + uid,
|
url: 'json/categories?uid=' + uid,
|
||||||
filter: function (list) {
|
filter: function (list) {
|
||||||
return $.map(list, function (name) {
|
return $.map(list, function (obj) {
|
||||||
return {name: name};
|
return obj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -122,8 +120,8 @@ $(document).ready(function () {
|
|||||||
url: 'json/categories?search=%QUERY&uid=' + uid,
|
url: 'json/categories?search=%QUERY&uid=' + uid,
|
||||||
wildcard: '%QUERY',
|
wildcard: '%QUERY',
|
||||||
filter: function (list) {
|
filter: function (list) {
|
||||||
return $.map(list, function (name) {
|
return $.map(list, function (obj) {
|
||||||
return {name: name};
|
return obj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -851,7 +851,7 @@ return [
|
|||||||
'cannot_edit_other_fields' => 'You cannot mass-edit other fields than the ones here, because there is no room to show them. Please follow the link and edit them by one-by-one, if you need to edit these fields.',
|
'cannot_edit_other_fields' => 'You cannot mass-edit other fields than the ones here, because there is no room to show them. Please follow the link and edit them by one-by-one, if you need to edit these fields.',
|
||||||
'no_budget' => '(no budget)',
|
'no_budget' => '(no budget)',
|
||||||
'no_budget_squared' => '(no budget)',
|
'no_budget_squared' => '(no budget)',
|
||||||
'perm-delete-many' => 'Deleting many items in one go can be very disruptive. Please be cautious.',
|
'perm-delete-many' => 'Deleting many items in one go can be very disruptive. Please be cautious. You can delete part of a split transaction from this page, so take care.',
|
||||||
'mass_deleted_transactions_success' => 'Deleted :amount transaction(s).',
|
'mass_deleted_transactions_success' => 'Deleted :amount transaction(s).',
|
||||||
'mass_edited_transactions_success' => 'Updated :amount transaction(s)',
|
'mass_edited_transactions_success' => 'Updated :amount transaction(s)',
|
||||||
'opt_group_' => '(no account type)',
|
'opt_group_' => '(no account type)',
|
||||||
|
@@ -23,64 +23,65 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'buttons' => 'Buttons',
|
'buttons' => 'Buttons',
|
||||||
'icon' => 'Icon',
|
'icon' => 'Icon',
|
||||||
'id' => 'ID',
|
'id' => 'ID',
|
||||||
'create_date' => 'Created at',
|
'create_date' => 'Created at',
|
||||||
'update_date' => 'Updated at',
|
'update_date' => 'Updated at',
|
||||||
'updated_at' => 'Updated at',
|
'updated_at' => 'Updated at',
|
||||||
'balance_before' => 'Balance before',
|
'balance_before' => 'Balance before',
|
||||||
'balance_after' => 'Balance after',
|
'balance_after' => 'Balance after',
|
||||||
'name' => 'Name',
|
'name' => 'Name',
|
||||||
'role' => 'Role',
|
'role' => 'Role',
|
||||||
'currentBalance' => 'Current balance',
|
'currentBalance' => 'Current balance',
|
||||||
'linked_to_rules' => 'Relevant rules',
|
'linked_to_rules' => 'Relevant rules',
|
||||||
'active' => 'Is active?',
|
'active' => 'Is active?',
|
||||||
'lastActivity' => 'Last activity',
|
'transaction_type' => 'Type',
|
||||||
'balanceDiff' => 'Balance difference',
|
'lastActivity' => 'Last activity',
|
||||||
'matchesOn' => 'Matched on',
|
'balanceDiff' => 'Balance difference',
|
||||||
'account_type' => 'Account type',
|
'matchesOn' => 'Matched on',
|
||||||
'created_at' => 'Created at',
|
'account_type' => 'Account type',
|
||||||
'account' => 'Account',
|
'created_at' => 'Created at',
|
||||||
'matchingAmount' => 'Amount',
|
'account' => 'Account',
|
||||||
'split_number' => 'Split #',
|
'matchingAmount' => 'Amount',
|
||||||
'destination' => 'Destination',
|
'split_number' => 'Split #',
|
||||||
'source' => 'Source',
|
'destination' => 'Destination',
|
||||||
'next_expected_match' => 'Next expected match',
|
'source' => 'Source',
|
||||||
'automatch' => 'Auto match?',
|
'next_expected_match' => 'Next expected match',
|
||||||
'repeat_freq' => 'Repeats',
|
'automatch' => 'Auto match?',
|
||||||
'description' => 'Description',
|
'repeat_freq' => 'Repeats',
|
||||||
'amount' => 'Amount',
|
'description' => 'Description',
|
||||||
'internal_reference' => 'Internal reference',
|
'amount' => 'Amount',
|
||||||
'date' => 'Date',
|
'internal_reference' => 'Internal reference',
|
||||||
'interest_date' => 'Interest date',
|
'date' => 'Date',
|
||||||
'book_date' => 'Book date',
|
'interest_date' => 'Interest date',
|
||||||
'process_date' => 'Processing date',
|
'book_date' => 'Book date',
|
||||||
'due_date' => 'Due date',
|
'process_date' => 'Processing date',
|
||||||
'payment_date' => 'Payment date',
|
'due_date' => 'Due date',
|
||||||
'invoice_date' => 'Invoice date',
|
'payment_date' => 'Payment date',
|
||||||
'interal_reference' => 'Internal reference',
|
'invoice_date' => 'Invoice date',
|
||||||
'notes' => 'Notes',
|
'interal_reference' => 'Internal reference',
|
||||||
'from' => 'From',
|
'notes' => 'Notes',
|
||||||
'piggy_bank' => 'Piggy bank',
|
'from' => 'From',
|
||||||
'to' => 'To',
|
'piggy_bank' => 'Piggy bank',
|
||||||
'budget' => 'Budget',
|
'to' => 'To',
|
||||||
'category' => 'Category',
|
'budget' => 'Budget',
|
||||||
'bill' => 'Bill',
|
'category' => 'Category',
|
||||||
'withdrawal' => 'Withdrawal',
|
'bill' => 'Bill',
|
||||||
'deposit' => 'Deposit',
|
'withdrawal' => 'Withdrawal',
|
||||||
'transfer' => 'Transfer',
|
'deposit' => 'Deposit',
|
||||||
'type' => 'Type',
|
'transfer' => 'Transfer',
|
||||||
'completed' => 'Completed',
|
'type' => 'Type',
|
||||||
'iban' => 'IBAN',
|
'completed' => 'Completed',
|
||||||
'paid_current_period' => 'Paid this period',
|
'iban' => 'IBAN',
|
||||||
'email' => 'Email',
|
'paid_current_period' => 'Paid this period',
|
||||||
'registered_at' => 'Registered at',
|
'email' => 'Email',
|
||||||
'is_blocked' => 'Is blocked',
|
'registered_at' => 'Registered at',
|
||||||
'is_admin' => 'Is admin',
|
'is_blocked' => 'Is blocked',
|
||||||
'has_two_factor' => 'Has 2FA',
|
'is_admin' => 'Is admin',
|
||||||
'blocked_code' => 'Block code',
|
'has_two_factor' => 'Has 2FA',
|
||||||
'source_account' => 'Source account',
|
'blocked_code' => 'Block code',
|
||||||
|
'source_account' => 'Source account',
|
||||||
'destination_account' => 'Destination account',
|
'destination_account' => 'Destination account',
|
||||||
'accounts_count' => 'Number of accounts',
|
'accounts_count' => 'Number of accounts',
|
||||||
'journals_count' => 'Number of transactions',
|
'journals_count' => 'Number of transactions',
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
{{ trans('form.permDeleteWarning') }}
|
{{ trans('form.permDeleteWarning') }}
|
||||||
{{ 'perm-delete-many'|_ }}
|
{{ 'perm-delete-many'|_ }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{{ trans('form.mass_journal_are_you_sure') }}
|
{{ trans('form.mass_journal_are_you_sure') }}
|
||||||
{{ trans('form.mass_make_selection') }}
|
{{ trans('form.mass_make_selection') }}
|
||||||
@@ -28,8 +27,9 @@
|
|||||||
<table class="table table-striped table-condensed">
|
<table class="table table-striped table-condensed">
|
||||||
<tr>
|
<tr>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
|
<th>{{ trans('list.transaction_type') }}</th>
|
||||||
<th>{{ trans('list.description') }}</th>
|
<th>{{ trans('list.description') }}</th>
|
||||||
<th>{{ trans('list.total_amount') }}</th>
|
<th>{{ trans('list.amount') }}</th>
|
||||||
<th class="hidden-sm hidden-xs">{{ trans('list.date') }}</th>
|
<th class="hidden-sm hidden-xs">{{ trans('list.date') }}</th>
|
||||||
<th class="hidden-xs">{{ trans('list.from') }}</th>
|
<th class="hidden-xs">{{ trans('list.from') }}</th>
|
||||||
<th class="hidden-xs">{{ trans('list.to') }}</th>
|
<th class="hidden-xs">{{ trans('list.to') }}</th>
|
||||||
@@ -37,22 +37,61 @@
|
|||||||
{% for journal in journals %}
|
{% for journal in journals %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" name="confirm_mass_delete[]" value="{{ journal.id }}" checked/>
|
<input type="checkbox" name="confirm_mass_delete[]" value="{{ journal.transaction_journal_id }}" checked/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ route('transactions.show',journal.id) }}" title="{{ journal.description }}">{{ journal.description }}</a>
|
{% if journal.transaction_type_type == 'Withdrawal' %}
|
||||||
|
<i class="fa fa-long-arrow-left fa-fw" title="{{ trans('firefly.Withdrawal') }}"></i>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if journal.transaction_type_type == 'Deposit' %}
|
||||||
|
<i class="fa fa-long-arrow-right fa-fw" title="{{ trans('firefly.Deposit') }}"></i>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if journal.transaction_type_type == 'Transfer' %}
|
||||||
|
<i class="fa fa-exchange fa-fw" title="{{ trans('firefly.Deposit') }}"></i>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if journal.transaction_type_type == 'Reconciliation' %}
|
||||||
|
<i class="fa-fw fa fa-calculator" title="{{ trans('firefly.reconciliation_transaction') }}"></i>
|
||||||
|
{% endif %}
|
||||||
|
{% if journal.transaction_type_type == 'Opening balance' %}
|
||||||
|
<i class="fa-fw fa fa-star-o" title="{{ trans('firefly.Opening balance') }}"></i>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ journal|journalTotalAmount }}
|
<a href="{{ route('transactions.show',journal.transaction_journal_id) }}"
|
||||||
|
title="{{ journal.description }}">{{ journal.description }}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if journal.transaction_type_type == 'Deposit' %}
|
||||||
|
{{ formatAmountBySymbol(journal.amount*-1, journal.currency_symbol, journal.currency_symbol_decimal_places) }}
|
||||||
|
{% if null != journal.foreign_amount %}
|
||||||
|
({{ formatAmountBySymbol(journal.foreign_amount*-1, journal.foreign_currency_symbol, journal.foreign_currency_symbol_decimal_places) }})
|
||||||
|
{% endif %}
|
||||||
|
{% elseif journal.transaction_type_type == 'Transfer' %}
|
||||||
|
<span class="text-info">{{ formatAmountBySymbol(journal.amount*-1, journal.currency_symbol, journal.currency_symbol_decimal_places, false) }}
|
||||||
|
{% if null != journal.foreign_amount %}
|
||||||
|
({{ formatAmountBySymbol(journal.foreign_amount*-1, journal.foreign_currency_symbol, journal.foreign_currency_symbol_decimal_places, false) }})
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
{{ formatAmountBySymbol(journal.amount, journal.currency_symbol, journal.currency_symbol_decimal_places) }}
|
||||||
|
{% if null != journal.foreign_amount %}
|
||||||
|
({{ formatAmountBySymbol(journal.foreign_amount, journal.foreign_currency_symbol, journal.foreign_currency_symbol_decimal_places) }})
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ journal.date.formatLocalized(monthAndDayFormat) }}
|
{{ journal.date.formatLocalized(monthAndDayFormat) }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ sourceAccount(journal)|raw }}
|
<a href="{{ route('accounts.show', [journal.source_account_id]) }}"
|
||||||
|
title="{{ journal.source_account_iban|default(journal.source_account_name) }}">{{ journal.source_account_name }}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ destinationXAccount(journal)|raw }}
|
<a href="{{ route('accounts.show', [journal.destination_account_id]) }}"
|
||||||
|
title="{{ journal.destination_account_iban|default(journal.destination_account_name) }}">{{ journal.destination_account_name }}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{% extends "./layout/default" %}
|
{% extends "./layout/default" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, transactions) }}
|
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, journals) }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
@@ -29,91 +29,107 @@
|
|||||||
<th class="col-lg-2 col-md-2 col-sm-2">{{ trans('list.category') }}</th>
|
<th class="col-lg-2 col-md-2 col-sm-2">{{ trans('list.category') }}</th>
|
||||||
<th class="col-lg-2 col-md-2 col-sm-2">{{ trans('list.budget') }}</th>
|
<th class="col-lg-2 col-md-2 col-sm-2">{{ trans('list.budget') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for transaction in transactions %}
|
{% for journal in journals %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{# LINK TO EDIT FORM #}
|
{# LINK TO EDIT FORM #}
|
||||||
<a href="{{ route('transactions.edit', transaction.journal_id) }}" class="btn btn-xs btn-default"><i
|
<a href="{{ route('transactions.edit', journal.transaction_group_id) }}" class="btn btn-xs btn-default"><i
|
||||||
class="fa fa-fw fa-pencil"></i></a>
|
class="fa fa-fw fa-pencil"></i></a>
|
||||||
<input type="hidden" name="journals[]" value="{{ transaction.journal_id }}"/>
|
<input type="hidden" name="journals[]" value="{{ journal.transaction_journal_id }}"/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{# DESCRIPTION #}
|
{# DESCRIPTION #}
|
||||||
<input class="form-control input-sm" autocomplete="off"
|
<input class="form-control input-sm" autocomplete="off"
|
||||||
placeholder="{{ transaction.description }}" name="description[{{ transaction.journal_id }}]"
|
placeholder="{{ journal.description }}" name="description[{{ journal.transaction_journal_id }}]"
|
||||||
type="text" value="{{ transaction.description }}">
|
type="text" value="{{ journal.description }}">
|
||||||
</td>
|
</td>
|
||||||
{# AMOUNT #}
|
{# AMOUNT #}
|
||||||
<td>
|
<td>
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<span class="input-group-addon">{{ transaction.currency_symbol }}</span>
|
|
||||||
<input name="amount[{{ transaction.journal_id }}]" class="form-control" autocomplete="off"
|
|
||||||
step="any" type="number" value="{{ transaction.amount }}">
|
<span class="input-group-addon">{{ journal.currency_symbol }}</span>
|
||||||
<input type="hidden" name="transaction_currency_id[{{ transaction.journal_id }}]"
|
<input name="amount[{{ journal.transaction_journal_id }}]" class="form-control" autocomplete="off"
|
||||||
value="{{ transaction.currency_id }}">
|
step="any" type="number" value="{{ journal.amount }}">
|
||||||
|
<input type="hidden" name="transaction_currency_id[{{ journal.transaction_journal_id }}]"
|
||||||
|
value="{{ journal.currency_id }}">
|
||||||
</div>
|
</div>
|
||||||
{% if transaction.foreign_amount %}
|
{% if journal.foreign_amount %}
|
||||||
{# insert foreign data #}
|
{# insert foreign data #}
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<span class="input-group-addon">{{ transaction.foreign_currency_symbol }}</span>
|
<span class="input-group-addon">{{ journal.foreign_currency_symbol }}</span>
|
||||||
<input name="foreign_amount[{{ transaction.journal_id }}]" class="form-control" autocomplete="off"
|
<input name="foreign_amount[{{ journal.transaction_journal_id }}]" class="form-control" autocomplete="off"
|
||||||
step="any" type="number" value="{{ transaction.foreign_amount }}">
|
step="any" type="number" value="{{ journal.foreign_amount }}">
|
||||||
<input type="hidden" name="foreign_currency_id[{{ transaction.journal_id }}]" value="{{ transaction.foreign_currency_id }}">
|
<input type="hidden" name="foreign_currency_id[{{ journal.transaction_journal_id }}]"
|
||||||
|
value="{{ journal.foreign_currency_id }}">
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{# DATE #}
|
{# DATE #}
|
||||||
<input class="form-control input-sm" autocomplete="off"
|
<input class="form-control input-sm" autocomplete="off"
|
||||||
name="date[{{ transaction.journal_id }}]" type="date" value="{{ transaction.date|slice(0,10) }}">
|
name="date[{{ journal.transaction_journal_id }}]" type="date" value="{{ journal.date|slice(0,10) }}">
|
||||||
</td>
|
</td>
|
||||||
|
<!-- {{ journal.transaction_type_type }} -->
|
||||||
|
<!-- Source: {{ journal.source_account_name }} ({{ journal.source_account_id }}) -->
|
||||||
|
<!-- Destination: {{ journal.destination_account_name }} ({{ journal.destination_account_id }}) -->
|
||||||
<td style="position: relative;">
|
<td style="position: relative;">
|
||||||
|
|
||||||
{# SOURCE ACCOUNT ID FOR TRANSFER OR WITHDRAWAL #}
|
{# SOURCE ACCOUNT ID FOR TRANSFER OR WITHDRAWAL #}
|
||||||
{% if transaction.type == 'Transfer' or transaction.type == 'Withdrawal' %}
|
{% if journal.transaction_type_type == 'Transfer' or journal.transaction_type_type == 'Withdrawal' %}
|
||||||
<select class="form-control input-sm" name="source_id[{{ transaction.journal_id }}]">
|
<select class="form-control input-sm" name="source_id[{{ journal.transaction_journal_id }}]">
|
||||||
{% for account in accounts %}
|
{% for account in withdrawalSources %}
|
||||||
<!-- {{ transaction.type }}: {{ transaction.source_name }} -->
|
<option value="{{ account.id }}"{% if account.id == journal.source_account_id %} selected{% endif %}
|
||||||
<option value="{{ account.id }}"{% if account.id == transaction.source_id %} selected{% endif %} label="{{ account.name }}">{{ account.name }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
{% else %}
|
|
||||||
{# SOURCE ACCOUNT NAME FOR DEPOSIT #}
|
|
||||||
<input class="form-control input-sm" placeholder="{% if transaction.source_type != 'Cash account' %}{{ transaction.source_name }}{% endif %}" autocomplete="off"
|
|
||||||
name="source_name[{{ transaction.journal_id }}]" type="text" value="{% if transaction.source_type != 'Cash account' %}{{ transaction.source_name }}{% endif %}">
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td style="position: relative;">
|
|
||||||
{% if transaction.type == 'Transfer' or transaction.type == 'Deposit' %}
|
|
||||||
{# DESTINATION ACCOUNT NAME FOR TRANSFER AND DEPOSIT #}
|
|
||||||
<select class="form-control input-sm" name="destination_id[{{ transaction.journal_id }}]">
|
|
||||||
{% for account in accounts %}
|
|
||||||
<option value="{{ account.id }}"{% if account.id == transaction.destination_id %} selected="selected"{% endif %}
|
|
||||||
label="{{ account.name }}">{{ account.name }}</option>
|
label="{{ account.name }}">{{ account.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
{% else %}
|
{% endif %}
|
||||||
|
|
||||||
{# DESTINATION ACCOUNT NAME FOR EXPENSE #}
|
{# SOURCE ACCOUNT NAME FOR DEPOSIT #}
|
||||||
<input class="form-control input-sm" placeholder="{% if transaction.destination_type != 'Cash account' %}{{ transaction.destination_name }}{% endif %}"
|
{% if journal.transaction_type_type == 'Deposit' %}
|
||||||
name="destination_name[{{ transaction.journal_id }}]" type="text" autocomplete="off"
|
<input class="form-control input-sm"
|
||||||
value="{% if transaction.destination_type != 'Cash account' %}{{ transaction.destination_name }}{% endif %}">
|
placeholder="{% if journal.source_type != 'Cash account' %}{{ journal.source_account_name }}{% endif %}"
|
||||||
|
autocomplete="off"
|
||||||
|
name="source_name[{{ journal.transaction_journal_id }}]" type="text"
|
||||||
|
value="{% if journal.source_type != 'Cash account' %}{{ journal.source_account_name }}{% endif %}">
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td style="position: relative;">
|
||||||
|
|
||||||
|
{# DESTINATION ACCOUNT NAME FOR TRANSFER AND DEPOSIT #}
|
||||||
|
{% if journal.transaction_type_type == 'Transfer' or journal.transaction_type_type == 'Deposit' %}
|
||||||
|
|
||||||
|
<select class="form-control input-sm" name="destination_id[{{ journal.transaction_journal_id }}]">
|
||||||
|
{% for account in depositDestinations %}
|
||||||
|
<option value="{{ account.id }}"{% if account.id == journal.destination_account_id %} selected="selected"{% endif %}
|
||||||
|
label="{{ account.name }}">{{ account.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# DESTINATION ACCOUNT NAME FOR WITHDRAWAL #}
|
||||||
|
{% if journal.transaction_type_type == 'Withdrawal' %}
|
||||||
|
<input class="form-control input-sm"
|
||||||
|
placeholder="{% if journal.destination_type != 'Cash account' %}{{ journal.destination_account_name }}{% endif %}"
|
||||||
|
name="destination_name[{{ journal.transaction_journal_id }}]" type="text" autocomplete="off"
|
||||||
|
value="{% if journal.destination_type != 'Cash account' %}{{ journal.destination_account_name }}{% endif %}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{# category #}
|
{# category #}
|
||||||
<td style="position: relative;">
|
<td style="position: relative;">
|
||||||
<input class="form-control input-sm" placeholder="{{ transaction.category_name }}" autocomplete="off"
|
<input class="form-control input-sm" placeholder="{{ journal.category_name }}" autocomplete="off"
|
||||||
name="category[{{ transaction.journal_id }}]" type="text" value="{{ transaction.category_name }}">
|
name="category[{{ journal.transaction_journal_id }}]" type="text" value="{{ journal.category_name }}">
|
||||||
</td>
|
</td>
|
||||||
{# budget #}
|
{# budget #}
|
||||||
<td>
|
<td>
|
||||||
{% if transaction.type == 'Withdrawal' %}
|
{% if journal.transaction_type_type == 'Withdrawal' %}
|
||||||
<select class="form-control input-sm" name="budget_id[{{ transaction.journal_id }}]">
|
<select class="form-control input-sm" name="budget_id[{{ journal.transaction_journal_id }}]">
|
||||||
<option value="0" label="({{ 'no_budget'|_ }})"
|
<option value="0" label="({{ 'no_budget'|_ }})"
|
||||||
{% if transaction.budget_id == 0 %}selected="selected"{% endif %}
|
{% if journal.budget_id == 0 %}selected="selected"{% endif %}
|
||||||
>({{ 'no_budget'|_ }})
|
>({{ 'no_budget'|_ }})
|
||||||
</option>
|
</option>
|
||||||
{% for budget in budgets %}
|
{% for budget in budgets %}
|
||||||
<option value="{{ budget.id }}"{% if budget.id == transaction.budget_id %} selected="selected"{% endif %}
|
<option value="{{ budget.id }}"{% if budget.id == journal.budget_id %} selected="selected"{% endif %}
|
||||||
label="{{ budget.name }}">{{ budget.name }}</option>
|
label="{{ budget.name }}">{{ budget.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
@@ -41,7 +41,6 @@ use FireflyIII\Models\TransactionCurrency;
|
|||||||
use FireflyIII\Models\TransactionGroup;
|
use FireflyIII\Models\TransactionGroup;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\TransactionJournalLink;
|
use FireflyIII\Models\TransactionJournalLink;
|
||||||
use FireflyIII\Models\TransactionType;
|
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@@ -1096,12 +1095,11 @@ try {
|
|||||||
// MASS TRANSACTION EDIT / DELETE
|
// MASS TRANSACTION EDIT / DELETE
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'transactions.mass.edit',
|
'transactions.mass.edit',
|
||||||
function (BreadcrumbsGenerator $breadcrumbs, Collection $journals): void {
|
static function (BreadcrumbsGenerator $breadcrumbs, array $journals): void {
|
||||||
if (\count($journals) > 0) {
|
if (count($journals) > 0) {
|
||||||
$journalIds = $journals->pluck('id')->toArray();
|
$objectType = strtolower(reset($journals)['transaction_type_type']);
|
||||||
$what = strtolower($journals->first()['type']);
|
$breadcrumbs->parent('transactions.index', $objectType);
|
||||||
$breadcrumbs->parent('transactions.index', $what);
|
$breadcrumbs->push(trans('firefly.mass_edit_journals'), route('transactions.mass.edit', ['']));
|
||||||
$breadcrumbs->push(trans('firefly.mass_edit_journals'), route('transactions.mass.edit', $journalIds));
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1111,11 +1109,10 @@ try {
|
|||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'transactions.mass.delete',
|
'transactions.mass.delete',
|
||||||
function (BreadcrumbsGenerator $breadcrumbs, Collection $journals) {
|
static function (BreadcrumbsGenerator $breadcrumbs, array $journals) {
|
||||||
$journalIds = $journals->pluck('id')->toArray();
|
$objectType= strtolower(reset($journals)['transaction_type_type']);
|
||||||
$what = strtolower($journals->first()->transactionType->type);
|
$breadcrumbs->parent('transactions.index', $objectType);
|
||||||
$breadcrumbs->parent('transactions.index', $what);
|
$breadcrumbs->push(trans('firefly.mass_edit_journals'), route('transactions.mass.delete', ['']));
|
||||||
$breadcrumbs->push(trans('firefly.mass_edit_journals'), route('transactions.mass.delete', $journalIds));
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -922,7 +922,7 @@ Route::group(
|
|||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Transaction', 'prefix' => 'transactions/mass', 'as' => 'transactions.mass.'],
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Transaction', 'prefix' => 'transactions/mass', 'as' => 'transactions.mass.'],
|
||||||
function () {
|
function () {
|
||||||
Route::get('edit/{simpleJournalList}', ['uses' => 'MassController@edit', 'as' => 'edit']);
|
Route::get('edit/{journalList}', ['uses' => 'MassController@edit', 'as' => 'edit']);
|
||||||
Route::get('delete/{journalList}', ['uses' => 'MassController@delete', 'as' => 'delete']);
|
Route::get('delete/{journalList}', ['uses' => 'MassController@delete', 'as' => 'delete']);
|
||||||
Route::post('update', ['uses' => 'MassController@update', 'as' => 'update']);
|
Route::post('update', ['uses' => 'MassController@update', 'as' => 'update']);
|
||||||
Route::post('destroy', ['uses' => 'MassController@destroy', 'as' => 'destroy']);
|
Route::post('destroy', ['uses' => 'MassController@destroy', 'as' => 'destroy']);
|
||||||
@@ -935,7 +935,7 @@ Route::group(
|
|||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Transaction', 'prefix' => 'transactions/bulk', 'as' => 'transactions.bulk.'],
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Transaction', 'prefix' => 'transactions/bulk', 'as' => 'transactions.bulk.'],
|
||||||
function () {
|
function () {
|
||||||
Route::get('edit/{simpleJournalList}', ['uses' => 'BulkController@edit', 'as' => 'edit']);
|
Route::get('edit/{journalList}', ['uses' => 'BulkController@edit', 'as' => 'edit']);
|
||||||
Route::post('update', ['uses' => 'BulkController@update', 'as' => 'update']);
|
Route::post('update', ['uses' => 'BulkController@update', 'as' => 'update']);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@@ -23,17 +23,18 @@ declare(strict_types=1);
|
|||||||
namespace Tests\Feature\Controllers\Transaction;
|
namespace Tests\Feature\Controllers\Transaction;
|
||||||
|
|
||||||
|
|
||||||
use FireflyIII\Models\AccountType;
|
use Amount;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\Transformers\TransactionTransformer;
|
use FireflyIII\Services\Internal\Update\JournalUpdateService;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Log;
|
use Log;
|
||||||
use Mockery;
|
use Mockery;
|
||||||
|
use Preferences;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,26 +57,32 @@ class MassControllerTest extends TestCase
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \FireflyIII\Http\Controllers\Transaction\MassController
|
|
||||||
* @covers \FireflyIII\Http\Controllers\Transaction\MassController
|
* @covers \FireflyIII\Http\Controllers\Transaction\MassController
|
||||||
*/
|
*/
|
||||||
public function testDelete(): void
|
public function testDelete(): void
|
||||||
{
|
{
|
||||||
$this->markTestIncomplete('Needs to be rewritten for v4.8.0');
|
|
||||||
|
|
||||||
return;
|
$this->mockDefaultSession();
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
$withdrawal = $this->getRandomWithdrawal();
|
||||||
$userRepos = $this->mock(UserRepositoryInterface::class);
|
$withdrawalArray = $this->getRandomWithdrawalAsArray();
|
||||||
|
$userRepos = $this->mock(UserRepositoryInterface::class);
|
||||||
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
|
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
|
||||||
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
$collector = $this->mock(GroupCollectorInterface::class);
|
||||||
$journalRepos->shouldReceive('getJournalSourceAccounts')->andReturn(new Collection)->once();
|
$collector->shouldReceive('setTypes')
|
||||||
$journalRepos->shouldReceive('getJournalDestinationAccounts')->andReturn(new Collection)->once();
|
->withArgs([[TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]])->atLeast()->once()->andReturnSelf();
|
||||||
|
|
||||||
|
$collector->shouldReceive('withCategoryInformation')->atLeast()->once()->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withBudgetInformation')->atLeast()->once()->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withTagInformation')->atLeast()->once()->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withAccountInformation')->atLeast()->once()->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setJournalIds')->withArgs([[$withdrawal->id]])->atLeast()->once()->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getExtractedJournals')->atLeast()->once()->andReturn([$withdrawalArray]);
|
||||||
|
|
||||||
|
Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('x');
|
||||||
|
|
||||||
$withdrawals = TransactionJournal::where('transaction_type_id', 1)->where('user_id', $this->user()->id)->take(2)->get()->pluck('id')->toArray();
|
|
||||||
$this->be($this->user());
|
$this->be($this->user());
|
||||||
$response = $this->get(route('transactions.mass.delete', $withdrawals));
|
$response = $this->get(route('transactions.mass.delete', [$withdrawal->id]));
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
$response->assertSee('Delete a number of transactions');
|
$response->assertSee('Delete a number of transactions');
|
||||||
// has bread crumb
|
// has bread crumb
|
||||||
@@ -87,26 +94,16 @@ class MassControllerTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testDestroy(): void
|
public function testDestroy(): void
|
||||||
{
|
{
|
||||||
$this->markTestIncomplete('Needs to be rewritten for v4.8.0');
|
$repository = $this->mockDefaultSession();
|
||||||
|
$deposit = $this->getRandomDeposit();
|
||||||
|
|
||||||
return;
|
$repository->shouldReceive('findNull')->atLeast()->once()->andReturn($deposit);
|
||||||
|
$repository->shouldReceive('destroyJournal')->atLeast()->once();
|
||||||
$deposits = TransactionJournal::where('transaction_type_id', 2)->where('user_id', $this->user()->id)->take(2)->get();
|
Preferences::shouldReceive('mark')->atLeast()->once();
|
||||||
$depositIds = $deposits->pluck('id')->toArray();
|
|
||||||
|
|
||||||
// mock deletion:
|
|
||||||
$repository = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$userRepos = $this->mock(UserRepositoryInterface::class);
|
|
||||||
|
|
||||||
$repository->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('findNull')->andReturnValues([$deposits[0], $deposits[1]])->times(2);
|
|
||||||
$repository->shouldReceive('destroy')->times(2);
|
|
||||||
|
|
||||||
$this->session(['transactions.mass-delete.uri' => 'http://localhost']);
|
$this->session(['transactions.mass-delete.uri' => 'http://localhost']);
|
||||||
|
|
||||||
$data = [
|
$data = ['confirm_mass_delete' => [$deposit->id],];
|
||||||
'confirm_mass_delete' => $depositIds,
|
|
||||||
];
|
|
||||||
$this->be($this->user());
|
$this->be($this->user());
|
||||||
$response = $this->post(route('transactions.mass.destroy'), $data);
|
$response = $this->post(route('transactions.mass.destroy'), $data);
|
||||||
$response->assertSessionHas('success');
|
$response->assertSessionHas('success');
|
||||||
@@ -118,161 +115,59 @@ class MassControllerTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testEdit(): void
|
public function testEdit(): void
|
||||||
{
|
{
|
||||||
$this->markTestIncomplete('Needs to be rewritten for v4.8.0');
|
$withdrawal = $this->getRandomWithdrawal();
|
||||||
|
$withdrawalArray = $this->getRandomWithdrawalAsArray();
|
||||||
|
$asset = $this->getRandomAsset();
|
||||||
|
$budget = $this->getRandomBudget();
|
||||||
|
|
||||||
return;
|
$journalRepos = $this->mockDefaultSession();
|
||||||
// mock things
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$userRepos = $this->mock(UserRepositoryInterface::class);
|
$userRepos = $this->mock(UserRepositoryInterface::class);
|
||||||
$transformer = $this->mock(TransactionTransformer::class);
|
$repository = $this->mock(AccountRepositoryInterface::class);
|
||||||
$collector = $this->mock(TransactionCollectorInterface::class);
|
|
||||||
|
|
||||||
// data:
|
|
||||||
$transfers = TransactionJournal::where('transaction_type_id', 3)->where('user_id', $this->user()->id)->take(2)->get();
|
|
||||||
$transfersArray = $transfers->pluck('id')->toArray();
|
|
||||||
$source = $this->user()->accounts()->first();
|
|
||||||
|
|
||||||
$transaction = new Transaction;
|
|
||||||
|
|
||||||
// mock calls:
|
|
||||||
$transformer->shouldReceive('setParameters')->atLeast()->once();
|
|
||||||
$transformer->shouldReceive('transform')->atLeast()->once()->andReturn(
|
|
||||||
[
|
|
||||||
'amount' => '10',
|
|
||||||
'foreign_amount' => '',
|
|
||||||
'type' => 'transfer',
|
|
||||||
'id' => 3,
|
|
||||||
'journal_id' => 1,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$collector->shouldReceive('setUser')->atLeast()->once()->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withOpposingAccount')->atLeast()->once()->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withCategoryInformation')->atLeast()->once()->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withBudgetInformation')->atLeast()->once()->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setJournals')->atLeast()->once()->andReturnSelf();
|
|
||||||
$collector->shouldReceive('addFilter')->atLeast()->once()->andReturnSelf();
|
|
||||||
$collector->shouldReceive('getTransactions')->atLeast()->once()->andReturn(new Collection([new Transaction]));
|
|
||||||
|
|
||||||
|
|
||||||
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
|
|
||||||
|
|
||||||
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
// mock data for edit page:
|
|
||||||
$journalRepos->shouldReceive('getJournalSourceAccounts')->andReturn(new Collection([$source]))->atLeast()->once();
|
|
||||||
$journalRepos->shouldReceive('getJournalDestinationAccounts')->andReturn(new Collection([$source]))->atLeast()->once();
|
|
||||||
$journalRepos->shouldReceive('getTransactionType')->andReturn('Transfer')->atLeast()->once();
|
|
||||||
|
|
||||||
$journalRepos->shouldReceive('isJournalReconciled')->andReturn(false)->atLeast()->once();
|
|
||||||
|
|
||||||
// mock stuff:
|
|
||||||
$repository = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$repository->shouldReceive('getAccountsByType')->once()->withArgs([[AccountType::DEFAULT, AccountType::ASSET]])->andReturn(new Collection);
|
|
||||||
|
|
||||||
// mock more stuff:
|
|
||||||
$budgetRepos = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$budgetRepos->shouldReceive('getBudgets')->andReturn(new Collection)->atLeast()->once();
|
|
||||||
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->get(route('transactions.mass.edit', $transfersArray));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
$response->assertSee('Edit a number of transactions');
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\Transaction\MassController
|
|
||||||
*/
|
|
||||||
public function testEditMultiple(): void
|
|
||||||
{
|
|
||||||
$this->markTestIncomplete('Needs to be rewritten for v4.8.0');
|
|
||||||
|
|
||||||
return;
|
|
||||||
$budgetRepos = $this->mock(BudgetRepositoryInterface::class);
|
$budgetRepos = $this->mock(BudgetRepositoryInterface::class);
|
||||||
$userRepos = $this->mock(UserRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$transformer = $this->mock(TransactionTransformer::class);
|
|
||||||
$collector = $this->mock(TransactionCollectorInterface::class);
|
|
||||||
|
|
||||||
// mock calls:
|
|
||||||
$transformer->shouldReceive('setParameters')->atLeast()->once();
|
|
||||||
$transformer->shouldReceive('transform')->atLeast()->once()->andReturn(
|
|
||||||
[
|
|
||||||
'amount' => '10',
|
|
||||||
'foreign_amount' => '',
|
|
||||||
'type' => 'transfer',
|
|
||||||
'id' => 3,
|
|
||||||
'journal_id' => 1,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$collector->shouldReceive('setUser')->atLeast()->once()->andReturnSelf();
|
$collector = $this->mock(GroupCollectorInterface::class);
|
||||||
$collector->shouldReceive('withOpposingAccount')->atLeast()->once()->andReturnSelf();
|
$collector->shouldReceive('setTypes')
|
||||||
|
->withArgs([[TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]])->atLeast()->once()->andReturnSelf();
|
||||||
|
|
||||||
$collector->shouldReceive('withCategoryInformation')->atLeast()->once()->andReturnSelf();
|
$collector->shouldReceive('withCategoryInformation')->atLeast()->once()->andReturnSelf();
|
||||||
$collector->shouldReceive('withBudgetInformation')->atLeast()->once()->andReturnSelf();
|
$collector->shouldReceive('withBudgetInformation')->atLeast()->once()->andReturnSelf();
|
||||||
$collector->shouldReceive('setJournals')->atLeast()->once()->andReturnSelf();
|
$collector->shouldReceive('withTagInformation')->atLeast()->once()->andReturnSelf();
|
||||||
$collector->shouldReceive('addFilter')->atLeast()->once()->andReturnSelf();
|
$collector->shouldReceive('withAccountInformation')->atLeast()->once()->andReturnSelf();
|
||||||
$collector->shouldReceive('getTransactions')->atLeast()->once()->andReturn(new Collection([new Transaction]));
|
$collector->shouldReceive('setJournalIds')->withArgs([[$withdrawal->id]])->atLeast()->once()->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getExtractedJournals')->atLeast()->once()->andReturn([$withdrawalArray]);
|
||||||
|
|
||||||
|
$repository->shouldReceive('getAccountsByType')->atLeast()->once()->andReturn(new Collection([$asset]));
|
||||||
|
$budgetRepos->shouldReceive('getBudgets')->atLeast()->once()->andReturn(new Collection([$budget]));
|
||||||
|
|
||||||
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
|
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
|
||||||
$budgetRepos->shouldReceive('getBudgets')->andReturn(new Collection)->atLeast()->once();
|
|
||||||
|
|
||||||
|
|
||||||
// mock stuff:
|
|
||||||
$repository = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$repository->shouldReceive('getAccountsByType')->once()->withArgs([[AccountType::DEFAULT, AccountType::ASSET]])->andReturn(new Collection);
|
|
||||||
|
|
||||||
$journalRepos->shouldReceive('firstNull')->andReturn(new TransactionJournal)->atLeast()->once();
|
|
||||||
$journalRepos->shouldReceive('getJournalSourceAccounts')
|
|
||||||
->andReturn(new Collection([1, 2, 3]), new Collection, new Collection, new Collection, new Collection([1]))->atLeast()->once();
|
|
||||||
$journalRepos->shouldReceive('getJournalDestinationAccounts')
|
|
||||||
->andReturn(new Collection, new Collection([1, 2, 3]), new Collection, new Collection, new Collection([1]))->atLeast()->once();
|
|
||||||
$journalRepos->shouldReceive('getTransactionType')
|
|
||||||
->andReturn('Withdrawal', 'Opening balance', 'Withdrawal', 'Withdrawal', 'Withdrawal')->atLeast()->once();
|
|
||||||
$journalRepos->shouldReceive('isJournalReconciled')
|
|
||||||
->andReturn(true, false, false, false, false)->atLeast()->once();
|
|
||||||
|
|
||||||
// default transactions
|
|
||||||
$collection = $this->user()->transactionJournals()->take(5)->get();
|
|
||||||
$allIds = $collection->pluck('id')->toArray();
|
|
||||||
$route = route('transactions.mass.edit', implode(',', $allIds));
|
|
||||||
$this->be($this->user());
|
$this->be($this->user());
|
||||||
$response = $this->get($route);
|
$response = $this->get(route('transactions.mass.edit', [$withdrawal->id]));
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
$response->assertSee('Edit a number of transactions');
|
$response->assertSee('Edit a number of transactions');
|
||||||
// has bread crumb
|
// has bread crumb
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
$response->assertSee('marked as reconciled');
|
|
||||||
$response->assertSee('multiple source accounts');
|
|
||||||
$response->assertSee('multiple destination accounts');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \FireflyIII\Http\Controllers\Transaction\MassController
|
* @covers \FireflyIII\Http\Controllers\Transaction\MassController
|
||||||
*/
|
*/
|
||||||
public function testUpdate(): void
|
public function testUpdate(): void
|
||||||
{
|
{
|
||||||
$this->markTestIncomplete('Needs to be rewritten for v4.8.0');
|
$deposit = $this->getRandomDeposit();
|
||||||
|
$repository = $this->mockDefaultSession();
|
||||||
|
$userRepos = $this->mock(UserRepositoryInterface::class);
|
||||||
|
$updateService = $this->mock(JournalUpdateService::class);
|
||||||
|
|
||||||
return;
|
$this->expectsEvents(UpdatedTransactionGroup::class);
|
||||||
$deposit = TransactionJournal::where('transaction_type_id', 2)->where('user_id', $this->user()->id)
|
|
||||||
->whereNull('deleted_at')
|
|
||||||
->first();
|
|
||||||
|
|
||||||
// mock stuff
|
$updateService->shouldReceive('setTransactionJournal')->atLeast()->once();
|
||||||
$repository = $this->mock(JournalRepositoryInterface::class);
|
$updateService->shouldReceive('setData')->atLeast()->once();
|
||||||
$userRepos = $this->mock(UserRepositoryInterface::class);
|
$updateService->shouldReceive('update')->atLeast()->once();
|
||||||
|
Preferences::shouldReceive('mark')->atLeast()->once();
|
||||||
|
|
||||||
$repository->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
$repository->shouldReceive('findNull')->atLeast()->once()->andReturn($deposit);
|
||||||
$repository->shouldReceive('update')->once();
|
|
||||||
$repository->shouldReceive('findNull')->once()->andReturn($deposit);
|
|
||||||
$repository->shouldReceive('getTransactionType')->andReturn('Deposit');
|
|
||||||
$repository->shouldReceive('getNoteText')->andReturn('Some note');
|
|
||||||
|
|
||||||
$this->session(['transactions.mass-edit.uri' => 'http://localhost']);
|
$this->session(['transactions.mass-edit.uri' => 'http://localhost']);
|
||||||
|
|
||||||
@@ -280,7 +175,6 @@ class MassControllerTest extends TestCase
|
|||||||
'journals' => [$deposit->id],
|
'journals' => [$deposit->id],
|
||||||
'description' => [$deposit->id => 'Updated salary thing'],
|
'description' => [$deposit->id => 'Updated salary thing'],
|
||||||
'amount' => [$deposit->id => 1600],
|
'amount' => [$deposit->id => 1600],
|
||||||
'amount_currency_id_amount_' . $deposit->id => 1,
|
|
||||||
'date' => [$deposit->id => '2014-07-24'],
|
'date' => [$deposit->id => '2014-07-24'],
|
||||||
'source_name' => [$deposit->id => 'Job'],
|
'source_name' => [$deposit->id => 'Job'],
|
||||||
'destination_id' => [$deposit->id => 1],
|
'destination_id' => [$deposit->id => 1],
|
||||||
|
@@ -159,6 +159,7 @@ abstract class TestCase extends BaseTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'transaction_group_id' => $withdrawal->transaction_group_id,
|
||||||
'transaction_journal_id' => $withdrawal->id,
|
'transaction_journal_id' => $withdrawal->id,
|
||||||
'transaction_type_type' => 'Withdrawal',
|
'transaction_type_type' => 'Withdrawal',
|
||||||
'currency_id' => $euro->id,
|
'currency_id' => $euro->id,
|
||||||
@@ -166,6 +167,7 @@ abstract class TestCase extends BaseTestCase
|
|||||||
'date' => $date,
|
'date' => $date,
|
||||||
'description' => sprintf('I am descr #%d', $this->randomInt()),
|
'description' => sprintf('I am descr #%d', $this->randomInt()),
|
||||||
'source_account_id' => 1,
|
'source_account_id' => 1,
|
||||||
|
'foreign_amount' => null,
|
||||||
'destination_account_id' => $expense->id,
|
'destination_account_id' => $expense->id,
|
||||||
'destination_account_name' => $expense->name,
|
'destination_account_name' => $expense->name,
|
||||||
'currency_name' => $euro->name,
|
'currency_name' => $euro->name,
|
||||||
|
Reference in New Issue
Block a user