@@ -98,7 +98,7 @@ public function generate(int $idcompany, string $dateFrom, string $dateTo, array
9898 }
9999
100100 $ saldo = $ debe - $ haber ;
101- if ($ level > 0 && strlen ($ account ->codcuenta ) > $ level ) {
101+ if ($ level > 0 && $ level <= 4 && strlen ($ account ->codcuenta ) > $ level ) {
102102 continue ;
103103 }
104104
@@ -116,14 +116,32 @@ public function generate(int $idcompany, string $dateFrom, string $dateTo, array
116116 }
117117 $ rows [] = $ accountRow ;
118118
119- if ($ level > 0 ) {
119+ if ($ level > 0 && $ level <= 4 ) {
120120 continue ;
121121 }
122122
123- // añadimos las líneas de las subcuentas y recalculamos debe y haber para comprobar que cuadran
123+ // añadimos las líneas de las subcuentas y recalculamos debe y haber para comprobar que cuadren
124124 $ debe2 = $ haber2 = 0.00 ;
125- foreach ($ amounts as $ amount ) {
126- if ($ amount ['idcuenta ' ] == $ account ->idcuenta ) {
125+
126+ // filtramos los importes que pertenecen a esta cuenta
127+ $ accountAmounts = array_filter ($ amounts , function ($ amount ) use ($ account ) {
128+ return $ amount ['idcuenta ' ] == $ account ->idcuenta ;
129+ });
130+
131+ // si hay nivel intermedio, agrupamos las subcuentas por prefijo según el nivel indicado
132+ if ($ level > 0 && $ level < $ this ->exercise ->longsubcuenta ) {
133+ $ groupedAmounts = $ this ->groupAmountsByLevel ($ level , $ accountAmounts , $ openingAmounts );
134+ foreach ($ groupedAmounts as $ groupedAmount ) {
135+ $ rows [] = $ groupedAmount ;
136+ $ debe2 += (float )$ groupedAmount ['_debe_raw ' ];
137+ $ haber2 += (float )$ groupedAmount ['_haber_raw ' ];
138+ }
139+ } else {
140+ foreach ($ accountAmounts as $ amount ) {
141+ if ($ level > 4 && strlen ($ amount ['codsubcuenta ' ]) > $ level ) {
142+ continue ;
143+ }
144+
127145 $ rows [] = $ this ->processAmountLine ($ subaccounts , $ amount , $ openingAmounts );
128146 $ debe2 += (float )$ amount ['debe ' ];
129147 $ haber2 += (float )$ amount ['haber ' ];
@@ -377,12 +395,77 @@ protected function getOpeningData(array $params = []): array
377395 }
378396
379397 /**
380- * @param Subcuenta[] $subaccounts
381- * @param array $amount
382- * @param array $openingAmounts partidas de apertura indexadas por codsubcuenta
398+ * Agrupa los importes de subcuentas por prefijo según el nivel indicado y devuelve
399+ * las filas ya formateadas. Cada fila incluye las claves internas '_debe_raw' y '_haber_raw'
400+ * con los valores numéricos para poder acumular los totales en el método llamante.
383401 *
384- * @return array
402+ * Ejemplo con level=5 y subcuenta 4300000000:
403+ * - El prefijo sería '43000' y se sumarían 4300000001, 4300000002, 4300000034, 4300004396.
404+ * Ejemplo con level=8 y subcuenta 4300000000:
405+ * - El prefijo '43000000' acumula 4300000001 y 4300000002.
406+ * - El prefijo '43000003' acumula 4300000034.
407+ * - El prefijo '43000439' acumula 4300004396.
385408 */
409+ protected function groupAmountsByLevel (int $ level , array $ accountAmounts , array $ openingAmounts = []): array
410+ {
411+ // agrupamos los importes por el prefijo de longitud $level
412+ $ groups = [];
413+ foreach ($ accountAmounts as $ amount ) {
414+ $ prefix = substr ($ amount ['codsubcuenta ' ], 0 , $ level );
415+ if (!isset ($ groups [$ prefix ])) {
416+ $ groups [$ prefix ] = [
417+ 'prefix ' => $ prefix ,
418+ 'debe ' => 0.00 ,
419+ 'haber ' => 0.00 ,
420+ 'opening ' => null ,
421+ ];
422+ }
423+ $ groups [$ prefix ]['debe ' ] += (float )$ amount ['debe ' ];
424+ $ groups [$ prefix ]['haber ' ] += (float )$ amount ['haber ' ];
425+
426+ // acumulamos el saldo de apertura si está activo
427+ if ($ this ->showBalanceOpening ) {
428+ $ codsubcuenta = $ amount ['codsubcuenta ' ];
429+ if (isset ($ openingAmounts [$ codsubcuenta ])) {
430+ $ openingSaldo = $ openingAmounts [$ codsubcuenta ]['debe ' ] - $ openingAmounts [$ codsubcuenta ]['haber ' ];
431+ } else {
432+ $ openingSaldo = 0.00 ;
433+ }
434+ if ($ groups [$ prefix ]['opening ' ] === null ) {
435+ $ groups [$ prefix ]['opening ' ] = 0.00 ;
436+ }
437+ $ groups [$ prefix ]['opening ' ] += $ openingSaldo ;
438+ }
439+ }
440+
441+ // construimos las filas formateadas
442+ $ rows = [];
443+ foreach ($ groups as $ group ) {
444+ $ debe = $ group ['debe ' ];
445+ $ haber = $ group ['haber ' ];
446+ $ saldo = $ debe - $ haber ;
447+
448+ $ row = [
449+ 'cuenta ' => $ group ['prefix ' ],
450+ 'descripcion ' => $ this ->formatValue ($ group ['prefix ' ], 'text ' ),
451+ 'debe ' => $ this ->formatValue ((string )$ debe ),
452+ 'haber ' => $ this ->formatValue ((string )$ haber ),
453+ 'saldo ' => $ this ->formatValue ((string )$ saldo ),
454+ // valores raw para acumular totales en el método llamante
455+ '_debe_raw ' => $ debe ,
456+ '_haber_raw ' => $ haber ,
457+ ];
458+
459+ if ($ group ['opening ' ] !== null ) {
460+ $ row ['opening ' ] = $ this ->formatValue ((string )$ group ['opening ' ]);
461+ }
462+
463+ $ rows [] = $ row ;
464+ }
465+
466+ return $ rows ;
467+ }
468+
386469 protected function processAmountLine (array $ subaccounts , array $ amount , array $ openingAmounts = []): array
387470 {
388471 $ debe = (float )$ amount ['debe ' ];
0 commit comments