Skip to content

Commit 5b3a045

Browse files
NeoRazorXclaude
andcommitted
Empresa obligatoria en proveedores, ajustes de UI y fix de duplicados
- ReportSuppliers: empresa obligatoria (Empresas::default por defecto, Empresas::all cacheado), eliminados los condicionales 'all' y la tarjeta "Con deuda" enlaza a la sección de acreedores. - Cards con shadow-sm y etiquetas reducidas (total, with-debt, new-30-days) compartidas entre clientes, proveedores y contactos. - Corregido el desajuste entre el KPI "con deuda" y el bloque de deudores/acreedores: agrupación solo por codcliente/codproveedor usando MAX(nombre) como representante para evitar filas duplicadas cuando un mismo cliente/proveedor aparece con variantes en el nombre. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent de4d818 commit 5b3a045

31 files changed

Lines changed: 267 additions & 175 deletions

Controller/ReportCustomers.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,13 +340,13 @@ protected function getDebtorsSql(int $limit = 0): string
340340
{
341341
$sql = "SELECT "
342342
. "f.codcliente as codcliente, "
343-
. "COALESCE(NULLIF(f.nombrecliente, ''), f.codcliente, '" . Tools::trans('no-data') . "') as xcol, "
343+
. "COALESCE(NULLIF(MAX(f.nombrecliente), ''), f.codcliente, '" . Tools::trans('no-data') . "') as xcol, "
344344
. "SUM(f.total) as ycol "
345345
. "FROM facturascli f "
346346
. "WHERE f.pagada = " . $this->db()->var2str(false)
347347
. " AND f.idempresa = " . $this->db()->var2str((int)$this->idempresa);
348348

349-
$sql .= " GROUP BY f.codcliente, xcol ORDER BY ycol DESC, xcol ASC";
349+
$sql .= " GROUP BY f.codcliente ORDER BY ycol DESC, xcol ASC";
350350
if ($limit > 0) {
351351
$sql .= " LIMIT " . $limit;
352352
}

Controller/ReportSuppliers.php

Lines changed: 48 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
namespace FacturaScripts\Plugins\Informes\Controller;
2121

22+
use FacturaScripts\Core\DataSrc\Empresas;
2223
use FacturaScripts\Core\Template\Controller;
2324
use FacturaScripts\Core\Tools;
2425
use FacturaScripts\Dinamic\Model\Empresa;
@@ -35,7 +36,7 @@ class ReportSuppliers extends Controller
3536
/** @var array todas las empresas a listar en el formulario [idEmpresa => nombre empresa] */
3637
public $companies = [];
3738

38-
/** @var int|string|null el idempresa sugerido por el usuario (puede ser 'all') */
39+
/** @var int empresa seleccionada (obligatoria) */
3940
public $idempresa;
4041

4142
/** @var int Total de proveedores */
@@ -115,21 +116,15 @@ public function run(): void
115116

116117
protected function loadCompanies(): void
117118
{
118-
$this->companies = ['all' => Tools::trans('all-companies')];
119-
foreach (Empresa::all() as $company) {
119+
foreach (Empresas::all() as $company) {
120120
$this->companies[$company->idempresa] = $company->nombrecorto;
121121
}
122-
// empresa seleccionada
123-
$this->idempresa = $this->request()->queryOrInput('idempresa', null);
124-
if (null === $this->idempresa) {
125-
// seleccionar todas por defecto si no hay nada
126-
$this->idempresa = 'all';
127-
} elseif ($this->idempresa === 'all') {
128-
// seleccionar todas
129-
$this->idempresa = 'all';
130-
} else {
131-
// seleccionar sugerida
132-
$this->idempresa = (int)$this->idempresa;
122+
123+
$requested = $this->request()->queryOrInput('idempresa', null);
124+
$this->idempresa = $requested === null ? Empresas::default()->idempresa : (int)$requested;
125+
126+
if (!isset($this->companies[$this->idempresa])) {
127+
$this->idempresa = Empresas::default()->idempresa;
133128
}
134129
}
135130

@@ -138,11 +133,9 @@ protected function loadData(): void
138133
$this->currentYear = date('Y');
139134
$this->companyCountryCode = Tools::settings('default', 'codpais');
140135

141-
if ($this->idempresa !== 'all') {
142-
$company = new Empresa();
143-
if ($company->load($this->idempresa) && !empty($company->codpais)) {
144-
$this->companyCountryCode = $company->codpais;
145-
}
136+
$company = new Empresa();
137+
if ($company->load($this->idempresa) && !empty($company->codpais)) {
138+
$this->companyCountryCode = $company->codpais;
146139
}
147140

148141
$country = new Pais();
@@ -152,10 +145,8 @@ protected function loadData(): void
152145
$this->companyCountry = $this->companyCountryCode;
153146
}
154147

155-
if ($this->idempresa !== 'all') {
156-
$this->whereEmpresaFacturasProv = " AND idempresa = " . $this->idempresa;
157-
$this->whereEmpresaProveedores = " WHERE codproveedor IN (SELECT codproveedor FROM facturasprov WHERE idempresa = " . $this->idempresa . ")";
158-
}
148+
$this->whereEmpresaFacturasProv = " AND idempresa = " . (int)$this->idempresa;
149+
$this->whereEmpresaProveedores = " WHERE codproveedor IN (SELECT codproveedor FROM facturasprov WHERE idempresa = " . (int)$this->idempresa . ")";
159150
}
160151

161152
protected function loadTotalSuppliers(): void
@@ -179,22 +170,15 @@ protected function loadActiveSupplierYear(): void
179170

180171
protected function loadInactiveSupplier(): void
181172
{
182-
$sqlInactive = "SELECT COUNT(*) as total FROM proveedores";
183-
if ($this->idempresa !== 'all') {
184-
$sqlInactive .= " WHERE debaja = true AND codproveedor IN (SELECT codproveedor FROM facturasprov WHERE idempresa = " . $this->idempresa . ")";
185-
} else {
186-
$sqlInactive .= " WHERE debaja = true";
187-
}
173+
$sqlInactive = "SELECT COUNT(*) as total FROM proveedores WHERE debaja = true"
174+
. " AND codproveedor IN (SELECT codproveedor FROM facturasprov WHERE idempresa = " . (int)$this->idempresa . ")";
188175
$this->inactiveSuppliers = $this->db()->select($sqlInactive)[0]['total'];
189176
}
190177

191178
protected function loadNewSuppliers30Days(): void
192179
{
193-
$sql = "SELECT COUNT(*) as total FROM proveedores WHERE fechaalta >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)";
194-
195-
if ($this->idempresa !== 'all') {
196-
$sql .= " AND codproveedor IN (SELECT codproveedor FROM facturasprov WHERE idempresa = " . (int)$this->idempresa . ")";
197-
}
180+
$sql = "SELECT COUNT(*) as total FROM proveedores WHERE fechaalta >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)"
181+
. " AND codproveedor IN (SELECT codproveedor FROM facturasprov WHERE idempresa = " . (int)$this->idempresa . ")";
198182
$this->newSuppliers30Days = (int)$this->db()->select($sql)[0]['total'];
199183
}
200184

@@ -211,15 +195,12 @@ protected function loadNewSuppliersByMonth(): void
211195
$report->addCustomFilter('fechaalta', '>=', '{-1 year}');
212196
$report->addCustomFilter('fechaalta', '<=', '{today}');
213197

214-
// aplicamos el filtro de empresa si no se están mostrando todas
215-
if ($this->idempresa !== 'all') {
216-
Report::activateAdvancedReport(true);
217-
$report->addCustomFilter(
218-
'codproveedor',
219-
'IN',
220-
'SELECT codproveedor FROM facturasprov WHERE idempresa = ' . (int)$this->idempresa
221-
);
222-
}
198+
Report::activateAdvancedReport(true);
199+
$report->addCustomFilter(
200+
'codproveedor',
201+
'IN',
202+
'SELECT codproveedor FROM facturasprov WHERE idempresa = ' . (int)$this->idempresa
203+
);
223204

224205
$this->charts['reportTest'] = $report;
225206
}
@@ -235,28 +216,24 @@ protected function loadNewSuppliersByYear(): void
235216
$report->yoperation = 'COUNT';
236217
$report->addFieldXName('');
237218

238-
if ($this->idempresa !== 'all') {
239-
Report::activateAdvancedReport(true);
240-
$report->addCustomFilter(
241-
'codproveedor',
242-
'IN',
243-
'SELECT codproveedor FROM facturasprov WHERE idempresa = ' . (int)$this->idempresa
244-
);
245-
}
219+
Report::activateAdvancedReport(true);
220+
$report->addCustomFilter(
221+
'codproveedor',
222+
'IN',
223+
'SELECT codproveedor FROM facturasprov WHERE idempresa = ' . (int)$this->idempresa
224+
);
246225

247226
$this->charts['newSuppliersByYear'] = $report;
248227
}
249228

