mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	Fix #9650
This commit is contained in:
		| @@ -57,7 +57,7 @@ class IndexController extends Controller | |||||||
| 
 | 
 | ||||||
|         $this->middleware( |         $this->middleware( | ||||||
|             function ($request, $next) { |             function ($request, $next) { | ||||||
|                 app('view')->share('title', (string) trans('firefly.bills')); |                 app('view')->share('title', (string)trans('firefly.bills')); | ||||||
|                 app('view')->share('mainTitleIcon', 'fa-calendar-o'); |                 app('view')->share('mainTitleIcon', 'fa-calendar-o'); | ||||||
|                 $this->repository = app(BillRepositoryInterface::class); |                 $this->repository = app(BillRepositoryInterface::class); | ||||||
| 
 | 
 | ||||||
| @@ -79,7 +79,6 @@ class IndexController extends Controller | |||||||
|         $total      = $collection->count(); |         $total      = $collection->count(); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         $parameters = new ParameterBag(); |         $parameters = new ParameterBag(); | ||||||
|         // sub one day from temp start so the last paid date is one day before it should be.
 |         // sub one day from temp start so the last paid date is one day before it should be.
 | ||||||
|         $tempStart = clone $start; |         $tempStart = clone $start; | ||||||
| @@ -112,7 +111,7 @@ class IndexController extends Controller | |||||||
|         $bills = [ |         $bills = [ | ||||||
|             0 => [ // the index is the order, not the ID.
 |             0 => [ // the index is the order, not the ID.
 | ||||||
|                    'object_group_id'    => 0, |                    'object_group_id'    => 0, | ||||||
|                 'object_group_title' => (string) trans('firefly.default_group_title_name'), |                    'object_group_title' => (string)trans('firefly.default_group_title_name'), | ||||||
|                    'bills'              => [], |                    'bills'              => [], | ||||||
|             ], |             ], | ||||||
|         ]; |         ]; | ||||||
| @@ -120,7 +119,7 @@ class IndexController extends Controller | |||||||
|         /** @var Bill $bill */ |         /** @var Bill $bill */ | ||||||
|         foreach ($collection as $bill) { |         foreach ($collection as $bill) { | ||||||
|             $array      = $transformer->transform($bill); |             $array      = $transformer->transform($bill); | ||||||
|             $groupOrder                       = (int) $array['object_group_order']; |             $groupOrder = (int)$array['object_group_order']; | ||||||
|             // make group array if necessary:
 |             // make group array if necessary:
 | ||||||
|             $bills[$groupOrder] ??= [ |             $bills[$groupOrder] ??= [ | ||||||
|                 'object_group_id'    => $array['object_group_id'], |                 'object_group_id'    => $array['object_group_id'], | ||||||
| @@ -173,16 +172,28 @@ class IndexController extends Controller | |||||||
|                     'currency_symbol'         => $bill['currency_symbol'], |                     'currency_symbol'         => $bill['currency_symbol'], | ||||||
|                     'currency_decimal_places' => $bill['currency_decimal_places'], |                     'currency_decimal_places' => $bill['currency_decimal_places'], | ||||||
|                     'avg'                     => '0', |                     'avg'                     => '0', | ||||||
|  |                     'total_left_to_pay'       => '0', | ||||||
|                     'period'                  => $range, |                     'period'                  => $range, | ||||||
|                     'per_period'              => '0', |                     'per_period'              => '0', | ||||||
|                 ]; |                 ]; | ||||||
| 
 | 
 | ||||||
|                 // only fill in avg when bill is active.
 |                 // only fill in avg when bill is active.
 | ||||||
|                 if (null !== $bill['next_expected_match']) { |                 if (null !== $bill['next_expected_match']) { | ||||||
|                     $avg                                   = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2'); |                     $avg                                   = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2'); | ||||||
|                     $avg                                   = bcmul($avg, (string) count($bill['pay_dates'])); |                     $avg                                   = bcmul($avg, (string)count($bill['pay_dates'])); | ||||||
|                     $sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg); |                     $sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg); | ||||||
|                 } |                 } | ||||||
|  |                 // only fill in total_left_to_pay when bill is not yet paid.
 | ||||||
|  |                 if (count($bill['paid_dates']) < count($bill['pay_dates'])) { | ||||||
|  |                     $count = count($bill['pay_dates']) - count($bill['paid_dates']); | ||||||
|  |                     if ($count > 0) { | ||||||
|  |                         $avg                                                 = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2'); | ||||||
|  |                         $avg                                                 = bcmul($avg, (string)$count); | ||||||
|  |                         $sums[$groupOrder][$currencyId]['total_left_to_pay'] = bcadd($sums[$groupOrder][$currencyId]['total_left_to_pay'], $avg); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|                 // fill in per period regardless:
 |                 // fill in per period regardless:
 | ||||||
|                 $sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range)); |                 $sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range)); | ||||||
|             } |             } | ||||||
| @@ -193,7 +204,7 @@ class IndexController extends Controller | |||||||
| 
 | 
 | ||||||
