Passed
Push — main ( 6985c7...fc1e24 )
by Daniel
03:02
created

setDefaultsToInvoiceDetailsArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 18
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 20
rs 9.6666
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
20
    use \danielgp\io_operations\InputOutputFiles;
21
22
    protected array $arrayConfiguration;
23
    protected $translation;
24
25
    public function actionAnalyzeZIPfromANAFfromLocalFolder(string $strFilePath): array
26
    {
27
        $arrayFiles    = new \RecursiveDirectoryIterator($strFilePath, \FilesystemIterator::SKIP_DOTS);
28
        $arrayInvoices = [];
29
        $intFileNo     = 0;
30
        foreach ($arrayFiles as $strFile) {
31
            if ($strFile->isFile()) {
32
                $arrayFileDetails = $this->handleResponseFile($strFile);
33
                if ($arrayFileDetails !== []) {
34
                    $arrayInvoices[$intFileNo] = $arrayFileDetails;
35
                    $intFileNo++;
36
                }
37
            }
38
        }
39
        return $arrayInvoices;
40
    }
41
42
    protected function getConfiguration()
43
    {
44
        $this->arrayConfiguration = $this->getArrayFromJsonFile(__DIR__
45
            . DIRECTORY_SEPARATOR . 'config', 'BasicConfiguration.json');
46
    }
47
48
    /**
49
     * Archived document is read as content in memory since 2024-02-16
50
     * (prior to this date a temporary local file was saved, processed and finally removed when done with it)
51
     *
52
     * @param array $arrayData
53
     * @return array
54
     */
55
    private function getDocumentDetails(array $arrayData): array
56
    {
57
        $appR               = new \danielgp\efactura\ClassElectronicInvoiceRead();
58
        $arrayElectronicInv = $appR->readElectronicInvoice($arrayData['strInvoiceContent']);
59
        $arrayBasic         = $arrayElectronicInv['Header']['CommonBasicComponents-2'];
60
        $arrayAggregate     = $arrayElectronicInv['Header']['CommonAggregateComponents-2'];
61
        $arrayStandardized  = [
62
            'Customer'    => $arrayAggregate['AccountingCustomerParty']['Party'],
63
            'ID'          => $arrayBasic['ID'],
64
            'IssueDate'   => $arrayBasic['IssueDate'],
65
            'No_of_Lines' => count($arrayElectronicInv['Lines']),
66
            'Supplier'    => $arrayAggregate['AccountingSupplierParty']['Party'],
67
            'TOTAL'       => (float) $arrayAggregate['LegalMonetaryTotal']['TaxInclusiveAmount']['value'],
68
            'wo_VAT'      => (float) $arrayAggregate['LegalMonetaryTotal']['TaxExclusiveAmount']['value'],
69
        ];
70
        return $arrayStandardized;
71
    }
72
73
    private function handleResponseFile(\SplFileInfo|string $strFile): array
74
    {
75
        $arrayToReturn = [];
76
        $strFileMime   = mime_content_type($strFile->getRealPath());
77
        switch ($strFileMime) {
78
            case 'application/json':
79
                $arrayError    = $this->getArrayFromJsonFile($strFile->getPath(), $strFile->getFilename());
80
                $arrayToReturn = $this->setStandardizedFeedbackArray([
81
                    'Error'          => $arrayError['eroare'] . ' ===> ' . $arrayError['titlu'],
82
                    'Response_Index' => pathinfo($strFile)['filename'],
83
                ]);
84
                break;
85
            case 'application/zip':
86
                $arrayToReturn = $this->setArchiveFromAnaf($strFile->getRealPath());
87
                break;
88
        }
89
        return $arrayToReturn;
90
    }
91
92
    private function handleArchiveContent(\ZipArchive $classZip, string $strFile): array
