mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-30 18:41:08 +00:00
New files for future release.
This commit is contained in:
166
app/Support/Chart/Category/WholePeriodChartGenerator.php
Normal file
166
app/Support/Chart/Category/WholePeriodChartGenerator.php
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* WholePeriodChartGenerator.php
|
||||||
|
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III.
|
||||||
|
*
|
||||||
|
* Firefly III is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Firefly III is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\Chart\Category;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\Category;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WholePeriodChartGenerator
|
||||||
|
*/
|
||||||
|
class WholePeriodChartGenerator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Category $category
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function generate(Category $category, Carbon $start, Carbon $end): array
|
||||||
|
{
|
||||||
|
/** @var CategoryRepositoryInterface $repository */
|
||||||
|
$repository = app(CategoryRepositoryInterface::class);
|
||||||
|
|
||||||
|
/** @var AccountRepositoryInterface $accountRepository */
|
||||||
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
|
||||||
|
$types = [AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
|
||||||
|
$accounts = $accountRepository->getAccountsByType($types);
|
||||||
|
$step = $this->calculateStep($start, $end);
|
||||||
|
$chartData = [];
|
||||||
|
$spent = [];
|
||||||
|
$earned = [];
|
||||||
|
|
||||||
|
/** @var Carbon $current */
|
||||||
|
$current = clone $start;
|
||||||
|
|
||||||
|
while ($current <= $end) {
|
||||||
|
$key = $current->format('Y-m-d');
|
||||||
|
$currentEnd = app('navigation')->endOfPeriod($current, $step);
|
||||||
|
$spent[$key] = $repository->spentInPeriod($category, $accounts, $current, $currentEnd);
|
||||||
|
$earned[$key] = $repository->earnedInPeriod($category, $accounts, $current, $currentEnd);
|
||||||
|
$current = app('navigation')->addPeriod($current, $step, 0);
|
||||||
|
}
|
||||||
|
$currencies = $this->extractCurrencies($spent) + $this->extractCurrencies($earned);
|
||||||
|
|
||||||
|
// generate chart data (for each currency)
|
||||||
|
/** @var array $currency */
|
||||||
|
foreach ($currencies as $currency) {
|
||||||
|
$code = $currency['currency_code'];
|
||||||
|
$name = $currency['currency_name'];
|
||||||
|
$chartData[sprintf('spent-in-%s', $code)] = [
|
||||||
|
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $name]),
|
||||||
|
'entries' => [],
|
||||||
|
'type' => 'bar',
|
||||||
|
'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red
|
||||||
|
];
|
||||||
|
|
||||||
|
$chartData[sprintf('earned-in-%s', $code)] = [
|
||||||
|
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $name]),
|
||||||
|
'entries' => [],
|
||||||
|
'type' => 'bar',
|
||||||
|
'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Carbon $current */
|
||||||
|
$current = clone $start;
|
||||||
|
|
||||||
|
while ($current <= $end) {
|
||||||
|
$key = $current->format('Y-m-d');
|
||||||
|
$label = app('navigation')->periodShow($current, $step);
|
||||||
|
|
||||||
|
/** @var array $currency */
|
||||||
|
foreach ($currencies as $currency) {
|
||||||
|
$code = $currency['currency_code'];
|
||||||
|
$spentInfoKey = sprintf('spent-in-%s', $code);
|
||||||
|
$earnedInfoKey = sprintf('earned-in-%s', $code);
|
||||||
|
$spentAmount = $spent[$key][$code]['spent'] ?? '0';
|
||||||
|
$earnedAmount = $earned[$key][$code]['earned'] ?? '0';
|
||||||
|
$chartData[$spentInfoKey]['entries'][$label] = round($spentAmount, $currency['currency_decimal_places']);
|
||||||
|
$chartData[$earnedInfoKey]['entries'][$label] = round($earnedAmount, $currency['currency_decimal_places']);
|
||||||
|
}
|
||||||
|
$current = app('navigation')->addPeriod($current, $step, 0);
|
||||||
|
}
|
||||||
|
return $chartData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO is a duplicate function.
|
||||||
|
*
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function calculateStep(Carbon $start, Carbon $end): string
|
||||||
|
{
|
||||||
|
|
||||||
|
$step = '1D';
|
||||||
|
$months = $start->diffInMonths($end);
|
||||||
|
if ($months > 3) {
|
||||||
|
$step = '1W'; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
if ($months > 24) {
|
||||||
|
$step = '1M'; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
if ($months > 100) {
|
||||||
|
$step = '1Y'; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
|
return $step;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loop array of spent/earned info, and extract which currencies are present.
|
||||||
|
* Key is the currency ID.
|
||||||
|
*
|
||||||
|
* @param array $array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function extractCurrencies(array $array): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
foreach ($array as $info) {
|
||||||
|
foreach ($info as $block) {
|
||||||
|
$currencyId = $block['currency_id'];
|
||||||
|
if (!isset($return[$currencyId])) {
|
||||||
|
$return[$currencyId] = [
|
||||||
|
'currency_id' => $block['currency_id'],
|
||||||
|
'currency_code' => $block['currency_code'],
|
||||||
|
'currency_name' => $block['currency_name'],
|
||||||
|
'currency_symbol' => $block['currency_symbol'],
|
||||||
|
'currency_decimal_places' => $block['currency_decimal_places'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
208
config/ide-helper.php
Normal file
208
config/ide-helper.php
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Filename & Format
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The default filename (without extension) and the format (php or json)
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'filename' => '_ide_helper',
|
||||||
|
'format' => 'php',
|
||||||
|
|
||||||
|
'meta_filename' => '.phpstorm.meta.php',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Fluent helpers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Set to true to generate commonly used Fluent methods
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'include_fluent' => true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Write Model Magic methods
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Set to false to disable write magic methods of model
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'write_model_magic_where' => true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Write Eloquent Model Mixins
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This will add the necessary DocBlock mixins to the model class
|
||||||
|
| contained in the Laravel Framework. This helps the IDE with
|
||||||
|
| auto-completion.
|
||||||
|
|
|
||||||
|
| Please be aware that this setting changes a file within the /vendor directory.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'write_eloquent_model_mixins' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Helper files to include
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Include helper files. By default not included, but can be toggled with the
|
||||||
|
| -- helpers (-H) option. Extra helper files can be included.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'include_helpers' => false,
|
||||||
|
|
||||||
|
'helper_files' => array(
|
||||||
|
base_path().'/vendor/laravel/framework/src/Illuminate/Support/helpers.php',
|
||||||
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Model locations to include
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define in which directories the ide-helper:models command should look
|
||||||
|
| for models.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'model_locations' => array(
|
||||||
|
'app',
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Extra classes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| These implementations are not really extended, but called with magic functions
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'extra' => array(
|
||||||
|
'Eloquent' => array('Illuminate\Database\Eloquent\Builder', 'Illuminate\Database\Query\Builder'),
|
||||||
|
'Session' => array('Illuminate\Session\Store'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'magic' => array(
|
||||||
|
'Log' => array(
|
||||||
|
'debug' => 'Monolog\Logger::addDebug',
|
||||||
|
'info' => 'Monolog\Logger::addInfo',
|
||||||
|
'notice' => 'Monolog\Logger::addNotice',
|
||||||
|
'warning' => 'Monolog\Logger::addWarning',
|
||||||
|
'error' => 'Monolog\Logger::addError',
|
||||||
|
'critical' => 'Monolog\Logger::addCritical',
|
||||||
|
'alert' => 'Monolog\Logger::addAlert',
|
||||||
|
'emergency' => 'Monolog\Logger::addEmergency',
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Interface implementations
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| These interfaces will be replaced with the implementing class. Some interfaces
|
||||||
|
| are detected by the helpers, others can be listed below.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'interfaces' => array(
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Support for custom DB types
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This setting allow you to map any custom database type (that you may have
|
||||||
|
| created using CREATE TYPE statement or imported using database plugin
|
||||||
|
| / extension to a Doctrine type.
|
||||||
|
|
|
||||||
|
| Each key in this array is a name of the Doctrine2 DBAL Platform. Currently valid names are:
|
||||||
|
| 'postgresql', 'db2', 'drizzle', 'mysql', 'oracle', 'sqlanywhere', 'sqlite', 'mssql'
|
||||||
|
|
|
||||||
|
| This name is returned by getName() method of the specific Doctrine/DBAL/Platforms/AbstractPlatform descendant
|
||||||
|
|
|
||||||
|
| The value of the array is an array of type mappings. Key is the name of the custom type,
|
||||||
|
| (for example, "jsonb" from Postgres 9.4) and the value is the name of the corresponding Doctrine2 type (in
|
||||||
|
| our case it is 'json_array'. Doctrine types are listed here:
|
||||||
|
| http://doctrine-dbal.readthedocs.org/en/latest/reference/types.html
|
||||||
|
|
|
||||||
|
| So to support jsonb in your models when working with Postgres, just add the following entry to the array below:
|
||||||
|
|
|
||||||
|
| "postgresql" => array(
|
||||||
|
| "jsonb" => "json_array",
|
||||||
|
| ),
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'custom_db_types' => array(
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Support for camel cased models
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| There are some Laravel packages (such as Eloquence) that allow for accessing
|
||||||
|
| Eloquent model properties via camel case, instead of snake case.
|
||||||
|
|
|
||||||
|
| Enabling this option will support these packages by saving all model
|
||||||
|
| properties as camel case, instead of snake case.
|
||||||
|
|
|
||||||
|
| For example, normally you would see this:
|
||||||
|
|
|
||||||
|
| * @property \Illuminate\Support\Carbon $created_at
|
||||||
|
| * @property \Illuminate\Support\Carbon $updated_at
|
||||||
|
|
|
||||||
|
| With this enabled, the properties will be this:
|
||||||
|
|
|
||||||
|
| * @property \Illuminate\Support\Carbon $createdAt
|
||||||
|
| * @property \Illuminate\Support\Carbon $updatedAt
|
||||||
|
|
|
||||||
|
| Note, it is currently an all-or-nothing option.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'model_camel_case_properties' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Property Casts
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Cast the given "real type" to the given "type".
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'type_overrides' => array(
|
||||||
|
'integer' => 'int',
|
||||||
|
'boolean' => 'bool',
|
||||||
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Include DocBlocks from classes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Include DocBlocks from classes to allow additional code inspection for
|
||||||
|
| magic methods and properties.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'include_class_docblocks' => false,
|
||||||
|
|
||||||
|
);
|
Reference in New Issue
Block a user