changeset 4815:3e49997e14fa

task #16043: Migration to GNU Health 4.0: Initial migration of health_inpatient package
author Luis Falcon <falcon@gnuhealth.org>
date Tue, 21 Dec 2021 00:17:12 +0000
parents e159b19e21c2
children c38c485dbbde
files tryton/health_inpatient/__init__.py tryton/health_inpatient/data/health_inpatient_sequence.xml tryton/health_inpatient/data/messages/messages.xml tryton/health_inpatient/exceptions.py tryton/health_inpatient/health_inpatient.py tryton/health_inpatient/sequences.py tryton/health_inpatient/tryton.cfg tryton/health_inpatient/view/gnuhealth_bed_transfer_tree.xml tryton/health_inpatient/view/gnuhealth_inpatient_diet_therapeutic_tree.xml tryton/health_inpatient/view/gnuhealth_inpatient_diet_tree.xml tryton/health_inpatient/view/gnuhealth_inpatient_meal_order_item_tree.xml tryton/health_inpatient/view/gnuhealth_inpatient_med_admin_time_tree.xml tryton/health_inpatient/view/gnuhealth_inpatient_med_log_tree.xml tryton/health_inpatient/wizard/wizard_health_inpatient.py tryton/health_inpatient/wizard/wizard_inpatient_evaluation.py
diffstat 15 files changed, 288 insertions(+), 202 deletions(-) [+]
line wrap: on
line diff
--- a/tryton/health_inpatient/__init__.py
+++ b/tryton/health_inpatient/__init__.py
@@ -22,33 +22,33 @@
 ##############################################################################
 
 from trytond.pool import Pool
-from .health_inpatient import *
-from .wizard import *
-
+from . import health_inpatient
+from . import wizard
+from . import sequences
 
 def register():
     Pool.register(
-        GnuHealthSequences,
-        GnuHealthSequenceSetup,
-        DietTherapeutic,
-        InpatientRegistration,
-        BedTransfer,
-        Appointment,
-        PatientEvaluation,
-        ECG,
-        PatientData,
-        InpatientMedication,
-        InpatientMedicationAdminTimes,
-        InpatientMedicationLog,
-        InpatientDiet,
-        CreateBedTransferInit,
-        InpatientMeal,
-        InpatientMealOrder,
-        InpatientMealOrderItem,
+        health_inpatient.DietTherapeutic,
+        health_inpatient.InpatientRegistration,
+        health_inpatient.BedTransfer,
+        health_inpatient.Appointment,
+        health_inpatient.PatientEvaluation,
+        health_inpatient.ECG,
+        health_inpatient.PatientData,
+        health_inpatient.InpatientMedication,
+        health_inpatient.InpatientMedicationAdminTimes,
+        health_inpatient.InpatientMedicationLog,
+        health_inpatient.InpatientDiet,
+        wizard.CreateBedTransferInit,
+        health_inpatient.InpatientMeal,
+        health_inpatient.InpatientMealOrder,
+        health_inpatient.InpatientMealOrderItem,
+        sequences.GnuHealthSequences,
+        sequences.InpatientRegistrationSequence,
+        sequences.InpatientMealOrderSequence,
         module='health_inpatient', type_='model')
     
     Pool.register(
-        CreateBedTransfer,
-        CreateInpatientEvaluation,
+        wizard.CreateBedTransfer,
+        wizard.CreateInpatientEvaluation,
         module='health_inpatient', type_='wizard')
-
--- a/tryton/health_inpatient/data/health_inpatient_sequence.xml
+++ b/tryton/health_inpatient/data/health_inpatient_sequence.xml
@@ -6,12 +6,11 @@
 
         <record id="seq_type_gnuhealth_inpatient_registration" model="ir.sequence.type">
             <field name="name">Inpatient Registration</field>
-            <field name="code">gnuhealth.inpatient.registration</field>
         </record>
 
         <record id="seq_gnuhealth_inpatient_registration" model="ir.sequence">
             <field name="name">Inpatient Registration</field>
-            <field name="code">gnuhealth.inpatient.registration</field>
+            <field name="sequence_type" ref="seq_type_gnuhealth_inpatient_registration"></field>
             <field name="prefix">INPAC</field>
             <field name="padding">3</field>
         </record>