|     private function amountPerPeriod(array $bill, string $range): string |     private function amountPerPeriod(array $bill, string $range): string | ||||||
|     { |     { | ||||||
|         $avg        = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2'); |         $avg = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2'); | ||||||
| 
 | 
 | ||||||
|         app('log')->debug(sprintf('Amount per period for bill #%d "%s"', $bill['id'], $bill['name'])); |         app('log')->debug(sprintf('Amount per period for bill #%d "%s"', $bill['id'], $bill['name'])); | ||||||
|         app('log')->debug(sprintf('Average is %s', $avg)); |         app('log')->debug(sprintf('Average is %s', $avg)); | ||||||
| @@ -206,8 +217,8 @@ class IndexController extends Controller | |||||||
|             'weekly'    => '52.17', |             'weekly'    => '52.17', | ||||||
|             'daily'     => '365.24', |             'daily'     => '365.24', | ||||||
|         ]; |         ]; | ||||||
|         $yearAmount = bcmul($avg, bcdiv($multiplies[$bill['repeat_freq']], (string) ($bill['skip'] + 1))); |         $yearAmount = bcmul($avg, bcdiv($multiplies[$bill['repeat_freq']], (string)($bill['skip'] + 1))); | ||||||
|         app('log')->debug(sprintf('Amount per year is %s (%s * %s / %s)', $yearAmount, $avg, $multiplies[$bill['repeat_freq']], (string) ($bill['skip'] + 1))); |         app('log')->debug(sprintf('Amount per year is %s (%s * %s / %s)', $yearAmount, $avg, $multiplies[$bill['repeat_freq']], (string)($bill['skip'] + 1))); | ||||||
| 
 | 
 | ||||||
|         // per period:
 |         // per period:
 | ||||||