93
    {
94
        $arrayToReturn    = [];
95
        $intFilesArchived = $classZip->numFiles;
96
        for ($intArchivedFile = 0; $intArchivedFile < $intFilesArchived; $intArchivedFile++) {
97
            $strArchivedFile = $classZip->getNameIndex($intArchivedFile);
98
            $matches         = [];
99
            preg_match('/^[0-9]{5,20}\.xml$/', $strArchivedFile, $matches, PREG_OFFSET_CAPTURE);
100
            $matches2        = [];
101
            preg_match('/^semnatura_[0-9]{5,20}\.xml$/', $strArchivedFile, $matches2, PREG_OFFSET_CAPTURE);
102
            if ($matches !== []) {
103
                $resInvoice        = $classZip->getStream($strArchivedFile);
104
                $strInvoiceContent = stream_get_contents($resInvoice);
105
                fclose($resInvoice);
106
                $strFileStats      = $classZip->statIndex($intArchivedFile);
107
                $arrayToReturn     = $this->setStandardizedFeedbackArray([
108
                    'Response_Index'      => pathinfo($strFile)['filename'],
109
                    'Size'                => $strFileStats['size'],
110
                    'FileDate'            => date('Y-m-d H:i:s', $strFileStats['mtime']),
111
                    'Matches'             => $matches,
112
                    'strArchivedFileName' => $strArchivedFile,
113
                    'strInvoiceContent'   => $strInvoiceContent,
114
                ]);
115
            } elseif ($matches2 === []) {
116
                echo vsprintf('<div>' . $this->arrayConfiguration['Feedback']['DifferentFile'] . '</div>', [
117
                    $strArchivedFile,
118
                    $strFile->getBasename(),
119
                ]);
120
            }
121
        }
122
        return $arrayToReturn;
123
    }
124
125
    private function setArchiveFromAnaf(string $strFile)
126
    {
127
        $arrayToReturn = [];
128
        $classZip      = new \ZipArchive();
129
        $res           = $classZip->open($strFile, \ZipArchive::RDONLY);
130
        if ($res) {
131
            $arrayToReturn = $this->handleArchiveContent($classZip, $strFile);
132
        } else {
133
            // @codeCoverageIgnoreStart
134
            $arrayToReturn = $this->setStandardizedFeedbackArray([
135
                'Response_Index' => pathinfo($strFile)['filename'],
136
                'Error'          => $this->translation->find(null, 'i18n_Msg_InvalidZip')->getTranslation(),
137
            ]);
138
            // @codeCoverageIgnoreEnd
139
        }
140
        return $arrayToReturn;
141
    }
142
143
    private function setDataSupplierOrCustomer(array $arrayData)
144
    {
145
        $strCustomerCui = '';
146
        if (isset($arrayData['PartyTaxScheme']['01']['CompanyID'])) {
147
            $strCustomerCui = $arrayData['PartyTaxScheme']['01']['CompanyID'];
148
        } else {
149
            $strCustomerCui = $arrayData['PartyLegalEntity']['CompanyID'];
150
        }
151
        if (is_numeric($strCustomerCui)) {
152
            $strCustomerCui = 'RO' . $strCustomerCui;
153
        }
154
        return $strCustomerCui;
155
    }
156
157
    private function setDaysElapsed(string $strFirstDate, string $strLaterDate): string
158
    {
159
        $origin   = new \DateTimeImmutable($strFirstDate);
160
        $target   = new \DateTimeImmutable($strLaterDate);
161
        $interval = $origin->diff($target);
162
        return $interval->format('%R%a');
163
    }
164
165
    private function setDefaultsToInvoiceDetailsArray(string $strResponseIndex): array
166
    {
167
        return [
168
            'Response_Date'   => '',
169
            'Response_Index'  => $strResponseIndex,
170
            'Loading_Index'   => '',
171
            'Size'            => '',
172
            'Document_No'     => '',
173
            'Issue_Date'      => '',
174
            'Issue_YearMonth' => '',
175
            'Amount_wo_VAT'   => '',
176
            'Amount_TOTAL'    => '',
177
            'Amount_VAT'      => '',
178
            'Supplier_CUI'    => '',
179
            'Supplier_Name'   => '',
180
            'Customer_CUI'    => '',
181
            'Customer_Name'   => '',
182
            'No_of_Lines'     => '',
183
            'Error'           => '',
184
            'Days_Between'    => '',
185
        ];
186
    }
187
188
    private function setErrorsFromExtendedMarkupLaguage(array $arrayData, string $strErrorTag): array
