| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2016-02-05 12:08:25 +01:00
										 |  |  | declare(strict_types = 1); | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace FireflyIII\Repositories\Bill; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use Carbon\Carbon; | 
					
						
							| 
									
										
										
										
											2015-05-08 14:00:49 +02:00
										 |  |  | use DB; | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  | use FireflyIII\Models\Bill; | 
					
						
							|  |  |  | use FireflyIII\Models\TransactionJournal; | 
					
						
							| 
									
										
										
										
											2015-12-27 17:29:41 +01:00
										 |  |  | use FireflyIII\Models\TransactionType; | 
					
						
							| 
									
										
										
										
											2016-03-03 08:40:25 +01:00
										 |  |  | use FireflyIII\User; | 
					
						
							| 
									
										
										
										
											2015-12-26 09:39:35 +01:00
										 |  |  | use Illuminate\Database\Query\JoinClause; | 
					
						
							| 
									
										
										
										
											2016-04-21 10:23:19 +02:00
										 |  |  | use Illuminate\Pagination\LengthAwarePaginator; | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  | use Illuminate\Support\Collection; | 
					
						
							| 
									
										
										
										
											2015-03-03 17:40:17 +01:00
										 |  |  | use Navigation; | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Class BillRepository | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @package FireflyIII\Repositories\Bill | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class BillRepository implements BillRepositoryInterface | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-04-07 10:14:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-03 08:40:25 +01:00
										 |  |  |     /** @var User */ | 
					
						
							|  |  |  |     private $user; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * BillRepository constructor. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param User $user | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __construct(User $user) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->user = $user; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @param Bill $bill | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2016-04-06 09:27:45 +02:00
										 |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function destroy(Bill $bill): bool | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |         $bill->delete(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 13:07:19 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Find a bill by ID. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param int $billId | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Bill | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function find(int $billId) : Bill | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $bill = $this->user->bills()->find($billId); | 
					
						
							|  |  |  |         if (is_null($bill)) { | 
					
						
							|  |  |  |             $bill = new Bill; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $bill; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @return Collection | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getActiveBills(): Collection | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         /** @var Collection $set */ | 
					
						
							| 
									
										
										
										
											2016-03-03 08:40:25 +01:00
										 |  |  |         $set = $this->user->bills() | 
					
						
							|  |  |  |                           ->where('active', 1) | 
					
						
							|  |  |  |                           ->get( | 
					
						
							|  |  |  |                               [ | 
					
						
							|  |  |  |                                   'bills.*', | 
					
						
							| 
									
										
										
										
											2016-04-21 10:23:19 +02:00
										 |  |  |                                   DB::raw('((`bills`.`amount_min` + `bills`.`amount_max`) / 2) as `expectedAmount`'), | 
					
						
							| 
									
										
										
										
											2016-03-03 08:40:25 +01:00
										 |  |  |                               ] | 
					
						
							|  |  |  |                           )->sortBy('name'); | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $set; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-01 21:07:15 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Returns all journals connected to these bills in the given range. Amount paid | 
					
						
							|  |  |  |      * is stored in "journalAmount" as a negative number. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Collection $bills | 
					
						
							|  |  |  |      * @param Carbon     $start | 
					
						
							|  |  |  |      * @param Carbon     $end | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Collection | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getAllJournalsInRange(Collection $bills, Carbon $start, Carbon $end): Collection | 
					
						
							| 
									
										
										
										
											2016-01-01 21:07:15 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         $ids = $bills->pluck('id')->toArray(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-03 08:40:25 +01:00
										 |  |  |         $set = $this->user->transactionjournals() | 
					
						
							|  |  |  |                           ->leftJoin( | 
					
						
							|  |  |  |                               'transactions', function (JoinClause $join) { | 
					
						
							|  |  |  |                               $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | 
					
						
							|  |  |  |                           } | 
					
						
							|  |  |  |                           ) | 
					
						
							|  |  |  |                           ->whereIn('bill_id', $ids) | 
					
						
							|  |  |  |                           ->before($end) | 
					
						
							|  |  |  |                           ->after($start) | 
					
						
							|  |  |  |                           ->groupBy('transaction_journals.bill_id') | 
					
						
							|  |  |  |                           ->get( | 
					
						
							|  |  |  |                               [ | 
					
						
							|  |  |  |                                   'transaction_journals.bill_id', | 
					
						
							|  |  |  |                                   'transaction_journals.id', | 
					
						
							|  |  |  |                                   DB::raw('SUM(`transactions`.`amount`) as `journalAmount`'), | 
					
						
							|  |  |  |                               ] | 
					
						
							|  |  |  |                           ); | 
					
						
							| 
									
										
										
										
											2016-01-01 21:07:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $set; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @return Collection | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getBills(): Collection | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-04-06 09:15:59 +02:00
										 |  |  |         /** @var Collection $set */ | 
					
						
							| 
									
										
										
										
											2016-03-03 08:40:25 +01:00
										 |  |  |         $set = $this->user->bills()->orderBy('name', 'ASC')->get(); | 
					
						
							| 
									
										
										
										
											2015-04-06 09:15:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-01 10:52:42 +02:00
										 |  |  |         $set = $set->sortBy( | 
					
						
							|  |  |  |             function (Bill $bill) { | 
					
						
							| 
									
										
										
										
											2015-09-08 19:36:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 $int = $bill->active == 1 ? 0 : 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-08 19:38:04 +02:00
										 |  |  |                 return $int . strtolower($bill->name); | 
					
						
							| 
									
										
										
										
											2015-07-01 10:52:42 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-06 09:15:59 +02:00
										 |  |  |         return $set; | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 10:33:19 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @param Collection $accounts | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Collection | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getBillsForAccounts(Collection $accounts): Collection | 
					
						
							| 
									
										
										
										
											2015-12-12 10:33:19 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-12-30 09:16:58 +01:00
										 |  |  |         $ids = $accounts->pluck('id')->toArray(); | 
					
						
							| 
									
										
										
										
											2016-03-03 08:40:25 +01:00
										 |  |  |         $set = $this->user->bills() | 
					
						
							|  |  |  |                           ->leftJoin( | 
					
						
							|  |  |  |                               'transaction_journals', function (JoinClause $join) { | 
					
						
							|  |  |  |                               $join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at'); | 
					
						
							|  |  |  |                           } | 
					
						
							|  |  |  |                           ) | 
					
						
							|  |  |  |                           ->leftJoin( | 
					
						
							|  |  |  |                               'transactions', function (JoinClause $join) { | 
					
						
							|  |  |  |                               $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); | 
					
						
							|  |  |  |                           } | 
					
						
							|  |  |  |                           ) | 
					
						
							|  |  |  |                           ->whereIn('transactions.account_id', $ids) | 
					
						
							|  |  |  |                           ->whereNull('transaction_journals.deleted_at') | 
					
						
							|  |  |  |                           ->groupBy('bills.id') | 
					
						
							|  |  |  |                           ->get(['bills.*']); | 
					
						
							| 
									
										
										
										
											2015-12-12 10:33:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $set = $set->sortBy( | 
					
						
							|  |  |  |             function (Bill $bill) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 $int = $bill->active == 1 ? 0 : 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return $int . strtolower($bill->name); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $set; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get the total amount of money paid for the users active bills in the date range given. | 
					
						
							|  |  |  |      * This amount will be negative (they're expenses). | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Carbon $start | 
					
						
							|  |  |  |      * @param Carbon $end | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getBillsPaidInRange(Carbon $start, Carbon $end): string | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         $amount = '0'; | 
					
						
							|  |  |  |         $bills  = $this->getActiveBills(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** @var Bill $bill */ | 
					
						
							|  |  |  |         foreach ($bills as $bill) { | 
					
						
							|  |  |  |             $ranges = $this->getRanges($bill, $start, $end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             foreach ($ranges as $range) { | 
					
						
							| 
									
										
										
										
											2016-02-05 12:28:05 +01:00
										 |  |  |                 $paid      = $bill->transactionjournals() | 
					
						
							|  |  |  |                                   ->before($range['end']) | 
					
						
							|  |  |  |                                   ->after($range['start']) | 
					
						
							|  |  |  |                                   ->leftJoin( | 
					
						
							|  |  |  |                                       'transactions', function (JoinClause $join) { | 
					
						
							|  |  |  |                                       $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | 
					
						
							|  |  |  |                                   } | 
					
						
							|  |  |  |                                   ) | 
					
						
							| 
									
										
										
										
											2016-02-07 07:56:58 +01:00
										 |  |  |                                   ->first([DB::raw('SUM(`transactions`.`amount`) as `sum_amount`')]); | 
					
						
							| 
									
										
										
										
											2016-02-05 12:28:05 +01:00
										 |  |  |                 $sumAmount = $paid->sum_amount ?? '0'; | 
					
						
							|  |  |  |                 $amount    = bcadd($amount, $sumAmount); | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $amount; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the total amount of money due for the users active bills in the date range given. This amount will be positive. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Carbon $start | 
					
						
							|  |  |  |      * @param Carbon $end | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getBillsUnpaidInRange(Carbon $start, Carbon $end): string | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         $amount = '0'; | 
					
						
							|  |  |  |         $bills  = $this->getActiveBills(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** @var Bill $bill */ | 
					
						
							|  |  |  |         foreach ($bills as $bill) { | 
					
						
							|  |  |  |             $ranges   = $this->getRanges($bill, $start, $end); | 
					
						
							|  |  |  |             $paidBill = '0'; | 
					
						
							|  |  |  |             foreach ($ranges as $range) { | 
					
						
							| 
									
										
										
										
											2016-02-05 12:28:05 +01:00
										 |  |  |                 $paid      = $bill->transactionjournals() | 
					
						
							|  |  |  |                                   ->before($range['end']) | 
					
						
							|  |  |  |                                   ->after($range['start']) | 
					
						
							|  |  |  |                                   ->leftJoin( | 
					
						
							|  |  |  |                                       'transactions', function (JoinClause $join) { | 
					
						
							|  |  |  |                                       $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '>', 0); | 
					
						
							|  |  |  |                                   } | 
					
						
							|  |  |  |                                   ) | 
					
						
							| 
									
										
										
										
											2016-02-07 07:56:58 +01:00
										 |  |  |                                   ->first([DB::raw('SUM(`transactions`.`amount`) as `sum_amount`')]); | 
					
						
							| 
									
										
										
										
											2016-02-05 12:28:05 +01:00
										 |  |  |                 $sumAmount = $paid->sum_amount ?? '0'; | 
					
						
							|  |  |  |                 $paidBill  = bcadd($sumAmount, $paidBill); | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |             if ($paidBill == 0) { | 
					
						
							|  |  |  |                 $amount = bcadd($amount, $bill->expectedAmount); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $amount; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2015-12-27 20:07:49 +01:00
										 |  |  |      * This method also returns the amount of the journal in "journalAmount" | 
					
						
							|  |  |  |      * for easy access. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |      * @param Bill $bill | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2016-04-21 10:23:19 +02:00
										 |  |  |      * @param int  $page | 
					
						
							|  |  |  |      * @param int  $pageSize | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return LengthAwarePaginator|Collection | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-04-21 10:23:19 +02:00
										 |  |  |     public function getJournals(Bill $bill, int $page, int $pageSize = 50): LengthAwarePaginator | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-21 10:23:19 +02:00
										 |  |  |         $offset    = ($page - 1) * $pageSize; | 
					
						
							|  |  |  |         $query     = $bill->transactionjournals() | 
					
						
							|  |  |  |                           ->expanded() | 
					
						
							| 
									
										
										
										
											2016-05-11 07:57:16 +02:00
										 |  |  |                           ->sortCorrectly(); | 
					
						
							| 
									
										
										
										
											2016-04-21 10:23:19 +02:00
										 |  |  |         $count     = $query->count(); | 
					
						
							| 
									
										
										
										
											2016-04-29 21:52:15 +02:00
										 |  |  |         $set       = $query->take($pageSize)->offset($offset)->get(TransactionJournal::queryFields()); | 
					
						
							| 
									
										
										
										
											2016-04-21 10:23:19 +02:00
										 |  |  |         $paginator = new LengthAwarePaginator($set, $count, $pageSize, $page); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $paginator; | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 10:14:10 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get all journals that were recorded on this bill between these dates. | 
					
						
							| 
									
										
										
										
											2016-04-25 18:43:09 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2015-04-07 10:14:10 +02:00
										 |  |  |      * @param Bill   $bill | 
					
						
							|  |  |  |      * @param Carbon $start | 
					
						
							|  |  |  |      * @param Carbon $end | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Collection | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getJournalsInRange(Bill $bill, Carbon $start, Carbon $end): Collection | 
					
						
							| 
									
										
										
										
											2015-04-07 10:14:10 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         return $bill->transactionjournals()->before($end)->after($start)->get(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @param Bill $bill | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Collection | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getPossiblyRelatedJournals(Bill $bill): Collection | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |         $set = new Collection( | 
					
						
							|  |  |  |             DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max) | 
					
						
							|  |  |  |               ->get(['transaction_journal_id']) | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |         ); | 
					
						
							| 
									
										
										
										
											2015-12-30 09:16:58 +01:00
										 |  |  |         $ids = $set->pluck('transaction_journal_id')->toArray(); | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $journals = new Collection; | 
					
						
							|  |  |  |         if (count($ids) > 0) { | 
					
						
							| 
									
										
										
										
											2016-03-03 08:40:25 +01:00
										 |  |  |             $journals = $this->user->transactionjournals()->transactionTypes([TransactionType::WITHDRAWAL])->whereIn('transaction_journals.id', $ids)->get( | 
					
						
							| 
									
										
										
										
											2015-10-03 17:55:08 +02:00
										 |  |  |                 ['transaction_journals.*'] | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $journals; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-03 17:40:17 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself) | 
					
						
							|  |  |  |      * and returns date ranges that fall within the given range; those ranges are the bills expected. When a bill is due on the 14th of the month and | 
					
						
							|  |  |  |      * you give 1st and the 31st of that month as argument, you'll get one response, matching the range of your bill. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Bill   $bill | 
					
						
							|  |  |  |      * @param Carbon $start | 
					
						
							|  |  |  |      * @param Carbon $end | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |      * @return array | 
					
						
							| 
									
										
										
										
											2015-03-03 17:40:17 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function getRanges(Bill $bill, Carbon $start, Carbon $end): array | 
					
						
							| 
									
										
										
										
											2015-03-03 17:40:17 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-18 19:33:02 +02:00
										 |  |  |         $startOfBill = Navigation::startOfPeriod($start, $bill->repeat_freq); | 
					
						
							| 
									
										
										
										
											2015-03-03 17:40:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // all periods of this bill up until the current period:
 | 
					
						
							|  |  |  |         $billStarts = []; | 
					
						
							|  |  |  |         while ($startOfBill < $end) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $endOfBill = Navigation::endOfPeriod($startOfBill, $bill->repeat_freq); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $billStarts[] = [ | 
					
						
							|  |  |  |                 'start' => clone $startOfBill, | 
					
						
							|  |  |  |                 'end'   => clone $endOfBill, | 
					
						
							|  |  |  |             ]; | 
					
						
							|  |  |  |             // actually the next one:
 | 
					
						
							|  |  |  |             $startOfBill = Navigation::addPeriod($startOfBill, $bill->repeat_freq, $bill->skip); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // for each
 | 
					
						
							|  |  |  |         $validRanges = []; | 
					
						
							|  |  |  |         foreach ($billStarts as $dateEntry) { | 
					
						
							|  |  |  |             if ($dateEntry['end'] > $start && $dateEntry['start'] < $end) { | 
					
						
							|  |  |  |                 // count transactions for bill in this range (not relevant yet!):
 | 
					
						
							|  |  |  |                 $validRanges[] = $dateEntry; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $validRanges; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @param Bill $bill | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |      * @return \Carbon\Carbon | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function lastFoundMatch(Bill $bill): Carbon | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         $last = $bill->transactionjournals()->orderBy('date', 'DESC')->first(); | 
					
						
							|  |  |  |         if ($last) { | 
					
						
							|  |  |  |             return $last->date; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |         return Carbon::now()->addDays(2); // in the future!
 | 
					
						
							| 
									
										
										
										
											2015-04-05 18:20:06 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @param Bill $bill | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2015-05-26 20:59:16 +02:00
										 |  |  |      * @return \Carbon\Carbon | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function nextExpectedMatch(Bill $bill): Carbon | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-03-03 17:40:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-02 12:47:15 +01:00
										 |  |  |         $finalDate       = Carbon::now(); | 
					
						
							| 
									
										
										
										
											2016-02-10 06:55:08 +01:00
										 |  |  |         $finalDate->year = 1900; | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |         if ($bill->active == 0) { | 
					
						
							|  |  |  |             return $finalDate; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |          * $today is the start of the next period, to make sure FF3 won't miss anything | 
					
						
							|  |  |  |          * when the current period has a transaction journal. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2015-05-05 10:23:01 +02:00
										 |  |  |         /** @var \Carbon\Carbon $obj */ | 
					
						
							| 
									
										
										
										
											2015-05-05 12:57:27 +02:00
										 |  |  |         $obj   = new Carbon; | 
					
						
							| 
									
										
										
										
											2015-05-05 10:23:01 +02:00
										 |  |  |         $today = Navigation::addPeriod($obj, $bill->repeat_freq, 0); | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $skip  = $bill->skip + 1; | 
					
						
							| 
									
										
										
										
											2015-05-05 10:23:01 +02:00
										 |  |  |         $start = Navigation::startOfPeriod($obj, $bill->repeat_freq); | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |         /* | 
					
						
							|  |  |  |          * go back exactly one month/week/etc because FF3 does not care about 'next' | 
					
						
							|  |  |  |          * bills if they're too far into the past. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $counter = 0; | 
					
						
							|  |  |  |         while ($start <= $today) { | 
					
						
							|  |  |  |             if (($counter % $skip) == 0) { | 
					
						
							|  |  |  |                 // do something.
 | 
					
						
							|  |  |  |                 $end          = Navigation::endOfPeriod(clone $start, $bill->repeat_freq); | 
					
						
							|  |  |  |                 $journalCount = $bill->transactionjournals()->before($end)->after($start)->count(); | 
					
						
							|  |  |  |                 if ($journalCount == 0) { | 
					
						
							| 
									
										
										
										
											2015-05-27 07:58:54 +02:00
										 |  |  |                     $finalDate = new Carbon($start->format('Y-m-d')); | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // add period for next round!
 | 
					
						
							|  |  |  |             $start = Navigation::addPeriod($start, $bill->repeat_freq, 0); | 
					
						
							|  |  |  |             $counter++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $finalDate; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param Bill               $bill | 
					
						
							|  |  |  |      * @param TransactionJournal $journal | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function scan(Bill $bill, TransactionJournal $journal): bool | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-11-20 20:13:10 +01:00
										 |  |  |         /* | 
					
						
							|  |  |  |          * Can only support withdrawals. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2015-12-09 22:39:50 -02:00
										 |  |  |         if (false === $journal->isWithdrawal()) { | 
					
						
							| 
									
										
										
										
											2015-11-20 20:13:10 +01:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-05-15 15:24:23 +02:00
										 |  |  |         $destinationAccounts = TransactionJournal::destinationAccountList($journal); | 
					
						
							|  |  |  |         $sourceAccounts      = TransactionJournal::sourceAccountList($journal); | 
					
						
							|  |  |  |         $matches             = explode(',', $bill->match); | 
					
						
							|  |  |  |         $description         = strtolower($journal->description) . ' '; | 
					
						
							|  |  |  |         $description .= strtolower(join(' ', $destinationAccounts->pluck('name')->toArray())); | 
					
						
							|  |  |  |         $description .= strtolower(join(' ', $sourceAccounts->pluck('name')->toArray())); | 
					
						
							| 
									
										
										
										
											2016-03-29 15:24:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-07 08:13:19 +02:00
										 |  |  |         $wordMatch   = $this->doWordMatch($matches, $description); | 
					
						
							| 
									
										
										
										
											2016-03-02 20:11:28 +01:00
										 |  |  |         $amountMatch = $this->doAmountMatch(TransactionJournal::amountPositive($journal), $bill->amount_min, $bill->amount_max); | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-20 20:13:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |         /* | 
					
						
							|  |  |  |          * If both, update! | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if ($wordMatch && $amountMatch) { | 
					
						
							|  |  |  |             $journal->bill()->associate($bill); | 
					
						
							|  |  |  |             $journal->save(); | 
					
						
							| 
									
										
										
										
											2015-06-07 08:13:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ($bill->id == $journal->bill_id) { | 
					
						
							|  |  |  |             // if no match, but bill used to match, remove it:
 | 
					
						
							|  |  |  |             $journal->bill_id = null; | 
					
						
							|  |  |  |             $journal->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-06-07 08:13:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-13 10:02:36 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param array $data | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Bill | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function store(array $data): Bill | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |     { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $bill = Bill::create( | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 'name'        => $data['name'], | 
					
						
							|  |  |  |                 'match'       => $data['match'], | 
					
						
							|  |  |  |                 'amount_min'  => $data['amount_min'], | 
					
						
							|  |  |  |                 'user_id'     => $data['user'], | 
					
						
							|  |  |  |                 'amount_max'  => $data['amount_max'], | 
					
						
							|  |  |  |                 'date'        => $data['date'], | 
					
						
							|  |  |  |                 'repeat_freq' => $data['repeat_freq'], | 
					
						
							|  |  |  |                 'skip'        => $data['skip'], | 
					
						
							|  |  |  |                 'automatch'   => $data['automatch'], | 
					
						
							|  |  |  |                 'active'      => $data['active'], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ] | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $bill; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param Bill  $bill | 
					
						
							|  |  |  |      * @param array $data | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2015-05-26 18:57:31 +00:00
										 |  |  |      * @return Bill | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     public function update(Bill $bill, array $data): Bill | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  |     { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $bill->name        = $data['name']; | 
					
						
							|  |  |  |         $bill->match       = $data['match']; | 
					
						
							|  |  |  |         $bill->amount_min  = $data['amount_min']; | 
					
						
							|  |  |  |         $bill->amount_max  = $data['amount_max']; | 
					
						
							|  |  |  |         $bill->date        = $data['date']; | 
					
						
							|  |  |  |         $bill->repeat_freq = $data['repeat_freq']; | 
					
						
							|  |  |  |         $bill->skip        = $data['skip']; | 
					
						
							|  |  |  |         $bill->automatch   = $data['automatch']; | 
					
						
							|  |  |  |         $bill->active      = $data['active']; | 
					
						
							|  |  |  |         $bill->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $bill; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-06-07 08:13:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param float $amount | 
					
						
							|  |  |  |      * @param float $min | 
					
						
							|  |  |  |      * @param float $max | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     protected function doAmountMatch($amount, $min, $max): bool | 
					
						
							| 
									
										
										
										
											2015-06-07 08:13:19 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         if ($amount >= $min && $amount <= $max) { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-07-09 09:41:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |      * @param array $matches | 
					
						
							|  |  |  |      * @param       $description | 
					
						
							| 
									
										
										
										
											2015-07-09 09:41:54 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2015-07-09 09:41:54 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-06 18:59:48 +01:00
										 |  |  |     protected function doWordMatch(array $matches, $description): bool | 
					
						
							| 
									
										
										
										
											2015-07-09 09:41:54 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |         $wordMatch = false; | 
					
						
							|  |  |  |         $count     = 0; | 
					
						
							|  |  |  |         foreach ($matches as $word) { | 
					
						
							|  |  |  |             if (!(strpos($description, strtolower($word)) === false)) { | 
					
						
							|  |  |  |                 $count++; | 
					
						
							| 
									
										
										
										
											2015-07-09 09:41:54 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |         if ($count >= count($matches)) { | 
					
						
							|  |  |  |             $wordMatch = true; | 
					
						
							| 
									
										
										
										
											2015-12-27 17:29:41 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 15:21:27 +01:00
										 |  |  |         return $wordMatch; | 
					
						
							| 
									
										
										
										
											2015-12-26 09:39:35 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-02-25 15:19:14 +01:00
										 |  |  | } |