PDFDocument::insertBusinessDocFooter()   F
last analyzed

Complexity

Conditions 18
Paths 2592

Size

Total Lines 142
Code Lines 97

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 97
nc 2592
nop 1
dl 0
loc 142
rs 0.6254
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * Copyright (C) 2022 Joe Nilson <[email protected]>
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Lesser General Public License as
7
 * published by the Free Software Foundation, either version 3 of the
8
 * License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Lesser General Public License for more details.
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
namespace FacturaScripts\Plugins\fsRepublicaDominicana\Lib\PDF;
19
20
use FacturaScripts\Core\Tools;
21
use FacturaScripts\Core\Lib\TwoFactorManager;
22
use FacturaScripts\Dinamic\Model\Empresa;
23
use FacturaScripts\Core\Lib\PDF\PDFDocument as ParentClass;
0 ignored issues
show
Bug introduced by
The type FacturaScripts\Core\Lib\PDF\PDFDocument 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...
24
25
abstract class PDFDocument extends ParentClass
26
{
27
    protected function insertBusinessDocHeader($model): void
28
    {
29
        $headerData = [
30
            'title' => $this->i18n->trans($model->modelClassName() . '-min'),
31
            'subject' => $this->i18n->trans('customer'),
32
            'fieldName' => 'nombrecliente'
33
        ];
34
35
        if (isset($model->codproveedor)) {
36
            $headerData['subject'] = $this->i18n->trans('supplier');
37
            $headerData['fieldName'] = 'nombre';
38
        }
39
40
        if (!empty($this->format->titulo)) {
41
            $headerData['title'] = Tools::fixHtml($this->format->titulo);
42
        }
43
44
        $y = $this->pdf->y;
45
        $this->pdf->ezText($model->descripcionTipoComprobante(), self::FONT_SIZE + 2, ['justification' => 'right']);
46
        $this->pdf->ezSetY($y);
47
        $this->pdf->ezText($headerData['title'] . ': ' . $model->numeroncf . "\n", self::FONT_SIZE + 2);
48
        $this->newLine();
49
50
        $subject = $model->getSubject();
51
        $tipoidfiscal = empty($subject->tipoidfiscal) ? $this->i18n->trans('cifnif') : $subject->tipoidfiscal;
52
53
        $tableData = [
54
            ['key' => $headerData['subject'], 'value' => Tools::fixHtml($model->{$headerData['fieldName']})],
55
            ['key' => $this->i18n->trans('date'), 'value' => $model->fecha],
56
            ['key' => $this->i18n->trans('address'), 'value' => $this->getDocAddress($subject, $model)],
57
            ['key' => $tipoidfiscal, 'value' => $model->cifnif],
58
            ['key' => $this->i18n->trans('tipocomprobante'), 'value' => $model->descripcionTipoComprobante()],
59
            ['key' => $this->i18n->trans('number'), 'value' => $model->numeroncf],
60
            ['key'=>$this->i18n->trans('code'), 'value'=> $model->codigo],
61
            ['key' => $this->i18n->trans('due-date'), 'value' => $model->ncffechavencimiento],
62
            ['key' => $this->i18n->trans('currency'), 'value' => $this->getDivisaName($model->coddivisa)],
63
        ];
64
65
        // rectified invoice?
66
        if (!empty($model->codigorect)) {
67
            $facturaOrigen = $model->parentDocuments();
68
            $tableData[9] = ['key' => $this->i18n->trans('ncf-modifies'), 'value' => $facturaOrigen[0]->numeroncf];
69
        }
70
71
        $tableOptions = [
72
            'width' => $this->tableWidth,
73
            'showHeadings' => 0,
74
            'shaded' => 0,
75
            'lineCol' => [1, 1, 1],
76
            'cols' => []
77
        ];
78
        $this->insertParallelTable($tableData, '', $tableOptions);
79
        $this->pdf->ezText('');
80
81
        if (!empty($model->idcontactoenv)
82
            && ($model->idcontactoenv !== $model->idcontactofact || !empty($model->codtrans))) {
83
            $this->insertBusinessDocShipping($model);
84
        }
85
    }
86
    protected function getLineHeaders(): array
87
    {
88
        return [
89
            'codarticulo' => ['type' => 'text', 'title' => $this->i18n->trans('code')],
90
            'referencia' => ['type' => 'text', 'title' => $this->i18n->trans('reference')],
91
            'cantidad' => ['type' => 'number', 'title' => $this->i18n->trans('quantity')],
92
            'pvpunitario' => ['type' => 'number', 'title' => $this->i18n->trans('price')],
93
            'pvptotal' => ['type' => 'number', 'title' => $this->i18n->trans('subtotal')],
94
            'iva_value' => ['type' => 'number', 'title' => $this->i18n->trans('iva')],
95
            'rdtaxisc_value' => ['type' => 'number', 'title' => $this->i18n->trans('rdtaxisc')],
96
            'rdtaxcdt_value' => ['type' => 'number', 'title' => $this->i18n->trans('rdtaxcdt')],
97
            'rdtaxlegaltip_value' => ['type' => 'number', 'title' => $this->i18n->trans('rdtaxlegaltip')],
98
            'rdtaxfirstplate_value' => ['type' => 'number', 'title' => $this->i18n->trans('rdtaxfirstplate')],
99
            'totalplustaxes' => ['type' => 'number', 'title' => $this->i18n->trans('total')]
100
        ];
101
    }
102
103
    protected function insertBusinessDocBody($model)
104
    {
105
        $qrTitle = $this->pipe('qrTitleAfterLines', $model);
106
        $qrImage = $this->pipe('qrImageAfterLines', $model);
107
        $qrSubtitle = $this->pipe('qrSubtitleAfterLines', $model);
108
109
        $headers = [];
110
        $tableOptions = [
111
            'cols' => [],
112
            'shadeCol' => [0.95, 0.95, 0.95],
113
            'shadeHeadingCol' => [0.95, 0.95, 0.95],
114
            'width' => $this->tableWidth
115
        ];
116
117
        // fill headers and options with the line headers information
118
        $lineHeaders = $this->getLineHeaders();
119
        foreach ($lineHeaders as $key => $value) {
120
            $headers[$key] = $value['title'];
121
            if (in_array($value['type'], ['number', 'percentage'], true)) {
122
                $tableOptions['cols'][$key] = ['justification' => 'right'];
123
            }
124
        }
125
126
        $allLines = $model->getlines();
127
        $fullTableData = [];
128
        foreach ($allLines as $line) {
129
            // Calcular valores adicionales en valor monetario
130
            $line->iva_value = (float)($line->pvptotal ?? 0) * (float)($line->iva ?? 0) / 100.0;
131
            $line->rdtaxisc_value = (float)($line->pvpsindto ?? 0) * (float)($line->rdtaxisc ?? 0) / 100.0;
132
            $line->rdtaxcdt_value = (float)($line->pvpsindto ?? 0) * (float)($line->rdtaxcdt ?? 0) / 100.0;
133
            $line->rdtaxlegaltip_value = (float)($line->pvpsindto ?? 0) * (float)($line->rdtaxlegaltip ?? 0) / 100.0;
134
            $line->rdtaxfirstplate_value = (float)($line->pvpsindto ?? 0) * (float)($line->rdtaxfirstplate ?? 0) / 100.0;
135
136
            $data = [];
137
            foreach ($lineHeaders as $key => $value) {
138
                if (property_exists($line, 'mostrar_precio') &&
139
                    $line->mostrar_precio === false &&
140
                    in_array($key, ['pvpunitario', 'dtopor', 'dtopor2', 'pvptotal', 'iva', 'recargo', 'irpf', 'iva_value', 'rdtaxisc_value', 'rdtaxcdt_value', 'rdtaxlegaltip_value', 'rdtaxfirstplate_value', 'totalplustaxes'], true)) {
141
                    continue;
142
                }
143
144
                if ($key === 'referencia') {
145
                    $data[$key] = empty($line->referencia) ? Tools::fixHtml($line->descripcion) : Tools::fixHtml($line->referencia . " - " . $line->descripcion);
146
                } elseif ($key === 'cantidad' && property_exists($line, 'mostrar_cantidad')) {
147
                    $data[$key] = $line->mostrar_cantidad ? $line->{$key} : '';
148
                } elseif ($value['type'] === 'percentage') {
149
                    $data[$key] = Tools::number($line->{$key}) . '%';
150
                } elseif ($value['type'] === 'number') {
151
                    $data[$key] = Tools::number($line->{$key});
152
                } else {
153
                    $data[$key] = $line->{$key};
154
                }
155
            }
156
            $fullTableData[] = $data;
157
        }
158
159
        // Eliminamos las columnas vacías en todo el documento para mantener consistencia
160
        $this->removeEmptyCols($fullTableData, $headers, Tools::number(0));
161
162
        $tableData = [];
163
        foreach ($fullTableData as $index => $data) {
164
            $tableData[] = $data;
165
            $line = $allLines[$index];
166
167
            if (property_exists($line, 'salto_pagina') && $line->salto_pagina) {
168
                $this->pdf->ezTable($tableData, $headers, '', $tableOptions);
169
                $tableData = [];
170
                $this->pdf->ezNewPage();
171
            }
172
        }
173
174
        if (false === empty($tableData)) {
175
            $this->pdf->ezTable($tableData, $headers, '', $tableOptions);
176
        }
177
178
        // añadir el código QR si existe
179
        if ($model->modelClassName() === 'FacturaCliente' && !empty($qrImage) && substr($model->numeroncf, 0, 1) === "E") {
180
            // Añadir margen superior antes del QR
181
            $this->pdf->y -= 10;
182
183
            // Calcular el ancho disponible con margen derecho (usar mismo layout que el header)
184
            $pageWidth = $this->pdf->ez['pageWidth'] - $this->pdf->ez['leftMargin'] - $this->pdf->ez['rightMargin'];
185
            $rightBlockWidth = $pageWidth * 0.2; // 20% para el QR (igual que en header)
186
            $leftBlockWidth = $pageWidth * 0.8;  // 80% espacio libre a la izquierda (igual que en header)
187
            $this->renderQRimage($qrImage, $qrTitle, $qrSubtitle, $this->pdf->ez['leftMargin'], $this->pdf->y, $leftBlockWidth, $rightBlockWidth);
188
        }
189
    }
190
191
    protected function insertBusinessDocFooter($model)
192
    {
193
        if (!empty($model->observaciones)) {
194
            $this->newPage();
195
            $this->pdf->ezText($this->i18n->trans('observations') . "\n", self::FONT_SIZE);
196
            $this->newLine();
197
            $this->pdf->ezText(Tools::fixHtml($model->observaciones) . "\n", self::FONT_SIZE);
198
        }
199
200
        $this->newPage();
201
202
        // taxes
203
        $taxHeaders = [
204
            'tax' => $this->i18n->trans('tax'),
205
            'taxbase' => $this->i18n->trans('tax-base'),
206
            'taxp' => $this->i18n->trans('percentage'),
207
            'taxamount' => $this->i18n->trans('amount'),
208
            'taxsurchargep' => $this->i18n->trans('re'),
209
            'taxsurcharge' => $this->i18n->trans('amount')
210
        ];
211
        $taxRows = $this->getTaxesRows($model);
212
        $taxTableOptions = [
213
            'cols' => [
214
                'tax' => ['justification' => 'right'],
215
                'taxbase' => ['justification' => 'right'],
216
                'taxp' => ['justification' => 'right'],
217
                'taxamount' => ['justification' => 'right'],
218
                'taxsurchargep' => ['justification' => 'right'],
219
                'taxsurcharge' => ['justification' => 'right']
220
            ],
221
            'shadeCol' => [0.95, 0.95, 0.95],
222
            'shadeHeadingCol' => [0.95, 0.95, 0.95],
223
            'width' => $this->tableWidth
224
        ];
225
        if (count($taxRows) > 1) {
226
            $this->removeEmptyCols($taxRows, $taxHeaders, Tools::number(0));
227
            $this->pdf->ezTable($taxRows, $taxHeaders, '', $taxTableOptions);
228
            $this->pdf->ezText("\n");
229
        } elseif ($this->pdf->ezPageCount < 2 && strlen($this->format->texto ?? '') < 400 && $this->pdf->y > static::INVOICE_TOTALS_Y) {
230
            $this->pdf->y = static::INVOICE_TOTALS_Y;
231
        }
232
233
        // Tarea 2: Totales específicos
234
        $headers = [
235
            'label' => '',
236
            'value' => ''
237
        ];
238
        $rows = [
239
            ['label' => $this->i18n->trans('total-exempt'), 'value' => Tools::number($model->totalexento)],
240
            ['label' => $this->i18n->trans('total-taxed'), 'value' => Tools::number($model->neto - $model->totalexento)],
241
        ];
242
243
        // Suma de cada impuesto adicional
244
        $addedTaxes = [
245
            'rdtaxisc' => 0,
246
            'rdtaxcdt' => 0,
247
            'rdtaxlegaltip' => 0,
248
            'rdtaxfirstplate' => 0
249
        ];
250
        foreach ($model->getLines() as $line) {
251
            foreach (array_keys($addedTaxes) as $tax) {
252
                if (!empty($line->{$tax})) {
253
                    $addedTaxes[$tax] += (float)$line->pvpsindto * (float)$line->{$tax} / 100.0;
254
                }
255
            }
256
        }
257
        $rows[] = ['label' => $this->i18n->trans('iva') . ' ' . $line->iva . '%', 'value' => Tools::number($model->totaliva)];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $line seems to be defined by a foreach iteration on line 250. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
258
        foreach ($addedTaxes as $tax => $value) {
259
            if ($value > 0) {
260
                $rows[] = ['label' => $this->i18n->trans($tax) . ' ' . $line->{$tax} . '%', 'value' => Tools::number($value)];
261
            }
262
        }
263
264
        $rows[] = ['label' => $this->i18n->trans('total-added-taxes') , 'value' => Tools::number($model->totaladdedtaxes)];
265
266
        $total_final = ($model->totalplustaxes !== 0.0) ? $model->totalplustaxes : ($model->totaliva + $model->totaladdedtaxes + $model->neto);
267
268
        $rows[] = ['label' => $this->i18n->trans('total'), 'value' => Tools::number($total_final)];
269
270
        // QR y Datos de Seguridad
271
        $qrBlockWidth = 0;
272
        $startY = $this->pdf->y;
273
        $qrBottomY = $startY;
274
275
        if ($model->modelClassName() === 'FacturaCliente' && (substr($model->numeroncf, 0, 1) === 'E')) {
276
            $code = Tools::settings('default', 'idempresa', '');
277
            $company = new Empresa();
278
            if ($company->load($code)) {
279
                $url = "https://fc.dgii.gov.do/ecf/consultatimbrefc?" . http_build_query([
280
                    'RncEmisor' => $company->cifnif,
281
                    'ENCF' => $model->numeroncf,
282
                    'FechaEmision' => $model->fecha,
283
                    'MontoTotal' => $model->totalplustaxes,
284
                    'FechaFirma' => $model->ecf_fecha_firma,
285
                    'CodigoSeguridad' => $model->ecf_codigo_seguridad
286
                ]);
287
288
                $qrImage = TwoFactorManager::getQRCodeImage($url);
289
                $qrBlockWidth = 130;
290
                $this->renderQRimage($qrImage, null, null, $this->pdf->ez['leftMargin'], $startY + 15, 0, $qrBlockWidth);
291
292
                // Manualmente agregamos los datos de seguridad debajo del QR
293
                $qrSize = 110;
294
                $qrX = $this->pdf->ez['leftMargin'] + 10 + ($qrBlockWidth - 10 - $qrSize) / 2;
295
                $textX = $qrX + 6;
296
                $textY = $startY - $qrSize;
297
                $this->pdf->addText($textX, $textY, self::FONT_SIZE - 2, $this->i18n->trans('desc-ecf_codigo_seguridad') . ": " . $model->ecf_codigo_seguridad, 0, 'left');
298
                $this->pdf->addText($textX, $textY - self::FONT_SIZE, self::FONT_SIZE - 2, $this->i18n->trans('desc-ecf_fecha_firma') . ': ' . $model->ecf_fecha_firma, 0, 'left');
299
                $qrBottomY = $textY - self::FONT_SIZE - 10;
300
            }
301
        }
302
303
        // Totales al lado del QR
304
        $this->pdf->ezSetY($startY);
305
        $tableOptions = [
306
            'showHeadings' => 0,
307
            'shaded' => 0,
308
            'width' => $this->tableWidth - $qrBlockWidth,
309
            'cols' => [
310
                'label' => ['justification' => 'right', 'width' => ($this->tableWidth - $qrBlockWidth) * 0.8],
311
                'value' => ['justification' => 'right', 'width' => ($this->tableWidth - $qrBlockWidth) * 0.2]
312
            ]
313
        ];
314
315
        $oldMarginLeft = $this->pdf->ez['leftMargin'];
316
        $this->pdf->ez['leftMargin'] += $qrBlockWidth;
317
        $this->pdf->ezTable($rows, $headers, '', $tableOptions);
318
        $tableBottomY = $this->pdf->y;
319
        $this->pdf->ez['leftMargin'] = $oldMarginLeft;
320
321
        // Aseguramos que los siguientes elementos comiencen después de ambos bloques
322
        $this->pdf->y = min($qrBottomY, $tableBottomY);
323
324
        // receipts
325
        if ($model->modelClassName() === 'FacturaCliente') {
326
            $this->insertInvoiceReceipts($model);
327
        } elseif (isset($model->codcliente)) {
328
            $this->insertInvoicePayMethod($model);
329
        }
330
331
        if (!empty($this->format->texto)) {
332
            $this->pdf->ezText("\n" . Tools::fixHtml($this->format->texto), self::FONT_SIZE);
333
        }
334
    }
335
}