mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/4.3.0'
This commit is contained in:
commit
ad1e9c27e9
@ -38,9 +38,14 @@ SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=true
|
||||
SHOW_INCOMPLETE_TRANSLATIONS=false
|
||||
|
||||
CACHE_PREFIX=firefly
|
||||
|
||||
ANALYTICS_ID=
|
||||
SITE_OWNER=mail@example.com
|
||||
|
||||
PUSHER_KEY=
|
||||
PUSHER_SECRET=
|
||||
PUSHER_APP_ID=
|
||||
|
||||
DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
@ -5,14 +5,13 @@ php:
|
||||
|
||||
install:
|
||||
- phpenv config-rm xdebug.ini
|
||||
- composer selfupdate
|
||||
- rm composer.lock
|
||||
- composer update --no-scripts
|
||||
- php artisan clear-compiled
|
||||
- php artisan optimize
|
||||
- php artisan env
|
||||
- ./test.sh -r
|
||||
- php artisan env
|
||||
- cp .env.testing .env
|
||||
- mv storage/database/databasecopy.sqlite storage/database/database.sqlite
|
||||
|
||||
script:
|
||||
- phpunit
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -2,6 +2,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [4.3.0] - 2015-12-26
|
||||
### Added
|
||||
- New method of keeping track of available budget, see issue #489
|
||||
- Support for Spanish
|
||||
- Firefly III now has an extended demo mode. Will expand further in the future.
|
||||
|
||||
|
||||
### Changed
|
||||
- New favicon
|
||||
- Import routine no longer gives transactions a description #483
|
||||
|
||||
|
||||
### Removed
|
||||
- All test data generation code.
|
||||
|
||||
### Fixed
|
||||
- Removed import accounts from search results #478
|
||||
- Redirect after delete will no longer go back to deleted item #477
|
||||
- Cannot math #482
|
||||
- Fixed bug in virtual balance field #479
|
||||
|
||||
## [4.2.2] - 2016-12-18
|
||||
### Added
|
||||
- New budget report (still a bit of a beta)
|
||||
|
12
README.md
12
README.md
@ -1,8 +1,8 @@
|
||||
# Firefly III [](https://secure.php.net/downloads.php#v7.0.4) [](https://packagist.org/packages/grumpydictator/firefly-iii) [](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
|
||||
# Firefly III: A personal finances manager
|
||||
|
||||
[](https://travis-ci.org/JC5/firefly-iii)
|
||||
[](https://secure.php.net/downloads.php#v7.0.4) [](https://packagist.org/packages/grumpydictator/firefly-iii) [](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
|
||||
|
||||
## A personal finances manager
|
||||
[](https://travis-ci.org/JC5/firefly-iii) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)
|
||||
|
||||
[](https://i.nder.be/h2b37243) [](https://i.nder.be/hv70pbwc)
|
||||
|
||||
@ -12,6 +12,10 @@ _(You can click on the images for a better view)_
|
||||
|
||||
"Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money.
|
||||
|
||||
## Try it out!
|
||||
|
||||
Try out Firefly III on the [demo site](https://firefly-iii.nder.be/).
|
||||
|
||||
## Installation
|
||||
|
||||
To install Firefly III, you'll need a web server (preferrably on Linux) and access to the command line. Then, please read the [installation guide](https://firefly-iii.github.io/installation-guide/).
|
||||
@ -31,4 +35,6 @@ Firefly works on the principle that if you know where you're money is going, you
|
||||
|
||||
Firefly is pretty awesome. [You can read more about Firefly III, and its features, on the Github Pages](https://firefly-iii.github.io/).
|
||||
|
||||
If you like Firefly and if it helps you save lots of money, why not send me [a dime for every dollar saved](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA) (this is a joke, although the Paypal form works just fine, try it!)
|
||||
|
||||
If you want to contact me, please open an issue or [email me](mailto:thegrumpydictator@gmail.com).
|
||||
|
@ -50,11 +50,10 @@ class CreateImport extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// find the file
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
$file = $this->argument('file');
|
||||
@ -67,7 +66,6 @@ class CreateImport extends Command
|
||||
return;
|
||||
}
|
||||
|
||||
// try to parse configuration data:
|
||||
$configurationData = json_decode(file_get_contents($configuration));
|
||||
if (is_null($configurationData)) {
|
||||
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
@ -82,21 +80,17 @@ class CreateImport extends Command
|
||||
|
||||
/** @var ImportJobRepositoryInterface $jobRepository */
|
||||
$jobRepository = app(ImportJobRepositoryInterface::class, [$user]);
|
||||
|
||||
$job = $jobRepository->create($type);
|
||||
$job = $jobRepository->create($type);
|
||||
$this->line(sprintf('Created job "%s"...', $job->key));
|
||||
|
||||
// put the file in the proper place:
|
||||
Artisan::call('firefly:encrypt', ['file' => $file, 'key' => $job->key]);
|
||||
$this->line('Stored import data...');
|
||||
|
||||
// store the configuration in the job:
|
||||
$job->configuration = $configurationData;
|
||||
$job->status = 'settings_complete';
|
||||
$job->save();
|
||||
$this->line('Stored configuration...');
|
||||
|
||||
// if user wants to run it, do!
|
||||
if ($this->option('start') === true) {
|
||||
$this->line('The import will start in a moment. This process is not visible...');
|
||||
Log::debug('Go for import!');
|
||||
@ -109,10 +103,10 @@ class CreateImport extends Command
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
|
||||
*/
|
||||
private function validArguments(): bool
|
||||
{
|
||||
// find the file
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
$file = $this->argument('file');
|
||||
|
@ -18,6 +18,7 @@ use FireflyIII\Import\Logging\CommandHandler;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
@ -69,32 +70,15 @@ class Import extends Command
|
||||
$monolog = Log::getMonolog();
|
||||
$handler = new CommandHandler($this);
|
||||
$monolog->pushHandler($handler);
|
||||
$importProcedure = new ImportProcedure;
|
||||
$result = $importProcedure->runImport($job);
|
||||
|
||||
$result = ImportProcedure::runImport($job);
|
||||
|
||||
|
||||
/**
|
||||
* @var int $index
|
||||
* @var TransactionJournal $journal
|
||||
*/
|
||||
foreach ($result as $index => $journal) {
|
||||
if (!is_null($journal->id)) {
|
||||
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
|
||||
continue;
|
||||
}
|
||||
$this->error(sprintf('Could not store line #%d', $index));
|
||||
}
|
||||
|
||||
// display result to user:
|
||||
$this->presentResults($result);
|
||||
$this->line('The import has completed.');
|
||||
|
||||
// get any errors from the importer:
|
||||
$extendedStatus = $job->extended_status;
|
||||
if (isset($extendedStatus['errors']) && count($extendedStatus['errors']) > 0) {
|
||||
$this->line(sprintf('The following %d error(s) occured during the import:', count($extendedStatus['errors'])));
|
||||
foreach ($extendedStatus['errors'] as $error) {
|
||||
$this->error($error);
|
||||
}
|
||||
}
|
||||
$this->presentErrors($job);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -120,4 +104,36 @@ class Import extends Command
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*/
|
||||
private function presentErrors(ImportJob $job)
|
||||
{
|
||||
$extendedStatus = $job->extended_status;
|
||||
if (isset($extendedStatus['errors']) && count($extendedStatus['errors']) > 0) {
|
||||
$this->line(sprintf('The following %d error(s) occured during the import:', count($extendedStatus['errors'])));
|
||||
foreach ($extendedStatus['errors'] as $error) {
|
||||
$this->error($error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $result
|
||||
*/
|
||||
private function presentResults(Collection $result)
|
||||
{
|
||||
/**
|
||||
* @var int $index
|
||||
* @var TransactionJournal $journal
|
||||
*/
|
||||
foreach ($result as $index => $journal) {
|
||||
if (!is_null($journal->id)) {
|
||||
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
|
||||
continue;
|
||||
}
|
||||
$this->error(sprintf('Could not store line #%d', $index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,42 +60,26 @@ class ScanAttachments extends Command
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($attachments as $attachment) {
|
||||
$fileName = $attachment->fileName();
|
||||
|
||||
// try to grab file content:
|
||||
try {
|
||||
$content = $disk->get($fileName);
|
||||
} catch (FileNotFoundException $e) {
|
||||
$this->error(sprintf('Could not find data for attachment #%d', $attachment->id));
|
||||
continue;
|
||||
}
|
||||
// try to decrypt content.
|
||||
try {
|
||||
$decrypted = Crypt::decrypt($content);
|
||||
} catch (DecryptException $e) {
|
||||
$this->error(sprintf('Could not decrypt data of attachment #%d', $attachment->id));
|
||||
continue;
|
||||
}
|
||||
|
||||
// make temp file:
|
||||
$tmpfname = tempnam(sys_get_temp_dir(), 'FireflyIII');
|
||||
|
||||
// store content in temp file:
|
||||
file_put_contents($tmpfname, $decrypted);
|
||||
|
||||
// get md5 and mime
|
||||
$md5 = md5_file($tmpfname);
|
||||
$mime = mime_content_type($tmpfname);
|
||||
|
||||
// update attachment:
|
||||
$md5 = md5_file($tmpfname);
|
||||
$mime = mime_content_type($tmpfname);
|
||||
$attachment->md5 = $md5;
|
||||
$attachment->mime = $mime;
|
||||
$attachment->save();
|
||||
|
||||
|
||||
$this->line(sprintf('Fixed attachment #%d', $attachment->id));
|
||||
|
||||
// find file:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,16 +124,16 @@ class VerifyDatabase extends Command
|
||||
{
|
||||
$set = Budget::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
|
||||
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
|
||||
->groupBy(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email'])
|
||||
->groupBy(['budgets.id', 'budgets.name', 'budgets.encrypted', 'budgets.user_id', 'users.email'])
|
||||
->whereNull('budget_limits.id')
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']);
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'budgets.encrypted', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
/** @var Budget $entry */
|
||||
foreach ($set as $entry) {
|
||||
|
||||
$name = $entry->encrypted ? Crypt::decrypt($entry->name) : $entry->name;
|
||||
$line = sprintf(
|
||||
'Notice: User #%d (%s) has budget #%d ("%s") which has no budget limits.',
|
||||
$entry->user_id, $entry->email, $entry->id, Crypt::decrypt($entry->name)
|
||||
$entry->user_id, $entry->email, $entry->id, $name
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
|
0
app/Console/Kernel.php
Executable file → Normal file
0
app/Console/Kernel.php
Executable file → Normal file
0
app/Exceptions/Handler.php
Executable file → Normal file
0
app/Exceptions/Handler.php
Executable file → Normal file
@ -31,6 +31,8 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
* 0: [
|
||||
* 'label' => 'label of set',
|
||||
* 'type' => bar or line, optional
|
||||
* 'yAxisID' => ID of yAxis, optional, will not be included when unused.
|
||||
* 'fill' => if to fill a line? optional, will not be included when unused.
|
||||
* 'entries' =>
|
||||
* [
|
||||
* 'label-of-entry' => 'value'
|
||||
@ -39,6 +41,8 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
* 1: [
|
||||
* 'label' => 'label of another set',
|
||||
* 'type' => bar or line, optional
|
||||
* 'yAxisID' => ID of yAxis, optional, will not be included when unused.
|
||||
* 'fill' => if to fill a line? optional, will not be included when unused.
|
||||
* 'entries' =>
|
||||
* [
|
||||
* 'label-of-entry' => 'value'
|
||||
@ -64,11 +68,19 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
unset($first, $labels);
|
||||
|
||||
foreach ($data as $set) {
|
||||
$chartData['datasets'][] = [
|
||||
$currentSet = [
|
||||
'label' => $set['label'],
|
||||
'type' => $set['type'] ?? 'line',
|
||||
'data' => array_values($set['entries']),
|
||||
];
|
||||
if (isset($set['yAxisID'])) {
|
||||
$currentSet['yAxisID'] = $set['yAxisID'];
|
||||
}
|
||||
if (isset($set['fill'])) {
|
||||
$currentSet['fill'] = $set['fill'];
|
||||
}
|
||||
|
||||
$chartData['datasets'][] = $currentSet;
|
||||
}
|
||||
|
||||
return $chartData;
|
||||
|
@ -60,6 +60,7 @@ class JournalCollector implements JournalCollectorInterface
|
||||
'transaction_types.type as transaction_type_type',
|
||||
'transaction_journals.bill_id',
|
||||
'bills.name as bill_name',
|
||||
'bills.name_encrypted as bill_name_encrypted',
|
||||
'transactions.id as id',
|
||||
'transactions.amount as transaction_amount',
|
||||
'transactions.description as transaction_description',
|
||||
@ -180,10 +181,12 @@ class JournalCollector implements JournalCollectorInterface
|
||||
$set->each(
|
||||
function (Transaction $transaction) {
|
||||
$transaction->date = new Carbon($transaction->date);
|
||||
$transaction->description = intval($transaction->encrypted) === 1 ? Crypt::decrypt($transaction->description) : $transaction->description;
|
||||
$transaction->bill_name = !is_null($transaction->bill_name) ? Crypt::decrypt($transaction->bill_name) : '';
|
||||
$transaction->description = $transaction->encrypted ? Crypt::decrypt($transaction->description) : $transaction->description;
|
||||
|
||||
if (!is_null($transaction->bill_name)) {
|
||||
$transaction->bill_name = $transaction->bill_name_encrypted ? Crypt::decrypt($transaction->bill_name) : $transaction->bill_name;
|
||||
}
|
||||
|
||||
// optionally decrypted:
|
||||
try {
|
||||
$transaction->opposing_account_name = Crypt::decrypt($transaction->opposing_account_name);
|
||||
} catch (DecryptException $e) {
|
||||
|
@ -26,6 +26,7 @@ use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class BalanceReportHelper
|
||||
@ -59,19 +60,23 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
*/
|
||||
public function getBalanceReport(Collection $accounts, Carbon $start, Carbon $end): Balance
|
||||
{
|
||||
Log::debug('Start of balance report');
|
||||
$balance = new Balance;
|
||||
$header = new BalanceHeader;
|
||||
$limitRepetitions = $this->budgetRepository->getAllBudgetLimitRepetitions($start, $end);
|
||||
foreach ($accounts as $account) {
|
||||
Log::debug(sprintf('Add account %s to headers.', $account->name));
|
||||
$header->addAccount($account);
|
||||
}
|
||||
|
||||
/** @var LimitRepetition $repetition */
|
||||
foreach ($limitRepetitions as $repetition) {
|
||||
$budget = $this->budgetRepository->find($repetition->budget_id);
|
||||
$line = $this->createBalanceLine($budget, $repetition, $accounts);
|
||||
Log::debug(sprintf('Create balance line for budget #%d ("%s") and repetition #%d', $budget->id, $budget->name, $repetition->id));
|
||||
$line = $this->createBalanceLine($budget, $repetition, $accounts);
|
||||
$balance->addBalanceLine($line);
|
||||
}
|
||||
Log::debug('Create rest of the things.');
|
||||
$noBudgetLine = $this->createNoBudgetLine($accounts, $start, $end);
|
||||
$coveredByTagLine = $this->createTagsBalanceLine($accounts, $start, $end);
|
||||
$leftUnbalancedLine = $this->createLeftUnbalancedLine($noBudgetLine, $coveredByTagLine);
|
||||
@ -81,9 +86,12 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
$balance->addBalanceLine($leftUnbalancedLine);
|
||||
$balance->setBalanceHeader($header);
|
||||
|
||||
Log::debug('Clear unused budgets.');
|
||||
// remove budgets without expenses from balance lines:
|
||||
$balance = $this->removeUnusedBudgets($balance);
|
||||
|
||||
Log::debug('Return report.');
|
||||
|
||||
return $balance;
|
||||
}
|
||||
|
||||
|
@ -124,17 +124,24 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function destroy(ARI $repository, Account $account)
|
||||
{
|
||||
$type = $account->accountType->type;
|
||||
$typeName = config('firefly.shortNamesByFullName.' . $type);
|
||||
$name = $account->name;
|
||||
$moveTo = $repository->find(intval(Input::get('move_account_before_delete')));
|
||||
$type = $account->accountType->type;
|
||||
$typeName = config('firefly.shortNamesByFullName.' . $type);
|
||||
$name = $account->name;
|
||||
$accountId = $account->id;
|
||||
$moveTo = $repository->find(intval(Input::get('move_account_before_delete')));
|
||||
|
||||
$repository->destroy($account, $moveTo);
|
||||
|
||||
Session::flash('success', strval(trans('firefly.' . $typeName . '_deleted', ['name' => $name])));
|
||||
Preferences::mark();
|
||||
|
||||
return redirect(session('accounts.delete.url'));
|
||||
$uri = session('accounts.delete.url');
|
||||
if (!(strpos($uri, sprintf('accounts/show/%s', $accountId)) === false)) {
|
||||
// uri would point back to account
|
||||
$uri = route('accounts.index', [$typeName]);
|
||||
}
|
||||
|
||||
return redirect($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -192,8 +199,7 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function index(ARI $repository, string $what)
|
||||
{
|
||||
$what = $what ?? 'asset';
|
||||
|
||||
$what = $what ?? 'asset';
|
||||
$subTitle = trans('firefly.' . $what . '_accounts');
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$types = config('firefly.accountTypesByIdentifier.' . $what);
|
||||
@ -214,6 +220,7 @@ class AccountController extends Controller
|
||||
$account->lastActivityDate = $this->isInArray($activities, $account->id);
|
||||
$account->startBalance = $this->isInArray($startBalances, $account->id);
|
||||
$account->endBalance = $this->isInArray($endBalances, $account->id);
|
||||
$account->difference = bcsub($account->endBalance, $account->startBalance);
|
||||
}
|
||||
);
|
||||
|
||||
@ -235,12 +242,12 @@ class AccountController extends Controller
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$subTitle = $account->name;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
|
||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$chartUri = route('chart.account.single', [$account->id]);
|
||||
|
||||
// grab those journals:
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->setLimit($pageSize)->setPage($page);
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
@ -379,7 +386,7 @@ class AccountController extends Controller
|
||||
return $array[$entryId];
|
||||
}
|
||||
|
||||
return '';
|
||||
return '0';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,16 +95,12 @@ class AttachmentController extends Controller
|
||||
* @throws FireflyException
|
||||
*
|
||||
*/
|
||||
public function download(Attachment $attachment)
|
||||
public function download(AttachmentRepositoryInterface $repository, Attachment $attachment)
|
||||
{
|
||||
// create a disk.
|
||||
$disk = Storage::disk('upload');
|
||||
$file = $attachment->fileName();
|
||||
|
||||
if ($disk->exists($file)) {
|
||||
|
||||
if ($repository->exists($attachment)) {
|
||||
$content = $repository->getContent($attachment);
|
||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||
$content = Crypt::decrypt($disk->get($file));
|
||||
|
||||
|
||||
Log::debug('Send file to user', ['file' => $quoted, 'size' => strlen($content)]);
|
||||
|
||||
@ -118,8 +114,8 @@ class AttachmentController extends Controller
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', strlen($content));
|
||||
|
||||
}
|
||||
|
||||
throw new FireflyException('Could not find the indicated attachment. The file is no longer there.');
|
||||
}
|
||||
|
||||
|
37
app/Http/Controllers/Auth/ForgotPasswordController.php
Executable file → Normal file
37
app/Http/Controllers/Auth/ForgotPasswordController.php
Executable file → Normal file
@ -13,7 +13,9 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Class ForgotPasswordController
|
||||
@ -33,4 +35,39 @@ class ForgotPasswordController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a reset link to the given user.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function sendResetLinkEmail(Request $request)
|
||||
{
|
||||
$this->validate($request, ['email' => 'required|email']);
|
||||
|
||||
// verify if the user is not a demo user. If so, we give him back an error.
|
||||
$user = User::where('email', $request->get('email'))->first();
|
||||
if (!is_null($user) && $user->hasRole('demo')) {
|
||||
return back()->withErrors(
|
||||
['email' => trans('firefly.cannot_reset_demo_user')]
|
||||
);
|
||||
}
|
||||
|
||||
$response = $this->broker()->sendResetLink(
|
||||
$request->only('email')
|
||||
);
|
||||
|
||||
if ($response === Password::RESET_LINK_SENT) {
|
||||
return back()->with('status', trans($response));
|
||||
}
|
||||
|
||||
// If an error was returned by the password broker, we will get this message
|
||||
// translated so we can notify a user of the problem. We'll redirect back
|
||||
// to where the users came from so they can attempt this process again.
|
||||
return back()->withErrors(
|
||||
['email' => trans($response)]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
4
app/Http/Controllers/Auth/LoginController.php
Executable file → Normal file
4
app/Http/Controllers/Auth/LoginController.php
Executable file → Normal file
@ -53,9 +53,9 @@ class LoginController extends Controller
|
||||
/**
|
||||
* Handle a login request to the application.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
|
@ -26,8 +26,8 @@ use Illuminate\Support\Facades\Password;
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
* @method getEmailSubject()
|
||||
* @method getSendResetLinkEmailSuccessResponse()
|
||||
* @method getSendResetLinkEmailFailureResponse()
|
||||
* @method getSendResetLinkEmailSuccessResponse(string $response)
|
||||
* @method getSendResetLinkEmailFailureResponse(string $response)
|
||||
*/
|
||||
class PasswordController extends Controller
|
||||
{
|
||||
|
3
app/Http/Controllers/Auth/RegisterController.php
Executable file → Normal file
3
app/Http/Controllers/Auth/RegisterController.php
Executable file → Normal file
@ -22,11 +22,8 @@ use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Mail\Message;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Session;
|
||||
use Swift_TransportException;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
|
0
app/Http/Controllers/Auth/ResetPasswordController.php
Executable file → Normal file
0
app/Http/Controllers/Auth/ResetPasswordController.php
Executable file → Normal file
@ -99,13 +99,20 @@ class BillController extends Controller
|
||||
*/
|
||||
public function destroy(BillRepositoryInterface $repository, Bill $bill)
|
||||
{
|
||||
$name = $bill->name;
|
||||
$name = $bill->name;
|
||||
$billId = $bill->id;
|
||||
$repository->destroy($bill);
|
||||
|
||||
Session::flash('success', strval(trans('firefly.deleted_bill', ['name' => $name])));
|
||||
Preferences::mark();
|
||||
|
||||
return redirect(session('bills.delete.url'));
|
||||
$uri = session('bills.delete.url');
|
||||
if (!(strpos($uri, sprintf('bills/show/%s', $billId)) === false)) {
|
||||
// uri would point back to bill
|
||||
$uri = route('bills.index');
|
||||
}
|
||||
|
||||
return redirect($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,10 +15,10 @@ namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Amount;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
||||
use FireflyIII\Http\Requests\BudgetFormRequest;
|
||||
use FireflyIII\Http\Requests\BudgetIncomeRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
@ -26,8 +26,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Input;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
@ -42,6 +40,9 @@ use View;
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
|
||||
/** @var BudgetRepositoryInterface */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -55,6 +56,7 @@ class BudgetController extends Controller
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.budgets'));
|
||||
View::share('mainTitleIcon', 'fa-tasks');
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -73,21 +75,15 @@ class BudgetController extends Controller
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', Carbon::now()->startOfMonth());
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Carbon::now()->endOfMonth());
|
||||
$viewRange = Preferences::get('viewRange', '1M')->data;
|
||||
|
||||
// is custom view range?
|
||||
if (session('is_custom_range') === true) {
|
||||
$viewRange = 'custom';
|
||||
}
|
||||
|
||||
$end = session('end', Carbon::now()->endOfMonth());
|
||||
$viewRange = Preferences::get('viewRange', '1M')->data;
|
||||
$limitRepetition = $repository->updateLimitAmount($budget, $start, $end, $viewRange, $amount);
|
||||
if ($amount == 0) {
|
||||
$limitRepetition = null;
|
||||
}
|
||||
Preferences::mark();
|
||||
|
||||
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]);
|
||||
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0, 'amount' => $amount]);
|
||||
|
||||
}
|
||||
|
||||
@ -134,15 +130,21 @@ class BudgetController extends Controller
|
||||
public function destroy(Budget $budget, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
$name = $budget->name;
|
||||
$name = $budget->name;
|
||||
$budgetId = $budget->id;
|
||||
$repository->destroy($budget);
|
||||
|
||||
|
||||
Session::flash('success', strval(trans('firefly.deleted_budget', ['name' => e($name)])));
|
||||
Preferences::mark();
|
||||
|
||||
$uri = session('budgets.delete.url');
|
||||
if (!(strpos($uri, sprintf('budgets/show/%s', $budgetId)) === false)) {
|
||||
// uri would point back to budget
|
||||
$uri = route('budgets.index');
|
||||
}
|
||||
|
||||
return redirect(session('budgets.delete.url'));
|
||||
return redirect($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,82 +169,27 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
* @param AccountRepositoryInterface $accountRepository
|
||||
*
|
||||
* @return View
|
||||
*
|
||||
*/
|
||||
public function index(BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository)
|
||||
public function index()
|
||||
{
|
||||
$repository->cleanupBudgets();
|
||||
$this->repository->cleanupBudgets();
|
||||
|
||||
$budgets = $repository->getActiveBudgets();
|
||||
$inactive = $repository->getInactiveBudgets();
|
||||
$spent = '0';
|
||||
$budgeted = '0';
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$repeatFreq = Config::get('firefly.range_to_repeat_freq.' . $range);
|
||||
|
||||
if (session('is_custom_range') === true) {
|
||||
$repeatFreq = 'custom';
|
||||
}
|
||||
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', new Carbon);
|
||||
/** @var Carbon $end */
|
||||
$budgets = $this->repository->getActiveBudgets();
|
||||
$inactive = $this->repository->getInactiveBudgets();
|
||||
$start = session('start', new Carbon);
|
||||
$end = session('end', new Carbon);
|
||||
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
|
||||
$budgetIncomeTotal = Preferences::get($key, 1000)->data;
|
||||
$period = Navigation::periodShow($start, $range);
|
||||
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
|
||||
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
|
||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
||||
$startAsString = $start->format('Y-m-d');
|
||||
$endAsString = $end->format('Y-m-d');
|
||||
Log::debug('Now at /budgets');
|
||||
|
||||
// loop the budgets:
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
Log::debug(sprintf('Now at budget #%d ("%s")', $budget->id, $budget->name));
|
||||
$budget->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end);
|
||||
$allRepetitions = $repository->getAllBudgetLimitRepetitions($start, $end);
|
||||
$otherRepetitions = new Collection;
|
||||
|
||||
/** @var LimitRepetition $repetition */
|
||||
foreach ($allRepetitions as $repetition) {
|
||||
if ($repetition->budget_id == $budget->id) {
|
||||
if ($repetition->budgetLimit->repeat_freq == $repeatFreq
|
||||
&& $repetition->startdate->format('Y-m-d') == $startAsString
|
||||
&& $repetition->enddate->format('Y-m-d') == $endAsString
|
||||
) {
|
||||
// do something
|
||||
$budget->currentRep = $repetition;
|
||||
continue;
|
||||
}
|
||||
$otherRepetitions->push($repetition);
|
||||
}
|
||||
}
|
||||
$budget->otherRepetitions = $otherRepetitions;
|
||||
|
||||
if (!is_null($budget->currentRep) && !is_null($budget->currentRep->id)) {
|
||||
$budgeted = bcadd($budgeted, $budget->currentRep->amount);
|
||||
}
|
||||
$spent = bcadd($spent, $budget->spent);
|
||||
|
||||
}
|
||||
|
||||
|
||||
$defaultCurrency = Amount::getDefaultCurrency();
|
||||
$budgetInformation = $this->collectBudgetInformation($budgets, $start, $end);
|
||||
$defaultCurrency = Amount::getDefaultCurrency();
|
||||
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
|
||||
$spent = array_sum(array_column($budgetInformation, 'spent'));
|
||||
$budgeted = array_sum(array_column($budgetInformation, 'budgeted'));
|
||||
|
||||
return view(
|
||||
'budgets.index', compact(
|
||||
'periodStart', 'periodEnd',
|
||||
'period', 'range', 'budgetIncomeTotal',
|
||||
'defaultCurrency', 'inactive', 'budgets',
|
||||
'spent', 'budgeted'
|
||||
)
|
||||
'budgets.index',
|
||||
compact('available', 'periodStart', 'periodEnd', 'budgetInformation', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted')
|
||||
);
|
||||
}
|
||||
|
||||
@ -274,16 +221,14 @@ class BudgetController extends Controller
|
||||
/**
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postUpdateIncome()
|
||||
public function postUpdateIncome(BudgetIncomeRequest $request)
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
/** @var Carbon $date */
|
||||
$date = session('start', new Carbon);
|
||||
$start = Navigation::startOfPeriod($date, $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
|
||||
$start = session('start', new Carbon);
|
||||
$end = session('end', new Carbon);
|
||||
$defaultCurrency = Amount::getDefaultCurrency();
|
||||
$amount = $request->get('amount');
|
||||
|
||||
Preferences::set($key, intval(Input::get('amount')));
|
||||
$this->repository->setAvailableBudget($defaultCurrency, $start, $end, $amount);
|
||||
Preferences::mark();
|
||||
|
||||
return redirect(route('budgets.index'));
|
||||
@ -424,19 +369,57 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function updateIncome()
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$format = strval(trans('config.month_and_day'));
|
||||
$start = session('start', new Carbon);
|
||||
$end = session('end', new Carbon);
|
||||
$defaultCurrency = Amount::getDefaultCurrency();
|
||||
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
|
||||
|
||||
/** @var Carbon $date */
|
||||
$date = session('start', new Carbon);
|
||||
$start = Navigation::startOfPeriod($date, $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
|
||||
$amount = Preferences::get($key, 1000);
|
||||
$displayStart = $start->formatLocalized($format);
|
||||
$displayEnd = $end->formatLocalized($format);
|
||||
|
||||
return view('budgets.income', compact('amount', 'displayStart', 'displayEnd'));
|
||||
return view('budgets.income', compact('available', 'start', 'end'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function collectBudgetInformation(Collection $budgets, Carbon $start, Carbon $end): array
|
||||
{
|
||||
// get account information
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
||||
$return = [];
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
$budgetId = $budget->id;
|
||||
$return[$budgetId] = [
|
||||
'spent' => $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end),
|
||||
'budgeted' => '0',
|
||||
'currentRep' => false,
|
||||
];
|
||||
$allRepetitions = $this->repository->getAllBudgetLimitRepetitions($start, $end);
|
||||
$otherRepetitions = new Collection;
|
||||
|
||||
// get all the limit repetitions relevant between start and end and examine them:
|
||||
/** @var LimitRepetition $repetition */
|
||||
foreach ($allRepetitions as $repetition) {
|
||||
if ($repetition->budget_id == $budget->id) {
|
||||
if ($repetition->startdate->isSameDay($start) && $repetition->enddate->isSameDay($end)
|
||||
) {
|
||||
$return[$budgetId]['currentRep'] = $repetition;
|
||||
$return[$budgetId]['budgeted'] = $repetition->amount;
|
||||
continue;
|
||||
}
|
||||
// otherwise it's just one of the many relevant repetitions:
|
||||
$otherRepetitions->push($repetition);
|
||||
}
|
||||
}
|
||||
$return[$budgetId]['otherRepetitions'] = $otherRepetitions;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -98,13 +98,20 @@ class CategoryController extends Controller
|
||||
public function destroy(CRI $repository, Category $category)
|
||||
{
|
||||
|
||||
$name = $category->name;
|
||||
$name = $category->name;
|
||||
$categoryId = $category->id;
|
||||
$repository->destroy($category);
|
||||
|
||||
Session::flash('success', strval(trans('firefly.deleted_category', ['name' => e($name)])));
|
||||
Preferences::mark();
|
||||
|
||||
return redirect(session('categories.delete.url'));
|
||||
$uri = session('categories.delete.url');
|
||||
if (!(strpos($uri, sprintf('categories/show/%s', $categoryId)) === false)) {
|
||||
// uri would point back to category
|
||||
$uri = route('categories.index');
|
||||
}
|
||||
|
||||
return redirect($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -262,7 +269,6 @@ class CategoryController extends Controller
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('categories/show/' . $category->id . '/' . $date);
|
||||
|
||||
|
||||
return view('categories.show-by-date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon'));
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
// for no budget:
|
||||
$row = $this->spentInPeriodWithout($start, $end);
|
||||
if (bccomp($row['spent'], '0') !== 0 || bccomp($row['repetition_left'], '0') !== 0) {
|
||||
if (bccomp($row['repetition_overspent'], '0') !== 0) {
|
||||
$chartData[0]['entries'][$row['name']] = bcmul($row['spent'], '-1');
|
||||
$chartData[1]['entries'][$row['name']] = $row['repetition_left'];
|
||||
$chartData[2]['entries'][$row['name']] = bcmul($row['repetition_overspent'], '-1');
|
||||
@ -284,8 +284,8 @@ class BudgetController extends Controller
|
||||
foreach (array_keys($periods) as $period) {
|
||||
$label = $periods[$period];
|
||||
$spent = isset($entries[$budget->id]['entries'][$period]) ? $entries[$budget->id]['entries'][$period] : '0';
|
||||
$limit = isset($entries[$period]) ? $budgeted[$period] : 0;
|
||||
$chartData[0]['entries'][$label] = bcmul($spent, '-1');
|
||||
$limit = isset($budgeted[$period]) ? $budgeted[$period] : 0;
|
||||
$chartData[0]['entries'][$label] = round(bcmul($spent, '-1'), 2);
|
||||
$chartData[1]['entries'][$label] = $limit;
|
||||
|
||||
}
|
||||
@ -386,7 +386,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
$amount = $repetition->amount;
|
||||
$left = bccomp(bcadd($amount, $expenses), '0') < 1 ? '0' : bcadd($amount, $expenses);
|
||||
$spent = bccomp(bcadd($amount, $expenses), '0') < 1 ? bcmul($amount, '-1') : $expenses;
|
||||
$spent = $expenses;
|
||||
$overspent = bccomp(bcadd($amount, $expenses), '0') < 1 ? bcadd($amount, $expenses) : '0';
|
||||
$return[] = [
|
||||
'name' => $name,
|
||||
@ -454,8 +454,8 @@ class BudgetController extends Controller
|
||||
$array = [
|
||||
'name' => strval(trans('firefly.no_budget')),
|
||||
'repetition_left' => '0',
|
||||
'repetition_overspent' => '0',
|
||||
'spent' => $sum,
|
||||
'repetition_overspent' => $sum,
|
||||
'spent' => '0',
|
||||
];
|
||||
|
||||
return $array;
|
||||
|
@ -20,16 +20,17 @@ use FireflyIII\Generator\Report\Category\MonthReportGenerator;
|
||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Response;
|
||||
|
||||
|
||||
/**
|
||||
* Separate controller because many helper functions are shared.
|
||||
*
|
||||
@ -83,6 +84,7 @@ class BudgetReportController extends Controller
|
||||
$cache->addProperty($budgets);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($others);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
@ -139,6 +141,7 @@ class BudgetReportController extends Controller
|
||||
$cache->addProperty($budgets);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($others);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
@ -195,21 +198,39 @@ class BudgetReportController extends Controller
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
|
||||
/** @var BudgetRepositoryInterface $repository */
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = Navigation::preferredEndOfPeriod($start, $end);
|
||||
$chartData = [];
|
||||
$currentStart = clone $start;
|
||||
$limits = $repository->getAllBudgetLimitRepetitions($start, $end); // also for ALL budgets.
|
||||
|
||||
// prep chart data:
|
||||
foreach ($budgets as $budget) {
|
||||
$chartData[$budget->id] = [
|
||||
'label' => $budget->name,
|
||||
$chartData[$budget->id] = [
|
||||
'label' => strval(trans('firefly.spent_in_specific_budget', ['budget' => $budget->name])),
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 'y-axis-0',
|
||||
'entries' => [],
|
||||
];
|
||||
$chartData[$budget->id . '-sum'] = [
|
||||
'label' => strval(trans('firefly.sum_of_expenses_in_budget', ['budget' => $budget->name])),
|
||||
'type' => 'line',
|
||||
'fill' => false,
|
||||
'yAxisID' => 'y-axis-1',
|
||||
'entries' => [],
|
||||
];
|
||||
$chartData[$budget->id . '-left'] = [
|
||||
'label' => strval(trans('firefly.left_in_budget_limit', ['budget' => $budget->name])),
|
||||
'type' => 'bar',
|
||||
'fill' => false,
|
||||
'yAxisID' => 'y-axis-0',
|
||||
'entries' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$sumOfExpenses = [];
|
||||
$leftOfLimits = [];
|
||||
while ($currentStart < $end) {
|
||||
$currentEnd = clone $currentStart;
|
||||
$currentEnd = $currentEnd->$function();
|
||||
@ -218,7 +239,20 @@ class BudgetReportController extends Controller
|
||||
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
$chartData[$budget->id]['entries'][$label] = $expenses[$budget->id] ?? '0';
|
||||
$currentExpenses = $expenses[$budget->id] ?? '0';
|
||||
$sumOfExpenses[$budget->id] = $sumOfExpenses[$budget->id] ?? '0';
|
||||
$sumOfExpenses[$budget->id] = bcadd($currentExpenses, $sumOfExpenses[$budget->id]);
|
||||
$chartData[$budget->id]['entries'][$label] = round(bcmul($currentExpenses, '-1'), 2);
|
||||
$chartData[$budget->id . '-sum']['entries'][$label] = round(bcmul($sumOfExpenses[$budget->id], '-1'), 2);
|
||||
|
||||
$limit = $this->filterLimits($limits, $budget, $currentStart);
|
||||
if (!is_null($limit->id)) {
|
||||
$leftOfLimits[$limit->id] = $leftOfLimits[$limit->id] ?? strval($limit->amount);
|
||||
$leftOfLimits[$limit->id] = bcadd($leftOfLimits[$limit->id], $currentExpenses);
|
||||
$chartData[$budget->id . '-left']['entries'][$label] = round($leftOfLimits[$limit->id], 2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
$currentStart = clone $currentEnd;
|
||||
$currentStart->addDay();
|
||||
@ -230,6 +264,44 @@ class BudgetReportController extends Controller
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $limits
|
||||
* @param $budget
|
||||
* @param $currentStart
|
||||
*
|
||||
* @return LimitRepetition
|
||||
*/
|
||||
private function filterLimits(Collection $limits, Budget $budget, Carbon $date): LimitRepetition
|
||||
{
|
||||
Log::debug(sprintf('Start of filterLimits with %d limits.', $limits->count()));
|
||||
$filtered = $limits->filter(
|
||||
function (LimitRepetition $limit) use ($budget, $date) {
|
||||
if ($limit->budget_id !== $budget->id) {
|
||||
Log::debug(sprintf('LimitRepetition has budget #%d but expecting #%d', $limit->budget_id, $budget->id));
|
||||
|
||||
return false;
|
||||
}
|
||||
if ($date < $limit->startdate || $date > $limit->enddate) {
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Date %s is not between %s and %s',
|
||||
$date->format('Y-m-d'), $limit->startdate->format('Y-m-d'), $limit->enddate->format('Y-m-d')
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $limit;
|
||||
}
|
||||
);
|
||||
if ($filtered->count() === 1) {
|
||||
return $filtered->first();
|
||||
}
|
||||
|
||||
return new LimitRepetition;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
|
@ -83,6 +83,7 @@ class CategoryReportController extends Controller
|
||||
$cache->addProperty($categories);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($others);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
@ -138,6 +139,7 @@ class CategoryReportController extends Controller
|
||||
$cache->addProperty($accounts);
|
||||
$cache->addProperty($categories);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($others);
|
||||
$cache->addProperty($end);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
@ -194,6 +196,7 @@ class CategoryReportController extends Controller
|
||||
$cache->addProperty($categories);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($others);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
@ -250,6 +253,7 @@ class CategoryReportController extends Controller
|
||||
$cache->addProperty($categories);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($others);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
@ -314,14 +318,33 @@ class CategoryReportController extends Controller
|
||||
$chartData[$category->id . '-in'] = [
|
||||
'label' => $category->name . ' (' . strtolower(strval(trans('firefly.income'))) . ')',
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 'y-axis-0',
|
||||
'entries' => [],
|
||||
];
|
||||
$chartData[$category->id . '-out'] = [
|
||||
'label' => $category->name . ' (' . strtolower(strval(trans('firefly.expenses'))) . ')',
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 'y-axis-0',
|
||||
'entries' => [],
|
||||
];
|
||||
// total in, total out:
|
||||
$chartData[$category->id . '-total-in'] = [
|
||||
'label' => $category->name . ' (' . strtolower(strval(trans('firefly.sum_of_income'))) . ')',
|
||||
'type' => 'line',
|
||||
'fill' => false,
|
||||
'yAxisID' => 'y-axis-1',
|
||||
'entries' => [],
|
||||
];
|
||||
$chartData[$category->id . '-total-out'] = [
|
||||
'label' => $category->name . ' (' . strtolower(strval(trans('firefly.sum_of_expenses'))) . ')',
|
||||
'type' => 'line',
|
||||
'fill' => false,
|
||||
'yAxisID' => 'y-axis-1',
|
||||
'entries' => [],
|
||||
];
|
||||
}
|
||||
$sumOfIncome = [];
|
||||
$sumOfExpense = [];
|
||||
|
||||
while ($currentStart < $end) {
|
||||
$currentEnd = clone $currentStart;
|
||||
@ -332,17 +355,40 @@ class CategoryReportController extends Controller
|
||||
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
$labelIn = $category->id . '-in';
|
||||
$labelOut = $category->id . '-out';
|
||||
// get sum, and get label:
|
||||
$chartData[$labelIn]['entries'][$label] = $income[$category->id] ?? '0';
|
||||
$chartData[$labelOut]['entries'][$label] = $expenses[$category->id] ?? '0';
|
||||
$labelIn = $category->id . '-in';
|
||||
$labelOut = $category->id . '-out';
|
||||
$labelSumIn = $category->id . '-total-in';
|
||||
$labelSumOut = $category->id . '-total-out';
|
||||
$currentIncome = $income[$category->id] ?? '0';
|
||||
$currentExpense = $expenses[$category->id] ?? '0';
|
||||
|
||||
|
||||
// add to sum:
|
||||
$sumOfIncome[$category->id] = $sumOfIncome[$category->id] ?? '0';
|
||||
$sumOfExpense[$category->id] = $sumOfExpense[$category->id] ?? '0';
|
||||
$sumOfIncome[$category->id] = bcadd($sumOfIncome[$category->id], $currentIncome);
|
||||
$sumOfExpense[$category->id] = bcadd($sumOfExpense[$category->id], $currentExpense);
|
||||
|
||||
// add to chart:
|
||||
$chartData[$labelIn]['entries'][$label] = $currentIncome;
|
||||
$chartData[$labelOut]['entries'][$label] = $currentExpense;
|
||||
$chartData[$labelSumIn]['entries'][$label] = $sumOfIncome[$category->id];
|
||||
$chartData[$labelSumOut]['entries'][$label] = $sumOfExpense[$category->id];
|
||||
}
|
||||
$currentStart = clone $currentEnd;
|
||||
$currentStart->addDay();
|
||||
}
|
||||
|
||||
$data = $this->generator->multiSet($chartData);
|
||||
// remove all empty entries to prevent cluttering:
|
||||
$newSet = [];
|
||||
foreach ($chartData as $key => $entry) {
|
||||
if (!array_sum($entry['entries']) == 0) {
|
||||
$newSet[$key] = $chartData[$key];
|
||||
}
|
||||
}
|
||||
if (count($newSet) === 0) {
|
||||
$newSet = $chartData;
|
||||
}
|
||||
$data = $this->generator->multiSet($newSet);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
6
app/Http/Controllers/Controller.php
Executable file → Normal file
6
app/Http/Controllers/Controller.php
Executable file → Normal file
@ -23,6 +23,7 @@ use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Session;
|
||||
use View;
|
||||
use FireflyConfig;
|
||||
|
||||
/**
|
||||
* Class Controller
|
||||
@ -49,7 +50,10 @@ class Controller extends BaseController
|
||||
View::share('hideCategories', false);
|
||||
View::share('hideBills', false);
|
||||
View::share('hideTags', false);
|
||||
|
||||
$isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
|
||||
View::share('IS_DEMO_SITE', $isDemoSite);
|
||||
View::share('DEMO_USERNAME', env('DEMO_USERNAME',''));
|
||||
View::share('DEMO_PASSWORD', env('DEMO_PASSWORD',''));
|
||||
|
||||
// translations:
|
||||
|
||||
|
@ -22,6 +22,7 @@ use FireflyIII\Http\Requests\ExportFormRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface;
|
||||
use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface as EJRI;
|
||||
use Preferences;
|
||||
use Response;
|
||||
@ -59,21 +60,22 @@ class ExportController extends Controller
|
||||
* @return \Symfony\Component\HttpFoundation\Response|\Illuminate\Contracts\Routing\ResponseFactory
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function download(ExportJob $job)
|
||||
public function download(ExportJobRepositoryInterface $repository, ExportJob $job)
|
||||
{
|
||||
$disk = Storage::disk('export');
|
||||
$file = $job->key . '.zip';
|
||||
$date = date('Y-m-d \a\t H-i-s');
|
||||
$name = 'Export job on ' . $date . '.zip';
|
||||
$quoted = sprintf('"%s"', addcslashes($name, '"\\'));
|
||||
|
||||
if (!$disk->exists($file)) {
|
||||
if (!$repository->exists($job)) {
|
||||
throw new FireflyException('Against all expectations, zip file "' . $file . '" does not exist.');
|
||||
}
|
||||
$content = $repository->getContent($job);
|
||||
|
||||
|
||||
$job->change('export_downloaded');
|
||||
|
||||
return response($disk->get($file), 200)
|
||||
return response($content, 200)
|
||||
->header('Content-Description', 'File Transfer')
|
||||
->header('Content-Type', 'application/octet-stream')
|
||||
->header('Content-Disposition', 'attachment; filename=' . $quoted)
|
||||
@ -82,7 +84,7 @@ class ExportController extends Controller
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', $disk->size($file));
|
||||
->header('Content-Length', strlen($content));
|
||||
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@ class HomeController extends Controller
|
||||
// a possible problem with the budgets.
|
||||
if ($label === strval(trans('firefly.everything')) || $label === strval(trans('firefly.customRange'))) {
|
||||
$isCustomRange = true;
|
||||
//Preferences::set('viewRange', 'custom');
|
||||
Log::debug('Range is now marked as "custom".');
|
||||
}
|
||||
|
||||
@ -107,7 +108,7 @@ class HomeController extends Controller
|
||||
$journal->save();
|
||||
}
|
||||
}
|
||||
|
||||
Session::forget(['start', 'end', 'viewRange', 'range', 'is_custom_range']);
|
||||
|
||||
Session::clear();
|
||||
Artisan::call('cache:clear');
|
||||
|
@ -15,7 +15,7 @@ namespace FireflyIII\Http\Controllers;
|
||||
use Crypt;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Requests\ImportUploadRequest;
|
||||
use FireflyIII\Import\ImportProcedure;
|
||||
use FireflyIII\Import\ImportProcedureInterface;
|
||||
use FireflyIII\Import\Setup\SetupInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
@ -315,13 +315,13 @@ class ImportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
* @param ImportProcedureInterface $importProcedure
|
||||
* @param ImportJob $job
|
||||
*/
|
||||
public function start(ImportJob $job)
|
||||
public function start(ImportProcedureInterface $importProcedure, ImportJob $job)
|
||||
{
|
||||
set_time_limit(0);
|
||||
if ($job->status == 'settings_complete') {
|
||||
$importProcedure = new ImportProcedure;
|
||||
$importProcedure->runImport($job);
|
||||
}
|
||||
}
|
||||
@ -334,7 +334,7 @@ class ImportController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||
*/
|
||||
public function status(ImportJob $job)
|
||||
{
|
||||
{ //
|
||||
Log::debug('Now in status()', ['job' => $job->key]);
|
||||
if (!$this->jobInCorrectStep($job, 'status')) {
|
||||
return $this->redirectToCorrectStep($job);
|
||||
|
@ -24,6 +24,7 @@ use Illuminate\Support\Collection;
|
||||
use Input;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use Steam;
|
||||
use URL;
|
||||
@ -149,13 +150,18 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function destroy(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
|
||||
|
||||
Session::flash('success', strval(trans('firefly.deleted_piggy_bank', ['name' => e($piggyBank->name)])));
|
||||
Preferences::mark();
|
||||
$piggyBankId = $piggyBank->id;
|
||||
$repository->destroy($piggyBank);
|
||||
|
||||
return redirect(session('piggy-banks.delete.url'));
|
||||
$uri = session('piggy-banks.delete.url');
|
||||
if (!(strpos($uri, sprintf('piggy-banks/show/%s', $piggyBankId)) === false)) {
|
||||
// uri would point back to piggy bank
|
||||
$uri = route('piggy-banks.index');
|
||||
}
|
||||
|
||||
return redirect($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,6 +249,8 @@ class PiggyBankController extends Controller
|
||||
|
||||
/**
|
||||
* @param PiggyBankRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function order(PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
@ -257,6 +265,8 @@ class PiggyBankController extends Controller
|
||||
$repository->setOrder(intval($id), ($order + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return Response::json(['result' => 'ok']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,8 +133,8 @@ class ReportController extends Controller
|
||||
|
||||
$budget->name = strval(trans('firefly.leftUnbalanced'));
|
||||
$journals = $journals->filter(
|
||||
function (TransactionJournal $journal) {
|
||||
$tags = $journal->tags()->where('tagMode', 'balancingAct')->count();
|
||||
function (Transaction $transaction) {
|
||||
$tags = $transaction->transactionJournal->tags()->where('tagMode', 'balancingAct')->count();
|
||||
if ($tags === 0) {
|
||||
return true;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ class PreferencesController extends Controller
|
||||
|
||||
// custom fiscal year
|
||||
$customFiscalYear = intval($request->get('customFiscalYear')) === 1;
|
||||
$fiscalYearStart = date('m-d', strtotime($request->get('fiscalYearStart')));
|
||||
$fiscalYearStart = date('m-d', strtotime(strval($request->get('fiscalYearStart'))));
|
||||
Preferences::set('customFiscalYear', $customFiscalYear);
|
||||
Preferences::set('fiscalYearStart', $fiscalYearStart);
|
||||
|
||||
@ -166,13 +166,17 @@ class PreferencesController extends Controller
|
||||
Preferences::set('transactionPageSize', 50);
|
||||
}
|
||||
|
||||
// two factor auth
|
||||
$twoFactorAuthEnabled = intval($request->get('twoFactorAuthEnabled'));
|
||||
$hasTwoFactorAuthSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
|
||||
$twoFactorAuthEnabled = false;
|
||||
$hasTwoFactorAuthSecret = false;
|
||||
if (!auth()->user()->hasRole('demo')) {
|
||||
// two factor auth
|
||||
$twoFactorAuthEnabled = intval($request->get('twoFactorAuthEnabled'));
|
||||
$hasTwoFactorAuthSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
|
||||
|
||||
// If we already have a secret, just set the two factor auth enabled to 1, and let the user continue with the existing secret.
|
||||
if ($hasTwoFactorAuthSecret) {
|
||||
Preferences::set('twoFactorAuthEnabled', $twoFactorAuthEnabled);
|
||||
// If we already have a secret, just set the two factor auth enabled to 1, and let the user continue with the existing secret.
|
||||
if ($hasTwoFactorAuthSecret) {
|
||||
Preferences::set('twoFactorAuthEnabled', $twoFactorAuthEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
// language:
|
||||
|
@ -51,6 +51,12 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function changePassword()
|
||||
{
|
||||
if (auth()->user()->hasRole('demo')) {
|
||||
Session::flash('info', strval(trans('firefly.cannot_change_demo')));
|
||||
|
||||
return redirect(route('profile.index'));
|
||||
}
|
||||
|
||||
$title = auth()->user()->email;
|
||||
$subTitle = strval(trans('firefly.change_your_password'));
|
||||
$subTitleIcon = 'fa-key';
|
||||
@ -63,6 +69,12 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function deleteAccount()
|
||||
{
|
||||
if (auth()->user()->hasRole('demo')) {
|
||||
Session::flash('info', strval(trans('firefly.cannot_delete_demo')));
|
||||
|
||||
return redirect(route('profile.index'));
|
||||
}
|
||||
|
||||
$title = auth()->user()->email;
|
||||
$subTitle = strval(trans('firefly.delete_account'));
|
||||
$subTitleIcon = 'fa-trash';
|
||||
@ -83,12 +95,19 @@ class ProfileController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProfileFormRequest $request
|
||||
* @param ProfileFormRequest $request
|
||||
* @param UserRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function postChangePassword(ProfileFormRequest $request)
|
||||
public function postChangePassword(ProfileFormRequest $request, UserRepositoryInterface $repository)
|
||||
{
|
||||
if (auth()->user()->hasRole('demo')) {
|
||||
Session::flash('info', strval(trans('firefly.cannot_change_demo')));
|
||||
|
||||
return redirect(route('profile.index'));
|
||||
}
|
||||
|
||||
// old, new1, new2
|
||||
if (!Hash::check($request->get('current_password'), auth()->user()->password)) {
|
||||
Session::flash('error', strval(trans('firefly.invalid_current_password')));
|
||||
@ -103,9 +122,7 @@ class ProfileController extends Controller
|
||||
}
|
||||
|
||||
// update the user with the new password.
|
||||
auth()->user()->password = bcrypt($request->get('new_password'));
|
||||
auth()->user()->save();
|
||||
|
||||
$repository->changePassword(auth()->user(), $request->get('new_password'));
|
||||
Session::flash('success', strval(trans('firefly.password_changed')));
|
||||
|
||||
return redirect(route('profile.index'));
|
||||
@ -119,6 +136,12 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function postDeleteAccount(UserRepositoryInterface $repository, DeleteAccountFormRequest $request)
|
||||
{
|
||||
if (auth()->user()->hasRole('demo')) {
|
||||
Session::flash('info', strval(trans('firefly.cannot_delete_demo')));
|
||||
|
||||
return redirect(route('profile.index'));
|
||||
}
|
||||
|
||||
// old, new1, new2
|
||||
if (!Hash::check($request->get('password'), auth()->user()->password)) {
|
||||
Session::flash('error', strval(trans('firefly.invalid_password')));
|
||||
|
@ -15,7 +15,6 @@ namespace FireflyIII\Http\Controllers\Report;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
|
@ -22,6 +22,7 @@ use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\Rules\TransactionMatcher;
|
||||
use Illuminate\Http\Request;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Response;
|
||||
@ -86,10 +87,10 @@ class RuleController extends Controller
|
||||
$subTitle = trans('firefly.make_new_rule', ['title' => $ruleGroup->title]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (session('rules.rule.create.fromStore') !== true) {
|
||||
Session::put('rules.rule.create.url', URL::previous());
|
||||
if (session('rules.create.fromStore') !== true) {
|
||||
Session::put('rules.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('rules.rule.create.fromStore');
|
||||
Session::forget('rules.create.fromStore');
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'create-rule');
|
||||
|
||||
@ -110,7 +111,7 @@ class RuleController extends Controller
|
||||
$subTitle = trans('firefly.delete_rule', ['title' => $rule->title]);
|
||||
|
||||
// put previous url in session
|
||||
Session::put('rules.rule.delete.url', URL::previous());
|
||||
Session::put('rules.delete.url', URL::previous());
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'delete-rule');
|
||||
|
||||
@ -135,7 +136,7 @@ class RuleController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
|
||||
return redirect(session('rules.rule.delete.url'));
|
||||
return redirect(session('rules.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,10 +179,10 @@ class RuleController extends Controller
|
||||
$subTitle = trans('firefly.edit_rule', ['title' => $rule->title]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (session('rules.rule.edit.fromUpdate') !== true) {
|
||||
Session::put('rules.rule.edit.url', URL::previous());
|
||||
if (session('rules.edit.fromUpdate') !== true) {
|
||||
Session::put('rules.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('rules.rule.edit.fromUpdate');
|
||||
Session::forget('rules.edit.fromUpdate');
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'edit-rule');
|
||||
|
||||
@ -203,14 +204,15 @@ class RuleController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param RuleRepositoryInterface $repository
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function reorderRuleActions(RuleRepositoryInterface $repository, Rule $rule)
|
||||
public function reorderRuleActions(Request $request, RuleRepositoryInterface $repository, Rule $rule)
|
||||
{
|
||||
$ids = Input::get('actions');
|
||||
$ids = $request->get('actions');
|
||||
if (is_array($ids)) {
|
||||
$repository->reorderRuleActions($rule, $ids);
|
||||
}
|
||||
@ -220,14 +222,15 @@ class RuleController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param RuleRepositoryInterface $repository
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function reorderRuleTriggers(RuleRepositoryInterface $repository, Rule $rule)
|
||||
public function reorderRuleTriggers(Request $request, RuleRepositoryInterface $repository, Rule $rule)
|
||||
{
|
||||
$ids = Input::get('triggers');
|
||||
$ids = $request->get('triggers');
|
||||
if (is_array($ids)) {
|
||||
$repository->reorderRuleTriggers($rule, $ids);
|
||||
}
|
||||
@ -254,13 +257,13 @@ class RuleController extends Controller
|
||||
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('rules.rule.create.fromStore', true);
|
||||
Session::put('rules.create.fromStore', true);
|
||||
|
||||
return redirect(route('rules.rule.create', [$ruleGroup]))->withInput();
|
||||
return redirect(route('rules.create', [$ruleGroup]))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return redirect(session('rules.rule.create.url'));
|
||||
return redirect(session('rules.create.url'));
|
||||
|
||||
}
|
||||
|
||||
@ -341,13 +344,13 @@ class RuleController extends Controller
|
||||
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('rules.rule.edit.fromUpdate', true);
|
||||
Session::put('rules.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('rules.rule.edit', [$rule->id]))->withInput(['return_to_edit' => 1]);
|
||||
return redirect(route('rules.edit', [$rule->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return redirect(session('rules.rule.edit.url'));
|
||||
return redirect(session('rules.edit.url'));
|
||||
}
|
||||
|
||||
private function createDefaultRule()
|
||||
|
@ -62,10 +62,10 @@ class RuleGroupController extends Controller
|
||||
$subTitle = trans('firefly.make_new_rule_group');
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (session('rules.rule-group.create.fromStore') !== true) {
|
||||
Session::put('rules.rule-group.create.url', URL::previous());
|
||||
if (session('rule-groups.create.fromStore') !== true) {
|
||||
Session::put('rule-groups.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('rules.rule-group.create.fromStore');
|
||||
Session::forget('rule-groups.create.fromStore');
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'create-rule-group');
|
||||
|
||||
@ -86,7 +86,7 @@ class RuleGroupController extends Controller
|
||||
unset($ruleGroupList[$ruleGroup->id]);
|
||||
|
||||
// put previous url in session
|
||||
Session::put('rules.rule-group.delete.url', URL::previous());
|
||||
Session::put('rule-groups.delete.url', URL::previous());
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'delete-rule-group');
|
||||
|
||||
@ -113,7 +113,7 @@ class RuleGroupController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
|
||||
return redirect(session('rules.rule-group.delete.url'));
|
||||
return redirect(session('rule-groups.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,10 +140,10 @@ class RuleGroupController extends Controller
|
||||
$subTitle = trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (session('rules.rule-group.edit.fromUpdate') !== true) {
|
||||
Session::put('rules.rule-group.edit.url', URL::previous());
|
||||
if (session('rule-groups.edit.fromUpdate') !== true) {
|
||||
Session::put('rule-groups.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('rules.rule-group.edit.fromUpdate');
|
||||
Session::forget('rule-groups.edit.fromUpdate');
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'edit-rule-group');
|
||||
|
||||
@ -220,13 +220,13 @@ class RuleGroupController extends Controller
|
||||
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('rules.rule-group.create.fromStore', true);
|
||||
Session::put('rule-groups.create.fromStore', true);
|
||||
|
||||
return redirect(route('rules.rule-group.create'))->withInput();
|
||||
return redirect(route('rule-groups.create'))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return redirect(session('rules.rule-group.create.url'));
|
||||
return redirect(session('rule-groups.create.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,13 +265,13 @@ class RuleGroupController extends Controller
|
||||
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('rules.rule-group.edit.fromUpdate', true);
|
||||
Session::put('rule-groups.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('rules.rule-group.edit', [$ruleGroup->id]))->withInput(['return_to_edit' => 1]);
|
||||
return redirect(route('rule-groups.edit', [$ruleGroup->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return redirect(session('rules.rule-group.edit.url'));
|
||||
return redirect(session('rule-groups.edit.url'));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -153,16 +153,21 @@ class SingleController extends Controller
|
||||
if ($this->isOpeningBalance($transactionJournal)) {
|
||||
return $this->redirectToAccount($transactionJournal);
|
||||
}
|
||||
|
||||
$type = TransactionJournal::transactionTypeStr($transactionJournal);
|
||||
$journalId = $transactionJournal->id;
|
||||
$type = TransactionJournal::transactionTypeStr($transactionJournal);
|
||||
Session::flash('success', strval(trans('firefly.deleted_' . strtolower($type), ['description' => e($transactionJournal->description)])));
|
||||
|
||||
$repository->delete($transactionJournal);
|
||||
|
||||
Preferences::mark();
|
||||
|
||||
// redirect to previous URL:
|
||||
return redirect(session('transactions.delete.url'));
|
||||
$uri = session('transactions.delete.url');
|
||||
if (!(strpos($uri, sprintf('transactions/show/%s', $journalId)) === false)) {
|
||||
// uri would point back to transaction
|
||||
$uri = route('transactions.index', [strtolower($type)]);
|
||||
}
|
||||
|
||||
return redirect($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
|
0
app/Http/Kernel.php
Executable file → Normal file
0
app/Http/Kernel.php
Executable file → Normal file
0
app/Http/Middleware/EncryptCookies.php
Executable file → Normal file
0
app/Http/Middleware/EncryptCookies.php
Executable file → Normal file
0
app/Http/Middleware/RedirectIfAuthenticated.php
Executable file → Normal file
0
app/Http/Middleware/RedirectIfAuthenticated.php
Executable file → Normal file
0
app/Http/Middleware/VerifyCsrfToken.php
Executable file → Normal file
0
app/Http/Middleware/VerifyCsrfToken.php
Executable file → Normal file
42
app/Http/Requests/BudgetIncomeRequest.php
Normal file
42
app/Http/Requests/BudgetIncomeRequest.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetIncomeRequest.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
/**
|
||||
* Class BudgetIncomeRequest
|
||||
*
|
||||
*
|
||||
* @package FireflyIII\Http\Requests
|
||||
*/
|
||||
class BudgetIncomeRequest extends Request
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
// Only allow logged in users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'amount' => 'numeric|required|min:0',
|
||||
];
|
||||
}
|
||||
}
|
@ -42,8 +42,8 @@ class PiggyBankFormRequest extends Request
|
||||
'startdate' => new Carbon,
|
||||
'account_id' => intval($this->get('account_id')),
|
||||
'targetamount' => round($this->get('targetamount'), 2),
|
||||
'targetdate' => strlen($this->get('targetdate')) > 0 ? new Carbon($this->get('targetdate')) : null,
|
||||
'note' => trim($this->get('note')),
|
||||
'targetdate' => strlen(strval($this->get('targetdate'))) > 0 ? new Carbon($this->get('targetdate')) : null,
|
||||
'note' => trim(strval($this->get('note'))),
|
||||
];
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ class PiggyBankFormRequest extends Request
|
||||
'name' => $nameRule,
|
||||
'account_id' => 'required|belongsToUser:accounts',
|
||||
'targetamount' => 'required|min:0.01',
|
||||
'amount_currency_id_targetamount' => 'exists:transaction_currencies,id',
|
||||
'amount_currency_id_targetamount' => 'required|exists:transaction_currencies,id',
|
||||
'startdate' => 'date',
|
||||
'targetdate' => $targetDateRule,
|
||||
'order' => 'integer|min:1',
|
||||
|
@ -10,13 +10,6 @@
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
/**
|
||||
* RuleGroupFormRequest.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
|
@ -413,7 +413,22 @@ Breadcrumbs::register(
|
||||
'piggy-banks.show', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) {
|
||||
$breadcrumbs->parent('piggy-banks.index');
|
||||
$breadcrumbs->push(e($piggyBank->name), route('piggy-banks.show', [$piggyBank->id]));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'piggy-banks.add-money-mobile', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) {
|
||||
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
|
||||
$breadcrumbs->push(trans('firefly.add_money_to_piggy', ['name' => $piggyBank->name]), route('piggy-banks.add-money-mobile', [$piggyBank->id]));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'piggy-banks.remove-money-mobile', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) {
|
||||
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
|
||||
$breadcrumbs->push(
|
||||
trans('firefly.remove_money_from_piggy_title', ['name' => $piggyBank->name]), route('piggy-banks.remove-money-mobile', [$piggyBank->id])
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@ -500,16 +515,63 @@ Breadcrumbs::register(
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'reports.report', function (BreadCrumbGenerator $breadcrumbs, Carbon $start, Carbon $end, $reportType, $accountIds) {
|
||||
'reports.report.audit', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, Carbon $start, Carbon $end) {
|
||||
$breadcrumbs->parent('reports.index');
|
||||
|
||||
$monthFormat = (string)trans('config.month_and_day');
|
||||
$title = (string)trans(
|
||||
'firefly.report_' . $reportType,
|
||||
['start' => $start->formatLocalized($monthFormat), 'end' => $end->formatLocalized($monthFormat)]
|
||||
);
|
||||
$startString = $start->formatLocalized($monthFormat);
|
||||
$endString = $end->formatLocalized($monthFormat);
|
||||
$title = (string)trans('firefly.report_audit', ['start' => $startString, 'end' => $endString]);
|
||||
|
||||
$breadcrumbs->push($title, route('reports.report', [$reportType, $start->format('Ymd'), $end->format('Ymd'), $accountIds]));
|
||||
$breadcrumbs->push($title, route('reports.report.audit', [$accountIds, $start->format('Ymd'), $end->format('Ymd')]));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'reports.report.budget', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, string $budgetIds, Carbon $start, Carbon $end) {
|
||||
$breadcrumbs->parent('reports.index');
|
||||
|
||||
$monthFormat = (string)trans('config.month_and_day');
|
||||
$startString = $start->formatLocalized($monthFormat);
|
||||
$endString = $end->formatLocalized($monthFormat);
|
||||
$title = (string)trans('firefly.report_budget', ['start' => $startString, 'end' => $endString]);
|
||||
|
||||
$breadcrumbs->push($title, route('reports.report.budget', [$accountIds, $budgetIds, $start->format('Ymd'), $end->format('Ymd')]));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'reports.report.category', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, string $categoryIds, Carbon $start, Carbon $end) {
|
||||
$breadcrumbs->parent('reports.index');
|
||||
|
||||
$monthFormat = (string)trans('config.month_and_day');
|
||||
$startString = $start->formatLocalized($monthFormat);
|
||||
$endString = $end->formatLocalized($monthFormat);
|
||||
$title = (string)trans('firefly.report_category', ['start' => $startString, 'end' => $endString]);
|
||||
|
||||
$breadcrumbs->push($title, route('reports.report.category', [$accountIds, $categoryIds, $start->format('Ymd'), $end->format('Ymd')]));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'reports.report.default', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, Carbon $start, Carbon $end) {
|
||||
$breadcrumbs->parent('reports.index');
|
||||
|
||||
$monthFormat = (string)trans('config.month_and_day');
|
||||
$startString = $start->formatLocalized($monthFormat);
|
||||
$endString = $end->formatLocalized($monthFormat);
|
||||
$title = (string)trans('firefly.report_default', ['start' => $startString, 'end' => $endString]);
|
||||
|
||||
$breadcrumbs->push($title, route('reports.report.default', [$accountIds, $start->format('Ymd'), $end->format('Ymd')]));
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* New user Controller
|
||||
*/
|
||||
Breadcrumbs::register(
|
||||
'new-user.index', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('firefly.getting_started'), route('new-user.index'));
|
||||
}
|
||||
);
|
||||
|
||||
@ -524,47 +586,54 @@ Breadcrumbs::register(
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'rules.rule.create', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
'rules.create', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
$breadcrumbs->parent('rules.index');
|
||||
$breadcrumbs->push(trans('firefly.make_new_rule', ['title' => $ruleGroup->title]), route('rules.rule.create', [$ruleGroup]));
|
||||
$breadcrumbs->push(trans('firefly.make_new_rule', ['title' => $ruleGroup->title]), route('rules.create', [$ruleGroup]));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'rules.rule.edit', function (BreadCrumbGenerator $breadcrumbs, Rule $rule) {
|
||||
'rules.edit', function (BreadCrumbGenerator $breadcrumbs, Rule $rule) {
|
||||
$breadcrumbs->parent('rules.index');
|
||||
$breadcrumbs->push(trans('firefly.edit_rule', ['title' => $rule->title]), route('rules.rule.edit', [$rule]));
|
||||
$breadcrumbs->push(trans('firefly.edit_rule', ['title' => $rule->title]), route('rules.edit', [$rule]));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'rules.rule.delete', function (BreadCrumbGenerator $breadcrumbs, Rule $rule) {
|
||||
'rules.delete', function (BreadCrumbGenerator $breadcrumbs, Rule $rule) {
|
||||
$breadcrumbs->parent('rules.index');
|
||||
$breadcrumbs->push(trans('firefly.delete_rule', ['title' => $rule->title]), route('rules.rule.delete', [$rule]));
|
||||
$breadcrumbs->push(trans('firefly.delete_rule', ['title' => $rule->title]), route('rules.delete', [$rule]));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'rules.rule-group.create', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
'rule-groups.create', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('rules.index');
|
||||
$breadcrumbs->push(trans('firefly.make_new_rule_group'), route('rules.rule-group.create'));
|
||||
$breadcrumbs->push(trans('firefly.make_new_rule_group'), route('rule-groups.create'));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'rules.rule-group.edit', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
'rule-groups.edit', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
$breadcrumbs->parent('rules.index');
|
||||
$breadcrumbs->push(trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]), route('rules.rule-group.edit', [$ruleGroup]));
|
||||
$breadcrumbs->push(trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]), route('rule-groups.edit', [$ruleGroup]));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'rules.rule-group.delete', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
'rule-groups.delete', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
$breadcrumbs->parent('rules.index');
|
||||
$breadcrumbs->push(trans('firefly.delete_rule_group', ['title' => $ruleGroup->title]), route('rules.rule-group.delete', [$ruleGroup]));
|
||||
$breadcrumbs->push(trans('firefly.delete_rule_group', ['title' => $ruleGroup->title]), route('rule-groups.delete', [$ruleGroup]));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'rules.rule-group.select_transactions', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
'rule-groups.select-transactions', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
$breadcrumbs->parent('rules.index');
|
||||
$breadcrumbs->push(trans('firefly.rule_group_select_transactions', ['title' => $ruleGroup->title]), route('rule-groups.select-transactions', [$ruleGroup]));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'rule-groups.select_transactions', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
|
||||
$breadcrumbs->parent('rules.index');
|
||||
$breadcrumbs->push(
|
||||
trans('firefly.execute_group_on_existing_transactions', ['title' => $ruleGroup->title]), route('rules.rule-group.select_transactions', [$ruleGroup])
|
||||
trans('firefly.execute_group_on_existing_transactions', ['title' => $ruleGroup->title]), route('rule-groups.select_transactions', [$ruleGroup])
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -96,6 +96,7 @@ class ImportEntry
|
||||
case 'account-id':
|
||||
case 'account-iban':
|
||||
case 'account-name':
|
||||
case 'account-number':
|
||||
$this->setObject('asset-account', $convertedValue, $certainty);
|
||||
break;
|
||||
case 'opposing-number':
|
||||
|
@ -23,7 +23,7 @@ use Illuminate\Support\Collection;
|
||||
*
|
||||
* @package FireflyIII\Import
|
||||
*/
|
||||
class ImportProcedure
|
||||
class ImportProcedure implements ImportProcedureInterface
|
||||
{
|
||||
|
||||
/**
|
||||
|
33
app/Import/ImportProcedureInterface.php
Normal file
33
app/Import/ImportProcedureInterface.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* ImportProcedureInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import;
|
||||
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface ImportProcedureInterface
|
||||
*
|
||||
* @package FireflyIII\Import
|
||||
*/
|
||||
interface ImportProcedureInterface
|
||||
{
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function runImport(ImportJob $job): Collection;
|
||||
|
||||
}
|
@ -376,14 +376,14 @@ class ImportStorage
|
||||
$sourceData = [
|
||||
'account_id' => $accounts['source']->id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'description' => $journal->description,
|
||||
'description' => null,
|
||||
'amount' => bcmul($amount, '-1'),
|
||||
];
|
||||
|
||||
$destinationData = [
|
||||
'account_id' => $accounts['destination']->id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'description' => $journal->description,
|
||||
'description' => null,
|
||||
'amount' => $amount,
|
||||
];
|
||||
|
||||
|
@ -81,7 +81,7 @@ class MailError extends Job implements ShouldQueue
|
||||
['emails.error-html', 'emails.error-text'], $args,
|
||||
function (Message $message) use ($email) {
|
||||
if ($email != 'mail@example.com') {
|
||||
$message->to($email, $email)->subject('Caught an error in Firely III.');
|
||||
$message->to($email, $email)->subject('Caught an error in Firely III');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -36,12 +36,25 @@ class Account extends Model
|
||||
{
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'active' => 'boolean',
|
||||
'encrypted' => 'boolean',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
/** @var array */
|
||||
protected $fillable = ['user_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban'];
|
||||
/** @var array */
|
||||
protected $hidden = ['virtual_balance_encrypted', 'encrypted'];
|
||||
protected $hidden = ['encrypted'];
|
||||
protected $rules
|
||||
= [
|
||||
'user_id' => 'required|exists:users,id',
|
||||
@ -184,7 +197,7 @@ class Account extends Model
|
||||
public function getNameAttribute($value): string
|
||||
{
|
||||
|
||||
if (intval($this->encrypted) == 1) {
|
||||
if ($this->encrypted) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,18 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
class AccountMeta extends Model
|
||||
{
|
||||
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
protected $fillable = ['account_id', 'name', 'data'];
|
||||
protected $table = 'account_meta';
|
||||
|
||||
|
@ -33,6 +33,18 @@ class AccountType extends Model
|
||||
const IMPORT = 'Import account';
|
||||
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
];
|
||||
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
|
||||
//
|
||||
|
@ -29,6 +29,21 @@ class Attachment extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'uploaded' => 'boolean',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
/** @var array */
|
||||
protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'md5', 'filename', 'mime', 'title', 'notes', 'description', 'size', 'uploaded'];
|
||||
|
||||
/**
|
||||
|
63
app/Models/AvailableBudget.php
Normal file
63
app/Models/AvailableBudget.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* AvailableBudget.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* Class AvailableBudget
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class AvailableBudget extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
/** @var array */
|
||||
protected $fillable = ['user_id', 'transaction_currency_id', 'amount', 'start_date', 'end_date'];
|
||||
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function transactionCurrency()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\TransactionCurrency');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
}
|
@ -29,8 +29,26 @@ class Bill extends Model
|
||||
{
|
||||
|
||||
use ValidatingTrait;
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'date'];
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'date' => 'date',
|
||||
'skip' => 'int',
|
||||
'automatch' => 'boolean',
|
||||
'active' => 'boolean',
|
||||
'name_encrypted' => 'boolean',
|
||||
'match_encrypted' => 'boolean',
|
||||
];
|
||||
protected $fillable
|
||||
= ['name', 'match', 'amount_min', 'match_encrypted', 'name_encrypted', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip',
|
||||
'automatch', 'active',];
|
||||
|
@ -30,7 +30,23 @@ class Budget extends Model
|
||||
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'startdate', 'enddate'];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'active' => 'boolean',
|
||||
'encrypted' => 'boolean',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'name', 'active'];
|
||||
protected $hidden = ['encrypted'];
|
||||
protected $rules = ['name' => 'required|between:1,200',];
|
||||
@ -95,7 +111,7 @@ class Budget extends Model
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->encrypted) == 1) {
|
||||
if ($this->encrypted) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
@ -115,8 +131,8 @@ class Budget extends Model
|
||||
*/
|
||||
public function setNameAttribute($value)
|
||||
{
|
||||
$this->attributes['name'] = Crypt::encrypt($value);
|
||||
$this->attributes['encrypted'] = true;
|
||||
$this->attributes['name'] = $value;
|
||||
$this->attributes['encrypted'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,20 @@ use Illuminate\Database\Eloquent\Model;
|
||||
class BudgetLimit extends Model
|
||||
{
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'startdate'];
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'startdate' => 'date',
|
||||
'repeats' => 'boolean',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
protected $hidden = ['amount_encrypted'];
|
||||
|
||||
/**
|
||||
|
@ -29,10 +29,26 @@ class Category extends Model
|
||||
{
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'encrypted' => 'boolean',
|
||||
];
|
||||
/** @var array */
|
||||
protected $fillable = ['user_id', 'name'];
|
||||
/** @var array */
|
||||
protected $hidden = ['encrypted'];
|
||||
/** @var array */
|
||||
protected $rules = ['name' => 'required|between:1,200',];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
@ -86,7 +102,7 @@ class Category extends Model
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->encrypted) == 1) {
|
||||
if ($this->encrypted) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
@ -99,8 +115,8 @@ class Category extends Model
|
||||
*/
|
||||
public function setNameAttribute($value)
|
||||
{
|
||||
$this->attributes['name'] = Crypt::encrypt($value);
|
||||
$this->attributes['encrypted'] = true;
|
||||
$this->attributes['name'] = $value;
|
||||
$this->attributes['encrypted'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,17 @@ class Configuration extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
protected $table = 'configuration';
|
||||
|
||||
|
@ -23,6 +23,15 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
*/
|
||||
class ExportJob extends Model
|
||||
{
|
||||
/** @var array */
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
|
@ -27,6 +27,19 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
class ImportJob extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
|
||||
protected $validStatus
|
||||
= [
|
||||
'import_status_never_started', // initial state
|
||||
|
@ -26,6 +26,18 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
class LimitRepetition extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'startdate' => 'date',
|
||||
'enddate' => 'date',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at', 'startdate', 'enddate'];
|
||||
protected $hidden = ['amount_encrypted'];
|
||||
|
||||
@ -38,10 +50,10 @@ class LimitRepetition extends Model
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$object = self::where('limit_repetitions.id', $value)
|
||||
->leftJoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->where('budgets.user_id', auth()->user()->id)
|
||||
->first(['limit_repetitions.*']);
|
||||
->leftJoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->where('budgets.user_id', auth()->user()->id)
|
||||
->first(['limit_repetitions.*']);
|
||||
if ($object) {
|
||||
return $object;
|
||||
}
|
||||
|
@ -23,10 +23,20 @@ use League\CommonMark\CommonMarkConverter;
|
||||
*/
|
||||
class Note extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
protected $fillable = ['title', 'text'];
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@ -29,10 +29,25 @@ class PiggyBank extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'startdate', 'targetdate'];
|
||||
protected $fillable
|
||||
= ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate'];
|
||||
protected $hidden = ['targetamount_encrypted', 'encrypted'];
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'startdate' => 'date',
|
||||
'targetdate' => 'date',
|
||||
'order' => 'int',
|
||||
'active' => 'boolean',
|
||||
'encrypted' => 'boolean',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'startdate', 'targetdate'];
|
||||
protected $fillable = ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate'];
|
||||
protected $hidden = ['targetamount_encrypted', 'encrypted'];
|
||||
|
||||
/**
|
||||
* @param PiggyBank $value
|
||||
@ -86,7 +101,7 @@ class PiggyBank extends Model
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->encrypted) == 1) {
|
||||
if ($this->encrypted) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
@ -144,8 +159,8 @@ class PiggyBank extends Model
|
||||
*/
|
||||
public function setNameAttribute($value)
|
||||
{
|
||||
$this->attributes['name'] = Crypt::encrypt($value);
|
||||
$this->attributes['encrypted'] = true;
|
||||
$this->attributes['name'] = $value;
|
||||
$this->attributes['encrypted'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,6 +23,17 @@ use Illuminate\Database\Eloquent\Model;
|
||||
class PiggyBankEvent extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'date' => 'date',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at', 'date'];
|
||||
protected $fillable = ['piggy_bank_id', 'transaction_journal_id', 'date', 'amount'];
|
||||
protected $hidden = ['amount_encrypted'];
|
||||
|
@ -25,9 +25,21 @@ use Illuminate\Database\Eloquent\Model;
|
||||
class PiggyBankRepetition extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'startdate' => 'date',
|
||||
'targetdate' => 'date',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at', 'startdate', 'targetdate'];
|
||||
protected $fillable = ['piggy_bank_id', 'startdate', 'targetdate', 'currentamount'];
|
||||
protected $hidden = ['currentamount_encrypted'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
|
@ -27,6 +27,16 @@ use Log;
|
||||
class Preference extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
protected $fillable = ['user_id', 'data', 'name', 'data'];
|
||||
|
||||
|
@ -23,6 +23,17 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
*/
|
||||
class Role extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
|
@ -26,6 +26,23 @@ class Rule extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'active' => 'boolean',
|
||||
'order' => 'int',
|
||||
'stop_processing' => 'boolean',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
|
||||
/**
|
||||
* @param Rule $value
|
||||
*
|
||||
|
@ -10,13 +10,6 @@
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
/**
|
||||
* RuleAction.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
@ -29,6 +22,22 @@ use Illuminate\Database\Eloquent\Model;
|
||||
*/
|
||||
class RuleAction extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'active' => 'boolean',
|
||||
'order' => 'int',
|
||||
'stop_processing' => 'boolean',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
|
@ -25,6 +25,22 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
class RuleGroup extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'active' => 'boolean',
|
||||
'order' => 'int',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
|
||||
|
||||
protected $fillable = ['user_id', 'order', 'title', 'description', 'active'];
|
||||
|
||||
|
@ -22,6 +22,22 @@ use Illuminate\Database\Eloquent\Model;
|
||||
*/
|
||||
class RuleTrigger extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'active' => 'boolean',
|
||||
'order' => 'int',
|
||||
'stop_processing' => 'boolean',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
|
@ -15,6 +15,7 @@ namespace FireflyIII\Models;
|
||||
|
||||
use Crypt;
|
||||
use FireflyIII\Support\Models\TagSupport;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
@ -25,11 +26,25 @@ use Watson\Validating\ValidatingTrait;
|
||||
*/
|
||||
class Tag extends TagSupport
|
||||
{
|
||||
protected $dates = ['created_at', 'updated_at', 'date'];
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'date' => 'date',
|
||||
'zoomLevel' => 'int',
|
||||
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at', 'date', 'deleted_at'];
|
||||
protected $fillable = ['user_id', 'tag', 'date', 'description', 'longitude', 'latitude', 'zoomLevel', 'tagMode'];
|
||||
protected $rules = ['tag' => 'required|between:1,200',];
|
||||
|
||||
use ValidatingTrait;
|
||||
use ValidatingTrait, SoftDeletes;
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
|
@ -27,6 +27,20 @@ use Watson\Validating\ValidatingTrait;
|
||||
class Transaction extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'identifier' => 'int',
|
||||
'encrypted' => 'boolean', // model does not have these fields though
|
||||
'bill_name_encrypted' => 'boolean',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount', 'identifier'];
|
||||
protected $hidden = ['encrypted'];
|
||||
@ -37,7 +51,6 @@ class Transaction extends Model
|
||||
'description' => 'between:0,1024',
|
||||
'amount' => 'required|numeric',
|
||||
];
|
||||
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
/**
|
||||
|
@ -27,11 +27,20 @@ class TransactionCurrency extends Model
|
||||
{
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at','date'];
|
||||
protected $fillable = ['name', 'code', 'symbol'];
|
||||
protected $rules = ['name' => 'required|between:1,200', 'code' => 'required|between:3,3', 'symbol' => 'required|between:1,12'];
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
];
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionGroup.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* Class TransactionGroup
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class TransactionGroup extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionJournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
}
|
@ -34,6 +34,25 @@ class TransactionJournal extends TransactionJournalSupport
|
||||
{
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
'date' => 'date',
|
||||
'interest_date' => 'date',
|
||||
'book_date' => 'date',
|
||||
'process_date' => 'date',
|
||||
'order' => 'int',
|
||||
'tag_count' => 'int',
|
||||
'encrypted' => 'boolean',
|
||||
'completed' => 'boolean',
|
||||
];
|
||||
/** @var array */
|
||||
protected $dates = ['created_at', 'updated_at', 'date', 'deleted_at', 'interest_date', 'book_date', 'process_date'];
|
||||
/** @var array */
|
||||
@ -65,9 +84,9 @@ class TransactionJournal extends TransactionJournalSupport
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$object = self::where('transaction_journals.id', $value)
|
||||
->with('transactionType')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->where('user_id', auth()->user()->id)->first(['transaction_journals.*']);
|
||||
->with('transactionType')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->where('user_id', auth()->user()->id)->first(['transaction_journals.*']);
|
||||
if (!is_null($object)) {
|
||||
return $object;
|
||||
}
|
||||
@ -352,8 +371,8 @@ class TransactionJournal extends TransactionJournalSupport
|
||||
*/
|
||||
public function setDescriptionAttribute($value)
|
||||
{
|
||||
$this->attributes['description'] = Crypt::encrypt($value);
|
||||
$this->attributes['encrypted'] = true;
|
||||
$this->attributes['description'] = $value;
|
||||
$this->attributes['encrypted'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,18 @@ class TransactionJournalMeta extends Model
|
||||
{
|
||||
|
||||
use SoftDeletes;
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
];
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
protected $fillable = ['transaction_journal_id', 'name', 'data', 'hash'];
|
||||
protected $table = 'journal_meta';
|
||||
|
||||
|
@ -31,6 +31,18 @@ class TransactionType extends Model
|
||||
const TRANSFER = 'Transfer';
|
||||
const OPENING_BALANCE = 'Opening balance';
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'date',
|
||||
'updated_at' => 'date',
|
||||
'deleted_at' => 'date',
|
||||
];
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
|
||||
/**
|
||||
|
0
app/Providers/AppServiceProvider.php
Executable file → Normal file
0
app/Providers/AppServiceProvider.php
Executable file → Normal file
0
app/Providers/AuthServiceProvider.php
Executable file → Normal file
0
app/Providers/AuthServiceProvider.php
Executable file → Normal file
0
app/Providers/BroadcastServiceProvider.php
Executable file → Normal file
0
app/Providers/BroadcastServiceProvider.php
Executable file → Normal file
0
app/Providers/EventServiceProvider.php
Executable file → Normal file
0
app/Providers/EventServiceProvider.php
Executable file → Normal file
@ -98,21 +98,13 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
|
||||
// other generators
|
||||
$this->app->bind('FireflyIII\Export\ProcessorInterface', 'FireflyIII\Export\Processor');
|
||||
$this->app->bind('FireflyIII\Import\ImportProcedureInterface', 'FireflyIII\Import\ImportProcedure');
|
||||
$this->app->bind('FireflyIII\Repositories\User\UserRepositoryInterface', 'FireflyIII\Repositories\User\UserRepository');
|
||||
$this->app->bind('FireflyIII\Helpers\Attachments\AttachmentHelperInterface', 'FireflyIII\Helpers\Attachments\AttachmentHelper');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Bill\BillChartGeneratorInterface', 'FireflyIII\Generator\Chart\Bill\ChartJsBillChartGenerator');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Budget\BudgetChartGeneratorInterface', 'FireflyIII\Generator\Chart\Budget\ChartJsBudgetChartGenerator');
|
||||
$this->app->bind(
|
||||
'FireflyIII\Generator\Chart\Category\CategoryChartGeneratorInterface', 'FireflyIII\Generator\Chart\Category\ChartJsCategoryChartGenerator'
|
||||
);
|
||||
$this->app->bind(
|
||||
'FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGeneratorInterface', 'FireflyIII\Generator\Chart\PiggyBank\ChartJsPiggyBankChartGenerator'
|
||||
);
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Report\ReportChartGeneratorInterface', 'FireflyIII\Generator\Chart\Report\ChartJsReportChartGenerator');
|
||||
|
||||
$this->app->bind('FireflyIII\Helpers\Help\HelpInterface', 'FireflyIII\Helpers\Help\Help');
|
||||
$this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper');
|
||||
$this->app->bind('FireflyIII\Helpers\FiscalHelperInterface', 'FireflyIII\Helpers\FiscalHelper');
|
||||
$this->app->bind('FireflyIII\Helpers\Report\AccountReportHelperInterface', 'FireflyIII\Helpers\Report\AccountReportHelper');
|
||||
$this->app->bind('FireflyIII\Helpers\Report\BalanceReportHelperInterface', 'FireflyIII\Helpers\Report\BalanceReportHelper');
|
||||
$this->app->bind('FireflyIII\Helpers\Report\BudgetReportHelperInterface', 'FireflyIII\Helpers\Report\BudgetReportHelper');
|
||||
}
|
||||
|
0
app/Providers/RouteServiceProvider.php
Executable file → Normal file
0
app/Providers/RouteServiceProvider.php
Executable file → Normal file
@ -343,7 +343,9 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$account->save();
|
||||
|
||||
$this->updateMetadata($account, $data);
|
||||
$this->updateInitialBalance($account, $data);
|
||||
if ($this->validOpeningBalanceData($data)) {
|
||||
$this->updateInitialBalance($account, $data);
|
||||
}
|
||||
|
||||
return $account;
|
||||
}
|
||||
@ -438,7 +440,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
{
|
||||
$amount = $data['openingBalance'];
|
||||
$name = $data['name'];
|
||||
$opposing = $this->storeOpposingAccount($amount, $name);
|
||||
$opposing = $this->storeOpposingAccount($name);
|
||||
$transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
@ -448,7 +450,6 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'description' => 'Initial balance for "' . $account->name . '"',
|
||||
'completed' => true,
|
||||
'date' => $data['openingBalanceDate'],
|
||||
'encrypted' => true,
|
||||
]
|
||||
);
|
||||
Log::debug(sprintf('Created new opening balance journal: #%d', $journal->id));
|
||||
@ -481,17 +482,16 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
protected function storeOpposingAccount(float $amount, string $name): Account
|
||||
protected function storeOpposingAccount(string $name): Account
|
||||
{
|
||||
$type = $amount < 0 ? 'expense' : 'revenue';
|
||||
$opposingData = [
|
||||
'accountType' => $type,
|
||||
'accountType' => 'initial',
|
||||
'name' => $name . ' initial balance',
|
||||
'active' => false,
|
||||
'iban' => '',
|
||||
'virtualBalance' => 0,
|
||||
];
|
||||
Log::debug('Going to create an opening balance opposing account');
|
||||
Log::debug('Going to create an opening balance opposing account.');
|
||||
|
||||
return $this->storeAccount($opposingData);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class AttachmentRepository
|
||||
@ -56,6 +57,19 @@ class AttachmentRepository implements AttachmentRepositoryInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(Attachment $attachment): bool
|
||||
{
|
||||
/** @var Storage $disk */
|
||||
$disk = Storage::disk('upload');
|
||||
|
||||
return $disk->exists($attachment->fileName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
@ -82,6 +96,26 @@ class AttachmentRepository implements AttachmentRepositoryInterface
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(Attachment $attachment): string
|
||||
{
|
||||
// create a disk.
|
||||
$disk = Storage::disk('upload');
|
||||
$file = $attachment->fileName();
|
||||
|
||||
if ($disk->exists($file)) {
|
||||
$content = Crypt::decrypt($disk->get($file));
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
* @param array $data
|
||||
|
@ -37,6 +37,20 @@ interface AttachmentRepositoryInterface
|
||||
*/
|
||||
public function get(): Collection;
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(Attachment $attachment): bool;
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(Attachment $attachment): string;
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
|
@ -17,10 +17,12 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Events\StoredBudgetLimit;
|
||||
use FireflyIII\Events\UpdatedBudgetLimit;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\User;
|
||||
@ -201,15 +203,51 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
{
|
||||
$query = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00'))
|
||||
->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00'))
|
||||
->where('budgets.user_id', $this->user->id);
|
||||
->where(
|
||||
function (Builder $q1) use ($start, $end) {
|
||||
$q1->where(
|
||||
function (Builder $q2) use ($start, $end) {
|
||||
$q2->where('limit_repetitions.enddate', '>=', $start->format('Y-m-d 00:00:00'));
|
||||
$q2->where('limit_repetitions.enddate', '<=', $end->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
)
|
||||
->orWhere(
|
||||
function (Builder $q3) use ($start, $end) {
|
||||
$q3->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00'));
|
||||
$q3->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
->where('budgets.user_id', $this->user->id)
|
||||
->whereNull('budgets.deleted_at');
|
||||
|
||||
$set = $query->get(['limit_repetitions.*', 'budget_limits.budget_id']);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string
|
||||
{
|
||||
$amount = '0';
|
||||
$availableBudget = $this->user->availableBudgets()
|
||||
->where('transaction_currency_id', $currency->id)
|
||||
->where('start_date', $start->format('Y-m-d'))
|
||||
->where('end_date', $end->format('Y-m-d'))->first();
|
||||
if (!is_null($availableBudget)) {
|
||||
$amount = strval($availableBudget->amount);
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is being used to generate the budget overview in the year/multi-year report. Its used
|
||||
* in both the year/multi-year budget overview AND in the accompanying chart.
|
||||
@ -322,6 +360,33 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param string $amount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): bool
|
||||
{
|
||||
$availableBudget = $this->user->availableBudgets()
|
||||
->where('transaction_currency_id', $currency->id)
|
||||
->where('start_date', $start->format('Y-m-d'))
|
||||
->where('end_date', $end->format('Y-m-d'))->first();
|
||||
if (is_null($availableBudget)) {
|
||||
$availableBudget = new AvailableBudget;
|
||||
$availableBudget->user()->associate($this->user);
|
||||
$availableBudget->transactionCurrency()->associate($currency);
|
||||
$availableBudget->start_date = $start;
|
||||
$availableBudget->end_date = $end;
|
||||
}
|
||||
$availableBudget->amount = $amount;
|
||||
$availableBudget->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Collection $accounts
|
||||
@ -333,10 +398,11 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
public function spentInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): string
|
||||
{
|
||||
// collect amount of transaction journals, which is easy:
|
||||
$budgetIds = $budgets->pluck('id')->toArray();
|
||||
$budgetIds = $budgets->pluck('id')->toArray();
|
||||
|
||||
$accountIds = $accounts->pluck('id')->toArray();
|
||||
|
||||
Log::debug('spentInPeriod: Now in spentInPeriod for these budgets: ', $budgetIds);
|
||||
Log::debug(sprintf('spentInPeriod: Now in spentInPeriod for these budgets (%d): ', count($budgetIds)), $budgetIds);
|
||||
Log::debug('spentInPeriod: and these accounts: ', $accountIds);
|
||||
Log::debug(sprintf('spentInPeriod: Start date is "%s", end date is "%s"', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
|
||||
|
@ -16,6 +16,7 @@ namespace FireflyIII\Repositories\Budget;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
@ -90,6 +91,15 @@ interface BudgetRepositoryInterface
|
||||
*/
|
||||
public function getAllBudgetLimitRepetitions(Carbon $start, Carbon $end): Collection;
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Collection $budgets
|
||||
@ -120,6 +130,16 @@ interface BudgetRepositoryInterface
|
||||
*/
|
||||
public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param string $amount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): bool;
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Collection $accounts
|
||||
|
@ -17,6 +17,7 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Str;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class ExportJobRepository
|
||||
@ -94,6 +95,19 @@ class ExportJobRepository implements ExportJobRepositoryInterface
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExportJob $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(ExportJob $job): bool
|
||||
{
|
||||
$disk = Storage::disk('export');
|
||||
$file = $job->key . '.zip';
|
||||
|
||||
return $disk->exists($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
@ -109,4 +123,17 @@ class ExportJobRepository implements ExportJobRepositoryInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExportJob $job
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(ExportJob $job): string
|
||||
{
|
||||
$disk = Storage::disk('export');
|
||||
$file = $job->key . '.zip';
|
||||
$content = $disk->get($file);
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,13 @@ interface ExportJobRepositoryInterface
|
||||
*/
|
||||
public function create(): ExportJob;
|
||||
|
||||
/**
|
||||
* @param ExportJob $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(ExportJob $job): bool;
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
@ -39,4 +46,11 @@ interface ExportJobRepositoryInterface
|
||||
*/
|
||||
public function findByKey(string $key): ExportJob;
|
||||
|
||||
/**
|
||||
* @param ExportJob $job
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(ExportJob $job): string;
|
||||
|
||||
}
|
||||
|
@ -148,4 +148,17 @@ class UserRepository implements UserRepositoryInterface
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param string $password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function changePassword(User $user, string $password): bool
|
||||
{
|
||||
$user->password = bcrypt($password);
|
||||
$user->save();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,14 @@ interface UserRepositoryInterface
|
||||
*/
|
||||
public function attachRole(User $user, string $role): bool;
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param string $password
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function changePassword(User $user, string $password);
|
||||
|
||||
/**
|
||||
* Returns a count of all users.
|
||||
*
|
||||
|
@ -10,13 +10,6 @@
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
/**
|
||||
* ActionFactory.php
|
||||
* Copyright (C) 2016 Robert Horlings
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Rules\Factory;
|
||||
|
||||
|
@ -76,8 +76,6 @@ class CacheProperties
|
||||
public function has(): bool
|
||||
{
|
||||
if (getenv('APP_ENV') == 'testing') {
|
||||
Log::debug('APP_ENV is testing, cache disabled.');
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->md5();
|
||||
|
@ -283,6 +283,24 @@ class ExpandedForm
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function password(string $name, array $options = []): string
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$html = view('form.password', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param array $list
|
||||
@ -341,24 +359,6 @@ class ExpandedForm
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function password(string $name, array $options = []): string
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$html = view('form.password', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
@ -496,11 +496,20 @@ class ExpandedForm
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = 'any';
|
||||
$options['min'] = '0.01';
|
||||
if ($view !== 'balance') {
|
||||
$options['min'] = '0.01';
|
||||
}
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
unset($options['currency']);
|
||||
unset($options['placeholder']);
|
||||
|
||||
// make sure value is formatted nicely:
|
||||
if (!is_null($value) && $value !== '') {
|
||||
$value = round($value, 2);
|
||||
}
|
||||
|
||||
|
||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
@ -1,897 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* TestData.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Support\Migration;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Crypt;
|
||||
use DB;
|
||||
use Navigation;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class TestData
|
||||
*
|
||||
* @package FireflyIII\Support\Migration
|
||||
*/
|
||||
class TestData
|
||||
{
|
||||
/** @var array */
|
||||
private $data = [];
|
||||
/** @var Carbon */
|
||||
private $end;
|
||||
/** @var Carbon */
|
||||
private $start;
|
||||
|
||||
/** @var string */
|
||||
private $time;
|
||||
|
||||
/**
|
||||
* TestData constructor.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
private function __construct(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
$start = new Carbon;
|
||||
$start->startOfYear();
|
||||
$start->subYears(2);
|
||||
$end = new Carbon;
|
||||
|
||||
$this->start = $start;
|
||||
$this->end = $end;
|
||||
$this->time = $end->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public static function run(array $data)
|
||||
{
|
||||
$seeder = new TestData($data);
|
||||
$seeder->go();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createAccounts()
|
||||
{
|
||||
$insert = [];
|
||||
foreach ($this->data['accounts'] as $account) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $account['user_id'],
|
||||
'account_type_id' => $account['account_type_id'],
|
||||
'name' => $account['name'],
|
||||
'active' => 1,
|
||||
'encrypted' => 0,
|
||||
'virtual_balance' => 0,
|
||||
'iban' => isset($account['iban']) ? Crypt::encrypt($account['iban']) : null,
|
||||
];
|
||||
}
|
||||
DB::table('accounts')->insert($insert);
|
||||
$insert = [];
|
||||
foreach ($this->data['account-meta'] as $meta) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'account_id' => $meta['account_id'],
|
||||
'name' => $meta['name'],
|
||||
'data' => $meta['data'],
|
||||
];
|
||||
}
|
||||
DB::table('account_meta')->insert($insert);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createAttachments()
|
||||
{
|
||||
$disk = Storage::disk('upload');
|
||||
foreach ($this->data['attachments'] as $attachment) {
|
||||
$data = Crypt::encrypt($attachment['content']);
|
||||
$attachmentId = DB::table('attachments')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'attachable_id' => $attachment['attachable_id'],
|
||||
'attachable_type' => $attachment['attachable_type'],
|
||||
'user_id' => $attachment['user_id'],
|
||||
'md5' => md5($attachment['content']),
|
||||
'filename' => Crypt::encrypt($attachment['filename']),
|
||||
'title' => Crypt::encrypt($attachment['title']),
|
||||
'description' => Crypt::encrypt($attachment['description']),
|
||||
'notes' => Crypt::encrypt($attachment['notes']),
|
||||
'mime' => Crypt::encrypt($attachment['mime']),
|
||||
'size' => strlen($attachment['content']),
|
||||
'uploaded' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
$disk->put('at-' . $attachmentId . '.data', $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createBills()
|
||||
{
|
||||
$insert = [];
|
||||
foreach ($this->data['bills'] as $bill) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $bill['user_id'],
|
||||
'name' => Crypt::encrypt($bill['name']),
|
||||
'match' => Crypt::encrypt($bill['match']),
|
||||
'amount_min' => $bill['amount_min'],
|
||||
'amount_max' => $bill['amount_max'],
|
||||
'date' => $bill['date'],
|
||||
'active' => $bill['active'],
|
||||
'automatch' => $bill['automatch'],
|
||||
'repeat_freq' => $bill['repeat_freq'],
|
||||
'skip' => $bill['skip'],
|
||||
'name_encrypted' => 1,
|
||||
'match_encrypted' => 1,
|
||||
];
|
||||
}
|
||||
DB::table('bills')->insert($insert);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createBudgets()
|
||||
{
|
||||
$insert = [];
|
||||
foreach ($this->data['budgets'] as $budget) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $budget['user_id'],
|
||||
'name' => Crypt::encrypt($budget['name']),
|
||||
'encrypted' => 1,
|
||||
];
|
||||
}
|
||||
DB::table('budgets')->insert($insert);
|
||||
|
||||
foreach ($this->data['budget-limits'] as $limit) {
|
||||
$amount = rand($limit['amount_min'], $limit['amount_max']);
|
||||
$limitId = DB::table('budget_limits')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'budget_id' => $limit['budget_id'],
|
||||
'startdate' => $limit['startdate'],
|
||||
'amount' => $amount,
|
||||
'repeats' => 0,
|
||||
'repeat_freq' => $limit['repeat_freq'],
|
||||
]
|
||||
);
|
||||
|
||||
DB::table('limit_repetitions')->insert(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'budget_limit_id' => $limitId,
|
||||
'startdate' => $limit['startdate'],
|
||||
'enddate' => Navigation::endOfPeriod(new Carbon($limit['startdate']), $limit['repeat_freq'])->format('Y-m-d'),
|
||||
'amount' => $amount,
|
||||
]
|
||||
);
|
||||
}
|
||||
$current = clone $this->start;
|
||||
while ($current <= $this->end) {
|
||||
foreach ($this->data['monthly-limits'] as $limit) {
|
||||
$amount = rand($limit['amount_min'], $limit['amount_max']);
|
||||
$limitId = DB::table('budget_limits')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'budget_id' => $limit['budget_id'],
|
||||
'startdate' => $current->format('Y-m-d'),
|
||||
'amount' => $amount,
|
||||
'repeats' => 0,
|
||||
'repeat_freq' => 'monthly',
|
||||
]
|
||||
);
|
||||
|
||||
DB::table('limit_repetitions')->insert(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'budget_limit_id' => $limitId,
|
||||
'startdate' => $current->format('Y-m-d'),
|
||||
'enddate' => Navigation::endOfPeriod($current, 'monthly')->format('Y-m-d'),
|
||||
'amount' => $amount,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$current->addMonth();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createCategories()
|
||||
{
|
||||
$insert = [];
|
||||
foreach ($this->data['categories'] as $category) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $category['user_id'],
|
||||
'name' => Crypt::encrypt($category['name']),
|
||||
'encrypted' => 1,
|
||||
];
|
||||
}
|
||||
DB::table('categories')->insert($insert);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createCurrencies()
|
||||
{
|
||||
$insert = [];
|
||||
foreach ($this->data['currencies'] as $job) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'deleted_at' => null,
|
||||
'code' => $job['code'],
|
||||
'name' => $job['name'],
|
||||
'symbol' => $job['symbol'],
|
||||
];
|
||||
}
|
||||
DB::table('transaction_currencies')->insert($insert);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createExportJobs()
|
||||
{
|
||||
$insert = [];
|
||||
$disk = Storage::disk('export');
|
||||
foreach ($this->data['export-jobs'] as $job) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $job['user_id'],
|
||||
'key' => $job['key'],
|
||||
'status' => $job['status'],
|
||||
];
|
||||
$disk->put($job['key'] . '.zip', 'Nonsense data for "ziP" file.');
|
||||
}
|
||||
DB::table('export_jobs')->insert($insert);
|
||||
|
||||
// store fake export file:
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createImportJobs()
|
||||
{
|
||||
|
||||
$disk = Storage::disk('upload');
|
||||
$insert = [];
|
||||
foreach ($this->data['import-jobs'] as $job) {
|
||||
$insert[]
|
||||
= [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $job['user_id'],
|
||||
'file_type' => $job['file_type'],
|
||||
'key' => $job['key'],
|
||||
'status' => $job['status'],
|
||||
'extended_status' => json_encode($job['extended_status']),
|
||||
'configuration' => json_encode($job['configuration']),
|
||||
];
|
||||
|
||||
$disk->put($job['key'] . '.upload', Crypt::encrypt(''));
|
||||
}
|
||||
DB::table('import_jobs')->insert($insert);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createJournals()
|
||||
{
|
||||
$current = clone $this->start;
|
||||
$transactions = [];
|
||||
while ($current <= $this->end) {
|
||||
$date = $current->format('Y-m-');
|
||||
$month = $current->format('F');
|
||||
|
||||
// run all monthly withdrawals:
|
||||
foreach ($this->data['monthly-withdrawals'] as $withdrawal) {
|
||||
$description = str_replace(':month', $month, $withdrawal['description']);
|
||||
$journalId = DB::table('transaction_journals')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $withdrawal['user_id'],
|
||||
'transaction_type_id' => 1,
|
||||
'bill_id' => $withdrawal['bill_id'] ?? null,
|
||||
'transaction_currency_id' => 1,
|
||||
'description' => Crypt::encrypt($description),
|
||||
'completed' => 1,
|
||||
'date' => $date . $withdrawal['day-of-month'],
|
||||
'interest_date' => $withdrawal['interest_date'] ?? null,
|
||||
'book_date' => $withdrawal['book_date'] ?? null,
|
||||
'process_date' => $withdrawal['process_date'] ?? null,
|
||||
'encrypted' => 1,
|
||||
'order' => 0,
|
||||
'tag_count' => 0,
|
||||
]
|
||||
);
|
||||
$amount = (rand($withdrawal['min_amount'] * 100, $withdrawal['max_amount'] * 100)) / 100;
|
||||
$transactions[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'account_id' => $withdrawal['source_id'],
|
||||
'amount' => $amount * -1,
|
||||
];
|
||||
$transactions[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'account_id' => $withdrawal['destination_id'],
|
||||
'amount' => $amount,
|
||||
];
|
||||
|
||||
// link to budget if set.
|
||||
if (isset($withdrawal['budget_id'])) {
|
||||
DB::table('budget_transaction_journal')->insert(
|
||||
[
|
||||
'budget_id' => $withdrawal['budget_id'],
|
||||
'transaction_journal_id' => $journalId,
|
||||
|
||||
]
|
||||
);
|
||||
}
|
||||
// link to category if set.
|
||||
if (isset($withdrawal['category_id'])) {
|
||||
DB::table('category_transaction_journal')->insert(
|
||||
[
|
||||
'category_id' => $withdrawal['category_id'],
|
||||
'transaction_journal_id' => $journalId,
|
||||
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// run all monthly deposits:
|
||||
foreach ($this->data['monthly-deposits'] as $deposit) {
|
||||
$description = str_replace(':month', $month, $deposit['description']);
|
||||
$journalId = DB::table('transaction_journals')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $deposit['user_id'],
|
||||
'transaction_type_id' => 2,
|
||||
'bill_id' => $deposit['bill_id'] ?? null,
|
||||
'transaction_currency_id' => 1,
|
||||
'description' => Crypt::encrypt($description),
|
||||
'completed' => 1,
|
||||
'date' => $date . $deposit['day-of-month'],
|
||||
'interest_date' => $deposit['interest_date'] ?? null,
|
||||
'book_date' => $deposit['book_date'] ?? null,
|
||||
'process_date' => $deposit['process_date'] ?? null,
|
||||
'encrypted' => 1,
|
||||
'order' => 0,
|
||||
'tag_count' => 0,
|
||||
]
|
||||
);
|
||||
$amount = (rand($deposit['min_amount'] * 100, $deposit['max_amount'] * 100)) / 100;
|
||||
$transactions[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'account_id' => $deposit['source_id'],
|
||||
'amount' => $amount * -1,
|
||||
];
|
||||
$transactions[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'account_id' => $deposit['destination_id'],
|
||||
'amount' => $amount,
|
||||
];
|
||||
|
||||
// link to category if set.
|
||||
if (isset($deposit['category_id'])) {
|
||||
DB::table('category_transaction_journal')->insert(
|
||||
[
|
||||
'category_id' => $deposit['category_id'],
|
||||
'transaction_journal_id' => $journalId,
|
||||
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
// run all monthly transfers:
|
||||
foreach ($this->data['monthly-transfers'] as $transfer) {
|
||||
$description = str_replace(':month', $month, $transfer['description']);
|
||||
$journalId = DB::table('transaction_journals')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $transfer['user_id'],
|
||||
'transaction_type_id' => 3,
|
||||
'bill_id' => $transfer['bill_id'] ?? null,
|
||||
'transaction_currency_id' => 1,
|
||||
'description' => Crypt::encrypt($description),
|
||||
'completed' => 1,
|
||||
'date' => $date . $transfer['day-of-month'],
|
||||
'interest_date' => $transfer['interest_date'] ?? null,
|
||||
'book_date' => $transfer['book_date'] ?? null,
|
||||
'process_date' => $transfer['process_date'] ?? null,
|
||||
'encrypted' => 1,
|
||||
'order' => 0,
|
||||
'tag_count' => 0,
|
||||
]
|
||||
);
|
||||
$amount = (rand($transfer['min_amount'] * 100, $transfer['max_amount'] * 100)) / 100;
|
||||
$transactions[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'account_id' => $transfer['source_id'],
|
||||
'amount' => $amount * -1,
|
||||
];
|
||||
$transactions[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'account_id' => $transfer['destination_id'],
|
||||
'amount' => $amount,
|
||||
];
|
||||
// link to category if set.
|
||||
if (isset($transfer['category_id'])) {
|
||||
DB::table('category_transaction_journal')->insert(
|
||||
[
|
||||
'category_id' => $transfer['category_id'],
|
||||
'transaction_journal_id' => $journalId,
|
||||
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
DB::table('transactions')->insert($transactions);
|
||||
$transactions = [];
|
||||
$current->addMonth();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createMultiDeposits()
|
||||
{
|
||||
foreach ($this->data['multi-deposits'] as $deposit) {
|
||||
$journalId = DB::table('transaction_journals')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $deposit['user_id'],
|
||||
'transaction_type_id' => 2,
|
||||
'transaction_currency_id' => 1,
|
||||
'description' => Crypt::encrypt($deposit['description']),
|
||||
'completed' => 1,
|
||||
'date' => $deposit['date'],
|
||||
'interest_date' => $deposit['interest_date'] ?? null,
|
||||
'book_date' => $deposit['book_date'] ?? null,
|
||||
'process_date' => $deposit['process_date'] ?? null,
|
||||
'encrypted' => 1,
|
||||
'order' => 0,
|
||||
'tag_count' => 0,
|
||||
]
|
||||
);
|
||||
$identifier = 0;
|
||||
foreach ($deposit['source_ids'] as $index => $source) {
|
||||
$description = $deposit['description'] . ' (#' . ($index + 1) . ')';
|
||||
$amount = $deposit['amounts'][$index];
|
||||
$first = DB::table('transactions')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'account_id' => $deposit['destination_id'],
|
||||
'transaction_journal_id' => $journalId,
|
||||
'description' => $description,
|
||||
'amount' => $amount,
|
||||
'identifier' => $identifier,
|
||||
]
|
||||
);
|
||||
$second = DB::table('transactions')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'account_id' => $source,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'description' => $description,
|
||||
'amount' => $amount * -1,
|
||||
'identifier' => $identifier,
|
||||
]
|
||||
);
|
||||
$identifier++;
|
||||
// link first and second to budget and category, if present.
|
||||
|
||||
if (isset($deposit['category_ids'][$index])) {
|
||||
DB::table('category_transaction')->insert(
|
||||
[
|
||||
'category_id' => $deposit['category_ids'][$index],
|
||||
'transaction_id' => $first,
|
||||
]
|
||||
);
|
||||
DB::table('category_transaction')->insert(
|
||||
[
|
||||
'category_id' => $deposit['category_ids'][$index],
|
||||
'transaction_id' => $second,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function createMultiTransfers()
|
||||
{
|
||||
foreach ($this->data['multi-transfers'] as $transfer) {
|
||||
$journalId = DB::table('transaction_journals')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $transfer['user_id'],
|
||||
'transaction_type_id' => 3,
|
||||
'transaction_currency_id' => 1,
|
||||
'description' => Crypt::encrypt($transfer['description']),
|
||||
'completed' => 1,
|
||||
'date' => $transfer['date'],
|
||||
'interest_date' => $transfer['interest_date'] ?? null,
|
||||
'book_date' => $transfer['book_date'] ?? null,
|
||||
'process_date' => $transfer['process_date'] ?? null,
|
||||
'encrypted' => 1,
|
||||
'order' => 0,
|
||||
'tag_count' => 0,
|
||||
]
|
||||
);
|
||||
$identifier = 0;
|
||||
foreach ($transfer['destination_ids'] as $index => $destination) {
|
||||
$description = $transfer['description'] . ' (#' . ($index + 1) . ')';
|
||||
$amount = $transfer['amounts'][$index];
|
||||
$source = $transfer['source_ids'][$index];
|
||||
$first = DB::table('transactions')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'account_id' => $source,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'description' => $description,
|
||||
'amount' => $amount * -1,
|
||||
'identifier' => $identifier,
|
||||
]
|
||||
);
|
||||
$second = DB::table('transactions')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'account_id' => $destination,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'description' => $description,
|
||||
'amount' => $amount,
|
||||
'identifier' => $identifier,
|
||||
]
|
||||
);
|
||||
$identifier++;
|
||||
if (isset($transfer['category_ids'][$index])) {
|
||||
DB::table('category_transaction')->insert(
|
||||
[
|
||||
'category_id' => $transfer['category_ids'][$index],
|
||||
'transaction_id' => $first,
|
||||
]
|
||||
);
|
||||
DB::table('category_transaction')->insert(
|
||||
[
|
||||
'category_id' => $transfer['category_ids'][$index],
|
||||
'transaction_id' => $second,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createMultiWithdrawals()
|
||||
{
|
||||
foreach ($this->data['multi-withdrawals'] as $withdrawal) {
|
||||
$journalId = DB::table('transaction_journals')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $withdrawal['user_id'],
|
||||
'transaction_type_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'description' => Crypt::encrypt($withdrawal['description']),
|
||||
'completed' => 1,
|
||||
'date' => $withdrawal['date'],
|
||||
'interest_date' => $withdrawal['interest_date'] ?? null,
|
||||
'book_date' => $withdrawal['book_date'] ?? null,
|
||||
'process_date' => $withdrawal['process_date'] ?? null,
|
||||
'encrypted' => 1,
|
||||
'order' => 0,
|
||||
'tag_count' => 0,
|
||||
]
|
||||
);
|
||||
$identifier = 0;
|
||||
foreach ($withdrawal['destination_ids'] as $index => $destination) {
|
||||
$description = $withdrawal['description'] . ' (#' . ($index + 1) . ')';
|
||||
$amount = $withdrawal['amounts'][$index];
|
||||
$first = DB::table('transactions')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'account_id' => $withdrawal['source_id'],
|
||||
'transaction_journal_id' => $journalId,
|
||||
'description' => $description,
|
||||
'amount' => $amount * -1,
|
||||
'identifier' => $identifier,
|
||||
]
|
||||
);
|
||||
$second = DB::table('transactions')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'account_id' => $destination,
|
||||
'transaction_journal_id' => $journalId,
|
||||
'description' => $description,
|
||||
'amount' => $amount,
|
||||
'identifier' => $identifier,
|
||||
]
|
||||
);
|
||||
$identifier++;
|
||||
// link first and second to budget and category, if present.
|
||||
if (isset($withdrawal['budget_ids'][$index])) {
|
||||
DB::table('budget_transaction')->insert(
|
||||
[
|
||||
'budget_id' => $withdrawal['budget_ids'][$index],
|
||||
'transaction_id' => $first,
|
||||
]
|
||||
);
|
||||
DB::table('budget_transaction')->insert(
|
||||
[
|
||||
'budget_id' => $withdrawal['budget_ids'][$index],
|
||||
'transaction_id' => $second,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($withdrawal['category_ids'][$index])) {
|
||||
DB::table('category_transaction')->insert(
|
||||
[
|
||||
'category_id' => $withdrawal['category_ids'][$index],
|
||||
'transaction_id' => $first,
|
||||
]
|
||||
);
|
||||
DB::table('category_transaction')->insert(
|
||||
[
|
||||
'category_id' => $withdrawal['category_ids'][$index],
|
||||
'transaction_id' => $second,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createPiggyBanks()
|
||||
{
|
||||
foreach ($this->data['piggy-banks'] as $piggyBank) {
|
||||
$piggyId = DB::table('piggy_banks')->insertGetId(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'account_id' => $piggyBank['account_id'],
|
||||
'name' => Crypt::encrypt($piggyBank['name']),
|
||||
'targetamount' => $piggyBank['targetamount'],
|
||||
'startdate' => $piggyBank['startdate'],
|
||||
'order' => $piggyBank['order'],
|
||||
'encrypted' => 1,
|
||||
]
|
||||
);
|
||||
if (isset($piggyBank['currentamount'])) {
|
||||
DB::table('piggy_bank_repetitions')->insert(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'piggy_bank_id' => $piggyId,
|
||||
'startdate' => $piggyBank['startdate'],
|
||||
'currentamount' => $piggyBank['currentamount'],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->data['piggy-events'] as $event) {
|
||||
DB::table('piggy_bank_events')->insert(
|
||||
[
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'piggy_bank_id' => $event['piggy_bank_id'],
|
||||
'date' => $event['date'],
|
||||
'amount' => $event['amount'],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createRules()
|
||||
{
|
||||
$insert = [];
|
||||
foreach ($this->data['rule-groups'] as $group) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $group['user_id'],
|
||||
'order' => $group['order'],
|
||||
'title' => $group['title'],
|
||||
'description' => $group['description'],
|
||||
'active' => 1,
|
||||
];
|
||||
}
|
||||
DB::table('rule_groups')->insert($insert);
|
||||
$insert = [];
|
||||
foreach ($this->data['rules'] as $rule) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $rule['user_id'],
|
||||
'rule_group_id' => $rule['rule_group_id'],
|
||||
'order' => $rule['order'],
|
||||
'active' => $rule['active'],
|
||||
'stop_processing' => $rule['stop_processing'],
|
||||
'title' => $rule['title'],
|
||||
'description' => $rule['description'],
|
||||
];
|
||||
}
|
||||
DB::table('rules')->insert($insert);
|
||||
|
||||
$insert = [];
|
||||
foreach ($this->data['rule-triggers'] as $trigger) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'rule_id' => $trigger['rule_id'],
|
||||
'order' => $trigger['order'],
|
||||
'active' => $trigger['active'],
|
||||
'stop_processing' => $trigger['stop_processing'],
|
||||
'trigger_type' => $trigger['trigger_type'],
|
||||
'trigger_value' => $trigger['trigger_value'],
|
||||
];
|
||||
}
|
||||
DB::table('rule_triggers')->insert($insert);
|
||||
|
||||
$insert = [];
|
||||
foreach ($this->data['rule-actions'] as $action) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'rule_id' => $action['rule_id'],
|
||||
'order' => $action['order'],
|
||||
'active' => $action['active'],
|
||||
'stop_processing' => $action['stop_processing'],
|
||||
'action_type' => $action['action_type'],
|
||||
'action_value' => $action['action_value'],
|
||||
];
|
||||
}
|
||||
DB::table('rule_actions')->insert($insert);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createTags()
|
||||
{
|
||||
$insert = [];
|
||||
foreach ($this->data['tags'] as $tag) {
|
||||
$insert[]
|
||||
= [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $tag['user_id'],
|
||||
'tag' => Crypt::encrypt($tag['tag']),
|
||||
'tagMode' => $tag['tagMode'],
|
||||
'date' => $tag['date'] ?? null,
|
||||
];
|
||||
|
||||
}
|
||||
DB::table('tags')->insert($insert);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createUsers()
|
||||
{
|
||||
$insert = [];
|
||||
foreach ($this->data['users'] as $user) {
|
||||
$insert[]
|
||||
= [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'email' => $user['email'],
|
||||
'remember_token' => '',
|
||||
'password' => bcrypt($user['password']),
|
||||
];
|
||||
|
||||
}
|
||||
DB::table('users')->insert($insert);
|
||||
$insert = [];
|
||||
foreach ($this->data['roles'] as $role) {
|
||||
$insert[]
|
||||
= [
|
||||
'user_id' => $role['user_id'],
|
||||
'role_id' => $role['role'],
|
||||
];
|
||||
}
|
||||
DB::table('role_user')->insert($insert);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function go()
|
||||
{
|
||||
$this->createUsers();
|
||||
$this->createAccounts();
|
||||
$this->createBills();
|
||||
$this->createBudgets();
|
||||
$this->createCategories();
|
||||
$this->createPiggyBanks();
|
||||
$this->createRules();
|
||||
$this->createTags();
|
||||
$this->createJournals();
|
||||
$this->createAttachments();
|
||||
$this->createMultiWithdrawals();
|
||||
$this->createMultiDeposits();
|
||||
$this->createMultiTransfers();
|
||||
$this->createImportJobs();
|
||||
$this->createCurrencies();
|
||||
$this->createExportJobs();
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user