diff --git a/app/Helpers/Collection/BillLine.php b/app/Helpers/Collection/BillLine.php index ed5dde7fe7..849f14b8a2 100644 --- a/app/Helpers/Collection/BillLine.php +++ b/app/Helpers/Collection/BillLine.php @@ -42,9 +42,39 @@ class BillLine protected $min; /** @var Carbon */ private $lastHitDate; + /** @var Carbon */ + private $payDate; + /** @var Carbon */ + private $endOfPayDate; /** @var int */ private $transactionJournalId; + /** + * @return Carbon + */ + public function getPayDate(): Carbon + { + return $this->payDate; + } + + /** + * @return Carbon + */ + public function getEndOfPayDate(): Carbon + { + return $this->endOfPayDate; + } + + /** + * @param Carbon $endOfPayDate + */ + public function setEndOfPayDate(Carbon $endOfPayDate): void + { + $this->endOfPayDate = $endOfPayDate; + } + + + /** * BillLine constructor. */ @@ -172,4 +202,12 @@ class BillLine { $this->hit = $hit; } + + /** + * @param Carbon $payDate + */ + public function setPayDate(Carbon $payDate): void + { + $this->payDate = $payDate; + } } diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index 3b812533da..6fa664df84 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -71,34 +71,43 @@ class ReportHelper implements ReportHelperInterface /** @var BillRepositoryInterface $repository */ $repository = app(BillRepositoryInterface::class); $bills = $repository->getBillsForAccounts($accounts); - $collector = app(JournalCollectorInterface::class); - $collector->setAccounts($accounts)->setRange($start, $end)->setBills($bills); - $journals = $collector->getJournals(); + $collection = new BillCollection; $collection->setStartDate($start); $collection->setEndDate($end); /** @var Bill $bill */ foreach ($bills as $bill) { - $billLine = new BillLine; - $billLine->setBill($bill); - $billLine->setMin(strval($bill->amount_min)); - $billLine->setMax(strval($bill->amount_max)); - $billLine->setHit(false); - $entry = $journals->filter( - function (Transaction $transaction) use ($bill) { - return $transaction->bill_id === $bill->id; + $expectedDates = $repository->getPayDatesInRange($bill, $start, $end); + foreach($expectedDates as $payDate) { + $endOfPayPeriod = app('navigation')->endOfX($payDate, $bill->repeat_freq, null); + + $collector = app(JournalCollectorInterface::class); + $collector->setAccounts($accounts)->setRange($payDate, $endOfPayPeriod)->setBills($bills); + $journals = $collector->getJournals(); + + $billLine = new BillLine; + $billLine->setBill($bill); + $billLine->setPayDate($payDate); + $billLine->setEndOfPayDate($endOfPayPeriod); + $billLine->setMin(strval($bill->amount_min)); + $billLine->setMax(strval($bill->amount_max)); + $billLine->setHit(false); + $entry = $journals->filter( + function (Transaction $transaction) use ($bill) { + return $transaction->bill_id === $bill->id; + } + ); + $first = $entry->first(); + if (null !== $first) { + $billLine->setTransactionJournalId($first->id); + $billLine->setAmount($first->transaction_amount); + $billLine->setLastHitDate($first->date); + $billLine->setHit(true); + } + if ($billLine->isActive() || $billLine->isHit()) { + $collection->addBill($billLine); } - ); - $first = $entry->first(); - if (null !== $first) { - $billLine->setTransactionJournalId($first->id); - $billLine->setAmount($first->transaction_amount); - $billLine->setLastHitDate($first->date); - $billLine->setHit(true); - } - if ($billLine->isActive() || $billLine->isHit()) { - $collection->addBill($billLine); } } $collection->filterBills(); diff --git a/app/Http/Controllers/BillController.php b/app/Http/Controllers/BillController.php index 9a61d149f7..7aa321d9a8 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -186,11 +186,12 @@ class BillController extends Controller // paid in this period? $bill->paidDates = $repository->getPaidDatesInRange($bill, $start, $end); $bill->payDates = $repository->getPayDatesInRange($bill, $start, $end); - $lastDate = clone $start; + $lastPaidDate = $this->lastPaidDate($repository->getPaidDatesInRange($bill, $start, $end), $start); if ($bill->paidDates->count() >= $bill->payDates->count()) { - $lastDate = $end; + // if all bills have been been paid, jump to next period. + $lastPaidDate = $end; } - $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, $lastDate); + $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, $lastPaidDate); } ); @@ -235,6 +236,8 @@ class BillController extends Controller { /** @var Carbon $date */ $date = session('start'); + /** @var Carbon $end */ + $end = session('end'); $year = $date->year; $page = intval($request->get('page')); $pageSize = intval(Preferences::get('transactionPageSize', 50)->data); @@ -249,7 +252,15 @@ class BillController extends Controller $transactions = $collector->getPaginatedJournals(); $transactions->setPath(route('bills.show', [$bill->id])); - $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, new Carbon); + + $bill->paidDates = $repository->getPaidDatesInRange($bill, $date, $end); + $bill->payDates = $repository->getPayDatesInRange($bill, $date, $end); + $lastPaidDate = $this->lastPaidDate($repository->getPaidDatesInRange($bill, $date, $end), $date); + if ($bill->paidDates->count() >= $bill->payDates->count()) { + // if all bills have been been paid, jump to next period. + $lastPaidDate = $end; + } + $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, $lastPaidDate); $hideBill = true; $subTitle = e($bill->name); @@ -325,4 +336,29 @@ class BillController extends Controller return redirect($this->getPreviousUri('bills.edit.uri')); } + + /** + * Returns the latest date in the set, or start when set is empty. + * + * @param Collection $dates + * @param Carbon $default + * + * @return Carbon + */ + private function lastPaidDate(Collection $dates, Carbon $default): Carbon + { + if ($dates->count() === 0) { + return $default; + } + $latest = $dates->first(); + /** @var Carbon $date */ + foreach ($dates as $date) { + if ($date->gte($latest)) { + $latest = $date; + } + } + + return $latest; + + } } diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 718e80e255..9fea10b2da 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -589,6 +589,7 @@ return [ 'not_or_not_yet' => 'Not (yet)', 'not_expected_period' => 'Not expected this period', 'bill_is_active' => 'Bill is active', + 'bill_expected_between' => 'Expeced between :start and :end', 'bill_will_automatch' => 'Bill will automatically linked to matching transactions', 'skips_over' => 'skips over', diff --git a/resources/views/reports/partials/bills.twig b/resources/views/reports/partials/bills.twig index 5e653a1925..39eda91cf4 100644 --- a/resources/views/reports/partials/bills.twig +++ b/resources/views/reports/partials/bills.twig @@ -18,6 +18,9 @@ {{ line.getBill.name }} +
+ {{ trans('firefly.bill_expected_between', {start: line.getPayDate.formatLocalized(monthAndDayFormat), end: line.getEndOfPayDate.formatLocalized(monthAndDayFormat) }) }} +
{{ line.getMin|formatAmount }} {{ line.getMax|formatAmount }}