lims_industry: edit sample wizard: add edition log
This commit is contained in:
parent
0afdc805a9
commit
9f4a5ef933
|
@ -34,6 +34,7 @@ def register():
|
|||
analysis.Analysis,
|
||||
sample.Entry,
|
||||
sample.Sample,
|
||||
sample.SampleEditionLog,
|
||||
sample.Fraction,
|
||||
sample.FractionType,
|
||||
sample.CreateSampleStart,
|
||||
|
|
|
@ -466,6 +466,10 @@ msgctxt "field:lims.sample,component:"
|
|||
msgid "Component"
|
||||
msgstr "Componente"
|
||||
|
||||
msgctxt "field:lims.sample,edition_log:"
|
||||
msgid "Edition log"
|
||||
msgstr "Registro de cambios"
|
||||
|
||||
msgctxt "field:lims.sample,equipment:"
|
||||
msgid "Equipment"
|
||||
msgstr "Equipo"
|
||||
|
@ -566,6 +570,10 @@ msgctxt "field:lims.sample.attribute.set,name:"
|
|||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
msgctxt "field:lims.sample.edit.start,comercial_product:"
|
||||
msgid "Comercial Product"
|
||||
msgstr "Producto comercial"
|
||||
|
||||
msgctxt "field:lims.sample.edit.start,component:"
|
||||
msgid "Component"
|
||||
msgstr "Componente"
|
||||
|
@ -576,12 +584,32 @@ msgstr "Equipo"
|
|||
|
||||
msgctxt "field:lims.sample.edit.start,party:"
|
||||
msgid "Party"
|
||||
msgstr "Tercero"
|
||||
msgstr "Entidad"
|
||||
|
||||
msgctxt "field:lims.sample.edit.start,plant:"
|
||||
msgid "Plant"
|
||||
msgstr "Planta"
|
||||
|
||||
msgctxt "field:lims.sample.edition.log,create_date2:"
|
||||
msgid "Created at"
|
||||
msgstr "Creado el"
|
||||
|
||||
msgctxt "field:lims.sample.edition.log,field:"
|
||||
msgid "Field"
|
||||
msgstr "Campo"
|
||||
|
||||
msgctxt "field:lims.sample.edition.log,final_value:"
|
||||
msgid "Final value"
|
||||
msgstr "Valor final"
|
||||
|
||||
msgctxt "field:lims.sample.edition.log,initial_value:"
|
||||
msgid "Initial value"
|
||||
msgstr "Valor inicial"
|
||||
|
||||
msgctxt "field:lims.sample.edition.log,sample:"
|
||||
msgid "Sample"
|
||||
msgstr "Muestra"
|
||||
|
||||
msgctxt "field:lims.sampling.type,description:"
|
||||
msgid "Description"
|
||||
msgstr "Descripción"
|
||||
|
@ -726,6 +754,16 @@ msgctxt "model:ir.message,text:msg_component_type_unique"
|
|||
msgid "A component of the same type already exists for the equipment"
|
||||
msgstr "Ya existe un componente del mismo tipo para el equipo"
|
||||
|
||||
msgctxt "model:ir.message,text:msg_edit_entry_party"
|
||||
msgid "You must select all samples from the same entry to change the Party"
|
||||
msgstr ""
|
||||
"Debe seleccionar todas las muestras del mismo ingreso para cambiar la "
|
||||
"entidad"
|
||||
|
||||
msgctxt "model:ir.message,text:msg_edit_results_report_party"
|
||||
msgid "Sample \"%(sample)s\" has a Results report already released"
|
||||
msgstr "La muestra «%(sample)s» tiene un Informe de resultados ya publicado"
|
||||
|
||||
msgctxt "model:ir.message,text:msg_equipment_name_unique"
|
||||
msgid "There is already an equipment with the same name for the plant"
|
||||
msgstr "Ya existe un equipo con el mismo nombre para la planta"
|
||||
|
@ -859,6 +897,10 @@ msgctxt "model:lims.sample.edit.start,name:"
|
|||
msgid "Edit Samples"
|
||||
msgstr "Modificar muestras"
|
||||
|
||||
msgctxt "model:lims.sample.edition.log,name:"
|
||||
msgid "Sample Edition Log"
|
||||
msgstr "Registro de cambios en Muestra"
|
||||
|
||||
msgctxt "model:lims.sampling.type,name:"
|
||||
msgid "Sampling Type"
|
||||
msgstr "Muestreo"
|
||||
|
@ -871,6 +913,30 @@ msgctxt "selection:lims.configuration,mail_ack_report_grouping:"
|
|||
msgid "Plant"
|
||||
msgstr "Planta"
|
||||
|
||||
msgctxt "selection:lims.sample.edition.log,field:"
|
||||
msgid "Comercial Product"
|
||||
msgstr "Producto comercial"
|
||||
|
||||
msgctxt "selection:lims.sample.edition.log,field:"
|
||||
msgid "Component"
|
||||
msgstr "Componente"
|
||||
|
||||
msgctxt "selection:lims.sample.edition.log,field:"
|
||||
msgid "Equipment"
|
||||
msgstr "Equipo"
|
||||
|
||||
msgctxt "selection:lims.sample.edition.log,field:"
|
||||
msgid "Matrix"
|
||||
msgstr "Matriz"
|
||||
|
||||
msgctxt "selection:lims.sample.edition.log,field:"
|
||||
msgid "Party"
|
||||
msgstr "Entidad"
|
||||
|
||||
msgctxt "selection:lims.sample.edition.log,field:"
|
||||
msgid "Product type"
|
||||
msgstr "Tipo de producto"
|
||||
|
||||
msgctxt "selection:lims.trend.chart,filter:"
|
||||
msgid "Same Component"
|
||||
msgstr "Mismo Componente"
|
||||
|
@ -999,6 +1065,14 @@ msgctxt "view:lims.results_report.version.detail.sample:"
|
|||
msgid "Precedents"
|
||||
msgstr "Antecedentes"
|
||||
|
||||
msgctxt "view:lims.sample.edition.log:"
|
||||
msgid "Time"
|
||||
msgstr "Hora"
|
||||
|
||||
msgctxt "view:lims.sample:"
|
||||
msgid "Edition log"
|
||||
msgstr "Registro de cambios"
|
||||
|
||||
msgctxt "view:lims.sample:"
|
||||
msgid "Industry"
|
||||
msgstr "Industria"
|
||||
|
|
|
@ -49,5 +49,11 @@
|
|||
<record model="ir.message" id="msg_equipment_template_unique">
|
||||
<field name="text">There is already a equipment template with the same type, brand and model</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_edit_entry_party">
|
||||
<field name="text">You must select all samples from the same entry to change the Party</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_edit_results_report_party">
|
||||
<field name="text">Sample "%(sample)s" has a Results report already released</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
# The COPYRIGHT file at the top level of this repository contains
|
||||
# the full copyright notices and license terms.
|
||||
|
||||
from trytond.model import ModelView, fields
|
||||
from trytond.model import ModelSQL, ModelView, fields
|
||||
from trytond.wizard import Wizard, StateTransition, StateView, Button
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Eval, Bool
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.i18n import gettext
|
||||
|
||||
|
||||
class Entry(metaclass=PoolMeta):
|
||||
|
@ -64,6 +66,8 @@ class Sample(metaclass=PoolMeta):
|
|||
changed_oil = fields.Boolean('Did change Oil?')
|
||||
changed_oil_filter = fields.Boolean('Did change Oil Filter?')
|
||||
changed_air_filter = fields.Boolean('Did change Air Filter?')
|
||||
edition_log = fields.One2Many('lims.sample.edition.log', 'sample',
|
||||
'Edition log', readonly=True)
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
|
@ -182,6 +186,48 @@ class Sample(metaclass=PoolMeta):
|
|||
return result
|
||||
|
||||
|
||||
class SampleEditionLog(ModelSQL, ModelView):
|
||||
'Sample Edition Log'
|
||||
__name__ = 'lims.sample.edition.log'
|
||||
|
||||
create_date2 = fields.Function(fields.DateTime('Created at'),
|
||||
'get_create_date2', searcher='search_create_date2')
|
||||
sample = fields.Many2One('lims.sample', 'Sample', required=True,
|
||||
ondelete='CASCADE', select=True, readonly=True)
|
||||
field = fields.Selection([
|
||||
('party', 'Party'),
|
||||
('equipment', 'Equipment'),
|
||||
('component', 'Component'),
|
||||
('product_type', 'Product type'),
|
||||
('comercial_product', 'Comercial Product'),
|
||||
('matrix', 'Matrix'),
|
||||
], 'Field', readonly=True)
|
||||
initial_value = fields.Text('Initial value', readonly=True)
|
||||
final_value = fields.Text('Final value', readonly=True)
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order.insert(0, ('create_date', 'ASC'))
|
||||
|
||||
def get_create_date2(self, name):
|
||||
return self.create_date.replace(microsecond=0)
|
||||
|
||||
@classmethod
|
||||
def search_create_date2(cls, name, clause):
|
||||
cursor = Transaction().connection.cursor()
|
||||
operator_ = clause[1:2][0]
|
||||
cursor.execute('SELECT id '
|
||||
'FROM "' + cls._table + '" '
|
||||
'WHERE create_date' + operator_ + ' %s',
|
||||
clause[2:3])
|
||||
return [('id', 'in', [x[0] for x in cursor.fetchall()])]
|
||||
|
||||
@classmethod
|
||||
def order_create_date2(cls, tables):
|
||||
return cls.create_date.convert_order('create_date', tables, cls)
|
||||
|
||||
|
||||
class Fraction(metaclass=PoolMeta):
|
||||
__name__ = 'lims.fraction'
|
||||
|
||||
|
@ -450,6 +496,13 @@ class EditSampleStart(ModelView):
|
|||
component = fields.Many2One('lims.component', 'Component',
|
||||
domain=[('equipment', '=', Eval('equipment'))],
|
||||
depends=['equipment'])
|
||||
comercial_product = fields.Many2One('lims.comercial.product',
|
||||
'Comercial Product')
|
||||
|
||||
@fields.depends('component')
|
||||
def on_change_component(self):
|
||||
if self.component and self.component.comercial_product:
|
||||
self.comercial_product = self.component.comercial_product.id
|
||||
|
||||
|
||||
class EditSample(Wizard):
|
||||
|
@ -466,7 +519,8 @@ class EditSample(Wizard):
|
|||
def _get_filtered_samples(self):
|
||||
Sample = Pool().get('lims.sample')
|
||||
samples = Sample.browse(Transaction().context['active_ids'])
|
||||
return [s for s in samples if s.entry.state == 'draft']
|
||||
#return [s for s in samples if s.entry.state == 'draft']
|
||||
return samples
|
||||
|
||||
def default_start(self, fields):
|
||||
samples = self._get_filtered_samples()
|
||||
|
@ -482,29 +536,154 @@ class EditSample(Wizard):
|
|||
}
|
||||
|
||||
def transition_confirm(self):
|
||||
component_changed = bool(self.start.component)
|
||||
equipment_changed = bool(self.start.equipment)
|
||||
party_changed = bool(self.start.party)
|
||||
SampleEditionLog = Pool().get('lims.sample.edition.log')
|
||||
|
||||
samples = self._get_filtered_samples()
|
||||
samples_to_edit_party = []
|
||||
for sample in samples:
|
||||
if component_changed:
|
||||
sample.component = self.start.component.id
|
||||
if equipment_changed:
|
||||
check_typifications = False
|
||||
log = []
|
||||
if (self.start.party and
|
||||
self.start.party != sample.party):
|
||||
log.append({
|
||||
'sample': sample.id,
|
||||
'field': 'party',
|
||||
'initial_value': sample.party.rec_name,
|
||||
'final_value': self.start.party.rec_name,
|
||||
})
|
||||
samples_to_edit_party.append(sample)
|
||||
|
||||
if (self.start.equipment and
|
||||
self.start.equipment != sample.equipment):
|
||||
log.append({
|
||||
'sample': sample.id,
|
||||
'field': 'equipment',
|
||||
'initial_value': (sample.equipment and
|
||||
sample.equipment.rec_name or None),
|
||||
'final_value': self.start.equipment.rec_name,
|
||||
})
|
||||
sample.equipment = self.start.equipment.id
|
||||
if party_changed:
|
||||
if self.start.party.id != sample.party.id:
|
||||
entry = self._new_entry()
|
||||
sample.entry = entry.id
|
||||
|
||||
if (self.start.component and
|
||||
self.start.component != sample.component):
|
||||
log.append({
|
||||
'sample': sample.id,
|
||||
'field': 'component',
|
||||
'initial_value': (sample.component and
|
||||
sample.component.rec_name or None),
|
||||
'final_value': self.start.component.rec_name,
|
||||
})
|
||||
sample.component = self.start.component.id
|
||||
if (self.start.component.product_type and
|
||||
self.start.component.product_type !=
|
||||
sample.product_type):
|
||||
check_typifications = True
|
||||
log.append({
|
||||
'sample': sample.id,
|
||||
'field': 'product_type',
|
||||
'initial_value': sample.product_type.rec_name,
|
||||
'final_value': (
|
||||
self.start.component.product_type.rec_name),
|
||||
})
|
||||
sample.product_type = self.start.component.product_type.id
|
||||
|
||||
if (self.start.comercial_product and
|
||||
self.start.comercial_product != sample.comercial_product):
|
||||
log.append({
|
||||
'sample': sample.id,
|
||||
'field': 'comercial_product',
|
||||
'initial_value': (sample.comercial_product and
|
||||
sample.comercial_product.rec_name),
|
||||
'final_value': self.start.comercial_product.rec_name,
|
||||
})
|
||||
sample.comercial_product = self.start.comercial_product.id
|
||||
if (self.start.comercial_product.matrix and
|
||||
self.start.comercial_product.matrix !=
|
||||
self.start.comercial_product.matrix):
|
||||
check_typifications = True
|
||||
log.append({
|
||||
'sample': sample.id,
|
||||
'field': 'matrix',
|
||||
'initial_value': sample.matrix.rec_name,
|
||||
'final_value': (
|
||||
self.start.comercial_product.matrix.rec_name),
|
||||
})
|
||||
sample.matrix = self.start.comercial_product.matrix.id
|
||||
|
||||
if check_typifications:
|
||||
self.check_typifications(sample)
|
||||
|
||||
sample.save()
|
||||
if log:
|
||||
SampleEditionLog.create(log)
|
||||
|
||||
for sample in samples_to_edit_party:
|
||||
self.edit_party(sample, samples)
|
||||
|
||||
return 'end'
|
||||
|
||||
def _new_entry(self):
|
||||
def edit_party(self, sample, samples):
|
||||
self._edit_entry_party(sample, samples)
|
||||
self._edit_results_report_party(sample, samples)
|
||||
|
||||
def _edit_entry_party(self, sample, samples):
|
||||
pool = Pool()
|
||||
Sample = pool.get('lims.sample')
|
||||
Entry = pool.get('lims.entry')
|
||||
entry = Entry()
|
||||
|
||||
if Sample.search_count([
|
||||
('entry', '=', sample.entry.id),
|
||||
('id', 'not in', [s.id for s in samples]),
|
||||
]) > 0:
|
||||
raise UserError(gettext('lims_industry.msg_edit_entry_party'))
|
||||
|
||||
entry = Entry(sample.entry.id)
|
||||
entry.party = self.start.party.id
|
||||
entry.invoice_party = self.start.party.id
|
||||
entry.state = 'draft'
|
||||
entry.ack_report_format = None
|
||||
entry.ack_report_cache = None
|
||||
entry.save()
|
||||
return entry
|
||||
|
||||
def _edit_results_report_party(self, sample, samples):
|
||||
cursor = Transaction().connection.cursor()
|
||||
pool = Pool()
|
||||
Fraction = pool.get('lims.fraction')
|
||||
Notebook = pool.get('lims.notebook')
|
||||
ResultsSample = pool.get('lims.results_report.version.detail.sample')
|
||||
ResultsDetail = pool.get('lims.results_report.version.detail')
|
||||
ResultsVersion = pool.get('lims.results_report.version')
|
||||
ResultsReport = pool.get('lims.results_report')
|
||||
|
||||
if sample.has_results_report:
|
||||
raise UserError(gettext(
|
||||
'lims_industry.msg_edit_results_report_party',
|
||||
sample=sample.rec_name))
|
||||
|
||||
cursor.execute('SELECT rv.results_report '
|
||||
'FROM "' + ResultsVersion._table + '" rv '
|
||||
'INNER JOIN "' + ResultsDetail._table + '" rd '
|
||||
'ON rv.id = rd.report_version '
|
||||
'INNER JOIN "' + ResultsSample._table + '" rs '
|
||||
'ON rd.id = rs.version_detail '
|
||||
'INNER JOIN "' + Notebook._table + '" n '
|
||||
'ON n.id = rs.notebook '
|
||||
'INNER JOIN "' + Fraction._table + '" f '
|
||||
'ON f.id = n.fraction '
|
||||
'WHERE f.sample = %s '
|
||||
'AND rd.state NOT IN (\'released\', \'annulled\')',
|
||||
(str(sample.id),))
|
||||
reports_ids = [x[0] for x in cursor.fetchall()]
|
||||
if not reports_ids:
|
||||
return
|
||||
reports = ResultsReport.browse(reports_ids)
|
||||
ResultsReport.write(reports, {'party': self.start.party.id})
|
||||
|
||||
def check_typifications(self, sample):
|
||||
analysis_domain_ids = sample.on_change_with_analysis_domain()
|
||||
for f in sample.fractions:
|
||||
for s in f.services:
|
||||
if s.analysis.id not in analysis_domain_ids:
|
||||
raise UserError(gettext('lims.msg_not_typified',
|
||||
analysis=s.analysis.rec_name,
|
||||
product_type=sample.product_type.rec_name,
|
||||
matrix=sample.matrix.rec_name))
|
||||
|
|
|
@ -15,6 +15,19 @@
|
|||
<field name="name">sample_list</field>
|
||||
</record>
|
||||
|
||||
<!-- Sample Edition Log -->
|
||||
|
||||
<record model="ir.ui.view" id="sample_edition_log_view_list">
|
||||
<field name="model">lims.sample.edition.log</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">sample_edition_log_list</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="sample_edition_log_view_form">
|
||||
<field name="model">lims.sample.edition.log</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">sample_edition_log_form</field>
|
||||
</record>
|
||||
|
||||
<!-- Fraction Type -->
|
||||
|
||||
<record model="ir.ui.view" id="fraction_type_view_form">
|
||||
|
|
|
@ -8,4 +8,6 @@
|
|||
<field name="equipment"/>
|
||||
<label name="component"/>
|
||||
<field name="component"/>
|
||||
<label name="comercial_product"/>
|
||||
<field name="comercial_product"/>
|
||||
</form>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0"?>
|
||||
<form>
|
||||
<label name="create_date2"/>
|
||||
<field name="create_date2"/>
|
||||
<label name="create_uid"/>
|
||||
<field name="create_uid"/>
|
||||
<label name="field"/>
|
||||
<field name="field" colspan="3"/>
|
||||
<group id="initial_value" colspan="2" yexpand="1" yfill="1" col="1">
|
||||
<separator name="initial_value"/>
|
||||
<field name="initial_value"/>
|
||||
</group>
|
||||
<group id="final_value" colspan="2" yexpand="1" yfill="1" col="1">
|
||||
<separator name="final_value"/>
|
||||
<field name="final_value"/>
|
||||
</group>
|
||||
</form>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0"?>
|
||||
<tree>
|
||||
<field name="create_date2" widget="date"/>
|
||||
<field name="create_date2" widget="time" string="Time"/>
|
||||
<field name="create_uid"/>
|
||||
<field name="field"/>
|
||||
<field name="initial_value"/>
|
||||
<field name="final_value"/>
|
||||
</tree>
|
|
@ -62,4 +62,9 @@
|
|||
<field name="attributes_domain" colspan="4" invisible="1"/>
|
||||
</page>
|
||||
</xpath>
|
||||
<xpath expr="/form/notebook/page[@id='comments']" position="after">
|
||||
<page id="edition_log" string="Edition log">
|
||||
<field name="edition_log" colspan="4"/>
|
||||
</page>
|
||||
</xpath>
|
||||
</data>
|
||||
|
|
Loading…
Reference in New Issue