From 53eada84324b6af3adf546db3c92c07da3c26bf7 Mon Sep 17 00:00:00 2001 From: Luis Ernesto Portillo Zaldivar Date: Mon, 21 Jul 2025 16:09:39 -0600 Subject: [PATCH] =?UTF-8?q?feat(#71):=20Mejorar=20script=20de=20creaci?= =?UTF-8?q?=C3=B3n=20de=20=C3=B3rdenes=20de=20laboratorio=20-=202=20=C3=B3?= =?UTF-8?q?rdenes=20por=20paciente=20con=20manejo=20de=20errores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/create_lab_requests.py | 268 +++++++++++++++++++++++++----------- 1 file changed, 185 insertions(+), 83 deletions(-) diff --git a/test/create_lab_requests.py b/test/create_lab_requests.py index 741e650..707ef61 100644 --- a/test/create_lab_requests.py +++ b/test/create_lab_requests.py @@ -113,35 +113,79 @@ def process_order_tests(env, order): product_tmpl = test.product_id.product_tmpl_id for param_link in product_tmpl.parameter_ids: param = param_link.parameter_id - result = env['lims.result'].create({ + + # Prepare result data with values + result_data = { 'test_id': test.id, 'parameter_id': param.id, - }) - # Immediately set a value to avoid validation errors - if param.value_type == 'numeric': - # Generar valor que a veces esté fuera de rango - if random.random() < 0.3: # 30% de valores críticos - # Obtener rangos normales del parámetro - normal_min = param_link.normal_min if hasattr(param_link, 'normal_min') and param_link.normal_min else 10 - normal_max = param_link.normal_max if hasattr(param_link, 'normal_max') and param_link.normal_max else 100 - - # Decidir si será alto o bajo - if random.random() < 0.5: - # Valor alto - value = round(random.uniform(normal_max * 1.2, normal_max * 1.5), 2) + } + + # Set value based on parameter type + try: + if param.value_type == 'numeric': + # Generar valor que a veces esté fuera de rango + if random.random() < 0.3: # 30% de valores críticos + # Obtener rangos normales del parámetro + normal_min = param_link.normal_min if hasattr(param_link, 'normal_min') and param_link.normal_min else 10 + normal_max = param_link.normal_max if hasattr(param_link, 'normal_max') and param_link.normal_max else 100 + + # Decidir si será alto o bajo + if random.random() < 0.5: + # Valor alto + value = round(random.uniform(normal_max * 1.2, normal_max * 1.5), 2) + else: + # Valor bajo + value = round(random.uniform(normal_min * 0.5, normal_min * 0.8), 2) + result_data['value_numeric'] = value else: - # Valor bajo - value = round(random.uniform(normal_min * 0.5, normal_min * 0.8), 2) - result.value_numeric = value - else: - result.value_numeric = 50.0 - elif param.value_type == 'text': - result.value_text = "Normal" - elif param.value_type == 'boolean': - result.value_boolean = False - elif param.value_type == 'selection' and param.selection_options: - options = param.selection_options.split(',') - result.value_selection = options[0].strip() + result_data['value_numeric'] = 50.0 + elif param.value_type == 'text': + # Handle different text parameters appropriately + param_lower = param.name.lower() + if 'cultivo' in param_lower: + result_data['value_text'] = "No se observa crecimiento bacteriano" + elif 'observacion' in param_lower: + result_data['value_text'] = "Sin observaciones particulares" + elif 'color' in param_lower: + result_data['value_text'] = "Amarillo claro" + elif 'aspecto' in param_lower: + result_data['value_text'] = "Transparente" + elif 'olor' in param_lower: + result_data['value_text'] = "Sui generis" + else: + result_data['value_text'] = "Normal" + elif param.value_type == 'boolean': + result_data['value_boolean'] = False + elif param.value_type == 'selection': + if param.selection_values: + options = param.selection_values.split(',') + # For pregnancy tests, randomly assign positive/negative + if 'beta-hcg' in param.name.lower() or 'embarazo' in param.name.lower(): + # 30% chance of positive for pregnant patients, 5% for others + is_positive = random.random() < (0.3 if hasattr(test, 'patient_id') and test.patient_id.is_pregnant else 0.05) + result_data['value_selection'] = 'Positivo' if is_positive else 'Negativo' + else: + result_data['value_selection'] = options[0].strip() + else: + # No selection values defined, use default + if 'embarazo' in param.name.lower(): + result_data['value_selection'] = 'Negativo' + else: + result_data['value_selection'] = 'Normal' + except Exception as e: + print(f" - Error preparing value for parameter {param.name}: {str(e)}") + # Set a default value to avoid validation errors + if param.value_type == 'numeric': + result_data['value_numeric'] = 50.0 + elif param.value_type == 'text': + result_data['value_text'] = "Pendiente" + elif param.value_type == 'boolean': + result_data['value_boolean'] = False + elif param.value_type == 'selection': + result_data['value_selection'] = "Normal" + + # Create result with values + result = env['lims.result'].create(result_data) print(f" - Created {len(product_tmpl.parameter_ids)} result fields") # Evaluar resultados críticos y agregar notas @@ -209,65 +253,123 @@ def create_lab_requests(cr): except Exception: pass - try: - # Get patients and doctors - using search instead of ref to be more robust - patient1 = env['res.partner'].search([('patient_identifier', '=', 'P-A87B01'), ('is_patient', '=', True)], limit=1) - patient2 = env['res.partner'].search([('patient_identifier', '=', 'P-C45D02'), ('is_patient', '=', True)], limit=1) - doctor1 = env['res.partner'].search([('doctor_license', '=', 'L-98765'), ('is_doctor', '=', True)], limit=1) + # Get all available analysis products + all_analyses = env['product.template'].search([('is_analysis', '=', True)]) + + # Find or create pregnancy test + pregnancy_test = env['product.template'].search([('name', '=', 'Prueba de Embarazo'), ('is_analysis', '=', True)], limit=1) + if not pregnancy_test: + # Create pregnancy test if it doesn't exist + pregnancy_test = env['product.template'].create({ + 'name': 'Prueba de Embarazo', + 'is_analysis': True, + 'analysis_type': 'immunology', + 'list_price': 15.00, + 'standard_price': 8.00, + 'type': 'service', + 'categ_id': env.ref('lims_management.lims_category_immunology').id if env.ref('lims_management.lims_category_immunology', False) else env['product.category'].search([], limit=1).id, + }) + print("Created Pregnancy Test product") - if not patient1: - print("Warning: Patient 1 not found, skipping lab requests creation") - return - - # Get analysis products - using search instead of ref - hemograma = env['product.template'].search([('name', '=', 'Hemograma Completo'), ('is_analysis', '=', True)], limit=1) - perfil_lipidico = env['product.template'].search([('name', '=', 'Perfil Lipídico'), ('is_analysis', '=', True)], limit=1) - glucosa = env['product.template'].search([('name', '=', 'Glucosa en Sangre'), ('is_analysis', '=', True)], limit=1) - urocultivo = env['product.template'].search([('name', '=', 'Urocultivo'), ('is_analysis', '=', True)], limit=1) + # Create parameter for pregnancy test + preg_param = env['lims.analysis.parameter'].search([('name', '=', 'Beta-hCG')], limit=1) + if not preg_param: + preg_param = env['lims.analysis.parameter'].create({ + 'name': 'Beta-hCG', + 'code': 'BHCG', + 'value_type': 'selection', + 'selection_values': 'Positivo,Negativo,Indeterminado', + 'description': 'Hormona gonadotropina coriónica humana beta' + }) - # Create Lab Request 1 - Multiple analyses with same sample type - if patient1 and hemograma and perfil_lipidico: - order1 = env['sale.order'].create({ - 'partner_id': patient1.id, - 'doctor_id': doctor1.id if doctor1 else False, - 'is_lab_request': True, - 'order_line': [ - (0, 0, {'product_id': hemograma.product_variant_id.id, 'product_uom_qty': 1}), - (0, 0, {'product_id': perfil_lipidico.product_variant_id.id, 'product_uom_qty': 1}) - ] - }) - print(f"Created Lab Order 1: {order1.name}") - - # Confirm the order to test automatic sample generation - order1.action_confirm() - print(f"Confirmed Lab Order 1. Generated samples: {len(order1.generated_sample_ids)}") - - # Process tests for order1 - process_order_tests(env, order1) - - # Create Lab Request 2 - Different sample types - if patient2 and glucosa and urocultivo: - order2 = env['sale.order'].create({ - 'partner_id': patient2.id, - 'is_lab_request': True, - 'order_line': [ - (0, 0, {'product_id': glucosa.product_variant_id.id, 'product_uom_qty': 1}), - (0, 0, {'product_id': urocultivo.product_variant_id.id, 'product_uom_qty': 1}) - ] - }) - print(f"Created Lab Order 2: {order2.name}") - - # Confirm to test automatic sample generation with different types - order2.action_confirm() - print(f"Confirmed Lab Order 2. Generated samples: {len(order2.generated_sample_ids)}") - - # Process tests for order2 - process_order_tests(env, order2) - - except Exception as e: - print(f"Error creating lab requests: {str(e)}") - import traceback - traceback.print_exc() + # Link parameter to pregnancy test + env['product.template.parameter'].create({ + 'product_tmpl_id': pregnancy_test.id, + 'parameter_id': preg_param.id, + 'sequence': 10, + 'required': True + }) + + # Separate analyses for different purposes + routine_analyses = [a for a in all_analyses if a.name not in ['Prueba de Embarazo']] + + # Get all patients + all_patients = env['res.partner'].search([('is_patient', '=', True)], order='id') + + # Get available doctors + doctors = env['res.partner'].search([('is_doctor', '=', True)]) + + print(f"\n=== Starting creation of lab orders for {len(all_patients)} patients ===") + print(f"Available analyses: {len(all_analyses)}") + print(f"Available doctors: {len(doctors)}") + + orders_created = 0 + failed_orders = [] + + for idx, patient in enumerate(all_patients): + print(f"\n--- Processing patient {idx+1}/{len(all_patients)}: {patient.name} ---") + + # Randomly assign a doctor + doctor = random.choice(doctors) if doctors else False + + # Create 2 orders per patient + for order_num in range(1, 3): + try: + order_lines = [] + + # For pregnant patients, include pregnancy test in one of the orders + if patient.is_pregnant and order_num == 1: + order_lines.append((0, 0, { + 'product_id': pregnancy_test.product_variant_id.id, + 'product_uom_qty': 1 + })) + print(f" - Added pregnancy test for pregnant patient") + + # Select random analyses (minimum 2 per order) + num_analyses = random.randint(2, 4) + selected_analyses = random.sample(routine_analyses, min(num_analyses, len(routine_analyses))) + + for analysis in selected_analyses: + order_lines.append((0, 0, { + 'product_id': analysis.product_variant_id.id, + 'product_uom_qty': 1 + })) + + # Create the order + order = env['sale.order'].create({ + 'partner_id': patient.id, + 'doctor_id': doctor.id if doctor else False, + 'is_lab_request': True, + 'order_line': order_lines + }) + + print(f" Order {order_num}: Created {order.name} with {len(order_lines)} analyses") + + # Confirm the order + order.action_confirm() + print(f" Order {order_num}: Confirmed. Generated samples: {len(order.generated_sample_ids)}") + + # Process tests + process_order_tests(env, order) + + orders_created += 1 + + except Exception as e: + error_msg = f"Patient: {patient.name}, Order {order_num}, Error: {str(e)}" + failed_orders.append(error_msg) + print(f" ERROR creating order {order_num} for {patient.name}: {str(e)}") + import traceback + traceback.print_exc() + + # Final summary + print("\n=== SUMMARY ===") + print(f"Total orders created: {orders_created}") + print(f"Failed orders: {len(failed_orders)}") + + if failed_orders: + print("\n=== FAILED ORDERS ===") + for idx, error in enumerate(failed_orders, 1): + print(f"{idx}. {error}") if __name__ == '__main__': db_name = 'lims_demo'