feat(#10): Implementar etiquetas de muestras con código de barras
- Crear plantilla QWeb para etiquetas de 100x50mm - Incluir datos del paciente, orden y tipo de muestra - Generar código de barras Code128 usando campo existente - Agregar botón 'Imprimir Etiquetas' en órdenes confirmadas - Formato optimizado para impresoras de etiquetas Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
4d3206f3a1
commit
c74b17554e
|
@ -23,7 +23,8 @@
|
|||
"Bash(find:*)",
|
||||
"Bash(true)",
|
||||
"Bash(bash:*)",
|
||||
"Bash(grep:*)"
|
||||
"Bash(grep:*)",
|
||||
"Bash(gh pr merge:*)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
'views/product_template_parameter_config_views.xml',
|
||||
'views/parameter_dashboard_views.xml',
|
||||
'views/menus.xml',
|
||||
'report/sample_label_report.xml',
|
||||
],
|
||||
'demo': [
|
||||
'demo/z_lims_demo.xml',
|
||||
|
|
|
@ -293,3 +293,16 @@ class SaleOrder(models.Model):
|
|||
_logger.info(f"Cancelled {len(samples_to_cancel)} samples and {len(tests_to_cancel)} tests for order {self.name}")
|
||||
|
||||
return res
|
||||
|
||||
def action_print_sample_labels(self):
|
||||
"""Imprimir etiquetas de todas las muestras generadas para esta orden"""
|
||||
self.ensure_one()
|
||||
|
||||
if not self.generated_sample_ids:
|
||||
raise UserError(_('No hay muestras generadas para esta orden. Por favor, confirme la orden primero.'))
|
||||
|
||||
# Obtener el reporte
|
||||
report = self.env.ref('lims_management.action_report_sample_label')
|
||||
|
||||
# Retornar la acción de imprimir el reporte para todas las muestras
|
||||
return report.report_action(self.generated_sample_ids)
|
||||
|
|
1
lims_management/report/__init__.py
Normal file
1
lims_management/report/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
# -*- coding: utf-8 -*-
|
75
lims_management/report/sample_label_report.xml
Normal file
75
lims_management/report/sample_label_report.xml
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- Definir el reporte -->
|
||||
<record id="action_report_sample_label" model="ir.actions.report">
|
||||
<field name="name">Etiquetas de Muestras</field>
|
||||
<field name="model">stock.lot</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">lims_management.report_sample_label</field>
|
||||
<field name="report_file">lims_management.report_sample_label</field>
|
||||
<field name="print_report_name">'Etiquetas - ' + object.name</field>
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="lims_management.paperformat_sample_label"/>
|
||||
</record>
|
||||
|
||||
<!-- Formato de papel para etiquetas -->
|
||||
<record id="paperformat_sample_label" model="report.paperformat">
|
||||
<field name="name">Formato Etiqueta Muestra</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="format">custom</field>
|
||||
<field name="page_height">50</field>
|
||||
<field name="page_width">100</field>
|
||||
<field name="orientation">Landscape</field>
|
||||
<field name="margin_top">2</field>
|
||||
<field name="margin_bottom">2</field>
|
||||
<field name="margin_left">2</field>
|
||||
<field name="margin_right">2</field>
|
||||
<field name="header_line" eval="False"/>
|
||||
<field name="header_spacing">0</field>
|
||||
<field name="dpi">200</field>
|
||||
</record>
|
||||
|
||||
<!-- Template del reporte -->
|
||||
<template id="report_sample_label">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<div class="page" style="page-break-after: always;">
|
||||
<div style="width: 96mm; height: 46mm; border: 1px solid #ccc; padding: 2mm; font-family: Arial, sans-serif;">
|
||||
<!-- Encabezado -->
|
||||
<div style="text-align: center; margin-bottom: 2mm;">
|
||||
<h4 style="margin: 0; font-size: 14px;">LABORATORIO CLÍNICO</h4>
|
||||
</div>
|
||||
|
||||
<!-- Información del paciente -->
|
||||
<div style="font-size: 11px; margin-bottom: 2mm;">
|
||||
<div><strong>Paciente:</strong> <span t-field="o.patient_id.name"/></div>
|
||||
<div><strong>ID:</strong> <span t-field="o.patient_id.vat" t-if="o.patient_id.vat"/>
|
||||
<span t-else="">Sin ID</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Información de la muestra -->
|
||||
<div style="font-size: 10px; margin-bottom: 3mm;">
|
||||
<div><strong>Orden:</strong> <span t-field="o.origin"/></div>
|
||||
<div><strong>Tipo:</strong> <span t-esc="o.get_container_name()"/></div>
|
||||
<div><strong>Fecha:</strong> <span t-field="o.collection_date" t-options='{"widget": "date"}'/></div>
|
||||
</div>
|
||||
|
||||
<!-- Código de barras -->
|
||||
<div style="text-align: center; margin-top: 3mm;">
|
||||
<img t-att-src="'/report/barcode/?barcode_type=%s&value=%s&width=%s&height=%s&humanreadable=%s' % ('Code128', o.barcode, 250, 60, 1)"
|
||||
style="width: 250px; height: 60px;"/>
|
||||
</div>
|
||||
|
||||
<!-- Análisis a realizar (si caben) -->
|
||||
<div style="font-size: 9px; margin-top: 2mm;" t-if="o.analysis_names">
|
||||
<div><strong>Análisis:</strong> <span t-field="o.analysis_names"/></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
|
@ -8,6 +8,15 @@
|
|||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale.view_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- Agregar botón de imprimir etiquetas en el header -->
|
||||
<xpath expr="//header" position="inside">
|
||||
<button name="action_print_sample_labels"
|
||||
string="Imprimir Etiquetas"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
invisible="not is_lab_request or state != 'sale' or not generated_sample_ids"
|
||||
icon="fa-print"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="doctor_id" invisible="not is_lab_request"/>
|
||||
</xpath>
|
||||
|
|
48
pr_body_9.txt
Normal file
48
pr_body_9.txt
Normal file
|
@ -0,0 +1,48 @@
|
|||
## Implementación del flujo de validación y seguridad
|
||||
|
||||
### Cambios realizados
|
||||
|
||||
#### 1. Ajuste de permisos base (ir.model.access.csv)
|
||||
- Recepcionista: Solo lectura en lims.test y lims.result
|
||||
- Técnico: Lectura/escritura pero sin crear/eliminar
|
||||
- Administrador: Permisos completos
|
||||
|
||||
#### 2. Reglas de registro implementadas (lims_security.xml)
|
||||
- Recepcionistas no pueden editar pruebas
|
||||
- Técnicos solo pueden editar pruebas no validadas
|
||||
- Administradores tienen acceso completo
|
||||
|
||||
#### 3. Validación de permisos en transiciones (lims_test.py)
|
||||
- `action_start_process()`: Solo técnicos y administradores
|
||||
- `action_enter_results()`: Solo técnicos y administradores
|
||||
- `action_validate()`: Solo administradores
|
||||
- `action_cancel()`: Técnicos (excepto validadas) y administradores
|
||||
- `action_draft()`: Solo administradores
|
||||
|
||||
#### 4. Trazabilidad mejorada
|
||||
- stock.lot ahora hereda de mail.thread
|
||||
- Todos los cambios de estado se registran en el chatter
|
||||
- Mensajes más descriptivos con contexto
|
||||
|
||||
#### 5. Validaciones adicionales
|
||||
- Control de transiciones de estado válidas
|
||||
- Verificación del estado de la muestra
|
||||
- Validación de resultados críticos fuera de rango
|
||||
- No se puede crear pruebas en estado != draft sin ser admin
|
||||
|
||||
#### 6. Vistas actualizadas
|
||||
- Botones visibles solo para roles apropiados
|
||||
- Campos de resultados editables solo por técnicos/admin
|
||||
|
||||
#### 7. Usuarios demo para pruebas
|
||||
- Usuario: `recepcionista` / Contraseña: `demo`
|
||||
- Usuario: `tecnico` / Contraseña: `demo`
|
||||
- Usuario: `administrador` / Contraseña: `demo`
|
||||
|
||||
### Pruebas realizadas
|
||||
- Verificación de permisos por rol
|
||||
- Validación de transiciones de estado
|
||||
- Trazabilidad en chatter
|
||||
- Restricciones visuales en formularios
|
||||
|
||||
Closes #9
|
Loading…
Reference in New Issue
Block a user