fix(#60): Mejorar estructura de re-muestreos para mantener jerarquía plana
- Las re-muestras de re-muestras ahora se crean como hijas del padre original - Evita nombres anidados como RE-RE-0000002-1 - Mantiene estructura más clara: todas las re-muestras son hermanas - Actualiza mensajes para reflejar la muestra rechazada que originó la re-muestra - Mejora trazabilidad manteniendo referencia clara al origen 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3e97c9f418
commit
a77e848922
Binary file not shown.
|
@ -456,13 +456,18 @@ class StockLot(models.Model):
|
||||||
"""Create a new sample as a resample of the current one"""
|
"""Create a new sample as a resample of the current one"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
|
|
||||||
# Check if there's already an active resample
|
# Determine the parent sample for the new resample
|
||||||
active_resamples = self.child_sample_ids.filtered(
|
# If current sample is already a resample, use its parent
|
||||||
|
# Otherwise, use the current sample as parent
|
||||||
|
parent_for_resample = self.parent_sample_id if self.parent_sample_id else self
|
||||||
|
|
||||||
|
# Check if there's already an active resample for the parent
|
||||||
|
active_resamples = parent_for_resample.child_sample_ids.filtered(
|
||||||
lambda s: s.state not in ['rejected', 'cancelled', 'disposed']
|
lambda s: s.state not in ['rejected', 'cancelled', 'disposed']
|
||||||
)
|
)
|
||||||
if active_resamples:
|
if active_resamples:
|
||||||
raise UserError(_('Esta muestra ya tiene una re-muestra activa (%s). No se puede crear otra hasta que se procese o rechace la existente.') %
|
raise UserError(_('La muestra %s ya tiene una re-muestra activa (%s). No se puede crear otra hasta que se procese o rechace la existente.') %
|
||||||
', '.join(active_resamples.mapped('name')))
|
(parent_for_resample.name, ', '.join(active_resamples.mapped('name'))))
|
||||||
|
|
||||||
# Get configuration
|
# Get configuration
|
||||||
IrConfig = self.env['ir.config_parameter'].sudo()
|
IrConfig = self.env['ir.config_parameter'].sudo()
|
||||||
|
@ -472,7 +477,7 @@ class StockLot(models.Model):
|
||||||
max_attempts = int(IrConfig.get_param('lims_management.max_resample_attempts', '3'))
|
max_attempts = int(IrConfig.get_param('lims_management.max_resample_attempts', '3'))
|
||||||
|
|
||||||
# Find the original sample (root of the resample chain)
|
# Find the original sample (root of the resample chain)
|
||||||
original_sample = self
|
original_sample = parent_for_resample
|
||||||
while original_sample.parent_sample_id:
|
while original_sample.parent_sample_id:
|
||||||
original_sample = original_sample.parent_sample_id
|
original_sample = original_sample.parent_sample_id
|
||||||
|
|
||||||
|
@ -483,12 +488,12 @@ class StockLot(models.Model):
|
||||||
if max_attempts > 0 and total_resamples >= max_attempts:
|
if max_attempts > 0 and total_resamples >= max_attempts:
|
||||||
raise UserError(_('Se ha alcanzado el número máximo de re-muestreos (%d) para esta cadena de muestras.') % max_attempts)
|
raise UserError(_('Se ha alcanzado el número máximo de re-muestreos (%d) para esta cadena de muestras.') % max_attempts)
|
||||||
|
|
||||||
# Calculate resample number for naming
|
# Calculate resample number for naming (based on parent's resample count)
|
||||||
resample_number = self.resample_count + 1
|
resample_number = len(parent_for_resample.child_sample_ids) + 1
|
||||||
|
|
||||||
# Prepare values for new sample
|
# Prepare values for new sample
|
||||||
vals = {
|
vals = {
|
||||||
'name': f"{prefix}{self.name}-{resample_number}",
|
'name': f"{prefix}{parent_for_resample.name}-{resample_number}",
|
||||||
'product_id': self.product_id.id,
|
'product_id': self.product_id.id,
|
||||||
'patient_id': self.patient_id.id,
|
'patient_id': self.patient_id.id,
|
||||||
'doctor_id': self.doctor_id.id,
|
'doctor_id': self.doctor_id.id,
|
||||||
|
@ -498,23 +503,31 @@ class StockLot(models.Model):
|
||||||
'is_lab_sample': True,
|
'is_lab_sample': True,
|
||||||
'state': initial_state,
|
'state': initial_state,
|
||||||
'analysis_names': self.analysis_names,
|
'analysis_names': self.analysis_names,
|
||||||
'parent_sample_id': self.id,
|
'parent_sample_id': parent_for_resample.id, # Always use the determined parent
|
||||||
'request_id': self.request_id.id if self.request_id else False,
|
'request_id': self.request_id.id if self.request_id else False,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create the resample
|
# Create the resample
|
||||||
resample = self.create(vals)
|
resample = self.create(vals)
|
||||||
|
|
||||||
# Post message in both samples
|
# Post message in all relevant samples
|
||||||
self.message_post(
|
self.message_post(
|
||||||
body=_('Re-muestra creada: %s') % resample.name,
|
body=_('Re-muestra creada: %s') % resample.name,
|
||||||
subject='Re-muestreo',
|
subject='Re-muestreo',
|
||||||
message_type='notification'
|
message_type='notification'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self != parent_for_resample:
|
||||||
|
# If we're creating from a resample, also notify the parent
|
||||||
|
parent_for_resample.message_post(
|
||||||
|
body=_('Nueva re-muestra creada: %s (debido al rechazo de %s)') % (resample.name, self.name),
|
||||||
|
subject='Re-muestreo',
|
||||||
|
message_type='notification'
|
||||||
|
)
|
||||||
|
|
||||||
resample.message_post(
|
resample.message_post(
|
||||||
body=_('Esta es una re-muestra de: %s<br/>Motivo: %s') %
|
body=_('Esta es una re-muestra de: %s<br/>Creada debido al rechazo de: %s<br/>Motivo: %s') %
|
||||||
(self.name, self.rejection_reason_id.name if self.rejection_reason_id else 'No especificado'),
|
(parent_for_resample.name, self.name, self.rejection_reason_id.name if self.rejection_reason_id else 'No especificado'),
|
||||||
subject='Re-muestra creada',
|
subject='Re-muestra creada',
|
||||||
message_type='notification'
|
message_type='notification'
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user