Merge pull request 'feat(#54): Cancelar automáticamente muestras y pruebas al cancelar orden' (#55) from feature/54-auto-cancel-samples into dev
This commit is contained in:
commit
4d3206f3a1
24
issue_body.txt
Normal file
24
issue_body.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
## Descripción
|
||||
|
||||
Actualmente, cuando se cancela una orden de laboratorio, las muestras asociadas permanecen activas y no se descartan automáticamente. Esto puede causar confusión ya que quedan muestras "huérfanas" en el sistema que ya no tienen una orden válida.
|
||||
|
||||
## Comportamiento esperado
|
||||
|
||||
Cuando se cancela una orden de laboratorio:
|
||||
1. Todas las muestras generadas asociadas a esa orden deben cambiar automáticamente su estado a "cancelled"
|
||||
2. Si hay pruebas (lims.test) asociadas a esas muestras, también deben cancelarse
|
||||
3. Se debe registrar en el chatter de la muestra que fue cancelada debido a la cancelación de la orden
|
||||
|
||||
## Criterios de aceptación
|
||||
|
||||
- [ ] Al cancelar una orden de laboratorio, todas sus muestras asociadas se marcan como canceladas
|
||||
- [ ] Las pruebas asociadas a las muestras también se cancelan
|
||||
- [ ] Se registra un mensaje en el chatter de cada muestra indicando la razón de cancelación
|
||||
- [ ] Si una muestra ya estaba cancelada o completada, no se modifica
|
||||
- [ ] La acción es reversible: si se vuelve a poner la orden en borrador, las muestras NO deben reactivarse automáticamente
|
||||
|
||||
## Notas técnicas
|
||||
|
||||
- El método a modificar es `action_cancel()` en el modelo `sale.order`
|
||||
- Verificar el campo `generated_sample_ids` para obtener las muestras asociadas
|
||||
- Solo cancelar muestras que estén en estados: 'pending_collection', 'collected', 'in_analysis'
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -240,3 +240,56 @@ class SaleOrder(models.Model):
|
|||
return sample
|
||||
|
||||
return False
|
||||
|
||||
def action_cancel(self):
|
||||
"""Override para cancelar automáticamente muestras y pruebas asociadas cuando se cancela una orden de laboratorio"""
|
||||
# Primero llamar al método padre
|
||||
res = super(SaleOrder, self).action_cancel()
|
||||
|
||||
# Si es una orden de laboratorio, cancelar muestras y pruebas asociadas
|
||||
if self.is_lab_request:
|
||||
# Cancelar muestras que estén en estados cancelables
|
||||
cancelable_sample_states = ['pending_collection', 'collected', 'received', 'in_process']
|
||||
samples_to_cancel = self.generated_sample_ids.filtered(
|
||||
lambda s: s.state in cancelable_sample_states
|
||||
)
|
||||
|
||||
if samples_to_cancel:
|
||||
# Cancelar las muestras
|
||||
samples_to_cancel.action_cancel()
|
||||
|
||||
# Registrar en el chatter de cada muestra
|
||||
for sample in samples_to_cancel:
|
||||
sample.message_post(
|
||||
body=_("Muestra cancelada automáticamente debido a la cancelación de la orden %s") % self.name,
|
||||
message_type='notification'
|
||||
)
|
||||
|
||||
# Buscar y cancelar pruebas asociadas a estas muestras
|
||||
tests_to_cancel = self.env['lims.test'].search([
|
||||
('sample_id', 'in', samples_to_cancel.ids),
|
||||
('state', 'not in', ['validated', 'cancelled'])
|
||||
])
|
||||
|
||||
if tests_to_cancel:
|
||||
for test in tests_to_cancel:
|
||||
test.action_cancel()
|
||||
test.message_post(
|
||||
body=_("Prueba cancelada automáticamente debido a la cancelación de la orden %s") % self.name,
|
||||
message_type='notification'
|
||||
)
|
||||
|
||||
# Registrar en el chatter de la orden
|
||||
message = _("Se cancelaron automáticamente:<br/>")
|
||||
message += _("- %d muestras<br/>") % len(samples_to_cancel)
|
||||
if tests_to_cancel:
|
||||
message += _("- %d pruebas de laboratorio") % len(tests_to_cancel)
|
||||
|
||||
self.message_post(
|
||||
body=message,
|
||||
message_type='notification'
|
||||
)
|
||||
|
||||
_logger.info(f"Cancelled {len(samples_to_cancel)} samples and {len(tests_to_cancel)} tests for order {self.name}")
|
||||
|
||||
return res
|
||||
|
|
|
@ -80,7 +80,8 @@ class StockLot(models.Model):
|
|||
('in_process', 'En Proceso'),
|
||||
('analyzed', 'Analizada'),
|
||||
('stored', 'Almacenada'),
|
||||
('disposed', 'Desechada')
|
||||
('disposed', 'Desechada'),
|
||||
('cancelled', 'Cancelada')
|
||||
], string='Estado', default='collected', tracking=True)
|
||||
|
||||
def action_collect(self):
|
||||
|
@ -107,6 +108,10 @@ class StockLot(models.Model):
|
|||
"""Dispose of the sample"""
|
||||
self.write({'state': 'disposed'})
|
||||
|
||||
def action_cancel(self):
|
||||
"""Cancel the sample"""
|
||||
self.write({'state': 'cancelled'})
|
||||
|
||||
@api.onchange('sample_type_product_id')
|
||||
def _onchange_sample_type_product_id(self):
|
||||
"""Synchronize container_type when sample_type_product_id changes"""
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
from . import test_analysis_parameter
|
||||
from . import test_parameter_range
|
||||
from . import test_result_parameter_integration
|
||||
from . import test_auto_result_generation
|
||||
from . import test_auto_result_generation
|
||||
from . import test_order_cancel_cascade
|
263
lims_management/tests/test_order_cancel_cascade.py
Normal file
263
lims_management/tests/test_order_cancel_cascade.py
Normal file
|
@ -0,0 +1,263 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Test para verificar la cancelación en cascada de muestras y pruebas
|
||||
cuando se cancela una orden de laboratorio
|
||||
"""
|
||||
|
||||
from odoo.tests import TransactionCase
|
||||
from odoo.exceptions import UserError
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestOrderCancelCascade(TransactionCase):
|
||||
"""Test de cancelación en cascada de órdenes de laboratorio"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
# Obtener modelos
|
||||
self.Partner = self.env['res.partner']
|
||||
self.Product = self.env['product.product']
|
||||
self.SaleOrder = self.env['sale.order']
|
||||
self.StockLot = self.env['stock.lot']
|
||||
self.LimsTest = self.env['lims.test']
|
||||
|
||||
# Crear datos de prueba
|
||||
self.patient = self.Partner.create({
|
||||
'name': 'Test Patient Cancel',
|
||||
'is_patient': True,
|
||||
'birthdate_date': '1990-01-01',
|
||||
'gender': 'male'
|
||||
})
|
||||
|
||||
self.doctor = self.Partner.create({
|
||||
'name': 'Test Doctor Cancel',
|
||||
'is_doctor': True
|
||||
})
|
||||
|
||||
# Crear tipo de muestra
|
||||
self.sample_type = self.env['product.template'].create({
|
||||
'name': 'Tubo EDTA Test',
|
||||
'is_sample_type': True,
|
||||
'type': 'service',
|
||||
'categ_id': self.env.ref('product.product_category_all').id
|
||||
})
|
||||
|
||||
# Crear análisis
|
||||
self.analysis = self.env['product.template'].create({
|
||||
'name': 'Hemograma Test Cancel',
|
||||
'is_analysis': True,
|
||||
'type': 'service',
|
||||
'required_sample_type_id': self.sample_type.id,
|
||||
'categ_id': self.env.ref('product.product_category_all').id
|
||||
})
|
||||
|
||||
# Crear parámetro para el análisis
|
||||
self.parameter = self.env['lims.analysis.parameter'].create({
|
||||
'name': 'Hemoglobina Test',
|
||||
'code': 'HGB_TEST',
|
||||
'value_type': 'numeric',
|
||||
'unit': 'g/dL'
|
||||
})
|
||||
|
||||
# Configurar parámetro en el análisis
|
||||
self.env['product.template.parameter'].create({
|
||||
'product_tmpl_id': self.analysis.id,
|
||||
'parameter_id': self.parameter.id,
|
||||
'sequence': 10
|
||||
})
|
||||
|
||||
def test_01_cancel_order_cancels_samples(self):
|
||||
"""Test que al cancelar una orden se cancelan las muestras asociadas"""
|
||||
# Crear orden de laboratorio
|
||||
order = self.SaleOrder.create({
|
||||
'partner_id': self.patient.id,
|
||||
'doctor_id': self.doctor.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': self.analysis.product_variant_id.id,
|
||||
'product_uom_qty': 1.0
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar la orden (debe generar muestras)
|
||||
order.action_confirm()
|
||||
|
||||
# Verificar que se generaron muestras
|
||||
self.assertTrue(order.generated_sample_ids, "No se generaron muestras")
|
||||
samples = order.generated_sample_ids
|
||||
|
||||
# Verificar estado inicial de las muestras
|
||||
for sample in samples:
|
||||
self.assertIn(sample.state, ['pending_collection', 'collected'],
|
||||
f"Estado inicial incorrecto: {sample.state}")
|
||||
|
||||
# Cancelar la orden
|
||||
order.action_cancel()
|
||||
|
||||
# Verificar que las muestras fueron canceladas
|
||||
for sample in samples:
|
||||
self.assertEqual(sample.state, 'cancelled',
|
||||
f"Muestra no fue cancelada: {sample.state}")
|
||||
|
||||
def test_02_cancel_order_cancels_tests(self):
|
||||
"""Test que al cancelar una orden se cancelan las pruebas asociadas"""
|
||||
# Crear orden de laboratorio
|
||||
order = self.SaleOrder.create({
|
||||
'partner_id': self.patient.id,
|
||||
'doctor_id': self.doctor.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': self.analysis.product_variant_id.id,
|
||||
'product_uom_qty': 1.0
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar la orden
|
||||
order.action_confirm()
|
||||
|
||||
# Obtener las pruebas generadas
|
||||
tests = self.LimsTest.search([
|
||||
('sale_order_line_id.order_id', '=', order.id)
|
||||
])
|
||||
self.assertTrue(tests, "No se generaron pruebas")
|
||||
|
||||
# Verificar estado inicial
|
||||
for test in tests:
|
||||
self.assertEqual(test.state, 'draft',
|
||||
f"Estado inicial incorrecto: {test.state}")
|
||||
|
||||
# Iniciar proceso en una prueba
|
||||
if tests:
|
||||
tests[0].write({'sample_id': order.generated_sample_ids[0].id})
|
||||
tests[0].action_start_process()
|
||||
self.assertEqual(tests[0].state, 'in_process')
|
||||
|
||||
# Cancelar la orden
|
||||
order.action_cancel()
|
||||
|
||||
# Verificar que las pruebas fueron canceladas
|
||||
for test in tests:
|
||||
self.assertEqual(test.state, 'cancelled',
|
||||
f"Prueba no fue cancelada: {test.state}")
|
||||
|
||||
def test_03_dont_cancel_completed_samples(self):
|
||||
"""Test que no se cancelan muestras en estados finales"""
|
||||
# Crear orden
|
||||
order = self.SaleOrder.create({
|
||||
'partner_id': self.patient.id,
|
||||
'doctor_id': self.doctor.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': self.analysis.product_variant_id.id,
|
||||
'product_uom_qty': 1.0
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar
|
||||
order.action_confirm()
|
||||
|
||||
# Marcar una muestra como analizada
|
||||
sample = order.generated_sample_ids[0]
|
||||
sample.write({'state': 'analyzed'})
|
||||
|
||||
# Cancelar la orden
|
||||
order.action_cancel()
|
||||
|
||||
# Verificar que la muestra analizada no fue cancelada
|
||||
self.assertEqual(sample.state, 'analyzed',
|
||||
"Muestra analizada fue cancelada incorrectamente")
|
||||
|
||||
def test_04_dont_cancel_validated_tests(self):
|
||||
"""Test que no se cancelan pruebas validadas"""
|
||||
# Crear orden
|
||||
order = self.SaleOrder.create({
|
||||
'partner_id': self.patient.id,
|
||||
'doctor_id': self.doctor.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': self.analysis.product_variant_id.id,
|
||||
'product_uom_qty': 1.0
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar
|
||||
order.action_confirm()
|
||||
|
||||
# Obtener prueba y marcarla como validada
|
||||
test = self.LimsTest.search([
|
||||
('sale_order_line_id.order_id', '=', order.id)
|
||||
], limit=1)
|
||||
|
||||
if test:
|
||||
test.write({
|
||||
'state': 'validated',
|
||||
'sample_id': order.generated_sample_ids[0].id
|
||||
})
|
||||
|
||||
# Cancelar la orden
|
||||
order.action_cancel()
|
||||
|
||||
# Verificar que la prueba validada no fue cancelada
|
||||
self.assertEqual(test.state, 'validated',
|
||||
"Prueba validada fue cancelada incorrectamente")
|
||||
|
||||
def test_05_chatter_messages_created(self):
|
||||
"""Test que se crean mensajes en el chatter"""
|
||||
# Crear orden
|
||||
order = self.SaleOrder.create({
|
||||
'partner_id': self.patient.id,
|
||||
'doctor_id': self.doctor.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': self.analysis.product_variant_id.id,
|
||||
'product_uom_qty': 1.0
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar
|
||||
order.action_confirm()
|
||||
|
||||
# Obtener conteo inicial de mensajes
|
||||
initial_order_messages = len(order.message_ids)
|
||||
sample = order.generated_sample_ids[0]
|
||||
initial_sample_messages = len(sample.message_ids)
|
||||
|
||||
# Cancelar
|
||||
order.action_cancel()
|
||||
|
||||
# Verificar que se agregaron mensajes
|
||||
self.assertGreater(len(order.message_ids), initial_order_messages,
|
||||
"No se agregó mensaje en la orden")
|
||||
self.assertGreater(len(sample.message_ids), initial_sample_messages,
|
||||
"No se agregó mensaje en la muestra")
|
||||
|
||||
# Verificar contenido del mensaje
|
||||
last_order_msg = order.message_ids[0].body
|
||||
self.assertIn("cancelaron automáticamente", last_order_msg,
|
||||
"Mensaje de orden no contiene texto esperado")
|
||||
|
||||
def test_06_non_lab_order_not_affected(self):
|
||||
"""Test que órdenes normales no son afectadas"""
|
||||
# Crear orden normal (no de laboratorio)
|
||||
order = self.SaleOrder.create({
|
||||
'partner_id': self.patient.id,
|
||||
'is_lab_request': False, # NO es orden de laboratorio
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': self.analysis.product_variant_id.id,
|
||||
'product_uom_qty': 1.0
|
||||
})]
|
||||
})
|
||||
|
||||
# Confirmar
|
||||
order.action_confirm()
|
||||
|
||||
# No deberían generarse muestras
|
||||
self.assertFalse(order.generated_sample_ids,
|
||||
"Se generaron muestras en orden normal")
|
||||
|
||||
# Cancelar - no debería causar error
|
||||
order.action_cancel()
|
||||
self.assertEqual(order.state, 'cancel')
|
53
test/run_cancel_tests.py
Normal file
53
test/run_cancel_tests.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Ejecutar tests de cancelación en cascada
|
||||
"""
|
||||
|
||||
import odoo
|
||||
import sys
|
||||
|
||||
def run_tests(cr):
|
||||
"""Ejecutar los tests"""
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
# Importar y ejecutar tests
|
||||
from odoo.addons.lims_management.tests.test_order_cancel_cascade import TestOrderCancelCascade
|
||||
|
||||
suite = odoo.tests.loader.make_suite(TestOrderCancelCascade)
|
||||
result = odoo.tests.runner.run(suite)
|
||||
|
||||
print(f"\n📊 Resultados de los tests:")
|
||||
print(f" Tests ejecutados: {result.testsRun}")
|
||||
print(f" Errores: {len(result.errors)}")
|
||||
print(f" Fallos: {len(result.failures)}")
|
||||
|
||||
if result.errors:
|
||||
print("\n❌ Errores:")
|
||||
for test, error in result.errors:
|
||||
print(f" - {test}: {error}")
|
||||
|
||||
if result.failures:
|
||||
print("\n❌ Fallos:")
|
||||
for test, failure in result.failures:
|
||||
print(f" - {test}: {failure}")
|
||||
|
||||
if result.wasSuccessful():
|
||||
print("\n✅ Todos los tests pasaron exitosamente!")
|
||||
else:
|
||||
print("\n❌ Algunos tests fallaron")
|
||||
|
||||
return result.wasSuccessful()
|
||||
|
||||
if __name__ == '__main__':
|
||||
db_name = 'lims_demo'
|
||||
try:
|
||||
registry = odoo.modules.registry.Registry(db_name)
|
||||
with registry.cursor() as cr:
|
||||
success = run_tests(cr)
|
||||
sys.exit(0 if success else 1)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
149
test/test_cancel_cascade.py
Normal file
149
test/test_cancel_cascade.py
Normal file
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script para probar la funcionalidad de cancelación en cascada
|
||||
"""
|
||||
|
||||
import odoo
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def test_cancel_cascade(cr):
|
||||
"""Probar la cancelación en cascada de órdenes"""
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
print("🧪 Probando cancelación en cascada de órdenes de laboratorio\n")
|
||||
|
||||
try:
|
||||
# Buscar un paciente y doctor de prueba
|
||||
patient = env['res.partner'].search([('is_patient', '=', True)], limit=1)
|
||||
doctor = env['res.partner'].search([('is_doctor', '=', True)], limit=1)
|
||||
|
||||
if not patient or not doctor:
|
||||
print("❌ No se encontraron pacientes o doctores de prueba")
|
||||
return
|
||||
|
||||
# Buscar un análisis
|
||||
analysis = env['product.product'].search([
|
||||
('is_analysis', '=', True),
|
||||
('required_sample_type_id', '!=', False)
|
||||
], limit=1)
|
||||
|
||||
if not analysis:
|
||||
print("❌ No se encontró un análisis con tipo de muestra requerido")
|
||||
return
|
||||
|
||||
print(f"📋 Creando orden de laboratorio de prueba...")
|
||||
print(f" Paciente: {patient.name}")
|
||||
print(f" Doctor: {doctor.name}")
|
||||
print(f" Análisis: {analysis.name}")
|
||||
|
||||
# Crear orden de laboratorio
|
||||
order = env['sale.order'].create({
|
||||
'partner_id': patient.id,
|
||||
'doctor_id': doctor.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': analysis.id,
|
||||
'product_uom_qty': 1.0
|
||||
})]
|
||||
})
|
||||
|
||||
print(f"\n✓ Orden creada: {order.name}")
|
||||
print(f" Estado inicial: {order.state}")
|
||||
|
||||
# Confirmar la orden
|
||||
print("\n🔄 Confirmando orden...")
|
||||
order.action_confirm()
|
||||
|
||||
print(f"✓ Orden confirmada")
|
||||
print(f" Estado: {order.state}")
|
||||
print(f" Muestras generadas: {len(order.generated_sample_ids)}")
|
||||
|
||||
# Mostrar muestras generadas
|
||||
if order.generated_sample_ids:
|
||||
print("\n📦 Muestras generadas:")
|
||||
for sample in order.generated_sample_ids:
|
||||
print(f" - {sample.name}: {sample.sample_type_product_id.name} (Estado: {sample.state})")
|
||||
|
||||
# Buscar pruebas generadas
|
||||
tests = env['lims.test'].search([
|
||||
('sale_order_line_id.order_id', '=', order.id)
|
||||
])
|
||||
|
||||
print(f"\n🔬 Pruebas generadas: {len(tests)}")
|
||||
if tests:
|
||||
for test in tests:
|
||||
print(f" - {test.name}: {test.product_id.name} (Estado: {test.state})")
|
||||
|
||||
# Iniciar proceso en una prueba para hacerlo más realista
|
||||
if tests and order.generated_sample_ids:
|
||||
print("\n🔄 Iniciando proceso en primera prueba...")
|
||||
test = tests[0]
|
||||
test.sample_id = order.generated_sample_ids[0]
|
||||
test.action_start_process()
|
||||
print(f" ✓ Prueba {test.name} en proceso")
|
||||
|
||||
# CANCELAR LA ORDEN
|
||||
print("\n❌ Cancelando la orden de laboratorio...")
|
||||
order.action_cancel()
|
||||
|
||||
print(f"\n✓ Orden cancelada")
|
||||
print(f" Estado de la orden: {order.state}")
|
||||
|
||||
# Verificar estado de las muestras
|
||||
print("\n📦 Estado final de las muestras:")
|
||||
for sample in order.generated_sample_ids:
|
||||
print(f" - {sample.name}: {sample.state}")
|
||||
# Verificar si hay mensaje en el chatter
|
||||
last_msg = sample.message_ids[0] if sample.message_ids else None
|
||||
if last_msg and "cancelada automáticamente" in last_msg.body:
|
||||
print(f" ✓ Mensaje de cancelación registrado")
|
||||
|
||||
# Verificar estado de las pruebas
|
||||
print("\n🔬 Estado final de las pruebas:")
|
||||
for test in tests:
|
||||
test_updated = env['lims.test'].browse(test.id)
|
||||
print(f" - {test_updated.name}: {test_updated.state}")
|
||||
# Verificar mensaje
|
||||
last_msg = test_updated.message_ids[0] if test_updated.message_ids else None
|
||||
if last_msg and "cancelada automáticamente" in last_msg.body:
|
||||
print(f" ✓ Mensaje de cancelación registrado")
|
||||
|
||||
# Verificar mensaje en la orden
|
||||
print("\n📝 Mensajes en la orden:")
|
||||
for msg in order.message_ids[:3]: # Últimos 3 mensajes
|
||||
if "cancelaron automáticamente" in msg.body:
|
||||
print(f" ✓ Mensaje de resumen de cancelación encontrado")
|
||||
# Extraer números del mensaje
|
||||
import re
|
||||
samples_match = re.search(r'(\d+) muestras', msg.body)
|
||||
tests_match = re.search(r'(\d+) pruebas', msg.body)
|
||||
if samples_match:
|
||||
print(f" - Muestras canceladas: {samples_match.group(1)}")
|
||||
if tests_match:
|
||||
print(f" - Pruebas canceladas: {tests_match.group(1)}")
|
||||
break
|
||||
|
||||
print("\n✅ Prueba completada exitosamente!")
|
||||
|
||||
# Hacer rollback para no dejar datos de prueba
|
||||
cr.rollback()
|
||||
print("\n⚠️ Cambios revertidos (rollback)")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Error durante la prueba: {str(e)}")
|
||||
traceback.print_exc()
|
||||
cr.rollback()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
db_name = 'lims_demo'
|
||||
try:
|
||||
registry = odoo.modules.registry.Registry(db_name)
|
||||
with registry.cursor() as cr:
|
||||
test_cancel_cascade(cr)
|
||||
except Exception as e:
|
||||
print(f"Error general: {e}")
|
||||
traceback.print_exc()
|
49
test/verify_order_state.py
Normal file
49
test/verify_order_state.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Verificar estado de orden después de cancelar
|
||||
"""
|
||||
|
||||
import odoo
|
||||
|
||||
def verify_order_state(cr):
|
||||
"""Verificar que el estado de la orden cambia correctamente"""
|
||||
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
# Buscar datos necesarios
|
||||
patient = env['res.partner'].search([('is_patient', '=', True)], limit=1)
|
||||
analysis = env['product.product'].search([('is_analysis', '=', True)], limit=1)
|
||||
|
||||
# Crear orden simple
|
||||
order = env['sale.order'].create({
|
||||
'partner_id': patient.id,
|
||||
'is_lab_request': True,
|
||||
'order_line': [(0, 0, {
|
||||
'product_id': analysis.id,
|
||||
'product_uom_qty': 1.0
|
||||
})]
|
||||
})
|
||||
|
||||
print(f"Orden creada: {order.name}")
|
||||
print(f"Estado inicial: {order.state}")
|
||||
|
||||
# Confirmar
|
||||
order.action_confirm()
|
||||
print(f"Estado después de confirmar: {order.state}")
|
||||
|
||||
# Cancelar
|
||||
order.action_cancel()
|
||||
print(f"Estado después de cancelar: {order.state}")
|
||||
|
||||
# Verificar nuevamente
|
||||
order_check = env['sale.order'].browse(order.id)
|
||||
print(f"Estado verificado nuevamente: {order_check.state}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
db_name = 'lims_demo'
|
||||
try:
|
||||
registry = odoo.modules.registry.Registry(db_name)
|
||||
with registry.cursor() as cr:
|
||||
verify_order_state(cr)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
Loading…
Reference in New Issue
Block a user