Test Failed
Pull Request — master (#1563)
by
unknown
09:08
created

Cliente   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 298
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 123
dl 0
loc 298
rs 8.96
c 0
b 0
f 0
wmc 43

17 Methods

Rating   Name   Duplication   Size   Complexity  
A primaryColumn() 0 3 1
A primaryDescriptionColumn() 0 3 1
A getDefaultAddress() 0 6 2
B test() 0 27 8
A getPaymentDays() 0 10 3
A getGroup() 0 5 1
A clear() 0 4 1
A getAddresses() 0 5 1
B getSubcuenta() 0 40 7
A codeModelSearch() 0 7 2
A getBankAccounts() 0 5 1
A checkVies() 0 4 1
A createSubcuenta() 0 31 5
A tableName() 0 3 1
A install() 0 8 1
B saveInsert() 0 32 6
A getSettings() 0 10 1

How to fix   Complexity   

Complex Class

Complex classes like Cliente often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Cliente, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * This file is part of FacturaScripts
4
 * Copyright (C) 2013-2023 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\Model;
21
22
use FacturaScripts\Core\Base\DataBase\DataBaseWhere;
23
use FacturaScripts\Core\DataSrc\Paises;
24
use FacturaScripts\Core\Lib\Vies;
25
use FacturaScripts\Core\Tools;
26
use FacturaScripts\Dinamic\Model\Contacto as DinContacto;
27
use FacturaScripts\Dinamic\Model\CuentaBancoCliente as DinCuentaBancoCliente;
28
use FacturaScripts\Dinamic\Model\CuentaEspecial as DinCuentaEspecial;
29
use FacturaScripts\Dinamic\Model\GrupoClientes as DinGrupoClientes;
30
use FacturaScripts\Dinamic\Model\Subcuenta as DinSubcuenta;
31
32
/**
33
 * The client. You can have one or more associated addresses and accounts.
34
 *
35
 * @author Carlos García Gómez <[email protected]>
36
 */
37
class Cliente extends Base\ComercialContact
38
{
39
    use Base\ModelTrait;
0 ignored issues
show
Bug introduced by
The trait FacturaScripts\Core\Model\Base\ModelTrait requires the property $name which is not provided by FacturaScripts\Core\Model\Cliente.
Loading history...
40
41
    const SPECIAL_ACCOUNT = 'CLIENT';
42
43
    /** @var string */
44
    public $codagente;
45
46
    /** @var string */
47
    public $codgrupo;
48
49
    /** @var string */
50
    public $codtarifa;
51
52
    /** @var string */
53
    public $diaspago;
54
55
    /** @var integer */
56
    public $idcontactoenv;
57
58
    /** @var integer */
59
    public $idcontactofact;
60
61
    /** @var float */
62
    public $riesgoalcanzado;
63
64
    /** @var float */
65
    public $riesgomax;
66
67
    public function checkVies(): bool
68
    {
69
        $codiso = Paises::get($this->getDefaultAddress()->codpais)->codiso ?? '';
70
        return Vies::check($this->cifnif ?? '', $codiso) === 1;
71
    }
72
73
    public function clear()
74
    {
75
        parent::clear();
76
        $this->codretencion = Tools::settings('default', 'codretencion');
77
    }
78
79
    /**
80
     * @param string $query
81
     * @param string $fieldCode
82
     * @param DataBaseWhere[] $where
83
     *
84
     * @return CodeModel[]
85
     */
86
    public function codeModelSearch(string $query, string $fieldCode = '', array $where = []): array
87
    {
88
        $field = empty($fieldCode) ? $this->primaryColumn() : $fieldCode;
89
        $fields = 'cifnif|codcliente|email|nombre|observaciones|razonsocial|telefono1|telefono2';
90
        $where[] = new DataBaseWhere($fields, mb_strtolower($query, 'UTF8'), 'LIKE');
91
        $where[] = new DataBaseWhere('fechabaja', null, 'IS');
92
        return CodeModel::all($this->tableName(), $field, $this->primaryDescriptionColumn(), false, $where);
93
    }
94
95
    /**
96
     * Returns an array with the addresses associated with this customer.
97
     *
98
     * @return DinContacto[]
99
     */
100
    public function getAddresses(): array
101
    {
102
        $contactModel = new DinContacto();
103
        $where = [new DataBaseWhere($this->primaryColumn(), $this->primaryColumnValue())];
104
        return $contactModel->all($where, [], 0, 0);
105
    }
106
107
    /**
108
     * Returns the bank accounts associated with this customer.
109
     *
110
     * @return DinCuentaBancoCliente[]
111
     */
112
    public function getBankAccounts(): array
113
    {
114
        $contactAccounts = new DinCuentaBancoCliente();
115
        $where = [new DataBaseWhere($this->primaryColumn(), $this->primaryColumnValue())];
116
        return $contactAccounts->all($where, [], 0, 0);
117
    }
118
119
    /**
120
     * Return the default billing or shipping address.
121
     *
122
     * @return DinContacto
123
     */
124
    public function getDefaultAddress($type = 'billing'): Contacto
125
    {
126
        $contact = new DinContacto();
127
        $idcontacto = $type === 'shipping' ? $this->idcontactoenv : $this->idcontactofact;
128
        $contact->loadFromCode($idcontacto);
129
        return $contact;
130
    }
131
132
    public function getGroup(): GrupoClientes
133
    {
134
        $group = new DinGrupoClientes();
135
        $group->loadFromCode($this->codgrupo);
136
        return $group;
137
    }
138
139
    /**
140
     * Returns the preferred payment days for this customer.
141
     *
142
     * @return array
143
     */
144
    public function getPaymentDays(): array
145
    {
146
        $days = [];
147
        foreach (explode(',', $this->diaspago . ',') as $str) {
148
            if (is_numeric(trim($str))) {
149
                $days[] = trim($str);
150
            }
151
        }
152
153
        return $days;
154
    }
155
156
    public function getSubcuenta(string $codejercicio, bool $crear): Subcuenta
157
    {
158
        // ya tiene una subcuenta asignada
159
        if ($this->codsubcuenta) {
160
            // buscamos la subcuenta para el ejercicio
161
            $subAccount = new DinSubcuenta();
162
            $where = [
163
                new DataBaseWhere('codsubcuenta', $this->codsubcuenta),
164
                new DataBaseWhere('codejercicio', $codejercicio),
165
            ];
166
            if ($subAccount->loadFromCode('', $where)) {
167
                return $subAccount;
168
            }
169
170
            // no hemos encontrado la subcuenta
171
            // si no queremos crearla, devolvemos una vacía
172
            if (false === $crear) {
173
                return new DinSubcuenta();
174
            }
175
176
            // buscamos la cuenta especial
177
            $special = new DinCuentaEspecial();
178
            if (false === $special->loadFromCode(static::SPECIAL_ACCOUNT)) {
179
                return new DinSubcuenta();
180
            }
181
182
            // ahora creamos la subcuenta
183
            return $special->getCuenta($codejercicio)->createSubcuenta($this->codsubcuenta, $this->razonsocial);
184
        }
185
186
        // ¿El grupo tiene subcuenta?
187
        $group = $this->getGroup();
188
        if ($group->codsubcuenta) {
189
            return $group->getSubcuenta($codejercicio, $crear);
190
        }
191
192
        // si no creamos la subcuenta, devolvemos una vacía
193
        return $crear ?
194
            $this->createSubcuenta($codejercicio) :
195
            new DinSubcuenta();
196
    }
197
198
    public function install(): string
199
    {
200
        // we need exits Contacto before, but we can't check it because it would create a cyclic check
201
        // we need to check Agente and GrupoClientes models before
202
        new Agente();
203
        new GrupoClientes();
204
205
        return parent::install();
206
    }
207
208
    public static function primaryColumn(): string
209
    {
210
        return 'codcliente';
211
    }
212
213
    public function primaryDescriptionColumn(): string
214
    {
215
        return 'nombre';
216
    }
217
218
    public static function tableName(): string
219
    {
220
        return 'clientes';
221
    }
222
223
    public function test(): bool
224
    {
225
        if (empty($this->nombre)) {
226
            Tools::log()->warning(
227
                'field-can-not-be-null',
228
                ['%fieldName%' => 'nombre', '%tableName%' => static::tableName()]
229
            );
230
            return false;
231
        }
232
233
        if (!empty($this->codcliente) && 1 !== preg_match('/^[A-Z0-9_\+\.\-]{1,10}$/i', $this->codcliente)) {
234
            Tools::log()->error(
235
                'invalid-alphanumeric-code',
236
                ['%value%' => $this->codcliente, '%column%' => 'codcliente', '%min%' => '1', '%max%' => '10']
237
            );
238
            return false;
239
        }
240
241
        // we validate the days of payment
242
        $arrayDias = [];
243
        foreach (str_getcsv($this->diaspago ?? '') as $day) {
244
            if ((int)$day >= 1 && (int)$day <= 31) {
245
                $arrayDias[] = (int)$day;
246
            }
247
        }
248
        $this->diaspago = empty($arrayDias) ? null : implode(',', $arrayDias);
249
        return parent::test();
250
    }
251
252
    protected function createSubcuenta(string $codejercicio): Subcuenta
253
    {
254
        // buscamos la cuenta especial
255
        $special = new DinCuentaEspecial();
256
        if (false === $special->loadFromCode(static::SPECIAL_ACCOUNT)) {
257
            return new DinSubcuenta();
258
        }
259
260
        // buscamos la cuenta
261
        $cuenta = $special->getCuenta($codejercicio);
262
        if (empty($cuenta->codcuenta)) {
263
            return new DinSubcuenta();
264
        }
265
266
        // obtenemos un código de subcuenta libre
267
        $code = $cuenta->getFreeSubjectAccountCode($this);
268
        if (empty($code)) {
269
            return new DinSubcuenta();
270
        }
271
272
        // creamos la subcuenta
273
        $subAccount = $cuenta->createSubcuenta($code, $this->razonsocial);
274
        if (false === $subAccount->save()) {
275
            return new DinSubcuenta();
276
        }
277
278
        // guardamos el código de subcuenta
279
        $this->codsubcuenta = $subAccount->codsubcuenta;
280
        $this->save();
281
282
        return $subAccount;
283
    }
284
285
    protected function saveInsert(array $values = []): bool
286
    {
287
        if (empty($this->codcliente)) {
288
            $this->codcliente = (string)$this->newCode();
289
        }
290
291
        $return = parent::saveInsert($values);
292
        if ($return && empty($this->idcontactofact)) {
293
            $parts = explode(' ', $this->nombre);
294
295
            // creates new contact
296
            $contact = new DinContacto();
297
            $contact->apellidos = count($parts) > 1 ? implode(' ', array_slice($parts, 1)) : '';
298
            $contact->cifnif = $this->cifnif;
299
            $contact->codagente = $this->codagente;
300
            $contact->codcliente = $this->codcliente;
301
            $contact->descripcion = $this->nombre;
302
            $contact->email = $this->email;
303
            $contact->empresa = $this->razonsocial;
304
            $contact->fax = $this->fax;
305
            $contact->nombre = $parts[0];
306
            $contact->personafisica = $this->personafisica;
307
            $contact->telefono1 = $this->telefono1;
308
            $contact->telefono2 = $this->telefono2;
309
            $contact->tipoidfiscal = $this->tipoidfiscal;
310
            if ($contact->save()) {
311
                $this->idcontactofact = $contact->idcontacto;
312
                return $this->save();
313
            }
314
        }
315
316
        return $return;
317
    }
318
319
    /**
320
     * Devuelve las settings de la empresa
321
     *
322
     * @param string $idCompany
323
     * @return array
324
     */
325
    public function getSettings(string $idCompany)
326
    {
327
        $settingsModel = new SettingsModel();
328
        $settingsModel->loadFromCode('', [
329
            new DataBaseWhere('classnamemodel', static::class),
330
            new DataBaseWhere('idmodel', $this->primaryColumnValue()),
331
            new DataBaseWhere('idempresa', $idCompany),
332
        ]);
333
334
        return $settingsModel->settings ?? [];
335
    }
336
}
337