Mejoras integrales: visitas, POS, WACRM, reportes, temas y módulos legacy
- Módulo Visitas completo (auto desde agenda, insumos con descargo de inventario, fotos antes/después y documentos, receta imprimible) - Punto de Venta (catálogo + ticket sticky, cobro con cambio, pago con puntos monedero, ticket imprimible) - WACRM: leads automáticos desde WhatsApp, asignación de conversaciones y leads a agentes, conversión lead→paciente, ficha del paciente en chat - Pacientes: completitud de expediente, alertas clínicas, historial unificado con detalle, foto, WhatsApp, estado de cuenta, filtros rápidos (VIP/recientes/médico), documentos (expediente escaneado + galería) - Agenda: vistas por médico y por hora, filtros rápidos (libres, primera vez, check-in, no-show), modal de acciones, bloqueos por médico, drag&drop para mover citas - Reportes: 18 pestañas (diario, cortes, ingresos, inventario, adeudos, comisiones, pagos, devoluciones, top clientes, horas, paquetes, vendedores, concentrado, recomendaciones, KPIs) con exportación Excel - Temas: nuevo tema Clásico (look legacy AdminLTE) con submenús tipo treeview, selector de tema; accesos rápidos personalizables con 3 presentaciones; búsqueda global; notificaciones reales - Configuración: secciones (clínica, usuarios con permisos por sección, recetas, catálogos de diagnósticos y procedimientos) - Inventario: alertas de caducidad y sugerencia de compra, cron diario que descuenta artículos caducados, compras/bajas - Consultas Médicas, página Expedientes, importadores delta (citas/visitas legacy idempotentes), depuración de duplicados - Infra: tema Tailwind conectado (@config), gzip en nginx, secuencias Odoo corregidas (noupdate, company_id), rollback en validaciones
This commit is contained in:
@@ -55,6 +55,32 @@ class SkeenInventarioItem(models.Model):
|
||||
else:
|
||||
rec.stock_level = 'optimal'
|
||||
|
||||
@api.model
|
||||
def _cron_descontar_caducados(self):
|
||||
"""Descuenta (baja a cero) los artículos caducados con existencias.
|
||||
Corre diario vía ir.cron; la baja queda como movimiento tipo 'baja'."""
|
||||
hoy = fields.Date.today()
|
||||
caducados = self.search([
|
||||
('expiry_date', '!=', False),
|
||||
('expiry_date', '<', hoy),
|
||||
('qty', '>', 0),
|
||||
('active', '=', True),
|
||||
])
|
||||
Move = self.env['skeen.inventario.move'].sudo()
|
||||
for item in caducados:
|
||||
Move.create({
|
||||
'item_id': item.id,
|
||||
'type': 'baja',
|
||||
'qty': item.qty,
|
||||
'reference': 'CADUCIDAD',
|
||||
'notes': f'Descuento automático por caducidad {item.expiry_date}',
|
||||
})
|
||||
if caducados:
|
||||
import logging
|
||||
logging.getLogger(__name__).info(
|
||||
'Inventario: %s artículos caducados descontados', len(caducados))
|
||||
return len(caducados)
|
||||
|
||||
|
||||
class SkeenInventarioMove(models.Model):
|
||||
_name = 'skeen.inventario.move'
|
||||
|
||||
Reference in New Issue
Block a user