|         $division  = [ |         $division  = [ | ||||||
| @@ -258,8 +269,8 @@ class IndexController extends Controller | |||||||
|                     'period'                  => $entry['period'], |                     'period'                  => $entry['period'], | ||||||
|                     'per_period'              => '0', |                     'per_period'              => '0', | ||||||
|                 ]; |                 ]; | ||||||
|                 $totals[$currencyId]['avg']        = bcadd($totals[$currencyId]['avg'], (string) $entry['avg']); |                 $totals[$currencyId]['avg']        = bcadd($totals[$currencyId]['avg'], (string)$entry['avg']); | ||||||
|                 $totals[$currencyId]['per_period'] = bcadd($totals[$currencyId]['per_period'], (string) $entry['per_period']); |                 $totals[$currencyId]['per_period'] = bcadd($totals[$currencyId]['per_period'], (string)$entry['per_period']); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -271,8 +282,8 @@ class IndexController extends Controller | |||||||
|      */ |      */ | ||||||
|     public function setOrder(Request $request, Bill $bill): JsonResponse |     public function setOrder(Request $request, Bill $bill): JsonResponse | ||||||
|     { |     { | ||||||
|         $objectGroupTitle = (string) $request->get('objectGroupTitle'); |         $objectGroupTitle = (string)$request->get('objectGroupTitle'); | ||||||
|         $newOrder         = (int) $request->get('order'); |         $newOrder         = (int)$request->get('order'); | ||||||
|         $this->repository->setOrder($bill, $newOrder); |         $this->repository->setOrder($bill, $newOrder); | ||||||
|         if ('' !== $objectGroupTitle) { |         if ('' !== $objectGroupTitle) { | ||||||
|             $this->repository->setObjectGroup($bill, $objectGroupTitle); |             $this->repository->setObjectGroup($bill, $objectGroupTitle); | ||||||
|   | |||||||
| @@ -56,6 +56,7 @@ class SubscriptionEnrichment implements EnrichmentInterface | |||||||
|         $this->collectPaidDates(); |         $this->collectPaidDates(); | ||||||
|         $this->collectPayDates(); |         $this->collectPayDates(); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|         // TODO clean me up.
 |         // TODO clean me up.
 | ||||||
| 
 | 
 | ||||||
|         $notes            = $this->notes; |         $notes            = $this->notes; | ||||||
|   | |||||||
| @@ -110,8 +110,8 @@ class BillDateCalculator | |||||||
|             $currentStart      = clone $nextExpectedMatch; |             $currentStart      = clone $nextExpectedMatch; | ||||||
| 
 | 
 | ||||||
|             ++$loop; |             ++$loop; | ||||||
|             if ($loop > 12) { |             if ($loop > 31) { | ||||||
|                 Log::debug('Loop is more than 12, so we break.'); |                 Log::debug('Loop is more than 31, so we break.'); | ||||||
| 
 | 
 | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1864,6 +1864,7 @@ return [ | |||||||
|     'remove_budgeted_amount'                                                    => 'Remove budgeted amount in :currency', |     'remove_budgeted_amount'                                                    => 'Remove budgeted amount in :currency', | ||||||
| 
 | 
 | ||||||
|     // bills:
 |     // bills:
 | ||||||
|  |     'left_to_pay_active_bills' => 'active, expected and not yet paid subscriptions', | ||||||
|     'left_to_pay_lc' => 'left to pay', |     'left_to_pay_lc' => 'left to pay', | ||||||
|     'less_than_expected' => 'less than expected', |     'less_than_expected' => 'less than expected', | ||||||
|     'more_than_expected' => 'more than expected', |     'more_than_expected' => 'more than expected', | ||||||
|   | |||||||
| @@ -158,8 +158,8 @@ | |||||||
|                                     <td style="width:33%;">{{ 'amount'|_ }}</td> |                                     <td style="width:33%;">{{ 'amount'|_ }}</td> | ||||||
|                                     <td> |                                     <td> | ||||||
|                                         {{ formatAmountBySymbol(limit.amount, limit.transactionCurrency.symbol, limit.transactionCurrency.decimal_places) }} |                                         {{ formatAmountBySymbol(limit.amount, limit.transactionCurrency.symbol, limit.transactionCurrency.decimal_places) }} | ||||||
|                                         {% if convertToPrimary and 0 != limit.pc_amount %} |                                         {% if convertToPrimary and null != limit.native_amount %} | ||||||
|                                             ({{ formatAmountBySymbol(limit.pc_amount, primaryCurrency.symbol, primaryCurrency.decimal_places) }}) |                                             ({{ formatAmountBySymbol(limit.native_amount, primaryCurrency.symbol, primaryCurrency.decimal_places) }}) | ||||||
|                                         {% endif %} |                                         {% endif %} | ||||||
|                                     </td> |                                     </td> | ||||||
|                                 </tr> |                                 </tr> | ||||||
|   | |||||||
| @@ -189,6 +189,21 @@ | |||||||
|                         <td class="hidden-sm hidden-xs"> </td><!-- repeats --> |                         <td class="hidden-sm hidden-xs"> </td><!-- repeats --> | ||||||
|                     </tr> |                     </tr> | ||||||
|                 {% endif %} |                 {% endif %} | ||||||
|  |                 {% if '0' != sum.total_left_to_pay %} | ||||||
|  |                     <tr> | ||||||
|  |                         <td class="hidden-sm hidden-xs"> </td> <!-- handle --> | ||||||
|  |                         <td class="hidden-sm hidden-xs"> </td> <!-- buttons --> | ||||||
|  |                         <td colspan="2" style="text-align: right;"> <!-- title --> | ||||||
|  |                             <small>{{ 'sum'|_ }} ({{ sum.currency_name }}) ({{ 'left_to_pay_active_bills'|_ }})</small> | ||||||
|  |                         </td> | ||||||
|  |                         <td style="text-align: right;"> <!-- amount --> | ||||||
|  |                             {{ formatAmountBySymbol(sum.total_left_to_pay, sum.currency_symbol, sum.currency_decimal_places) }} | ||||||
|  |                         </td> | ||||||
|  |                         <td> </td> <!-- paid in period --> | ||||||
|  |                         <td class="hidden-sm hidden-xs"> </td> <!-- next expected match --> | ||||||
|  |                         <td class="hidden-sm hidden-xs"> </td><!-- repeats --> | ||||||
|  |                     </tr> | ||||||
|  |                 {% endif %} | ||||||
|                 {% if '0' != sum.per_period %} |                 {% if '0' != sum.per_period %} | ||||||
|                     <tr> |                     <tr> | ||||||
|                         <td class="hidden-sm hidden-xs"> </td> <!-- handle --> |                         <td class="hidden-sm hidden-xs"> </td> <!-- handle --> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user