@@ -20,12 +19,11 @@
 
         <record id="seq_type_gnuhealth_inpatient_meal_order" model="ir.sequence.type">
             <field name="name">Inpatient Meal Order</field>
-            <field name="code">gnuhealth.inpatient.meal.order</field>
         </record>
 
         <record id="seq_gnuhealth_inpatient_meal_order" model="ir.sequence">
             <field name="name">Inpatient Meal Order</field>
-            <field name="code">gnuhealth.inpatient.meal.order</field>
+            <field name="sequence_type" ref="seq_type_gnuhealth_inpatient_meal_order"></field>
             <field name="prefix">MEAL</field>
             <field name="padding">3</field>
         </record>
new file mode 100644
--- /dev/null
+++ b/tryton/health_inpatient/data/messages/messages.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!-- This file is part of GNU Health.  The COPYRIGHT file at the top level of
+this repository contains the full copyright notices and license terms. -->
+<tryton>
+    <data grouped="1">
+        <record model="ir.message" id="msg_no_associated_health_professional">
+            <field name="text">There is no health professional associated to this user</field>
+        </record>
+        <record model="ir.message" id="msg_bed_is_not_available">
+            <field name="text">Bed is not available</field>
+        </record>
+        <record model="ir.message" id="msg_destination_bed_not_available">
+            <field name="text">Destination bed is not available</field>
+        </record>
+        <record model="ir.message" id="msg_discharge_reason_needed">
+            <field name="text">Admission and Discharge reasons as well as Discharge Dx are needed</field>
+        </record>
+        <record model="ir.message" id="msg_discharge_befor_admission">
+            <field name="text">The Discharge date must later than the admission</field>
+        </record>
+        <record model="ir.message" id="msg_need_timezone">
+            <field name="text">Need timezone</field>
+        </record>
+        <record model="ir.message" id="msg_special_meal_needs">
+            <field name="text">This patient has special meal needs</field>
+        </record>
+        <record model="ir.message" id="msg_many_records_chosen">
+            <field name="text">You have chosen more than 1 record. Please choose only one</field>
+        </record>
+        <record model="ir.message" id="msg_no_record_selected">
+            <field name="text">You need to select one record</field>
+        </record>
+    </data>
+</tryton>
new file mode 100644
--- /dev/null
+++ b/tryton/health_inpatient/exceptions.py
@@ -0,0 +1,35 @@
+# This file is part of GNU Health.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.exceptions import UserError, UserWarning
+from trytond.model.exceptions import ValidationError
+
+
+class NoAssociatedHealthProfessional(ValidationError):
+    pass
+
+class BedIsNotAvailable(UserError):
+    pass
+
+class DischargeReasonNeeded(UserError):
+    pass
+
+class DischargeBeforeAdmission(UserError):
+    pass
+
+class DestinationBedNotavailable(UserError):
+    pass
+
+class NeedTimeZone(UserError):
+    pass
+
+class AdmissionMustBeToday(UserError):
+    pass
+
+class ManyRecordsChosen(UserError):
+    pass
+
+class NoRecordSelected(UserError):
+    pass
+
+class SpecialMealNeeds(UserWarning):
+    pass
--- a/tryton/health_inpatient/health_inpatient.py
+++ b/tryton/health_inpatient/health_inpatient.py
@@ -30,109 +30,26 @@
 from trytond.pyson import Eval, Not, Bool, And, Equal, Or
 from trytond import backend
 from trytond.tools.multivalue import migrate_property
+from trytond.pyson import Id
+from trytond.modules.health.core import get_health_professional, get_institution
 
 import pytz
 
