Source code for nh_eobs_mental_health.models.nh_clinical_patient_observation_ews

from datetime import datetime, timedelta

from openerp import SUPERUSER_ID
from openerp import api
from openerp.osv import orm, fields
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DTF


[docs]class NHClinicalPatientObservationEWS(orm.Model): """ Override of nh.clinical.patient.observation.ews for generic mental health behaviour """ _name = 'nh.clinical.patient.observation.ews' _inherit = 'nh.clinical.patient.observation.ews' _partial_reasons = [ ['asleep', 'Asleep'], ['refused', 'Refused'], ['request_by_doctor', 'Request By Doctor'], ['patient_aggression', 'Patient Aggression'] ] _columns = { 'partial_reason': fields.selection(_partial_reasons, 'Reason if partial observation') }
[docs] def complete(self, cr, uid, activity_id, context=None): """ It determines which acuity case the current observation is in with the stored data and responds to the different policy triggers accordingly defined on the ``_POLICY`` dictionary:: {'ranges': [0, 4, 6], 'case': '0123', --> Used with bisect to determine the acuity case based on the score. 'frequencies': [720, 240, 60, 30], --> frequency of recurrency of the NEWS observation, based on the case. 'notifications': [...], Information sent to the trigger_notifications method, based on case. 'risk': ['None', 'Low', 'Medium', 'High']} --> Clinical risk of the patient, based on case. All the case based lists work in a simple way: list[case] --> value used After the policy triggers take place the activity is `completed` and a new NEWS activity is created. Then the case based `frequency` is applied, effectively scheduling it. In the case of having a `partial` observation we won't have a new frequency so the new activity is scheduled to the same time the one just `completed` was, as the need for a complete observation is still there. :returns: ``True`` :rtype: bool """ res = super(NHClinicalPatientObservationEWS, self).complete( cr, uid, activity_id, context=context) activity_model = self.pool['nh.activity'] activity = activity_model.browse(cr, uid, activity_id, context=context) ews = activity.data_ref patient_spell = activity.spell_activity_id.data_ref patient_refusing = patient_spell.refusing_obs if not ews.is_partial: patient_spell.write({'refusing_obs': False}) if ews.is_partial and not patient_refusing \ and ews.partial_reason == 'refused': api_model = self.pool['nh.eobs.api'] cron_model = self.pool['ir.cron'] patient = api_model.get_patients( cr, uid, ews.patient_id.ids, context=context) days_to_schedule = 1 higher_risks = ['None', 'Low'] if patient[0].get('clinical_risk') in higher_risks: days_to_schedule = 7 schedule_date = datetime.now() + timedelta(days=days_to_schedule) patient_spell.write({'refusing_obs': True}) cron_model.create(cr, SUPERUSER_ID, { 'name': 'Clinical Review Task ' 'for Activity:{0}'.format(activity_id), 'user_id': uid, 'numbercall': 1, 'model': 'nh.clinical.patient.observation.ews', 'function': 'schedule_clinical_review_notification', 'args': '({0},)'.format(activity_id), 'priority': 0, 'nextcall': schedule_date.strftime(DTF), 'interval_type': 'days', 'interval_number': days_to_schedule }, context=context) return res
[docs] @api.model def schedule_clinical_review_notification(self, activity_id): """ Determines if a Clinical Review notification needs to be created based on if a full NEWS observation has been completed since the partial NEWS that triggered the call to this method was completed :return: Nothing, only side effects """ # Find all ews that have been done since the activity activity_model = self.env['nh.activity'] activity = activity_model.browse(activity_id) still_valid = self.is_refusal_in_effect(activity_id, mode='child') if still_valid: self.create_clinical_review_task(activity)
[docs] @api.model def create_clinical_review_task(self, activity): """ Create a 'nh.clinical.notification.clinical_review' record and associated activity. :param activity: :type activity: 'nh.activity' record """ clinical_review_model = \ self.pool['nh.clinical.notification.clinical_review'] due_date = datetime.now().strftime(DTF) clinical_review_model.create_activity( self._cr, SUPERUSER_ID, { 'creator_id': activity.id, 'parent_id': activity.spell_activity_id.id, 'date_scheduled': due_date, 'date_deadline': due_date }, { 'patient_id': activity.data_ref.patient_id.id } )
[docs] def is_refusal_in_effect(self, cr, uid, activity_id, mode='parent', context=None): """ Use the last_refused_ews SQL view to see if activity_id is part of a patient refusal :param cr: Odoo cursor :param uid: User doing operation :param activity_id: <nh.activity> Activity ID :param mode: Mode to operate on, parent goes up chain, child goes down :param context: Odoo Context :return: If the patient is currently in refusal """ activity_model = self.pool['nh.activity'] activity = activity_model.browse(cr, uid, activity_id) if activity.spell_activity_id.state in ['completed', 'cancelled']: return False column = 'last_activity_id' first_act_order = 'DESC' if mode == 'child': column = 'first_activity_id' first_act_order = 'ASC' cr.execute( 'SELECT refused.refused, ' 'acts.date_terminated ' 'FROM refused_ews_activities AS refused ' 'RIGHT OUTER JOIN wb_activity_ranked AS acts ' 'ON acts.id = refused.id ' 'RIGHT OUTER JOIN nh_clinical_spell AS spell ' 'ON spell.activity_id = refused.spell_activity_id ' 'LEFT JOIN wb_transfer_ranked as transfer ' 'ON transfer.spell_id = spell.id ' 'AND transfer.rank = 1 ' 'LEFT JOIN last_finished_obs_stop AS obs_stop ' 'ON obs_stop.spell_id = spell.id ' 'WHERE {column} = {id} ' 'AND coalesce(acts.date_terminated ' '>= transfer.date_terminated, TRUE) ' 'AND coalesce(acts.date_terminated >= ' 'obs_stop.activity_date_terminated, TRUE) ' 'AND (spell.obs_stop <> TRUE OR spell.obs_stop IS NULL) ' 'ORDER BY refused.spell_activity_id ASC, ' 'refused.first_activity_id {first_act_order}, ' 'refused.last_activity_id DESC ' 'LIMIT 1;'.format( column=column, id=activity_id, first_act_order=first_act_order ) ) result = cr.dictfetchall() if result: return result[0].get('refused', False) return False