250229
protected function loadSuppliersByCountry(): void
251230
{
252-
$sqlCountries = "SELECT c.codpais, p.codiso, p.nombre, COUNT(*) as total
253-
FROM proveedores pv
254-
LEFT JOIN contactos c ON pv.idcontacto = c.idcontacto
255-
LEFT JOIN paises p ON c.codpais = p.codpais";
256-
if ($this->idempresa !== 'all') {
257-
$sqlCountries .= " WHERE pv.codproveedor IN (SELECT codproveedor FROM facturasprov WHERE idempresa = " . $this->idempresa . ")";
258-
}
259-
$sqlCountries .= " GROUP BY c.codpais, p.codiso, p.nombre ORDER BY total DESC";
231+
$sqlCountries = "SELECT c.codpais, p.codiso, p.nombre, COUNT(*) as total
232+
FROM proveedores pv
233+
LEFT JOIN contactos c ON pv.idcontacto = c.idcontacto
234+
LEFT JOIN paises p ON c.codpais = p.codpais
235+
WHERE pv.codproveedor IN (SELECT codproveedor FROM facturasprov WHERE idempresa = " . (int)$this->idempresa . ")
236+
GROUP BY c.codpais, p.codiso, p.nombre ORDER BY total DESC";
260237
$this->suppliersByCountry = $this->db()->select($sqlCountries);
261238
}
262239

