| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  | <?php | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * AbnAmroDescription.php | 
					
						
							| 
									
										
										
										
											2017-12-17 14:41:58 +01:00
										 |  |  |  * Copyright (c) 2017 Robert Horlings | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-10-21 08:40:00 +02:00
										 |  |  |  * This file is part of Firefly III. | 
					
						
							| 
									
										
										
										
											2016-10-05 06:52:15 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-10-21 08:40:00 +02:00
										 |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2017-12-17 14:41:58 +01:00
										 |  |  |  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-04-09 07:44:22 +02:00
										 |  |  | declare(strict_types=1); | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace FireflyIII\Import\Specifics; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |  * Class AbnAmroDescription. | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |  * Parses the description from txt files for ABN AMRO bank accounts. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Based on the logic as described in the following Gist: | 
					
						
							|  |  |  |  * https://gist.github.com/vDorst/68d555a6a90f62fec004 | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | class AbnAmroDescription implements SpecificInterface | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |     /** @var array */ | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |     public $row; | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-08-12 15:10:03 +02:00
										 |  |  |     public static function getDescription(): string | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |         return 'Fixes possible problems with ABN Amro descriptions.'; | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-08-12 15:10:03 +02:00
										 |  |  |     public static function getName(): string | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |         return 'ABN Amro description'; | 
					
						
							| 
									
										
										
										
											2016-06-24 14:24:34 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-12 09:27:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param array $row | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function run(array $row): array | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-12-12 21:05:16 +01:00
										 |  |  |         $this->row = array_values($row); | 
					
						
							| 
									
										
										
										
											2016-09-29 07:02:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!isset($row[7])) { | 
					
						
							|  |  |  |             return $row; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |         // Try to parse the description in known formats.
 | 
					
						
							|  |  |  |         $parsed = $this->parseSepaDescription() || $this->parseTRTPDescription() || $this->parseGEABEADescription() || $this->parseABNAMRODescription(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // If the description could not be parsed, specify an unknown opposing
 | 
					
						
							|  |  |  |         // account, as an opposing account is required
 | 
					
						
							|  |  |  |         if (!$parsed) { | 
					
						
							| 
									
										
										
										
											2016-10-09 17:19:00 +02:00
										 |  |  |             $this->row[8] = trans('firefly.unknown'); // opposing-account-name
 | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->row; | 
					
						
							| 
									
										
										
										
											2016-08-12 09:27:09 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |      * Parses the current description with costs from ABN AMRO itself. | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool true if the description is GEA/BEA-format, false otherwise | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function parseABNAMRODescription() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // See if the current description is formatted in ABN AMRO format
 | 
					
						
							|  |  |  |         if (preg_match('/ABN AMRO.{24} (.*)/', $this->row[7], $matches)) { | 
					
						
							|  |  |  |             $this->row[8] = 'ABN AMRO'; // this one is new (opposing account name)
 | 
					
						
							|  |  |  |             $this->row[7] = $matches[1]; // this is the description
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |      * Parses the current description in GEA/BEA format. | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool true if the description is GEA/BEAformat, false otherwise | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function parseGEABEADescription() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // See if the current description is formatted in GEA/BEA format
 | 
					
						
							|  |  |  |         if (preg_match('/([BG]EA) +(NR:[a-zA-Z:0-9]+) +([0-9.\/]+) +([^,]*)/', $this->row[7], $matches)) { | 
					
						
							|  |  |  |             // description and opposing account will be the same.
 | 
					
						
							|  |  |  |             $this->row[8] = $matches[4]; // 'opposing-account-name'
 | 
					
						
							|  |  |  |             $this->row[7] = $matches[4]; // 'description'
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |             if ('GEA' === $matches[1]) { | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |                 $this->row[7] = 'GEA ' . $matches[4]; // 'description'
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |      * Parses the current description in SEPA format. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2017-10-22 20:13:02 +02:00
										 |  |  |      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | 
					
						
							| 
									
										
										
										
											2017-11-05 19:49:20 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |      * @return bool true if the description is SEPA format, false otherwise | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function parseSepaDescription() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // See if the current description is formatted as a SEPA plain description
 | 
					
						
							|  |  |  |         if (preg_match('/^SEPA(.{28})/', $this->row[7], $matches)) { | 
					
						
							|  |  |  |             $type           = $matches[1]; | 
					
						
							|  |  |  |             $reference      = ''; | 
					
						
							|  |  |  |             $name           = ''; | 
					
						
							|  |  |  |             $newDescription = ''; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // SEPA plain descriptions contain several key-value pairs, split by a colon
 | 
					
						
							|  |  |  |             preg_match_all('/([A-Za-z]+(?=:\s)):\s([A-Za-z 0-9._#-]+(?=\s|$))/', $this->row[7], $matches, PREG_SET_ORDER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (is_array($matches)) { | 
					
						
							|  |  |  |                 foreach ($matches as $match) { | 
					
						
							|  |  |  |                     $key   = $match[1]; | 
					
						
							|  |  |  |                     $value = trim($match[2]); | 
					
						
							|  |  |  |                     switch (strtoupper($key)) { | 
					
						
							|  |  |  |                         case 'OMSCHRIJVING': | 
					
						
							|  |  |  |                             $newDescription = $value; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         case 'NAAM': | 
					
						
							|  |  |  |                             $this->row[8] = $value; | 
					
						
							| 
									
										
										
										
											2016-08-26 08:21:31 +02:00
										 |  |  |                             $name         = $value; | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |                             break; | 
					
						
							|  |  |  |                         case 'KENMERK': | 
					
						
							|  |  |  |                             $reference = $value; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         case 'IBAN': | 
					
						
							|  |  |  |                             $this->row[9] = $value; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         default: | 
					
						
							|  |  |  |                             // Ignore the rest
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Set a new description for the current transaction. If none was given
 | 
					
						
							|  |  |  |             // set the description to type, name and reference
 | 
					
						
							|  |  |  |             $this->row[7] = $newDescription; | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |             if (0 === strlen($newDescription)) { | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |                 $this->row[7] = sprintf('%s - %s (%s)', $type, $name, $reference); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |      * Parses the current description in TRTP format. | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool true if the description is TRTP format, false otherwise | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function parseTRTPDescription() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // See if the current description is formatted in TRTP format
 | 
					
						
							|  |  |  |         if (preg_match_all('!\/([A-Z]{3,4})\/([^/]*)!', $this->row[7], $matches, PREG_SET_ORDER)) { | 
					
						
							|  |  |  |             $type           = ''; | 
					
						
							|  |  |  |             $name           = ''; | 
					
						
							|  |  |  |             $reference      = ''; | 
					
						
							|  |  |  |             $newDescription = ''; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Search for properties specified in the TRTP format. If no description
 | 
					
						
							|  |  |  |             // is provided, use the type, name and reference as new description
 | 
					
						
							|  |  |  |             if (is_array($matches)) { | 
					
						
							|  |  |  |                 foreach ($matches as $match) { | 
					
						
							|  |  |  |                     $key   = $match[1]; | 
					
						
							|  |  |  |                     $value = trim($match[2]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     switch (strtoupper($key)) { | 
					
						
							|  |  |  |                         case 'NAME': | 
					
						
							|  |  |  |                             $this->row[8] = $name = $value; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         case 'REMI': | 
					
						
							|  |  |  |                             $newDescription = $value; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         case 'IBAN': | 
					
						
							|  |  |  |                             $this->row[9] = $value; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         case 'EREF': | 
					
						
							|  |  |  |                             $reference = $value; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         case 'TRTP': | 
					
						
							|  |  |  |                             $type = $value; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         default: | 
					
						
							|  |  |  |                             // Ignore the rest
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Set a new description for the current transaction. If none was given
 | 
					
						
							|  |  |  |                 // set the description to type, name and reference
 | 
					
						
							|  |  |  |                 $this->row[7] = $newDescription; | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |                 if (0 === strlen($newDescription)) { | 
					
						
							| 
									
										
										
										
											2016-08-12 12:55:52 +02:00
										 |  |  |                     $this->row[7] = sprintf('%s - %s (%s)', $type, $name, $reference); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-12 15:10:03 +02:00
										 |  |  | } |