Hsbc::parseTransactionValueTimestamp()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 2
b 0
f 0
nc 2
nop 0
dl 0
loc 8
rs 10
1
<?php
2
3
namespace Kingsquare\Parser\Banking\Mt940\Engine;
4
5
use Kingsquare\Banking\Statement;
6
use Kingsquare\Banking\Hsbc\HsbcTransaction;
7
use Kingsquare\Banking\Transaction;
8
use Kingsquare\Parser\Banking\Mt940\Engine;
9
10
/**
11
 * @author  jun ([email protected])
12
 * @license http://opensource.org/licenses/MIT MIT
13
 */
14
class Hsbc extends Engine
15
{
16
    const PATTERN_TAG_61 = '/^:61:(\d{6})(\d{4}?)(C|D|EC|ED|RC|RD)[A-Z](\d+,\d+)([FNS])([A-Z]{3})(.{16})/m';
17
18
    /**
19
     * returns the name of the bank.
20
     *
21
     * @return string
22
     */
23
    protected function parseStatementBank()
24
    {
25
        return 'HSBC';
26
    }
27
28
    /**
29
     * Overloaded
30
     *
31
     * @return array
32
     */
33
    protected function parseStatementData()
34
    {
35
        $results = preg_split(
36
            '/(^:20:|^-X{,3}$|\Z)/m',
37
            $this->getRawData(),
38
            -1,
39
            PREG_SPLIT_NO_EMPTY
40
        );
41
        return $results;
42
    }
43
44
    /**
45
     * Overloaded: add support for virtual account.
46
     *
47
     * @return Statement[]
48
     */
49
    public function parse()
50
    {
51
        $results = [];
52
        foreach ($this->parseStatementData() as $this->currentStatementData) {
53
            $statement = new Statement();
54
            if ($this->debug) {
55
                $statement->rawData = $this->currentStatementData;
56
            }
57
            $statement->setBank($this->parseStatementBank());
58
            $statement->setAccount($this->parseStatementAccount());
59
            $statement->setStartPrice($this->parseStatementStartPrice());
60
            $statement->setEndPrice($this->parseStatementEndPrice());
61
            $statement->setStartTimestamp($this->parseStatementStartTimestamp());
62
            $statement->setEndTimestamp($this->parseStatementEndTimestamp());
63
            $statement->setNumber($this->parseStatementNumber());
64
            $statement->setCurrency($this->parseStatementCurrency());
65
66
            foreach ($this->parseTransactionData() as $this->currentTransactionData) {
0 ignored issues
show
Comprehensibility Bug introduced by
$this is overwriting a variable from outer foreach loop.
Loading history...
67
                $transaction = new HsbcTransaction();
68
                if ($this->debug) {
69
                    $transaction->rawData = $this->currentTransactionData;
70
                }
71
                $transaction->setAccount($this->parseTransactionAccount());
72
                $transaction->setAccountName($this->parseTransactionAccountName());
73
                $transaction->setPrice($this->parseTransactionPrice());
74
                $transaction->setDebitCredit($this->parseTransactionDebitCredit());
75
                $transaction->setCancellation($this->parseTransactionCancellation());
76
                $transaction->setDescription($this->parseTransactionDescription());
77
                $transaction->setValueTimestamp($this->parseTransactionValueTimestamp());
78
                $transaction->setEntryTimestamp($this->parseTransactionEntryTimestamp());
79
                $transaction->setTransactionCode($this->parseTransactionCode());
80
                $transaction->setVirtualAccount($this->parseVirtualAccount());
81
                $statement->addTransaction($transaction);
82
            }
83
            $results[] = $statement;
84
        }
85
86
        return $results;
87
    }
88
89
    /**
90
     * Overloaded: 16x, like 808XXXXXX292 .
91
     *
92
     * @return string accountnumber
93
     */
94
    protected function parseStatementAccount()
95
    {
96
        $results = [];
97
        if (preg_match('/:25:([0-9X]+)*/', $this->getCurrentStatementData(), $results)
98
            && !empty($results[1])
99
        ) {
100
            return $this->sanitizeAccount($results[1]);
101
        }
102
103
        return '';
104
    }
105
106
    /**
107
     * Overloaded: HSBC has different way of storing account info.
108
     *
109
     * {@inheritdoc}
110
     */
111
    protected function parseTransactionAccount()
112
    {
113
        $results = [];
114
        // YYMMDD[MMDD]2a[1!a]15d1!a3!c16x[//16x][34x]
115
        // eg.: :61:1203290329DD20000,00NTRF1004688128      //6128522200250001
116
        // Reference for the Account Owner (16x): 1004688128
117
        // Reference of the Account Servicing Institution [//16x]: 6128522200250001
118
        // Supplementary Details [34x]: null
119
        if (preg_match(self::PATTERN_TAG_61, $this->getCurrentTransactionData(), $results)) {
120
            return $this->sanitizeAccount($results[7]);
121
        }
122
123
        return '';
124
    }
125
126
    /**
127
     * Overloaded: debit or credit of the transaction.
128
     *
129
     * @return string
130
     */
131
    protected function parseTransactionDebitCredit()
132
    {
133
        $results = [];
134
        if (preg_match(self::PATTERN_TAG_61, $this->getCurrentTransactionData(), $results)) {
135
            return $this->sanitizeDebitCredit($results[3]);
136
        }
137
138
        return '';
139
    }
140
141
    /**
142
     * Overloaded: HSBC has different way of storing account name.
143
     *
144
     * {@inheritdoc}
145
     */
146
    protected function parseTransactionAccountName()
147
    {
148
        $results = [];
149
        // SEPA MT940 Structured
150
        if (preg_match('#/NAME/(.+?)\n?/(REMI|ADDR|ISDT|CSID)/#ms', $this->getCurrentTransactionData(), $results)) {
151
            $accountName = trim($results[1]);
152
            if (!empty($accountName)) {
153
                return $this->sanitizeAccountName($accountName);
154
            }
155
        }
156
157
        if (preg_match('/^:61:.*? (.+)/m', $this->getCurrentTransactionData(), $results)) {
158
            $accountName = trim($results[1]);
159
            if (!empty($accountName)) {
160
                return $this->sanitizeAccountName($accountName);
161
            }
162
        }
163
164
        if (preg_match('/(.*) Betaalautomaat/', $this->parseTransactionDescription(), $results)) {
165
            $accountName = trim($results[1]);
166
            if (!empty($accountName)) {
167
                return $this->sanitizeAccountName($accountName);
168
            }
169
        }
170
        return '';
171
    }
172
173
    /**
174
     * Overloaded: HSBC has different way of storing transaction value timestamps (ymd).
175
     *
176
     * {@inheritdoc}
177
     */
178
    protected function parseTransactionEntryTimestamp()
179
    {
180
        $results = [];
181
        if (preg_match('/^:60F:[C|D]([\d]{6})/m', $this->getCurrentStatementData(), $results)) {
182
            return $this->sanitizeTimestamp($results[1]);
183
        }
184
185
        return 0;
186
    }
187
188
    /**
189
     * Overloaded: HSBC has different way of storing transaction value timestamps (ymd).
190
     *
191
     * {@inheritdoc}
192
     */
193
    protected function parseTransactionValueTimestamp()
194
    {
195
        $results = [];
196
        if (preg_match(self::PATTERN_TAG_61, $this->getCurrentTransactionData(), $results)) {
197
            return $this->sanitizeTimestamp($results[1]);
198
        }
199
200
        return 0;
201
    }
202
203
    /**
204
     * retrieve the virtual account from full description of the transaction.
205
     *
206
     * @return string
207
     */
208
    protected function parseVirtualAccount()
209
    {
210
        $results = [];
211
        if (preg_match('/[\n].*?(?:\/VA\/(.+)$)/m', $this->getCurrentTransactionData(), $results)) {
212
            return $this->sanitizeVirtualAccount($results[1]);
213
        }
214
215
        return '';
216
    }
217
218
    /**
219
     * Overloaded: HSBC encapsulates the description with /REMI/ for SEPA.
220
     *
221
     * {@inheritdoc}
222
     */
223
    protected function sanitizeDescription($string)
224
    {
225
        $description = parent::sanitizeDescription($string);
226
        if (strpos($description, '/REMI/') !== false
227
            && preg_match('#/REMI/(.*?)(/((PURP|ISDT|CSID|RTRN)/)|$)#s', $description, $results) && !empty($results[1])
228
        ) {
229
            return $results[1];
230
        }
231
        if (strpos($description, '/EREF/') !== false
232
            && preg_match('#/EREF/(.*?)/(ORDP)/#s', $description, $results) && !empty($results[1])
233
        ) {
234
            return $results[1];
235
        }
236
237
        return $description;
238
    }
239
240
    /**
241
     * Overloaded: HSBC has some specific debit/credit marks.
242
     *
243
     * @param string $string
244
     *
245
     * @return string
246
     */
247
    protected function sanitizeDebitCredit($string)
248
    {
249
        $debitOrCredit = strtoupper(substr((string)$string, -1, 1));
250
        if ($debitOrCredit !== Transaction::DEBIT && $debitOrCredit !== Transaction::CREDIT) {
251
            trigger_error('wrong value for debit/credit (' . $string . ')', E_USER_ERROR);
252
            $debitOrCredit = '';
253
        }
254
255
        return $debitOrCredit;
256
    }
257
258
    /**
259
     * @param string $string
260
     *
261
     * @return string
262
     */
263
    protected function sanitizeVirtualAccount($string)
264
    {
265
        return trim($string);
266
    }
267
268
    /**
269
     * Overloaded: Is applicable if first line starts with :20:AI.
270
     *
271
     * {@inheritdoc}
272
     */
273
    public static function isApplicable($string)
274
    {
275
        $firstline = strtok($string, "\r\n\t");
276
277
        return strpos($firstline, ':20:AI') !== false && strlen($firstline) === 20;
278
    }
279
}
280