untitled

Pasted Nov 9, 2026, 7:32 PM1 file119 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/zzgs8w76ytbdapp1
untitled
 @Transaction
    suspend fun registrarVentaCompleta(
        venta: VentaEntity,
        detalles: List<DetalleVentaEntity>,
        pagos: List<PagoVentaEntity>,
        movimientos: List<MovimientoInventarioEntity>,
        descontarInventario: Boolean
    ) {
        check(venta.estadoEntrega != "PENDIENTE_ENTREGA") {
            "Un pedido debe pasar por el proceso de reserva antes de quedar pendiente de entrega."
        }

        check(detalles.isNotEmpty()) {
            "La venta debe tener al menos un producto."
        }

        check(detalles.all {
            it.ventaId == venta.id && it.cantidad > 0
        }) {
            "Hay productos con cantidades incorrectas."
        }
        check(descontarInventario == (venta.estadoEntrega == "ENTREGADA")) {
            "El estado de entrega no coincide con la operación de inventario."
        }

        if (descontarInventario) {

            val asignaciones = mutableListOf<LoteVentaEntity>()

            for (detalle in detalles) {

                // Descontar del inventario general
                val resultado = descontarExistencias(
                    presentacionId = detalle.presentacionId,
                    sede = venta.sede,
                    cantidad = detalle.cantidad,
                    fecha = System.currentTimeMillis()
                )

                check(resultado == 1) {
                    "No hay existencias suficientes para completar la venta."
                }

                // Buscar los lotes más antiguos de esa presentación y sede
                val lotes = obtenerLotesDisponiblesFIFO(
                    presentacionId = detalle.presentacionId,
                    sede = venta.sede
                )

                var pendiente = detalle.cantidad

                for (lote in lotes) {

                    if (pendiente <= 0) break

                    val cantidadTomada = minOf(
                        pendiente,
                        lote.cantidadDisponible
                    )

                    val actualizado = descontarCantidadLote(
                        loteInventarioId = lote.id,
                        cantidad = cantidadTomada
                    )

                    check(actualizado == 1) {
                        "No se pudo descontar una cantidad del lote."
                    }

                    asignaciones.add(
                        LoteVentaEntity(
                            id = UUID.randomUUID().toString(),
                            ventaId = venta.id,
                            detalleVentaId = detalle.id,
                            loteInventarioId = lote.id,
                            cantidad = cantidadTomada,
                            estado = "VENDIDA"
                        )
                    )

                    pendiente -= cantidadTomada
                }

                check(pendiente == 0) {
                    "No hay existencias suficientes en los lotes de esta sede."
                }
            }

            if (asignaciones.isNotEmpty()) {
                guardarAsignacionesLoteVenta(asignaciones)
            }
        }


        guardarVenta(venta)
        guardarDetallesVenta(detalles)

        if (pagos.isNotEmpty()) {
            guardarPagosVenta(pagos)
        }

        if (descontarInventario && movimientos.isNotEmpty()) {
            guardarMovimientosVenta(movimientos)
        }
    }

    // CONSULTAR DETALLES DE UN PEDIDO

    @Query("""
        SELECT * FROM detalles_venta
        WHERE ventaId = :ventaId
    """)
    suspend fun buscarDetallesVenta(
        ventaId: String
    ): List<DetalleVentaEntity>


    // CAMBIAR ESTADO DE UN PEDIDO

3,690 chars · codepastes.com