@@ -276,14 +253,11 @@ protected function loadSuppliersByProvince(): void
276253
// filtramos por el país de la empresa para mostrar solo provincias del país
277254
$report->addCustomFilter('c.codpais', '=', $this->companyCountryCode);
278255

279-
// aplicamos el filtro de empresa si no se están mostrando todas
280-
if ($this->idempresa !== 'all') {
281-
$report->addCustomFilter(
282-
'pv.codproveedor',
283-
'IN',
284-
'SELECT codproveedor FROM facturasprov WHERE idempresa = ' . (int)$this->idempresa
285-
);
286-
}
256+
$report->addCustomFilter(
257+
'pv.codproveedor',
258+
'IN',
259+
'SELECT codproveedor FROM facturasprov WHERE idempresa = ' . (int)$this->idempresa
260+
);
287261

288262
$this->charts['suppliersByProvince'] = $report;
289263
}
@@ -302,21 +276,15 @@ protected function loadInvoicesByProvince(): void
302276
$report->addCustomJoin('LEFT JOIN proveedores pv ON f.codproveedor = pv.codproveedor');
303277
$report->addCustomJoin('LEFT JOIN contactos c ON pv.idcontacto = c.idcontacto');
304278

305-
// aplicamos el filtro de empresa si no se están mostrando todas
306-
if ($this->idempresa !== 'all') {
307-
$report->addCustomFilter('f.idempresa', '=', (int)$this->idempresa);
308-
}
279+
$report->addCustomFilter('f.idempresa', '=', (int)$this->idempresa);
309280

310281
$this->charts['invoicesByProvince'] = $report;
311282
}
312283

