untitled

Pasted Nov 9, 2026, 6:50 AM1 file379 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgs99k8413f0pan
untitled
package com.negocio.desinfectantes.ui.produccion

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.negocio.desinfectantes.data.*
import java.text.NumberFormat
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

private val LoteNavy = Color(0xFF101D35)
private val LoteCardBlue = Color(0xFF1B2D4A)
private val LoteAccentBlue = Color(0xFF2585F5)
private val LoteSoftBlue = Color(0xFFA9BEDB)
private val LoteWhite = Color(0xFFFFFFFF)

@Composable
fun HistorialLotesScreen(
    modifier: Modifier = Modifier,
    lotes: List<LoteProduccionEntity>,
    detalles: List<LoteDetalleEntity>,
    gastos: List<LoteGastoEntity>,
    inventariosLote: List<LoteInventarioEntity>,
    ingresosPorLoteYSede: List<IngresoLoteSedeResultado> = emptyList(),
    productos: List<ProductoEntity>,
    aromas: List<AromaEntity>,
    presentaciones: List<PresentacionEntity>,
    onVolver: () -> Unit
) {
    val formatoFecha = SimpleDateFormat(
        "dd/MM/yyyy • hh:mm a",
        Locale("es", "CO")
    )

    val formatoPesos = NumberFormat.getCurrencyInstance(
        Locale("es", "CO")
    ).apply {
        maximumFractionDigits = 0
        minimumFractionDigits = 0
    }

    Column(
        modifier = modifier
            .fillMaxSize()
            .background(LoteNavy)
            .verticalScroll(rememberScrollState())
            .padding(20.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        TextButton(onClick = onVolver) {
            Text("← Volver", color = LoteSoftBlue)
        }

        Text(
            "Historial de lotes",
            color = LoteWhite,
            style = MaterialTheme.typography.headlineMedium,
            fontWeight = FontWeight.Bold
        )

        Text(
            "Consulta las producciones y sus gastos registrados.",
            color = LoteSoftBlue
        )

        if (lotes.isEmpty()) {
            Card(
                modifier = Modifier.fillMaxWidth(),
                colors = CardDefaults.cardColors(
                    containerColor = LoteCardBlue
                ),
                shape = RoundedCornerShape(16.dp)
            ) {
                Column(
                    modifier = Modifier.padding(20.dp),
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    Text(
                        "Todavía no hay lotes registrados",
                        color = LoteWhite,
                        fontWeight = FontWeight.Bold
                    )
                    Text(
                        "Cuando registres una producción, aparecerá aquí.",
                        color = LoteSoftBlue
                    )
                }
            }
        }

        lotes.forEach { lote ->
            val producto = productos.firstOrNull {
                it.id == lote.productoId
            }

            val aroma = aromas.firstOrNull {
                it.id == lote.aromaId
            }

            val detallesLote = detalles.filter {
                it.loteId == lote.id
            }

            val gastosLote = gastos.filter {
                it.loteId == lote.id
            }

            val inventarios = inventariosLote.filter {
                it.loteId == lote.id
            }

            val totalUnidades = detallesLote.sumOf {
                it.cantidadFabricada
            }

            val totalGastos = gastosLote.sumOf {
                it.monto
            }

            val ingresosLote = ingresosPorLoteYSede.filter {
                it.loteId == lote.id
            }

            val ingresosBarrancas = ingresosLote
                .filter { it.sede.equals("Barrancas", ignoreCase = true) }
                .sumOf { it.ingresos }

            val ingresosValledupar = ingresosLote
                .filter { it.sede.equals("Valledupar", ignoreCase = true) }
                .sumOf { it.ingresos }

            val ingresosTotales = ingresosBarrancas + ingresosValledupar

            val gananciaLote = ingresosTotales - totalGastos

            Card(
                modifier = Modifier.fillMaxWidth(),
                colors = CardDefaults.cardColors(
                    containerColor = LoteCardBlue
                ),
                shape = RoundedCornerShape(18.dp)
            ) {
                Column(
                    modifier = Modifier.padding(16.dp),
                    verticalArrangement = Arrangement.spacedBy(12.dp)
                ) {
                    Text(
                        lote.numeroLote,
                        color = LoteAccentBlue,
                        style = MaterialTheme.typography.titleMedium,
                        fontWeight = FontWeight.Bold
                    )
                    Text(
                        producto?.nombre ?: "Producto no encontrado",
                        color = LoteWhite,
                        style = MaterialTheme.typography.titleLarge,
                        fontWeight = FontWeight.Bold
                    )

                    Text(
                        "Aroma: ${aroma?.nombre ?: "No encontrado"}",
                        color = LoteSoftBlue
                    )

                    Text(
                        "Fecha: ${formatoFecha.format(Date(lote.fechaCreacion))}",
                        color = LoteSoftBlue
                    )

                    HorizontalDivider(color = Color(0xFF40536F))

                    Text(
                        "Producción",
                        color = LoteAccentBlue,
                        fontWeight = FontWeight.Bold
                    )

                    detallesLote.forEach { detalle ->
                        val presentacion = presentaciones.firstOrNull {
                            it.id == detalle.presentacionId
                        }

                        val distribuciones = inventarios.filter {
                            it.presentacionId == detalle.presentacionId
                        }

                        Column(
                            verticalArrangement = Arrangement.spacedBy(5.dp)
                        ) {
                            Text(
                                presentacion?.nombre
                                    ?: "Presentación no encontrada",
                                color = LoteWhite,
                                fontWeight = FontWeight.SemiBold
                            )

                            Text(
                                "${detalle.cantidadFabricada} unidades fabricadas",
                                color = LoteSoftBlue
                            )


                            distribuciones.forEach { distribucion ->
                                Text(
                                    "• ${distribucion.sede}: ${distribucion.cantidadDisponible} unidades disponibles",
                                    color = LoteSoftBlue
                                )

                                if (distribucion.cantidadReservada > 0) {
                                    Text(
                                        "   ${distribucion.cantidadReservada} unidades reservadas",
                                        color = LoteAccentBlue
                                    )
                                }
                            }

                        }
                    }

                    HorizontalDivider(color = Color(0xFF40536F))

                    Text(
                        "Gastos de producción",
                        color = LoteAccentBlue,
                        fontWeight = FontWeight.Bold
                    )

                    if (gastosLote.isEmpty()) {
                        Text(
                            "No se registraron gastos.",
                            color = LoteSoftBlue
                        )
                    } else {
                        gastosLote.forEach { gasto ->
                            Column(
                                verticalArrangement = Arrangement.spacedBy(3.dp)
                            ) {
                                Row(
                                    modifier = Modifier.fillMaxWidth(),
                                    horizontalArrangement = Arrangement.SpaceBetween
                                ) {
                                    Text(
                                        gasto.concepto,
                                        color = LoteWhite,
                                        modifier = Modifier.weight(1f)
                                    )
                                    Text(
                                        formatoPesos.format(gasto.monto),
                                        color = LoteWhite,
                                        fontWeight = FontWeight.SemiBold
                                    )
                                }

                                if (!gasto.observacion.isNullOrBlank()) {
                                    Text(
                                        gasto.observacion,
                                        color = LoteSoftBlue,
                                        style = MaterialTheme.typography.bodySmall
                                    )
                                }
                            }
                        }
                    }

                    HorizontalDivider(color = Color(0xFF40536F))

                    Text(
                        "Rentabilidad del lote",
                        color = LoteAccentBlue,
                        fontWeight = FontWeight.Bold
                    )

                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Text("Ingresos Barrancas", color = LoteSoftBlue)
                        Text(
                            formatoPesos.format(ingresosBarrancas),
                            color = LoteWhite
                        )
                    }

                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Text("Ingresos Valledupar", color = LoteSoftBlue)
                        Text(
                            formatoPesos.format(ingresosValledupar),
                            color = LoteWhite
                        )
                    }

                    HorizontalDivider(color = Color(0xFF40536F))

                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Text(
                            "Ingresos totales",
                            color = LoteWhite,
                            fontWeight = FontWeight.Bold
                        )
                        Text(
                            formatoPesos.format(ingresosTotales),
                            color = LoteWhite,
                            fontWeight = FontWeight.Bold
                        )
                    }

                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Text(
                            if (gananciaLote >= 0) "Ganancia del lote" else "Pérdida del lote",
                            color = LoteWhite,
                            fontWeight = FontWeight.Bold
                        )
                        Text(
                            formatoPesos.format(gananciaLote),
                            color = if (gananciaLote >= 0) Color(0xFF4ADE80)
                            else Color(0xFFFF6B6B),
                            fontWeight = FontWeight.Bold
                        )
                    }

                    HorizontalDivider(color = Color(0xFF40536F))

                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Text(
                            "Unidades fabricadas",
                            color = LoteSoftBlue
                        )
                        Text(
                            totalUnidades.toString(),
                            color = LoteWhite,
                            fontWeight = FontWeight.Bold
                        )
                    }

                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Text(
                            "Total de gastos",
                            color = LoteSoftBlue
                        )
                        Text(
                            formatoPesos.format(totalGastos),
                            color = LoteWhite,
                            fontWeight = FontWeight.Bold
                        )
                    }
                }
            }
        }

        Spacer(modifier = Modifier.height(20.dp))
    }
}


13,785 chars · codepastes.com