Completed
Push — master ( 0119bb...5b186d )
by Esteban De La Fuente
02:09
created

Dte::setAnchoColumnasDetalle()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 4
nc 3
nop 1
1
<?php
2
3
/**
4
 * LibreDTE
5
 * Copyright (C) SASCO SpA (https://sasco.cl)
6
 *
7
 * Este programa es software libre: usted puede redistribuirlo y/o
8
 * modificarlo bajo los términos de la Licencia Pública General Affero de GNU
9
 * publicada por la Fundación para el Software Libre, ya sea la versión
10
 * 3 de la Licencia, o (a su elección) cualquier versión posterior de la
11
 * misma.
12
 *
13
 * Este programa se distribuye con la esperanza de que sea útil, pero
14
 * SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita
15
 * MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO.
16
 * Consulte los detalles de la Licencia Pública General Affero de GNU para
17
 * obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
22
 */
23
24
namespace sasco\LibreDTE\Sii\Dte\PDF;
25
26
/**
27
 * Clase para generar el PDF de un documento tributario electrónico (DTE)
28
 * chileno.
29
 * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
30
 * @version 2018-11-04
31
 */
32
class Dte extends \sasco\LibreDTE\PDF
33
{
34
35
    use \sasco\LibreDTE\Sii\Dte\Base\DteImpreso;
36
37
    protected $logo; ///< Datos del logo que se ubicará en el PDF (ruta, datos y/o posición)
38
    protected $papelContinuo = false; ///< Indica si se usa papel continuo o no (=0 papel carta, otro valor contínuo en PDF)
39
    protected $ecl = 5; ///< error correction level para PHP >= 7.0.0
40
    protected $papel_continuo_alto = 5000; ///< Alto exageradamente grande para autocálculo de alto en papel continuo
41
    protected $timbre_pie = true; ///< Indica si el timbre va al pie o no (va pegado al detalle)
42
    protected $item_detalle_posicion = 0; ///< Posición del detalle del item respecto al nombre
43
    protected $detalle_fuente = 10; ///< Tamaño de la fuente para el detalle en hoja carta
44
45
    protected $detalle_cols = [
46
        'CdgItem' => ['title'=>'Código', 'align'=>'left', 'width'=>20],
47
        'NmbItem' => ['title'=>'Item', 'align'=>'left', 'width'=>0],
48
        'IndExe' => ['title'=>'IE', 'align'=>'left', 'width'=>'7'],
49
        'QtyItem' => ['title'=>'Cant.', 'align'=>'right', 'width'=>15],
50
        'UnmdItem' => ['title'=>'Unidad', 'align'=>'left', 'width'=>22],
51
        'QtyRef' => ['title'=>'Cant. Ref.', 'align'=>'right', 'width'=>22],
52
        'PrcItem' => ['title'=>'P. unitario', 'align'=>'right', 'width'=>22],
53
        'DescuentoMonto' => ['title'=>'Descuento', 'align'=>'right', 'width'=>22],
54
        'RecargoMonto' => ['title'=>'Recargo', 'align'=>'right', 'width'=>22],
55
        'MontoItem' => ['title'=>'Total item', 'align'=>'right', 'width'=>22],
56
    ]; ///< Nombres de columnas detalle, alineación y ancho
57
58
    public static $papel = [
59
        0  => 'Hoja carta',
60
        57 => 'Papel contínuo 57mm',
61
        75 => 'Papel contínuo 75mm',
62
        80 => 'Papel contínuo 80mm',
63
        110 => 'Papel contínuo 110mm',
64
    ]; ///< Tamaño de papel que es soportado
65
66
    /**
67
     * Constructor de la clase
68
     * @param papelContinuo =true indica que el PDF se generará en formato papel continuo (si se pasa un número será el ancho del PDF en mm)
69
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
70
     * @version 2016-10-06
71
     */
72
    public function __construct($papelContinuo = false)
73
    {
74
        parent::__construct();
75
        $this->SetTitle('Documento Tributario Electrónico (DTE) de Chile by LibreDTE');
76
        $this->papelContinuo = $papelContinuo === true ? 80 : $papelContinuo;
0 ignored issues
show
Documentation Bug introduced by
It seems like $papelContinuo === true ? 80 : $papelContinuo can also be of type integer. However, the property $papelContinuo is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
77
    }
78
79
    /**
80
     * Método que asigna la ubicación del logo de la empresa
81
     * @param logo URI del logo (puede ser local o en una URL)
82
     * @param posicion Posición respecto a datos del emisor (=0 izq, =1 arriba). Nota: parámetro válido sólo para formato hoja carta
83
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
84
     * @version 2016-08-04
85
     */
86
    public function setLogo($logo, $posicion = 0)
87
    {
88
        $this->logo = [
89
            'uri' => $logo,
90
            'posicion' => (int)$posicion,
91
        ];
92
    }
93
94
    /**
95
     * Método que asigna la posición del detalle del Item respecto al nombre
96
     * Nota: método válido sólo para formato hoja carta
97
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
98
     * @version 2016-08-05
99
     */
100
    public function setPosicionDetalleItem($posicion)
101
    {
102
        $this->item_detalle_posicion = (int)$posicion;
103
    }
104
105
    /**
106
     * Método que asigna el tamaño de la fuente para el detalle
107
     * Nota: método válido sólo para formato hoja carta
108
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
109
     * @version 2016-08-03
110
     */
111
    public function setFuenteDetalle($fuente)
112
    {
113
        $this->detalle_fuente = (int)$fuente;
114
    }
115
116
    /**
117
     * Método que asigna el ancho e las columnas del detalle desde un arreglo
118
     * Nota: método válido sólo para formato hoja carta
119
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
120
     * @version 2016-08-03
121
     */
122
    public function setAnchoColumnasDetalle(array $anchos)
123
    {
124
        foreach ($anchos as $col => $ancho) {
125
            if (isset($this->detalle_cols[$col]) and $ancho) {
126
                $this->detalle_cols[$col]['width'] = (int)$ancho;
127
            }
128
        }
129
    }
130
131
    /**
132
     * Método que asigna si el tumbre va al pie (por defecto) o va pegado al detalle
133
     * Nota: método válido sólo para formato hoja carta
134
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
135
     * @version 2017-10-05
136
     */
137
    public function setTimbrePie($timbre_pie = true)
138
    {
139
        $this->timbre_pie = (bool)$timbre_pie;
140
    }
141
142
    /**
143
     * Método que agrega un documento tributario, ya sea en formato de una
144
     * página o papel contínuo según se haya indicado en el constructor
145
     * @param dte Arreglo con los datos del XML (tag Documento)
146
     * @param timbre String XML con el tag TED del DTE
147
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
148
     * @version 2019-10-06
149
     */
150
    public function agregar(array $dte, $timbre = null)
151
    {
152
        $this->dte = $dte['Encabezado']['IdDoc']['TipoDTE'];
153
        $papel_tipo = (int)$this->papelContinuo;
154
        $method = 'agregar_papel_'.$papel_tipo;
155
        if (!method_exists($this, $method)) {
156
            $tipo = !empty(self::$papel[$papel_tipo]) ? self::$papel[$papel_tipo] : $papel_tipo;
157
            throw new \Exception('Papel de tipo "'.$tipo.'" no está disponible');
158
        }
159
        $this->$method($dte, $timbre);
160
    }
161
162
    /**
163
     * Método que agrega una página con el documento tributario
164
     * @param dte Arreglo con los datos del XML (tag Documento)
165
     * @param timbre String XML con el tag TED del DTE
166
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
167
     * @version 2017-11-07
168
     */
169
    private function agregar_papel_0(array $dte, $timbre)
170
    {
171
        // agregar página para la factura
172
        $this->AddPage();
173
        // agregar cabecera del documento
174
        $y[] = $this->agregarEmisor($dte['Encabezado']['Emisor']);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$y was never initialized. Although not strictly required by PHP, it is generally a good practice to add $y = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
175
        $y[] = $this->agregarFolio(
176
            $dte['Encabezado']['Emisor']['RUTEmisor'],
177
            $dte['Encabezado']['IdDoc']['TipoDTE'],
178
            $dte['Encabezado']['IdDoc']['Folio'],
179
            !empty($dte['Encabezado']['Emisor']['CmnaOrigen']) ? $dte['Encabezado']['Emisor']['CmnaOrigen'] : null
180
        );
181
        $this->setY(max($y));
182
        $this->Ln();
183
        // datos del documento
184
        $y = [];
185
        $y[] = $this->agregarDatosEmision($dte['Encabezado']['IdDoc'], !empty($dte['Encabezado']['Emisor']['CdgVendedor'])?$dte['Encabezado']['Emisor']['CdgVendedor']:null);
186
        $y[] = $this->agregarReceptor($dte['Encabezado']);
187
        $this->setY(max($y));
188
        $this->agregarTraslado(
189
            !empty($dte['Encabezado']['IdDoc']['IndTraslado']) ? $dte['Encabezado']['IdDoc']['IndTraslado'] : null,
190
            !empty($dte['Encabezado']['Transporte']) ? $dte['Encabezado']['Transporte'] : null
191
        );
192
        if (!empty($dte['Referencia'])) {
193
            $this->agregarReferencia($dte['Referencia']);
194
        }
195
        $this->agregarDetalle($dte['Detalle']);
196
        if (!empty($dte['DscRcgGlobal'])) {
197
            $this->agregarSubTotal($dte['Detalle']);
198
            $this->agregarDescuentosRecargos($dte['DscRcgGlobal']);
199
        }
200 View Code Duplication
        if (!empty($dte['Encabezado']['IdDoc']['MntPagos'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
            $this->agregarPagos($dte['Encabezado']['IdDoc']['MntPagos']);
202
        }
203
        // agregar observaciones
204
        $this->x_fin_datos = $this->getY();
205
        $this->agregarObservacion($dte['Encabezado']['IdDoc']);
206
        if (!$this->timbre_pie) {
207
            $this->Ln();
208
        }
209
        $this->x_fin_datos = $this->getY();
210
        $this->agregarTotales($dte['Encabezado']['Totales'], !empty($dte['Encabezado']['OtraMoneda']) ? $dte['Encabezado']['OtraMoneda'] : null);
211
        // agregar timbre
212
        $this->agregarTimbre($timbre);
213
        // agregar acuse de recibo y leyenda cedible
214
        if ($this->cedible and !in_array($dte['Encabezado']['IdDoc']['TipoDTE'], $this->sinAcuseRecibo)) {
215
            $this->agregarAcuseRecibo();
216
            $this->agregarLeyendaDestino($dte['Encabezado']['IdDoc']['TipoDTE']);
217
        }
218
    }
219
220
    /**
221
     * Método que agrega una página con el documento tributario
222
     * @param dte Arreglo con los datos del XML (tag Documento)
223
     * @param timbre String XML con el tag TED del DTE
224
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
225
     * @version 2019-08-05
226
     */
227
    private function agregar_papel_57(array $dte, $timbre, $height = 0)
228
    {
229
        $width = 57;
230
        // determinar alto de la página y agregarla
231
        $this->AddPage('P', [$height ? $height : $this->papel_continuo_alto, $width]);
232
        $x = 1;
233
        $y = 5;
234
        $this->SetXY($x,$y);
235
        // agregar datos del documento
236
        $this->setFont('', '', 8);
237
        $this->MultiTexto(!empty($dte['Encabezado']['Emisor']['RznSoc']) ? $dte['Encabezado']['Emisor']['RznSoc'] : $dte['Encabezado']['Emisor']['RznSocEmisor'], $x, null, '', $width-2);
238
        $this->MultiTexto($dte['Encabezado']['Emisor']['RUTEmisor'], $x, null, '', $width-2);
239
        $this->MultiTexto('Giro: '.(!empty($dte['Encabezado']['Emisor']['GiroEmis']) ? $dte['Encabezado']['Emisor']['GiroEmis'] : $dte['Encabezado']['Emisor']['GiroEmisor']), $x, null, '', $width-2);
240
        $this->MultiTexto($dte['Encabezado']['Emisor']['DirOrigen'].', '.$dte['Encabezado']['Emisor']['CmnaOrigen'], $x, null, '', $width-2);
241
        if (!empty($dte['Encabezado']['Emisor']['Sucursal'])) {
242
            $this->MultiTexto('Sucursal: '.$dte['Encabezado']['Emisor']['Sucursal'], $x, null, '', $width-2);
243
        }
244
        if (!empty($this->casa_matriz)) {
245
            $this->MultiTexto('Casa matriz: '.$this->casa_matriz, $x, null, '', $width-2);
246
        }
247
        $this->MultiTexto($this->getTipo($dte['Encabezado']['IdDoc']['TipoDTE'], $dte['Encabezado']['IdDoc']['Folio']).' N° '.$dte['Encabezado']['IdDoc']['Folio'], $x, null, '', $width-2);
248
        $this->MultiTexto('Fecha: '.date('d/m/Y', strtotime($dte['Encabezado']['IdDoc']['FchEmis'])), $x, null, '', $width-2);
249
        // si no es boleta no nominativa se agregan datos receptor
250
        if ($dte['Encabezado']['Receptor']['RUTRecep']!='66666666-6') {
251
            $this->Ln();
252
            $this->MultiTexto('Receptor: '.$dte['Encabezado']['Receptor']['RUTRecep'], $x, null, '', $width-2);
253
            $this->MultiTexto($dte['Encabezado']['Receptor']['RznSocRecep'], $x, null, '', $width-2);
254
            if (!empty($dte['Encabezado']['Receptor']['GiroRecep'])) {
255
                $this->MultiTexto('Giro: '.$dte['Encabezado']['Receptor']['GiroRecep'], $x, null, '', $width-2);
256
            }
257
            if (!empty($dte['Encabezado']['Receptor']['DirRecep'])) {
258
                $this->MultiTexto($dte['Encabezado']['Receptor']['DirRecep'].', '.$dte['Encabezado']['Receptor']['CmnaRecep'], $x, null, '', $width-2);
259
            }
260
        }
261
        $this->Ln();
262
        // hay un sólo detalle
263
        if (!isset($dte['Detalle'][0])) {
264
            $this->MultiTexto($dte['Detalle']['NmbItem'].': $'.$this->num($dte['Detalle']['MontoItem']), $x, null, '', $width-2);
265
        }
266
        // hay más de un detalle
267
        else {
268
            foreach ($dte['Detalle'] as $d) {
269
                $this->MultiTexto($d['NmbItem'].': $'.$this->num($d['MontoItem']), $x, null, '', $width-2);
270
            }
271
            if (in_array($dte['Encabezado']['IdDoc']['TipoDTE'], [39, 41])) {
272
                $this->MultiTexto('TOTAL: $'.$this->num($dte['Encabezado']['Totales']['MntTotal']), $x, null, '', $width-2);
273
            }
274
        }
275
        // si no es boleta se coloca EXENTO, NETO, IVA y TOTAL si corresponde
276
        if (!in_array($dte['Encabezado']['IdDoc']['TipoDTE'], [39, 41])) {
277 View Code Duplication
            if (!empty($dte['Encabezado']['Totales']['MntExe'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
278
                $this->MultiTexto('EXENTO: $'.$this->num($dte['Encabezado']['Totales']['MntExe']), $x, null, '', $width-2);
279
            }
280 View Code Duplication
            if (!empty($dte['Encabezado']['Totales']['MntNeto'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
281
                $this->MultiTexto('NETO: $'.$this->num($dte['Encabezado']['Totales']['MntNeto']), $x, null, '', $width-2);
282
            }
283 View Code Duplication
            if (!empty($dte['Encabezado']['Totales']['IVA'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
284
                $this->MultiTexto('IVA: $'.$this->num($dte['Encabezado']['Totales']['IVA']), $x, null, '', $width-2);
285
            }
286
            $this->MultiTexto('TOTAL: $'.$this->num($dte['Encabezado']['Totales']['MntTotal']), $x, null, '', $width-2);
287
        }
288
        // agregar acuse de recibo y leyenda cedible
289 View Code Duplication
        if ($this->cedible and !in_array($dte['Encabezado']['IdDoc']['TipoDTE'], $this->sinAcuseRecibo)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
290
            $this->agregarAcuseReciboContinuo(-1, $this->y+6, $width+2, 34);
291
            $this->agregarLeyendaDestinoContinuo($dte['Encabezado']['IdDoc']['TipoDTE']);
292
        }
293
        // agregar timbre
294
        if (!empty($dte['Encabezado']['IdDoc']['TermPagoGlosa'])) {
295
            $this->Ln();
296
            $this->MultiTexto('Observación: '.$dte['Encabezado']['IdDoc']['TermPagoGlosa']."\n\n", $x);
297
        }
298
        $this->agregarTimbre($timbre, -11, $x, $this->GetY()+6, 55, 6);
299
        // si el alto no se pasó, entonces es con autocálculo, se elimina esta página y se pasa el alto
300
        // que se logró determinar para crear la página con el alto correcto
301
        if (!$height) {
302
            $this->deletePage($this->PageNo());
303
            $this->agregar_papel_57($dte, $timbre, $this->getY()+30);
304
        }
305
    }
306
307
    /**
308
     * Método que agrega una página con el documento tributario en papel
309
     * contínuo de 75mm
310
     * @param dte Arreglo con los datos del XML (tag Documento)
311
     * @param timbre String XML con el tag TED del DTE
312
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
313
     * @version 2019-10-06
314
     */
315
    private function agregar_papel_75(array $dte, $timbre)
316
    {
317
        $this->agregar_papel_80($dte, $timbre, 75);
318
    }
319
320
    /**
321
     * Método que agrega una página con el documento tributario en papel
322
     * contínuo de 80mm
323
     * @param dte Arreglo con los datos del XML (tag Documento)
324
     * @param timbre String XML con el tag TED del DTE
325
     * @param width Ancho del papel contínuo en mm (es parámetro porque se usa el mismo método para 75mm)
326
     * @author Pablo Reyes (https://github.com/pabloxp)
327
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
328
     * @version 2019-10-06
329
     */
330
    private function agregar_papel_80(array $dte, $timbre, $width = 80, $height = 0)
331
    {
332
        // si hay logo asignado se usa centrado
333
        if (!empty($this->logo)) {
334
            $this->logo['posicion'] = 'C';
335
        }
336
        // determinar alto de la página y agregarla
337
        $x_start = 1;
338
        $y_start = 1;
339
        $offset = 14;
340
        // determinar alto de la página y agregarla
341
        $this->AddPage('P', [$height ? $height : $this->papel_continuo_alto, $width]);
342
        // agregar cabecera del documento
343
        $y = $this->agregarFolio(
344
            $dte['Encabezado']['Emisor']['RUTEmisor'],
345
            $dte['Encabezado']['IdDoc']['TipoDTE'],
346
            $dte['Encabezado']['IdDoc']['Folio'],
347
            $dte['Encabezado']['Emisor']['CmnaOrigen'],
348
            $x_start, $y_start, $width-($x_start*4), 10,
349
            [0,0,0]
350
        );
351
        $y = $this->agregarEmisor($dte['Encabezado']['Emisor'], $x_start, $y+2, $width-($x_start*45), 8, 9, [0,0,0]);
352
        // datos del documento
353
        $this->SetY($y);
354
        $this->Ln();
355
        $this->setFont('', '', 8);
356
        $this->agregarDatosEmision($dte['Encabezado']['IdDoc'], !empty($dte['Encabezado']['Emisor']['CdgVendedor'])?$dte['Encabezado']['Emisor']['CdgVendedor']:null, $x_start, $offset, false);
357
        $this->agregarReceptor($dte['Encabezado'], $x_start, $offset);
358
        $this->agregarTraslado(
359
            !empty($dte['Encabezado']['IdDoc']['IndTraslado']) ? $dte['Encabezado']['IdDoc']['IndTraslado'] : null,
360
            !empty($dte['Encabezado']['Transporte']) ? $dte['Encabezado']['Transporte'] : null,
361
            $x_start, $offset
362
        );
363
        if (!empty($dte['Referencia'])) {
364
            $this->agregarReferencia($dte['Referencia'], $x_start, $offset);
365
        }
366
        $this->Ln();
367
        $this->agregarDetalleContinuo($dte['Detalle']);
368 View Code Duplication
        if (!empty($dte['DscRcgGlobal'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
369
            $this->Ln();
370
            $this->Ln();
371
            $this->agregarSubTotal($dte['Detalle'], $x_start);
372
            $this->agregarDescuentosRecargos($dte['DscRcgGlobal'], $x_start);
373
        }
374 View Code Duplication
        if (!empty($dte['Encabezado']['IdDoc']['MntPagos'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
375
            $this->Ln();
376
            $this->Ln();
377
            $this->agregarPagos($dte['Encabezado']['IdDoc']['MntPagos'], $x_start);
378
        }
379
        $this->agregarTotales($dte['Encabezado']['Totales'], !empty($dte['Encabezado']['OtraMoneda']) ? $dte['Encabezado']['OtraMoneda'] : null, $this->y+6, 23, 17);
380
        // agregar acuse de recibo y leyenda cedible
381 View Code Duplication
        if ($this->cedible and !in_array($dte['Encabezado']['IdDoc']['TipoDTE'], $this->sinAcuseRecibo)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
382
            $this->agregarAcuseReciboContinuo(3, $this->y+6, 68, 34);
383
            $this->agregarLeyendaDestinoContinuo($dte['Encabezado']['IdDoc']['TipoDTE']);
384
        }
385
        // agregar timbre
386
        $y = $this->agregarObservacion($dte['Encabezado']['IdDoc'], $x_start, $this->y+6);
387
        $this->agregarTimbre($timbre, -10, $x_start, $y+6, 70, 6);
388
        // si el alto no se pasó, entonces es con autocálculo, se elimina esta página y se pasa el alto
389
        // que se logró determinar para crear la página con el alto correcto
390
        if (!$height) {
391
            $this->deletePage($this->PageNo());
392
            $this->agregar_papel_80($dte, $timbre, $width, $this->getY()+30);
393
        }
394
    }
395
396
    /**
397
     * Método que agrega una página con el documento tributario en papel
398
     * contínuo de 110mm
399
     * @param dte Arreglo con los datos del XML (tag Documento)
400
     * @param timbre String XML con el tag TED del DTE
401
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
402
     * @version 2019-10-06
403
     */
404
    private function agregar_papel_110(array $dte, $timbre, $height = 0)
405
    {
406
        $width = 110;
407
        if (!empty($this->logo)) {
408
            $this->logo['posicion'] = 1;
409
        }
410
        // determinar alto de la página y agregarla
411
        $x_start = 1;
412
        $y_start = 1;
0 ignored issues
show
Unused Code introduced by
$y_start is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
413
        $offset = 14;
414
        // determinar alto de la página y agregarla
415
        $this->AddPage('P', [$height ? $height : $this->papel_continuo_alto, $width]);
416
        // agregar cabecera del documento
417
        $y[] = $this->agregarEmisor($dte['Encabezado']['Emisor'], 1, 2, 20, 30, 9, [0,0,0]);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$y was never initialized. Although not strictly required by PHP, it is generally a good practice to add $y = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
418
        $y[] = $this->agregarFolio(
419
            $dte['Encabezado']['Emisor']['RUTEmisor'],
420
            $dte['Encabezado']['IdDoc']['TipoDTE'],
421
            $dte['Encabezado']['IdDoc']['Folio'],
422
            !empty($dte['Encabezado']['Emisor']['CmnaOrigen']) ? $dte['Encabezado']['Emisor']['CmnaOrigen'] : null,
423
            63,
424
            2,
425
            45,
426
            9,
427
            [0,0,0]
428
        );
429
        $this->SetY(max($y));
430
        $this->Ln();
431
        // datos del documento
432
        $this->setFont('', '', 8);
433
        $this->agregarDatosEmision($dte['Encabezado']['IdDoc'], !empty($dte['Encabezado']['Emisor']['CdgVendedor'])?$dte['Encabezado']['Emisor']['CdgVendedor']:null, $x_start, $offset, false);
434
        $this->agregarReceptor($dte['Encabezado'], $x_start, $offset);
435
        $this->agregarTraslado(
436
            !empty($dte['Encabezado']['IdDoc']['IndTraslado']) ? $dte['Encabezado']['IdDoc']['IndTraslado'] : null,
437
            !empty($dte['Encabezado']['Transporte']) ? $dte['Encabezado']['Transporte'] : null,
438
            $x_start, $offset
439
        );
440
        if (!empty($dte['Referencia'])) {
441
            $this->agregarReferencia($dte['Referencia'], $x_start, $offset);
442
        }
443
        $this->Ln();
444
        $this->agregarDetalleContinuo($dte['Detalle'], 3, [1, 53, 73, 83], true);
445 View Code Duplication
        if (!empty($dte['DscRcgGlobal'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
446
            $this->Ln();
447
            $this->Ln();
448
            $this->agregarSubTotal($dte['Detalle'], $x_start);
449
            $this->agregarDescuentosRecargos($dte['DscRcgGlobal'], $x_start);
450
        }
451 View Code Duplication
        if (!empty($dte['Encabezado']['IdDoc']['MntPagos'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
452
            $this->Ln();
453
            $this->Ln();
454
            $this->agregarPagos($dte['Encabezado']['IdDoc']['MntPagos'], $x_start);
455
        }
456
        $this->agregarTotales($dte['Encabezado']['Totales'], !empty($dte['Encabezado']['OtraMoneda']) ? $dte['Encabezado']['OtraMoneda'] : null, $this->y+6, 61, 17);
457
        // agregar observaciones
458
        $y = $this->agregarObservacion($dte['Encabezado']['IdDoc'], $x_start, $this->y+6);
459
        // agregar timbre
460
        $this->agregarTimbre($timbre, 2, 2, $y+6, 60, 6, 'S');
461
        // agregar acuse de recibo y leyenda cedible
462
        if ($this->cedible and !in_array($dte['Encabezado']['IdDoc']['TipoDTE'], $this->sinAcuseRecibo)) {
463
            $this->agregarAcuseRecibo(63, $y+6, 45, 40, 15);
464
            $this->setFont('', 'B', 8);
465
            $this->Texto('CEDIBLE'.($dte['Encabezado']['IdDoc']['TipoDTE']==52?' CON SU FACTURA':''), $x_start, $this->y+1, 'L');
466
        }
467
        // si el alto no se pasó, entonces es con autocálculo, se elimina esta página y se pasa el alto
468
        // que se logró determinar para crear la página con el alto correcto
469
        if (!$height) {
470
            $this->deletePage($this->PageNo());
471
            $this->agregar_papel_110($dte, $timbre, $this->getY()+30);
472
        }
473
    }
474
475
    /**
476
     * Método que agrega los datos de la empresa
477
     * Orden de los datos:
478
     *  - Razón social del emisor
479
     *  - Giro del emisor (sin abreviar)
480
     *  - Dirección casa central del emisor
481
     *  - Dirección sucursales
482
     * @param emisor Arreglo con los datos del emisor (tag Emisor del XML)
483
     * @param x Posición horizontal de inicio en el PDF
484
     * @param y Posición vertical de inicio en el PDF
485
     * @param w Ancho de la información del emisor
486
     * @param w_img Ancho máximo de la imagen
487
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
488
     * @version 2019-10-06
489
     */
490
    protected function agregarEmisor(array $emisor, $x = 10, $y = 15, $w = 75, $w_img = 30, $font_size = null, array $color = null)
491
    {
492
        // logo del documento
493
        if (isset($this->logo)) {
494
            if (!empty($this->logo['posicion']) and $this->logo['posicion'] == 'C') {
495
                $logo_w = null;
496
                $logo_y = null;
497
                $logo_position = 'C';
498
                $logo_next_pointer = 'N';
499
            } else {
500
                $logo_w = !$this->logo['posicion'] ? $w_img : null;
501
                $logo_y = $this->logo['posicion'] ? $w_img/2 : null;
502
                $logo_position = '';
503
                $logo_next_pointer = 'T';
504
            }
505
            $this->Image(
506
                $this->logo['uri'],
507
                $x,
508
                $y,
509
                $logo_w,
510
                $logo_y,
511
                'PNG',
512
                (isset($emisor['url'])?$emisor['url']:''),
513
                $logo_next_pointer,
514
                2,
515
                300,
516
                $logo_position
517
            );
518
            if (!empty($this->logo['posicion']) and $this->logo['posicion'] == 'C') {
519
                $w += 40;
520
            } else {
521
                if ($this->logo['posicion']) {
522
                    $this->SetY($this->y + ($w_img/2));
523
                    $w += 40;
524
                } else {
525
                    $x = $this->x+3;
526
                }
527
            }
528
        } else {
529
            $this->y = $y-2;
530
            $w += 40;
531
        }
532
        // agregar datos del emisor
533
        $this->setFont('', 'B', $font_size ? $font_size : 14);
534
        $this->SetTextColorArray($color===null?[32, 92, 144]:$color);
535
        $this->MultiTexto(!empty($emisor['RznSoc']) ? $emisor['RznSoc'] : $emisor['RznSocEmisor'], $x, $this->y+2, 'L', $w);
536
        $this->setFont('', 'B', $font_size ? $font_size : 9);
537
        $this->SetTextColorArray([0,0,0]);
538
        $this->MultiTexto(!empty($emisor['GiroEmis']) ? $emisor['GiroEmis'] : $emisor['GiroEmisor'], $x, $this->y, 'L', $w);
539
        $comuna = !empty($emisor['CmnaOrigen']) ? $emisor['CmnaOrigen'] : null;
540
        $ciudad = !empty($emisor['CiudadOrigen']) ? $emisor['CiudadOrigen'] : \sasco\LibreDTE\Chile::getCiudad($comuna);
541
        $this->MultiTexto($emisor['DirOrigen'].($comuna?(', '.$comuna):'').($ciudad?(', '.$ciudad):''), $x, $this->y, 'L', $w);
542
        if (!empty($emisor['Sucursal'])) {
543
            $this->MultiTexto('Sucursal: '.$emisor['Sucursal'], $x, $this->y, 'L', $w);
544
        }
545
        if (!empty($this->casa_matriz)) {
546
            $this->MultiTexto('Casa matriz: '.$this->casa_matriz, $x, $this->y, 'L', $w);
547
        }
548
        $contacto = [];
549
        if (!empty($emisor['Telefono'])) {
550
            if (!is_array($emisor['Telefono']))
551
                $emisor['Telefono'] = [$emisor['Telefono']];
552
            foreach ($emisor['Telefono'] as $t)
553
                $contacto[] = $t;
554
        }
555
        if (!empty($emisor['CorreoEmisor'])) {
556
            $contacto[] = $emisor['CorreoEmisor'];
557
        }
558
        if ($contacto) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $contacto of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
559
            $this->MultiTexto(implode(' / ', $contacto), $x, $this->y, 'L', $w);
560
        }
561
        return $this->y;
562
    }
563
564
    /**
565
     * Método que agrega el recuadro con el folio
566
     * Recuadro:
567
     *  - Tamaño mínimo 1.5x5.5 cms
568
     *  - En lado derecho (negro o rojo)
569
     *  - Enmarcado por una línea de entre 0.5 y 1 mm de espesor
570
     *  - Tamaño máximo 4x8 cms
571
     *  - Letras tamaño 10 o superior en mayúsculas y negritas
572
     *  - Datos del recuadro: RUT emisor, nombre de documento en 2 líneas,
573
     *    folio.
574
     *  - Bajo el recuadro indicar la Dirección regional o Unidad del SII a la
575
     *    que pertenece el emisor
576
     * @param rut RUT del emisor
577
     * @param tipo Código o glosa del tipo de documento
578
     * @param sucursal_sii Código o glosa de la sucursal del SII del Emisor
579
     * @param x Posición horizontal de inicio en el PDF
580
     * @param y Posición vertical de inicio en el PDF
581
     * @param w Ancho de la información del emisor
582
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
583
     * @version 2019-08-05
584
     */
585
    protected function agregarFolio($rut, $tipo, $folio, $sucursal_sii = null, $x = 130, $y = 15, $w = 70, $font_size = null, array $color = null)
586
    {
587
        if ($color===null) {
588
            $color = $tipo ? ($tipo==52 ? [0,172,140] : [255,0,0]) : [0,0,0];
589
        }
590
        $this->SetTextColorArray($color);
591
        // colocar rut emisor, glosa documento y folio
592
        list($rut, $dv) = explode('-', $rut);
593
        $this->setFont ('', 'B', $font_size ? $font_size : 15);
594
        $this->MultiTexto('R.U.T.: '.$this->num($rut).'-'.$dv, $x, $y+4, 'C', $w);
595
        $this->setFont('', 'B', $font_size ? $font_size : 12);
596
        $this->MultiTexto($this->getTipo($tipo, $folio), $x, null, 'C', $w);
597
        $this->setFont('', 'B', $font_size ? $font_size : 15);
598
        $this->MultiTexto('N° '.$folio, $x, null, 'C', $w);
599
        // dibujar rectángulo rojo
600
        $this->Rect($x, $y, $w, round($this->getY()-$y+3), 'D', ['all' => ['width' => 0.5, 'color' => $color]]);
601
        // colocar unidad del SII
602
        $this->setFont('', 'B', $font_size ? $font_size : 10);
603
        if ($tipo) {
604
            $this->Texto('S.I.I. - '.\sasco\LibreDTE\Sii::getDireccionRegional($sucursal_sii), $x, $this->getY()+4, 'C', $w);
0 ignored issues
show
Bug introduced by
It seems like $sucursal_sii defined by parameter $sucursal_sii on line 585 can also be of type null; however, sasco\LibreDTE\Sii::getDireccionRegional() does only seem to accept object<sasco\LibreDTE\de>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
605
        }
606
        $this->SetTextColorArray([0,0,0]);
607
        $this->Ln();
608
        return $this->y;
609
    }
610
611
    /**
612
     * Método que agrega los datos de la emisión del DTE que no son los dato del
613
     * receptor
614
     * @param IdDoc Información general del documento
615
     * @param x Posición horizontal de inicio en el PDF
616
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
617
     * @version 2017-06-15
618
     */
619
    protected function agregarDatosEmision($IdDoc, $CdgVendedor, $x = 10, $offset = 22, $mostrar_dia = true)
620
    {
621
        // si es hoja carta
622
        if ($x==10) {
623
            $y = $this->GetY();
624
            // fecha emisión
625
            $this->setFont('', 'B', null);
626
            $this->MultiTexto($this->date($IdDoc['FchEmis'], $mostrar_dia), $x, null, 'R');
627
            $this->setFont('', '', null);
628
            // período facturación
629
            if (!empty($IdDoc['PeriodoDesde']) and !empty($IdDoc['PeriodoHasta'])) {
630
                $this->MultiTexto('Período del '.date('d/m/y', strtotime($IdDoc['PeriodoDesde'])).' al '.date('d/m/y', strtotime($IdDoc['PeriodoHasta'])), $x, null, 'R');
631
            }
632
            // pago anticicado
633 View Code Duplication
            if (!empty($IdDoc['FchCancel'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
634
                $this->MultiTexto('Pagado el '.$this->date($IdDoc['FchCancel'], false), $x, null, 'R');
635
            }
636
            // fecha vencimiento
637 View Code Duplication
            if (!empty($IdDoc['FchVenc'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
638
                $this->MultiTexto('Vence el '.$this->date($IdDoc['FchVenc'], false), $x, null, 'R');
639
            }
640
            // forma de pago nacional
641 View Code Duplication
            if (!empty($IdDoc['FmaPago'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
642
                $this->MultiTexto('Venta: '.strtolower($this->formas_pago[$IdDoc['FmaPago']]), $x, null, 'R');
643
            }
644
            // forma de pago exportación
645 View Code Duplication
            if (!empty($IdDoc['FmaPagExp'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
646
                $this->MultiTexto('Venta: '.strtolower($this->formas_pago_exportacion[$IdDoc['FmaPagExp']]), $x, null, 'R');
647
            }
648
            // vendedor
649
            if (!empty($CdgVendedor)) {
650
                $this->MultiTexto('Vendedor: '.$CdgVendedor, $x, null, 'R');
651
            }
652
            $y_end = $this->GetY();
653
            $this->SetY($y);
654
        }
655
        // papel contínuo
656
        else {
657
            // fecha de emisión
658
            $this->setFont('', 'B', null);
659
            $this->Texto('Emisión', $x);
660
            $this->Texto(':', $x+$offset);
661
            $this->setFont('', '', null);
662
            $this->MultiTexto($this->date($IdDoc['FchEmis'], $mostrar_dia), $x+$offset+2);
663
            // forma de pago nacional
664
            if (!empty($IdDoc['FmaPago'])) {
665
                $this->setFont('', 'B', null);
666
                $this->Texto('Venta', $x);
667
                $this->Texto(':', $x+$offset);
668
                $this->setFont('', '', null);
669
                $this->MultiTexto($this->formas_pago[$IdDoc['FmaPago']], $x+$offset+2);
670
            }
671
            // forma de pago exportación
672
            if (!empty($IdDoc['FmaPagExp'])) {
673
                $this->setFont('', 'B', null);
674
                $this->Texto('Venta', $x);
675
                $this->Texto(':', $x+$offset);
676
                $this->setFont('', '', null);
677
                $this->MultiTexto($this->formas_pago_exportacion[$IdDoc['FmaPagExp']], $x+$offset+2);
678
            }
679
            // pago anticicado
680
            if (!empty($IdDoc['FchCancel'])) {
681
                $this->setFont('', 'B', null);
682
                $this->Texto('Pagado el', $x);
683
                $this->Texto(':', $x+$offset);
684
                $this->setFont('', '', null);
685
                $this->MultiTexto($this->date($IdDoc['FchCancel'], $mostrar_dia), $x+$offset+2);
686
            }
687
            // fecha vencimiento
688
            if (!empty($IdDoc['FchVenc'])) {
689
                $this->setFont('', 'B', null);
690
                $this->Texto('Vence el', $x);
691
                $this->Texto(':', $x+$offset);
692
                $this->setFont('', '', null);
693
                $this->MultiTexto($this->date($IdDoc['FchVenc'], $mostrar_dia), $x+$offset+2);
694
            }
695
            $y_end = $this->GetY();
696
        }
697
        return $y_end;
698
    }
699
700
    /**
701
     * Método que agrega los datos del receptor
702
     * @param receptor Arreglo con los datos del receptor (tag Receptor del XML)
703
     * @param x Posición horizontal de inicio en el PDF
704
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
705
     * @version 2019-10-06
706
     */
707
    protected function agregarReceptor(array $Encabezado, $x = 10, $offset = 22)
708
    {
709
        $receptor = $Encabezado['Receptor'];
710
        if (!empty($receptor['RUTRecep']) and $receptor['RUTRecep']!='66666666-6') {
711
            list($rut, $dv) = explode('-', $receptor['RUTRecep']);
712
            $this->setFont('', 'B', null);
713
            $this->Texto(in_array($this->dte, [39, 41]) ? 'R.U.N.' : 'R.U.T.', $x);
714
            $this->Texto(':', $x+$offset);
715
            $this->setFont('', '', null);
716
            $this->MultiTexto($this->num($rut).'-'.$dv, $x+$offset+2);
717
        }
718
        if (!empty($receptor['RznSocRecep'])) {
719
            $this->setFont('', 'B', null);
720
            $this->Texto(in_array($this->dte, [39, 41]) ? 'Nombre' : ($x==10?'Razón social':'Razón soc.'), $x);
721
            $this->Texto(':', $x+$offset);
722
            $this->setFont('', '', null);
723
            $this->MultiTexto($receptor['RznSocRecep'], $x+$offset+2, null, '', $x==10?105:0);
724
        }
725 View Code Duplication
        if (!empty($receptor['GiroRecep'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
726
            $this->setFont('', 'B', null);
727
            $this->Texto('Giro', $x);
728
            $this->Texto(':', $x+$offset);
729
            $this->setFont('', '', null);
730
            $this->MultiTexto($receptor['GiroRecep'], $x+$offset+2);
731
        }
732
        if (!empty($receptor['DirRecep'])) {
733
            $this->setFont('', 'B', null);
734
            $this->Texto('Dirección', $x);
735
            $this->Texto(':', $x+$offset);
736
            $this->setFont('', '', null);
737
            $ciudad = !empty($receptor['CiudadRecep']) ? $receptor['CiudadRecep'] : (
738
                !empty($receptor['CmnaRecep']) ? \sasco\LibreDTE\Chile::getCiudad($receptor['CmnaRecep']) : ''
739
            );
740
            $this->MultiTexto($receptor['DirRecep'].(!empty($receptor['CmnaRecep'])?(', '.$receptor['CmnaRecep']):'').($ciudad?(', '.$ciudad):''), $x+$offset+2);
741
        }
742
        if (!empty($receptor['Extranjero']['Nacionalidad'])) {
743
            $this->setFont('', 'B', null);
744
            $this->Texto('Nacionalidad', $x);
745
            $this->Texto(':', $x+$offset);
746
            $this->setFont('', '', null);
747
            $this->MultiTexto(\sasco\LibreDTE\Sii\Aduana::getNacionalidad($receptor['Extranjero']['Nacionalidad']), $x+$offset+2);
748
        }
749
        if (!empty($receptor['Extranjero']['NumId'])) {
750
            $this->setFont('', 'B', null);
751
            $this->Texto('N° ID extranj.', $x);
752
            $this->Texto(':', $x+$offset);
753
            $this->setFont('', '', null);
754
            $this->MultiTexto($receptor['Extranjero']['NumId'], $x+$offset+2);
755
        }
756
        $contacto = [];
757
        if (!empty($receptor['Contacto']))
758
            $contacto[] = $receptor['Contacto'];
759
        if (!empty($receptor['CorreoRecep']))
760
            $contacto[] = $receptor['CorreoRecep'];
761 View Code Duplication
        if (!empty($contacto)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
762
            $this->setFont('', 'B', null);
763
            $this->Texto('Contacto', $x);
764
            $this->Texto(':', $x+$offset);
765
            $this->setFont('', '', null);
766
            $this->MultiTexto(implode(' / ', $contacto), $x+$offset+2);
767
        }
768
        if (!empty($Encabezado['RUTSolicita'])) {
769
            list($rut, $dv) = explode('-', $Encabezado['RUTSolicita']);
770
            $this->setFont('', 'B', null);
771
            $this->Texto('RUT solicita', $x);
772
            $this->Texto(':', $x+$offset);
773
            $this->setFont('', '', null);
774
            $this->MultiTexto($this->num($rut).'-'.$dv, $x+$offset+2);
775
        }
776
        if (!empty($receptor['CdgIntRecep'])) {
777
            $this->setFont('', 'B', null);
778
            $this->Texto('Cód. recep.', $x);
779
            $this->Texto(':', $x+$offset);
780
            $this->setFont('', '', null);
781
            $this->MultiTexto($receptor['CdgIntRecep'], $x+$offset+2, null, '', $x==10?105:0);
782
        }
783
        return $this->GetY();
784
    }
785
786
    /**
787
     * Método que agrega los datos del traslado
788
     * @param IndTraslado
789
     * @param Transporte
790
     * @param x Posición horizontal de inicio en el PDF
791
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
792
     * @version 2016-08-03
793
     */
794
    protected function agregarTraslado($IndTraslado, array $Transporte = null, $x = 10, $offset = 22)
795
    {
796
        // agregar tipo de traslado
797 View Code Duplication
        if ($IndTraslado) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
798
            $this->setFont('', 'B', null);
799
            $this->Texto('Tipo oper.', $x);
800
            $this->Texto(':', $x+$offset);
801
            $this->setFont('', '', null);
802
            $this->MultiTexto($this->traslados[$IndTraslado], $x+$offset+2);
803
        }
804
        // agregar información de transporte
805
        if ($Transporte) {
806
            $transporte = '';
807
            if (!empty($Transporte['DirDest']) and !empty($Transporte['CmnaDest'])) {
808
                $transporte .= 'a '.$Transporte['DirDest'].', '.$Transporte['CmnaDest'];
809
            }
810
            if (!empty($Transporte['RUTTrans']))
811
                $transporte .= ' por '.$Transporte['RUTTrans'];
812
            if (!empty($Transporte['Patente']))
813
                $transporte .= ' en vehículo '.$Transporte['Patente'];
814
            if (isset($Transporte['Chofer']) and is_array($Transporte['Chofer'])) {
815 View Code Duplication
                if (!empty($Transporte['Chofer']['NombreChofer'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
816
                    $transporte .= ' con chofer '.$Transporte['Chofer']['NombreChofer'];
817
                }
818 View Code Duplication
                if (!empty($Transporte['Chofer']['RUTChofer'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
819
                    $transporte .= ' ('.$Transporte['Chofer']['RUTChofer'].')';
820
                }
821
            }
822 View Code Duplication
            if ($transporte) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
823
                $this->setFont('', 'B', null);
824
                $this->Texto('Traslado', $x);
825
                $this->Texto(':', $x+$offset);
826
                $this->setFont('', '', null);
827
                $this->MultiTexto(ucfirst(trim($transporte)), $x+$offset+2);
828
            }
829
        }
830
        // agregar información de aduana
831
        if (!empty($Transporte['Aduana']) and is_array($Transporte['Aduana'])) {
832
            $col = 0;
833
            foreach ($Transporte['Aduana'] as $tag => $codigo) {
834
                if ($codigo===false) {
835
                    continue;
836
                }
837
                $glosa = \sasco\LibreDTE\Sii\Aduana::getGlosa($tag);
838
                $valor = \sasco\LibreDTE\Sii\Aduana::getValor($tag, $codigo);
839
                if ($glosa!==false and $valor!==false) {
840
                    if ($tag=='TipoBultos' and $col) {
841
                        $col = abs($col-110);
842
                        $this->Ln();
843
                    }
844
                    /*if (in_array($tag, ['CodClauVenta', 'CodViaTransp', 'CodPtoEmbarque', 'Tara', 'MntFlete', 'CodPaisRecep']) and $col) {
845
                        $col = 0;
846
		    }*/
847
                    $this->setFont('', 'B', null);
848
                    $this->Texto($glosa, $x+$col);
849
                    $this->Texto(':', $x+$offset+$col);
850
                    $this->setFont('', '', null);
851
                    $this->Texto($valor, $x+$offset+2+$col);
852
                    if ($tag=='TipoBultos') {
853
                        $col = abs($col-110);
854
                    }
855
                    if ($col) {
856
                        $this->Ln();
857
                    }
858
                    $col = abs($col-110);
859
                }
860
            }
861
            if ($col) {
862
                $this->Ln();
863
            }
864
        }
865
    }
866
867
    /**
868
     * Método que agrega las referencias del documento
869
     * @param referencias Arreglo con las referencias del documento (tag Referencia del XML)
870
     * @param x Posición horizontal de inicio en el PDF
871
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
872
     * @version 2017-09-25
873
     */
874
    protected function agregarReferencia($referencias, $x = 10, $offset = 22)
875
    {
876
        if (!isset($referencias[0]))
877
            $referencias = [$referencias];
878
        foreach($referencias as $r) {
879
            $texto = $r['NroLinRef'].' - ';
880
            if (!empty($r['TpoDocRef'])) {
881
                $texto .= $this->getTipo($r['TpoDocRef']).' ';
882
            }
883
            if (!empty($r['FolioRef'])) {
884
                if (is_numeric($r['FolioRef'])) {
885
                    $texto .= ' N° '.$r['FolioRef'].' ';
886
                } else {
887
                    $texto .= ' '.$r['FolioRef'].' ';
888
                }
889
            }
890
            if (!empty($r['FchRef'])) {
891
                $texto .= 'del '.date('d/m/Y', strtotime($r['FchRef']));
892
            }
893
            if (isset($r['RazonRef']) and $r['RazonRef']!==false) {
894
                $texto = $texto.': '.$r['RazonRef'];
895
            }
896
            $this->setFont('', 'B', null);
897
            $this->Texto('Referencia', $x);
898
            $this->Texto(':', $x+$offset);
899
            $this->setFont('', '', null);
900
            $this->MultiTexto($texto, $x+$offset+2);
901
        }
902
    }
903
904
    /**
905
     * Método que agrega el detalle del documento
906
     * @param detalle Arreglo con el detalle del documento (tag Detalle del XML)
907
     * @param x Posición horizontal de inicio en el PDF
908
     * @param y Posición vertical de inicio en el PDF
909
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
910
     * @version 2019-07-09
911
     */
912
    protected function agregarDetalle($detalle, $x = 10, $html = true)
913
    {
914
        if (!isset($detalle[0])) {
915
            $detalle = [$detalle];
916
        }
917
        $this->setFont('', '', $this->detalle_fuente);
918
        // titulos
919
        $titulos = [];
920
        $titulos_keys = array_keys($this->detalle_cols);
921
        foreach ($this->detalle_cols as $key => $info) {
922
            $titulos[$key] = $info['title'];
923
        }
924
        // normalizar cada detalle
925
        $dte_exento = in_array($this->dte, [34, 110, 111, 112]);
926
        foreach ($detalle as &$item) {
927
            // quitar columnas
928
            foreach ($item as $col => $valor) {
929
                if ($col=='DscItem' and !empty($item['DscItem'])) {
930
                    $item['NmbItem'] .= !$this->item_detalle_posicion ? ($html?'<br/>':"\n") : ': ';
931
                    if ($html) {
932
                        $item['NmbItem'] .= '<span style="font-size:0.7em">'.$item['DscItem'].'</span>';
933
                    } else {
934
                        $item['NmbItem'] .= $item['DscItem'];
935
                    }
936
                }
937
                if ($col=='Subcantidad' and !empty($item['Subcantidad'])) {
938
                    //$item['NmbItem'] .= $html ? '<br/>' : "\n";
939
                    if (!isset($item['Subcantidad'][0])) {
940
                        $item['Subcantidad'] = [$item['Subcantidad']];
941
                    }
942
                    foreach ($item['Subcantidad'] as $Subcantidad) {
943
                        if ($html) {
944
                            $item['NmbItem'] .= '<br/><span style="font-size:0.7em">  - Subcantidad: '.$Subcantidad['SubQty'].' '.$Subcantidad['SubCod'].'</span>';
945
                        } else {
946
                            $item['NmbItem'] .= "\n".'  - Subcantidad: '.$Subcantidad['SubQty'].' '.$Subcantidad['SubCod'];
947
                        }
948
                    }
949
                }
950
                if ($col=='UnmdRef' and !empty($item['UnmdRef']) and !empty($item['QtyRef'])) {
951
                    $item['QtyRef'] .= ' '.$item['UnmdRef'];
952
                }
953
                if ($col=='DescuentoPct' and !empty($item['DescuentoPct'])) {
954
                    $item['DescuentoMonto'] = $item['DescuentoPct'].'%';
955
                }
956
                if ($col=='RecargoPct' and !empty($item['RecargoPct'])) {
957
                    $item['RecargoMonto'] = $item['RecargoPct'].'%';
958
                }
959
                if (!in_array($col, $titulos_keys) or ($dte_exento and $col=='IndExe')) {
960
                    unset($item[$col]);
961
                }
962
            }
963
            // ajustes a IndExe
964
            if (isset($item['IndExe'])) {
965
                if ($item['IndExe']==1) {
966
                    $item['IndExe'] = 'EX';
967
                } else if ($item['IndExe']==2) {
968
                    $item['IndExe'] = 'NF';
969
                }
970
            }
971
            // agregar todas las columnas que se podrían imprimir en la tabla
972
            $item_default = [];
973
            foreach ($this->detalle_cols as $key => $info) {
974
                $item_default[$key] = false;
975
            }
976
            $item = array_merge($item_default, $item);
977
            // si hay código de item se extrae su valor
978
            if (!empty($item['CdgItem']['VlrCodigo'])){
979
                $item['CdgItem'] = $item['CdgItem']['VlrCodigo'];
980
            }
981
            // dar formato a números
982
            foreach (['QtyItem', 'PrcItem', 'DescuentoMonto', 'RecargoMonto', 'MontoItem'] as $col) {
983
                if ($item[$col]) {
984
                    $item[$col] = is_numeric($item[$col]) ? $this->num($item[$col]) : $item[$col];
985
                }
986
            }
987
        }
988
        // opciones
989
        $options = ['align'=>[]];
990
        $i = 0;
991
        foreach ($this->detalle_cols as $info) {
992
            if (isset($info['width'])) {
993
                $options['width'][$i] = $info['width'];
994
            }
995
            $options['align'][$i] = $info['align'];
996
            $i++;
997
        }
998
        // agregar tabla de detalle
999
        $this->Ln();
1000
        $this->SetX($x);
1001
        $this->addTableWithoutEmptyCols($titulos, $detalle, $options);
1002
    }
1003
1004
    /**
1005
     * Método que agrega el detalle del documento
1006
     * @param detalle Arreglo con el detalle del documento (tag Detalle del XML)
1007
     * @param x Posición horizontal de inicio en el PDF
1008
     * @param y Posición vertical de inicio en el PDF
1009
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1010
     * @author Pablo Reyes (https://github.com/pabloxp)
1011
     * @version 2019-10-06
1012
     */
1013
    protected function agregarDetalleContinuo($detalle, $x = 3, array $offsets = [], $descripcion = false)
1014
    {
1015
        if (!$offsets) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $offsets of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1016
            $offsets = [1, 15, 35, 45];
1017
        }
1018
        $this->SetY($this->getY()+1);
1019
        $p1x = $x;
1020
        $p1y = $this->y;
1021
        $p2x = $this->getPageWidth() - 2;
1022
        $p2y = $p1y;  // Use same y for a straight line
1023
        $style = array('width' => 0.2,'color' => array(0, 0, 0));
1024
        $this->Line($p1x, $p1y, $p2x, $p2y, $style);
1025
        $this->Texto($this->detalle_cols['NmbItem']['title'], $x+$offsets[0], $this->y, ucfirst($this->detalle_cols['NmbItem']['align'][0]), $this->detalle_cols['NmbItem']['width']);
1026
        $this->Texto($this->detalle_cols['PrcItem']['title'], $x+$offsets[1], $this->y, ucfirst($this->detalle_cols['PrcItem']['align'][0]), $this->detalle_cols['PrcItem']['width']);
1027
        $this->Texto($this->detalle_cols['QtyItem']['title'], $x+$offsets[2], $this->y, ucfirst($this->detalle_cols['QtyItem']['align'][0]), $this->detalle_cols['QtyItem']['width']);
1028
        $this->Texto($this->detalle_cols['MontoItem']['title'], $x+$offsets[3], $this->y, ucfirst($this->detalle_cols['MontoItem']['align'][0]), $this->detalle_cols['MontoItem']['width']);
1029
        $this->Line($p1x, $p1y+4, $p2x, $p2y+4, $style);
1030
        if (!isset($detalle[0])) {
1031
            $detalle = [$detalle];
1032
        }
1033
        $this->SetY($this->getY()+2);
1034
        foreach($detalle as  &$d) {
1035
            $item = $d['NmbItem'];
1036
            if ($descripcion and !empty($d['DscItem'])) {
1037
                $item .= ': '.$d['DscItem'];
1038
            }
1039
            $this->MultiTexto($item, $x+$offsets[0], $this->y+4, ucfirst($this->detalle_cols['NmbItem']['align'][0]), $this->detalle_cols['NmbItem']['width']);
1040
            $this->Texto(number_format($d['PrcItem'],0,',','.'), $x+$offsets[1], $this->y, ucfirst($this->detalle_cols['PrcItem']['align'][0]), $this->detalle_cols['PrcItem']['width']);
1041
            $this->Texto($this->num($d['QtyItem']), $x+$offsets[2], $this->y, ucfirst($this->detalle_cols['QtyItem']['align'][0]), $this->detalle_cols['QtyItem']['width']);
1042
            $this->Texto($this->num($d['MontoItem']), $x+$offsets[3], $this->y, ucfirst($this->detalle_cols['MontoItem']['align'][0]), $this->detalle_cols['MontoItem']['width']);
1043
        }
1044
        $this->Line($p1x, $this->y+4, $p2x, $this->y+4, $style);
1045
    }
1046
1047
    /**
1048
     * Método que agrega el subtotal del DTE
1049
     * @param detalle Arreglo con los detalles del documentos para poder
1050
     * calcular subtotal
1051
     * @param x Posición horizontal de inicio en el PDF
1052
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1053
     * @version 2016-08-17
1054
     */
1055
    protected function agregarSubTotal(array $detalle, $x = 10) {
1056
        $subtotal = 0;
1057
        if (!isset($detalle[0])) {
1058
            $detalle = [$detalle];
1059
        }
1060
        foreach($detalle as  &$d) {
1061
            if (!empty($d['MontoItem'])) {
1062
                $subtotal += $d['MontoItem'];
1063
            }
1064
        }
1065
        if ($this->papelContinuo) {
1066
            $this->Texto('Subtotal: '.$this->num($subtotal), $x);
1067
        } else {
1068
            $this->Texto('Subtotal:', 77, null, 'R', 100);
1069
            $this->Texto($this->num($subtotal), 177, null, 'R', 22);
1070
        }
1071
        $this->Ln();
1072
    }
1073
1074
    /**
1075
     * Método que agrega los descuentos y/o recargos globales del documento
1076
     * @param descuentosRecargos Arreglo con los descuentos y/o recargos del documento (tag DscRcgGlobal del XML)
1077
     * @param x Posición horizontal de inicio en el PDF
1078
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1079
     * @version 2018-05-29
1080
     */
1081
    protected function agregarDescuentosRecargos(array $descuentosRecargos, $x = 10)
1082
    {
1083
        if (!isset($descuentosRecargos[0])) {
1084
            $descuentosRecargos = [$descuentosRecargos];
1085
        }
1086
        foreach($descuentosRecargos as $dr) {
1087
            $tipo = $dr['TpoMov']=='D' ? 'Descuento' : 'Recargo';
1088
            if (!empty($dr['IndExeDR'])) {
1089
                $tipo .= ' EX';
1090
            }
1091
            $valor = $dr['TpoValor']=='%' ? $dr['ValorDR'].'%' : $this->num($dr['ValorDR']);
1092
            if ($this->papelContinuo) {
1093
                $this->Texto($tipo.' global: '.$valor.(!empty($dr['GlosaDR'])?(' ('.$dr['GlosaDR'].')'):''), $x);
1094
            } else {
1095
                $this->Texto($tipo.(!empty($dr['GlosaDR'])?(' ('.$dr['GlosaDR'].')'):'').':', 77, null, 'R', 100);
1096
                $this->Texto($valor, 177, null, 'R', 22);
1097
            }
1098
            $this->Ln();
1099
        }
1100
    }
1101
1102
    /**
1103
     * Método que agrega los pagos del documento
1104
     * @param pagos Arreglo con los pagos del documento
1105
     * @param x Posición horizontal de inicio en el PDF
1106
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1107
     * @version 2016-07-24
1108
     */
1109
    protected function agregarPagos(array $pagos, $x = 10)
1110
    {
1111
        if (!isset($pagos[0]))
1112
            $pagos = [$pagos];
1113
        $this->Texto('Pago(s) programado(s):', $x);
1114
        $this->Ln();
1115
        foreach($pagos as $p) {
1116
            $this->Texto('  - '.$this->date($p['FchPago'], false).': $'.$this->num($p['MntPago']).'.-'.(!empty($p['GlosaPagos'])?(' ('.$p['GlosaPagos'].')'):''), $x);
1117
            $this->Ln();
1118
        }
1119
    }
1120
1121
    /**
1122
     * Método que agrega los totales del documento
1123
     * @param totales Arreglo con los totales (tag Totales del XML)
1124
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1125
     * @version 2017-10-05
1126
     */
1127
    protected function agregarTotales(array $totales, $otra_moneda, $y = 190, $x = 145, $offset = 25)
1128
    {
1129
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
1130
        // normalizar totales
1131
        $totales = array_merge([
1132
            'TpoMoneda' => false,
1133
            'MntNeto' => false,
1134
            'MntExe' => false,
1135
            'TasaIVA' => false,
1136
            'IVA' => false,
1137
            'IVANoRet' => false,
1138
            'CredEC' => false,
1139
            'MntTotal' => false,
1140
            'MontoNF' => false,
1141
            'MontoPeriodo' => false,
1142
            'SaldoAnterior' => false,
1143
            'VlrPagar' => false,
1144
        ], $totales);
1145
        // glosas
1146
        $glosas = [
1147
            'TpoMoneda' => 'Moneda',
1148
            'MntNeto' => 'Neto $',
1149
            'MntExe' => 'Exento $',
1150
            'IVA' => 'IVA ('.$totales['TasaIVA'].'%) $',
1151
            'IVANoRet' => 'IVA no retenido $',
1152
            'CredEC' => 'Desc. 65% IVA $',
1153
            'MntTotal' => 'Total $',
1154
            'MontoNF' => 'Monto no facturable $',
1155
            'MontoPeriodo' => 'Monto período $',
1156
            'SaldoAnterior' => 'Saldo anterior $',
1157
            'VlrPagar' => 'Valor a pagar $',
1158
        ];
1159
        // agregar impuestos adicionales y retenciones
1160
        if (!empty($totales['ImptoReten'])) {
1161
            $ImptoReten = $totales['ImptoReten'];
1162
            $MntTotal = $totales['MntTotal'];
1163
            unset($totales['ImptoReten'], $totales['MntTotal']);
1164
            if (!isset($ImptoReten[0])) {
1165
                $ImptoReten = [$ImptoReten];
1166
            }
1167
            foreach($ImptoReten as $i) {
1168
                $totales['ImptoReten_'.$i['TipoImp']] = $i['MontoImp'];
1169
                if (!empty($i['TasaImp'])) {
1170
                    $glosas['ImptoReten_'.$i['TipoImp']] = \sasco\LibreDTE\Sii\ImpuestosAdicionales::getGlosa($i['TipoImp']).' ('.$i['TasaImp'].'%) $';
1171
                } else {
1172
                    $glosas['ImptoReten_'.$i['TipoImp']] = \sasco\LibreDTE\Sii\ImpuestosAdicionales::getGlosa($i['TipoImp']).' $';
1173
                }
1174
            }
1175
            $totales['MntTotal'] = $MntTotal;
1176
        }
1177
        // agregar cada uno de los totales
1178
        $this->setY($y);
1179
        $this->setFont('', 'B', null);
1180
        foreach ($totales as $key => $total) {
1181
            if ($total!==false and isset($glosas[$key])) {
1182
                $y = $this->GetY();
1183
                if (!$this->cedible or $this->papelContinuo) {
1184
                    $this->Texto($glosas[$key].' :', $x, null, 'R', 30);
1185
                    $this->Texto($this->num($total), $x+$offset, $y, 'R', 30);
1186
                    $this->Ln();
1187
                } else {
1188
                    $this->MultiTexto($glosas[$key].' :', $x, null, 'R', 30);
1189
                    $y_new = $this->GetY();
1190
                    $this->Texto($this->num($total), $x+$offset, $y, 'R', 30);
1191
                    $this->SetY($y_new);
1192
                }
1193
            }
1194
        }
1195
        // agregar totales en otra moneda
1196
        if (!empty($otra_moneda)) {
1197
            if (!isset($otra_moneda[0])) {
1198
                $otra_moneda = [$otra_moneda];
1199
            }
1200
            $this->setFont('', '', null);
1201
            $this->Ln();
1202
            foreach ($otra_moneda as $om) {
1203
                $y = $this->GetY();
1204
                if (!$this->cedible or $this->papelContinuo) {
1205
                    $this->Texto('Total '.$om['TpoMoneda'].' :', $x, null, 'R', 30);
1206
                    $this->Texto($this->num($om['MntTotOtrMnda']), $x+$offset, $y, 'R', 30);
1207
                    $this->Ln();
1208
                } else {
1209
                    $this->MultiTexto('Total '.$om['TpoMoneda'].' :', $x, null, 'R', 30);
1210
                    $y_new = $this->GetY();
1211
                    $this->Texto($this->num($om['MntTotOtrMnda']), $x+$offset, $y, 'R', 30);
1212
                    $this->SetY($y_new);
1213
                }
1214
            }
1215
            $this->setFont('', 'B', null);
1216
        }
1217
    }
1218
1219
    /**
1220
     * Método que coloca las diferentes observaciones que puede tener el documnto
1221
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1222
     * @version 2018-06-15
1223
     */
1224
    protected function agregarObservacion($IdDoc, $x = 10, $y = 190)
1225
    {
1226
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
1227
        if (!$this->papelContinuo and $this->timbre_pie) {
1228
            $y -= 15;
1229
        }
1230
        $this->SetXY($x, $y);
1231
        if (!empty($IdDoc['TermPagoGlosa'])) {
1232
            $this->MultiTexto('Observación: '.$IdDoc['TermPagoGlosa']);
1233
        }
1234
        if (!empty($IdDoc['MedioPago']) or !empty($IdDoc['TermPagoDias'])) {
1235
            $pago = [];
1236
            if (!empty($IdDoc['MedioPago'])) {
1237
                $medio = 'Medio de pago: '.(!empty($this->medios_pago[$IdDoc['MedioPago']]) ? $this->medios_pago[$IdDoc['MedioPago']] : $IdDoc['MedioPago']);
1238
                if (!empty($IdDoc['BcoPago'])) {
1239
                    $medio .= ' a '.$IdDoc['BcoPago'];
1240
                }
1241
                if (!empty($IdDoc['TpoCtaPago'])) {
1242
                    $medio .= ' en cuenta '.strtolower($IdDoc['TpoCtaPago']);
1243
                }
1244
                if (!empty($IdDoc['NumCtaPago'])) {
1245
                    $medio .= ' N° '.$IdDoc['NumCtaPago'];
1246
                }
1247
                $pago[] = $medio;
1248
            }
1249
            if (!empty($IdDoc['TermPagoDias'])) {
1250
                $pago[] = 'Días de pago: '.$IdDoc['TermPagoDias'];
1251
            }
1252
            $this->SetXY($x, $this->GetY());
1253
            $this->MultiTexto(implode(' / ', $pago));
1254
        }
1255
        return $this->GetY();
1256
    }
1257
1258
    /**
1259
     * Método que agrega el timbre de la factura
1260
     *  - Se imprime en el tamaño mínimo: 2x5 cms
1261
     *  - En el lado de abajo con margen izquierdo mínimo de 2 cms
1262
     * @param timbre String con los datos del timbre
1263
     * @param x Posición horizontal de inicio en el PDF
1264
     * @param y Posición vertical de inicio en el PDF
1265
     * @param w Ancho del timbre
1266
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1267
     * @version 2019-10-06
1268
     */
1269
    protected function agregarTimbre($timbre, $x_timbre = 10, $x = 10, $y = 190, $w = 70, $font_size = 8, $position = null)
1270
    {
1271
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
1272
        if ($timbre!==null) {
1273
            $style = [
1274
                'border' => false,
1275
                'padding' => 0,
1276
                'hpadding' => 0,
1277
                'vpadding' => 0,
1278
                'module_width' => 1, // width of a single module in points
1279
                'module_height' => 1, // height of a single module in points
1280
                'fgcolor' => [0,0,0],
1281
                'bgcolor' => false, // [255,255,255]
1282
                'position' => $position === null ? ($this->papelContinuo ? 'C' : 'S') : $position,
1283
            ];
1284
            $ecl = version_compare(phpversion(), '7.0.0', '<') ? -1 : $this->ecl;
1285
            $this->write2DBarcode($timbre, 'PDF417,,'.$ecl, $x_timbre, $y, $w, 0, $style, 'B');
1286
            $this->setFont('', 'B', $font_size);
1287
            $this->Texto('Timbre Electrónico SII', $x, null, 'C', $w);
1288
            $this->Ln();
1289
            $this->Texto('Resolución '.$this->resolucion['NroResol'].' de '.explode('-', $this->resolucion['FchResol'])[0], $x, null, 'C', $w);
1290
            $this->Ln();
1291
            if ($w>=60) {
1292
                $this->Texto('Verifique documento: '.$this->web_verificacion, $x, null, 'C', $w);
1293
            } else {
1294
                $this->Texto('Verifique documento:', $x, null, 'C', $w);
1295
                $this->Ln();
1296
                $this->Texto($this->web_verificacion, $x, null, 'C', $w);
1297
            }
1298
        }
1299
    }
1300
1301
    /**
1302
     * Método que agrega el acuse de rebido
1303
     * @param x Posición horizontal de inicio en el PDF
1304
     * @param y Posición vertical de inicio en el PDF
1305
     * @param w Ancho del acuse de recibo
1306
     * @param h Alto del acuse de recibo
1307
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1308
     * @version 2019-10-06
1309
     */
1310
    protected function agregarAcuseRecibo($x = 83, $y = 190, $w = 60, $h = 40, $line = 25)
1311
    {
1312
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
1313
        $this->SetTextColorArray([0,0,0]);
1314
        $this->Rect($x, $y, $w, $h, 'D', ['all' => ['width' => 0.1, 'color' => [0, 0, 0]]]);
1315
        $this->setFont('', 'B', 10);
1316
        $this->Texto('Acuse de recibo', $x, $y+1, 'C', $w);
1317
        $this->setFont('', 'B', 8);
1318
        $this->Texto('Nombre', $x+2, $this->y+8);
1319
        $this->Texto(str_repeat('_', $line), $x+18);
1320
        $this->Texto('RUN', $x+2, $this->y+6);
1321
        $this->Texto(str_repeat('_', $line), $x+18);
1322
        $this->Texto('Fecha', $x+2, $this->y+6);
1323
        $this->Texto(str_repeat('_', $line), $x+18);
1324
        $this->Texto('Recinto', $x+2, $this->y+6);
1325
        $this->Texto(str_repeat('_', $line), $x+18);
1326
        $this->Texto('Firma', $x+2, $this->y+8);
1327
        $this->Texto(str_repeat('_', $line), $x+18);
1328
        $this->setFont('', 'B', 7);
1329
        $this->MultiTexto('El acuse de recibo que se declara en este acto, de acuerdo a lo dispuesto en la letra b) del Art. 4°, y la letra c) del Art. 5° de la Ley 19.983, acredita que la entrega de mercaderías o servicio (s) prestado (s) ha (n) sido recibido (s).'."\n", $x, $this->y+6, 'J', $w);
1330
    }
1331
1332
    /**
1333
     * Método que agrega el acuse de rebido
1334
     * @param x Posición horizontal de inicio en el PDF
1335
     * @param y Posición vertical de inicio en el PDF
1336
     * @param w Ancho del acuse de recibo
1337
     * @param h Alto del acuse de recibo
1338
     * @author Pablo Reyes (https://github.com/pabloxp)
1339
     * @version 2015-11-17
1340
     */
1341
    protected function agregarAcuseReciboContinuo($x = 3, $y = null, $w = 68, $h = 40)
1342
    {
1343
        $this->SetTextColorArray([0,0,0]);
1344
        $this->Rect($x, $y, $w, $h, 'D', ['all' => ['width' => 0.1, 'color' => [0, 0, 0]]]);
1345
        $style = array('width' => 0.2,'color' => array(0, 0, 0));
1346
        $this->Line($x, $y+22, $w+3, $y+22, $style);
1347
        //$this->setFont('', 'B', 10);
1348
        //$this->Texto('Acuse de recibo', $x, $y+1, 'C', $w);
1349
        $this->setFont('', 'B', 6);
1350
        $this->Texto('Nombre', $x+2, $this->y+8);
1351
        $this->Texto('_____________________________________________', $x+12);
1352
        $this->Texto('RUN', $x+2, $this->y+6);
1353
        $this->Texto('________________', $x+12);
1354
        $this->Texto('Firma', $x+32, $this->y+0.5);
1355
        $this->Texto('___________________', $x+42.5);
1356
        $this->Texto('Fecha', $x+2, $this->y+6);
1357
        $this->Texto('________________', $x+12);
1358
        $this->Texto('Recinto', $x+32, $this->y+0.5);
1359
        $this->Texto('___________________', $x+42.5);
1360
1361
        $this->setFont('', 'B', 5);
1362
        $this->MultiTexto('El acuse de recibo que se declara en este acto, de acuerdo a lo dispuesto en la letra b) del Art. 4°, y la letra c) del Art. 5° de la Ley 19.983, acredita que la entrega de mercaderías o servicio (s) prestado (s) ha (n) sido recibido (s).'."\n", $x+2, $this->y+8, 'J', $w-3);
1363
    }
1364
1365
    /**
1366
     * Método que agrega la leyenda de destino
1367
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1368
     * @version 2018-09-10
1369
     */
1370
    protected function agregarLeyendaDestino($tipo, $y = 190, $font_size = 10)
1371
    {
1372
        $y = (!$this->papelContinuo and !$this->timbre_pie and $this->x_fin_datos<=$y) ? $this->x_fin_datos : $y;
1373
        $y += 48;
1374
        $this->setFont('', 'B', $font_size);
1375
        $this->Texto('CEDIBLE'.($tipo==52?' CON SU FACTURA':''), null, $y, 'R');
1376
    }
1377
1378
    /**
1379
     * Método que agrega la leyenda de destino
1380
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1381
     * @version 2017-10-05
1382
     */
1383
    protected function agregarLeyendaDestinoContinuo($tipo)
1384
    {
1385
        $this->setFont('', 'B', 8);
1386
        $this->Texto('CEDIBLE'.($tipo==52?' CON SU FACTURA':''), null, $this->y+6, 'R');
1387
    }
1388
1389
}
1390