+from .exceptions import (
+    NoAssociatedHealthProfessional, BedIsNotAvailable,
+    DischargeReasonNeeded, DischargeBeforeAdmission,
+    DestinationBedNotavailable, NeedTimeZone,
+    AdmissionMustBeToday, SpecialMealNeeds
+    )
 
 
-__all__ = ['GnuHealthSequences', 'GnuHealthSequenceSetup',
+__all__ = [
     'DietTherapeutic','InpatientRegistration', 
     'BedTransfer', 'Appointment', 'PatientEvaluation', 'PatientData',
     'InpatientMedication', 'InpatientMedicationAdminTimes',
     'InpatientMedicationLog', 'InpatientDiet', 'InpatientMeal',
     'InpatientMealOrder','InpatientMealOrderItem', 'ECG']
 
-
-sequences = ['inpatient_registration_sequence',
-            'inpatient_meal_order_sequence']
-
-
-class GnuHealthSequences(ModelSingleton, ModelSQL, ModelView, ValueMixin):
-    'GNU Health Sequences'
-    __name__ = 'gnuhealth.sequences'
-
-    inpatient_registration_sequence = fields.MultiValue(fields.Many2One(
-        'ir.sequence', 'Inpatient Sequence', required=True,
-        domain=[('code', '=', 'gnuhealth.inpatient.registration')]))
-
-    inpatient_meal_order_sequence = fields.MultiValue(fields.Many2One(
-        'ir.sequence', 'Inpatient Meal Sequence', required=True,
-        domain=[('code', '=', 'gnuhealth.inpatient.meal.order')]))
-
-
-    @classmethod
-    def multivalue_model(cls, field):
-        pool = Pool()
-
-        if field in sequences:
-            return pool.get('gnuhealth.sequence.setup')
-        return super(GnuHealthSequences, cls).multivalue_model(field)
-
-
-    @classmethod
-    def default_inpatient_registration_sequence(cls):
-        return cls.multivalue_model(
-            'inpatient_registration_sequence').default_inpatient_registration_sequence()
-
-
-    @classmethod
-    def default_inpatient_meal_order_sequence(cls):
-        return cls.multivalue_model(
-            'inpatient_meal_order_sequence').default_inpatient_meal_order_sequence()
-
-    
-# SEQUENCE SETUP
-class GnuHealthSequenceSetup(ModelSQL, ValueMixin):
-    'GNU Health Sequences Setup'
-    __name__ = 'gnuhealth.sequence.setup'
-
-    inpatient_registration_sequence = fields.Many2One('ir.sequence', 
-        'Inpatient Sequence', required=True,
-        domain=[('code', '=', 'gnuhealth.inpatient.registration')])
-
-
-    inpatient_meal_order_sequence = fields.Many2One('ir.sequence',
-        'Inpatient Meal Sequence', required=True,
-        domain=[('code', '=', 'gnuhealth.inpatient.meal.order')])
-
-  
-    @classmethod
-    def __register__(cls, module_name):
-        TableHandler = backend.get('TableHandler')
-        exist = TableHandler.table_exist(cls._table)
-
-        super(GnuHealthSequenceSetup, cls).__register__(module_name)
-
-        if not exist:
-            cls._migrate_property([], [], [])
-
-    @classmethod
-    def _migrate_property(cls, field_names, value_names, fields):
-        field_names.extend(sequences)
-        value_names.extend(sequences)
-        migrate_property(
-            'gnuhealth.sequences', field_names, cls, value_names,
-            fields=fields)
-
-    @classmethod
-    def default_inpatient_registration_sequence(cls):
-        pool = Pool()
-        ModelData = pool.get('ir.model.data')
-        return ModelData.get_id(
-            'health_inpatient', 'seq_gnuhealth_inpatient_registration')
-
-    @classmethod
-    def default_inpatient_meal_order_sequence(cls):
-        pool = Pool()
-        ModelData = pool.get('ir.model.data')
-        return ModelData.get_id(
-            'health_inpatient', 'seq_gnuhealth_inpatient_meal_order')
-    
-# END SEQUENCE SETUP , MIGRATION FROM FIELDS.PROPERTY
-
-
-
-
 # Therapeutic Diet types
 
 class DietTherapeutic (ModelSQL, ModelView):
@@ -243,9 +160,7 @@
 
     @staticmethod
     def default_institution():
-        HealthInst = Pool().get('gnuhealth.institution')
-        institution = HealthInst.get_institution()
-        return institution
+        return get_institution()
 
     def get_patient_puid(self, name):
         return self.patient.name.ref
@@ -266,12 +181,6 @@
                 'The Registration code already exists'),
             ]
 
