From c108ee498e45891692477ca606ba567c701294ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Bernardi?= Date: Thu, 3 Jun 2021 21:22:24 -0300 Subject: [PATCH] lims: notebook: add wizards to annull lines and revert annulment --- lims/__init__.py | 4 + lims/locale/es.po | 60 ++++++++++++- lims/notebook.py | 104 ++++++++++++++++++++++- lims/notebook.xml | 45 +++++++++- lims/sample.py | 29 +++++-- lims/view/notebook_accept_lines_form.xml | 2 +- lims/view/notebook_annul_lines_form.xml | 8 ++ lims/view/notebook_line_all_form.xml | 28 +++--- lims/view/notebook_line_all_list.xml | 1 + lims/view/notebook_line_form.xml | 31 ++++--- 10 files changed, 270 insertions(+), 42 deletions(-) create mode 100644 lims/view/notebook_annul_lines_form.xml diff --git a/lims/__init__.py b/lims/__init__.py index 1fc08f0c..aa462fd3 100644 --- a/lims/__init__.py +++ b/lims/__init__.py @@ -147,6 +147,7 @@ def register(): notebook.NotebookLoadResultsManualSit2, notebook.NotebookAddInternalRelationsStart, notebook.NotebookAcceptLinesStart, + notebook.NotebookAnnulLinesStart, notebook.NotebookLineRepeatAnalysisStart, sample.FractionsByLocationsStart, notebook.NotebookResultsVerificationStart, @@ -302,6 +303,9 @@ def register(): notebook.NotebookAcceptLines, notebook.NotebookLineAcceptLines, notebook.NotebookLineUnacceptLines, + notebook.NotebookAnnulLines, + notebook.NotebookLineAnnulLines, + notebook.NotebookLineUnannulLines, notebook.NotebookLineRepeatAnalysis, sample.FractionsByLocations, notebook.NotebookResultsVerification, diff --git a/lims/locale/es.po b/lims/locale/es.po index 34529609..c26e1f0c 100644 --- a/lims/locale/es.po +++ b/lims/locale/es.po @@ -2679,6 +2679,10 @@ msgctxt "field:lims.notebook.add_internal_relations.start,analysis_domain:" msgid "Internal relations domain" msgstr "Dominio para Relaciones internas" +msgctxt "field:lims.notebook.annul_lines.start,annulment_reason:" +msgid "Annulment reason" +msgstr "Motivo de anulación" + msgctxt "field:lims.notebook.generate_results_report.start,append_samples:" msgid "Append samples to existing reports" msgstr "Anexar muestras a informes existentes" @@ -2887,6 +2891,10 @@ msgctxt "field:lims.notebook.line,annulment_date:" msgid "Annulment date" msgstr "Fecha de anulación" +msgctxt "field:lims.notebook.line,annulment_reason:" +msgid "Annulment reason" +msgstr "Motivo de anulación" + msgctxt "field:lims.notebook.line,backup:" msgid "Backup" msgstr "Resguardo" @@ -3195,6 +3203,10 @@ msgctxt "field:lims.notebook.line.all_fields,annulment_date:" msgid "Annulment date" msgstr "Fecha de anulación" +msgctxt "field:lims.notebook.line.all_fields,annulment_reason:" +msgid "Annulment reason" +msgstr "Motivo de anulación" + msgctxt "field:lims.notebook.line.all_fields,backup:" msgid "Backup" msgstr "Resguardo" @@ -7144,12 +7156,16 @@ msgstr "Gestionar servicios" msgctxt "model:ir.action,name:wiz_lims_notebook_accept_lines" msgid "Accept Lines" -msgstr "11) Aceptar Resultados a todas las líneas" +msgstr "11) Aceptar resultados a todas las líneas" msgctxt "model:ir.action,name:wiz_lims_notebook_add_internal_relations" msgid "Add Internal Relations" msgstr "02) Agregar relaciones internas" +msgctxt "model:ir.action,name:wiz_lims_notebook_annul_lines" +msgid "Annul Lines" +msgstr "12) Anular resultados a todas las líneas" + msgctxt "model:ir.action,name:wiz_lims_notebook_initial_concentration_calc" msgid "Initial Concentration Calculation" msgstr "03) Cálculo de concentración inicial" @@ -7168,7 +7184,11 @@ msgstr "09) Validación de límites" msgctxt "model:ir.action,name:wiz_lims_notebook_line_accept_lines" msgid "Accept Lines" -msgstr "11) Aceptar Resultados a las líneas" +msgstr "11) Aceptar resultados a las líneas" + +msgctxt "model:ir.action,name:wiz_lims_notebook_line_annul_lines" +msgid "Annul Lines" +msgstr "13) Anular resultados a las líneas" msgctxt "" "model:ir.action,name:wiz_lims_notebook_line_initial_concentration_calc" @@ -7206,8 +7226,12 @@ msgid "Results Verification" msgstr "08) Verificación de resultados" msgctxt "model:ir.action,name:wiz_lims_notebook_line_unaccept_lines" -msgid "Unaccept Lines" -msgstr "12) Revertir Aceptación de Resultados a las líneas" +msgid "Revert Lines Acceptance" +msgstr "12) Revertir Aceptación de resultados a las líneas" + +msgctxt "model:ir.action,name:wiz_lims_notebook_line_unannul_lines" +msgid "Revert Lines Annulment" +msgstr "14) Revertir Anulación de resultados a las líneas" msgctxt "model:ir.action,name:wiz_lims_notebook_line_uncertainty_calc" msgid "Uncertainty Calculation" @@ -9158,6 +9182,10 @@ msgctxt "model:lims.notebook.add_internal_relations.start,name:" msgid "Add Internal Relations" msgstr "Agregar relaciones internas" +msgctxt "model:lims.notebook.annul_lines.start,name:" +msgid "Annul Lines" +msgstr "Anular líneas" + msgctxt "model:lims.notebook.evaluate_rules.start,name:" msgid "Evaluate Rules" msgstr "Evaluar Reglas de cuaderno" @@ -12882,6 +12910,10 @@ msgctxt "selection:lims.rule.condition,condition:" msgid ">=" msgstr ">=" +msgctxt "selection:lims.sample,state:" +msgid "Annulled" +msgstr "Anulada" + msgctxt "selection:lims.sample,state:" msgid "Draft" msgstr "Borrador" @@ -13574,6 +13606,10 @@ msgctxt "view:lims.notebook.add_internal_relations.start:" msgid "Add Internal Relations" msgstr "Agregar relaciones internas" +msgctxt "view:lims.notebook.annul_lines.start:" +msgid "Annul all lines?" +msgstr "¿Anular todas las líneas?" + msgctxt "view:lims.notebook.evaluate_rules.start:" msgid "Evaluate rules?" msgstr "¿Evaluar reglas de cuaderno?" @@ -14603,6 +14639,14 @@ msgctxt "wizard_button:lims.notebook.add_internal_relations,start,end:" msgid "Cancel" msgstr "Cancelar" +msgctxt "wizard_button:lims.notebook.annul_lines,start,end:" +msgid "Cancel" +msgstr "Cancelar" + +msgctxt "wizard_button:lims.notebook.annul_lines,start,ok:" +msgid "Ok" +msgstr "Aceptar" + msgctxt "wizard_button:lims.notebook.evaluate_rules,start,end:" msgid "Cancel" msgstr "Cancelar" @@ -14802,6 +14846,14 @@ msgctxt "wizard_button:lims.notebook_line.accept_lines,start,ok:" msgid "Ok" msgstr "Aceptar" +msgctxt "wizard_button:lims.notebook_line.annul_lines,start,end:" +msgid "Cancel" +msgstr "Cancelar" + +msgctxt "wizard_button:lims.notebook_line.annul_lines,start,ok:" +msgid "Ok" +msgstr "Aceptar" + msgctxt "wizard_button:lims.notebook_line.evaluate_rules,start,end:" msgid "Cancel" msgstr "Cancelar" diff --git a/lims/notebook.py b/lims/notebook.py index 91c87b53..bdd232a7 100644 --- a/lims/notebook.py +++ b/lims/notebook.py @@ -912,6 +912,9 @@ class NotebookLine(ModelSQL, ModelView): select=True) annulment_date = fields.DateTime('Annulment date', states={'readonly': True}) + annulment_reason = fields.Text('Annulment reason', + states={'readonly': True, 'invisible': ~Eval('annulled')}, + depends=['annulled']) results_report = fields.Many2One('lims.results_report', 'Results Report', readonly=True, select=True) planification = fields.Many2One('lims.planification', 'Planification', @@ -1723,6 +1726,9 @@ class NotebookLineAllFields(ModelSQL, ModelView): acceptance_date = fields.DateTime('Acceptance date', readonly=True) annulled = fields.Boolean('Annulled', readonly=True) annulment_date = fields.DateTime('Annulment date', readonly=True) + annulment_reason = fields.Text('Annulment reason', readonly=True, + states={'invisible': ~Eval('annulled')}, + depends=['annulled']) results_report = fields.Many2One('lims.results_report', 'Results Report', readonly=True) planification = fields.Many2One('lims.planification', 'Planification', @@ -1827,6 +1833,7 @@ class NotebookLineAllFields(ModelSQL, ModelView): line.acceptance_date, line.annulled, line.annulment_date, + line.annulment_reason, line.results_report, line.planification, detail.confirmation_date, @@ -4856,7 +4863,7 @@ class NotebookLineAcceptLines(NotebookAcceptLines): class NotebookLineUnacceptLines(Wizard): - 'Unaccept Lines' + 'Revert Lines Acceptance' __name__ = 'lims.notebook_line.unaccept_lines' start_state = 'ok' @@ -4901,6 +4908,101 @@ class NotebookLineUnacceptLines(Wizard): return 'reload' +class NotebookAnnulLinesStart(ModelView): + 'Annul Lines' + __name__ = 'lims.notebook.annul_lines.start' + + annulment_reason = fields.Text('Annulment reason') + + +class NotebookAnnulLines(Wizard): + 'Annul Lines' + __name__ = 'lims.notebook.annul_lines' + + start = StateView('lims.notebook.annul_lines.start', + 'lims.lims_notebook_annul_lines_start_view_form', [ + Button('Cancel', 'end', 'tryton-cancel'), + Button('Ok', 'ok', 'tryton-ok', default=True), + ]) + ok = StateTransition() + + def transition_ok(self): + NotebookLine = Pool().get('lims.notebook.line') + + notebook_lines = NotebookLine.search([ + ('notebook', 'in', Transaction().context['active_ids']), + ('accepted', '=', False), + ('annulled', '=', False), + ]) + if notebook_lines: + self.lines_annul(notebook_lines) + return 'end' + + def lines_annul(self, notebook_lines): + NotebookLine = Pool().get('lims.notebook.line') + + NotebookLine.write(notebook_lines, { + 'result_modifier': 'na', + 'annulled': True, + 'annulment_date': datetime.now(), + 'annulment_reason': self.start.annulment_reason, + 'report': False, + }) + + def end(self): + return 'reload' + + +class NotebookLineAnnulLines(NotebookAnnulLines): + 'Annul Lines' + __name__ = 'lims.notebook_line.annul_lines' + + def transition_ok(self): + NotebookLine = Pool().get('lims.notebook.line') + + notebook_lines = NotebookLine.search([ + ('id', 'in', Transaction().context['active_ids']), + ('accepted', '=', False), + ('annulled', '=', False), + ]) + if notebook_lines: + self.lines_annul(notebook_lines) + return 'end' + + +class NotebookLineUnannulLines(Wizard): + 'Revert Lines Annulment' + __name__ = 'lims.notebook_line.unannul_lines' + + start_state = 'ok' + ok = StateTransition() + + def transition_ok(self): + NotebookLine = Pool().get('lims.notebook.line') + + notebook_lines = NotebookLine.search([ + ('id', 'in', Transaction().context['active_ids']), + ('annulled', '=', True), + ]) + if notebook_lines: + self.lines_unannul(notebook_lines) + return 'end' + + def lines_unannul(self, notebook_lines): + NotebookLine = Pool().get('lims.notebook.line') + + NotebookLine.write(notebook_lines, { + 'result_modifier': 'eq', + 'annulled': False, + 'annulment_date': None, + 'annulment_reason': None, + 'report': True, + }) + + def end(self): + return 'reload' + + class NotebookResultsVerificationStart(ModelView): 'Results Verification' __name__ = 'lims.notebook.results_verification.start' diff --git a/lims/notebook.xml b/lims/notebook.xml index bc4b162f..cd29d108 100644 --- a/lims/notebook.xml +++ b/lims/notebook.xml @@ -620,10 +620,10 @@ - + - Unaccept Lines + Revert Lines Acceptance lims.notebook_line.unaccept_lines @@ -639,6 +639,47 @@ + + + + lims.notebook.annul_lines.start + form + notebook_annul_lines_form + + + + Annul Lines + lims.notebook.annul_lines + + + form_action + lims.notebook,-1 + + + + + Annul Lines + lims.notebook_line.annul_lines + + + form_action + lims.notebook.line,-1 + + + + + + + Revert Lines Annulment + lims.notebook_line.unannul_lines + + + + form_action + lims.notebook.line,-1 + + + diff --git a/lims/sample.py b/lims/sample.py index 269536e7..146ddb90 100644 --- a/lims/sample.py +++ b/lims/sample.py @@ -2502,6 +2502,7 @@ class Sample(ModelSQL, ModelView): 'get_results_reports_list', searcher='search_results_reports_list') state = fields.Selection([ ('draft', 'Draft'), + ('annulled', 'Annulled'), ('pending_planning', 'Pending Planification'), ('planned', 'Planned'), ('in_lab', 'In Laboratory'), @@ -2918,14 +2919,15 @@ class Sample(ModelSQL, ModelView): def order_state(tables): table, _ = tables[None] order = [Case((table.state == 'draft', 1), - else_=Case((table.state == 'pending_planning', 2), - else_=Case((table.state == 'planned', 3), - else_=Case((table.state == 'in_lab', 4), - else_=Case((table.state == 'lab_pending_acceptance', 5), - else_=Case((table.state == 'pending_report', 6), - else_=Case((table.state == 'in_report', 7), - else_=Case((table.state == 'report_released', 8), - else_=0))))))))] + else_=Case((table.state == 'annulled', 2), + else_=Case((table.state == 'pending_planning', 3), + else_=Case((table.state == 'planned', 4), + else_=Case((table.state == 'in_lab', 5), + else_=Case((table.state == 'lab_pending_acceptance', 6), + else_=Case((table.state == 'pending_report', 7), + else_=Case((table.state == 'in_report', 8), + else_=Case((table.state == 'report_released', 9), + else_=0)))))))))] return order def get_confirmed(self, name=None): @@ -3348,6 +3350,17 @@ class Sample(ModelSQL, ModelView): return 'in_lab' return 'planned' if self.confirmation_date: + cursor.execute('SELECT COUNT(*) ' + 'FROM "' + NotebookLine._table + '" nl ' + 'INNER JOIN "' + Service._table + '" s ' + 'ON s.id = nl.service ' + 'INNER JOIN "' + Fraction._table + '" f ' + 'ON f.id = s.fraction ' + 'WHERE f.sample = %s ' + 'AND nl.annulled = FALSE', + (self.id,)) + if cursor.fetchone()[0] == 0: + return 'annulled' return 'pending_planning' return 'draft' diff --git a/lims/view/notebook_accept_lines_form.xml b/lims/view/notebook_accept_lines_form.xml index d1a69571..4ecfa622 100644 --- a/lims/view/notebook_accept_lines_form.xml +++ b/lims/view/notebook_accept_lines_form.xml @@ -2,5 +2,5 @@