mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	Refactor category repositories.
This commit is contained in:
		| @@ -28,12 +28,10 @@ use FireflyIII\Generator\Chart\Basic\GeneratorInterface; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\NoCategoryRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\OperationsRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use FireflyIII\Support\Chart\Category\WholePeriodChartGenerator; | ||||
| use FireflyIII\Support\Http\Controllers\AugumentData; | ||||
| @@ -68,8 +66,6 @@ class CategoryController extends Controller | ||||
|     /** | ||||
|      * Show an overview for a category for all time, per month/week/year. | ||||
|      * | ||||
|      * TODO this chart is not multi-currency aware. | ||||
|      * | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
| @@ -82,7 +78,7 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty('chart.category.all'); | ||||
|         $cache->addProperty($category->id); | ||||
|         if ($cache->has()) { | ||||
|             return response()->json($cache->get()); // @codeCoverageIgnore | ||||
|             // return response()->json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|         $start = $repository->firstUseDate($category) ?? $this->getDate(); | ||||
|         $range = app('preferences')->get('viewRange', '1M')->data; | ||||
| @@ -116,12 +112,10 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('chart.category.frontpage'); | ||||
|         if ($cache->has()) { | ||||
|             return response()->json($cache->get()); // @codeCoverageIgnore | ||||
|             // return response()->json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         // currency repos: | ||||
|         /** @var CurrencyRepositoryInterface $currencyRepository */ | ||||
|         $currencyRepository = app(CurrencyRepositoryInterface::class); | ||||
|         /** @var CategoryRepositoryInterface $repository */ | ||||
|         $repository = app(CategoryRepositoryInterface::class); | ||||
|  | ||||
| @@ -134,68 +128,76 @@ class CategoryController extends Controller | ||||
|         /** @var NoCategoryRepositoryInterface $noCatRepository */ | ||||
|         $noCatRepository = app(NoCategoryRepositoryInterface::class); | ||||
|  | ||||
|         $currencies = []; | ||||
|  | ||||
|  | ||||
|         $chartData  = []; | ||||
|         $currencies = []; | ||||
|         $tempData   = []; | ||||
|         $categories = $repository->getCategories(); | ||||
|         $accounts   = $accountRepository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]); | ||||
|  | ||||
|         /** @var Category $category */ | ||||
|         foreach ($categories as $category) { | ||||
|             $spentArray = $opsRepository->spentInPeriodPerCurrency(new Collection([$category]), $accounts, $start, $end); | ||||
|             foreach ($spentArray as $categoryId => $spentInfo) { | ||||
|                 foreach ($spentInfo['spent'] as $currencyId => $row) { | ||||
|                     $spent = $row['spent']; | ||||
|                     if (bccomp($spent, '0') === -1) { | ||||
|                         $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepository->findNull((int)$currencyId); | ||||
|                         $tempData[]              = [ | ||||
|                             'name'        => $category->name, | ||||
|                             'spent'       => bcmul($spent, '-1'), | ||||
|                             'spent_float' => (float)bcmul($spent, '-1'), | ||||
|                             'currency_id' => $currencyId, | ||||
|                         ]; | ||||
|                     } | ||||
|                 } | ||||
|             $collection = new Collection([$category]); | ||||
|             $spent      = $opsRepository->sumExpenses($start, $end, $accounts, $collection); | ||||
|             //$spentArray = $opsRepository->spentInPeriodPerCurrency(new Collection([$category]), $accounts, $start, $end); | ||||
|             foreach ($spent as $currency) { | ||||
|                 $currencyId              = $currency['currency_id']; | ||||
|                 $currencies[$currencyId] = $currencies[$currencyId] ?? [ | ||||
|                         'currency_id'             => $currencyId, | ||||
|                         'currency_name'           => $currency['currency_name'], | ||||
|                         'currency_symbol'         => $currency['currency_symbol'], | ||||
|                         'currency_code'           => $currency['currency_code'], | ||||
|                         'currency_decimal_places' => $currency['currency_decimal_places'], | ||||
|                     ]; | ||||
|                 $tempData[]              = [ | ||||
|                     'name'        => $category->name, | ||||
|                     'sum'         => $currency['sum'], | ||||
|                     'sum_float'   => round($currency['sum'], $currency['currency_decimal_places']), | ||||
|                     'currency_id' => $currencyId, | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // no category per currency: | ||||
|         $noCategory = $noCatRepository->spentInPeriodPcWoCategory(new Collection, $start, $end); | ||||
|         foreach ($noCategory as $currencyId => $spent) { | ||||
|             $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepository->findNull($currencyId); | ||||
|         $noCategory = $noCatRepository->sumExpenses($start, $end); | ||||
|  | ||||
|         foreach ($noCategory as $currency) { | ||||
|             $currencyId              = $currency['currency_id']; | ||||
|             $currencies[$currencyId] = $currencies[$currencyId] ?? [ | ||||
|                     'currency_id'             => $currency['currency_id'], | ||||
|                     'currency_name'           => $currency['currency_name'], | ||||
|                     'currency_symbol'         => $currency['currency_symbol'], | ||||
|                     'currency_code'           => $currency['currency_code'], | ||||
|                     'currency_decimal_places' => $currency['currency_decimal_places'], | ||||
|                 ]; | ||||
|             $tempData[]              = [ | ||||
|                 'name'        => trans('firefly.no_category'), | ||||
|                 'spent'       => bcmul($spent['spent'], '-1'), | ||||
|                 'spent_float' => (float)bcmul($spent['spent'], '-1'), | ||||
|                 'currency_id' => $currencyId, | ||||
|                 'sum'         => $currency['sum'], | ||||
|                 'sum_float'   => round($currency['sum'], $currency['currency_decimal_places']), | ||||
|                 'currency_id' => $currency['currency_id'], | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         // sort temp array by amount. | ||||
|         $amounts = array_column($tempData, 'spent_float'); | ||||
|         $amounts = array_column($tempData, 'sum_float'); | ||||
|         array_multisort($amounts, SORT_DESC, $tempData); | ||||
|  | ||||
|         // loop all found currencies and build the data array for the chart. | ||||
|         /** | ||||
|          * @var int                 $currencyId | ||||
|          * @var TransactionCurrency $currency | ||||
|          */ | ||||
|         foreach ($currencies as $currencyId => $currency) { | ||||
|             $dataSet                = [ | ||||
|                 'label'           => (string)trans('firefly.spent'), | ||||
|         /** @var array $currency */ | ||||
|         foreach ($currencies as $currency) { | ||||
|             $dataSet                             = [ | ||||
|                 'label'           => sprintf('%s (%s)', (string)trans('firefly.spent'), $currency['currency_name']), | ||||
|                 'type'            => 'bar', | ||||
|                 'currency_symbol' => $currency->symbol, | ||||
|                 'currency_symbol' => $currency['currency_symbol'], | ||||
|                 'entries'         => $this->expandNames($tempData), | ||||
|             ]; | ||||
|             $chartData[$currencyId] = $dataSet; | ||||
|             $chartData[$currency['currency_id']] = $dataSet; | ||||
|         } | ||||
|  | ||||
|         // loop temp data and place data in correct array: | ||||
|         foreach ($tempData as $entry) { | ||||
|             $currencyId                               = $entry['currency_id']; | ||||
|             $name                                     = $entry['name']; | ||||
|             $chartData[$currencyId]['entries'][$name] = $entry['spent']; | ||||
|             $chartData[$currencyId]['entries'][$name] = bcmul($entry['sum'], '-1'); | ||||
|         } | ||||
|         $data = $this->generator->multiSet($chartData); | ||||
|         $cache->store($data); | ||||
| @@ -206,8 +208,6 @@ class CategoryController extends Controller | ||||
|     /** | ||||
|      * Chart report. | ||||
|      * | ||||
|      * TODO this chart is not multi-currency aware. | ||||
|      * | ||||
|      * @param Category   $category | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
| @@ -224,44 +224,62 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty($accounts->pluck('id')->toArray()); | ||||
|         $cache->addProperty($category); | ||||
|         if ($cache->has()) { | ||||
|             return response()->json($cache->get());// @codeCoverageIgnore | ||||
|             // return response()->json($cache->get());// @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         /** @var OperationsRepositoryInterface $opsRepository */ | ||||
|         $opsRepository = app(OperationsRepositoryInterface::class); | ||||
|  | ||||
|         $expenses  = $opsRepository->periodExpenses(new Collection([$category]), $accounts, $start, $end); | ||||
|         $income    = $opsRepository->periodIncome(new Collection([$category]), $accounts, $start, $end); | ||||
|         $periods   = app('navigation')->listOfPeriods($start, $end); | ||||
|         $chartData = [ | ||||
|             [ | ||||
|                 'label'           => (string)trans('firefly.spent'), | ||||
|  | ||||
|         // this gives us all currencies | ||||
|         $collection = new Collection([$category]); | ||||
|         $expenses   = $opsRepository->listExpenses($start, $end, null, $collection); | ||||
|         $income     = $opsRepository->listIncome($start, $end, null, $collection); | ||||
|         $currencies = array_unique(array_merge(array_keys($income), array_keys($expenses))); | ||||
|         $periods    = app('navigation')->listOfPeriods($start, $end); | ||||
|         $format     = app('navigation')->preferredCarbonLocalizedFormat($start, $end); | ||||
|         $chartData  = []; | ||||
|         // make empty data array: | ||||
|         // double foreach (bad) to make empty array: | ||||
|         foreach ($currencies as $currencyId) { | ||||
|             $currencyInfo = $expenses[$currencyId] ?? $income[$currencyId]; | ||||
|             $outKey       = sprintf('%d-out', $currencyId); | ||||
|             $inKey        = sprintf('%d-in', $currencyId); | ||||
|             $chartData[$outKey] | ||||
|                           = [ | ||||
|                 'label'           => sprintf('%s (%s)', (string)trans('firefly.spent'), $currencyInfo['currency_name']), | ||||
|                 'entries'         => [], | ||||
|                 'type'            => 'bar', | ||||
|                 'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red | ||||
|             ], | ||||
|             [ | ||||
|                 'label'           => (string)trans('firefly.earned'), | ||||
|             ]; | ||||
|  | ||||
|             $chartData[$inKey] | ||||
|                 = [ | ||||
|                 'label'           => sprintf('%s (%s)', (string)trans('firefly.earned'), $currencyInfo['currency_name']), | ||||
|                 'entries'         => [], | ||||
|                 'type'            => 'bar', | ||||
|                 'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green | ||||
|             ], | ||||
|             [ | ||||
|                 'label'   => (string)trans('firefly.sum'), | ||||
|                 'entries' => [], | ||||
|                 'type'    => 'line', | ||||
|                 'fill'    => false, | ||||
|             ], | ||||
|         ]; | ||||
|             ]; | ||||
|  | ||||
|         foreach (array_keys($periods) as $period) { | ||||
|             $label                           = $periods[$period]; | ||||
|             $spent                           = $expenses[$category->id]['entries'][$period] ?? '0'; | ||||
|             $earned                          = $income[$category->id]['entries'][$period] ?? '0'; | ||||
|             $sum                             = bcadd($spent, $earned); | ||||
|             $chartData[0]['entries'][$label] = round($spent, 12); | ||||
|             $chartData[1]['entries'][$label] = round($earned, 12); | ||||
|             $chartData[2]['entries'][$label] = round($sum, 12); | ||||
|  | ||||
|             // loop empty periods: | ||||
|             foreach (array_keys($periods) as $period) { | ||||
|                 $label                                 = $periods[$period]; | ||||
|                 $chartData[$outKey]['entries'][$label] = '0'; | ||||
|                 $chartData[$inKey]['entries'][$label]  = '0'; | ||||
|             } | ||||
|             // loop income and expenses for this category.: | ||||
|             $outSet = $expenses[$currencyId]['categories'][$category->id] ?? ['transaction_journals' => []]; | ||||
|             foreach ($outSet['transaction_journals'] as $journal) { | ||||
|                 $date                                 = $journal['date']->formatLocalized($format); | ||||
|                 $chartData[$outKey]['entries'][$date] = bcadd($journal['amount'], $chartData[$outKey]['entries'][$date]); | ||||
|             } | ||||
|  | ||||
|             $inSet = $income[$currencyId]['categories'][$category->id] ?? ['transaction_journals' => []]; | ||||
|             foreach ($inSet['transaction_journals'] as $journal) { | ||||
|                 $date                                = $journal['date']->formatLocalized($format); | ||||
|                 $chartData[$inKey]['entries'][$date] = bcadd($journal['amount'], $chartData[$inKey]['entries'][$date]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->multiSet($chartData); | ||||
| @@ -288,7 +306,7 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty('chart.category.period.no-cat'); | ||||
|         $cache->addProperty($accounts->pluck('id')->toArray()); | ||||
|         if ($cache->has()) { | ||||
|             // return response()->json($cache->get()); // @codeCoverageIgnore | ||||
|             return response()->json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         /** @var NoCategoryRepositoryInterface $noCatRepository */ | ||||
| @@ -339,118 +357,13 @@ class CategoryController extends Controller | ||||
|  | ||||
|             $inSet = $income[$currencyId] ?? ['transaction_journals' => []]; | ||||
|             foreach ($inSet['transaction_journals'] as $journal) { | ||||
|                 $date                                 = $journal['date']->formatLocalized($format); | ||||
|                 $date                                = $journal['date']->formatLocalized($format); | ||||
|                 $chartData[$inKey]['entries'][$date] = bcadd($journal['amount'], $chartData[$inKey]['entries'][$date]); | ||||
|             } | ||||
|         } | ||||
|         $data = $this->generator->multiSet($chartData); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return response()->json($data); | ||||
|         var_dump($chartData); | ||||
|         var_dump(array_values($chartData)); | ||||
|         exit; | ||||
|  | ||||
|  | ||||
|         $format    = app('navigation')->preferredCarbonLocalizedFormat($start, $end); | ||||
|         $chartData = []; | ||||
|  | ||||
|         // double foreach (bad) to make empty array: | ||||
|         foreach ($currencies as $currencyId) { | ||||
|             $currencyInfo = $expenses[$currencyId] ?? $income[$currencyId]; | ||||
|  | ||||
|             $spentArray | ||||
|                 = [ | ||||
|                 'label'           => sprintf('%s (%s)', (string)trans('firefly.spent'), $currencyInfo['currency_name']), | ||||
|                 'entries'         => [], | ||||
|                 'type'            => 'bar', | ||||
|                 'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red | ||||
|             ]; | ||||
|             $incomeArray | ||||
|                 = [ | ||||
|                 'label'           => sprintf('%s (%s)', (string)trans('firefly.earned'), $currencyInfo['currency_name']), | ||||
|                 'entries'         => [], | ||||
|                 'type'            => 'bar', | ||||
|                 'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green | ||||
|             ]; | ||||
|  | ||||
|             foreach (array_keys($periods) as $period) { | ||||
|                 $label                          = $periods[$period]; | ||||
|                 $spentArray['entries'][$label]  = '0'; | ||||
|                 $incomeArray['entries'][$label] = '0'; | ||||
|  | ||||
|                 // then loop income and then loop expenses, maybe? | ||||
|                 $currencyExpenses = $expenses[$currencyId] ?? ['transaction_journals' => []]; | ||||
|                 foreach ($currencyExpenses['transaction_journals'] as $row) { | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|             $chartData[] = $spentArray; | ||||
|             $chartData[] = $incomeArray; | ||||
|         } | ||||
|         var_dump($chartData); | ||||
|         exit; | ||||
|  | ||||
|  | ||||
|         foreach ($currencies as $currencyId) { | ||||
|             $currencyInfo = $expenses[$currencyId] ?? $income[$currencyId]; | ||||
|             // loop expenses[$currencyId], if set | ||||
|             $spentArray | ||||
|                 = [ | ||||
|                 'label'           => sprintf('%s (%s)', (string)trans('firefly.spent'), $currencyInfo['currency_name']), | ||||
|                 'entries'         => [], | ||||
|                 'type'            => 'bar', | ||||
|                 'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red | ||||
|             ]; | ||||
|  | ||||
|             $current = $expenses[$currencyId] ?? ['transaction_journals' => []]; | ||||
|             foreach ($current['transaction_journals'] as $row) { | ||||
|                 $thisPeriod                         = $row['date']->formatLocalized($format); | ||||
|                 $spentArray['entries'][$thisPeriod] = $spentArray['entries'][$thisPeriod] ?? '0'; | ||||
|                 $spentArray['entries'][$thisPeriod] = bcadd($spentArray['entries'][$thisPeriod], $row['amount']); | ||||
|             } | ||||
|             $chartData[] = $spentArray; | ||||
|  | ||||
|             // loop income[$currencyId], if set | ||||
|             $incomeArray | ||||
|                 = [ | ||||
|                 'label'           => sprintf('%s (%s)', (string)trans('firefly.earned'), $currencyInfo['currency_name']), | ||||
|                 'entries'         => [], | ||||
|                 'type'            => 'bar', | ||||
|                 'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green | ||||
|             ]; | ||||
|  | ||||
|             $current = $income[$currencyId] ?? ['transaction_journals' => []]; | ||||
|             foreach ($current['transaction_journals'] as $row) { | ||||
|                 $thisPeriod                          = $row['date']->formatLocalized($format); | ||||
|                 $incomeArray['entries'][$thisPeriod] = $incomeArray['entries'][$thisPeriod] ?? '0'; | ||||
|                 $incomeArray['entries'][$thisPeriod] = bcadd($incomeArray['entries'][$thisPeriod], $row['amount']); | ||||
|             } | ||||
|             $chartData[] = $incomeArray; | ||||
|  | ||||
|             //            $chartData[]  = [ | ||||
|             //                'label'           => sprintf('%s (%s)', (string)trans('firefly.earned'), $currencyInfo['currency_name']), | ||||
|             //                'entries'         => [], | ||||
|             //                'type'            => 'bar', | ||||
|             //                'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green | ||||
|             //            ]; | ||||
|         } | ||||
|         echo '<pre>'; | ||||
|         print_r($chartData); | ||||
|         exit; | ||||
|  | ||||
|         foreach (array_keys($periods) as $period) { | ||||
|             $label                           = $periods[$period]; | ||||
|             $spent                           = $expenses['entries'][$period] ?? '0'; | ||||
|             $earned                          = $income['entries'][$period] ?? '0'; | ||||
|             $sum                             = bcadd($spent, $earned); | ||||
|             $chartData[0]['entries'][$label] = bcmul($spent, '-1'); | ||||
|             $chartData[1]['entries'][$label] = $earned; | ||||
|             $chartData[2]['entries'][$label] = $sum; | ||||
|         } | ||||
|         $data = $this->generator->multiSet($chartData); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return response()->json($data); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -69,24 +69,68 @@ class CategoryController extends Controller | ||||
|         /** @var NoCategoryRepositoryInterface $noCatRepos */ | ||||
|         $noCatRepos = app(NoCategoryRepositoryInterface::class); | ||||
|  | ||||
|         $periods    = app('navigation')->listOfPeriods($start, $end); | ||||
|         $data       = []; | ||||
|         $categories = $repository->getCategories(); | ||||
|         $data       = $opsRepository->periodExpenses($categories, $accounts, $start, $end); | ||||
|         $data[0]    = $noCatRepos->periodExpensesNoCategory($accounts, $start, $end); | ||||
|         $report     = $this->filterPeriodReport($data); | ||||
|  | ||||
|         // depending on the carbon format (a reliable way to determine the general date difference) | ||||
|         // change the "listOfPeriods" call so the entire period gets included correctly. | ||||
|         $range = app('navigation')->preferredCarbonFormat($start, $end); | ||||
|         $format = app('navigation')->preferredCarbonFormat($start, $end); | ||||
|  | ||||
|         if ('Y' === $range) { | ||||
|         if ('Y' === $format) { | ||||
|             $start->startOfYear(); | ||||
|         } | ||||
|         if ('Y-m' === $range) { | ||||
|         if ('Y-m' === $format) { | ||||
|             $start->startOfMonth(); | ||||
|         } | ||||
|  | ||||
|         $periods = app('navigation')->listOfPeriods($start, $end); | ||||
|         $data    = []; | ||||
|         $with    = $opsRepository->listExpenses($start, $end, $accounts); | ||||
|         $without = $noCatRepos->listExpenses($start, $end, $accounts); | ||||
|  | ||||
|         foreach ($with as $currencyId => $currencyRow) { | ||||
|             foreach ($currencyRow['categories'] as $categoryId => $categoryRow) { | ||||
|                 $key        = sprintf('%d-%d', $currencyId, $categoryId); | ||||
|                 $data[$key] = $data[$key] ?? [ | ||||
|                         'id'                      => $categoryRow['id'], | ||||
|                         'title'                   => sprintf('%s (%s)', $categoryRow['name'], $currencyRow['currency_name']), | ||||
|                         'currency_id'             => $currencyRow['currency_id'], | ||||
|                         'currency_symbol'         => $currencyRow['currency_symbol'], | ||||
|                         'currency_name'           => $currencyRow['currency_name'], | ||||
|                         'currency_code'           => $currencyRow['currency_code'], | ||||
|                         'currency_decimal_places' => $currencyRow['currency_decimal_places'], | ||||
|                         'sum'                     => '0', | ||||
|                         'entries'                 => [], | ||||
|  | ||||
|                     ]; | ||||
|                 foreach ($categoryRow['transaction_journals'] as $journalId => $journal) { | ||||
|                     $date                         = $journal['date']->format($format); | ||||
|                     $data[$key]['entries'][$date] = $data[$key]['entries'][$date] ?? '0'; | ||||
|                     $data[$key]['entries'][$date] = bcadd($data[$key]['entries'][$date], $journal['amount']); | ||||
|                     $data[$key]['sum']            = bcadd($data[$key]['sum'], $journal['amount']); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         foreach ($without as $currencyId => $currencyRow) { | ||||
|             $key        = sprintf('0-%d', $currencyId); | ||||
|             $data[$key] = $data[$key] ?? [ | ||||
|                     'id'                      => 0, | ||||
|                     'title'                   => sprintf('%s (%s)', trans('firefly.noCategory'), $currencyRow['currency_name']), | ||||
|                     'currency_id'             => $currencyRow['currency_id'], | ||||
|                     'currency_symbol'         => $currencyRow['currency_symbol'], | ||||
|                     'currency_name'           => $currencyRow['currency_name'], | ||||
|                     'currency_code'           => $currencyRow['currency_code'], | ||||
|                     'currency_decimal_places' => $currencyRow['currency_decimal_places'], | ||||
|                     'sum'                     => '0', | ||||
|                     'entries'                 => [], | ||||
|                 ]; | ||||
|             foreach ($currencyRow['transaction_journals'] as $journalId => $journal) { | ||||
|                 $date                         = $journal['date']->format($format); | ||||
|                 $data[$key]['entries'][$date] = $data[$key]['entries'][$date] ?? '0'; | ||||
|                 $data[$key]['entries'][$date] = bcadd($data[$key]['entries'][$date], $journal['amount']); | ||||
|                 $data[$key]['sum']            = bcadd($data[$key]['sum'], $journal['amount']); | ||||
|             } | ||||
|         } | ||||
|         $cache->store($data); | ||||
|  | ||||
|         $report = $data; | ||||
|  | ||||
|         try { | ||||
|             $result = view('reports.partials.category-period', compact('report', 'periods'))->render(); | ||||
| @@ -121,34 +165,78 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty('category-period-income-report'); | ||||
|         $cache->addProperty($accounts->pluck('id')->toArray()); | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|             // return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|         /** @var CategoryRepositoryInterface $repository */ | ||||
|         $repository = app(CategoryRepositoryInterface::class); | ||||
|  | ||||
|         /** @var OperationsRepositoryInterface $opsRepository */ | ||||
|         $opsRepository = app(OperationsRepositoryInterface::class); | ||||
|  | ||||
|         /** @var NoCategoryRepositoryInterface $noCatRepository */ | ||||
|         $noCatRepository = app(NoCategoryRepositoryInterface::class); | ||||
|  | ||||
|         $categories = $repository->getCategories(); | ||||
|         $data       = $opsRepository->periodIncome($categories, $accounts, $start, $end); | ||||
|         $data[0]    = $noCatRepository->periodIncomeNoCategory($accounts, $start, $end); | ||||
|         $report     = $this->filterPeriodReport($data); | ||||
|         /** @var NoCategoryRepositoryInterface $noCatRepos */ | ||||
|         $noCatRepos = app(NoCategoryRepositoryInterface::class); | ||||
|  | ||||
|         // depending on the carbon format (a reliable way to determine the general date difference) | ||||
|         // change the "listOfPeriods" call so the entire period gets included correctly. | ||||
|         $range = app('navigation')->preferredCarbonFormat($start, $end); | ||||
|         $format = app('navigation')->preferredCarbonFormat($start, $end); | ||||
|  | ||||
|         if ('Y' === $range) { | ||||
|         if ('Y' === $format) { | ||||
|             $start->startOfYear(); | ||||
|         } | ||||
|         if ('Y-m' === $range) { | ||||
|         if ('Y-m' === $format) { | ||||
|             $start->startOfMonth(); | ||||
|         } | ||||
|  | ||||
|         $periods = app('navigation')->listOfPeriods($start, $end); | ||||
|         $data    = []; | ||||
|         $with    = $opsRepository->listIncome($start, $end, $accounts); | ||||
|         $without = $noCatRepos->listIncome($start, $end, $accounts); | ||||
|  | ||||
|         foreach ($with as $currencyId => $currencyRow) { | ||||
|             foreach ($currencyRow['categories'] as $categoryId => $categoryRow) { | ||||
|                 $key        = sprintf('%d-%d', $currencyId, $categoryId); | ||||
|                 $data[$key] = $data[$key] ?? [ | ||||
|                         'id'                      => $categoryRow['id'], | ||||
|                         'title'                   => sprintf('%s (%s)', $categoryRow['name'], $currencyRow['currency_name']), | ||||
|                         'currency_id'             => $currencyRow['currency_id'], | ||||
|                         'currency_symbol'         => $currencyRow['currency_symbol'], | ||||
|                         'currency_name'           => $currencyRow['currency_name'], | ||||
|                         'currency_code'           => $currencyRow['currency_code'], | ||||
|                         'currency_decimal_places' => $currencyRow['currency_decimal_places'], | ||||
|                         'sum'                     => '0', | ||||
|                         'entries'                 => [], | ||||
|  | ||||
|                     ]; | ||||
|                 foreach ($categoryRow['transaction_journals'] as $journalId => $journal) { | ||||
|                     $date                         = $journal['date']->format($format); | ||||
|                     $data[$key]['entries'][$date] = $data[$key]['entries'][$date] ?? '0'; | ||||
|                     $data[$key]['entries'][$date] = bcadd($data[$key]['entries'][$date], $journal['amount']); | ||||
|                     $data[$key]['sum']            = bcadd($data[$key]['sum'], $journal['amount']); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         foreach ($without as $currencyId => $currencyRow) { | ||||
|             $key        = sprintf('0-%d', $currencyId); | ||||
|             $data[$key] = $data[$key] ?? [ | ||||
|                     'id'                      => 0, | ||||
|                     'title'                   => sprintf('%s (%s)', trans('firefly.noCategory'), $currencyRow['currency_name']), | ||||
|                     'currency_id'             => $currencyRow['currency_id'], | ||||
|                     'currency_symbol'         => $currencyRow['currency_symbol'], | ||||
|                     'currency_name'           => $currencyRow['currency_name'], | ||||
|                     'currency_code'           => $currencyRow['currency_code'], | ||||
|                     'currency_decimal_places' => $currencyRow['currency_decimal_places'], | ||||
|                     'sum'                     => '0', | ||||
|                     'entries'                 => [], | ||||
|                 ]; | ||||
|             foreach ($currencyRow['transaction_journals'] as $journalId => $journal) { | ||||
|                 $date                         = $journal['date']->format($format); | ||||
|                 $data[$key]['entries'][$date] = $data[$key]['entries'][$date] ?? '0'; | ||||
|                 $data[$key]['entries'][$date] = bcadd($data[$key]['entries'][$date], $journal['amount']); | ||||
|                 $data[$key]['sum']            = bcadd($data[$key]['sum'], $journal['amount']); | ||||
|             } | ||||
|         } | ||||
|         $cache->store($data); | ||||
|  | ||||
|         $report = $data; | ||||
|  | ||||
|         try { | ||||
|             $result = view('reports.partials.category-period', compact('report', 'periods'))->render(); | ||||
|             // @codeCoverageIgnoreStart | ||||
| @@ -157,6 +245,7 @@ class CategoryController extends Controller | ||||
|             $result = sprintf('An error prevented Firefly III from rendering: %s. Apologies.', $e->getMessage()); | ||||
|         } | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|         $cache->store($result); | ||||
|  | ||||
|         return $result; | ||||
| @@ -182,7 +271,7 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty('category-report'); | ||||
|         $cache->addProperty($accounts->pluck('id')->toArray()); | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|             // return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         /** @var CategoryRepositoryInterface $repository */ | ||||
| @@ -191,60 +280,120 @@ class CategoryController extends Controller | ||||
|         /** @var OperationsRepositoryInterface $opsRepository */ | ||||
|         $opsRepository = app(OperationsRepositoryInterface::class); | ||||
|  | ||||
|         $categories = $repository->getCategories(); | ||||
|         $report     = [ | ||||
|         /** @var NoCategoryRepositoryInterface $noCatRepository */ | ||||
|         $noCatRepository = app(NoCategoryRepositoryInterface::class); | ||||
|  | ||||
|         $categories    = $repository->getCategories(); | ||||
|         $earnedWith    = $opsRepository->listIncome($start, $end, $accounts); | ||||
|         $spentWith     = $opsRepository->listExpenses($start, $end, $accounts); | ||||
|         $earnedWithout = $noCatRepository->listIncome($start, $end, $accounts); | ||||
|         $spentWithout  = $noCatRepository->listExpenses($start, $end, $accounts); | ||||
|  | ||||
|         $report = [ | ||||
|             'categories' => [], | ||||
|             'sums'       => [], | ||||
|         ]; | ||||
|         /** @var Category $category */ | ||||
|         foreach ($categories as $category) { | ||||
|             $spent  = $opsRepository->spentInPeriod($category, $accounts, $start, $end); | ||||
|             $earned = $opsRepository->earnedInPeriod($category, $accounts, $start, $end); | ||||
|             if (0 === count($spent) && 0 === count($earned)) { | ||||
|                 continue; | ||||
|             } | ||||
|             $currencies = array_unique(array_merge(array_keys($spent), array_keys($earned))); | ||||
|             foreach ($currencies as $code) { | ||||
|                 $currencyInfo               = $spent[$code] ?? $earned[$code]; | ||||
|                 $key                        = sprintf('%s-%s', $category->id, $code); | ||||
|                 $report['categories'][$key] = [ | ||||
|                     'name'                    => $category->name, | ||||
|                     'spent'                   => $spent[$code]['spent'] ?? '0', | ||||
|                     'earned'                  => $earned[$code]['earned'] ?? '0', | ||||
|                     'id'                      => $category->id, | ||||
|                     'currency_id'             => $currencyInfo['currency_id'], | ||||
|                     'currency_code'           => $currencyInfo['currency_code'], | ||||
|                     'currency_symbol'         => $currencyInfo['currency_symbol'], | ||||
|                     'currency_name'           => $currencyInfo['currency_name'], | ||||
|                     'currency_decimal_places' => $currencyInfo['currency_decimal_places'], | ||||
|                 ]; | ||||
|  | ||||
|         // needs four for-each loops. | ||||
|         // TODO improve this. | ||||
|         foreach ([$earnedWith, $spentWith] as $data) { | ||||
|             foreach ($data as $currencyId => $currencyRow) { | ||||
|                 $report['sums'][$currencyId] = $report['sums'][$currencyId] ?? [ | ||||
|                         'spent'                     => '0', | ||||
|                         'earned'                     => '0', | ||||
|                         'sum'                     => '0', | ||||
|                         'currency_id'             => $currencyRow['currency_id'], | ||||
|                         'currency_symbol'         => $currencyRow['currency_symbol'], | ||||
|                         'currency_name'           => $currencyRow['currency_name'], | ||||
|                         'currency_code'           => $currencyRow['currency_code'], | ||||
|                         'currency_decimal_places' => $currencyRow['currency_decimal_places'], | ||||
|                     ]; | ||||
|  | ||||
|  | ||||
|                 foreach ($currencyRow['categories'] as $categoryId => $categoryRow) { | ||||
|                     $key                        = sprintf('%s-%s', $currencyId, $categoryId); | ||||
|                     $report['categories'][$key] = $report['categories'][$key] ?? [ | ||||
|                             'id'                      => $categoryId, | ||||
|                             'title'                   => sprintf('%s (%s)', $categoryRow['name'], $currencyRow['currency_name']), | ||||
|                             'currency_id'             => $currencyRow['currency_id'], | ||||
|                             'currency_symbol'         => $currencyRow['currency_symbol'], | ||||
|                             'currency_name'           => $currencyRow['currency_name'], | ||||
|                             'currency_code'           => $currencyRow['currency_code'], | ||||
|                             'currency_decimal_places' => $currencyRow['currency_decimal_places'], | ||||
|                             'spent'                   => '0', | ||||
|                             'earned'                  => '0', | ||||
|                             'sum'                     => '0', | ||||
|                         ]; | ||||
|                     // loop journals: | ||||
|                     foreach ($categoryRow['transaction_journals'] as $journal) { | ||||
|                         // sum of sums | ||||
|                         $report['sums'][$currencyId]['sum']   = bcadd($report['sums'][$currencyId]['sum'], $journal['amount']); | ||||
|                         // sum of spent: | ||||
|                         $report['sums'][$currencyId]['spent']   = -1 === bccomp($journal['amount'], '0') ? bcadd($report['sums'][$currencyId]['spent'], $journal['amount']): $report['sums'][$currencyId]['spent']; | ||||
|                         // sum of earned | ||||
|                         $report['sums'][$currencyId]['earned']   = 1 === bccomp($journal['amount'], '0') ? bcadd($report['sums'][$currencyId]['earned'], $journal['amount']): $report['sums'][$currencyId]['earned']; | ||||
|  | ||||
|                         // sum of category | ||||
|                         $report['categories'][$key]['sum']    = bcadd($report['categories'][$key]['sum'], $journal['amount']); | ||||
|                         // total spent in category | ||||
|                         $report['categories'][$key]['spent']  = -1 === bccomp($journal['amount'], '0') ? bcadd( | ||||
|                             $report['categories'][$key]['spent'], $journal['amount'] | ||||
|                         ) : $report['categories'][$key]['spent']; | ||||
|                         // total earned in category | ||||
|                         $report['categories'][$key]['earned'] = 1 === bccomp($journal['amount'], '0') ? bcadd( | ||||
|                             $report['categories'][$key]['earned'], $journal['amount'] | ||||
|                         ) : $report['categories'][$key]['earned']; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         $sum = []; | ||||
|         /** | ||||
|          * @var string $categoryId | ||||
|          * @var array  $row | ||||
|          */ | ||||
|         foreach ($report['categories'] as $categoryId => $row) { | ||||
|             $sum[$categoryId] = (float)$row['spent']; | ||||
|         } | ||||
|         array_multisort($sum, SORT_ASC, $report['categories']); | ||||
|         foreach ([$earnedWithout, $spentWithout] as $data) { | ||||
|             foreach ($data as $currencyId => $currencyRow) { | ||||
|                 $report['sums'][$currencyId] = $report['sums'][$currencyId] ?? [ | ||||
|                         'spent'                   => '0', | ||||
|                         'earned'                  => '0', | ||||
|                         'sum'                     => '0', | ||||
|                         'currency_id'             => $currencyRow['currency_id'], | ||||
|                         'currency_symbol'         => $currencyRow['currency_symbol'], | ||||
|                         'currency_name'           => $currencyRow['currency_name'], | ||||
|                         'currency_code'           => $currencyRow['currency_code'], | ||||
|                         'currency_decimal_places' => $currencyRow['currency_decimal_places'], | ||||
|                     ]; | ||||
|                 $key                         = sprintf('%s-0', $currencyId); | ||||
|                 $report['categories'][$key]  = $report['categories'][$key] ?? [ | ||||
|                         'id'                      => 0, | ||||
|                         'title'                   => sprintf('%s (%s)', trans('firefly.noCategory'), $currencyRow['currency_name']), | ||||
|                         'currency_id'             => $currencyRow['currency_id'], | ||||
|                         'currency_symbol'         => $currencyRow['currency_symbol'], | ||||
|                         'currency_name'           => $currencyRow['currency_name'], | ||||
|                         'currency_code'           => $currencyRow['currency_code'], | ||||
|                         'currency_decimal_places' => $currencyRow['currency_decimal_places'], | ||||
|                         'spent'                   => '0', | ||||
|                         'earned'                  => '0', | ||||
|                         'sum'                     => '0', | ||||
|                     ]; | ||||
|                 // loop journals: | ||||
|                 foreach ($currencyRow['transaction_journals'] as $journal) { | ||||
|                     // sum of all | ||||
|                     $report['sums'][$currencyId]['sum']   = bcadd($report['sums'][$currencyId]['sum'], $journal['amount']); | ||||
|  | ||||
|         // get sums: | ||||
|         foreach ($report['categories'] as $entry) { | ||||
|             $currencyId                            = $entry['currency_id']; | ||||
|             $report['sums'][$currencyId]           = $report['sums'][$currencyId] ?? [ | ||||
|                     'spent'                   => '0', | ||||
|                     'earned'                  => '0', | ||||
|                     'currency_id'             => $entry['currency_id'], | ||||
|                     'currency_code'           => $entry['currency_code'], | ||||
|                     'currency_symbol'         => $entry['currency_symbol'], | ||||
|                     'currency_name'           => $entry['currency_name'], | ||||
|                     'cyrrency_decimal_places' => $entry['currency_decimal_places'], | ||||
|                 ]; | ||||
|             $report['sums'][$currencyId]['spent']  = bcadd($report['sums'][$currencyId]['spent'], $entry['spent']); | ||||
|             $report['sums'][$currencyId]['earned'] = bcadd($report['sums'][$currencyId]['earned'], $entry['earned']); | ||||
|                     // sum of spent: | ||||
|                     $report['sums'][$currencyId]['spent']   = -1 === bccomp($journal['amount'], '0') ? bcadd($report['sums'][$currencyId]['spent'], $journal['amount']): $report['sums'][$currencyId]['spent']; | ||||
|                     // sum of earned | ||||
|                     $report['sums'][$currencyId]['earned']   = 1 === bccomp($journal['amount'], '0') ? bcadd($report['sums'][$currencyId]['earned'], $journal['amount']): $report['sums'][$currencyId]['earned']; | ||||
|  | ||||
|                     // sum of category | ||||
|                     $report['categories'][$key]['sum']    = bcadd($report['categories'][$key]['sum'], $journal['amount']); | ||||
|                     // total spent in no category | ||||
|                     $report['categories'][$key]['spent']  = -1 === bccomp($journal['amount'], '0') ? bcadd( | ||||
|                         $report['categories'][$key]['spent'], $journal['amount'] | ||||
|                     ) : $report['categories'][$key]['spent']; | ||||
|                     // total earned in no category | ||||
|                     $report['categories'][$key]['earned'] = 1 === bccomp($journal['amount'], '0') ? bcadd( | ||||
|                         $report['categories'][$key]['earned'], $journal['amount'] | ||||
|                     ) : $report['categories'][$key]['earned']; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreStart | ||||
|   | ||||
		Reference in New Issue
	
	Block a user