1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of FacturaScripts |
4
|
|
|
* Copyright (C) 2021-2024 Carlos Garcia Gomez <[email protected]> |
5
|
|
|
* |
6
|
|
|
* This program is free software: you can redistribute it and/or modify |
7
|
|
|
* it under the terms of the GNU Lesser General Public License as |
8
|
|
|
* published by the Free Software Foundation, either version 3 of the |
9
|
|
|
* License, or (at your option) any later version. |
10
|
|
|
* |
11
|
|
|
* This program is distributed in the hope that it will be useful, |
12
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14
|
|
|
* GNU Lesser General Public License for more details. |
15
|
|
|
* |
16
|
|
|
* You should have received a copy of the GNU Lesser General Public License |
17
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
18
|
|
|
*/ |
19
|
|
|
|
20
|
|
|
namespace FacturaScripts\Core\Controller; |
21
|
|
|
|
22
|
|
|
use FacturaScripts\Core\Base\Controller; |
23
|
|
|
use FacturaScripts\Core\Base\ControllerPermissions; |
24
|
|
|
use FacturaScripts\Core\DataSrc\Divisas; |
25
|
|
|
use FacturaScripts\Core\Tools; |
26
|
|
|
use FacturaScripts\Dinamic\Lib\ExportManager; |
27
|
|
|
use FacturaScripts\Dinamic\Lib\InvoiceOperation; |
28
|
|
|
use FacturaScripts\Dinamic\Model\Divisa; |
29
|
|
|
use FacturaScripts\Dinamic\Model\Pais; |
30
|
|
|
use FacturaScripts\Dinamic\Model\Serie; |
31
|
|
|
use FacturaScripts\Dinamic\Model\User; |
32
|
|
|
use Symfony\Component\HttpFoundation\Response; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Description of ReportTaxes |
36
|
|
|
* |
37
|
|
|
* @author Carlos Garcia Gomez <[email protected]> |
38
|
|
|
*/ |
39
|
|
|
class ReportTaxes extends Controller |
40
|
|
|
{ |
41
|
|
|
const MAX_TOTAL_DIFF = 0.05; |
42
|
|
|
|
43
|
|
|
/** @var string */ |
44
|
|
|
public $coddivisa; |
45
|
|
|
|
46
|
|
|
/** @var string */ |
47
|
|
|
public $codpais; |
48
|
|
|
|
49
|
|
|
/** @var string */ |
50
|
|
|
public $codserie; |
51
|
|
|
|
52
|
|
|
/** @var string */ |
53
|
|
|
public $datefrom; |
54
|
|
|
|
55
|
|
|
/** @var string */ |
56
|
|
|
public $dateto; |
57
|
|
|
|
58
|
|
|
/** @var Divisa */ |
59
|
|
|
public $divisa; |
60
|
|
|
|
61
|
|
|
/** @var string */ |
62
|
|
|
public $format; |
63
|
|
|
|
64
|
|
|
/** @var int */ |
65
|
|
|
public $idempresa; |
66
|
|
|
|
67
|
|
|
/** @var Pais */ |
68
|
|
|
public $pais; |
69
|
|
|
|
70
|
|
|
/** @var Serie */ |
71
|
|
|
public $serie; |
72
|
|
|
|
73
|
|
|
/** @var string */ |
74
|
|
|
public $source; |
75
|
|
|
|
76
|
|
|
/** @var string */ |
77
|
|
|
public $typeDate; |
78
|
|
|
|
79
|
|
|
public function getPageData(): array |
80
|
|
|
{ |
81
|
|
|
$data = parent::getPageData(); |
82
|
|
|
$data['title'] = 'taxes'; |
83
|
|
|
$data['menu'] = 'reports'; |
84
|
|
|
$data['icon'] = 'fas fa-wallet'; |
85
|
|
|
return $data; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @param Response $response |
90
|
|
|
* @param User $user |
91
|
|
|
* @param ControllerPermissions $permissions |
92
|
|
|
*/ |
93
|
|
|
public function privateCore(&$response, $user, $permissions) |
94
|
|
|
{ |
95
|
|
|
parent::privateCore($response, $user, $permissions); |
96
|
|
|
|
97
|
|
|
$this->divisa = new Divisa(); |
98
|
|
|
$this->pais = new Pais(); |
99
|
|
|
$this->serie = new Serie(); |
100
|
|
|
$this->initFilters(); |
101
|
|
|
|
102
|
|
|
if ('export' === $this->request->request->get('action')) { |
103
|
|
|
$this->exportAction(); |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
protected function exportAction(): void |
108
|
|
|
{ |
109
|
|
|
$i18n = Tools::lang(); |
110
|
|
|
$data = $this->getReportData(); |
111
|
|
|
if (empty($data)) { |
112
|
|
|
Tools::log()->warning('no-data'); |
113
|
|
|
return; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
// prepare lines |
117
|
|
|
$lastCode = ''; |
118
|
|
|
$lines = []; |
119
|
|
|
foreach ($data as $row) { |
120
|
|
|
$hide = $row['codigo'] === $lastCode && $this->format === 'PDF'; |
121
|
|
|
$num2title = $this->source === 'sales' ? 'number2' : 'numproveedor'; |
122
|
|
|
|
123
|
|
|
$lines[] = [ |
124
|
|
|
$i18n->trans('serie') => $hide ? '' : $row['codserie'], |
125
|
|
|
$i18n->trans('code') => $hide ? '' : $row['codigo'], |
126
|
|
|
$i18n->trans($num2title) => $hide ? '' : $row['numero2'], |
127
|
|
|
$i18n->trans('date') => $hide ? '' : Tools::date($row['fecha']), |
128
|
|
|
$i18n->trans('name') => $hide ? '' : Tools::fixHtml($row['nombre']), |
129
|
|
|
$i18n->trans('cifnif') => $hide ? '' : $row['cifnif'], |
130
|
|
|
$i18n->trans('net') => $this->exportFieldFormat('number', $row['neto']), |
131
|
|
|
$i18n->trans('pct-tax') => $this->exportFieldFormat('number', $row['iva']), |
132
|
|
|
$i18n->trans('tax') => $this->exportFieldFormat('number', $row['totaliva']), |
133
|
|
|
$i18n->trans('pct-surcharge') => $this->exportFieldFormat('number', $row['recargo']), |
134
|
|
|
$i18n->trans('surcharge') => $this->exportFieldFormat('number', $row['totalrecargo']), |
135
|
|
|
$i18n->trans('pct-irpf') => $this->exportFieldFormat('number', $row['irpf']), |
136
|
|
|
$i18n->trans('irpf') => $this->exportFieldFormat('number', $row['totalirpf']), |
137
|
|
|
$i18n->trans('supplied-amount') => $this->exportFieldFormat('number', $row['suplidos']), |
138
|
|
|
$i18n->trans('total') => $hide ? '' : $this->exportFieldFormat('number', $row['total']) |
139
|
|
|
]; |
140
|
|
|
|
141
|
|
|
$lastCode = $row['codigo']; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
$totalsData = $this->getTotals($data); |
145
|
|
|
if (false === $this->validateTotals($totalsData)) { |
146
|
|
|
return; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
// prepare totals |
150
|
|
|
$totals = []; |
151
|
|
|
foreach ($totalsData as $row) { |
152
|
|
|
$total = $row['neto'] + $row['totaliva'] + $row['totalrecargo'] - $row['totalirpf'] - $row['suplidos']; |
153
|
|
|
$totals[] = [ |
154
|
|
|
$i18n->trans('net') => $this->exportFieldFormat('number', $row['neto']), |
155
|
|
|
$i18n->trans('pct-tax') => $this->exportFieldFormat('percentage', $row['iva']), |
156
|
|
|
$i18n->trans('tax') => $this->exportFieldFormat('number', $row['totaliva']), |
157
|
|
|
$i18n->trans('pct-surcharge') => $this->exportFieldFormat('percentage', $row['recargo']), |
158
|
|
|
$i18n->trans('surcharge') => $this->exportFieldFormat('number', $row['totalrecargo']), |
159
|
|
|
$i18n->trans('pct-irpf') => $this->exportFieldFormat('percentage', $row['irpf']), |
160
|
|
|
$i18n->trans('irpf') => $this->exportFieldFormat('number', $row['totalirpf']), |
161
|
|
|
$i18n->trans('supplied-amount') => $this->exportFieldFormat('number', $row['suplidos']), |
162
|
|
|
$i18n->trans('total') => $this->exportFieldFormat('number', $total) |
163
|
|
|
]; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
$this->setTemplate(false); |
167
|
|
|
$this->processLayout($lines, $totals); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
protected function exportFieldFormat(string $format, string $value): string |
171
|
|
|
{ |
172
|
|
|
switch ($format) { |
173
|
|
|
case 'number': |
174
|
|
|
return $this->format === 'PDF' ? Tools::number($value) : $value; |
|
|
|
|
175
|
|
|
|
176
|
|
|
case 'percentage': |
177
|
|
|
return $this->format === 'PDF' ? Tools::number($value) . ' %' : $value; |
178
|
|
|
|
179
|
|
|
default: |
180
|
|
|
return $value; |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
protected function getQuarterDate(bool $start): string |
185
|
|
|
{ |
186
|
|
|
$month = (int)date('m'); |
187
|
|
|
|
188
|
|
|
// si la fecha actual es de enero, seleccionamos el trimestre anterior |
189
|
|
|
if ($month === 1) { |
190
|
|
|
return $start ? |
191
|
|
|
date('Y-10-01', strtotime('-1 year')) : |
192
|
|
|
date('Y-12-31', strtotime('-1 year')); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
// comprobamos si la fecha actual está en el primer trimestre o justo en el siguiente mes |
196
|
|
|
if ($month >= 1 && $month <= 4) { |
197
|
|
|
return $start ? date('Y-01-01') : date('Y-03-31'); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
// comprobamos si la fecha actual está en el segundo trimestre o justo en el siguiente mes |
201
|
|
|
if ($month >= 4 && $month <= 7) { |
202
|
|
|
return $start ? date('Y-04-01') : date('Y-06-30'); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
// comprobamos si la fecha actual está en el tercer trimestre o justo en el siguiente mes |
206
|
|
|
if ($month >= 7 && $month <= 10) { |
207
|
|
|
return $start ? date('Y-07-01') : date('Y-09-30'); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
// la fecha actual está en el cuarto trimestre |
211
|
|
|
return $start ? date('Y-10-01') : date('Y-12-31'); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
protected function getReportData(): array |
215
|
|
|
{ |
216
|
|
|
$sql = ''; |
217
|
|
|
$numCol = strtolower(FS_DB_TYPE) == 'postgresql' ? 'CAST(f.numero as integer)' : 'CAST(f.numero as unsigned)'; |
|
|
|
|
218
|
|
|
$columnDate = $this->typeDate === 'create' ? 'f.fecha' : 'COALESCE(f.fechadevengo, f.fecha)'; |
219
|
|
|
switch ($this->source) { |
220
|
|
|
case 'purchases': |
221
|
|
|
$sql .= 'SELECT f.codserie, f.codigo, f.numproveedor AS numero2, f.fecha, f.fechadevengo, f.nombre, f.cifnif, l.pvptotal,' |
222
|
|
|
. ' l.iva, l.recargo, l.irpf, l.suplido, f.dtopor1, f.dtopor2, f.total, f.operacion' |
223
|
|
|
. ' FROM lineasfacturasprov AS l' |
224
|
|
|
. ' LEFT JOIN facturasprov AS f ON l.idfactura = f.idfactura ' |
225
|
|
|
. ' WHERE f.idempresa = ' . $this->dataBase->var2str($this->idempresa) |
226
|
|
|
. ' AND ' . $columnDate . ' >= ' . $this->dataBase->var2str($this->datefrom) |
227
|
|
|
. ' AND ' . $columnDate . ' <= ' . $this->dataBase->var2str($this->dateto) |
228
|
|
|
. ' AND (l.pvptotal <> 0.00 OR l.iva <> 0.00)' |
229
|
|
|
. ' AND f.coddivisa = ' . $this->dataBase->var2str($this->coddivisa); |
230
|
|
|
break; |
231
|
|
|
|
232
|
|
|
case 'sales': |
233
|
|
|
$sql .= 'SELECT f.codserie, f.codigo, f.numero2, f.fecha, f.fechadevengo, f.nombrecliente AS nombre, f.cifnif, l.pvptotal,' |
234
|
|
|
. ' l.iva, l.recargo, l.irpf, l.suplido, f.dtopor1, f.dtopor2, f.total, f.operacion' |
235
|
|
|
. ' FROM lineasfacturascli AS l' |
236
|
|
|
. ' LEFT JOIN facturascli AS f ON l.idfactura = f.idfactura ' |
237
|
|
|
. ' WHERE f.idempresa = ' . $this->dataBase->var2str($this->idempresa) |
238
|
|
|
. ' AND ' . $columnDate . ' >= ' . $this->dataBase->var2str($this->datefrom) |
239
|
|
|
. ' AND ' . $columnDate . ' <= ' . $this->dataBase->var2str($this->dateto) |
240
|
|
|
. ' AND (l.pvptotal <> 0.00 OR l.iva <> 0.00)' |
241
|
|
|
. ' AND f.coddivisa = ' . $this->dataBase->var2str($this->coddivisa); |
242
|
|
|
if ($this->codpais) { |
243
|
|
|
$sql .= ' AND codpais = ' . $this->dataBase->var2str($this->codpais); |
244
|
|
|
} |
245
|
|
|
break; |
246
|
|
|
|
247
|
|
|
default: |
248
|
|
|
Tools::log()->warning('wrong-source'); |
249
|
|
|
return []; |
250
|
|
|
} |
251
|
|
|
if ($this->codserie) { |
252
|
|
|
$sql .= ' AND codserie = ' . $this->dataBase->var2str($this->codserie); |
253
|
|
|
} |
254
|
|
|
$sql .= ' ORDER BY ' . $columnDate . ', ' . $numCol . ' ASC;'; |
255
|
|
|
|
256
|
|
|
$data = []; |
257
|
|
|
foreach ($this->dataBase->select($sql) as $row) { |
258
|
|
|
$pvpTotal = floatval($row['pvptotal']) * (100 - floatval($row['dtopor1'])) * (100 - floatval($row['dtopor2'])) / 10000; |
259
|
|
|
$code = $row['codigo'] . '-' . $row['iva'] . '-' . $row['recargo'] . '-' . $row['irpf'] . '-' . $row['suplido']; |
260
|
|
|
if (isset($data[$code])) { |
261
|
|
|
$data[$code]['neto'] += $row['suplido'] ? 0 : $pvpTotal; |
262
|
|
|
$data[$code]['totaliva'] += $row['suplido'] || $row['operacion'] === InvoiceOperation::INTRA_COMMUNITY ? 0 : (float)$row['iva'] * $pvpTotal / 100; |
263
|
|
|
$data[$code]['totalrecargo'] += $row['suplido'] ? 0 : (float)$row['recargo'] * $pvpTotal / 100; |
264
|
|
|
$data[$code]['totalirpf'] += $row['suplido'] ? 0 : (float)$row['irpf'] * $pvpTotal / 100; |
265
|
|
|
$data[$code]['suplidos'] += $row['suplido'] ? $pvpTotal : 0; |
266
|
|
|
continue; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
$data[$code] = [ |
270
|
|
|
'codserie' => $row['codserie'], |
271
|
|
|
'codigo' => $row['codigo'], |
272
|
|
|
'numero2' => $row['numero2'], |
273
|
|
|
'fecha' => $this->typeDate == 'create' ? |
274
|
|
|
$row['fecha'] : |
275
|
|
|
$row['fechadevengo'] ?? $row['fecha'], |
276
|
|
|
'nombre' => $row['nombre'], |
277
|
|
|
'cifnif' => $row['cifnif'], |
278
|
|
|
'neto' => $row['suplido'] ? 0 : $pvpTotal, |
279
|
|
|
'iva' => $row['suplido'] ? 0 : (float)$row['iva'], |
280
|
|
|
'totaliva' => $row['suplido'] || $row['operacion'] === InvoiceOperation::INTRA_COMMUNITY ? 0 : (float)$row['iva'] * $pvpTotal / 100, |
281
|
|
|
'recargo' => $row['suplido'] ? 0 : (float)$row['recargo'], |
282
|
|
|
'totalrecargo' => $row['suplido'] ? 0 : (float)$row['recargo'] * $pvpTotal / 100, |
283
|
|
|
'irpf' => $row['suplido'] ? 0 : (float)$row['irpf'], |
284
|
|
|
'totalirpf' => $row['suplido'] ? 0 : (float)$row['irpf'] * $pvpTotal / 100, |
285
|
|
|
'suplidos' => $row['suplido'] ? $pvpTotal : 0, |
286
|
|
|
'total' => (float)$row['total'] |
287
|
|
|
]; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
// round |
291
|
|
|
foreach ($data as $key => $value) { |
292
|
|
|
$data[$key]['neto'] = round($value['neto'], FS_NF0); |
293
|
|
|
$data[$key]['totaliva'] = round($value['totaliva'], FS_NF0); |
294
|
|
|
$data[$key]['totalrecargo'] = round($value['totalrecargo'], FS_NF0); |
295
|
|
|
$data[$key]['totalirpf'] = round($value['totalirpf'], FS_NF0); |
296
|
|
|
$data[$key]['suplidos'] = round($value['suplidos'], FS_NF0); |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
return $data; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
protected function getTotals(array $data): array |
303
|
|
|
{ |
304
|
|
|
$totals = []; |
305
|
|
|
foreach ($data as $row) { |
306
|
|
|
$code = $row['iva'] . '-' . $row['recargo'] . '-' . $row['irpf']; |
307
|
|
|
if (isset($totals[$code])) { |
308
|
|
|
$totals[$code]['neto'] += $row['neto']; |
309
|
|
|
$totals[$code]['totaliva'] += $row['totaliva']; |
310
|
|
|
$totals[$code]['totalrecargo'] += $row['totalrecargo']; |
311
|
|
|
$totals[$code]['totalirpf'] += $row['totalirpf']; |
312
|
|
|
$totals[$code]['suplidos'] += $row['suplidos']; |
313
|
|
|
continue; |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
$totals[$code] = [ |
317
|
|
|
'neto' => $row['neto'], |
318
|
|
|
'iva' => $row['iva'], |
319
|
|
|
'totaliva' => $row['totaliva'], |
320
|
|
|
'recargo' => $row['recargo'], |
321
|
|
|
'totalrecargo' => $row['totalrecargo'], |
322
|
|
|
'irpf' => $row['irpf'], |
323
|
|
|
'totalirpf' => $row['totalirpf'], |
324
|
|
|
'suplidos' => $row['suplidos'] |
325
|
|
|
]; |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
return $totals; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
protected function initFilters(): void |
332
|
|
|
{ |
333
|
|
|
$this->coddivisa = $this->request->request->get( |
334
|
|
|
'coddivisa', |
335
|
|
|
Tools::settings('default', 'coddivisa') |
336
|
|
|
); |
337
|
|
|
|
338
|
|
|
$this->codpais = $this->request->request->get('codpais', ''); |
339
|
|
|
$this->codserie = $this->request->request->get('codserie', ''); |
340
|
|
|
$this->datefrom = $this->request->request->get('datefrom', $this->getQuarterDate(true)); |
341
|
|
|
$this->dateto = $this->request->request->get('dateto', $this->getQuarterDate(false)); |
342
|
|
|
|
343
|
|
|
$this->idempresa = (int)$this->request->request->get( |
344
|
|
|
'idempresa', |
345
|
|
|
Tools::settings('default', 'idempresa') |
346
|
|
|
); |
347
|
|
|
|
348
|
|
|
$this->format = $this->request->request->get('format'); |
349
|
|
|
$this->source = $this->request->request->get('source'); |
350
|
|
|
$this->typeDate = $this->request->request->get('type-date'); |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
protected function processLayout(array &$lines, array &$totals): void |
354
|
|
|
{ |
355
|
|
|
$i18n = Tools::lang(); |
356
|
|
|
$exportManager = new ExportManager(); |
357
|
|
|
$exportManager->setOrientation('landscape'); |
358
|
|
|
$exportManager->newDoc($this->format, $i18n->trans('taxes')); |
359
|
|
|
|
360
|
|
|
// add information table |
361
|
|
|
$exportManager->addTablePage( |
362
|
|
|
[ |
363
|
|
|
$i18n->trans('report'), |
364
|
|
|
$i18n->trans('currency'), |
365
|
|
|
$i18n->trans('date'), |
366
|
|
|
$i18n->trans('from-date'), |
367
|
|
|
$i18n->trans('until-date') |
368
|
|
|
], |
369
|
|
|
[[ |
370
|
|
|
$i18n->trans('report') => $i18n->trans('taxes') . ' ' . $i18n->trans($this->source), |
371
|
|
|
$i18n->trans('currency') => Divisas::get($this->coddivisa)->descripcion, |
372
|
|
|
$i18n->trans('date') => $i18n->trans($this->typeDate === 'create' ? 'creation-date' : 'accrual-date'), |
373
|
|
|
$i18n->trans('from-date') => Tools::date($this->datefrom), |
374
|
|
|
$i18n->trans('until-date') => Tools::date($this->dateto) |
375
|
|
|
]] |
376
|
|
|
); |
377
|
|
|
|
378
|
|
|
$options = [ |
379
|
|
|
$i18n->trans('net') => ['display' => 'right'], |
380
|
|
|
$i18n->trans('pct-tax') => ['display' => 'right'], |
381
|
|
|
$i18n->trans('tax') => ['display' => 'right'], |
382
|
|
|
$i18n->trans('pct-surcharge') => ['display' => 'right'], |
383
|
|
|
$i18n->trans('surcharge') => ['display' => 'right'], |
384
|
|
|
$i18n->trans('pct-irpf') => ['display' => 'right'], |
385
|
|
|
$i18n->trans('irpf') => ['display' => 'right'], |
386
|
|
|
$i18n->trans('supplied-amount') => ['display' => 'right'], |
387
|
|
|
$i18n->trans('total') => ['display' => 'right'] |
388
|
|
|
]; |
389
|
|
|
|
390
|
|
|
// add lines table |
391
|
|
|
$this->reduceLines($lines); |
392
|
|
|
$headers = empty($lines) ? [] : array_keys(end($lines)); |
393
|
|
|
$exportManager->addTablePage($headers, $lines, $options); |
394
|
|
|
|
395
|
|
|
// add totals table |
396
|
|
|
$headTotals = empty($totals) ? [] : array_keys(end($totals)); |
397
|
|
|
$exportManager->addTablePage($headTotals, $totals, $options); |
398
|
|
|
|
399
|
|
|
$exportManager->show($this->response); |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
protected function reduceLines(array &$lines): void |
403
|
|
|
{ |
404
|
|
|
$i18n = Tools::lang(); |
405
|
|
|
$zero = Tools::number(0); |
406
|
|
|
$numero2 = $recargo = $totalRecargo = $irpf = $totalIrpf = $suplidos = false; |
407
|
|
|
foreach ($lines as $row) { |
408
|
|
|
if (!empty($row[$i18n->trans('number2')])) { |
409
|
|
|
$numero2 = true; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
if ($row[$i18n->trans('pct-surcharge')] !== $zero) { |
413
|
|
|
$recargo = true; |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
if ($row[$i18n->trans('surcharge')] !== $zero) { |
417
|
|
|
$totalRecargo = true; |
418
|
|
|
} |
419
|
|
|
|
420
|
|
|
if ($row[$i18n->trans('pct-irpf')] !== $zero) { |
421
|
|
|
$irpf = true; |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
if ($row[$i18n->trans('irpf')] !== $zero) { |
425
|
|
|
$totalIrpf = true; |
426
|
|
|
} |
427
|
|
|
|
428
|
|
|
if ($row[$i18n->trans('supplied-amount')] !== $zero) { |
429
|
|
|
$suplidos = true; |
430
|
|
|
} |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
foreach (array_keys($lines) as $key) { |
434
|
|
|
if (false === $numero2) { |
435
|
|
|
unset($lines[$key][$i18n->trans('number2')]); |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
if (false === $recargo) { |
439
|
|
|
unset($lines[$key][$i18n->trans('pct-surcharge')]); |
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
if (false === $totalRecargo) { |
443
|
|
|
unset($lines[$key][$i18n->trans('surcharge')]); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
if (false === $irpf) { |
447
|
|
|
unset($lines[$key][$i18n->trans('pct-irpf')]); |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
if (false === $totalIrpf) { |
451
|
|
|
unset($lines[$key][$i18n->trans('irpf')]); |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
if (false === $suplidos) { |
455
|
|
|
unset($lines[$key][$i18n->trans('supplied-amount')]); |
456
|
|
|
} |
457
|
|
|
} |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
protected function validateTotals(array $totalsData): bool |
461
|
|
|
{ |
462
|
|
|
// sum totals from the given data |
463
|
|
|
$neto = $totalIva = $totalRecargo = 0.0; |
464
|
|
|
foreach ($totalsData as $row) { |
465
|
|
|
$neto += $row['neto']; |
466
|
|
|
$totalIva += $row['totaliva']; |
467
|
|
|
$totalRecargo += $row['totalrecargo']; |
468
|
|
|
} |
469
|
|
|
|
470
|
|
|
// gets totals from the database |
471
|
|
|
$neto2 = $totalIva2 = $totalRecargo2 = 0.0; |
472
|
|
|
$tableName = $this->source === 'sales' ? 'facturascli' : 'facturasprov'; |
473
|
|
|
$columnDate = $this->typeDate === 'create' ? 'fecha' : 'COALESCE(fechadevengo, fecha)'; |
474
|
|
|
$sql = 'SELECT SUM(neto) as neto, SUM(totaliva) as t1, SUM(totalrecargo) as t2' |
475
|
|
|
. ' FROM ' . $tableName |
476
|
|
|
. ' WHERE idempresa = ' . $this->dataBase->var2str($this->idempresa) |
477
|
|
|
. ' AND ' . $columnDate . ' >= ' . $this->dataBase->var2str($this->datefrom) |
478
|
|
|
. ' AND ' . $columnDate . ' <= ' . $this->dataBase->var2str($this->dateto) |
479
|
|
|
. ' AND coddivisa = ' . $this->dataBase->var2str($this->coddivisa); |
480
|
|
|
if ($this->codserie) { |
481
|
|
|
$sql .= ' AND codserie = ' . $this->dataBase->var2str($this->codserie); |
482
|
|
|
} |
483
|
|
|
if ($this->codpais && $this->source === 'sales') { |
484
|
|
|
$sql .= ' AND codpais = ' . $this->dataBase->var2str($this->codpais); |
485
|
|
|
} |
486
|
|
|
foreach ($this->dataBase->selectLimit($sql) as $row) { |
487
|
|
|
$neto2 += (float)$row['neto']; |
488
|
|
|
$totalIva2 += (float)$row['t1']; |
489
|
|
|
$totalRecargo2 += (float)$row['t2']; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
// compare |
493
|
|
|
$result = true; |
494
|
|
|
if (abs($neto - $neto2) > self::MAX_TOTAL_DIFF) { |
495
|
|
|
Tools::log()->error('calculated-net-diff', ['%net%' => $neto, '%net2%' => $neto2]); |
496
|
|
|
$result = false; |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
if (abs($totalIva - $totalIva2) > self::MAX_TOTAL_DIFF) { |
500
|
|
|
Tools::log()->error('calculated-tax-diff', ['%tax%' => $totalIva, '%tax2%' => $totalIva2]); |
501
|
|
|
$result = false; |
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
if (abs($totalRecargo - $totalRecargo2) > self::MAX_TOTAL_DIFF) { |
505
|
|
|
Tools::log()->error('calculated-surcharge-diff', [ |
506
|
|
|
'%surcharge%' => $totalRecargo, '%surcharge2%' => $totalRecargo2 |
507
|
|
|
]); |
508
|
|
|
$result = false; |
509
|
|
|
} |
510
|
|
|
|
511
|
|
|
return $result; |
512
|
|
|
} |
513
|
|
|
} |
514
|
|
|
|