Passed
Push — main ( cee9ce...016e91 )
by Daniel
13:50
created

TraitUserInterfaceLogic::handleDocumentTypeCode()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
/*
4
 * Copyright (c) 2024, Daniel Popiniuc and its licensors.
5
 *
6
 * All rights reserved. This program and the accompanying materials
7
 * are made available under the terms of the Eclipse Public License v1.0
8
 * which accompanies this distribution, and is available at
9
 * http://www.eclipse.org/legal/epl-v20.html
10
 *
11
 * Contributors:
12
 *    Daniel Popiniuc
13
 */
14
15
namespace danielgp\efactura;
16
17
trait TraitUserInterfaceLogic
18
{
19
    use \danielgp\io_operations\InputOutputFiles;
20
21
    protected array $arrayConfiguration;
22
    protected $translation;
23
24
    public function actionAnalyzeZIPfromANAFfromLocalFolder(string $strFilePath): array
25
    {
26
        $arrayFiles    = new \RecursiveDirectoryIterator($strFilePath, \FilesystemIterator::SKIP_DOTS);
27
        $arrayInvoices = [];
28
        $intFileNo     = 0;
29
        foreach ($arrayFiles as $strFile) {
30
            if ($strFile->isFile()) {
31
                $arrayFileDetails = $this->handleResponseFile($strFile);
32
                if ($arrayFileDetails !== []) {
33
                    $arrayInvoices[$intFileNo] = $arrayFileDetails;
34
                    $intFileNo++;
35
                }
36
            }
37
        }
38
        return $arrayInvoices;
39
    }
40
41
    protected function getConfiguration()
42
    {
43
        $this->arrayConfiguration = $this->getArrayFromJsonFile(__DIR__
44
            . DIRECTORY_SEPARATOR . 'config', 'BasicConfiguration.json');
45
    }
46
47
    /**
48
     * Archived document is read as content in memory since 2024-02-16
49
     * (prior to this date a temporary local file was saved, processed and finally removed when done with it)
50
     *
51
     * @param array $arrayData
52
     * @return array
53
     */
54
    private function getDocumentDetails(array $arrayData): array
55
    {
56
        $appR               = new \danielgp\efactura\ClassElectronicInvoiceRead();
57
        $arrayElectronicInv = $appR->readElectronicInvoice($arrayData['strInvoiceContent']);
58
        $arrayBasic         = $arrayElectronicInv['Header']['CommonBasicComponents-2'];
59
        $arrayAggregate     = $arrayElectronicInv['Header']['CommonAggregateComponents-2'];
60
        $arrayStandardized  = [
61
            'DocumentTypeCode'     => $this->handleDocumentTypeCode($arrayBasic),
62
            'Customer'             => $arrayAggregate['AccountingCustomerParty']['Party'],
63
            'ID'                   => $arrayBasic['ID'],
64
            'IssueDate'            => $arrayBasic['IssueDate'],
65
            'DocumentCurrencyCode' => $arrayBasic['DocumentCurrencyCode'],
66
            'No_of_Lines'          => count($arrayElectronicInv['Lines']),
67
            'Supplier'             => $arrayAggregate['AccountingSupplierParty']['Party'],
68
            'TOTAL'                => (float) $arrayAggregate['LegalMonetaryTotal']['TaxInclusiveAmount']['value'],
69
            'wo_VAT'               => (float) $arrayAggregate['LegalMonetaryTotal']['TaxExclusiveAmount']['value'],
70
        ];
71
        return $arrayStandardized;
72
    }
73
74
    private function handleArchiveContent(\ZipArchive $classZip, array $arrayArchiveParam): array
75
    {
76
        $arrayToReturn = [];
77
        for ($intArchivedFile = 0; $intArchivedFile < $arrayArchiveParam['No_of_Files']; $intArchivedFile++) {
78
            $strArchivedFile = $classZip->getNameIndex($intArchivedFile);
79
            $matches         = [];
80
            preg_match('/^[0-9]{5,20}\.xml$/', $strArchivedFile, $matches, PREG_OFFSET_CAPTURE);
81
            $matches2        = [];
82
            preg_match('/^semnatura_[0-9]{5,20}\.xml$/', $strArchivedFile, $matches2, PREG_OFFSET_CAPTURE);
83
            if ($matches !== []) {
84
                $resInvoice        = $classZip->getStream($strArchivedFile);
85
                $strInvoiceContent = stream_get_contents($resInvoice);
86
                fclose($resInvoice);
87
                $strFileStats      = $classZip->statIndex($intArchivedFile);
88
                $arrayToReturn     = $this->setStandardizedFeedbackArray([
89
                    'Response_Index'      => pathinfo($arrayArchiveParam['FileName'])['filename'],
90
                    'Size'                => $strFileStats['size'],
91
                    'FileDateTime'        => date('Y-m-d H:i:s', $strFileStats['mtime']),
92
                    'Matches'             => $matches,
93
                    'strArchivedFileName' => $strArchivedFile,
94
                    'strInvoiceContent'   => $strInvoiceContent,
95
                    'Response_Size'       => $arrayArchiveParam['Response_Size'],
96
                ]);
97
            } elseif ($matches2 === []) {
98
                echo vsprintf('<div>' . $this->arrayConfiguration['Feedback']['DifferentFile'] . '</div>', [
99
                    $strArchivedFile,
100
                    $strFile->getBasename(),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $strFile does not exist. Did you maybe mean $strFileStats?
Loading history...
101
                ]);
102
            }
103
        }
104
        return $arrayToReturn;
105
    }
106
107
    private function handleDocumentTypeCode(array $arrayBasic): string
108
    {
109
        $strValueToReturn = '';
110
        if (array_key_exists('InvoiceTypeCode', $arrayBasic)) {
111
            $strValueToReturn = $arrayBasic['InvoiceTypeCode'];
112
        } elseif (array_key_exists('CreditNoteTypeCode', $arrayBasic)) {
113
            $strValueToReturn = $arrayBasic['CreditNoteTypeCode'];
114
        }
115
        return $strValueToReturn;
116
    }
117
118
    private function handleResponseFile(\SplFileInfo | string $strFile): array
119
    {
120
        $arrayToReturn = [];
121
        $strFileMime   = mime_content_type($strFile->getRealPath());
122
        switch($strFileMime) {
123
            case 'application/json':
124
                $arrayError    = $this->getArrayFromJsonFile($strFile->getPath(), $strFile->getFilename());
125
                $arrayToReturn = $this->setStandardizedFeedbackArray([
126
                    'Error'          => $arrayError['eroare'] . ' ===> ' . $arrayError['titlu'],
127
                    'Response_Index' => $strFile->getFilename(),
128
                    'Response_Size'  => $strFile->getSize(),
129
                ]);
130
                break;
131
            case 'application/zip':
132
                $arrayToReturn = $this->setArchiveFromAnaf($strFile->getRealPath(), $strFile->getSize());
133
                break;
134
        }
135
        return $arrayToReturn;
136
    }
137
138
    private function setArchiveFromAnaf(string $strFile, int $intFileSize)
139
    {
140
        $arrayToReturn = [];
141
        $classZip      = new \ZipArchive();
142
        $res           = $classZip->open($strFile, \ZipArchive::RDONLY);
143
        if ($res) {
144
            $intFilesArchived = $classZip->numFiles;
145
            $arrayToReturn    = $this->handleArchiveContent($classZip, [
146
                'No_of_Files'   => $intFilesArchived,
147
                'FileName'      => $strFile,
148
                'Response_Size' => $intFileSize,
149
            ]);
150
        } else {
151
            // @codeCoverageIgnoreStart
152
            $arrayToReturn = $this->setStandardizedFeedbackArray([
153
                'Response_Index' => pathinfo($strFile)['filename'],
154
                'Error'          => $this->translation->find(null, 'i18n_Msg_InvalidZip')->getTranslation(),
155
                'Response_Size'  => 0,
156
            ]);
157
            // @codeCoverageIgnoreEnd
158
        }
159
        return $arrayToReturn;
160
    }
161
162
    private function setDataSupplierOrCustomer(array $arrayData)
163
    {
164
        $strCustomerCui = '';
165
        if (isset($arrayData['PartyTaxScheme']['01']['CompanyID'])) {
166
            $strCustomerCui = $arrayData['PartyTaxScheme']['01']['CompanyID'];
167
        } else {
168
            $strCustomerCui = $arrayData['PartyLegalEntity']['CompanyID'];
169
        }
170
        if (is_numeric($strCustomerCui)) {
171
            $strCustomerCui = 'RO' . $strCustomerCui;
172
        }
173
        return $strCustomerCui;
174
    }
175
176
    private function setDaysElapsed(string $strFirstDate, string $strLaterDate): string
177
    {
178
        $origin   = new \DateTimeImmutable($strFirstDate);
179
        $target   = new \DateTimeImmutable($strLaterDate);
180
        $interval = $origin->diff($target);
181
        return $interval->format('%R%a');
182
    }
183
184
    private function setDefaultsToInvoiceDetailsArray(array $arrayData): array
185
    {
186
        return [
187
            'Response_DateTime'      => '',
188
            'Response_Index'         => $arrayData['Response_Index'],
189
            'Response_Size'          => $arrayData['Response_Size'],
190
            'Loading_Index'          => '',
191
            'Size'                   => '',
192
            'Document_Type_Code'     => '',
193
            'Document_No'            => '',
194
            'Issue_Date'             => '',
195
            'Issue_YearMonth'        => '',
196
            'Document_Currency_Code' => '',
197
            'Amount_wo_VAT'          => '',
198
            'Amount_TOTAL'           => '',
199
            'Amount_VAT'             => '',
200
            'Supplier_CUI'           => '',
201
            'Supplier_Name'          => '',
202
            'Customer_CUI'           => '',
203
            'Customer_Name'          => '',
204
            'No_of_Lines'            => '',
205
            'Error'                  => '',
206
            'Message'                => '',
207
            'Days_Between'           => '',
208
        ];
209
    }
210
211
    private function setErrorsFromExtendedMarkupLaguage(array $arrayData, string $strErrorTag): array
212
    {
213
        $arrayErrors = [];
214
        $parser      = xml_parser_create();
215
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
216
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
217
        xml_parse_into_struct($parser, $arrayData['strInvoiceContent'], $arrayErrors);
218
        xml_parser_free($parser);
219
        return [
220
            'Loading_Index'     => $arrayErrors[0]['attributes']['Index_incarcare'],
221
            'Size'              => $arrayData['Size'],
222
            'Response_DateTime' => $arrayData['FileDateTime'],
223
            'Supplier_CUI'      => 'RO' . $arrayErrors[0]['attributes']['Cif_emitent'],
224
            'Supplier_Name'     => '??????????',
225
            'Error'             => sprintf($strErrorTag, $arrayErrors[1]['attributes']['errorMessage']),
226
        ];
227
    }
228
229
    private function setLocalization(): void
230
    {
231
        if (!array_key_exists('language_COUNTRY', $_GET)) {
232
            $_GET['language_COUNTRY'] = 'ro_RO';
233
        }
234
        $loader            = new \Gettext\Loader\PoLoader();
235
        $this->translation = $loader->loadFile(__DIR__ . '/locale/' . $_GET['language_COUNTRY']
236
            . '/LC_MESSAGES/eFactura.po');
237
    }
238
239
    private function setStandardizedFeedbackArray(array $arrayData): array
240
    {
241
        $arrayToReturn = $this->setDefaultsToInvoiceDetailsArray($arrayData);
242
        $strErrorTag   = '<div style="max-width:200px;font-size:0.8rem;">%s</div>';
243
        $strTimeZone   = $this->translation->find(null, 'i18n_TimeZone')->getTranslation();
244
        $strFormatter  = new \IntlDateFormatter(
245
            $_GET['language_COUNTRY'],
246
            \IntlDateFormatter::FULL,
247
            \IntlDateFormatter::FULL,
248
            $strTimeZone,
249
            \IntlDateFormatter::GREGORIAN,
250
            'r-MM__MMMM'
251
        );
252
        if (array_key_exists('Error', $arrayData)) {
253
            $arrayToReturn['Error'] = sprintf($strErrorTag, $arrayData['Error']);
254
            $arrayToReturn['Size']  = 0;
255
        } else {
256
            $appR              = new \danielgp\efactura\ClassElectronicInvoiceRead();
257
            $objFile           = $appR->readElectronicXmlHeader($arrayData['strInvoiceContent']);
258
            $documentHeaderTag = $appR->getDocumentRoot($objFile);
259
            switch($documentHeaderTag['DocumentTagName']) {
260
                case 'header':
261
                    switch($documentHeaderTag['DocumentNameSpaces']['']) {
262
                        case 'mfp:anaf:dgti:efactura:mesajEroriFactuta:v1':
263
                            $arrayTemp     = $this->setErrorsFromExtendedMarkupLaguage($arrayData, $strErrorTag);
264
                            $arrayToReturn = array_merge($arrayToReturn, $arrayTemp);
265
                            break;
266
                        case 'mfp:anaf:dgti:spv:reqMesaj:v1':
267
                            $arrayTemp     = [
268
                                'Loading_Index'     => $documentHeaderTag['header']['index_incarcare'],
269
                                'Message'           => $documentHeaderTag['header']['message'],
270
                                'Size'              => $arrayData['Size'],
271
                                'Response_DateTime' => $arrayData['FileDateTime'],
272
                            ];
273
                            $arrayToReturn = array_merge($arrayToReturn, $arrayTemp);
274
                            break;
275
                    }
276
                    break;
277
                case 'Invoice':
278
                    $arrayAttr     = $this->getDocumentDetails($arrayData);
279
                    $arrayTemp     = [
280
                        'Loading_Index'          => substr($arrayData['Matches'][0][0], 0, -4),
281
                        'Size'                   => $arrayData['Size'],
282
                        'Document_Type_Code'     => $arrayAttr['DocumentTypeCode'],
283
                        'Document_No'            => $arrayAttr['ID'],
284
                        'Issue_Date'             => $arrayAttr['IssueDate'],
285
                        'Issue_YearMonth'        => $strFormatter->format(new \DateTime($arrayAttr['IssueDate'])),
286
                        'Response_DateTime'      => $arrayData['FileDateTime'],
287
                        'Document_Currency_Code' => $arrayAttr['DocumentCurrencyCode'],
288
                        'Amount_wo_VAT'          => $arrayAttr['wo_VAT'],
289
                        'Amount_TOTAL'           => $arrayAttr['TOTAL'],
290
                        'Amount_VAT'             => round(($arrayAttr['TOTAL'] - $arrayAttr['wo_VAT']), 2),
291
                        'Supplier_CUI'           => $this->setDataSupplierOrCustomer($arrayAttr['Supplier']),
292
                        'Supplier_Name'          => $arrayAttr['Supplier']['PartyLegalEntity']['RegistrationName'],
293
                        'Customer_CUI'           => $this->setDataSupplierOrCustomer($arrayAttr['Customer']),
294
                        'Customer_Name'          => $arrayAttr['Customer']['PartyLegalEntity']['RegistrationName'],
295
                        'No_of_Lines'            => $arrayAttr['No_of_Lines'],
296
                        'Days_Between'           => $this->setDaysElapsed($arrayAttr['IssueDate'], $arrayData['FileDateTime']),
297
                    ];
298
                    $arrayToReturn = array_merge($arrayToReturn, $arrayTemp);
299
                    break;
300
            }
301
        }
302
        return $arrayToReturn;
303
    }
304
}
305