-        cls._error_messages.update({
-                'bed_is_not_available': 'Bed is not available',
-                'discharge_reason_needed': 'Admission and Discharge reasons \n'
-                'as well as Discharge Dx are needed',
-                'destination_bed_unavailable': 'Destination bed unavailable',
-                'need_timezone':'You need to set up the company timezone'})
         cls._buttons.update({
                 'confirmed': {
                     'invisible': And(Not(Equal(Eval('state'), 'free')),
@@ -313,10 +222,12 @@
         res = cursor.fetchone()
         if (registration_id.discharge_date.date() <
             registration_id.hospitalization_date.date()):
-            cls.raise_user_error("The Discharge date must later than the " \
-                "Admission")
+                raise DischargeBeforeAdmission(
+                    gettext('health_inpatient.msg_discharge_befor_admission'))
+
         if res[0] > 0:
-            cls.raise_user_error('bed_is_not_available')
+            raise BedIsNotAvailable(
+                gettext('health_inpatient.msg_bed_is_not_available'))
         else:
             cls.write(registrations, {'state': 'confirmed'})
             Bed.write([registration_id.bed], {'state': 'reserved'})
@@ -327,10 +238,10 @@
         registration_id = registrations[0]
         Bed = Pool().get('gnuhealth.hospital.bed')
 
-        signing_hp = Pool().get('gnuhealth.healthprofessional').get_health_professional()
+        signing_hp = get_health_professional()
         if not signing_hp:
-            cls.raise_user_error(
-                "No health professional associated to this user !")
+            raise NoAssociatedHealthProfessional(
+                gettext('health_inpatient.msg_no_associated_health_professional'))
 
         cls.write(registrations, {'state': 'done',
             'discharged_by': signing_hp})
@@ -377,26 +288,33 @@
 
                 if (registration_id.hospitalization_date.date() !=
                     dt_local.date()):
-                    cls.raise_user_error("The Admission date must be today")
+                    raise AdmissionMustBeToday(
+                        gettext('health_inpatient.msg_admission_must_be_today'))
                 else:
                     cls.write(registrations, {'state': 'hospitalized'})
                     Bed.write([registration_id.bed], {'state': 'occupied'})
 
             else:
-               cls.raise_user_error('need_timezone')
+                raise NeedTimeZone(
+                    gettext('health_inpatient.msg_need_timezone'))
+
+
+    @classmethod
+    def generate_code(cls, **pattern):
+        Config = Pool().get('gnuhealth.sequences')
+        config = Config(1)
+        sequence = config.get_multivalue(
+            'inpatient_registration_sequence', **pattern)
+        if sequence:
+            return sequence.get()
 
     @classmethod
     def create(cls, vlist):
-        Sequence = Pool().get('ir.sequence')
-        Config = Pool().get('gnuhealth.sequences')
-
         vlist = [x.copy() for x in vlist]
         for values in vlist:
             if not values.get('name'):
-                config = Config(1)
-                values['name'] = Sequence.get_id(
-                    config.inpatient_registration_sequence.id)
-        return super(InpatientRegistration, cls).create(vlist)
+                values['name'] = cls.generate_code()
+        return super(PatientAmbulatoryCare, cls).create(vlist)
 
     @staticmethod
     def default_state():
@@ -413,7 +331,8 @@
         if ((not self.discharge_reason or not self.discharge_dx
             or not self.admission_reason)
             and self.state == 'done'):
-                self.raise_user_error('discharge_reason_needed')
+                raise DischargeReasonNeeded(
+                    gettext('health_inpatient.msg_discharge_reason_needed'))
 
     
     # Format Registration ID : Patient : Bed
@@ -646,14 +565,6 @@
         help='specific remarks for this dose')
 
     @classmethod
-    def __setup__(cls):
-        super(InpatientMedicationLog, cls).__setup__()
-        cls._error_messages.update({
-            'health_professional_warning':
-                    'No health professional associated to this user',
-        })
-
-    @classmethod
     def validate(cls, records):
         super(InpatientMedicationLog, cls).validate(records)
         for record in records:
@@ -661,12 +572,12 @@
 
     def check_health_professional(self):
         if not self.health_professional:
-            self.raise_user_error('health_professional_warning')
+            raise NoAssociatedHealthProfessional(
+                gettext('health.msg_no_associated_health_professional'))
 
     @staticmethod
     def default_health_professional():
-        pool = Pool()
-        return pool.get('gnuhealth.healthprofessional').get_health_professional()
+        return get_health_professional()
 
     @staticmethod
     def default_admin_time():
@@ -780,22 +691,28 @@
 
     @staticmethod
     def default_health_professional():
-        pool = Pool()
-        return pool.get('gnuhealth.healthprofessional').get_health_professional()
+        return get_health_professional()
+
+
+
+    @classmethod
+    def generate_code(cls, **pattern):
+        Config = Pool().get('gnuhealth.sequences')
+        config = Config(1)
+        sequence = config.get_multivalue(
+            'inpatient_meal_order_sequence', **pattern)
+        if sequence:
+            return sequence.get()
 
     @classmethod
     def create(cls, vlist):
-        Sequence = Pool().get('ir.sequence')
-        Config = Pool().get('gnuhealth.sequences')
-
         vlist = [x.copy() for x in vlist]
         for values in vlist:
             if not values.get('meal_order'):
-                config = Config(1)
-                values['meal_order'] = Sequence.get_id(
-                    config.inpatient_meal_order_sequence.id)
+                values['meal_order'] = cls.generate_code()
         return super(InpatientMealOrder, cls).create(vlist)
 
+
     @classmethod
     def validate(cls, meal_orders):
         super(InpatientMealOrder, cls).validate(meal_orders)
@@ -805,11 +722,13 @@
             
     def check_meal_order_warning(self):
         if not self.meal_warning_ack and self.meal_warning:
-            self.raise_user_error('meal_order_warning')
+            raise SpecialMealNeeds(
+                gettext('health_inpatient.msg_special_meal_needs'))
 
     def check_health_professional(self):
         if not self.health_professional:
-            self.raise_user_error('health_professional_warning')
+            raise NoAssociatedHealthProfessional(
+                gettext('health.msg_no_associated_health_professional'))
 
 
     @fields.depends('name')
@@ -839,16 +758,6 @@
             'done': {'invisible': Not(Equal(Eval('state'), 'ordered'))}
             })
 
-        cls._error_messages.update({
-            'meal_order_warning':
-            '===== MEAL WARNING ! =====\n\n\n'
-            'This patient has special meal needs \n\n'
-            'Check and acknowledge that\n'
-            'the meal items in this order are correct \n\n',
-            'health_professional_warning':
-            'No health professional associated to this user',
-            })
-
         t = cls.__table__()
         cls._sql_constraints = [
             ('meal_order_uniq', Unique(t,t.meal_order),
new file mode 100644
--- /dev/null
+++ b/tryton/health_inpatient/sequences.py
@@ -0,0 +1,120 @@
+##############################################################################
+#
+#    GNU Health HMIS: The Free Health and Hospital Information System
+#    Copyright (C) 2008-2021 Luis Falcon <falcon@gnuhealth.org>
+#    Copyright (C) 2011-2021 GNU Solidario <health@gnusolidario.org>
+#
+#    The GNU Health HMIS component is part of the GNU Health project
+#    www.gnuhealth.org
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+# GNU Health HMIS sequences for this package
+
+from trytond.model import (ModelView, ModelSingleton, ModelSQL,
+                           ValueMixin, MultiValueMixin, fields)
+from trytond import backend
+from trytond.pyson import Id
+from trytond.pool import Pool
+from trytond.tools.multivalue import migrate_property
+
+# Sequences
+inpatient_registration_sequence = fields.Many2One(
+    'ir.sequence', 'Inpatient Registration Sequence', required=True,
+    domain=[('sequence_type', '=', Id(
+        'health', 'seq_type_gnuhealth_inpatient_registration'))])
+
+inpatient_meal_order_sequence = fields.Many2One(
+    'ir.sequence', 'Patient Rounding Sequence', required=True,
+    domain=[('sequence_type', '=', Id(
+        'health', 'seq_gnuhealth_inpatient_registration'))])
+
+
+
+# GNU HEALTH SEQUENCES
+class GnuHealthSequences(ModelSingleton, ModelSQL, ModelView, MultiValueMixin):
+    'Standard Sequences for GNU Health'
+    __name__ = 'gnuhealth.sequences'
+
+    inpatient_registration_sequence = fields.MultiValue(
+        inpatient_registration_sequence)
+
+    inpatient_meal_order_sequence = fields.MultiValue(
+        inpatient_meal_order_sequence)
+
+
+    @classmethod
+    def default_inpatient_registration_sequence(cls, **pattern):
+        pool = Pool()
+        ModelData = pool.get('ir.model.data')
+        try:
+            return ModelData.get_id('health',
+                                    'seq_gnuhealth_patient')
+        except KeyError:
+            return None
+
+    @classmethod
+    def default_inpatient_meal_order_sequence(cls, **pattern):
+        pool = Pool()
+        ModelData = pool.get('ir.model.data')
+        try:
+            return ModelData.get_id('health',
+                                    'seq_gnuhealth_patient_evaluation')
+        except KeyError:
+            return None
+
+class _ConfigurationValue(ModelSQL):
+
+    _configuration_value_field = None
+
+    @classmethod
+    def __register__(cls, module_name):
+        exist = backend.TableHandler.table_exist(cls._table)
+
+        super(_ConfigurationValue, cls).__register__(module_name)
+
+        if not exist:
+            cls._migrate_property([], [], [])
+
+    @classmethod
+    def _migrate_property(cls, field_names, value_names, fields):
+        field_names.append(cls._configuration_value_field)
+        value_names.append(cls._configuration_value_field)
+        migrate_property(
+            'gnuhealth.sequences', field_names, cls, value_names,
+            fields=fields)
+
+
+class InpatientRegistrationSequence(_ConfigurationValue, ModelSQL, ValueMixin):
+    'Ambulatory Care Sequences setup'
+    __name__ = 'gnuhealth.sequences.inpatient_registration_sequence'
+    inpatient_registration_sequence = inpatient_registration_sequence
+    _configuration_value_field = 'inpatient_registration_sequence'
+
+    @classmethod
+    def check_xml_record(cls, records, values):
+        return True
+
+
+class InpatientMealOrderSequence(_ConfigurationValue, ModelSQL, ValueMixin):
+    'Patient Evaluation Sequence setup'
+    __name__ = 'gnuhealth.sequences.inpatient_meal_order_sequence'
+    inpatient_meal_order_sequence = inpatient_meal_order_sequence
+    _configuration_value_field = 'inpatient_meal_order_sequence'
+
+    @classmethod
+    def check_xml_record(cls, records, values):
+        return True
--- a/tryton/health_inpatient/tryton.cfg
+++ b/tryton/health_inpatient/tryton.cfg
@@ -1,5 +1,5 @@
 [tryton]
-version=3.8.0
+version=3.9.0
 depends:
     health
     health_lifestyle
@@ -7,6 +7,7 @@
     health_inpatient_view.xml
     data/health_inpatient_sequence.xml
     data/inpatient_diets.xml
+    data/messages/messages.xml
     wizard/bed_transfer_wizard.xml
     wizard/inpatient_evaluation.xml
     security/access_rights.xml
--- a/tryton/health_inpatient/view/gnuhealth_bed_transfer_tree.xml
+++ b/tryton/health_inpatient/view/gnuhealth_bed_transfer_tree.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<tree editable="top">
+<tree editable="1">
     <field name="transfer_date" widget="date"/>
     <field name="transfer_date" widget="time"/>
     <field name="bed_from" expand="1"/>
--- a/tryton/health_inpatient/view/gnuhealth_inpatient_diet_therapeutic_tree.xml
+++ b/tryton/health_inpatient/view/gnuhealth_inpatient_diet_therapeutic_tree.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<tree editable="top">
+<tree editable="1">
     <field name="name" expand="1"/>
     <field name="code" expand="1"/>
     <field name="description"/>
--- a/tryton/health_inpatient/view/gnuhealth_inpatient_diet_tree.xml
+++ b/tryton/health_inpatient/view/gnuhealth_inpatient_diet_tree.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<tree editable="top">
+<tree editable="1">
     <field name="diet" expand="1"/>
     <field name="remarks" expand="1"/>
 </tree>
--- a/tryton/health_inpatient/view/gnuhealth_inpatient_meal_order_item_tree.xml
+++ b/tryton/health_inpatient/view/gnuhealth_inpatient_meal_order_item_tree.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<tree editable="top">
+<tree editable="1">
     <field name="name" expand="1"/>
     <field name="meal" expand="1"/>
     <field name="remarks" expand="1"/>
--- a/tryton/health_inpatient/view/gnuhealth_inpatient_med_admin_time_tree.xml
+++ b/tryton/health_inpatient/view/gnuhealth_inpatient_med_admin_time_tree.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<tree editable="top">
+<tree editable="1">
     <field name="admin_time"/>
     <field name="dose"/>
     <field name="dose_unit"/>
--- a/tryton/health_inpatient/view/gnuhealth_inpatient_med_log_tree.xml
+++ b/tryton/health_inpatient/view/gnuhealth_inpatient_med_log_tree.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<tree editable="top">
+<tree editable="1">
     <field name="admin_time" widget="date"/>
     <field name="admin_time" widget="time"/>
     <field name="health_professional" expand="1"/>
--- a/tryton/health_inpatient/wizard/wizard_health_inpatient.py
+++ b/tryton/health_inpatient/wizard/wizard_health_inpatient.py
@@ -26,7 +26,7 @@
 from trytond.wizard import Wizard, StateTransition, StateView, Button
 from trytond.transaction import Transaction
 from trytond.pool import Pool
-
+from ..exceptions import DestinationBedNotavailable, ManyRecordsChosen
 
 __all__ = ['CreateBedTransferInit', 'CreateBedTransfer']
 
@@ -65,13 +65,6 @@
     create_bed_transfer = StateTransition()
 
 
-    @classmethod
-    def __setup__(cls):
-        super(CreateBedTransfer, cls).__setup__()
-        cls._error_messages.update({
-            'bed_unavailable': 'Destination bed is unavailable',
-            'choose_one': 'You have chosen more than 1 records. Please choose only one'})
-
     def transition_create_bed_transfer(self):
         inpatient_registrations = Pool().get('gnuhealth.inpatient.registration')
         bed = Pool().get('gnuhealth.hospital.bed')
@@ -81,7 +74,8 @@
 
         # Don't allow mass changes. Work on a single record
         if len(registrations) > 1 :
-            self.raise_user_error('choose_one')
+            raise ManyRecordsChosen(
+                gettext('health_inpatient.msg_many_records_chosen'))
 
         registration = registrations[0]
         current_bed = registration.bed
@@ -118,7 +112,8 @@
 
 
         else:
-            self.raise_user_error('bed_unavailable')
+            raise DestinationBedNotAvailable(
+                gettext('health_inpatient.msg_destination_bed_not_available'))
 
         return 'end'
 
--- a/tryton/health_inpatient/wizard/wizard_inpatient_evaluation.py
+++ b/tryton/health_inpatient/wizard/wizard_inpatient_evaluation.py
@@ -27,6 +27,7 @@
 from trytond.pool import Pool
 from trytond.pyson import PYSONEncoder
 
+from ..exceptions import NoRecordSelected
 
 __all__ = ['CreateInpatientEvaluation']
 
@@ -45,8 +46,9 @@
             reg_id = \
                 Pool().get('gnuhealth.inpatient.registration').browse([inpatient_registration])[0]
         except:
-            self.raise_user_error('no_record_selected')
-            
+            raise NoRecordSelected(
+                gettext('health_inpatient.msg_no_record_selected'))
+
         patient = reg_id.patient.id
 
         
@@ -63,11 +65,3 @@
             
         return action, {}
         
-    @classmethod
-    def __setup__(cls):
-        super(CreateInpatientEvaluation, cls).__setup__()
-        cls._error_messages.update({
-            'no_record_selected':
-                'You need to select an inpatient registration record',
-        })
-