AbstractDocument   A
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 385
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 96
dl 0
loc 385
rs 9.44
c 0
b 0
f 0
wmc 37

34 Methods

Rating   Name   Duplication   Size   Complexity  
A getId() 0 2 1
A setIssuer() 0 3 1
A setIssuerFields() 0 3 1
A parseInputLine() 0 2 1
A parseCommonFields() 0 4 1
A saveDocumentInput() 0 2 1
A getIssuer() 0 2 1
A setFileName() 0 3 1
A generateFiles() 0 5 1
A hasLegalValidity() 0 2 1
A setId() 0 2 1
A signXmlFile() 0 2 1
A getRawData() 0 2 1
A setSeries() 0 3 1
A getBaseFieldsForXml() 0 11 1
A getNumber() 0 2 1
A getSeries() 0 2 1
A generateXmlFile() 0 6 1
A getLinesForXml() 0 6 2
A getXmlTplName() 0 2 1
A setCommonFields() 0 3 1
A getFileName() 0 2 1
A getLineForXml() 0 2 1
A setNumber() 0 3 1
A getLines() 0 2 1
A processInput() 0 5 1
A parseInputLines() 0 7 2
A getLineDefaults() 0 2 1
A __construct() 0 27 2
A getIssueDate() 0 2 1
A generateZipFile() 0 2 1
A setXmlTplName() 0 3 1
A setIssueDate() 0 3 1
A getParsedData() 0 2 1
1
<?php
2
3
/**
4
 * MÓDULO DE EMISIÓN ELECTRÓNICA F72X
5
 * UBL 2.1
6
 * Version 1.0
7
 * 
8
 * Copyright 2019, Jaime Cruz
9
 */
10
11
namespace F72X\Sunat\Document;
12
13
use DateTime;
14
use F72X\F72X;
15
use F72X\Company;
16
use F72X\Repository;
17
use F72X\Object\DocumentIssuer;
18
use F72X\Tools\TplRenderer;
19
use F72X\Tools\XmlDSig;
20
21
/**
22
 * AbstractDocument
23
 * 
24
 * This is base for all kind of documents
25
 */