189
    {
190
        $arrayErrors = [];
191
        $parser      = xml_parser_create();
192
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
193
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
194
        xml_parse_into_struct($parser, $arrayData['strInvoiceContent'], $arrayErrors);
195
        xml_parser_free($parser);
196
        return [
197
            'Loading_Index' => $arrayErrors[0]['attributes']['Index_incarcare'],
198
            'Size'          => $arrayData['Size'],
199
            'Response_Date' => $arrayData['FileDate'],
200
            'Supplier_CUI'  => 'RO' . $arrayErrors[0]['attributes']['Cif_emitent'],
201
            'Supplier_Name' => '??????????',
202
            'Error'         => sprintf($strErrorTag, $arrayErrors[1]['attributes']['errorMessage']),
203
        ];
204
    }
205
206
    private function setLocalization(): void
207
    {
208
        if (!array_key_exists('language_COUNTRY', $_GET)) {
209
            $_GET['language_COUNTRY'] = 'ro_RO';
210
        }
211
        $loader            = new \Gettext\Loader\PoLoader();
212
        $this->translation = $loader->loadFile(__DIR__ . '/locale/' . $_GET['language_COUNTRY']
213
            . '/LC_MESSAGES/eFactura.po');
214
    }
215
216
    private function setStandardizedFeedbackArray(array $arrayData): array
217
    {
218
        $arrayToReturn = $this->setDefaultsToInvoiceDetailsArray($arrayData['Response_Index']);
219
        $strErrorTag   = '<div style="max-width:200px;font-size:0.8rem;">%s</div>';
220
        if (array_key_exists('Error', $arrayData)) {
221
            $arrayToReturn['Error'] = sprintf($strErrorTag, $arrayData['Error']);
222
            $arrayToReturn['Size']  = 0;
223
        } elseif ($arrayData['Size'] > 1000) {
224
            $strTimeZone   = $this->translation->find(null, 'i18n_TimeZone')->getTranslation();
225
            $strFormatter  = new \IntlDateFormatter(
226
                $_GET['language_COUNTRY'],
227
                \IntlDateFormatter::FULL,
228
                \IntlDateFormatter::FULL,
229
                $strTimeZone,
230
                \IntlDateFormatter::GREGORIAN,
231
                'r-MM__MMMM'
232
            );
233
            $arrayAttr     = $this->getDocumentDetails($arrayData);
234
            $arrayTemp     = [
235
                'Loading_Index'   => substr($arrayData['Matches'][0][0], 0, -4),
236
                'Size'            => $arrayData['Size'],
237
                'Document_No'     => $arrayAttr['ID'],
238
                'Issue_Date'      => $arrayAttr['IssueDate'],
239
                'Issue_YearMonth' => $strFormatter->format(new \DateTime($arrayAttr['IssueDate'])),
240
                'Response_Date'   => $arrayData['FileDate'],
241
                'Amount_wo_VAT'   => $arrayAttr['wo_VAT'],
242
                'Amount_TOTAL'    => $arrayAttr['TOTAL'],
243
                'Amount_VAT'      => round(($arrayAttr['TOTAL'] - $arrayAttr['wo_VAT']), 2),
244
                'Supplier_CUI'    => $this->setDataSupplierOrCustomer($arrayAttr['Supplier']),
245
                'Supplier_Name'   => $arrayAttr['Supplier']['PartyLegalEntity']['RegistrationName'],
246
                'Customer_CUI'    => $this->setDataSupplierOrCustomer($arrayAttr['Customer']),
247
                'Customer_Name'   => $arrayAttr['Customer']['PartyLegalEntity']['RegistrationName'],
248
                'No_of_Lines'     => $arrayAttr['No_of_Lines'],
249
                'Days_Between'    => $this->setDaysElapsed($arrayAttr['IssueDate'], $arrayData['FileDate']),
250
            ];
251
            $arrayToReturn = array_merge($arrayToReturn, $arrayTemp);
252
        } elseif ($arrayData['Size'] > 0) {
253
            $arrayTemp     = $this->setErrorsFromExtendedMarkupLaguage($arrayData, $strErrorTag);
254
            $arrayToReturn = array_merge($arrayToReturn, $arrayTemp);
255
        }
256
        return $arrayToReturn;
257
    }
258
}
259