313284
protected function loadSuppliersWithPayables(): void
314285
{
315-
$sql = "SELECT COUNT(DISTINCT codproveedor) as total FROM facturasprov WHERE pagada = " . $this->db()->var2str(false);
316-
317-
if ($this->idempresa !== 'all') {
318-
$sql .= " AND idempresa = " . $this->db()->var2str((int)$this->idempresa);
319-
}
286+
$sql = "SELECT COUNT(DISTINCT codproveedor) as total FROM facturasprov WHERE pagada = " . $this->db()->var2str(false)
287+
. " AND idempresa = " . $this->db()->var2str((int)$this->idempresa);
320288

321289
$this->suppliersWithPayables = (int)$this->db()->select($sql)[0]['total'];
322290
}
@@ -355,16 +323,13 @@ protected function getCreditorsSql(int $limit = 0): string
355323
{
356324
$sql = "SELECT "
357325
. "f.codproveedor as codproveedor, "
358-
. "COALESCE(NULLIF(f.nombre, ''), f.codproveedor, '" . Tools::trans('no-data') . "') as xcol, "
326+
. "COALESCE(NULLIF(MAX(f.nombre), ''), f.codproveedor, '" . Tools::trans('no-data') . "') as xcol, "
359327
. "SUM(f.total) as ycol "
360328
. "FROM facturasprov f "
361-
. "WHERE f.pagada = " . $this->db()->var2str(false);
362-
363-
if ($this->idempresa !== 'all') {
364-
$sql .= " AND f.idempresa = " . $this->db()->var2str((int)$this->idempresa);
365-
}
329+
. "WHERE f.pagada = " . $this->db()->var2str(false)
330+
. " AND f.idempresa = " . $this->db()->var2str((int)$this->idempresa);
366331

367-
$sql .= " GROUP BY f.codproveedor, xcol ORDER BY ycol DESC, xcol ASC";
332+
$sql .= " GROUP BY f.codproveedor ORDER BY ycol DESC, xcol ASC";
368333
if ($limit > 0) {
369334
$sql .= " LIMIT " . $limit;
370335
}

Translation/ca_ES.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"active-customers": "Clients actius",
33
"active-customers-year": "Clients actius aquest any",
4+
"active-suppliers": "Proveedores activos",
5+
"active-suppliers-year": "Proyeedores activos este año",
46
"active-year": "Actius aquest any",
57
"amortization-intangible-assets": "Amortitzacions immobilitzat intangible",
68
"amortization-intangible-material": "Amortitzacions immobilitzat material",
@@ -67,6 +69,7 @@
6769
"group-by-months": "Agrupar per mesos",
6870
"has-a-value": "Té valor",
6971
"inactive-customers": "Clients donats de baixa",
72+
"inactive-suppliers": "Inactivos",
7073
"income-book": "Llibre d'ingressos",
7174
"income-book-description": "Registra totes les factures emeses",
7275
"input-tax": "IVA suportat",
@@ -80,6 +83,8 @@
8083
"monthly-average": "Mitjana mensual",
8184
"negative": "Negatiu",
8285
"negative-results-other-exercises": "Resultat negatiu altres exercicis",
86+
"new-30-days": "Nuevos 30 días",
87+
"new-suppliers": "Nuevos proveedores",
8388
"no-family": "Sense família",
8489
"opening": "Obertura",
8590
"passed-tax": "IVA repercutit",
@@ -252,6 +257,7 @@
252257
"treasury": "Tresoreria",
253258
"treemap": "Mapa d'arbre",
254259
"voluntary-reserves": "Reserves voluntàries",
260+
"with-debt": "Con deuda",
255261
"without-opening": "Sense obertura",
256262
"y-operation": "Operació sobre Y"
257263
}

Translation/cs_CZ.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"active-customers": "Aktivní zákazníci",
33
"active-customers-year": "Aktivní zákazníci v tomto roce",
4+
"active-suppliers": "Proveedores activos",
5+
"active-suppliers-year": "Proyeedores activos este año",
46
"active-year": "Aktivní tento rok",
57
"amortization-intangible-assets": "Amortizaciones inmovilizado intangible",
68
"amortization-intangible-material": "Amortizaciones inmovilizado material",
@@ -67,6 +69,7 @@
6769
"group-by-months": "Seskupit podle měsíců",
6870
"has-a-value": "Má hodnotu",
6971
"inactive-customers": "Neaktivní zákazníci",
72+
"inactive-suppliers": "Inactivos",
7073
"income-book": "Kniha příjmů",
7174
"income-book-description": "Zaznamenává všechny vystavené faktury",
7275
"input-tax": "IVA soportado",
@@ -80,6 +83,8 @@
8083
"monthly-average": "Media mensual",
8184
"negative": "Negativní",
8285
"negative-results-other-exercises": "Resultado negativo otros ejercicios",
86+
"new-30-days": "Nuevos 30 días",
87+
"new-suppliers": "Nuevos proveedores",
8388
"no-family": "Sin familia",
8489
"opening": "Otevření",
8590
"passed-tax": "IVA repercutido",
@@ -252,6 +257,7 @@
252257
"treasury": "Tesorería",
253258
"treemap": "Mapa stromu",
254259
"voluntary-reserves": "Reservas voluntarias",
260+
"with-debt": "Con deuda",
255261
"without-opening": "Bez otevření",
256262
"y-operation": "Operace na Y."
257263
}

