
- Agregar estado 'rejected' al ciclo de vida de la muestra - Crear modelo lims.rejection.reason para gestionar motivos de rechazo - Agregar campos de rechazo en stock.lot (reason, notes, rejected_by, date) - Crear wizard para proceso de rechazo con validaciones - Implementar acción de rechazo con notificaciones - Crear vistas para muestras rechazadas con filtros y búsquedas - Agregar 10 motivos de rechazo predefinidos (hemolizada, coagulada, etc.) - Incluir permisos de seguridad para los nuevos modelos - Agregar menús para gestión de rechazos y muestras rechazadas - Corregir compatibilidad con Odoo 18 en vistas existentes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
140 lines
9.2 KiB
XML
140 lines
9.2 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
<data>
|
|
|
|
<!-- Vista de Lista para Muestras de Laboratorio -->
|
|
<record id="view_lab_sample_list" model="ir.ui.view">
|
|
<field name="name">lab.sample.list</field>
|
|
<field name="model">stock.lot</field>
|
|
<field name="arch" type="xml">
|
|
<list string="Muestras de Laboratorio">
|
|
<field name="name" string="Código"/>
|
|
<field name="patient_id" string="Paciente"/>
|
|
<field name="product_id" string="Tipo de Muestra"/>
|
|
<field name="sample_type_product_id" string="Tipo de Muestra"/>
|
|
<field name="collection_date" string="Fecha de Recolección"/>
|
|
<field name="collector_id" string="Recolectado por"/>
|
|
<field name="container_type" optional="hide" string="Tipo Contenedor (Obsoleto)"/>
|
|
<field name="state" string="Estado" decoration-success="state == 'analyzed'" decoration-info="state == 'in_process'" decoration-danger="state == 'rejected'" decoration-muted="state == 'stored' or state == 'disposed' or state == 'cancelled'" widget="badge"/>
|
|
</list>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- Vista de Formulario para Muestras de Laboratorio -->
|
|
<record id="view_lab_sample_form" model="ir.ui.view">
|
|
<field name="name">lab.sample.form</field>
|
|
<field name="model">stock.lot</field>
|
|
<field name="arch" type="xml">
|
|
<form string="Muestra de Laboratorio">
|
|
<header>
|
|
<button name="action_collect" string="Recolectar" type="object" class="oe_highlight" invisible="state != 'pending_collection'"/>
|
|
<button name="action_receive" string="Recibir" type="object" class="oe_highlight" invisible="state != 'collected'"/>
|
|
<button name="action_start_analysis" string="Iniciar Análisis" type="object" class="oe_highlight" invisible="state != 'received'"/>
|
|
<button name="action_complete_analysis" string="Completar Análisis" type="object" class="oe_highlight" invisible="state != 'in_process'"/>
|
|
<button name="action_store" string="Almacenar" type="object" invisible="state not in ['analyzed', 'in_process', 'received']"/>
|
|
<button name="action_dispose" string="Desechar" type="object" invisible="state == 'disposed'"/>
|
|
<button name="action_open_rejection_wizard"
|
|
string="Rechazar Muestra"
|
|
type="object"
|
|
class="btn-danger"
|
|
invisible="state in ['completed', 'rejected', 'disposed', 'cancelled']"/>
|
|
<button name="action_cancel" string="Cancelar" type="object" invisible="state in ['cancelled', 'rejected', 'disposed']"/>
|
|
<field name="state" widget="statusbar" statusbar_visible="pending_collection,collected,received,in_process,analyzed,stored,rejected"/>
|
|
</header>
|
|
<sheet>
|
|
<div class="oe_title">
|
|
<h1>
|
|
<field name="name"/>
|
|
</h1>
|
|
</div>
|
|
<group>
|
|
<group>
|
|
<field name="patient_id" readonly="state not in ['pending_collection', 'collected']"/>
|
|
<field name="doctor_id" readonly="state not in ['pending_collection', 'collected']"/>
|
|
<field name="origin" readonly="1"/>
|
|
<field name="request_id"
|
|
readonly="state not in ['pending_collection', 'collected']"
|
|
domain="[('is_lab_request', '=', True), '|', ('partner_id', '=', False), ('partner_id', '=', patient_id)]"/>
|
|
<field name="product_id"
|
|
string="Sample Type"
|
|
domain="[('is_sample_type', '=', True)]"
|
|
options="{'no_create': True, 'no_create_edit': True}"
|
|
readonly="state not in ['pending_collection', 'collected']"/>
|
|
</group>
|
|
<group>
|
|
<field name="barcode" readonly="1"/>
|
|
<field name="collection_date" readonly="state not in ['pending_collection', 'collected']"/>
|
|
<field name="collector_id" readonly="state not in ['pending_collection', 'collected']"/>
|
|
<field name="sample_type_product_id"
|
|
readonly="state not in ['pending_collection', 'collected']"
|
|
options="{'no_create': True, 'no_create_edit': True}"/>
|
|
<field name="volume_ml" readonly="1"/>
|
|
<field name="analysis_names" readonly="1"/>
|
|
<field name="container_type"
|
|
readonly="state not in ['pending_collection', 'collected']"
|
|
invisible="sample_type_product_id != False"/>
|
|
</group>
|
|
</group>
|
|
<group string="Información de Rechazo" invisible="state != 'rejected'" col="4">
|
|
<field name="rejection_reason_id" readonly="1"/>
|
|
<field name="rejected_by" readonly="1"/>
|
|
<field name="rejection_date" readonly="1"/>
|
|
<field name="rejection_notes" readonly="1" colspan="4"/>
|
|
</group>
|
|
</sheet>
|
|
</form>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- Search View for Lab Samples -->
|
|
<record id="view_lab_sample_search" model="ir.ui.view">
|
|
<field name="name">lab.sample.search</field>
|
|
<field name="model">stock.lot</field>
|
|
<field name="arch" type="xml">
|
|
<search string="Buscar Muestras">
|
|
<field name="name" string="Código"/>
|
|
<field name="patient_id"/>
|
|
<field name="barcode"/>
|
|
<field name="analysis_names"/>
|
|
<filter string="Pendientes" name="pending" domain="[('state', 'in', ['pending_collection', 'collected', 'received'])]"/>
|
|
<filter string="En Proceso" name="in_process" domain="[('state', '=', 'in_process')]"/>
|
|
<filter string="Analizadas" name="analyzed" domain="[('state', '=', 'analyzed')]"/>
|
|
<filter string="Rechazadas" name="rejected" domain="[('state', '=', 'rejected')]"/>
|
|
<separator/>
|
|
<filter string="Hoy" name="today" domain="[('collection_date', '>=', datetime.datetime.now().strftime('%Y-%m-%d 00:00:00')), ('collection_date', '<=', datetime.datetime.now().strftime('%Y-%m-%d 23:59:59'))]"/>
|
|
<filter string="Esta Semana" name="this_week" domain="[('collection_date', '>=', (datetime.datetime.now() - datetime.timedelta(days=7)).strftime('%Y-%m-%d'))]"/>
|
|
<separator/>
|
|
<filter string="Rechazadas - Alta Severidad" name="rejected_high"
|
|
domain="[('state', '=', 'rejected'), ('rejection_reason_id.severity', 'in', ['high', 'critical'])]"/>
|
|
<group expand="0" string="Agrupar por">
|
|
<filter string="Estado" name="group_state" context="{'group_by': 'state'}"/>
|
|
<filter string="Paciente" name="group_patient" context="{'group_by': 'patient_id'}"/>
|
|
<filter string="Fecha de Recolección" name="group_collection" context="{'group_by': 'collection_date:day'}"/>
|
|
<filter string="Motivo de Rechazo" name="group_rejection" context="{'group_by': 'rejection_reason_id'}"/>
|
|
</group>
|
|
</search>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- Action for Rejected Samples -->
|
|
<record id="action_lab_sample_rejected" model="ir.actions.act_window">
|
|
<field name="name">Muestras Rechazadas</field>
|
|
<field name="res_model">stock.lot</field>
|
|
<field name="view_mode">list,form</field>
|
|
<field name="domain">[('is_lab_sample', '=', True), ('state', '=', 'rejected')]</field>
|
|
<field name="context">{'search_default_rejected': 1, 'default_is_lab_sample': True}</field>
|
|
<field name="search_view_id" ref="view_lab_sample_search"/>
|
|
<field name="help" type="html">
|
|
<p class="o_view_nocontent_smiling_face">
|
|
No hay muestras rechazadas
|
|
</p>
|
|
<p>
|
|
Las muestras rechazadas aparecerán aquí con información
|
|
sobre el motivo del rechazo y las acciones tomadas.
|
|
</p>
|
|
</field>
|
|
</record>
|
|
|
|
</data>
|
|
</odoo>
|