Completed
Push — master ( 99ba08...e85760 )
by Carlos
05:29
created

BusinessDocumentLine::getTax()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
/**
3
 * This file is part of FacturaScripts
4
 * Copyright (C) 2013-2019 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
namespace FacturaScripts\Core\Model\Base;
20
21
use FacturaScripts\Core\Base\DataBase\DataBaseWhere;
22
use FacturaScripts\Dinamic\Model\Impuesto;
23
use FacturaScripts\Dinamic\Model\Producto;
24
use FacturaScripts\Dinamic\Model\Stock;
25
use FacturaScripts\Dinamic\Model\Variante;
26
27
/**
28
 * Description of BusinessDocumentLine
29
 *
30
 * @author Carlos García Gómez <[email protected]>
31
 */
32
abstract class BusinessDocumentLine extends ModelOnChangeClass
33
{
34
35
    /**
36
     * Update stock status.
37
     *
38
     * @var int
39
     */
40
    public $actualizastock;
41
42
    /**
43
     * Quantity.
44
     *
45
     * @var float|int
46
     */
47
    public $cantidad;
48
49
    /**
50
     * Code of the related tax.
51
     *
52
     * @var string
53
     */
54
    public $codimpuesto;
55
56
    /**
57
     * Description of the line.
58
     *
59
     * @var string
60
     */
61
    public $descripcion;
62
63
    /**
64
     * % off discount.
65
     *
66
     * @var float|int
67
     */
68
    public $dtopor;
69
70
    /**
71
     * Primary key.
72
     *
73
     * @var int
74
     */
75
    public $idlinea;
76
77
    /**
78
     *
79
     * @var int
80
     */
81
    public $idproducto;
82
83
    /**
84
     * % of IRPF of the line.
85
     *
86
     * @var float|int
87
     */
88
    public $irpf;
89
90
    /**
91
     * % of the related tax.
92
     *
93
     * @var float|int
94
     */
95
    public $iva;
96
97
    /**
98
     * Position of the line in the document. The higher down.
99
     *
100
     * @var int
101
     */
102
    public $orden;
103
104
    /**
105
     * Net amount without discounts.
106
     *
107
     * @var float|int
108
     */
109
    public $pvpsindto;
110
111
    /**
112
     * Net amount of the line, without taxes.
113
     *
114
     * @var float|int
115
     */
116
    public $pvptotal;
117
118
    /**
119
     * Price of the item, one unit.
120
     *
121
     * @var float|int
122
     */
123
    public $pvpunitario;
124
125
    /**
126
     * % surcharge of line equivalence.
127
     *
128
     * @var float|int
129
     */
130
    public $recargo;
131
132
    /**
133
     * Reference of the article.
134
     *
135
     * @var string
136
     */
137
    public $referencia;
138
139
    /**
140
     * Served.
141
     *
142
     * @var float|int
143
     */
144
    public $servido;
145
146
    /**
147
     * Containt all avaliable taxes.
148
     *
149
     * @var Impuesto[]
150
     */
151
    private static $taxes = [];
152
153
    /**
154
     * Returns the parent document of this line.
155
     */
156
    abstract public function getDocument();
157
158
    /**
159
     * Returns the name of the column to store the document's identifier.
160
     */
161
    abstract public function documentColumn();
162
163
    /**
164
     * Reset the values of all model properties.
165
     */
166
    public function clear()
167
    {
168
        parent::clear();
169
        $this->actualizastock = 0;
170
        $this->cantidad = 0.0;
171
        $this->descripcion = '';
172
        $this->dtopor = 0.0;
173
        $this->irpf = 0.0;
174
        $this->orden = 0;
175
        $this->pvpsindto = 0.0;
176
        $this->pvptotal = 0.0;
177
        $this->pvpunitario = 0.0;
178
        $this->servido = 0.0;
179
180
        /// default tax
181
        $impuesto = $this->getDefaultTax();
182
        $this->codimpuesto = $impuesto->codimpuesto;
183
        $this->iva = $impuesto->iva;
184
        $this->recargo = $impuesto->recargo;
185
    }
186
187
    /**
188
     * Returns the identifier of the document.
189
     *
190
     * @return int
191
     */
192
    public function documentColumnValue()
193
    {
194
        return $this->{$this->documentColumn()};
195
    }
196
197
    /**
198
     * Returns related product.
199
     *
200
     * @return Producto
201
     */
202
    public function getProducto()
203
    {
204
        $producto = new Producto();
205
        $producto->loadFromCode($this->idproducto);
206
        return $producto;
207
    }
208
209
    /**
210
     * 
211
     * @return Impuesto
212
     */
213
    public function getTax()
214
    {
215
        if (!isset(self::$taxes[$this->codimpuesto])) {
216
            self::$taxes[$this->codimpuesto] = new Impuesto();
217
            self::$taxes[$this->codimpuesto]->loadFromCode($this->codimpuesto);
218
        }
219
220
        return self::$taxes[$this->codimpuesto];
221
    }
222
223
    /**
224
     * 
225
     * @return string
226
     */
227
    public function install()
228
    {
229
        /// needed dependencies
230
        new Impuesto();
231
        new Producto();
232
233
        return parent::install();
234
    }
235
236
    /**
237
     * Returns the name of the column that is the model's primary key.
238
     *
239
     * @return string
240
     */
241
    public static function primaryColumn()
242
    {
243
        return 'idlinea';
244
    }
245
246
    /**
247
     * Returns True if there is no errors on properties values.
248
     *
249
     * @return bool
250
     */
251
    public function test()
252
    {
253
        if ('' === $this->codimpuesto) {
254
            $this->codimpuesto = null;
255
        }
256
257
        $utils = $this->toolBox()->utils();
258
        $this->descripcion = $utils->noHtml($this->descripcion);
259
        $this->pvpsindto = $this->pvpunitario * $this->cantidad;
260
        $this->pvptotal = $this->pvpsindto * (100 - $this->dtopor) / 100;
261
        $this->referencia = $utils->noHtml($this->referencia);
262
        return parent::test();
263
    }
264
265
    /**
266
     * Custom url method.
267
     *
268
     * @param string $type
269
     * @param string $list
270
     * 
271
     * @return string
272
     */
273
    public function url(string $type = 'auto', string $list = 'List')
274
    {
275
        $name = str_replace('Linea', '', $this->modelClassName());
276
        if ($type === 'new') {
277
            return 'Edit' . $name;
278
        }
279
280
        return parent::url($type, 'List' . $name . '?activetab=List');
281
    }
282
283
    /**
284
     * Apply stock modifications according to $mode.
285
     *
286
     * @param int   $mode
287
     * @param float $quantity
288
     * @param Stock $stock
289
     */
290
    private function applyStockChanges(int $mode, float $quantity, Stock $stock)
291
    {
292
        switch ($mode) {
293
            case 1:
294
            case -1:
295
                $stock->cantidad += $mode * $quantity;
296
                break;
297
298
            case 2:
299
                $stock->pterecibir += $quantity;
300
                break;
301
302
            case -2:
303
                $stock->reservada += $quantity;
304
                break;
305
        }
306
    }
307
308
    /**
309
     * 
310
     * @return Impuesto
311
     */
312
    private function getDefaultTax()
313
    {
314
        $codimpuesto = $this->toolBox()->appSettings()->get('default', 'codimpuesto');
315
        $impuesto = new Impuesto();
316
        $impuesto->loadFromCode($codimpuesto);
317
        return $impuesto;
318
    }
319
320
    /**
321
     * This method is called before save (update) in the database this record
322
     * data when some field value has changed.
323
     * 
324
     * @param string $field
325
     *
326
     * @return bool
327
     */
328
    protected function onChange($field)
329
    {
330
        switch ($field) {
331
            case 'actualizastock':
332
            case 'cantidad':
333
                return $this->updateStock();
334
        }
335
336
        return parent::onChange($field);
337
    }
338
339
    /**
340
     * This method is called after this record is deleted from database.
341
     */
342
    protected function onDelete()
343
    {
344
        $this->cantidad = 0;
345
        $this->updateStock();
346
    }
347
348
    /**
349
     * 
350
     * @param array $values
351
     *
352
     * @return bool
353
     */
354
    protected function saveInsert(array $values = [])
355
    {
356
        if ($this->updateStock()) {
357
            return parent::saveInsert($values);
358
        }
359
360
        return false;
361
    }
362
363
    /**
364
     * 
365
     * @param array $fields
366
     */
367
    protected function setPreviousData(array $fields = [])
368
    {
369
        $more = [
370
            'actualizastock', 'cantidad', 'descripcion', 'dtopor', 'irpf',
371
            'iva', 'pvptotal', 'recargo'
372
        ];
373
        parent::setPreviousData(array_merge($more, $fields));
374
375
        if (null === $this->previousData['actualizastock']) {
376
            $this->previousData['actualizastock'] = 0;
377
        }
378
379
        if (null === $this->previousData['cantidad']) {
380
            $this->previousData['cantidad'] = 0.0;
381
        }
382
    }
383
384
    /**
385
     * Updates stock according to line data and $codalmacen warehouse.
386
     * 
387
     * @return bool
388
     */
389
    protected function updateStock()
390
    {
391
        $variante = new Variante();
392
        $where = [new DataBaseWhere('referencia', $this->referencia)];
393
        if (!empty($this->referencia) && $variante->loadFromCode('', $where)) {
394
            $producto = $variante->getProducto();
395
            if ($producto->nostock) {
396
                return true;
397
            }
398
399
            $stock = new Stock();
400
            $codalmacen = $this->getDocument()->codalmacen;
401
            $where2 = [
402
                new DataBaseWhere('codalmacen', $codalmacen),
403
                new DataBaseWhere('referencia', $this->referencia)
404
            ];
405
            if (!$stock->loadFromCode('', $where2)) {
406
                $stock->codalmacen = $codalmacen;
407
                $stock->idproducto = $producto->idproducto;
408
                $stock->referencia = $this->referencia;
409
            }
410
411
            $this->applyStockChanges($this->previousData['actualizastock'], $this->previousData['cantidad'] * -1, $stock);
412
            $this->applyStockChanges($this->actualizastock, $this->cantidad, $stock);
413
414
            /// enough stock?
415
            if (!$producto->ventasinstock && $this->actualizastock === -1 && $stock->cantidad < 0) {
416
                $this->toolBox()->i18nLog()->warning('not-enough-stock', ['%reference%' => $this->referencia]);
417
                return false;
418
            }
419
420
            return $stock->save();
421
        }
422
423
        return true;
424
    }
425
}
426