Translation/de_DE.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"active-customers": "Aktive Kunden",
33
"active-customers-year": "Aktive Kunden in diesem Jahr",
4+
"active-suppliers": "Proveedores activos",
5+
"active-suppliers-year": "Proyeedores activos este año",
46
"active-year": "Aktiv in diesem Jahr",
57
"amortization-intangible-assets": "Abschreibungen auf immaterielle Vermögenswerte",
68
"amortization-intangible-material": "Abschreibungen auf materielle Anlagen",
@@ -67,6 +69,7 @@
6769
"group-by-months": "Nach Monaten gruppieren",
6870
"has-a-value": "Hat einen Wert",
6971
"inactive-customers": "Kunden haben sich abgemeldet",
72+
"inactive-suppliers": "Inactivos",
7073
"income-book": "Einnahmenbuch",
7174
"income-book-description": "Erfasst alle ausgestellten Rechnungen",
7275
"input-tax": "Eingangssteuer",
@@ -80,6 +83,8 @@
8083
"monthly-average": "Monatsdurchschnitt",
8184
"negative": "Negativ",
8285
"negative-results-other-exercises": "Negatives Ergebnis aus anderen Übungen",
86+
"new-30-days": "Nuevos 30 días",
87+
"new-suppliers": "Nuevos proveedores",
8388
"no-family": "Ohne Familie",
8489
"opening": "Eröffnung",
8590
"passed-tax": "Umsatzsteuer",
@@ -252,6 +257,7 @@
252257
"treasury": "Schatzamt",
253258
"treemap": "Baumkarte",
254259
"voluntary-reserves": "Freiwillige Rücklagen",
260+
"with-debt": "Con deuda",
255261
"without-opening": "Ohne Eröffnung",
256262
"y-operation": "Operation über Y"
257263
}

Translation/en_EN.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"active-customers": "Active customers",
33
"active-customers-year": "Active customers this year",
4+
"active-suppliers": "Proveedores activos",
5+
"active-suppliers-year": "Proyeedores activos este año",
46
"active-year": "Active this year",
57
"amortization-intangible-assets": "Amortization of intangible assets",
68
"amortization-intangible-material": "Amortization of intangible material",
@@ -67,6 +69,7 @@
6769
"group-by-months": "Group by months",
6870
"has-a-value": "Has a value",
6971
"inactive-customers": "Inactive customers",
72+
"inactive-suppliers": "Inactivos",
7073
"income-book": "Income ledger",
7174
"income-book-description": "Registers all issued invoices",
7275
"input-tax": "Input VAT",
@@ -80,6 +83,8 @@
8083
"monthly-average": "Monthly average",
8184
"negative": "Negative",
8285
"negative-results-other-exercises": "Negative result other years exercises",
86+
"new-30-days": "Nuevos 30 días",
87+
"new-suppliers": "Nuevos proveedores",
8388
"no-family": "No family",
8489
"opening": "Opening",
8590
"passed-tax": "Output VAT",
@@ -252,6 +257,7 @@
252257
"treasury": "Treasury",
253258
"treemap": "Tree map",
254259
"voluntary-reserves": "Voluntary reserves",
260+
"with-debt": "Con deuda",
255261
"without-opening": "Without opening",
256262
"y-operation": "Y operation"
257263
}

0 commit comments

Comments
 (0)