| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | <?php | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * JournalUpdateService.php | 
					
						
							|  |  |  |  * Copyright (c) 2018 thegrumpydictator@gmail.com | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is part of Firefly III. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Firefly III is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |  * the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |  * (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Firefly III is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | declare(strict_types=1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 18:42:15 +01:00
										 |  |  | namespace FireflyIII\Services\Internal\Update; | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | use FireflyIII\Factory\TransactionFactory; | 
					
						
							|  |  |  | use FireflyIII\Models\Transaction; | 
					
						
							|  |  |  | use FireflyIII\Models\TransactionJournal; | 
					
						
							| 
									
										
										
										
											2018-08-09 20:46:47 +02:00
										 |  |  | use FireflyIII\Models\TransactionType; | 
					
						
							| 
									
										
										
										
											2018-02-23 15:12:47 +01:00
										 |  |  | use FireflyIII\Services\Internal\Support\JournalServiceTrait; | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | use Illuminate\Support\Collection; | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  | use Log; | 
					
						
							| 
									
										
										
										
											2019-02-12 21:49:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Class to centralise code that updates a journal given the input by system. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Class JournalUpdateService | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class JournalUpdateService | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-23 15:12:47 +01:00
										 |  |  |     use JournalServiceTrait; | 
					
						
							| 
									
										
										
										
											2019-02-12 21:49:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 12:29:32 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Constructor. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __construct() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-12-15 07:59:02 +01:00
										 |  |  |         if ('testing' === config('app.env')) { | 
					
						
							| 
									
										
										
										
											2018-09-06 12:29:32 +02:00
										 |  |  |             Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this))); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param TransactionJournal $journal | 
					
						
							|  |  |  |      * @param array              $data | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionJournal | 
					
						
							| 
									
										
										
										
											2018-07-26 06:27:52 +02:00
										 |  |  |      * @throws \FireflyIII\Exceptions\FireflyException | 
					
						
							| 
									
										
										
										
											2018-07-28 06:27:30 +02:00
										 |  |  |      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | 
					
						
							|  |  |  |      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function update(TransactionJournal $journal, array $data): TransactionJournal | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // update journal:
 | 
					
						
							|  |  |  |         $journal->description = $data['description']; | 
					
						
							|  |  |  |         $journal->date        = $data['date']; | 
					
						
							|  |  |  |         $journal->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // update transactions:
 | 
					
						
							|  |  |  |         /** @var TransactionUpdateService $service */ | 
					
						
							|  |  |  |         $service = app(TransactionUpdateService::class); | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |         $service->setUser($journal->user); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-29 07:25:04 +02:00
										 |  |  |         // create transactions:
 | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |         /** @var TransactionFactory $factory */ | 
					
						
							|  |  |  |         $factory = app(TransactionFactory::class); | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |         $factory->setUser($journal->user); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 06:23:13 +02:00
										 |  |  |         Log::debug(sprintf('Found %d rows in array (should result in %d transactions', \count($data['transactions']), \count($data['transactions']) * 2)); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * @var int   $identifier | 
					
						
							|  |  |  |          * @var array $trData | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         foreach ($data['transactions'] as $identifier => $trData) { | 
					
						
							|  |  |  |             // exists transaction(s) with this identifier? update!
 | 
					
						
							|  |  |  |             /** @var Collection $existing */ | 
					
						
							|  |  |  |             $existing = $journal->transactions()->where('identifier', $identifier)->get(); | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |             Log::debug(sprintf('Found %d transactions with identifier %d', $existing->count(), $identifier)); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |             if ($existing->count() > 0) { | 
					
						
							|  |  |  |                 $existing->each( | 
					
						
							|  |  |  |                     function (Transaction $transaction) use ($service, $trData) { | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |                         Log::debug(sprintf('Update transaction #%d (identifier %d)', $transaction->id, $trData['identifier'])); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |                         $service->update($transaction, $trData); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |             Log::debug('Found none, so create a pair.'); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |             // otherwise, create!
 | 
					
						
							|  |  |  |             $factory->createPair($journal, $trData); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-21 08:58:06 +01:00
										 |  |  |         // could be that journal has more transactions than submitted (remove split)
 | 
					
						
							|  |  |  |         $transactions = $journal->transactions()->where('amount', '>', 0)->get(); | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |         Log::debug(sprintf('Journal #%d has %d transactions', $journal->id, $transactions->count())); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:58:06 +01:00
										 |  |  |         /** @var Transaction $transaction */ | 
					
						
							|  |  |  |         foreach ($transactions as $transaction) { | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |             Log::debug(sprintf('Now at transaction %d with identifier %d', $transaction->id, $transaction->identifier)); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:58:06 +01:00
										 |  |  |             if (!isset($data['transactions'][$transaction->identifier])) { | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |                 Log::debug('No such entry in array, delete this set of transactions.'); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:58:06 +01:00
										 |  |  |                 $journal->transactions()->where('identifier', $transaction->identifier)->delete(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-28 06:23:13 +02:00
										 |  |  |         Log::debug(sprintf('New count is %d, transactions array held %d items', $journal->transactions()->count(), \count($data['transactions']))); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // connect bill:
 | 
					
						
							|  |  |  |         $this->connectBill($journal, $data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // connect tags:
 | 
					
						
							|  |  |  |         $this->connectTags($journal, $data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-29 07:25:04 +02:00
										 |  |  |         // remove category from journal:
 | 
					
						
							|  |  |  |         $journal->categories()->sync([]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // remove budgets from journal:
 | 
					
						
							|  |  |  |         $journal->budgets()->sync([]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |         // update or create custom fields:
 | 
					
						
							|  |  |  |         // store date meta fields (if present):
 | 
					
						
							|  |  |  |         $this->storeMeta($journal, $data, 'interest_date'); | 
					
						
							|  |  |  |         $this->storeMeta($journal, $data, 'book_date'); | 
					
						
							|  |  |  |         $this->storeMeta($journal, $data, 'process_date'); | 
					
						
							|  |  |  |         $this->storeMeta($journal, $data, 'due_date'); | 
					
						
							|  |  |  |         $this->storeMeta($journal, $data, 'payment_date'); | 
					
						
							|  |  |  |         $this->storeMeta($journal, $data, 'invoice_date'); | 
					
						
							|  |  |  |         $this->storeMeta($journal, $data, 'internal_reference'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // store note:
 | 
					
						
							|  |  |  |         $this->storeNote($journal, $data['notes']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $journal; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Update budget for a journal. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param TransactionJournal $journal | 
					
						
							|  |  |  |      * @param int                $budgetId | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionJournal | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /** @var TransactionUpdateService $service */ | 
					
						
							|  |  |  |         $service = app(TransactionUpdateService::class); | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |         $service->setUser($journal->user); | 
					
						
							| 
									
										
										
										
											2018-08-09 20:46:47 +02:00
										 |  |  |         if (TransactionType::WITHDRAWAL === $journal->transactionType->type) { | 
					
						
							|  |  |  |             /** @var Transaction $transaction */ | 
					
						
							|  |  |  |             foreach ($journal->transactions as $transaction) { | 
					
						
							|  |  |  |                 $service->updateBudget($transaction, $budgetId); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-02-12 21:49:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-09 20:49:30 +02:00
										 |  |  |             return $journal; | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-09 20:49:30 +02:00
										 |  |  |         // clear budget.
 | 
					
						
							|  |  |  |         /** @var Transaction $transaction */ | 
					
						
							|  |  |  |         foreach ($journal->transactions as $transaction) { | 
					
						
							|  |  |  |             $transaction->budgets()->sync([]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // remove budgets from journal:
 | 
					
						
							|  |  |  |         $journal->budgets()->sync([]); | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $journal; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Update category for a journal. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param TransactionJournal $journal | 
					
						
							|  |  |  |      * @param string             $category | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionJournal | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /** @var TransactionUpdateService $service */ | 
					
						
							|  |  |  |         $service = app(TransactionUpdateService::class); | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  |         $service->setUser($journal->user); | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @var Transaction $transaction */ | 
					
						
							|  |  |  |         foreach ($journal->transactions as $transaction) { | 
					
						
							|  |  |  |             $service->updateCategory($transaction, $category); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-05-29 07:25:04 +02:00
										 |  |  |         // make journal empty:
 | 
					
						
							|  |  |  |         $journal->categories()->sync([]); | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $journal; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-05 19:35:58 +01:00
										 |  |  | } |