26
abstract class AbstractDocument implements DocumentInterface {
27
28
    /**
29
     * The document's signature id.
30
     * 
31
     * By now this must be 'SignIMM' as in:
32
     * {@see \Greenter\XMLSecLibs\XMLSecurityDSig} line 70
33
     * 
34
     */
35
    const SIGNATURE_ID = 'SignIMM';
36
37
    /**
38
     * The Peruvian currency code
39
     */
40
    const LOCAL_CURRENCY_CODE = 'PEN';
41
42
    /**
43
     * The document's id.
44
     * 
45
     * @var string 
46
     */
47
    protected $id;
48
49
    /**
50
     * By default all the documents use series, however it's false in case of
51
     * Resumenes y Comunicaciones de baja.
52
     * @var type 
0 ignored issues
show
Bug introduced by
The type F72X\Sunat\Document\type was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
53
     */
54
    protected $usesSeries = true;
55
56
    /**
57
     * The document's series.
58
     * 
59
     * @var string 
60
     */
61
    protected $series;
62
63
    /**
64
     * The document's series prefix
65
     * 
66
     * Use:
67
     *  F: Factura
68
     *  B: Boleta
69
     *  P: Percepción
70
     *  R: Retención
71
     * 
72
     * @var string 
73
     */
74
    protected $seriesPrefix;
75
76
    /**
77
     * The document's number.
78
     * 
79
     * @var string 
80
     */
81
    protected $number;
82
83
    /**
84
     * The document's number max length
85
     * 
86
     * Default: 8 for Boletas, Facturas, Nota de crédito, Nota de débito,
87
     * Percepción y Retención.
88
     * 
89
     * Use: 5 for Resumen diario y comunicacón de baja.
90
     * 
91
     * @var int 
92
     */
93
    protected $numberMaxLength = 8;
94
95
    /**
96
     * The date when the document is generated.
97
     * 
98
     * @var DateTime 
99
     */
100
    protected $issueDate;
101
102
    /**
103
     * Saves the legal validity of the document
104
     * 
105
     * @var DateTime 
106
     */
107
    protected $legalValidity;
108
109
    /**
110
     * The document's filename.
111
     * 
112
     * @var string 
113
     */
114
    protected $fileName;
115
116
    /**
117
     * The entity that produces the document usually the company.
118
     * 
119
     * @var DocumentIssuer 
120
     */
121
    protected $issuer;
122
123
    /**
124
     * The document's lines.
125
     * 
126
     * @var array 
127
     */
128
    protected $lines;
129
130
    /**
131
     * Use this to set the default fields for the document lines.
132
     * @var array 
133
     */
134
    protected $lineDefaults = [];
135
136
    /**
137
     * Use this to  indicate the template that the document is going to use in
138
     * the XML file creation.
139
     * 
140
     * @var string
141
     */
142
    protected $xmlTplName;
143
144
    /**
145
     * Saves the received data by the constructor.
146
     * 
147
     * @var array 
148
     */
149
    private $rawData;
150
151
    /**
152
     * Saves the parsed data that is returned by the *parseInput* method.
153
     * @var array
154
     */
155
    private $parsedData;
156
157
    /**
158
     * Creates the document
159
     * 
160
     * @param array $inputData
161
     */
162
    public function __construct(array $inputData) {
163
        // Input validation
164
        $this->validateInput($inputData);
165
        // Input process
166
        $this->processInput($inputData);
167
        // Set Number
168
        $this->setNumber();
169
        // Set Series
170
        if ($this->usesSeries) {
171
            $this->setSeries();
172
        }
173
174
        // Set Common fields
175
        $this->setCommonFields();
176
        // Create an issuer instance
177
        $this->issuer = new DocumentIssuer();
178
        // Sets the company fields such as (RUC, Razón Social, etc.)
179
        $this->setIssuerFields();
180
        // Sets the fields related to the tipe of document.
181
        $this->setBodyFields();
182
        /**
183
         * Set Document ID This is last because some
184
         * fields depend on issuer and body fields.
185
         */
186
        $this->setId();
187
        // Set Filename
188
        $this->setFileName();
189
    }
190
191
    protected function setNumber() {
192
        $this->number = str_pad($this->parsedData['documentNumber'], $this->numberMaxLength, '0', STR_PAD_LEFT);
193
        return $this;
194
    }
195
196
    protected function setSeries() {
197
        $this->series = $this->seriesPrefix . $this->parsedData['documentSeries'];
198
        return $this;
199
    }
200
201
    /**
202
     * Sets the document's id
203
     * 
204
     * This can be overridden to create a new id format
205
     * Default SERIES-NUMBER
206
     */
207
    protected function setId() {
208
        $this->id = $this->series . '-' . $this->number;
209
    }
210
211
    private function setCommonFields() {
212
        $this->issueDate = $this->parsedData['issueDate'];
213
        $this->legalValidity = $this->parsedData['legalValidity'];
214
    }
215
216
    protected function setFileName() {
217
        // The  file name
218
        $this->fileName = $this->issuer->getIdDocNumber() . '-' . $this->id;
219
    }
220
221
    private function processInput(array $in) {
222
        $this->rawData = $in;
223
        $out1 = $this->parseCommonFields($in);
224
        $out2 = $this->parseInput($out1);
225
        $this->parsedData = $out2;
226
    }
227
228
    private function parseCommonFields(array $in) {
229
        $out = $in;
230
        $out['issueDate'] = new DateTime($in['issueDate']);
231
        return $out;
232
    }
233
234
    /**
235
     * Parses the raw input data
236
     * @param array $in The input data
237
     * @return array The parsed data
238
     */
239
    abstract protected function parseInput(array $in);
240
241
    public function parseInputLines(array $rawLines) {
242
        $parsedLines = [];
243
        foreach ($rawLines as $line) {
244
            $line = array_merge($this->lineDefaults, $line);
245
            $parsedLines[] = $this->parseInputLine($line);
246
        }
247
        return $parsedLines;
248
    }
249
250
    /**
251
     * 
252
     * @param array $in The raw input line
253
     * @return array
254
     */
255
    public function parseInputLine(array $in) {
256
        return $in;
257
    }
258
259
    public function setIssuerFields() {
260
        $this->issuer->setIdDocNumber(Company::getRUC());
261
        $this->issuer->setRegName(Company::getCompanyName());
262
    }
263
264
    /**
265
     * Returns the base fields for an XML file rendering.
266
     * @return array
267
     */
268
    protected function getBaseFieldsForXml() {
269
        $issuer = $this->issuer;
270
        return [
271
            'id' => $this->id,
272
            'issueDate' => $this->issueDate->format('Y-m-d'),
273
            'issuer' => [
274
                'idDocType' => $issuer->getIdDocType(),
275
                'idDocNumber' => $issuer->getIdDocNumber(),
276
                'regName' => $issuer->getRegName(),
277
            ],
278
            'lines' => $this->getLinesForXml($this->lines)
279
        ];
280
    }
281
282
    /**
283
     * Returns the parsed lines for the XML file rendering.
284
     * 
285
     * @param array $in The input data
286
     * @return array
287
     */
288
    protected function getLinesForXml(array $in) {
289
        $out = [];
290
        foreach ($in as $line) {
291
            $out[] = $this->getLineForXml($line);
292
        }
293
        return $out;
294
    }
295
296
    /**
297
     * Returns the parsed line for the XML file rendering.
298
     * 
299
     * @param array $in The input data
300
     * @return array
301
     */
302
    protected function getLineForXml(array $in) {
303
        return $in;
304
    }
305
306
    /**
307
     * Generates the document base files
308
     * Witch are the next:
309
     *     Document input
310
     *     The XML file
311
     *     The signed XML file
312
     *     The ZIP file
313
     */
314
    public function generateFiles() {
315
        $this->saveDocumentInput();
316
        $this->generateXmlFile();
317
        $this->signXmlFile();
318
        $this->generateZipFile();
319
    }
320
321
    public function saveDocumentInput() {
322
        Repository::saveDocumentInput($this->fileName, json_encode($this->getRawData(), JSON_PRETTY_PRINT));
323
    }
324
325
    /**
326
     * Generates the document's XML file
327
     */
328
    public function generateXmlFile() {
329
        $tplRenderer = TplRenderer::getRenderer(F72X::getSrcDir() . '/templates');
330
        $xmlData = $this->getDataForXml();
331
        $xmlData['signatureId'] = self::SIGNATURE_ID;
332
        $xmlContent = $tplRenderer->render($this->xmlTplName, $xmlData);
333
        Repository::saveDocument($this->fileName, $xmlContent);
334
    }
335
336
    /**
337
     * Signs the XML document witch should be generated previously.
338
     */
339
    public function signXmlFile() {
340
        XmlDSig::sign($this->fileName);
341
    }
342
343
    /**
344
     * Generates the document's ZIP file
345
     */
346
    public function generateZipFile() {
347
        Repository::zipDocument($this->fileName);
348
    }
349
350
    public function getId() {
351
        return $this->id;
352
    }
353
354
    public function getSeries() {
355
        return $this->series;
356
    }
357
358
    public function getNumber() {
359
        return $this->number;
360
    }
361
362
    public function getIssueDate() {
363
        return $this->issueDate;
364
    }
365
366
    public function getFileName() {
367
        return $this->fileName;
368
    }
369
370
    public function hasLegalValidity() {
371
        return $this->legalValidity;
372
    }
373
374
    public function getIssuer() {
375
        return $this->issuer;
376
    }
377
378
    public function getLines() {
379
        return $this->lines;
380
    }
381
382
    public function getLineDefaults() {
383
        return $this->lineDefaults;
384
    }
385
386
    public function getXmlTplName() {
387
        return $this->xmlTplName;
388
    }
389
390
    public function getRawData() {
391
        return $this->rawData;
392
    }
393
394
    public function getParsedData() {
395
        return $this->parsedData;
396
    }
397
398
    public function setIssueDate(DateTime $issueDate) {
399
        $this->issueDate = $issueDate;
400
        return $this;
401
    }
402
403
    public function setIssuer(DocumentIssuer $issuer) {
404
        $this->issuer = $issuer;
405
        return $this;
406
    }
407
408
    public function setXmlTplName($xmlTplName) {
409
        $this->xmlTplName = $xmlTplName;
410
        return $this;
411
    }
412
413
}
414