예제 #1
0
class PatientRounding(ModelSQL, ModelView):
    'Patient Rounding'
    __name__ = 'gnuhealth.patient.rounding'

    name = fields.Many2One('gnuhealth.inpatient.registration',
        'Registration Code', required=True)
    health_professional = fields.Many2One('gnuhealth.healthprofessional',
        'Health Professional', readonly=True)
    evaluation_start = fields.DateTime('Start', required=True)
    evaluation_end = fields.DateTime('End', required=True)
    environmental_assessment = fields.Char('Environment', help="Environment"
        " assessment . State any disorder in the room.")

    # The 6 P's of rounding
    pain = fields.Boolean('Pain', help="Check if the patient is in pain")
    pain_level = fields.Integer('Pain', help="Enter the pain level, from 1 to "
        "10")
    potty = fields.Boolean('Potty', help="Check if the patient needs to "
        "urinate / defecate")
    position = fields.Boolean('Position', help="Check if the patient needs to "
        "be repositioned or is unconfortable")
    proximity = fields.Boolean('Proximity', help="Check if personal items, "
        "water, alarm, ... are not in easy reach")
    pump = fields.Boolean('Pumps', help="Check if there is any issues with "
        "the pumps - IVs ... ")
    personal_needs = fields.Boolean('Personal needs', help="Check if the "
        "patient requests anything")

    # Vital Signs
    systolic = fields.Integer('Systolic Pressure')
    diastolic = fields.Integer('Diastolic Pressure')
    bpm = fields.Integer('Heart Rate',
        help='Heart rate expressed in beats per minute')
    respiratory_rate = fields.Integer('Respiratory Rate',
        help='Respiratory rate expressed in breaths per minute')
    osat = fields.Integer('Oxygen Saturation',
        help='Oxygen Saturation(arterial).')
    temperature = fields.Float('Temperature',
        help='Temperature in celsius')

    # Diuresis

    diuresis = fields.Integer('Diuresis',help="volume in ml")
    urinary_catheter = fields.Boolean('Urinary Catheter')

    #Glycemia
    glycemia = fields.Integer('Glycemia', help='Blood Glucose level')

    depression = fields.Boolean('Depression signs', help="Check this if the "
        "patient shows signs of depression")
    evolution = fields.Selection([
        ('n', 'Status Quo'),
        ('i', 'Improving'),
        ('w', 'Worsening'),
        ], 'Evolution', required=True, help="Check your judgement of current "
        "patient condition", sort=False)
    round_summary = fields.Text('Round Summary')
    warning = fields.Boolean('Warning', help="Check this box to alert the "
        "supervisor about this patient rounding. It will be shown in red in "
        "the rounding list")
    procedures = fields.One2Many('gnuhealth.rounding_procedure', 'name',
        'Procedures', help="List of the procedures in this rounding. Please "
        "enter the first one as the main procedure")

    @classmethod
    def __setup__(cls):
        super(PatientRounding, cls).__setup__()
        cls._error_messages.update({
            'health_professional_warning':
                    'No health professional associated to this user',
        })

    @classmethod
    def validate(cls, roundings):
        super(PatientRounding, cls).validate(roundings)
        for rounding in roundings:
            rounding.check_health_professional()

    def check_health_professional(self):
        if not self.health_professional:
            self.raise_user_error('health_professional_warning')

    @staticmethod
    def default_health_professional():
        cursor = Transaction().cursor
        User = Pool().get('res.user')
        user = User(Transaction().user)
        login_user_id = int(user.id)
        cursor.execute('SELECT id FROM party_party WHERE is_healthprof=True AND \
            internal_user = %s LIMIT 1', (login_user_id,))
        partner_id = cursor.fetchone()
        if partner_id:
            cursor = Transaction().cursor
            cursor.execute('SELECT id FROM gnuhealth_healthprofessional WHERE \
                name = %s LIMIT 1', (partner_id[0],))
            doctor_id = cursor.fetchone()
            return int(doctor_id[0])

    @staticmethod
    def default_evaluation_start():
        return datetime.now()
예제 #2
0
class BlogPost(Workflow, ModelSQL, ModelView):
    'Blog Post'
    __name__ = 'blog.post'
    _rec_name = 'title'

    title = fields.Char('Title', required=True, select=True, states=STATES)
    uri = fields.Char(
        'URI',
        required=True,
        select=True,
        on_change_with=['title', 'uri'],
        states=STATES,
    )
    nereid_user = fields.Many2One('nereid.user',
                                  'Nereid User',
                                  required=True,
                                  select=True,
                                  states=STATES)
    post_date = fields.DateTime('Post Date', states=STATES)
    content = fields.Text('Content', states=STATES)
    allow_guest_comments = fields.Boolean('Allow Guest Comments ?',
                                          select=True)
    comments = fields.One2Many('blog.post.comment', 'post', 'Comments')
    published_comments = fields.Function(
        fields.One2Many('blog.post.comment', None, 'Published Comments'),
        'get_published_comments')
    state = fields.Selection([
        ('Draft', 'Draft'),
        ('Published', 'Published'),
        ('Archived', 'Archived'),
    ],
                             'State',
                             readonly=True)

    @staticmethod
    def default_state():
        return 'Draft'

    def get_published_comments(self, name):
        "Returns the published comments, i.e., comments not marked as spam"
        Comment = Pool().get('blog.post.comment')

        return map(
            int,
            Comment.search([('post', '=', self.id), ('is_spam', '=', False)]))

    @classmethod
    def __setup__(cls):
        super(BlogPost, cls).__setup__()
        cls._sql_constraints += [
            ('nereid_user_uri_uniq', 'UNIQUE(nereid_user, uri)',
             'URI must be unique for a nereid user'),
        ]
        cls._transitions |= set((
            ('Draft', 'Published'),
            ('Published', 'Draft'),
            ('Draft', 'Archived'),
            ('Published', 'Archived'),
            ('Archived', 'Draft'),
        ))
        cls._buttons.update({
            'publish': {
                'invisible': Eval('state') != 'Draft',
            },
            'draft': {
                'invisible': Eval('state') == 'Draft',
            },
            'archive': {
                'invisible': Eval('state') != 'Published',
            }
        })
        cls.per_page = 10

    @classmethod
    @ModelView.button
    @Workflow.transition('Draft')
    def draft(cls, posts):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('Published')
    def publish(cls, posts):
        cls.write(posts, {'post_date': datetime.utcnow()})

    @classmethod
    @ModelView.button
    @Workflow.transition('Archived')
    def archive(cls, posts):
        pass

    def on_change_with_uri(self):
        if self.title and not self.uri:
            return slugify(self.title)
        return self.uri

    def serialize(self, purpose=None):
        '''
        Return serializable dict for `self`
        '''
        res = {
            'id': self.id,
            'title': self.title,
            'uri': self.uri,
            'post_date':
            self.post_date.isoformat() if self.post_date else None,
            'allow_guest_comments': self.allow_guest_comments,
            'state': self.state,
            'nereid_user': self.nereid_user.id,
            'displayName': self.rec_name,
        }
        if purpose == 'activity_stream':
            res['objectType'] = self.__name__
            res['content'] = self.content[0:50]
        else:
            res['content'] = self.content

        return res

    @classmethod
    @route('/post/-new', methods=['GET', 'POST'])
    @login_required
    def new_post(cls):
        """Create a new post
        """
        post_form = BlogPostForm(request.form)

        if request.method == 'POST' and post_form.validate():
            post, = cls.create([{
                'title':
                post_form.title.data,
                'uri':
                post_form.uri.data,
                'content':
                post_form.content.data,
                'nereid_user':
                request.nereid_user.id,
                'allow_guest_comments':
                post_form.allow_guest_comments.data,
            }])
            if post_form.publish.data:
                cls.publish([post])
                flash('Your post has been published.')
            else:
                flash('Your post has been saved.')

            if request.is_xhr:
                return jsonify(success=True, item=post.serialize())
            return redirect(
                url_for('blog.post.render',
                        user_id=post.nereid_user.id,
                        uri=post.uri))
        if request.is_xhr:
            return jsonify(
                success=request.method != 'POST',  # False for POST, else True
                errors=post_form.errors or None,
            )
        return render_template('blog_post_form.jinja', form=post_form)

    @classmethod
    def get_post_for_uri(cls, uri):
        """
            Return post for current user and uri
        """
        posts = cls.search([
            ('uri', '=', uri),
            ('nereid_user', '=', request.nereid_user.id),
        ])

        if not posts:
            abort(404)

        return posts[0]

    @classmethod
    @route('/post/<uri>/-edit', methods=['GET', 'POST'])
    @login_required
    def edit_post_for_uri(cls, uri):
        """
            Edit an existing post from uri
        """
        return cls.get_post_for_uri(uri).edit_post()

    @route('/post/<int:active_id>/-edit', methods=['GET', 'POST'])
    @login_required
    def edit_post(self):
        """
            Edit an existing post
        """
        if self.nereid_user != request.nereid_user:
            abort(404)

        # Search for a post with same uri
        post_form = BlogPostForm(request.form, obj=self)

        with Transaction().set_context(blog_id=self.id):
            if request.method == 'POST' and post_form.validate():
                self.title = post_form.title.data
                self.content = post_form.content.data
                self.allow_guest_comments = post_form.allow_guest_comments.data
                self.save()
                flash('Your post has been updated.')
                if request.is_xhr:
                    return jsonify(success=True, item=self.serialize())
                return redirect(
                    url_for('blog.post.render',
                            user_id=self.nereid_user.id,
                            uri=self.uri))
        if request.is_xhr:
            return jsonify(
                success=request.method != 'POST',  # False for POST, else True
                errors=post_form.errors or None,
            )
        return render_template('blog_post_edit.jinja',
                               form=post_form,
                               post=self)

    @classmethod
    @route('/post/<uri>/-change-state', methods=['POST'])
    @login_required
    def change_state_for_uri(cls, uri):
        "Change the state of the post for uri"

        return cls.get_post_for_uri(uri).change_state()

    @route('/post/<int:active_id>/-change-state', methods=['POST'])
    @login_required
    def change_state(self):
        "Change the state of the post"
        if self.nereid_user != request.nereid_user:
            abort(404)

        state = request.form.get('state')
        assert (state in ('publish', 'archive', 'draft'))
        getattr(self, str(state))([self])

        if request.is_xhr:
            return jsonify({
                'success': True,
                'new_state': self.state,
            })
        flash('Your post is now %s' % self.state)
        return redirect(
            url_for('blog.post.render',
                    user_id=self.nereid_user.id,
                    uri=self.uri))

    @classmethod
    @route('/post/<uri>/-change-guest-permission', methods=['POST'])
    @login_required
    def change_guest_permission_for_uri(cls, uri):
        "Change guest permission for uri"

        return cls.get_post_for_uri(uri).change_guest_permission()

    @route('/post/<int:active_id>/-change-guest-permission', methods=['POST'])
    @login_required
    def change_guest_permission(self):
        "Change guest permission of the post"
        if self.nereid_user != request.nereid_user:
            abort(404)

        allow_guest_comment = request.form.get('allow_guest_comments')
        self.allow_guest_comments = True if allow_guest_comment == 'true' \
            else False
        self.save()

        if request.is_xhr:
            return jsonify({
                'success': True,
            })
        return redirect(
            url_for('blog.post.render',
                    user_id=self.nereid_user.id,
                    uri=self.uri))

    @classmethod
    @route('/post/<int:user_id>/<uri>')
    def render(cls, user_id, uri):
        "Render the blog post"
        NereidUser = Pool().get('nereid.user')

        if 're_captcha_public' in CONFIG.options and request.is_guest_user:
            comment_form = GuestCommentForm(
                captcha={'ip_address': request.remote_addr})
        else:
            comment_form = PostCommentForm()

        user = NereidUser(user_id)

        posts = cls.search([
            ('nereid_user', '=', user.id),
            ('uri', '=', uri),
        ])
        if not posts:
            abort(404)

        # if only one post is found then it is rendered and
        # if more than one are found then the first one is rendered
        post = posts[0]

        if not (post.state == 'Published'
                or request.nereid_user == post.nereid_user):
            abort(403)

        if request.is_xhr:
            return jsonify(post.serialize())
        return render_template('blog_post.jinja',
                               post=post,
                               comment_form=comment_form,
                               poster=user)

    @classmethod
    @route('/posts/<int:user_id>')
    @route('/posts/<int:user_id>/<int:page>')
    def render_list(cls, user_id, page=1):
        """Render the blog posts for a user
        This should render the list of only published posts of the user
        """
        NereidUser = Pool().get('nereid.user')

        user = NereidUser(user_id)

        posts = Pagination(cls, [
            ('nereid_user', '=', user.id),
            ('state', '=', 'Published'),
        ], page, cls.per_page)
        if request.is_xhr:
            return jsonify({
                'has_next': posts.has_next,
                'has_prev': posts.has_prev,
                'items': [post.serialize() for post in posts],
            })

        return render_template('blog_posts.jinja', posts=posts, poster=user)

    @classmethod
    @route('/posts/-my')
    @route('/posts/-my/<int:page>')
    @login_required
    def my_posts(self, page=1):
        """Render all the posts of the logged in user
        """
        posts = Pagination(self, [
            ('nereid_user', '=', request.nereid_user.id),
        ], page, self.per_page)
        if request.is_xhr:
            return jsonify({
                'has_next': posts.has_next,
                'has_prev': posts.has_prev,
                'items': [post.serialize() for post in posts],
            })

        return render_template('my_blog_posts.jinja', posts=posts)

    @classmethod
    @route('/post/<int:user_id>/<uri>/-comment', methods=['GET', 'POST'])
    def add_comment(cls, user_id, uri):
        '''
        Add a comment
        '''
        warnings.warn(
            "add_comment will be deprecated in 3.2 use render_comment instead.",
            DeprecationWarning,
        )
        # Comments can only be added to published posts
        posts = cls.search([
            ('nereid_user', '=', user_id),
            ('uri', '=', uri),
        ],
                           limit=1)
        if not posts:
            abort(404)

        return posts[0].render_comments()

    @route('/post/<int:active_id>/-comment', methods=['GET', 'POST'])
    def render_comments(self):
        """
        Render comments

        GET: Return json of all the comments of this post.
        POST: Create new comment for this post.
        """
        if self.state != 'Published':
            abort(404)

        # Add re_captcha if the configuration has such an option and user
        # is guest
        if 're_captcha_public' in CONFIG.options and request.is_guest_user:
            comment_form = GuestCommentForm(
                request.form, captcha={'ip_address': request.remote_addr})
        else:
            comment_form = PostCommentForm(request.form)

        if request.method == 'GET':
            if self.nereid_user == request.nereid_user:
                return jsonify(comments=[
                    comment.serialize() for comment in self.comments
                ])
            return jsonify(comments=[
                comment.serialize() for comment in self.comments
                if not comment.is_spam
            ])

        # If post does not allow guest comments,
        # then dont allow guest user to comment
        if not self.allow_guest_comments and request.is_guest_user:
            flash('Guests are not allowed to write comments')
            if request.is_xhr:
                return jsonify(
                    success=False,
                    errors=['Guests are not allowed to write comments'])
            return redirect(
                url_for('blog.post.render',
                        user_id=self.nereid_user.id,
                        uri=self.uri))

        if request.method == 'POST' and comment_form.validate():
            self.write(
                [self], {
                    'comments': [('create', [{
                        'nereid_user':
                        current_user.id
                        if not current_user.is_anonymous() else None,
                        'name':
                        current_user.display_name
                        if not current_user.is_anonymous() else
                        comment_form.name.data,
                        'content':
                        comment_form.content.data,
                    }])]
                })

        if request.is_xhr:
            return jsonify(success=True) if comment_form.validate() \
                else jsonify(success=False, errors=comment_form.errors)
        return redirect(
            url_for('blog.post.render',
                    user_id=self.nereid_user.id,
                    uri=self.uri))
예제 #3
0
class DiseaseNotification(ModelView, ModelSQL):
    'Disease Notification'

    __name__ = 'gnuhealth.disease_notification'
    active = fields.Boolean('Active')
    patient = fields.Many2One('gnuhealth.patient',
                              'Patient',
                              required=True,
                              states=RO_SAVED)
    status = fields.Selection(NOTIFICATION_STATES,
                              'Status',
                              required=True,
                              sort=False)
    status_display = fields.Function(fields.Char('State'),
                                     'get_selection_display')
    name = fields.Char('Code',
                       size=18,
                       states={'readonly': True},
                       required=True)
    tracking_code = fields.Char('Case Tracking Code', select=True)
    date_notified = fields.DateTime('Date reported',
                                    required=True,
                                    states=RO_SAVED)
    date_received = fields.DateTime(
        'Date received',
        states=RO_NEW,
        help='Date received the National Surveillance Unit')
    diagnosis = fields.Many2One('gnuhealth.pathology',
                                'Suspected Diagnosis',
                                states=RO_STATE_END,
                                required=False)
    diagnosis_confirmed = fields.Many2One(
        'gnuhealth.pathology',
        'Confirmed Diagnosis',
        required=False,
        states={'invisible': Eval('id', 0) < 0})
    symptoms = fields.One2Many('gnuhealth.disease_notification.symptom',
                               'name',
                               'Symptoms',
                               states=RO_STATE_END)
    date_onset = fields.Date('Date of Onset',
                             help='Date of onset of the illness')
    epi_week_onset = fields.Function(
        fields.Char('Epi. Week of onset',
                    size=8,
                    help='Week of onset (epidemiological)'), 'epi_week')
    date_seen = fields.Date('Date Seen', help='Date seen by a medical officer')
    reporting_facility = fields.Many2One(
        'gnuhealth.institution',
        'Reporting facility',
        states={'invisible': Bool(Eval('reporting_facility_other'))})
    reporting_facility_other = fields.Char(
        'Other Reporting location',
        help='Used when the report came from an institution not found above',
        states={'invisible': Bool(Eval('reporting_facility'))})
    encounter = fields.Many2One('gnuhealth.encounter',
                                'Clinical Encounter',
                                domain=[('patient', '=', Eval('patient')),
                                        ('start_time', '<',
                                         Eval('date_notified'))])
    specimen_taken = fields.Boolean('Samples Taken')
    specimens = fields.One2Many('gnuhealth.disease_notification.specimen',
                                'notification',
                                'Samples',
                                states=ONLY_IF_LAB)
    hospitalized = fields.Boolean('Admitted to hospital')
    admission_date = fields.Date('Date admitted', states=ONLY_IF_ADMITTED)
    hospital = fields.Many2One('gnuhealth.institution',
                               'Hospital',
                               states=ONLY_IF_ADMITTED)
    ward = fields.Char('Ward', states=ONLY_IF_ADMITTED)
    deceased = fields.Boolean('Deceased')
    date_of_death = fields.Date('Date of Death', states=ONLY_IF_DEAD)
    healthprof = fields.Many2One('gnuhealth.healthprofessional', 'Reported by')
    comments = fields.Text('Additional comments')
    comments_short = fields.Function(fields.Char('Comments'), 'short_comment')
    risk_factors = fields.One2Many(
        'gnuhealth.disease_notification.risk_disease',
        'notification',
        'Risk Factors',
        help="Other conditions of merit")
    hx_travel = fields.Boolean('Recent Foreign Travels',
                               help="History of Overseas travel in the last"
                               " 4 - 6 weeks")
    hx_locations = fields.One2Many(
        'gnuhealth.disease_notification.travel',
        'notification',
        'Places visited',
        states={'invisible': ~Eval('hx_travel', False)})
    age = fields.Function(
        fields.Char('Age', size=8, help='age at date of onset'),
        'get_patient_age')
    sex = fields.Function(fields.Selection(SEX_OPTIONS, 'Sex'),
                          'get_patient_field',
                          searcher='search_patient_field')
    puid = fields.Function(fields.Char('UPI', size=12),
                           'get_patient_field',
                           searcher='search_patient_field')
    state_changes = fields.One2Many(
        'gnuhealth.disease_notification.statechange',
        'notification',
        'Status Changes',
        order=[('create_date', 'DESC')],
        readonly=True)
    ir_received = fields.Boolean('IR Received')
    # medical_record_num = fields.Function(fields.Char('Medical Record Numbers'),
    #                                      'get_patient_field',
    #                                      searcher='search_patient_field')

    @classmethod
    def __setup__(cls):
        super(DiseaseNotification, cls).__setup__()
        cls._order = [('date_onset', 'DESC')]
        cls._sql_error_messages = {
            'unique_name': 'There is another notification with this code'
        }
        cls._sql_constraints = [('name_uniq', 'UNIQUE(name)',
                                 'The code must be unique.')]

    @classmethod
    def get_patient_field(cls, instances, name):
        return dict([(x.id, getattr(x.patient, name)) for x in instances])

    @classmethod
    def get_patient_age(cls, instances, name):
        '''
        Uses the age function in the database to calculate the age at 
        the date specified.
        :param: instance_refs - a list of tuples with (id, ref_date)
        '''
        c = Transaction().cursor
        tbl = cls.__table__()
        qry = "\n".join([
            "SET intervalstyle TO 'iso_8601';",
            "SELECT a.id as id, btrim(lower("
            "regexp_replace(AGE(a.date_onset, c.dob)::varchar, "
            "'([YMD])', '\\1 ', 'g')), 'p ')  as showage ",
            "from " + str(tbl) + " as a ",
            " inner join gnuhealth_patient as b on a.patient=b.id",
            " inner join party_party c on b.name=c.id"
            " where a.id in %s ;"
        ])
        qry_parm = tuple(map(int, instances))
        c.execute(qry, (qry_parm, ))
        outx = c.fetchall()
        outd = dict([x for x in outx])
        return outd

    @classmethod
    def order_puid(cls, tables):
        table, _ = tables[None]
        return [Column(table, 'patient')]
        # not really a UPI/PUID sort, but good enough

    @classmethod
    def short_comment(cls, instances, name):
        return dict(
            map(
                lambda x: (x.id, x.comments and ' '.join(x.comments.split(
                    '\n'))[:40] or ''), instances))

    @classmethod
    def search_patient_field(cls, field_name, clause):
        return replace_clause_column(clause, 'patient.%s' % field_name)

    _rec_name = 'name'
    # @classmethod
    # def get_rec_name(cls, records, name):
    #     return dict([(x.id, x.name) for x in records])

    @classmethod
    def search_rec_name(cls, field_name, clause):
        _, operand, val = clause
        return ['OR', ('patient.puid', operand, val), ('name', operand, val)]

    @fields.depends('reporting_facility')
    def on_change_reporting_facility(self, *arg, **kwarg):
        return {'reporting_facility_other': ''}

    @fields.depends('diagnosis', 'name')
    def on_change_with_name(self):
        curname = self.name
        if self.diagnosis:
            newcode = '%s:' % self.diagnosis.code
            if curname:
                newcode = '%s:%s' % (self.diagnosis.code, curname)
            return newcode
        elif curname and ':' in curname:
            return curname[curname.index(':') + 1:]

    @fields.depends('diagnosis_confirmed', 'status')
    def on_change_diagnosis_confirmed(self):
        if self.diagnosis_confirmed and self.status == 'suspected':
            return {'status': 'confirmed'}
        else:
            return {}

    @fields.depends('encounter')
    def on_change_with_date_seen(self):
        return self.encounter.start_time.date() if self.encounter else None

    @staticmethod
    def default_healthprof():
        healthprof_model = Pool().get('gnuhealth.healthprofessional')
        return healthprof_model.get_health_professional()

    @staticmethod
    def default_status():
        return 'waiting'

    @staticmethod
    def default_active():
        return True

    @classmethod
    def create(cls, vlist):
        pool = Pool()
        Sequence = pool.get('ir.sequence')
        Config = pool.get('gnuhealth.sequences')
        config = Config(1)
        vlist = [x.copy() for x in vlist]
        for values in vlist:
            val_name = values.get('name', '')
            if not val_name or val_name.endswith(':'):
                newcode = Sequence.get_id(config.notification_sequence.id)
                values['name'] = '%s%s' % (values['name'], newcode)
            elif ':' in val_name and not values.get('diagnosis', False):
                values['name'] = val_name[val_name.index(':') + 1:]
            if values.get('state_changes', False):
                pass
            else:
                values['state_changes'] = [('create', [{
                    'orig_state':
                    None,
                    'target_state':
                    values['status'],
                    'healthprof':
                    values['healthprof']
                }])]
        return super(DiseaseNotification, cls).create(vlist)

    @classmethod
    def write(cls, records, values, *args):
        '''create a NotificationStateChange when the status changes'''
        healthprof = DiseaseNotification.default_healthprof()
        to_make = []
        irecs = iter((records, values) + args)
        for recs, vals in zip(irecs, irecs):
            newstate = vals.get('status', False)
            if newstate:
                for rec in recs:
                    if rec.status != newstate:
                        to_make.append({
                            'notification': rec.id,
                            'orig_state': rec.status,
                            'target_state': newstate,
                            'healthprof': healthprof
                        })
        return_val = super(DiseaseNotification,
                           cls).write(records, values, *args)
        # nsc = Notification State Change
        if to_make:
            nsc = Pool().get('gnuhealth.disease_notification.statechange')
            nsc.create(to_make)
        return return_val

    @classmethod
    def validate(cls, records):
        now = {date: date.today(), datetime: datetime.now(), type(None): None}
        date_fields = [
            'date_onset', 'date_seen', 'date_notified', 'admission_date',
            'date_of_death'
        ]
        # we need to ensure that none of these fields are in the future
        for rec in records:
            if rec.encounter:
                if rec.encounter.patient != rec.patient:
                    cls.raise_user_error('Invalid encounter selected.'
                                         'Different patient')
            for fld in date_fields:
                val = getattr(rec, fld)
                if val and val > now[type(val)]:
                    val_name = getattr(cls, fld).string
                    cls.raise_user_error('%s cannot be in the future',
                                         (val_name, ))

    @classmethod
    def copy(cls, records, default=None):
        if default is None:
            default = {}
        default = default.copy()
        default.update(diagnosis=None, state_changes=[])
        if 'name' in default:
            del default['name']
        return super(DiseaseNotification, cls).copy(records, default=default)

    @classmethod
    def epi_week(cls, instances, name):
        def ewcalc(k):
            return (k.id, epiweek_str(k.date_onset) if k.date_onset else '')

        if name == 'epi_week_onset':
            return dict(map(ewcalc, instances))

    @classmethod
    def get_selection_display(cls, instances, field_name):
        real_field = field_name[:0 - len('_display')]
        field_selections = cls._fields[real_field].selection
        xdict = dict(filter(lambda x: x[0], field_selections))
        return dict(
            map(lambda x: (x.id, xdict.get(getattr(x, real_field), '')),
                instances))
예제 #4
0
class PatientSESAssessment(ModelSQL, ModelView):
    'Socioeconomics and Family Functionality Assessment'
    __name__ = 'gnuhealth.ses.assessment'

    STATES = {'readonly': Eval('state') == 'done'}

    patient = fields.Many2One('gnuhealth.patient', 'Patient',
        required=True, states = STATES)
    gender = fields.Function(fields.Selection([
        (None, ''),
        ('m', 'Male'),
        ('f', 'Female'),
        ], 'Gender'), 'get_patient_gender', searcher='search_patient_gender')


    assessment_date = fields.DateTime('Date', help="Assessment date",
        states = STATES)
        
    computed_age = fields.Function(fields.Char(
            'Age',
            help="Computed patient age at the moment of the evaluation"),
            'patient_age_at_assessment')
            
    health_professional = fields.Many2One(
        'gnuhealth.healthprofessional', 'Health Professional', readonly=True,
        help="Health professional"
        )

    du = fields.Many2One(
        'gnuhealth.du', 'DU', help="Domiciliary Unit",
        states = STATES)

    ses = fields.Selection([
        (None, ''),
        ('0', 'Lower'),
        ('1', 'Lower-middle'),
        ('2', 'Middle'),
        ('3', 'Middle-upper'),
        ('4', 'Higher'),
        ], 'Socioeconomics', help="SES - Socioeconomic Status", sort=False,
            states = STATES)

    housing = fields.Selection([
        (None, ''),
        ('0', 'Shanty, deficient sanitary conditions'),
        ('1', 'Small, crowded but with good sanitary conditions'),
        ('2', 'Comfortable and good sanitary conditions'),
        ('3', 'Roomy and excellent sanitary conditions'),
        ('4', 'Luxury and excellent sanitary conditions'),
        ], 'Housing conditions',
         help="Housing and sanitary living conditions", sort=False,
            states = STATES)

    occupation = fields.Many2One('gnuhealth.occupation','Occupation',
        states = STATES)

    income = fields.Selection([
        (None, ''),
        ('l', 'Low'),
        ('m', 'Medium'),
        ('h', 'High'),
        ], 'Income', sort=False, states = STATES)


    fam_apgar_help = fields.Selection([
        (None, ''),
        ('0', 'None'),
        ('1', 'Moderately'),
        ('2', 'Very much'),
        ], 'Help from family',
        help="Is the patient satisfied with the level of help coming from " \
        "the family when there is a problem ?", sort=False,
            states = STATES)

    fam_apgar_discussion = fields.Selection([
        (None, ''),
        ('0', 'None'),
        ('1', 'Moderately'),
        ('2', 'Very much'),
        ], 'Problems discussion',
        help="Is the patient satisfied with the level talking over the " \
        "problems as family ?", sort=False, states = STATES)

    fam_apgar_decisions = fields.Selection([
        (None, ''),
        ('0', 'None'),
        ('1', 'Moderately'),
        ('2', 'Very much'),
        ], 'Decision making',
        help="Is the patient satisfied with the level of making important " \
        "decisions as a group ?", sort=False, states = STATES)

    fam_apgar_timesharing = fields.Selection([
        (None, ''),
        ('0', 'None'),
        ('1', 'Moderately'),
        ('2', 'Very much'),
        ], 'Time sharing',
        help="Is the patient satisfied with the level of time that they " \
        "spend together ?", sort=False, states = STATES)

    fam_apgar_affection = fields.Selection([
        (None, ''),
        ('0', 'None'),
        ('1', 'Moderately'),
        ('2', 'Very much'),
        ], 'Family affection',
        help="Is the patient satisfied with the level of affection coming " \
        "from the family ?", sort=False, states = STATES)

    fam_apgar_score = fields.Integer('Score',
        help="Total Family APGAR \n" \
        "7 - 10 : Functional Family \n" \
        "4 - 6  : Some level of disfunction \n" \
        "0 - 3  : Severe disfunctional family \n", states = STATES)

    education = fields.Selection([
        (None, ''),
        ('0', 'None'),
        ('1', 'Incomplete Primary School'),
        ('2', 'Primary School'),
        ('3', 'Incomplete Secondary School'),
        ('4', 'Secondary School'),
        ('5', 'University'),
        ], 'Education Level', help="Education Level", sort=False,
            states = STATES)

    notes = fields.Text('Notes', states = STATES)

    state = fields.Selection([
        (None, ''),
        ('in_progress', 'In progress'),
        ('done', 'Done'),
        ], 'State', readonly=True, sort=False)

    signed_by = fields.Many2One(
        'gnuhealth.healthprofessional', 'Signed by', readonly=True,
        states={'invisible': Equal(Eval('state'), 'in_progress')},
        help="Health Professional that finished the patient evaluation")


    @fields.depends('fam_apgar_help', 'fam_apgar_timesharing',
        'fam_apgar_discussion', 'fam_apgar_decisions', 'fam_apgar_affection')
    def on_change_with_fam_apgar_score(self):
        fam_apgar_help = int(self.fam_apgar_help or '0')
        fam_apgar_timesharing = int(self.fam_apgar_timesharing or '0')
        fam_apgar_discussion = int(self.fam_apgar_discussion or '0')
        fam_apgar_decisions = int(self.fam_apgar_decisions or '0')
        fam_apgar_affection = int(self.fam_apgar_affection or '0')
        total = (fam_apgar_help + fam_apgar_timesharing +
            fam_apgar_discussion + fam_apgar_decisions +
            fam_apgar_affection)

        return total

    @staticmethod
    def default_assessment_date():
        return datetime.now()

    @staticmethod
    def default_state():
        return 'in_progress'

    @staticmethod
    def default_health_professional():
        pool = Pool()
        HealthProf= pool.get('gnuhealth.healthprofessional')
        health_professional = HealthProf.get_health_professional()
        return health_professional

    # Show the gender and age upon entering the patient 
    # These two are function fields (don't exist at DB level)
    @fields.depends('patient')
    def on_change_patient(self):
        gender=None
        age=''
        self.gender = self.patient.gender
        self.computed_age = self.patient.age

        occupation=education=du=housing=None
        if (self.patient and self.patient.name.occupation):
            occupation = self.patient.name.occupation
        
        if (self.patient and self.patient.name.education):
            education = self.patient.name.education

        if (self.patient and self.patient.name.du):
            du = self.patient.name.du

        if (self.patient and self.patient.name.du):
            housing = self.patient.name.du.housing

        self.occupation = occupation
        self.education = education
        self.du = du
        self.housing = housing



    def get_patient_gender(self, name):
        return self.patient.gender

    @classmethod
    def search_patient_gender(cls, name, clause):
        res = []
        value = clause[2]
        res.append(('patient.name.gender', clause[1], value))
        return res

    @classmethod
    @ModelView.button
    def end_assessment(cls, assessments):
        
        assessment_id = assessments[0]

        # Change the state of the assessment to "Done"
        HealthProf= Pool().get('gnuhealth.healthprofessional')

        signing_hp = HealthProf.get_health_professional()

        cls.write(assessments, {
            'state': 'done',
            'signed_by': signing_hp,
            })
        

    def patient_age_at_assessment(self, name):
        if (self.patient.name.dob and self.assessment_date):
            rdelta = relativedelta (self.assessment_date.date(),
                self.patient.name.dob)
            years_months_days = str(rdelta.years) + 'y ' \
                + str(rdelta.months) + 'm ' \
                + str(rdelta.days) + 'd'
            return years_months_days
        else:
            return None


    @classmethod
    def __setup__(cls):
        super(PatientSESAssessment, cls).__setup__()

        cls._buttons.update({
            'end_assessment': {'invisible': Equal(Eval('state'), 'done')}
            })
        cls._order.insert(0, ('assessment_date', 'DESC'))


    @classmethod
    def search_rec_name(cls, name, clause):
        if clause[1].startswith('!') or clause[1].startswith('not '):
            bool_op = 'AND'
        else:
            bool_op = 'OR'
        return [bool_op,
            ('patient',) + tuple(clause[1:]),
            ]
예제 #5
0
class ImportDataDateTime(ModelSQL):
    "Import Data DateTime"
    __name__ = 'test.import_data.datetime'
    datetime = fields.DateTime('DateTime')
예제 #6
0
class WebsiteStoreView(ModelSQL, ModelView):
    """
    Magento Website Store View

    A store needs one or more store views to be browse-able in the front-end.
    It allows for multiple presentations of a store. Most implementations
    use store views for different languages
    """
    __name__ = 'magento.store.store_view'

    name = fields.Char('Name', required=True)
    code = fields.Char('Code', required=True, readonly=True)
    magento_id = fields.Integer('Magento ID', readonly=True, required=True)
    store = fields.Many2One(
        'magento.website.store',
        'Store',
        required=True,
        readonly=True,
    )
    instance = fields.Function(fields.Many2One('magento.instance', 'Instance'),
                               'get_instance')
    website = fields.Function(
        fields.Many2One('magento.instance.website', 'Website'), 'get_website')
    company = fields.Function(fields.Many2One('company.company', 'Company'),
                              'get_company')
    last_order_import_time = fields.DateTime('Last Order Import Time')
    last_order_export_time = fields.DateTime("Last Order Export Time")

    #: Last time at which the shipment status was exported to magento
    last_shipment_export_time = fields.DateTime('Last shipment export time')

    #: Checking this will make sure that only the done shipments which have a
    #: carrier and tracking reference are exported.
    export_tracking_information = fields.Boolean(
        'Export tracking information',
        help='Checking this will make sure'
        ' that only the done shipments which have a carrier and tracking '
        'reference are exported. This will update carrier and tracking '
        'reference on magento for the exported shipments as well.')

    def get_instance(self, name):
        """
        Returns instance related to store

        :param name: Field name
        """
        return self.store.instance.id

    def get_website(self, name):
        """
        Returns website related to store

        :param name: Field name
        """
        return self.store.website.id

    def get_company(self, name):
        """
        Returns company related to store

        :param name: Field name
        """
        return self.store.company.id

    @classmethod
    def __setup__(cls):
        """
        Setup the class before adding to pool
        """
        super(WebsiteStoreView, cls).__setup__()
        cls._sql_constraints += [
            ('magento_id_store_unique', 'UNIQUE(magento_id, store)',
             'A store view must be unique in a store')
        ]
        cls._error_messages.update({
            "states_not_found":
            'No order states found for importing orders! '
            'Please configure the order states on magento instance',
        })
        cls._buttons.update({
            'import_orders_button': {},
            'export_order_status_button': {}
        })

    @classmethod
    def find_or_create(cls, store, values):
        """
        Looks for the store view whose `values` are sent by magento against
        the store with `store` in tryton.
        If a record exists for this, return that else create a new one and
        return

        :param store: Active record of store
        :param values: Dictionary of values for store view sent by magento
        :return: Actice record of record created/found
        """
        store_views = cls.search([('store', '=', store.id),
                                  ('magento_id', '=', int(values['store_id']))
                                  ])

        if store_views:
            return store_views[0]

        return cls.create([{
            'name': values['name'],
            'code': values['code'],
            'store': store.id,
            'magento_id': int(values['store_id']),
        }])[0]

    @classmethod
    @ModelView.button_action('magento.wizard_import_orders')
    def import_orders_button(cls, store_views):
        """
        Calls wizard to import orders for store view

        :param store_views: List of active records of store views
        """
        pass

    @classmethod
    @ModelView.button_action('magento.wizard_export_order_status')
    def export_order_status_button(cls, store_views):
        """
        Calls wizard to export order status for store view

        :param store_views: List of active records of store views
        """
        pass

    def import_order_from_store_view(self):
        """
        Imports sale from store view

        :return: List of active record of sale imported
        """
        Sale = Pool().get('sale.sale')
        MagentoOrderState = Pool().get('magento.order_state')

        new_sales = []
        instance = self.instance
        with Transaction().set_context({
                'magento_instance': instance.id,
                'magento_website': self.website.id,
                'magento_store_view': self.id,
        }):

            order_states = MagentoOrderState.search([
                ('instance', '=', instance.id), ('use_for_import', '=', True)
            ])
            order_states_to_import_in = map(lambda state: state.code,
                                            order_states)

            if not order_states_to_import_in:
                self.raise_user_error("states_not_found")

            with magento.Order(instance.url, instance.api_user,
                               instance.api_key) as order_api:
                # Filter orders with date and store_id using list()
                # then get info of each order using info()
                # and call find_or_create_using_magento_data on sale
                filter = {
                    'store_id': {
                        '=': self.magento_id
                    },
                    'state': {
                        'in': order_states_to_import_in
                    },
                }
                if self.last_order_import_time:
                    filter.update({
                        'updated_at': {
                            'gteq': self.last_order_import_time
                        },
                    })
                self.write([self],
                           {'last_order_import_time': datetime.utcnow()})
                orders = order_api.list(filter)
                for order in orders:
                    new_sales.append(
                        Sale.find_or_create_using_magento_data(
                            order_api.info(order['increment_id'])))

        return new_sales

    def export_order_status(self, store_views=None):
        """
        Export sales orders status to magento.

        :param store_views: List of active record of store view
        """
        if not store_views:
            store_views = self.search([])

        for store_view in store_views:
            store_view.export_order_status_for_store_view()

    def export_order_status_for_store_view(self):
        """
        Export sale orders to magento for the current store view.
        If last export time is defined, export only those orders which are
        updated after last export time.

        :return: List of active records of sales exported
        """
        Sale = Pool().get('sale.sale')

        exported_sales = []
        domain = [('magento_store_view', '=', self.id)]

        if self.last_order_export_time:
            domain = [('write_date', '>=', self.last_order_export_time)]

        sales = Sale.search(domain)

        self.write([self], {'last_order_export_time': datetime.utcnow()})
        for sale in sales:
            exported_sales.append(sale.export_order_status_to_magento())

        return exported_sales

    @classmethod
    def import_orders(cls, store_views=None):
        """
        Import orders from magento for store views

        :param store_views: Active record list of store views
        """
        if not store_views:
            store_views = cls.search([])

        for store_view in store_views:
            store_view.import_order_from_store_view()

    @classmethod
    def export_shipment_status(cls, store_views=None):
        """
        Export Shipment status for shipments related to current store view.
        This method is called by cron.

        :param store_views: List of active records of store_view
        """
        if not store_views:
            store_views = cls.search([])

        for store_view in store_views:
            # Set the instance in context
            with Transaction().set_context(
                    magento_instance=store_view.instance.id):
                store_view.export_shipment_status_to_magento()

    def export_shipment_status_to_magento(self):
        """
        Exports shipment status for shipments to magento, if they are shipped

        :return: List of active record of shipment
        """
        Shipment = Pool().get('stock.shipment.out')
        Sale = Pool().get('sale.sale')

        instance = self.instance

        sale_domain = [
            ('magento_store_view', '=', self.id),
            ('shipment_state', '=', 'sent'),
            ('magento_id', '!=', None),
        ]

        if self.last_shipment_export_time:
            sale_domain.append(
                ('write_date', '>=', self.last_shipment_export_time))

        sales = Sale.search(sale_domain)

        for sale in sales:
            if not sale.shipments:
                sales.pop(sale)
                continue
            # Get the increment id from the sale reference
            increment_id = sale.reference[len(instance.order_prefix
                                              ):len(sale.reference)]
            self.write([self],
                       {'last_shipment_export_time': datetime.utcnow()})

            for shipment in sale.shipments:
                try:
                    # Some checks to make sure that only valid shipments are
                    # being exported
                    if shipment.is_tracking_exported_to_magento or \
                            shipment.state not in ('packed', 'done') or \
                            shipment.magento_increment_id:
                        sales.pop(sale)
                        continue
                    with magento.Shipment(instance.url, instance.api_user,
                                          instance.api_key) as shipment_api:
                        item_qty_map = {}
                        for move in shipment.outgoing_moves:
                            if isinstance(move.origin, SaleLine) \
                                    and move.origin.magento_id:
                                # This is done because there can be multiple
                                # lines with the same product and they need
                                # to be send as a sum of quanitities
                                item_qty_map.setdefault(
                                    str(move.origin.magento_id), 0)
                                item_qty_map[str(move.origin.magento_id)] += \
                                    move.quantity
                        shipment_increment_id = shipment_api.create(
                            order_increment_id=increment_id,
                            items_qty=item_qty_map)
                        Shipment.write(
                            sale.shipments, {
                                'magento_increment_id': shipment_increment_id,
                            })

                        if self.export_tracking_information and (
                                shipment.tracking_number and shipment.carrier):
                            shipment.export_tracking_info_to_magento()
                except xmlrpclib.Fault, fault:
                    if fault.faultCode == 102:
                        # A shipment already exists for this order,
                        # we cannot do anything about it.
                        # Maybe it was already exported earlier or was created
                        # separately on magento
                        # Hence, just continue
                        continue

        return sales
예제 #7
0
class PaperArchive(ModelSQL, ModelView):
    'Location of PAPER Patient Clinical History'

    __name__ = 'gnuhealth.paper_archive'

    patient = fields.Many2One('gnuhealth.patient',
                              'Patient',
                              required=True,
                              help="Patient associated to this newborn baby")

    legacy = fields.Char('Legacy Code', help="If existing, please enter" \
        " the old / legacy code associated to this Clinical History")
    location = fields.Many2One(
        'gnuhealth.hospital.unit', 'Unit', required=True,
        help="Location / Unit where this clinical history document" \
            " should reside.")

    hc_status = fields.Selection((
        ('archived', 'Archived'),
        ('borrowed', 'Borrowed'),
        ('lost', 'Lost'),
    ),
                                 'Status',
                                 required=True,
                                 sort=False)

    current_location = fields.Many2One(
        'gnuhealth.hospital.unit', 'Current Location',
        help="Location / Unit where this clinical history document" \
            " should reside.")

    identification_code = fields.Function(fields.Char('Code'),
                                          'get_patient_history',
                                          searcher='search_patient_code')

    requested_by = fields.Many2One(
        'party.party',
        'Resquested by',
        domain=[('is_person', '=', True)],
        help="Person who last requested the document")

    request_date = fields.DateTime("Request Date")
    return_date = fields.DateTime("Returned Date")
    comments = fields.Char("Comments")

    @classmethod
    def __setup__(cls):
        '''Create constraints for both the legacy number and patient'''
        super(PaperArchive, cls).__setup__()
        cls._sql_constraints = [
            ('legacy_uniq', 'UNIQUE(legacy)', 'The History already exists !'),
            ('patient_uniq', 'UNIQUE(patient)',
             'The Patient History already exists !'),
        ]

    @classmethod
    def search_patient_code(cls, name, clause):
        '''Retrieve the Patient Identification Code'''
        res = []
        value = clause[2]
        res.append(('patient.identification_code', clause[1], value))
        return res

    def get_patient_history(self, name):
        return self.patient.identification_code
예제 #8
0
파일: test.py 프로젝트: riskiNova/trytond
class DateTimeRequired(ModelSQL):
    'DateTime Required'
    __name__ = 'test.datetime_required'
    datetime = fields.DateTime(string='DateTime',
                               help='Test datetime',
                               required=True)
예제 #9
0
파일: test.py 프로젝트: riskiNova/trytond
class DateTimeFormat(ModelSQL):
    'DateTime Format'
    __name__ = 'test.datetime_format'
    datetime = fields.DateTime(string='DateTime', format='%H:%M')
예제 #10
0
class Surgery(ModelSQL, ModelView):
    'Surgery'
    __name__ = 'gnuhealth.surgery'

    def surgery_duration(self, name):

        if (self.surgery_end_date and self.surgery_date):
            return self.surgery_end_date - self.surgery_date
        else:
            return None

    def patient_age_at_surgery(self, name):
        if (self.patient.name.dob and self.surgery_date):
            rdelta = relativedelta(self.surgery_date.date(),
                                   self.patient.name.dob)
            years_months_days = str(rdelta.years) + 'y ' \
                + str(rdelta.months) + 'm ' \
                + str(rdelta.days) + 'd'
            return years_months_days
        else:
            return None

    patient = fields.Many2One('gnuhealth.patient', 'Patient', required=True)
    admission = fields.Many2One('gnuhealth.appointment', 'Admission')
    operating_room = fields.Many2One('gnuhealth.hospital.or', 'Operating Room')
    code = fields.Char('Code',
                       readonly=True,
                       help="Health Center code / sequence")

    procedures = fields.One2Many(
        'gnuhealth.operation',
        'name',
        'Procedures',
        help="List of the procedures in the surgery. Please enter the first "
        "one as the main procedure")

    supplies = fields.One2Many(
        'gnuhealth.surgery_supply',
        'name',
        'Supplies',
        help="List of the supplies required for the surgery")

    pathology = fields.Many2One('gnuhealth.pathology',
                                'Condition',
                                help="Base Condition / Reason")

    classification = fields.Selection([
        (None, ''),
        ('o', 'Optional'),
        ('r', 'Required'),
        ('u', 'Urgent'),
        ('e', 'Emergency'),
    ],
                                      'Urgency',
                                      help="Urgency level for this surgery",
                                      sort=False)
    surgeon = fields.Many2One('gnuhealth.healthprofessional',
                              'Surgeon',
                              help="Surgeon who did the procedure")

    anesthetist = fields.Many2One('gnuhealth.healthprofessional',
                                  'Anesthetist',
                                  help="Anesthetist in charge")

    surgery_date = fields.DateTime('Date', help="Start of the Surgery")

    surgery_end_date = fields.DateTime(
        'End',
        states={
            'required': Equal(Eval('state'), 'done'),
        },
        help="Automatically set when the surgery is done."
        "It is also the estimated end time when confirming the surgery.")

    surgery_length = fields.Function(
        fields.TimeDelta('Duration',
                         states={
                             'invisible':
                             And(Not(Equal(Eval('state'), 'done')),
                                 Not(Equal(Eval('state'), 'signed')))
                         },
                         help="Length of the surgery"), 'surgery_duration')

    state = fields.Selection([
        ('draft', 'Draft'),
        ('confirmed', 'Confirmed'),
        ('cancelled', 'Cancelled'),
        ('in_progress', 'In Progress'),
        ('done', 'Done'),
        ('signed', 'Signed'),
    ],
                             'State',
                             readonly=True,
                             sort=False)

    signed_by = fields.Many2One(
        'gnuhealth.healthprofessional',
        'Signed by',
        readonly=True,
        states={'invisible': Not(Equal(Eval('state'), 'signed'))},
        help="Health Professional that signed this surgery document")

    # age is deprecated in GNU Health 2.0
    age = fields.Char('Estimative Age',
                      help="Use this field for historical purposes, \
        when no date of surgery is given")

    computed_age = fields.Function(
        fields.Char('Age',
                    help="Computed patient age at the moment of the surgery"),
        'patient_age_at_surgery')

    gender = fields.Function(fields.Selection([
        (None, ''),
        ('m', 'Male'),
        ('f', 'Female'),
        ('f-m', 'Female -> Male'),
        ('m-f', 'Male -> Female'),
    ], 'Gender'),
                             'get_patient_gender',
                             searcher='search_patient_gender')

    description = fields.Char('Description')
    preop_mallampati = fields.Selection([
        (None, ''),
        ('Class 1', 'Class 1: Full visibility of tonsils, uvula and soft '
         'palate'),
        ('Class 2', 'Class 2: Visibility of hard and soft palate, '
         'upper portion of tonsils and uvula'),
        ('Class 3', 'Class 3: Soft and hard palate and base of the uvula are '
         'visible'),
        ('Class 4', 'Class 4: Only Hard Palate visible'),
    ],
                                        'Mallampati Score',
                                        sort=False)
    preop_bleeding_risk = fields.Boolean(
        'Risk of Massive bleeding',
        help="Patient has a risk of losing more than 500 "
        "ml in adults of over 7ml/kg in infants. If so, make sure that "
        "intravenous access and fluids are available")

    preop_oximeter = fields.Boolean('Pulse Oximeter in place',
                                    help="Pulse oximeter is in place "
                                    "and functioning")

    preop_site_marking = fields.Boolean(
        'Surgical Site Marking',
        help="The surgeon has marked the surgical incision")

    preop_antibiotics = fields.Boolean(
        'Antibiotic Prophylaxis',
        help="Prophylactic antibiotic treatment within the last 60 minutes")

    preop_sterility = fields.Boolean(
        'Sterility confirmed',
        help="Nursing team has confirmed sterility of the devices and room")

    preop_asa = fields.Selection([
        (None, ''),
        ('ps1', 'PS 1 : Normal healthy patient'),
        ('ps2', 'PS 2 : Patients with mild systemic disease'),
        ('ps3', 'PS 3 : Patients with severe systemic disease'),
        ('ps4', 'PS 4 : Patients with severe systemic disease that is'
         ' a constant threat to life '),
        ('ps5', 'PS 5 : Moribund patients who are not expected to'
         ' survive without the operation'),
        ('ps6', 'PS 6 : A declared brain-dead patient who organs are'
         ' being removed for donor purposes'),
    ],
                                 'ASA PS',
                                 help="ASA pre-operative Physical Status",
                                 sort=False)

    preop_rcri = fields.Many2One(
        'gnuhealth.rcri',
        'RCRI',
        help='Patient Revised Cardiac Risk Index\n'
        'Points 0: Class I Very Low (0.4% complications)\n'
        'Points 1: Class II Low (0.9% complications)\n'
        'Points 2: Class III Moderate (6.6% complications)\n'
        'Points 3 or more : Class IV High (>11% complications)')

    surgical_wound = fields.Selection([
        (None, ''),
        ('I', 'Clean . Class I'),
        ('II', 'Clean-Contaminated . Class II'),
        ('III', 'Contaminated . Class III'),
        ('IV', 'Dirty-Infected . Class IV'),
    ],
                                      'Surgical wound',
                                      sort=False)

    extra_info = fields.Text('Extra Info')

    anesthesia_report = fields.Text('Anesthesia Report')

    institution = fields.Many2One('gnuhealth.institution', 'Institution')

    report_surgery_date = fields.Function(fields.Date('Surgery Date'),
                                          'get_report_surgery_date')
    report_surgery_time = fields.Function(fields.Time('Surgery Time'),
                                          'get_report_surgery_time')

    surgery_team = fields.One2Many(
        'gnuhealth.surgery_team',
        'name',
        'Team Members',
        help="Professionals Involved in the surgery")

    postoperative_dx = fields.Many2One(
        'gnuhealth.pathology',
        'Post-op dx',
        states={
            'invisible':
            And(Not(Equal(Eval('state'), 'done')),
                Not(Equal(Eval('state'), 'signed')))
        },
        help="Post-operative diagnosis")

    @staticmethod
    def default_institution():
        HealthInst = Pool().get('gnuhealth.institution')
        institution = HealthInst.get_institution()
        return institution

    @staticmethod
    def default_surgery_date():
        return datetime.now()

    @staticmethod
    def default_surgeon():
        pool = Pool()
        HealthProf = pool.get('gnuhealth.healthprofessional')
        surgeon = HealthProf.get_health_professional()
        return surgeon

    @staticmethod
    def default_state():
        return 'draft'

    def get_patient_gender(self, name):
        return self.patient.gender

    @classmethod
    def search_patient_gender(cls, name, clause):
        res = []
        value = clause[2]
        res.append(('patient.name.gender', clause[1], value))
        return res

    # Show the gender and age upon entering the patient
    # These two are function fields (don't exist at DB level)
    @fields.depends('patient')
    def on_change_patient(self):
        gender = None
        age = ''
        self.gender = self.patient.gender
        self.computed_age = self.patient.age

    @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('code'):
                config = Config(1)
                values['code'] = Sequence.get_id(
                    config.surgery_code_sequence.id)
        return super(Surgery, cls).create(vlist)

    @classmethod
    # Update to version 2.0
    def __register__(cls, module_name):
        cursor = Transaction().cursor
        TableHandler = backend.get('TableHandler')
        table = TableHandler(cursor, cls, module_name)
        # Rename the date column to surgery_surgery_date
        if table.column_exist('date'):
            table.column_rename('date', 'surgery_date')

        super(Surgery, cls).__register__(module_name)

    @classmethod
    def __setup__(cls):
        super(Surgery, cls).__setup__()
        cls._error_messages.update({
            'end_date_before_start':
            'End time "%(end_date)s" BEFORE '
            'surgery date "%(surgery_date)s"',
            'or_is_not_available':
            'Operating Room is not available'
        })

        cls._buttons.update({
            'confirmed': {
                'invisible':
                And(Not(Equal(Eval('state'), 'draft')),
                    Not(Equal(Eval('state'), 'cancelled'))),
            },
            'cancel': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'start': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'done': {
                'invisible': Not(Equal(Eval('state'), 'in_progress')),
            },
            'signsurgery': {
                'invisible': Not(Equal(Eval('state'), 'done')),
            },
        })

    @classmethod
    def validate(cls, surgeries):
        super(Surgery, cls).validate(surgeries)
        for surgery in surgeries:
            surgery.validate_surgery_period()

    def validate_surgery_period(self):
        Lang = Pool().get('ir.lang')

        language, = Lang.search([
            ('code', '=', Transaction().language),
        ])
        if (self.surgery_end_date and self.surgery_date):
            if (self.surgery_end_date < self.surgery_date):
                self.raise_user_error(
                    'end_date_before_start', {
                        'surgery_date':
                        Lang.strftime(self.surgery_date, language.code,
                                      language.date),
                        'end_date':
                        Lang.strftime(self.surgery_end_date, language.code,
                                      language.date),
                    })

    @classmethod
    def write(cls, surgeries, vals):
        # Don't allow to write the record if the surgery has been signed
        if surgeries[0].state == 'signed':
            cls.raise_user_error(
                "This surgery is at state Done and has been signed\n"
                "You can no longer modify it.")
        return super(Surgery, cls).write(surgeries, vals)

    ## Method to check for availability and make the Operating Room reservation
    # for the associated surgery

    @classmethod
    @ModelView.button
    def confirmed(cls, surgeries):
        surgery_id = surgeries[0]
        Operating_room = Pool().get('gnuhealth.hospital.or')
        cursor = Transaction().cursor

        # Operating Room and end surgery time check
        if (not surgery_id.operating_room or not surgery_id.surgery_end_date):
            cls.raise_user_error("Operating Room and estimated end time  "
                                 "are needed in order to confirm the surgery")

        or_id = surgery_id.operating_room.id
        cursor.execute(
            "SELECT COUNT(*) \
            FROM gnuhealth_surgery \
            WHERE (surgery_date::timestamp,surgery_end_date::timestamp) \
                OVERLAPS (timestamp %s, timestamp %s) \
              AND (state = %s or state = %s) \
              AND operating_room = CAST(%s AS INTEGER) ",
            (surgery_id.surgery_date, surgery_id.surgery_end_date, 'confirmed',
             'in_progress', str(or_id)))
        res = cursor.fetchone()
        if (surgery_id.surgery_end_date < surgery_id.surgery_date):
            cls.raise_user_error("The Surgery end date must later than the \
                Start")
        if res[0] > 0:
            cls.raise_user_error('or_is_not_available')
        else:
            cls.write(surgeries, {'state': 'confirmed'})

    # Cancel the surgery and set it to draft state
    # Free the related Operating Room

    @classmethod
    @ModelView.button
    def cancel(cls, surgeries):
        surgery_id = surgeries[0]
        Operating_room = Pool().get('gnuhealth.hospital.or')

        cls.write(surgeries, {'state': 'cancelled'})

    # Start the surgery

    @classmethod
    @ModelView.button
    def start(cls, surgeries):
        surgery_id = surgeries[0]
        Operating_room = Pool().get('gnuhealth.hospital.or')

        cls.write(
            surgeries, {
                'state': 'in_progress',
                'surgery_date': datetime.now(),
                'surgery_end_date': datetime.now()
            })
        Operating_room.write([surgery_id.operating_room],
                             {'state': 'occupied'})

    # Finnish the surgery
    # Free the related Operating Room

    @classmethod
    @ModelView.button
    def done(cls, surgeries):
        surgery_id = surgeries[0]
        Operating_room = Pool().get('gnuhealth.hospital.or')

        cls.write(surgeries, {
            'state': 'done',
            'surgery_end_date': datetime.now()
        })

        Operating_room.write([surgery_id.operating_room], {'state': 'free'})

    # Sign the surgery document, and the surgical act.

    @classmethod
    @ModelView.button
    def signsurgery(cls, surgeries):
        surgery_id = surgeries[0]

        # Sign, change the state of the Surgery to "Signed"
        # and write the name of the signing health professional

        signing_hp = Pool().get(
            'gnuhealth.healthprofessional').get_health_professional()
        if not signing_hp:
            cls.raise_user_error(
                "No health professional associated to this user !")

        cls.write(surgeries, {'state': 'signed', 'signed_by': signing_hp})

    def get_report_surgery_date(self, name):
        Company = Pool().get('company.company')

        timezone = None
        company_id = Transaction().context.get('company')
        if company_id:
            company = Company(company_id)
            if company.timezone:
                timezone = pytz.timezone(company.timezone)

        dt = self.surgery_date
        return datetime.astimezone(dt.replace(tzinfo=pytz.utc),
                                   timezone).date()

    def get_report_surgery_time(self, name):
        Company = Pool().get('company.company')

        timezone = None
        company_id = Transaction().context.get('company')
        if company_id:
            company = Company(company_id)
            if company.timezone:
                timezone = pytz.timezone(company.timezone)

        dt = self.surgery_date
        return datetime.astimezone(dt.replace(tzinfo=pytz.utc),
                                   timezone).time()
예제 #11
0
파일: test.py 프로젝트: riskiNova/trytond
class DateTime(ModelSQL):
    'DateTime'
    __name__ = 'test.datetime'
    datetime = fields.DateTime(string='DateTime',
                               help='Test datetime',
                               required=False)
예제 #12
0
class TriageEntry(ModelSQL, ModelView):
    'Triage Entry'
    __name__ = 'gnuhealth.triage.entry'
    firstname = fields.Char('First Name', states=REQD_IF_NOPATIENT)
    lastname = fields.Char('Last Name', states=REQD_IF_NOPATIENT)
    sex = fields.Selection([(None, '')] + SEX_OPTIONS,
                           'Sex',
                           states=REQD_IF_NOPATIENT)
    age = fields.Char('Age', states=REQD_IF_NOPATIENT)
    sex_display = fields.Function(fields.Selection(SEX_OPTIONS, 'Sex'),
                                  'get_sex_age_display')
    age_display = fields.Function(fields.Char('Age'), 'get_sex_age_display')
    id_type = fields.Selection(ID_TYPES,
                               'ID Type',
                               states={
                                   'required': Bool(Eval('id_number')),
                                   'readonly': Bool(Eval('patient'))
                               },
                               sort=False)
    id_number = fields.Char(
        'ID Number',
        states={'readonly': Or(Bool(Eval('patient')), Eval('done', False))})
    id_display = fields.Function(fields.Char('UPI/MRN'),
                                 'get_id_display',
                                 searcher='search_id')
    patient = fields.Many2One('gnuhealth.patient',
                              'Patient',
                              states={
                                  'readonly':
                                  Or(~Eval('can_do_details', False),
                                     Eval('done', False))
                              })
    priority = fields.Selection(TRIAGE_PRIO,
                                'ESI Priority',
                                sort=False,
                                help='Emergency Severity Index Triage Level',
                                states={
                                    'invisible':
                                    ~(Eval('id', 0) > 0),
                                    'readonly':
                                    Or(~Eval('can_do_details', False),
                                       Eval('done', False))
                                })
    medical_alert = fields.Function(fields.Boolean(
        'Medical Alert',
        states={
            'invisible':
            Or(Eval('can_do_details',
                    False), ~In(Eval('status'), ['triage', 'pending']),
               ~In(Eval('priority'), ['99', '77']))
        }),
                                    'get_medical_alert',
                                    setter='set_medical_alert')
    injury = fields.Boolean('Injury', states=SIGNED_STATES)
    review = fields.Boolean('Review', states=SIGNED_STATES)
    status = fields.Selection(TRIAGE_STATUS,
                              'Status',
                              sort=False,
                              states={
                                  'readonly':
                                  Or(~Eval('can_do_details', False),
                                     Eval('done', False))
                              })
    status_display = fields.Function(fields.Char('Status'),
                                     'get_status_display')
    complaint = fields.Char('Primary Complaint', states=SIGNED_STATES)
    notes = fields.Text('Notes (edit)', states=SIGNED_STATES)
    note_entries = fields.One2Many('gnuhealth.triage.note', 'triage_entry',
                                   'Note entries')
    note_display = fields.Function(fields.Text('Notes'), 'get_note_display')
    upi = fields.Function(fields.Char('UPI'), 'get_patient_party_field')
    name = fields.Function(fields.Char('Name'),
                           'get_name',
                           searcher='search_name')
    patient_search = fields.Function(
        fields.One2Many('gnuhealth.patient', None, 'Patients'),
        'patient_search_result')
    queue_entry = fields.One2Many('gnuhealth.patient.queue_entry',
                                  'triage_entry',
                                  'Queue Entry',
                                  size=1)
    encounter = fields.Many2One('gnuhealth.encounter', 'Encounter')
    # Vital Signs
    systolic = fields.Integer('Systolic Pressure', states=SIGNED_STATES)
    diastolic = fields.Integer('Diastolic Pressure', states=SIGNED_STATES)
    bpm = fields.Integer('Heart Rate (bpm)',
                         help='Heart rate expressed in beats per minute',
                         states=SIGNED_STATES)
    respiratory_rate = fields.Integer(
        'Respiratory Rate',
        help='Respiratory rate expressed in breaths per minute',
        states=SIGNED_STATES)
    osat = fields.Integer('Oxygen Saturation',
                          help='Oxygen Saturation(arterial).',
                          states=SIGNED_STATES)
    temperature = fields.Float(u'Temperature (°C)',
                               digits=(4, 1),
                               help='Temperature in degrees celsius',
                               states=SIGNED_STATES)
    # domain=[('temperature', '>', 25), ('temperature', '<', 50)])
    childbearing_age = fields.Function(fields.Boolean('Childbearing Age'),
                                       'get_childbearing_age')
    pregnant = fields.Boolean('Pregnant', states=STATE_NO_MENSES)
    lmp = fields.Date('Last Menstrual Period',
                      states=STATE_NO_MENSES,
                      help='Date last menstrual period started')
    glucose = fields.Float(
        'Glucose (mmol/l)',
        digits=(5, 1),
        help='mmol/l. Reading from glucose meter',
        states=SIGNED_STATES,
        domain=[
            'OR', ('glucose', '=', None),
            ['AND', ('glucose', '>', 0), ('glucose', '<', 55.1)]
        ])
    height = fields.Numeric('Height (cm)', digits=(4, 1), states=SIGNED_STATES)
    weight = fields.Numeric('Weight (kg)', digits=(3, 2), states=SIGNED_STATES)
    uri_ph = fields.Numeric('pH', digits=(1, 1), states=SIGNED_STATES)
    uri_specific_gravity = fields.Numeric('Specific Gravity',
                                          digits=(1, 3),
                                          states=SIGNED_STATES)
    uri_protein = fields.Selection('uri_selection',
                                   'Protein',
                                   sort=False,
                                   states=SIGNED_STATES)
    uri_blood = fields.Selection('uri_selection',
                                 'Blood',
                                 sort=False,
                                 states=SIGNED_STATES)
    uri_glucose = fields.Selection('uri_selection',
                                   'Glucose',
                                   sort=False,
                                   states=SIGNED_STATES)
    uri_nitrite = fields.Selection('uri_nitrite_selection',
                                   'Nitrite',
                                   sort=False,
                                   states=SIGNED_STATES)
    uri_bilirubin = fields.Selection('uri_selection',
                                     'Bilirubin',
                                     sort=False,
                                     states=SIGNED_STATES)
    uri_leuko = fields.Selection('uri_selection',
                                 'Leukocytes',
                                 sort=False,
                                 states=SIGNED_STATES)
    uri_ketone = fields.Selection('uri_selection',
                                  'Ketone',
                                  sort=False,
                                  states=SIGNED_STATES)
    uri_urobili = fields.Selection('uri_selection',
                                   'Urobilinogen',
                                   sort=False,
                                   states=SIGNED_STATES)

    malnutrition = fields.Boolean(
        'Malnourished',
        help='Check this box if the patient show signs of malnutrition.',
        states=SIGNED_STATES)

    dehydration = fields.Selection(
        [(None, 'No'), ('mild', 'Mild'), ('moderate', 'Moderate'),
         ('severe', 'Severe')],
        'Dehydration',
        sort=False,
        help='If the patient show signs of dehydration.',
        states=SIGNED_STATES)
    symp_fever = fields.Boolean('Fever', states=SIGNED_STATES)
    symp_respiratory = fields.Boolean('Respiratory',
                                      help="breathing problems",
                                      states=SIGNED_STATES)
    symp_jaundice = fields.Boolean('Jaundice', states=SIGNED_STATES)
    symp_rash = fields.Boolean('Rash', states=SIGNED_STATES)
    symp_hemorrhagic = fields.Boolean("Hemorrhagic", states=SIGNED_STATES)
    symp_neurological = fields.Boolean("Neurological", states=SIGNED_STATES)
    symp_arthritis = fields.Boolean("Arthralgia/Arthritis",
                                    states=SIGNED_STATES)
    symp_vomitting = fields.Boolean("Vomitting", states=SIGNED_STATES)
    symp_diarrhoea = fields.Boolean("Diarrhoea", states=SIGNED_STATES)
    recent_travel_contact = fields.Char(
        "Countries visited/Contact with traveller",
        states=SIGNED_STATES,
        help="Countries visited or from which there was contact with a "
        "traveller within the last six weeks")
    institution = fields.Many2One('gnuhealth.institution',
                                  'Institution',
                                  states={'readonly': True})
    _history = True  # enable revision control from core
    can_do_details = fields.Function(fields.Boolean('Can do triage details'),
                                     'get_do_details_perm')
    first_contact_time = fields.Function(fields.Text('First Contact Time'),
                                         'get_first_time_contact')
    done = fields.Boolean('Done', states={'invisible': True})
    end_time = fields.DateTime('End Time',
                               help='Date and time triage ended',
                               states={
                                   'readonly':
                                   Or(~Eval('can_do_details', False),
                                      Eval('done', False))
                               })
    post_appointment = fields.Many2One('gnuhealth.appointment', 'Appointment')
    # signed_by = fields.Many2One('gnuhealth.healthprofessional'', 'Signed By')
    # sign_time = fields.DateTime('Signed on')
    total_time = fields.Function(
        fields.Char('Triage Time', states={'invisible': ~Eval('done', False)}),
        'get_triage_time')

    @classmethod
    def __setup__(cls):
        super(TriageEntry, cls).__setup__()
        cls._buttons.update({
            'set_done': {
                'readonly':
                ~Eval('can_do_details', False),
                'invisible':
                Or(In(Eval('status'), ['pending', 'triage']),
                   Eval('done', False))
            },
            'go_referral': {
                'readonly': ~Eval('can_do_details', False),
                'invisible': ~In(Eval('status'), ['refer', 'referin'])
            }
        })

    @classmethod
    def _swapnote(cls, vdict):
        '''swaps out the value in the notes field for an entry that creates
        a new gnuhealth.triage.note model instance'''
        new_note = vdict.get('notes', '')
        if new_note.strip():
            new_note = new_note.strip()
            noteobj = ('create', [{'note': new_note}])
            vdict.setdefault('note_entries', []).append(noteobj)
            vdict[
                'notes'] = u''  # toDo: remove this for next release and use vdict.pop
        return vdict

    @classmethod
    def make_priority_updates(cls, triage_entries, values_to_write):
        if ('priority' in values_to_write
                and 'queue_entry' not in values_to_write):
            prio = int(values_to_write['priority'])
            queue_model = Pool().get('gnuhealth.patient.queue_entry')
            qentries = queue_model.search([('triage_entry', 'in',
                                            triage_entries)])
            values_to_write['queue_entry'] = [('write', map(int, qentries), {
                'priority': prio
            })]
        # force end-time to now if none entered and the prompt ignored
        if (values_to_write.get('done', False)
                and not values_to_write.get('end_time', False)):
            values_to_write['end_time'] = datetime.now()

        return triage_entries, cls._swapnote(values_to_write)

    @classmethod
    def create(cls, vlist):
        # add me to the queue when created
        for vdict in vlist:
            if not vdict.get('queue_entry'):
                if vdict.get('medical_alert') is True:
                    vqprio = MED_ALERT
                else:
                    try:
                        vqprio = int(vdict.get('priority', TRIAGE_MAX_PRIO))
                    except TypeError:
                        vqprio = int(TRIAGE_MAX_PRIO)

                vdict['queue_entry'] = [('create', [{
                    'busy': False,
                    'priority': vqprio
                }])]
                vdict = cls._swapnote(vdict)  # in case there's a note now
        return super(TriageEntry, cls).create(vlist)

    @classmethod
    def write(cls, records, values, *args):
        # update queue priority when mine updated
        # but only if it's higher or there's no appointment
        records, values = cls.make_priority_updates(records, values)
        newargs = []
        if args:
            arglist = iter(args)
            for r, v in zip(arglist, arglist):
                r, v = cls.make_priority_updates(r, v)
                newargs.extend([r, v])
        return super(TriageEntry, cls).write(records, values, *newargs)

    @staticmethod
    def default_priority():
        return str(TRIAGE_MAX_PRIO)

    @staticmethod
    def default_status():
        return 'pending'

    def get_triage_time(self, name):
        endtime = self.end_time if self.done else datetime.now()
        return get_elapsed_time(self.create_date, endtime)

    def get_name(self, name):
        if name == 'name':
            if self.patient:
                return self.patient.name.name
            else:
                return '%s, %s' % (self.lastname, self.firstname)
        return ''

    @classmethod
    def search_name(cls, name, clause):
        fld, operator, operand = clause
        return [
            'OR', ('patient.name.name', operator, operand),
            ('firstname', operator, operand), ('lastname', operator, operand)
        ]

    @classmethod
    def search_id(cls, name, clause):
        fld, operator, operand = clause
        return [
            'OR' ('patient.name.upi', operator, operand),
            ('patient.medical_record_num', operator, operand),
            ('id_number', operator, operand)
        ]

    @classmethod
    def get_patient_party_field(cls, instances, name):
        out = dict([(i.id, '') for i in instances])
        if name == 'upi':
            out.update([(i.id, i.patient.puid) for i in instances
                        if i.patient])
        return out

    def get_id_display(self, name):
        idtypedict = dict(ID_TYPES)
        if self.patient:
            return '{} / {}'.format(self.patient.puid,
                                    self.patient.medical_record_num)
        elif self.id_number and self.id_type:
            return ': '.join(
                [idtypedict.get(self.id_type, '??'), self.id_number])
        else:
            return ''

    def patient_search_result(self, name):
        # ToDo: perform search against patient/party and return
        # the ones that match.
        # the domain should include :
        # lastname, firstname, sex, id_type, id_number
        return []

    def get_status_display(self, name):
        return TRIAGE_STATUS_LOOKUP.get(self.status)

    def get_childbearing_age(self, name):
        if self.patient:
            return self.patient.childbearing_age
        elif self.sex == 'm':
            return False
        else:
            age = self.age
            if age.isdigit():
                age = int(age)
            elif age[:-1].isdigit():
                age = int(age[:-1])
            else:
                age = 7  # hack to make a default false for BHC
            if age < MENARCH[0] or age > MENARCH[1]:
                return False
        return True

    def get_sex_age_display(self, name):
        field = name[:3]
        if self.patient:
            return getattr(self.patient, field)
        else:
            return getattr(self, field)

    @fields.depends('sex', 'patient')
    def on_change_with_childbearing_age(self, *a, **k):
        if self.patient:
            return self.patient.childbearing_age
        else:
            if self.sex == 'm':
                return False
            else:
                return True

    @classmethod
    def get_medical_alert(cls, instances, name):
        out = [(i.id, i.priority == MED_ALERT) for i in instances]
        return dict(out)

    @classmethod
    def set_medical_alert(cls, instances, name, value):
        to_write = []
        if value is False:
            return
        for i in instances:
            if i.priority > MED_ALERT:
                to_write.append(i)
        cls.write(to_write, {'priority': MED_ALERT})

    @classmethod
    def get_do_details_perm(cls, instances, name):
        user_has_perm = get_model_field_perm(cls.__name__,
                                             name,
                                             'create',
                                             default_deny=False)
        outval = dict([(x.id, user_has_perm) for x in instances])
        return outval

    @staticmethod
    def default_can_do_details():
        user_has_perm = get_model_field_perm('gnuhealth.triage.entry',
                                             'can_do_details',
                                             'create',
                                             default_deny=False)
        return user_has_perm

    @staticmethod
    def default_childbearing_age():
        return True

    @staticmethod
    def uri_selection():
        return [(None, '')] + URINALYSIS['default']

    @staticmethod
    def uri_nitrite_selection():
        return [(None, '')] + URINALYSIS['nitrite']

    def get_first_time_contact(self, name):
        '''This method gets the date and time 
           this person was first made contact
           with by the attending staff'''
        return localtime(self.create_date).strftime('%F %T')

    @staticmethod
    def default_institution():
        HI = Pool().get('gnuhealth.institution')
        return HI.get_institution()

    def get_note_display(self, name):
        notes = []
        if self.note_entries:
            return u'\n---\n'.join(
                map(lambda x: u' :\n'.join([x.byline, x.note]),
                    self.note_entries))
        else:
            return ''

    @classmethod
    @ModelView.button_action('health_triage_queue.act_triage_referral_starter')
    def go_referral(cls, queue_entries):
        pass

    @classmethod
    @ModelView.button
    def set_done(cls, entries):
        '''set done=True on the triage entry'''
        save_data = {'done': True}
        for entry in entries:
            if not entry.end_time:
                cls.raise_user_warning(
                    'triage_end_date_warn1',
                    'End time has not been set.\nThe current Date and time '
                    'will be used.')
                save_data.update(end_time=datetime.now())
        cls.write(entries, save_data)
예제 #13
0
class ImagingTestRequest(Workflow, ModelSQL, ModelView):
    'Imaging Test Request'
    __name__ = 'gnuhealth.imaging.test.request'

    patient = fields.Many2One('gnuhealth.patient', 'Patient', required=True)
    date = fields.DateTime('Date', required=True)
    requested_test = fields.Many2One('gnuhealth.imaging.test',
                                     'Test',
                                     required=True)
    doctor = fields.Many2One('gnuhealth.healthprofessional',
                             'Doctor',
                             required=True)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('requested', 'Requested'),
        ('done', 'Done'),
    ],
                             'State',
                             readonly=True)
    comment = fields.Text('Comment')
    request = fields.Char('Request', readonly=True)
    urgent = fields.Boolean('Urgent')

    @classmethod
    def __setup__(cls):
        super(ImagingTestRequest, cls).__setup__()
        cls._transitions |= set(
            (('draft', 'requested'), ('requested', 'done')))
        cls._buttons.update({
            'requested': {
                'invisible': ~Eval('state').in_(['draft']),
            },
            'generate_results': {
                'invisible': ~Eval('state').in_(['requested'])
            }
        })
        cls._order.insert(0, ('date', 'DESC'))
        cls._order.insert(1, ('request', 'DESC'))

    @staticmethod
    def default_date():
        return datetime.now()

    @staticmethod
    def default_state():
        return 'draft'

    @staticmethod
    def default_doctor():
        cursor = Transaction().cursor
        User = Pool().get('res.user')
        user = User(Transaction().user)
        login_user_id = int(user.id)
        cursor.execute(
            'SELECT id FROM party_party WHERE is_healthprof=True AND \
            internal_user = %s LIMIT 1', (login_user_id, ))
        partner_id = cursor.fetchone()
        if partner_id:
            cursor = Transaction().cursor
            cursor.execute(
                'SELECT id FROM gnuhealth_healthprofessional WHERE \
                name = %s LIMIT 1', (partner_id[0], ))
            doctor_id = cursor.fetchone()
            return int(doctor_id[0])

    @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('request'):
                config = Config(1)
                values['request'] = Sequence.get_id(
                    config.imaging_request_sequence.id)

        return super(ImagingTestRequest, cls).create(vlist)

    @classmethod
    def copy(cls, tests, default=None):
        if default is None:
            default = {}
        default = default.copy()
        default['request'] = None
        default['date'] = cls.default_date()
        return super(ImagingTestRequest, cls).copy(tests, default=default)

    @classmethod
    @ModelView.button
    @Workflow.transition('requested')
    def requested(cls, requests):
        pass

    @classmethod
    @ModelView.button_action('health_imaging.wizard_generate_result')
    def generate_results(cls, requests):
        pass

    @classmethod
    @Workflow.transition('done')
    def done(cls, requests):
        pass
예제 #14
0
class Consulta(ModelSQL, ModelView):
    'Consulta'
    _name = 'cefiro.consulta'
    _description = __doc__
    #_rec_name = 'horaIni'

    name = fields.Char('Nombre')

    libres = []

    psicologos = fields.Many2Many('cefiro.encuentropsi', 'evento', 'persona',
                                  u'Psicólogos')
    pacientes = fields.Many2Many('cefiro.encuentro', 'evento', 'persona',
                                 'Pacientes')
    estudiantes = fields.Many2Many('cefiro.encuentroest', 'evento', 'persona',
                                   'Estudiantes')

    informe = fields.One2One('cefiro.consultainforme', 'consulta', 'informe',
                             'Informe')

    horaIni = fields.DateTime('Fecha y hora de inicio', required=True)
    horaFin = fields.DateTime('Fecha y hora de fin', required=True)

    consulLibres = fields.Function(
        fields.One2Many('cefiro.consultorio',
                        None,
                        'Consultorios libres',
                        on_change_with=['horaIni', 'horaFin']), 'get_libres')
    #consulLibresInt = fields.Function(fields.One2Many('cefiro.consultorio',None,'Consultorios libres',on_change_with=['consulLbres']),'get_libresInt')

    consultorio = fields.Many2One('cefiro.consultorio',
                                  'Consultorio',
                                  required=True,
                                  domain=[('id', 'in', Eval('consulLibres'))])

    def get_libres(self, ids, name):
        res = {}
        objConsul = Pool().get('cefiro.consultorio')
        for elem in self.browse(ids):
            res[elem.id] = elem.libres
#			if consultorio_ids:
#				res[elem.id].extend(consultorio_ids)

        return res


#	def on_change_with_consulLibres(self,values):
#		return []

    def on_change_with_consulLibres(self, values):
        objConsultorio = Pool().get('cefiro.consultorio')
        objConsulta = Pool().get('cefiro.consulta')
        consultoriosTotId = objConsultorio.search([])
        res = []
        for cons in objConsultorio.browse(consultoriosTotId):
            estaVacio = True
            consultasIDs = cons.consultas

            listaDic = objConsulta.read(consultasIDs)
            for dic in listaDic:
                i1 = values.get('horaIni')
                f1 = values.get('horaFin')
                i2 = dic.get('horaIni')
                f2 = dic.get('horaFin')
                if not ((i1 == None) or (f1 == None)):
                    if not ((f2 < i1) or (f1 < i2)):
                        estaVacio = False
            if estaVacio:
                res.append(cons.id)

        self.libres = res
        #		objConsulta.write(self.id,{'libres':Eval('res')})

        return res
예제 #15
0
class InpatientRegistration(ModelSQL, ModelView):
    'Patient admission History'
    __name__ = 'gnuhealth.inpatient.registration'

    name = fields.Char('Registration Code', readonly=True, select=True)
    patient = fields.Many2One('gnuhealth.patient',
                              'Patient',
                              required=True,
                              select=True)
    admission_type = fields.Selection([
        ('routine', 'Routine'),
        ('maternity', 'Maternity'),
        ('elective', 'Elective'),
        ('urgent', 'Urgent'),
        ('emergency', 'Emergency'),
    ],
                                      'Admission type',
                                      required=True,
                                      select=True)
    hospitalization_date = fields.DateTime('Hospitalization date',
                                           required=True,
                                           select=True)
    discharge_date = fields.DateTime('Expected Discharge Date',
                                     required=True,
                                     select=True)
    attending_physician = fields.Many2One('gnuhealth.physician',
                                          'Attending Physician',
                                          select=True)
    operating_physician = fields.Many2One('gnuhealth.physician',
                                          'Operating Physician')
    admission_reason = fields.Many2One('gnuhealth.pathology',
                                       'Reason for Admission',
                                       help="Reason for Admission",
                                       select=True)
    bed = fields.Many2One('gnuhealth.hospital.bed',
                          'Hospital Bed',
                          states={
                              'required': Not(Bool(Eval('name'))),
                              'readonly': Bool(Eval('name')),
                          },
                          depends=['name'])
    nursing_plan = fields.Text('Nursing Plan')
    medications = fields.One2Many('gnuhealth.inpatient.medication', 'name',
                                  'Medications')
    therapeutic_diets = fields.One2Many('gnuhealth.inpatient.diet', 'name',
                                        'Therapeutic Diets')
    diet_belief = fields.Many2One(
        'gnuhealth.diet.belief',
        'Belief',
        help="Enter the patient belief or religion to choose the \
            proper diet")
    diet_vegetarian = fields.Selection((
        ('none', 'None'),
        ('vegetarian', 'Vegetarian'),
        ('lacto', 'Lacto vegetarian'),
        ('lactoovo', 'Lacto-ovo vegetarian'),
        ('pescetarian', 'Pescetarian'),
        ('vegan', 'Vegan'),
    ),
                                       'Vegetarian',
                                       sort=False,
                                       required=True)
    nutrition_notes = fields.Text('Nutrition notes / directions')
    discharge_plan = fields.Text('Discharge Plan')
    info = fields.Text('Extra Info')
    state = fields.Selection((
        ('free', 'free'),
        ('cancelled', 'cancelled'),
        ('confirmed', 'confirmed'),
        ('hospitalized', 'hospitalized'),
    ),
                             'Status',
                             select=True)
    bed_transfers = fields.One2Many('gnuhealth.bed.transfer',
                                    'name',
                                    'Transfer History',
                                    readonly=True)

    @classmethod
    def __setup__(cls):
        super(InpatientRegistration, cls).__setup__()
        cls._sql_constraints = [('name_uniq', 'unique(name)',
                                 'The Registration code already exists')]
        cls._error_messages.update({
            'bed_is_not_available':
            'Bed is not available',
            'destination_bed_unavailable':
            'Destination bed unavailable'
        })
        cls._buttons.update({
            'confirmed': {
                'invisible':
                And(Not(Equal(Eval('state'), 'free')),
                    Not(Equal(Eval('state'), 'cancelled'))),
            },
            'cancel': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'discharge': {
                'invisible': Not(Equal(Eval('state'), 'hospitalized')),
            },
            'admission': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
        })

    ## Method to check for availability and make the hospital bed reservation

    @classmethod
    @ModelView.button
    def confirmed(cls, registrations):
        registration_id = registrations[0]
        Bed = Pool().get('gnuhealth.hospital.bed')
        cursor = Transaction().cursor
        bed_id = registration_id.bed.id
        cursor.execute(
            "SELECT COUNT(*) \
            FROM gnuhealth_inpatient_registration \
            WHERE (hospitalization_date::timestamp,discharge_date::timestamp) \
                OVERLAPS (timestamp %s, timestamp %s) \
              AND (state = %s or state = %s) \
              AND bed = CAST(%s AS INTEGER) ",
            (registration_id.hospitalization_date,
             registration_id.discharge_date, 'confirmed', 'hospitalized',
             str(bed_id)))
        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")
        if res[0] > 0:
            cls.raise_user_error('bed_is_not_available')
        else:
            cls.write(registrations, {'state': 'confirmed'})
            Bed.write([registration_id.bed], {'state': 'reserved'})

    @classmethod
    @ModelView.button
    def discharge(cls, registrations):
        registration_id = registrations[0]
        Bed = Pool().get('gnuhealth.hospital.bed')

        cls.write(registrations, {'state': 'free'})
        Bed.write([registration_id.bed], {'state': 'free'})

    @classmethod
    @ModelView.button
    def cancel(cls, registrations):
        registration_id = registrations[0]
        Bed = Pool().get('gnuhealth.hospital.bed')

        cls.write(registrations, {'state': 'cancelled'})
        Bed.write([registration_id.bed], {'state': 'free'})

    @classmethod
    @ModelView.button
    def admission(cls, registrations):
        registration_id = registrations[0]
        Bed = Pool().get('gnuhealth.hospital.bed')

        if (registration_id.hospitalization_date.date() !=
                datetime.today().date()):
            cls.raise_user_error("The Admission date must be today")
        else:
            cls.write(registrations, {'state': 'hospitalized'})
            Bed.write([registration_id.bed], {'state': 'occupied'})

    @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)

    @staticmethod
    def default_state():
        return 'free'

    # Allow searching by the hospitalization code or patient name

    def get_rec_name(self, name):
        if self.patient:
            return self.name + ': ' + self.patient.name.name + ' ' + \
             self.patient.name.lastname
        else:
            return self.name

    @classmethod
    def search_rec_name(cls, name, clause):
        field = None
        for field in ('name', 'patient'):
            registrations = cls.search([(field, ) + clause[1:]], limit=1)
            if registrations:
                break
        if registrations:
            return [(field, ) + clause[1:]]
        return [(cls._rec_name, ) + clause[1:]]
예제 #16
0
class GnuHealthPatientLabTest(ModelSQL, ModelView):
    'Patient Lab Test'
    __name__ = 'gnuhealth.patient.lab.test'

    name = fields.Many2One('gnuhealth.lab.test_type', 'Test Type',
        required=True, select=True)
    date = fields.DateTime('Date', select=True)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('tested', 'Tested'),
        ('ordered', 'Ordered'),
        ('cancel', 'Cancel'),
        ], 'State', readonly=True, select=True)
    patient_id = fields.Many2One('gnuhealth.patient', 'Patient', required=True,
     select=True)
    doctor_id = fields.Many2One('gnuhealth.healthprofessional', 'Doctor',
        help="Doctor who Request the lab test.", select=True)
    request = fields.Integer('Request', readonly=True)
    urgent = fields.Boolean('Urgent')

    @classmethod
    def __setup__(cls):
        super(GnuHealthPatientLabTest, cls).__setup__()
        cls._order.insert(0, ('date', 'DESC'))
        cls._order.insert(1, ('request', 'DESC'))
        cls._order.insert(2, ('name', 'ASC'))

    @staticmethod
    def default_date():
        return datetime.now()

    @staticmethod
    def default_state():
        return 'draft'

    @staticmethod
    def default_doctor_id():
        User = Pool().get('res.user')
        user = User(Transaction().user)
        uid = int(user.id)

        parties = Pool().get('party.party').search([
                ('internal_user', '=', uid)])
        if parties:
            doctors = Pool().get('gnuhealth.healthprofessional').search([
                    ('name', '=', parties[0].id)])
            if doctors:
                return doctors[0].id
        else:
            return False

    @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('request'):
                config = Config(1)
                values['request'] = Sequence.get_id(
                    config.lab_request_sequence.id)

        return super(GnuHealthPatientLabTest, cls).create(vlist)

    @classmethod
    def copy(cls, tests, default=None):
        if default is None:
            default = {}
        default = default.copy()
        default['request'] = None
        default['date'] = cls.default_date()
        return super(GnuHealthPatientLabTest, cls).copy(tests,
            default=default)
예제 #17
0
class Cron(DeactivableMixin, ModelSQL, ModelView):
    "Cron"
    __name__ = "ir.cron"
    interval_number = fields.Integer('Interval Number', required=True)
    interval_type = fields.Selection([
            ('minutes', 'Minutes'),
            ('hours', 'Hours'),
            ('days', 'Days'),
            ('weeks', 'Weeks'),
            ('months', 'Months'),
            ], "Interval Type", sort=False, required=True)
    minute = fields.Integer("Minute",
        domain=['OR',
            ('minute', '=', None),
            [('minute', '>=', 0), ('minute', '<=', 59)],
            ],
        states={
            'invisible': Eval('interval_type').in_(['minutes']),
            },
        depends=['interval_type'])
    hour = fields.Integer("Hour",
        domain=['OR',
            ('hour', '=', None),
            [('hour', '>=', 0), ('hour', '<=', 23)],
            ],
        states={
            'invisible': Eval('interval_type').in_(['minutes', 'hours']),
            },
        depends=['interval_type'])
    weekday = fields.Many2One(
        'ir.calendar.day', "Day of Week",
        states={
            'invisible': Eval('interval_type').in_(
                ['minutes', 'hours', 'days']),
            },
        depends=['interval_type'])
    day = fields.Integer("Day",
        domain=['OR',
            ('day', '=', None),
            ('day', '>=', 0),
            ],
        states={
            'invisible': Eval('interval_type').in_(
                ['minutes', 'hours', 'days', 'weeks']),
            },
        depends=['interval_type'])

    next_call = fields.DateTime("Next Call", select=True)
    method = fields.Selection([
            ('ir.trigger|trigger_time', "Run On Time Triggers"),
            ('ir.queue|clean', "Clean Task Queue"),
            ], "Method", required=True)

    @classmethod
    def __setup__(cls):
        super(Cron, cls).__setup__()
        cls._buttons.update({
                'run_once': {
                    'icon': 'tryton-launch',
                    },
                })

    @classmethod
    def __register__(cls, module_name):
        super().__register__(module_name)

        table_h = cls.__table_handler__(module_name)

        # Migration from 5.0: remove fields
        for column in ['name', 'user', 'request_user', 'number_calls',
                'repeat_missed', 'model', 'function', 'args']:
            table_h.drop_column(column)

        # Migration from 5.0: remove required on next_call
        table_h.not_null_action('next_call', 'remove')

    @staticmethod
    def check_xml_record(crons, values):
        return True

    @classmethod
    def view_attributes(cls):
        return [(
                '//label[@id="time_label"]', 'states', {
                    'invisible': Eval('interval_type') == 'minutes',
                }),
            ]

    def compute_next_call(self, now):
        return (now
            + relativedelta(**{self.interval_type: self.interval_number})
            + relativedelta(
                microsecond=0,
                second=0,
                minute=(
                    self.minute
                    if self.interval_type != 'minutes'
                    else None),
                hour=(
                    self.hour
                    if self.interval_type not in {'minutes', 'hours'}
                    else None),
                day=(
                    self.day
                    if self.interval_type not in {
                        'minutes', 'hours', 'days', 'weeks'}
                    else None),
                weekday=(
                    int(self.weekday.index)
                    if self.weekday
                    and self.interval_type not in {'minutes', 'hours', 'days'}
                    else None)))

    @dualmethod
    @ModelView.button
    def run_once(cls, crons):
        pool = Pool()
        for cron in crons:
            model, method = cron.method.split('|')
            Model = pool.get(model)
            getattr(Model, method)()

    @classmethod
    def run(cls, db_name):
        transaction = Transaction()
        logger.info('cron started for "%s"', db_name)
        now = datetime.datetime.now()
        retry = config.getint('database', 'retry')
        with transaction.start(db_name, 0, context={'_skip_warnings': True}):
            transaction.database.lock(transaction.connection, cls._table)
            crons = cls.search(['OR',
                    ('next_call', '<=', now),
                    ('next_call', '=', None),
                    ])

            for cron in crons:
                name = '<Cron %s@%s %s>' % (cron.id, db_name, cron.method)
                logger.info("%s started", name)
                for count in range(retry, -1, -1):
                    if count != retry:
                        time.sleep(0.02 * (retry - count))
                    try:
                        with processing(name):
                            cron.run_once()
                            cron.next_call = cron.compute_next_call(now)
                            cron.save()
                            transaction.commit()
                    except Exception as e:
                        transaction.rollback()
                        if (isinstance(e, backend.DatabaseOperationalError)
                                and count):
                            continue
                        logger.error('%s failed', name, exc_info=True)
                    break
        while transaction.tasks:
            task_id = transaction.tasks.pop()
            run_task(db_name, task_id)
        logger.info('cron finished for "%s"', db_name)
예제 #18
0
class Newborn(ModelSQL, ModelView):
    'Newborn Information'
    __name__ = 'gnuhealth.newborn'

    STATES = {'readonly': Eval('state') == 'signed'}

    name = fields.Char('Newborn ID', states=STATES)
    patient = fields.Many2One('gnuhealth.patient',
                              'Baby',
                              required=True,
                              states=STATES,
                              help="Patient associated to this newborn")

    mother = fields.Many2One('gnuhealth.patient', 'Mother', states=STATES)
    newborn_name = fields.Char('Name at Birth', states=STATES)
    birth_date = fields.DateTime('DoB',
                                 required=True,
                                 help="Date and Time of birth",
                                 states=STATES)
    photo = fields.Binary('Picture', states=STATES)

    # Sex / Gender at birth.

    sex = fields.Selection([
        ('m', 'Male'),
        ('f', 'Female'),
        ], 'Sex',sort=False, required=True,
            help="Sex at birth. It might differ from the current patient" \
            " gender. This is the biological sex.", states = STATES)

    state = fields.Selection([
        (None, ''),
        ('draft', 'draft'),
        ('signed', 'Signed'),
    ],
                             'State',
                             readonly=True,
                             sort=False)

    cephalic_perimeter = fields.Integer(
        'CP', help="Cephalic Perimeter in centimeters (cm)", states=STATES)
    length = fields.Integer('Length',
                            help="Length in centimeters (cm)",
                            states=STATES)
    weight = fields.Integer('Weight',
                            help="Weight in grams (g)",
                            states=STATES)
    apgar1 = fields.Integer('APGAR 1st minute', states=STATES)
    apgar5 = fields.Integer('APGAR 5th minute', states=STATES)
    apgar_scores = fields.One2Many('gnuhealth.neonatal.apgar',
                                   'name',
                                   'APGAR scores',
                                   states=STATES)
    meconium = fields.Boolean('Meconium', states=STATES)

    #Deprecated. Use Patient conditions directly
    congenital_diseases = fields.One2Many('gnuhealth.patient.disease',
                                          'newborn_id',
                                          'Congenital diseases',
                                          states=STATES)

    reanimation_stimulation = fields.Boolean('Stimulation', states=STATES)
    reanimation_aspiration = fields.Boolean('Aspiration', states=STATES)
    reanimation_intubation = fields.Boolean('Intubation', states=STATES)
    reanimation_mask = fields.Boolean('Mask', states=STATES)
    reanimation_oxygen = fields.Boolean('Oxygen', states=STATES)
    test_vdrl = fields.Boolean('VDRL', states=STATES)
    test_toxo = fields.Boolean('Toxoplasmosis', states=STATES)
    test_chagas = fields.Boolean('Chagas', states=STATES)
    test_billirubin = fields.Boolean('Billirubin', states=STATES)
    test_audition = fields.Boolean('Audition', states=STATES)
    test_metabolic = fields.Boolean(
        'Metabolic ("heel stick screening")',
        help="Test for Fenilketonuria, Congenital Hypothyroidism, "
        "Quistic Fibrosis, Galactosemia",
        states=STATES)
    neonatal_ortolani = fields.Boolean('Positive Ortolani', states=STATES)
    neonatal_barlow = fields.Boolean('Positive Barlow', states=STATES)
    neonatal_hernia = fields.Boolean('Hernia', states=STATES)
    neonatal_ambiguous_genitalia = fields.Boolean('Ambiguous Genitalia',
                                                  states=STATES)
    neonatal_erbs_palsy = fields.Boolean('Erbs Palsy', states=STATES)
    neonatal_hematoma = fields.Boolean('Hematomas', states=STATES)
    neonatal_talipes_equinovarus = fields.Boolean('Talipes Equinovarus',
                                                  states=STATES)
    neonatal_polydactyly = fields.Boolean('Polydactyly', states=STATES)
    neonatal_syndactyly = fields.Boolean('Syndactyly', states=STATES)
    neonatal_moro_reflex = fields.Boolean('Moro Reflex', states=STATES)
    neonatal_grasp_reflex = fields.Boolean('Grasp Reflex', states=STATES)
    neonatal_stepping_reflex = fields.Boolean('Stepping Reflex', states=STATES)
    neonatal_babinski_reflex = fields.Boolean('Babinski Reflex', states=STATES)
    neonatal_blink_reflex = fields.Boolean('Blink Reflex', states=STATES)
    neonatal_sucking_reflex = fields.Boolean('Sucking Reflex', states=STATES)
    neonatal_swimming_reflex = fields.Boolean('Swimming Reflex', states=STATES)
    neonatal_tonic_neck_reflex = fields.Boolean('Tonic Neck Reflex',
                                                states=STATES)
    neonatal_rooting_reflex = fields.Boolean('Rooting Reflex', states=STATES)
    neonatal_palmar_crease = fields.Boolean('Transversal Palmar Crease',
                                            states=STATES)

    #Deprecated. Use Patient medication direcly
    medication = fields.One2Many('gnuhealth.patient.medication', 'newborn_id',
                                 'Medication')

    healthprof = fields.Many2One('gnuhealth.healthprofessional',
                                 'Health Professional',
                                 help="Health professional",
                                 readonly=True)

    signed_by = fields.Many2One(
        'gnuhealth.healthprofessional',
        'Signed by',
        readonly=True,
        states={'invisible': Not(Equal(Eval('state'), 'signed'))},
        help="Health Professional that signed this document")

    dismissed = fields.DateTime('Discharged', states=STATES)
    notes = fields.Text('Notes', states=STATES)

    # Deprecated. the following fields will be removed in 2.8
    # Decease information on fetus / newborn are linked now in
    # the obstetrics evaluation (prenatal) or patient if result of pregnancy
    # was a live birth.
    # The information is no longer shown at the view.
    # Fields to be removed : bd, died_at_delivery, died_at_the_hospital
    # died_being_transferred, tod, cod

    bd = fields.Boolean('Stillbirth')
    died_at_delivery = fields.Boolean('Died at delivery room')
    died_at_the_hospital = fields.Boolean('Died at the hospital')
    died_being_transferred = fields.Boolean(
        'Died being transferred',
        help="The baby died being transferred to another health institution")
    tod = fields.DateTime('Time of Death')
    cod = fields.Many2One('gnuhealth.pathology', 'Cause of death')

    @staticmethod
    def default_healthprof():
        pool = Pool()
        HealthProf = pool.get('gnuhealth.healthprofessional')
        healthprof = HealthProf.get_health_professional()
        return healthprof

    @staticmethod
    def default_state():
        return 'draft'

    @classmethod
    def __setup__(cls):
        super(Newborn, cls).__setup__()

        t = cls.__table__()
        cls._sql_constraints = [
            ('name_uniq', Unique(t, t.name), 'The Newborn ID must be unique'),
            ('patient_uniq', Unique(t, t.patient),
             'There is already a newborn record for this patient'),
        ]

        cls._buttons.update(
            {'sign_newborn': {
                'invisible': Equal(Eval('state'), 'signed')
            }})

    @classmethod
    @ModelView.button
    def sign_newborn(cls, newborns):
        pool = Pool()
        HealthProfessional = pool.get('gnuhealth.healthprofessional')
        Appointment = pool.get('gnuhealth.appointment')

        newborn_id = newborns[0]

        patient_app = []

        # Change the state of the newborn to "Done"

        signing_hp = HealthProfessional.get_health_professional()

        cls.write(newborns, {
            'state': 'signed',
            'signed_by': signing_hp,
        })

    @classmethod
    def __register__(cls, module_name):
        cursor = Transaction().cursor
        TableHandler = backend.get('TableHandler')
        table = TableHandler(cursor, cls, module_name)

        #Rename responsible -> healthprof
        if table.column_exist('responsible'):
            table.column_rename('responsible', 'healthprof')

        super(Newborn, cls).__register__(module_name)

    @classmethod
    def write(cls, newborns, values):
        pool = Pool()

        cursor = Transaction().cursor
        Patient = pool.get('gnuhealth.patient')
        Party = pool.get('party.party')

        party = []
        patient = []

        cursor = Transaction().cursor

        for newborn in newborns:

            newborn_patient_id = newborn.patient.id

            person = Patient.browse([newborn_patient_id])[0].name
            pat = Patient.browse([newborn_patient_id])[0]

            # Update the birth date on the party model upon WRITING it on the
            # newborn model

            born_date = datetime.date(newborn.birth_date)

            party.append(person)

            Party.write(party, {'dob': born_date})

            # Update the biological sex on the patient model upon WRITING
            # it on the newborn model

            if values.get('sex'):
                biological_sex = values.get('sex')

                patient.append(pat)

                Patient.write(patient, {'biological_sex': biological_sex})

        return super(Newborn, cls).write(newborns, values)

    @classmethod
    def create(cls, vlist):
        pool = Pool()
        vlist = [x.copy() for x in vlist]
        Patient = pool.get('gnuhealth.patient')
        Party = pool.get('party.party')

        party = []
        patient = []

        cursor = Transaction().cursor

        for values in vlist:
            newborn_patient_id = values['patient']

            person = Patient.browse([newborn_patient_id])[0].name
            pat = Patient.browse([newborn_patient_id])[0]

            # Update the birth date on the party model upon CREATING it on the
            # newborn model

            born_date = datetime.date(values['birth_date'])

            party.append(person)

            Party.write(party, {'dob': born_date})

            # Update the biological sex on the patient model upon CREATING
            # it on the newborn model

            if values.get('sex'):
                biological_sex = values.get('sex')

                patient.append(pat)

                Patient.write(patient, {'biological_sex': biological_sex})

        return super(Newborn, cls).create(vlist)
예제 #19
0
class SupportRequest (ModelSQL, ModelView):
    'Support Request Registration'
    __name__ = 'gnuhealth.support_request'
    _rec_name = 'code'

    code = fields.Char('Code',help='Request Code', readonly=True)

    operator = fields.Many2One(
        'gnuhealth.healthprofessional', 'Operator',
        help="Operator who took the call / support request")

    requestor = fields.Many2One('party.party', 'Requestor',
    domain=[('is_person', '=', True)], help="Related party (person)")

    patient = fields.Many2One('gnuhealth.patient', 'Patient')

    evaluation = fields.Many2One('gnuhealth.patient.evaluation',
        'Evaluation', 
        domain=[('patient', '=', Eval('patient'))], depends=['patient'],
        help='Related Patient Evaluation')

    request_date = fields.DateTime('Date', required=True,
        help="Date and time of the call for help")
    
    operational_sector = fields.Many2One('gnuhealth.operational_sector',
        'O. Sector',help="Operational Sector")

    latitude = fields.Numeric('Latidude', digits=(3, 14))
    longitude = fields.Numeric('Longitude', digits=(4, 14))

    address = fields.Text("Address", help="Free text address / location")
    urladdr = fields.Char(
        'OSM Map',
        help="Maps the location on Open Street Map")

    healthcenter = fields.Many2One('gnuhealth.institution','Calling Institution')

    patient_sex = fields.Function(
        fields.Char('Sex'),
        'get_patient_sex')

    patient_age = fields.Function(
        fields.Char('Age'),
        'get_patient_age')

    complaint = fields.Function(
        fields.Char('Chief Complaint'),
        'get_patient_complaint')

    urgency = fields.Selection([
        (None, ''),
        ('low', 'Low'),
        ('urgent', 'Urgent'),
        ('emergency', 'Emergency'),
        ], 'Urgency', sort=False)
       
    place_occurrance = fields.Selection([
        (None, ''),
        ('home', 'Home'),
        ('street', 'Street'),
        ('institution', 'Institution'),
        ('school', 'School'),
        ('commerce', 'Commercial Area'),
        ('recreational', 'Recreational Area'),
        ('transportation', 'Public transportation'),
        ('sports', 'Sports event'),
        ('publicbuilding', 'Public Building'),
        ('unknown', 'Unknown'),
        ], 'Origin', help="Place of occurrance",sort=False)

    event_type = fields.Selection([
        (None, ''),
        ('event1', 'Acute Coronary Syndrome'),
        ('event2', 'Acute pain'),
        ('event3', 'Acute illness'),
        ('event4', 'Allergic reaction'),
        ('event5', 'Bullying, battering'),
        ('event6', 'Gastrointestinal event'),
        ('event7', 'Endocrine event (diabetes, adrenal crisis, ..)'),
        ('event8', 'Choke'),
        ('event9', 'Domestic violence'),
        ('event10', 'Environmental event (weather, animals, ...)'),
        ('event11', 'Sexual assault'),
        ('event12', 'Drug intoxication'),
        ('event13', 'Robbery, violent assault'),
        ('event14', 'Respiratory distress'),
        ('event15', 'Pregnancy related event'),
        ('event16', 'Gas intoxication'),
        ('event17', 'Food intoxication'),
        ('event18', 'Neurological event (stroke, TIA, seizure, ...)'),
        ('event19', 'Chronic illness'),
        ('event20', 'Near drowning'),
        ('event21', 'Eye, Ear and Nose event'),
        ('event22', 'Fall'),
        ('event23', 'Deceased person'),
        ('event24', 'Psychiatric event'),
        ('event25', 'Suicide attempt'),
        ('event26', 'Fire'),
        ('event27', 'Transportation accident'),
        ('event28', 'Traumatic Injuries'),
        ('event29', 'Explosion'),
        ('event30', 'Other specified'),
        ], 'Event type')

    event_specific = fields.Many2One ('gnuhealth.pathology','Incident')

    multiple_casualties = fields.Boolean('Multiple Casualties')

    request_actions = fields.One2Many(
        'gnuhealth.support_request.log', 'sr',
        'Activities', help='Support request activity log')

    ambulances = fields.One2Many(
        'gnuhealth.ambulance.support', 'sr',
        'Ambulances', help='Ambulances requested in this Support Request')

    request_extra_info = fields.Text('Details')

    state = fields.Selection([
        (None, ''),
        ('open', 'Open'),
        ('closed', 'Closed'),
        ], 'State', sort=False, readonly=True)
 
    @staticmethod
    def default_request_date():
        return datetime.now()

    
    def get_patient_sex(self, name):
        if self.patient:
            return self.patient.gender

    def get_patient_age(self, name):
        if self.patient:
            return self.patient.name.age

    def get_patient_complaint(self, name):
        if self.evaluation:
            if self.evaluation.chief_complaint:
                return self.evaluation.chief_complaint

    @staticmethod
    def default_operator():
        pool = Pool()
        HealthProf= pool.get('gnuhealth.healthprofessional')
        operator = HealthProf.get_health_professional()
        return operator

    @staticmethod
    def default_state():
        return 'open'


    @fields.depends('latitude', 'longitude')
    def on_change_with_urladdr(self):
        # Generates the URL to be used in OpenStreetMap
        # The address will be mapped to the URL in the following way
        # If the latitud and longitude of the Accident / Injury 
        # are given, then those parameters will be used.

        ret_url = ''
        if (self.latitude and self.longitude):
            ret_url = 'http://openstreetmap.org/?mlat=' + \
                str(self.latitude) + '&mlon=' + str(self.longitude)

        return ret_url

    @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('code'):
                config = Config(1)
                values['code'] = Sequence.get_id(
                    config.support_request_code_sequence.id)

        return super(SupportRequest, cls).create(vlist)


    @classmethod
    def __setup__(cls):
        super(SupportRequest, cls).__setup__()
        t = cls.__table__()
        cls._sql_constraints = [
            ('code_uniq', Unique(t,t.code), 
            'This Request Code already exists'),
        ]

        cls._buttons.update({
            'open_support': {'invisible': Equal(Eval('state'), 'open')},
            'close_support': {'invisible': Equal(Eval('state'), 'closed')},
            })


    @classmethod
    @ModelView.button
    def open_support(cls, srs):
        cls.write(srs, {
            'state': 'open'})

    @classmethod
    @ModelView.button
    def close_support(cls, srs):
        cls.write(srs, {
            'state': 'closed'})
예제 #20
0
class PediatricSymptomsChecklist(ModelSQL, ModelView):
    'Pediatric Symptoms Checklist'
    __name__ = 'gnuhealth.patient.psc'

    patient = fields.Many2One('gnuhealth.patient', 'Patient', required=True)

    evaluation_date = fields.Many2One(
        'gnuhealth.appointment',
        'Appointment',
        help="Enter or select the date / ID of the appointment related to "
        "this evaluation")

    evaluation_start = fields.DateTime('Date', required=True)

    user_id = fields.Many2One('res.user', 'Health Professional', readonly=True)

    notes = fields.Text('Notes')

    psc_aches_pains = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                       'Complains of aches and pains',
                                       sort=False)

    psc_spend_time_alone = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                            'Spends more time alone',
                                            sort=False)

    psc_tires_easily = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                        'Tires easily, has little energy',
                                        sort=False)

    psc_fidgety = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                   'Fidgety, unable to sit still',
                                   sort=False)

    psc_trouble_with_teacher = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                                'Has trouble with teacher',
                                                sort=False)

    psc_less_interest_in_school = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                                   'Less interested in school',
                                                   sort=False)

    psc_acts_as_driven_by_motor = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Acts as if driven by a motor',
        sort=False)

    psc_daydreams_too_much = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                              'Daydreams too much',
                                              sort=False)

    psc_distracted_easily = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                             'Distracted easily',
                                             sort=False)

    psc_afraid_of_new_situations = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Is afraid of new situations',
        sort=False)

    psc_sad_unhappy = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                       'Feels sad, unhappy',
                                       sort=False)

    psc_irritable_angry = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                           'Is irritable, angry',
                                           sort=False)

    psc_feels_hopeless = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                          'Feels hopeless',
                                          sort=False)

    psc_trouble_concentrating = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                                 'Has trouble concentrating',
                                                 sort=False)

    psc_less_interested_in_friends = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Less interested in friends',
        sort=False)

    psc_fights_with_others = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                              'Fights with other children',
                                              sort=False)

    psc_absent_from_school = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                              'Absent from school',
                                              sort=False)

    psc_school_grades_dropping = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                                  'School grades dropping',
                                                  sort=False)

    psc_down_on_self = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                        'Is down on him or herself',
                                        sort=False)

    psc_visit_doctor_finds_ok = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Visits the doctor with doctor finding nothing wrong',
        sort=False)

    psc_trouble_sleeping = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                            'Has trouble sleeping',
                                            sort=False)

    psc_worries_a_lot = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                         'Worries a lot',
                                         sort=False)

    psc_wants_to_be_with_parents = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Wants to be with you more than before',
        sort=False)

    psc_feels_is_bad_child = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                              'Feels he or she is bad',
                                              sort=False)

    psc_takes_unnecesary_risks = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                                  'Takes unnecessary risks',
                                                  sort=False)

    psc_gets_hurt_often = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                           'Gets hurt frequently',
                                           sort=False)

    psc_having_less_fun = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                           'Seems to be having less fun',
                                           sort=False)

    psc_act_as_younger = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Acts younger than children his or her age',
        sort=False)

    psc_does_not_listen_to_rules = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                                    'Does not listen to rules',
                                                    sort=False)

    psc_does_not_show_feelings = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                                  'Does not show feelings',
                                                  sort=False)

    psc_does_not_get_people_feelings = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Does not get people feelings',
        sort=False)

    psc_teases_others = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                         'Teases others',
                                         sort=False)

    psc_blames_others = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Blames others for his or her troubles',
        sort=False)

    psc_takes_things_from_others = fields.Selection(
        [
            (None, ''),
            ('0', 'Never'),
            ('1', 'Sometimes'),
            ('2', 'Often'),
        ],
        'Takes things that do not belong to him or her',
        sort=False)

    psc_refuses_to_share = fields.Selection([
        (None, ''),
        ('0', 'Never'),
        ('1', 'Sometimes'),
        ('2', 'Often'),
    ],
                                            'Refuses to share',
                                            sort=False)

    psc_total = fields.Integer('PSC Total')

    @staticmethod
    def default_user_id():
        User = Pool().get('res.user')
        user = User(Transaction().user)
        return int(user.id)

    @staticmethod
    def default_psc_total():
        return 0

    @fields.depends(
        'psc_aches_pains', 'psc_spend_time_alone', 'psc_tires_easily',
        'psc_fidgety', 'psc_trouble_with_teacher',
        'psc_less_interest_in_school', 'psc_acts_as_driven_by_motor',
        'psc_daydreams_too_much', 'psc_distracted_easily',
        'psc_afraid_of_new_situations', 'psc_sad_unhappy',
        'psc_irritable_angry', 'psc_feels_hopeless',
        'psc_trouble_concentrating', 'psc_less_interested_in_friends',
        'psc_fights_with_others', 'psc_absent_from_school',
        'psc_school_grades_dropping', 'psc_down_on_self',
        'psc_visit_doctor_finds_ok', 'psc_trouble_sleeping',
        'psc_worries_a_lot', 'psc_wants_to_be_with_parents',
        'psc_feels_is_bad_child', 'psc_takes_unnecesary_risks',
        'psc_gets_hurt_often', 'psc_having_less_fun', 'psc_act_as_younger',
        'psc_does_not_listen_to_rules', 'psc_does_not_show_feelings',
        'psc_does_not_get_people_feelings', 'psc_teases_others',
        'psc_takes_things_from_others', 'psc_refuses_to_share')
    def on_change_with_psc_total(self):

        psc_aches_pains = self.psc_aches_pains or '0'
        psc_spend_time_alone = self.psc_spend_time_alone or '0'
        psc_tires_easily = self.psc_tires_easily or '0'
        psc_fidgety = self.psc_fidgety or '0'
        psc_trouble_with_teacher = self.psc_trouble_with_teacher or '0'
        psc_less_interest_in_school = self.psc_less_interest_in_school or '0'
        psc_acts_as_driven_by_motor = self.psc_acts_as_driven_by_motor or '0'
        psc_daydreams_too_much = self.psc_daydreams_too_much or '0'
        psc_distracted_easily = self.psc_distracted_easily or '0'
        psc_afraid_of_new_situations = self.psc_afraid_of_new_situations or '0'
        psc_sad_unhappy = self.psc_sad_unhappy or '0'
        psc_irritable_angry = self.psc_irritable_angry or '0'
        psc_feels_hopeless = self.psc_feels_hopeless or '0'
        psc_trouble_concentrating = self.psc_trouble_concentrating or '0'
        psc_less_interested_in_friends = \
                self.psc_less_interested_in_friends or '0'
        psc_fights_with_others = self.psc_fights_with_others or '0'
        psc_absent_from_school = self.psc_absent_from_school or '0'
        psc_school_grades_dropping = self.psc_school_grades_dropping or '0'
        psc_down_on_self = self.psc_down_on_self or '0'
        psc_visit_doctor_finds_ok = self.psc_visit_doctor_finds_ok or '0'
        psc_trouble_sleeping = self.psc_trouble_sleeping or '0'
        psc_worries_a_lot = self.psc_worries_a_lot or '0'
        psc_wants_to_be_with_parents = self.psc_wants_to_be_with_parents or '0'
        psc_feels_is_bad_child = self.psc_feels_is_bad_child or '0'
        psc_takes_unnecesary_risks = self.psc_takes_unnecesary_risks or '0'
        psc_gets_hurt_often = self.psc_gets_hurt_often or '0'
        psc_having_less_fun = self.psc_having_less_fun or '0'
        psc_act_as_younger = self.psc_act_as_younger or '0'
        psc_does_not_listen_to_rules = self.psc_does_not_listen_to_rules or '0'
        psc_does_not_show_feelings = self.psc_does_not_show_feelings or '0'
        psc_does_not_get_people_feelings = \
                self.psc_does_not_get_people_feelings or '0'
        psc_teases_others = self.psc_teases_others or '0'
        psc_takes_things_from_others = self.psc_takes_things_from_others or '0'
        psc_refuses_to_share = self.psc_refuses_to_share or '0'

        psc_total = int(psc_aches_pains) + int(psc_spend_time_alone) + \
            int(psc_tires_easily) + int(psc_fidgety) + \
            int(psc_trouble_with_teacher) + \
            int(psc_less_interest_in_school) + \
            int(psc_acts_as_driven_by_motor) + \
            int(psc_daydreams_too_much) + int(psc_distracted_easily) + \
            int(psc_afraid_of_new_situations) + int(psc_sad_unhappy) + \
            int(psc_irritable_angry) + int(psc_feels_hopeless) + \
            int(psc_trouble_concentrating) + \
            int(psc_less_interested_in_friends) + \
            int(psc_fights_with_others) + int(psc_absent_from_school) + \
            int(psc_school_grades_dropping) + int(psc_down_on_self) + \
            int(psc_visit_doctor_finds_ok) + int(psc_trouble_sleeping) + \
            int(psc_worries_a_lot) + int(psc_wants_to_be_with_parents) + \
            int(psc_feels_is_bad_child) + int(psc_takes_unnecesary_risks) + \
            int(psc_gets_hurt_often) + int(psc_having_less_fun) + \
            int(psc_act_as_younger) + int(psc_does_not_listen_to_rules) + \
            int(psc_does_not_show_feelings) + \
            int(psc_does_not_get_people_feelings) + \
            int(psc_teases_others) + \
            int(psc_takes_things_from_others) + \
            int(psc_refuses_to_share)

        return psc_total
예제 #21
0
class OphthalmologyEvaluation(ModelSQL, ModelView):
    'Ophthalmology Evaluation'
    __name__ = 'gnuhealth.ophthalmology.evaluation'

    STATES = {'readonly': Eval('state') == 'done'}

    patient = fields.Many2One('gnuhealth.patient', 'Patient', required=True)
    visit_date = fields.DateTime('Date', help="Date of Consultation")
    computed_age = fields.Function(
        fields.Char(
            'Age',
            help="Computed patient age at the moment of the evaluation"),
        'patient_age_at_evaluation')

    gender = fields.Function(fields.Selection([
        (None, ''),
        ('m', 'Male'),
        ('f', 'Female'),
    ], 'Gender'),
                             'get_patient_gender',
                             searcher='search_patient_gender')

    health_professional = fields.Many2One(
        'gnuhealth.healthprofessional',
        'Health Professional',
        readonly=True,
        help="Health professional / Ophthalmologist / OptoMetrist")

    # there are two types of charts, a meter chart.. 6/.. val
    # and ft chart.. 200/...
    snellen_chart = [
        (None, ''),
        ('6_6', '6/6'),
        ('6_9', '6/9'),
        ('6_12', '6/12'),
        ('6_18', '6/18'),
        ('6_24', '6/24'),
        ('6_36', '6/36'),
        ('6_60', '6/60'),
        ('5_60', '5/60'),
        ('4_60', '4/60'),
        ('3_60', '3/60'),
        ('2_60', '2/60'),
        ('1_60', '1/60'),
        ('1_meter_fc', '1 Meter FC'),
        ('1_2_meter_fc', '1/2 Meter FC'),
        ('hmfc', 'HMCF'),
        ('p_l', 'P/L'),
    ]

    # Near vision chart
    near_vision_chart = [
        (None, ''),
        ('N6', 'N6'),
        ('N8', 'N8'),
        ('N12', 'N12'),
        ('N18', 'N18'),
        ('N24', 'N24'),
        ('N36', 'N36'),
        ('N60', 'N60'),
    ]
    # vision test using snellen chart
    rdva = fields.Selection(snellen_chart,
                            'RDVA',
                            help="Right Eye Vision of Patient without aid",
                            sort=False,
                            states=STATES)
    ldva = fields.Selection(snellen_chart,
                            'LDVA',
                            help="Left Eye Vision of Patient without aid",
                            sort=False,
                            states=STATES)
    # vision test using pinhole accurate manual testing
    rdva_pinhole = fields.Selection(snellen_chart,
                                    'RDVA',
                                    help="Right Eye Vision Using Pin Hole",
                                    sort=False,
                                    states=STATES)
    ldva_pinhole = fields.Selection(snellen_chart,
                                    'LDVA',
                                    help="Left Eye Vision Using Pin Hole",
                                    sort=False,
                                    states=STATES)
    # vison testing with glasses just to assess what the patient sees with
    # his existing aid # useful esp with vision syndromes that are not
    # happening because of the lens
    rdva_aid = fields.Selection(snellen_chart,
                                'RDVA AID',
                                help="Vision with glasses or contact lens",
                                sort=False,
                                states=STATES)
    ldva_aid = fields.Selection(snellen_chart,
                                'LDVA AID',
                                help="Vision with glasses or contact lens",
                                sort=False,
                                states=STATES)

    # spherical
    rspherical = fields.Float('SPH', help='Right Eye Spherical', states=STATES)
    lspherical = fields.Float('SPH', help='Left Eye Spherical', states=STATES)

    # cylinder
    rcylinder = fields.Float('CYL', help='Right Eye Cylinder', states=STATES)
    lcylinder = fields.Float('CYL', help='Left Eye Cylinder', states=STATES)

    #axis
    raxis = fields.Float('Axis', help='Right Eye Axis', states=STATES)
    laxis = fields.Float('Axis', help='Left Eye Axis', states=STATES)

    # near vision testing .... you will get it when u cross 40 :)
    # its also thinning of the lens.. the focus falls behind the retina
    # in case of distant vision the focus does not reach retina

    rnv_add = fields.Float('NV Add',
                           help='Right Eye Best Corrected NV Add',
                           states=STATES)
    lnv_add = fields.Float('NV Add',
                           help='Left Eye Best Corrected NV Add',
                           states=STATES)

    rnv = fields.Selection(near_vision_chart,
                           'RNV',
                           help="Right Eye Near Vision",
                           sort=False,
                           states=STATES)
    lnv = fields.Selection(near_vision_chart,
                           'LNV',
                           help="Left Eye Near Vision",
                           sort=False,
                           states=STATES)

    # after the above tests the optometrist or doctor comes to a best conclusion
    # best corrected visual acuity
    # the above values are from autorefraction
    # the doctors decision is final
    # and there could be changes in values of cylinder, spherical and axis
    # these values will go into final prescription of glasses or contact lens
    # by default these values should be auto populated
    # and should be modifiable by an ophthalmologist
    rbcva_spherical = fields.Float('SPH',
                                   help='Right Eye Best Corrected Spherical',
                                   states=STATES)
    lbcva_spherical = fields.Float('SPH',
                                   help='Left Eye Best Corrected Spherical',
                                   states=STATES)

    rbcva_cylinder = fields.Float('CYL',
                                  help='Right Eye Best Corrected Cylinder',
                                  states=STATES)
    lbcva_cylinder = fields.Float('CYL',
                                  help='Left Eye Best Corrected Cylinder',
                                  states=STATES)

    rbcva_axis = fields.Float('Axis',
                              help='Right Eye Best Corrected Axis',
                              states=STATES)
    lbcva_axis = fields.Float('Axis',
                              help='Left Eye Best Corrected Axis',
                              states=STATES)

    rbcva = fields.Selection(snellen_chart,
                             'RBCVA',
                             help="Right Eye Best Corrected VA",
                             sort=False,
                             states=STATES)
    lbcva = fields.Selection(snellen_chart,
                             'LBCVA',
                             help="Left Eye Best Corrected VA",
                             sort=False,
                             states=STATES)

    rbcva_nv_add = fields.Float('BCVA - Add',
                                help='Right Eye Best Corrected NV Add',
                                states=STATES)
    lbcva_nv_add = fields.Float('BCVA - Add',
                                help='Left Eye Best Corrected NV Add',
                                states=STATES)

    rbcva_nv = fields.Selection(near_vision_chart,
                                'RBCVANV',
                                help="Right Eye Best Corrected Near Vision",
                                sort=False,
                                states=STATES)
    lbcva_nv = fields.Selection(near_vision_chart,
                                'LBCVANV',
                                help="Left Eye Best Corrected Near Vision",
                                sort=False,
                                states=STATES)

    #some other tests of the eyes
    #useful for diagnosis of glaucoma a disease that builds up
    #pressure inside the eye and destroy the retina
    #its also called the silent vision stealer
    #intra ocular pressure
    #there are three ways to test iop
    #   SCHIOTZ
    #   NONCONTACT TONOMETRY
    #   GOLDMANN APPLANATION TONOMETRY

    #notes by the ophthalmologist or optometrist
    notes = fields.Text('Notes', states=STATES)

    #Intraocular Pressure
    iop_method = fields.Selection(
        [
            (None, ''),
            ('nct', 'Non-contact tonometry'),
            ('schiotz', 'Schiotz tonometry'),
            ('goldmann', 'Goldman tonometry'),
        ],
        'Method',
        help='Tonometry / Intraocular pressure reading method',
        states=STATES)

    riop = fields.Float('RIOP',
                        digits=(2, 1),
                        help="Right Intraocular Pressure in mmHg",
                        states=STATES)

    liop = fields.Float('LIOP',
                        digits=(2, 1),
                        help="Left Intraocular Pressure in mmHg",
                        states=STATES)

    findings = fields.One2Many('gnuhealth.ophthalmology.findings',
                               'name',
                               'Findings',
                               states=STATES)

    state = fields.Selection([
        (None, ''),
        ('in_progress', 'In progress'),
        ('done', 'Done'),
    ],
                             'State',
                             readonly=True,
                             sort=False)

    signed_by = fields.Many2One(
        'gnuhealth.healthprofessional',
        'Signed by',
        readonly=True,
        states={'invisible': Equal(Eval('state'), 'in_progress')},
        help="Health Professional that finished the patient evaluation")

    def patient_age_at_evaluation(self, name):
        if (self.patient.name.dob and self.visit_date):
            rdelta = relativedelta(self.visit_date.date(),
                                   self.patient.name.dob)
            years_months_days = str(rdelta.years) + 'y ' \
                + str(rdelta.months) + 'm ' \
                + str(rdelta.days) + 'd'
            return years_months_days
        else:
            return None

    def get_patient_gender(self, name):
        return self.patient.gender

    @classmethod
    def search_patient_gender(cls, name, clause):
        res = []
        value = clause[2]
        res.append(('patient.name.gender', clause[1], value))
        return res

    @fields.depends('rdva')
    def on_change_with_rbcva(self):
        return self.rdva

    @fields.depends('ldva')
    def on_change_with_lbcva(self):
        return self.ldva

    @fields.depends('rcylinder')
    def on_change_with_rbcva_cylinder(self):
        return self.rcylinder

    @fields.depends('lcylinder')
    def on_change_with_lbcva_cylinder(self):
        return self.lcylinder

    @fields.depends('raxis')
    def on_change_with_rbcva_axis(self):
        return self.raxis

    @fields.depends('laxis')
    def on_change_with_lbcva_axis(self):
        return self.laxis

    @fields.depends('rspherical')
    def on_change_with_rbcva_spherical(self):
        return self.rspherical

    @fields.depends('lspherical')
    def on_change_with_lbcva_spherical(self):
        return self.lspherical

    @fields.depends('rnv_add')
    def on_change_with_rbcva_nv_add(self):
        return self.rnv_add

    @fields.depends('lnv_add')
    def on_change_with_lbcva_nv_add(self):
        return self.lnv_add

    @fields.depends('rnv')
    def on_change_with_rbcva_nv(self):
        return self.rnv

    @fields.depends('lnv')
    def on_change_with_lbcva_nv(self):
        return self.lnv

    @staticmethod
    def default_visit_date():
        return datetime.now()

    @staticmethod
    def default_state():
        return 'in_progress'

    @staticmethod
    def default_health_professional():
        pool = Pool()
        HealthProf = pool.get('gnuhealth.healthprofessional')
        health_professional = HealthProf.get_health_professional()
        return health_professional

    # Show the gender and age upon entering the patient
    # These two are function fields (don't exist at DB level)
    @fields.depends('patient')
    def on_change_patient(self):
        gender = None
        age = ''
        self.gender = self.patient.gender
        self.computed_age = self.patient.age

    @classmethod
    @ModelView.button
    def end_evaluation(cls, evaluations):

        evaluation_id = evaluations[0]

        # Change the state of the evaluation to "Done"
        HealthProf = Pool().get('gnuhealth.healthprofessional')

        signing_hp = HealthProf.get_health_professional()

        cls.write(evaluations, {
            'state': 'done',
            'signed_by': signing_hp,
        })

    @classmethod
    def __setup__(cls):
        super(OphthalmologyEvaluation, cls).__setup__()

        cls._buttons.update(
            {'end_evaluation': {
                'invisible': Equal(Eval('state'), 'done')
            }})
예제 #22
0
class ShipmentOut(metaclass=PoolMeta):
    __name__ = 'stock.shipment.out'
    systemlogics_modula = fields.Boolean('SystemLogics Modula')
    systemlogics_modula_completed = fields.Boolean(
        'SystemLogics Modula Completed')
    systemlogics_modula_sended = fields.Boolean('SystemLogics Modula Sended')
    ship_create_date = fields.Function(fields.DateTime('Create Date'),
                                       'get_ship_create_date')

    @staticmethod
    def default_systemlogics_modula():
        return False

    @staticmethod
    def default_systemlogics_modula_completed():
        return False

    @staticmethod
    def default_systemlogics_modula_sended():
        return False

    def get_ship_create_date(self, name):
        return self.create_date

    @classmethod
    def copy(cls, shipments, default=None):
        if default is None:
            default = {}
        default = default.copy()
        default['systemlogics_modula'] = False
        default['systemlogics_modula_completed'] = False
        default['systemlogics_modula_sended'] = False
        return super(ShipmentOut, cls).copy(shipments, default=default)

    @classmethod
    def generate_systemlogics_modula_file(cls, shipments):
        SystemLogicsModula = Pool().get('systemlogics.modula')

        # Force not get a rollback to generate XML file
        shipment_ids = [s.id for s in shipments]
        Transaction().commit()

        # Search shipment ID to sure not have a rollback
        shipments = cls.search([
            ('id', 'in', shipment_ids),
        ],
                               order=[('systemlogics_modula_completed', 'DESC')
                                      ])
        SystemLogicsModula.imp_ordini(shipments,
                                      template='IMP_ORDINI_OUT',
                                      type_='P')

    @classmethod
    def check_systemlogics_modula(cls, shipments):
        pool = Pool()
        Configuration = pool.get('stock.configuration')

        config = Configuration(1)
        if not (Transaction().context.get(
                'generate_systemlogics_modula',
                config.try_generate_systemlogics_modula)):
            return

        to_write = []
        values = {'systemlogics_modula': True}
        for shipment in shipments:
            if hasattr(shipment, 'review'):
                if shipment.review:
                    continue
            systemLogics = False
            completed = True
            for move in shipment.inventory_moves:
                if move.from_location.systemlogics_modula:
                    systemLogics = True
                else:
                    completed = False
            if systemLogics:
                values = values.copy()
                if completed:
                    values['systemlogics_modula_completed'] = True
                else:
                    values['systemlogics_modula_completed'] = False
                to_write.extend(([shipment], values))
        if to_write:
            cls.write(*to_write)

    @classmethod
    def generate_systemlogics_modula(cls, shipments):
        '''Generate SystemLogics Modula'''
        Configuration = Pool().get('stock.configuration')

        config = Configuration(1)
        if not (Transaction().context.get(
                'generate_systemlogics_modula',
                config.try_generate_systemlogics_modula)):
            return

        to_write = []
        shipments_modula = []
        value = {'systemlogics_modula_sended': True}
        for shipment in shipments:
            if hasattr(shipment, 'review'):
                if shipment.review:
                    continue
                shipments_modula.append(shipment)
                to_write.extend(([shipment], value))

        if shipments_modula:
            cls.write(*to_write)
            cls.generate_systemlogics_modula_file(shipments_modula)

    @classmethod
    def assign(cls, shipments):
        super(ShipmentOut, cls).assign(shipments)
        assigned = [s for s in shipments if s.state == 'assigned']
        cls.check_systemlogics_modula(assigned)
        cls.generate_systemlogics_modula(assigned)

    @classmethod
    def check_systemlogics_modula_scheduler(cls, args=None):
        '''
        This method is intended to be called from ir.cron
        args: warehouse ids [ids]
        '''
        pool = Pool()
        Configuration = pool.get('stock.configuration')
        config = Configuration(1)

        domain = [
            ('state', '=', 'assigned'),
            ('systemlogics_modula', '=', False),
        ]
        if args:
            domain.append(('warehouse', 'in', args), )
        shipments = cls.search(domain)

        len_ships = len(shipments)
        logger.info('Scheduler Try Check Systemlogics Modula. Total: %s' %
                    (len_ships))
        if len_ships:
            blocs = 1
            slice_systemlogics_modula = (config.slice_systemlogics_modula
                                         or len_ships)
            with Transaction().set_context(generate_systemlogics_modula=True):
                for sub_shipments in grouped_slice(shipments,
                                                   slice_systemlogics_modula):
                    logger.info('Start bloc %s of %s.' %
                                (blocs, len_ships / slice_systemlogics_modula))
                    cls.check_systemlogics_modula(list(sub_shipments))
                    logger.info('End bloc %s.' % blocs)
                    blocs += 1
        logger.info('End Scheduler Try Check Systemlogics Modula.')

    @classmethod
    def generate_systemlogics_modula_scheduler(cls, args=None):
        '''
        This method is intended to be called from ir.cron
        args: warehouse ids [ids]
        '''
        pool = Pool()
        Configuration = pool.get('stock.configuration')
        config = Configuration(1)

        domain = [
            ('state', '=', 'assigned'),
            ('systemlogics_modula', '=', True),
            ('systemlogics_modula_sended', '=', False),
        ]
        if args:
            domain.append(('warehouse', 'in', args), )
        shipments = cls.search(domain)

        len_ships = len(shipments)
        logger.info('Scheduler Try generate Systemlogics Modula. Total: %s' %
                    (len_ships))
        if len_ships:
            blocs = 1
            slice_systemlogics_modula = (config.slice_systemlogics_modula
                                         or len_ships)
            with Transaction().set_context(generate_systemlogics_modula=True):
                for sub_shipments in grouped_slice(shipments,
                                                   slice_systemlogics_modula):
                    logger.info('Start bloc %s of %s.' %
                                (blocs, len_ships / slice_systemlogics_modula))
                    cls.generate_systemlogics_modula(list(sub_shipments))
                    logger.info('End bloc %s.' % blocs)
                    blocs += 1
        logger.info('End Scheduler Try generate Systemlogics Modula.')
예제 #23
0
class Address(metaclass=PoolMeta):
    __name__ = 'party.address'

    building_address = fields.Function(fields.Char("Building Address"),
                                       'get_building_address')

    last_visit_time = fields.Function(fields.DateTime("Last Visit Time"),
                                      'get_last_visit',
                                      searcher='search_last_visit')
    last_visit_type = fields.Function(fields.Many2One('sale.direct.visit.type',
                                                      "Last Visit Type"),
                                      'get_last_visit',
                                      searcher='search_last_visit')
    last_visit_notes = fields.Function(fields.Text("Last Visit Notes"),
                                       'get_last_visit',
                                       searcher='search_last_visit')

    revisit_required = fields.Function(fields.Boolean("Revisit Required"),
                                       'get_last_visit',
                                       searcher='search_last_visit')
    revisit_today = fields.Function(fields.Boolean("Revisit Today"),
                                    'get_last_visit',
                                    searcher='search_last_visit')
    revisit_due = fields.Function(fields.DateTime("Revisit Due"),
                                  'get_last_visit',
                                  setter='set_revisit_due',
                                  searcher='search_last_visit')

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls._buttons.update({
            'visit': {},
            'register_order': {},
        })
        cls.party.required = False
        cls.party.states['readonly'] &= Eval('party')

    def get_building_address(self, name):
        if self.street:
            street, *locality = self.street.splitlines()
            if locality:
                locality = locality[0]
        else:
            street = locality = None
        if self.country:
            country = self.country.code
        else:
            country = None
        result = ', '.join(
            filter(None, [
                self.name, street, locality, self.postal_code, self.city,
                country
            ]))
        if not result:
            result = self.party.rec_name
        return result

    @classmethod
    def order_building_address(cls, tables):
        address, _ = tables[None]
        return [
            address.country,
            address.subdivision,
            address.city,
            address.street,
            address.name,
            address.party,
        ]

    @classmethod
    def get_last_visit(cls, addresses, names):
        address = cls.__table__()
        cursor = Transaction().connection.cursor()

        last_visit = cls.last_visit_query()
        columns = [address.id]
        for name in names:
            columns.append(getattr(last_visit, name))

        result = defaultdict(dict)
        for sub_ids in grouped_slice(addresses):
            red_sql = reduce_ids(address.id, sub_ids)
            cursor.execute(*address.join(
                last_visit, 'LEFT', condition=address.id ==
                last_visit.address).select(*columns, where=red_sql))
            for row in cursor.fetchall():
                address_id = row[0]
                for count, name in enumerate(names, 1):
                    result[name][address_id] = row[count]

        return result

    @classmethod
    def search_last_visit(cls, name, clause):
        _, operator, value = clause
        Operator = fields.SQL_OPERATORS[operator]
        last_visit = cls.last_visit_query()
        query = last_visit.select(last_visit.address,
                                  where=Operator(getattr(last_visit, name),
                                                 value))
        return [('id', 'in', query)]

    @classmethod
    def set_revisit_due(cls, addresses, name, value):
        pool = Pool()
        Visit = pool.get('sale.direct.visit')

        to_save = []
        visits = cls.get_last_visit(addresses, ['id'])
        for visit_id in visits['id'].values():
            visit = Visit(visit_id)
            visit.revisit_time = value
            to_save.append(visit)

        if to_save:
            Visit.save(to_save)

    @classmethod
    def order(cls, tables, name):
        address, _ = tables[None]
        key = 'last_visit'
        if key not in tables:
            last_visit = cls.last_visit_query()
            query = address.join(last_visit,
                                 'LEFT',
                                 condition=address.id == last_visit.address)
            tables[key] = {
                None: (query.right, query.condition),
            }
        else:
            last_visit, _ = tables[key][None]
        return [getattr(last_visit, name)]

    @classmethod
    def order_last_visit_time(cls, tables):
        return cls.order(tables, 'last_visit_time')

    @classmethod
    def order_revisit_due(cls, tables):
        return cls.order(tables, 'revisit_due')

    @classmethod
    def get_visit_address(cls, address):
        existing_address = cls.search_visit_address(address)
        if existing_address:
            return existing_address

        new_address = cls(
            name=address.name,
            street=address.street,
            city=address.city,
            country=address.country,
            subdivision=address.subdivision,
        )
        new_address.save()
        return new_address

    @classmethod
    def search_visit_address(cls, address):
        domain = []
        for name in {'name', 'street', 'city', 'subdivision', 'country'}:
            value = getattr(address, name, None)
            if hasattr(value, 'id'):
                domain.append((name, '=', getattr(value, 'id')))
            else:
                domain.append((name, '=', value))

        addresses = cls.search(domain, limit=1)
        if addresses:
            return addresses[0]

    @classmethod
    def last_visit_query(cls):
        pool = Pool()
        Visit = pool.get('sale.direct.visit')

        tomorrow = Literal(
            datetime.combine(date.today() + timedelta(days=1),
                             datetime.min.time()))

        visit = Visit.__table__()
        last_visit = visit.select(
            visit.address.as_('address'),
            Max(visit.time).as_('time'),
            group_by=[visit.address],
        )

        visit = Visit.__table__()
        revisit_required = (visit.revisit_time != Null)
        revisit_today = (visit.revisit_time < tomorrow)
        return visit.join(
            last_visit,
            condition=((visit.address == last_visit.address)
                       & (visit.time == last_visit.time))).select(
                           visit.id.as_('id'),
                           visit.address.as_('address'),
                           visit.time.as_('last_visit_time'),
                           visit.type.as_('last_visit_type'),
                           visit.notes.as_('last_visit_notes'),
                           revisit_required.as_('revisit_required'),
                           revisit_today.as_('revisit_today'),
                           visit.revisit_time.as_('revisit_due'),
                       )

    @classmethod
    def write(cls, *args):
        pool = Pool()
        Party = pool.get('party.party')

        # Skip error when setting the address party
        actions = iter(args)
        for addresses, values in zip(actions, actions):
            for address in addresses:
                if 'party' in values and address.party is None:
                    address.party = Party(values['party'])

        super(Address, cls).write(*args)

    @classmethod
    @ModelView.button_action('sale_direct.perform_visit_wizard')
    def visit(cls, addresses):
        pass

    @classmethod
    @ModelView.button_action('sale_direct.register_order_wizard')
    def register_order(cls, addresses):
        pass
예제 #24
0
class BaseComponent(ModelSQL, ModelView):
    '''All components should inherit from this class. It's not a real
    model as it is not registered in the pool. It defines the fields
    needed for a model to be a valid component. '''
    active = fields.Boolean('Active', select=True)
    encounter = fields.Many2One('gnuhealth.encounter',
                                'Encounter',
                                readonly=True,
                                required=True)
    start_time = fields.DateTime('Start', required=True, states=SIGNED_STATES)
    end_time = fields.DateTime('Finish', states=SIGNED_STATES)
    sign_time = fields.DateTime('Signed', readonly=True, states=SIGNED_VISIBLE)
    signed_by = fields.Many2One('gnuhealth.healthprofessional',
                                'Signed by',
                                readonly=True,
                                states=SIGNED_VISIBLE)
    performed_by = fields.Many2One('gnuhealth.healthprofessional',
                                   'Clinician',
                                   states=SIGNED_STATES)
    warning = fields.Boolean(
        'Warning',
        help="Check this box to alert the supervisor about this session."
        " It will be shown in red in the encounter",
        states=SIGNED_STATES)
    notes = fields.Text('Notes', states=SIGNED_STATES)
    critical_info = fields.Char('Summary', readonly=True, depends=['notes'])
    report_info = fields.Function(fields.Text('Report'), 'get_report_info')
    is_union_comp = fields.Function(fields.Boolean('Unified component'),
                                    'get_is_union')
    byline = fields.Function(
        fields.Char('Byline', help='date started, clinician and signed by'),
        'get_byline')

    @classmethod
    def __setup__(cls):
        super(BaseComponent, cls).__setup__()
        cls._order = [('start_time', 'ASC')]
        cls._order_name = 'start_time'
        cls.critical_info.depends = cls.get_critical_info_fields()
        cls._error_messages = {
            'bad_start_time': 'Component cannot start before the encounter',
            'bad_end_time': 'End time cannot be before start time'
        }

    @staticmethod
    def default_performed_by():
        HealthProfessional = Pool().get('gnuhealth.healthprofessional')
        return HealthProfessional.get_health_professional()

    @staticmethod
    def default_active():
        return True

    @classmethod
    def get_critical_info_fields(cls):
        '''
        return the list of field names that are used to calculate
        the critical_info summary field
        '''
        return ['notes']

    def make_critical_info(self):
        # return a single line, no more than 140 chars to describe the details
        # of what's happening in the measurements in this component
        return ""

    def get_report_info(self, name):
        # return details of the data contained in this component as plain text
        # no length limit
        return ""

    def get_is_union(self, name):
        return False

    @classmethod
    def pre_sign(cls, components):
        '''sets the healthprof and the sign_time for the current instance'''
        health_prof_model = Pool().get('gnuhealth.healthprofessional')
        signtime = datetime.now()
        for comp in components:
            comp.signed_by = health_prof_model.get_health_professional()
            comp.sign_time = signtime

    def pre_save(self):
        self.critical_info = self.make_critical_info()

    def on_change_with_critical_info(self, *arg, **kwarg):
        return self.make_critical_info()

    @staticmethod
    def default_start_time():
        return datetime.now()

    @classmethod
    def get_byline(cls, instances, name):
        def mk_byline(obj):
            dt = obj.start_time.strftime('%Y-%m-%d %H:%M')
            if obj.performed_by:
                nom = obj.performed_by.name.name
            else:
                nom = "-Unspecified-"
            if obj.signed_by and obj.signed_by != obj.performed_by:
                nom = u'%s (signed by %s)' % (nom, obj.signed_by.name.name)
            return u'on %s by %s' % (dt, nom)

        return dict([(i.id, mk_byline(i)) for i in instances])

    @classmethod
    @ModelView.button
    def mark_done(cls, components):
        pass
        # save the component and set the state to done

    @classmethod
    def validate(cls, records):
        for rec in records:
            # start time can't be before encounter start time
            if rec.start_time < rec.encounter.start_time:
                cls.raise_user_error('bad_start_time')
            if rec.end_time and rec.end_time < rec.start_time:
                cls.raise_user_error('bad_end_time')
예제 #25
0
class Entry(metaclass=PoolMeta):
    __name__ = 'lims.entry'

    last_release_date = fields.Function(fields.DateTime('Last Release date'),
                                        'get_last_release_date')
    qty_lines_pending_invoicing = fields.Function(
        fields.Integer('Lines pending invoicing'),
        'get_qty_lines_pending_invoicing')

    @classmethod
    def get_last_release_date(cls, entries, name):
        cursor = Transaction().connection.cursor()
        pool = Pool()
        ResultsVersion = pool.get('lims.results_report.version')
        ResultsDetail = pool.get('lims.results_report.version.detail')
        NotebookLine = pool.get('lims.notebook.line')
        Notebook = pool.get('lims.notebook')
        Fraction = pool.get('lims.fraction')
        Sample = pool.get('lims.sample')

        result = {}
        for e in entries:
            cursor.execute(
                'SELECT MAX(rd.release_date) '
                'FROM "' + ResultsVersion._table + '" rv '
                'INNER JOIN "' + ResultsDetail._table + '" rd '
                'ON rv.id = rd.report_version '
                'INNER JOIN "' + NotebookLine._table + '" nl '
                'ON nl.results_report = rv.results_report '
                'INNER JOIN "' + Notebook._table + '" n '
                'ON n.id = nl.notebook '
                'INNER JOIN "' + Fraction._table + '" f '
                'ON f.id = n.fraction '
                'INNER JOIN "' + Sample._table + '" s '
                'ON s.id = f.sample '
                'WHERE s.entry = %s '
                'AND rd.state = \'released\' '
                'AND rd.type != \'preliminary\'', (str(e.id), ))
            result[e.id] = cursor.fetchone()[0]

        return result

    @classmethod
    def get_qty_lines_pending_invoicing(cls, entries, name):
        cursor = Transaction().connection.cursor()
        pool = Pool()
        Sample = pool.get('lims.sample')
        Fraction = pool.get('lims.fraction')
        Service = pool.get('lims.service')
        InvoiceLine = pool.get('account.invoice.line')

        result = {}
        for e in entries:
            result[e.id] = 0

            cursor.execute(
                'SELECT srv.id '
                'FROM "' + Service._table + '" srv '
                'INNER JOIN "' + Fraction._table + '" f '
                'ON f.id = srv.fraction '
                'INNER JOIN "' + Sample._table + '" s '
                'ON s.id = f.sample '
                'WHERE s.entry = %s', (str(e.id), ))
            services_ids = [x[0] for x in cursor.fetchall()]
            if not services_ids:
                continue

            origins = '\', \''.join(
                ['lims.service,' + str(s) for s in services_ids])
            cursor.execute('SELECT COUNT(*) '
                           'FROM "' + InvoiceLine._table + '" '
                           'WHERE origin IN (\'' + origins + '\') '
                           'AND invoice IS NULL')
            result[e.id] = cursor.fetchone()[0]

        return result

    @classmethod
    def on_hold(cls, entries):
        super().on_hold(entries)
        cls.create_invoice_lines(entries)

    @classmethod
    def create_invoice_lines(cls, entries):
        Service = Pool().get('lims.service')

        with Transaction().set_context(_check_access=False):
            services = Service.search([
                ('entry', 'in', [e.id for e in entries]),
                ('annulled', '=', False),
            ])
        for service in services:
            service.create_invoice_line()

    @classmethod
    def view_toolbar_get(cls):
        if not Transaction().context.get('ready_for_invoicing', False):
            return super().view_toolbar_get()

        # Entries Ready for Invoicing uses specific keywords
        prints = cls.get_entries_ready_for_invoicing_keyword('form_print')
        actions = cls.get_entries_ready_for_invoicing_keyword('form_action')
        relates = cls.get_entries_ready_for_invoicing_keyword('form_relate')
        result = {
            'print': prints,
            'action': actions,
            'relate': relates,
            'exports': [],
        }
        return result

    @classmethod
    def get_entries_ready_for_invoicing_keyword(cls, keyword):
        """
        Method copied from ActionKeyword. It search for specific keywords
        for Entries Ready for Invoicing: lims.entry,-2
        """
        pool = Pool()
        ActionKeyword = pool.get('ir.action.keyword')
        Action = pool.get('ir.action')

        key = (keyword, ('lims.entry', -2))
        keywords = ActionKeyword._get_keyword_cache.get(key)
        if keywords is not None:
            return keywords

        clause = [
            ('keyword', '=', keyword),
            ('model', '=', 'lims.entry,-2'),
            ('action.active', '=', True),
        ]
        action_keywords = ActionKeyword.search(clause, order=[])
        types = defaultdict(list)
        for action_keyword in action_keywords:
            type_ = action_keyword.action.type
            types[type_].append(action_keyword.action.id)
        keywords = []
        for type_, action_ids in types.items():
            for value in Action.get_action_values(type_, action_ids):
                value['keyword'] = keyword
                keywords.append(value)
        keywords.sort(key=operator.itemgetter('name'))
        ActionKeyword._get_keyword_cache.set(key, keywords)
        return keywords
예제 #26
0
class PatientReferral(ModelSQL, ModelView):
    'Referral'
    __name__ = 'gnuhealth.patient.referral'
    name = fields.Many2One('gnuhealth.patient',
                           'Patient',
                           required=True,
                           states={
                               'readonly':
                               Or(Bool(Eval('from_triage')),
                                  Eval('signed_local', False),
                                  Bool(Eval('from_encounter')))
                           })
    sex = fields.Function(fields.Selection(SEX_OPTIONS, 'Sex'),
                          'get_patient_data',
                          searcher='search_patient_data')
    sex_display = fields.Function(fields.Char('Sex'), 'get_patient_data')
    puid = fields.Function(fields.Char('UPI'),
                           'get_patient_data',
                           searcher='search_patient_data')
    age = fields.Function(fields.Char('Current Age'), 'get_patient_data')
    dob = fields.Function(fields.Date('Date of Birth'),
                          'get_patient_data',
                          searcher='search_patient_data')

    referral_date = fields.DateTime('Date/Time',
                                    required=True,
                                    states=RO_THERE)
    referred_by = fields.Many2One('gnuhealth.healthprofessional',
                                  'Referred by',
                                  states=RO_THERE)
    reason = fields.Text('Reason for referral', states=RO_THERE)
    results = fields.Text('Consultant Notes/Findings', states=RO_HERE)
    from_institution = fields.Many2One('gnuhealth.institution',
                                       'Referred From',
                                       required=True,
                                       states=RO_THERE)
    to_institution = fields.Many2One('gnuhealth.institution',
                                     'Refer To',
                                     required=True,
                                     states=RO_THERE)
    to_specialty = fields.Many2One('gnuhealth.specialty',
                                   'Specialty',
                                   states=RO_THERE)
    referral_type = fields.Selection(plus_none(REFERRAL_TYPES),
                                     'Type',
                                     sort=False,
                                     states=RO_THERE)
    service_requested = fields.Selection(plus_none(REFERRAL_SERVICE),
                                         'Treatment Required',
                                         sort=False,
                                         states=RO_THERE)
    from_triage = fields.Many2One('gnuhealth.triage.entry',
                                  'Triage Entry',
                                  states=RO_THERE)
    from_encounter = fields.Many2One('gnuhealth.encounter',
                                     'Encounter',
                                     states=RO_THERE,
                                     domain=[('patient', '=', Eval('name'))])
    to_appointment = fields.Many2One('gnuhealth.appointment',
                                     'Appointment',
                                     domain=[('institution', '=',
                                              Eval('to_institution'))],
                                     states=RO_HERE)
    is_local = fields.Function(fields.Boolean('Originated here'),
                               'get_is_local',
                               searcher='search_target_local')
    is_target = fields.Function(fields.Boolean('Referred here'),
                                'get_is_target',
                                searcher='search_target_local')
    referer = fields.Many2One('gnuhealth.healthprofessional',
                              'Signed By',
                              states={
                                  'readonly': True,
                                  'invisible': ~Bool(Eval('referer_sign_date'))
                              })
    referer_sign_date = fields.DateTime('Sign date',
                                        states={
                                            'readonly': True,
                                            'invisible': ~Bool(Eval('referer'))
                                        })
    signed_local = fields.Function(fields.Boolean('Referer Signed'),
                                   'get_signed',
                                   searcher='search_signed')
    referee = fields.Many2One('gnuhealth.healthprofessional',
                              'Referee',
                              states={
                                  'readonly': True,
                                  'invisible': ~Bool(Eval('referee_sign_date'))
                              })
    referee_sign_date = fields.DateTime('Referee Sign Date',
                                        states={
                                            'readonly': True,
                                            'invisible': ~Bool(Eval('referee'))
                                        })
    signed_target = fields.Function(fields.Boolean('Referee Signed'),
                                    'get_signed',
                                    searcher='search_signed')

    @classmethod
    def __setup__(cls):
        super(PatientReferral, cls).__setup__()
        cls._error_messages.update({
            'health_professional_warning':
            'No health professional '
            'associated with this user'
        })
        cls._buttons.update({
            'btn_sign_local': {
                'invisible': Eval('signed_local', False),
                'readonly': ~Bool(Eval('name', False))
            },
            'btn_sign_target': {
                'invisible':
                Or(Eval('signed_target', False), ~Eval('signed_local', False),
                   ~Eval('is_target', False))
            }
        })

    def get_patient_data(self, name):
        return getattr(self.name, name)

    @classmethod
    def search_patient_data(*arg, **kwarg):
        pass

    @staticmethod
    def default_referral_date():
        return datetime.now()

    @staticmethod
    def default_referred_by():
        HP = Pool().get('gnuhealth.healthprofessional')
        hp = HP.get_health_professional()
        return hp

    @staticmethod
    def default_from_institution():
        HI = Pool().get('gnuhealth.institution')
        hi = HI.get_institution()
        return hi

    @staticmethod
    def default_is_local():
        return True
        # always local when new

    @classmethod
    def get_is_local(cls, instances, name):
        HI = Pool().get('gnuhealth.institution')
        hi = HI.get_institution()
        local_list = [(i.id, int(i.from_institution) == hi) for i in instances]
        return dict(local_list)

    @classmethod
    def get_is_target(cls, instances, name):
        HI = Pool().get('gnuhealth.institution')
        hi = HI.get_institution()
        target_list = [(i.id, int(i.to_institution) == hi) for i in instances]
        return dict(target_list)

    @classmethod
    def search_target_local(cls, name, clause):
        fld, operator, operand = clause
        HI = Pool().get('gnuhealth.institution')
        hi = HI.get_institution()
        field_name = {
            'is_local': 'from_institution',
            'is_target': 'to_institution'
        }[name]
        find_made_here = False
        if operand is True:
            if operator in ('=', 'in', 'is', '<=', '>=', 'like', 'ilike'):
                find_made_here = True
            else:
                find_made_here = False
        else:
            if operator in ('!=', 'not in', 'not like'):
                find_made_here = True
            else:
                find_made_here = False
        if find_made_here:
            return [(field_name, '=', hi)]
        else:
            return [(field_name, '!=', hi)]

    @classmethod
    def do_sign(cls, referrals, sign_local=True):
        HP = Pool().get('gnuhealth.healthprofessional')
        signing_hp = HP.get_health_professional()
        if not signing_hp:
            cls.raise_user_error('health_professional_warning')
        local_sign = []
        target_sign = []
        now = datetime.now()
        for referral in referrals:
            if sign_local:
                local_sign.append(referral)
            else:
                target_sign.append(referral)
        if local_sign:
            local_write = {'referer': signing_hp, 'referer_sign_date': now}
            cls.write(local_sign, local_write)
        if target_sign:
            target_write = {'referee': signing_hp, 'referee_sign_date': now}
            cls.write(target_sign, target_write)

    @classmethod
    @ModelView.button
    def btn_sign_local(cls, referrals):
        cls.do_sign(referrals, True)

    @classmethod
    @ModelView.button
    def btn_sign_target(cls, referrals):
        cls.do_sign(referrals, False)

    @classmethod
    def get_signed(cls, instances, name):
        if name == 'signed_local':
            field_name = 'referer_sign_date'
        else:
            field_name = 'referee_sign_date'
        outlist = [(int(i), getattr(i, field_name) is not None)
                   for i in instances]
        return dict(outlist)

    @classmethod
    def search_signed(cls, name, clause):
        fld, operator, operand = clause
        operdict = {'=': '!=', '!=': '='}
        if name == 'signed_local':
            field_name = 'referer_sign_date'
        else:
            field_name = 'referee_sign_date'
        if operator in operdict:
            if operand is True:
                return [(field_name, operdict[operator], None)]
            else:
                return [(field_name, operator, None)]

    @staticmethod
    def default_signed_local():
        return False

    @staticmethod
    def default_signed_target():
        return False
예제 #27
0
파일: email_.py 프로젝트: tryton/trytond
class Email(ResourceAccessMixin, ModelSQL, ModelView):
    "Email"
    __name__ = 'ir.email'

    user = fields.Function(fields.Char("User"), 'get_user')
    at = fields.Function(fields.DateTime("At"), 'get_at')
    recipients = fields.Char("Recipients", readonly=True)
    recipients_secondary = fields.Char("Secondary Recipients", readonly=True)
    recipients_hidden = fields.Char("Hidden Recipients", readonly=True)
    addresses = fields.One2Many('ir.email.address',
                                'email',
                                "Addresses",
                                readonly=True)
    subject = fields.Char("Subject", readonly=True)
    body = fields.Text("Body", readonly=True)

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls._order.insert(0, ('create_date', 'DESC'))
        cls.__rpc__.update({
            'send': RPC(readonly=False, result=int),
            'complete': RPC(check_access=False),
        })
        del cls.__rpc__['create']

    def get_user(self, name):
        return self.create_uid.rec_name

    def get_at(self, name):
        return self.create_date.replace(microsecond=0)

    @classmethod
    def send(cls,
             to='',
             cc='',
             bcc='',
             subject='',
             body='',
             files=None,
             record=None,
             reports=None,
             attachments=None):
        pool = Pool()
        User = pool.get('res.user')
        ActionReport = pool.get('ir.action.report')
        Attachment = pool.get('ir.attachment')
        transaction = Transaction()
        user = User(transaction.user)

        Model = pool.get(record[0])
        record = Model(record[1])

        body_html = HTML_EMAIL % {
            'subject': subject,
            'body': body,
            'signature': user.signature or '',
        }
        content = MIMEMultipart('alternative')
        if html2text:
            body_text = HTML_EMAIL % {
                'subject': subject,
                'body': body,
                'signature': '',
            }
            converter = html2text.HTML2Text()
            body_text = converter.handle(body_text)
            if user.signature:
                body_text += '\n-- \n' + converter.handle(user.signature)
            part = MIMEText(body_text, 'plain', _charset='utf-8')
            content.attach(part)
        part = MIMEText(body_html, 'html', _charset='utf-8')
        content.attach(part)
        if files or reports or attachments:
            msg = MIMEMultipart('mixed')
            msg.attach(content)
            if files is None:
                files = []
            else:
                files = list(files)

            for report_id in (reports or []):
                report = ActionReport(report_id)
                Report = pool.get(report.report_name, type='report')
                ext, content, _, title = Report.execute([record.id], {
                    'action_id': report.id,
                })
                name = '%s.%s' % (title, ext)
                if isinstance(content, str):
                    content = content.encode('utf-8')
                files.append((name, content))
            if attachments:
                files += [(a.name, a.data)
                          for a in Attachment.browse(attachments)]
            for name, data in files:
                mimetype, _ = mimetypes.guess_type(name)
                if mimetype:
                    attachment = MIMENonMultipart(*mimetype.split('/'))
                    attachment.set_payload(data)
                    encode_base64(attachment)
                else:
                    attachment = MIMEApplication(data)
                attachment.add_header('Content-Disposition',
                                      'attachment',
                                      filename=('utf-8', '', name))
                msg.attach(attachment)
        else:
            msg = content
        from_ = config.get('email', 'from')
        set_from_header(msg, from_, user.email or from_)
        msg['To'] = ', '.join(formataddr(a) for a in getaddresses([to]))
        msg['Cc'] = ', '.join(formataddr(a) for a in getaddresses([cc]))
        msg['Subject'] = Header(subject, 'utf-8')

        to_addrs = list(
            filter(
                None,
                map(str.strip,
                    _get_emails(to) + _get_emails(cc) + _get_emails(bcc))))
        sendmail_transactional(from_,
                               to_addrs,
                               msg,
                               datamanager=SMTPDataManager(strict=True))

        email = cls(recipients=to,
                    recipients_secondary=cc,
                    recipients_hidden=bcc,
                    addresses=[{
                        'address': a
                    } for a in to_addrs],
                    subject=subject,
                    body=body,
                    resource=record)
        email.save()
        with Transaction().set_context(_check_access=False):
            attachments_ = []
            for name, data in files:
                attachments_.append(
                    Attachment(resource=email, name=name, data=data))
            Attachment.save(attachments_)
        return email

    @classmethod
    def complete(cls, text, limit):
        limit = int(limit)
        if not limit > 0:
            raise ValueError('limit must be > 0: %r' % (limit, ))
        emails = getaddresses([text])
        if not emails:
            return []
        name, email = map(str.strip, emails[-1])
        if not name and not email:
            return []
        s = StringMatcher()
        try:
            s.set_seq2(_formataddr((name, email)))
        except UnicodeEncodeError:
            return []

        def generate(name, email):
            for name, email in cls._match(name, email):
                try:
                    address = _formataddr((name, email))
                except UnicodeEncodeError:
                    continue
                s.set_seq1(address)
                yield (s.ratio(), address, ', '.join(
                    map(_formataddr, emails[:-1] + [(name, email)])))

        return heapq.nlargest(limit, generate(name, email))

    @classmethod
    def _match(cls, name, email):
        pool = Pool()
        User = pool.get('res.user')
        domain = ['OR']
        for field in ['name', 'login', 'email']:
            for value in [name, email]:
                if value and len(value) >= 3:
                    domain.append(
                        (field, 'ilike', '%' + escape_wildcard(value) + '%'))
        for user in User.search([
            ('email', '!=', ''),
                domain,
        ], order=[]):
            yield user.name, user.email
예제 #28
0
class InpatientMedication(ModelSQL, ModelView):
    'Inpatient Medication'
    __name__ = 'gnuhealth.inpatient.medication'

    name = fields.Many2One('gnuhealth.inpatient.registration',
                           'Registration Code')
    medicament = fields.Many2One('gnuhealth.medicament',
                                 'Medicament',
                                 required=True,
                                 help='Prescribed Medicament')
    indication = fields.Many2One(
        'gnuhealth.pathology',
        'Indication',
        help='Choose a disease for this medicament from the disease list. It'
        ' can be an existing disease of the patient or a prophylactic.')
    start_treatment = fields.DateTime('Start',
                                      help='Date of start of Treatment',
                                      required=True)
    end_treatment = fields.DateTime('End', help='Date of start of Treatment')
    dose = fields.Float('Dose',
                        help='Amount of medication (eg, 250 mg) per dose',
                        required=True)
    dose_unit = fields.Many2One(
        'gnuhealth.dose.unit',
        'dose unit',
        required=True,
        help='Unit of measure for the medication to be taken')
    route = fields.Many2One('gnuhealth.drug.route',
                            'Administration Route',
                            required=True,
                            help='Drug administration route code.')
    form = fields.Many2One('gnuhealth.drug.form',
                           'Form',
                           required=True,
                           help='Drug form, such as tablet or gel')
    qty = fields.Integer(
        'x',
        required=True,
        help='Quantity of units (eg, 2 capsules) of the medicament')
    common_dosage = fields.Many2One(
        'gnuhealth.medication.dosage',
        'Frequency',
        help='Common / standard dosage frequency for this medicament')
    admin_times = fields.One2Many('gnuhealth.inpatient.medication.admin_time',
                                  'name', "Admin times")
    log_history = fields.One2Many('gnuhealth.inpatient.medication.log', 'name',
                                  "Log History")
    frequency = fields.Integer(
        'Frequency',
        help='Time in between doses the patient must wait (ie, for 1 pill'
        ' each 8 hours, put here 8 and select \"hours\" in the unit field')
    frequency_unit = fields.Selection([
        (None, ''),
        ('seconds', 'seconds'),
        ('minutes', 'minutes'),
        ('hours', 'hours'),
        ('days', 'days'),
        ('weeks', 'weeks'),
        ('wr', 'when required'),
    ],
                                      'unit',
                                      select=True,
                                      sort=False)
    frequency_prn = fields.Boolean('PRN', help='Use it as needed, pro re nata')
    is_active = fields.Boolean(
        'Active',
        on_change_with=['discontinued', 'course_completed'],
        help='Check if the patient is currently taking the medication')
    discontinued = fields.Boolean(
        'Discontinued', on_change_with=['is_active', 'course_completed'])
    course_completed = fields.Boolean(
        'Course Completed', on_change_with=['is_active', 'discontinued'])
    discontinued_reason = fields.Char(
        'Reason for discontinuation',
        states={
            'invisible': Not(Bool(Eval('discontinued'))),
            'required': Bool(Eval('discontinued')),
        },
        depends=['discontinued'],
        help='Short description for discontinuing the treatment')
    adverse_reaction = fields.Text(
        'Adverse Reactions',
        help='Side effects or adverse reactions that the patient experienced')

    def on_change_with_is_active(self):
        is_active = True
        if (self.discontinued or self.course_completed):
            is_active = False
        return is_active

    def on_change_with_discontinued(self):
        return not (self.is_active or self.course_completed)

    def on_change_with_course_completed(self):
        return not (self.is_active or self.discontinued)

    @staticmethod
    def default_is_active():
        return True
예제 #29
0
class RCRI(ModelSQL, ModelView):
    'Revised Cardiac Risk Index'
    __name__ = 'gnuhealth.rcri'

    patient = fields.Many2One('gnuhealth.patient', 'Patient ID', required=True)
    rcri_date = fields.DateTime('Date', required=True)
    health_professional = fields.Many2One(
        'gnuhealth.healthprofessional',
        'Health Professional',
        help="Health professional /"
        "Cardiologist who signed the assesment RCRI")

    rcri_high_risk_surgery = fields.Boolean(
        'High Risk surgery',
        help='Includes andy suprainguinal vascular, intraperitoneal,'
        ' or intrathoracic procedures')

    rcri_ischemic_history = fields.Boolean(
        'History of ischemic heart disease',
        help="history of MI or a positive exercise test, current \
        complaint of chest pain considered to be secondary to myocardial \
        ischemia, use of nitrate therapy, or ECG with pathological \
        Q waves; do not count prior coronary revascularization procedure \
        unless one of the other criteria for ischemic heart disease is \
        present")

    rcri_congestive_history = fields.Boolean(
        'History of congestive heart disease')

    rcri_diabetes_history = fields.Boolean(
        'Preoperative Diabetes',
        help="Diabetes Mellitus requiring treatment with Insulin")

    rcri_cerebrovascular_history = fields.Boolean(
        'History of Cerebrovascular disease')

    rcri_kidney_history = fields.Boolean(
        'Preoperative Kidney disease',
        help="Preoperative serum creatinine >2.0 mg/dL (177 mol/L)")

    rcri_total = fields.Integer(
        'Score',
        help='Points 0: Class I Very Low (0.4% complications)\n'
        'Points 1: Class II Low (0.9% complications)\n'
        'Points 2: Class III Moderate (6.6% complications)\n'
        'Points 3 or more : Class IV High (>11% complications)')

    rcri_class = fields.Selection([
        (None, ''),
        ('I', 'I'),
        ('II', 'II'),
        ('III', 'III'),
        ('IV', 'IV'),
    ],
                                  'RCRI Class',
                                  sort=False)

    @fields.depends('rcri_high_risk_surgery', 'rcri_ischemic_history',
                    'rcri_congestive_history', 'rcri_diabetes_history',
                    'rcri_cerebrovascular_history', 'rcri_kidney_history')
    def on_change_with_rcri_total(self):

        total = 0
        if self.rcri_high_risk_surgery:
            total = total + 1
        if self.rcri_ischemic_history:
            total = total + 1
        if self.rcri_congestive_history:
            total = total + 1
        if self.rcri_diabetes_history:
            total = total + 1
        if self.rcri_kidney_history:
            total = total + 1
        if self.rcri_cerebrovascular_history:
            total = total + 1

        return total

    @fields.depends('rcri_high_risk_surgery', 'rcri_ischemic_history',
                    'rcri_congestive_history', 'rcri_diabetes_history',
                    'rcri_cerebrovascular_history', 'rcri_kidney_history')
    def on_change_with_rcri_class(self):
        rcri_class = ''

        total = 0
        if self.rcri_high_risk_surgery:
            total = total + 1
        if self.rcri_ischemic_history:
            total = total + 1
        if self.rcri_congestive_history:
            total = total + 1
        if self.rcri_diabetes_history:
            total = total + 1
        if self.rcri_kidney_history:
            total = total + 1
        if self.rcri_cerebrovascular_history:
            total = total + 1

        if total == 0:
            rcri_class = 'I'
        if total == 1:
            rcri_class = 'II'
        if total == 2:
            rcri_class = 'III'
        if (total > 2):
            rcri_class = 'IV'

        return rcri_class

    @staticmethod
    def default_rcri_date():
        return datetime.now()

    @staticmethod
    def default_rcri_total():
        return 0

    @staticmethod
    def default_rcri_class():
        return 'I'

    def get_rec_name(self, name):
        res = 'Points: ' + str(self.rcri_total) + ' (Class ' + \
            str(self.rcri_class) + ')'
        return res

    @classmethod
    def __setup__(cls):
        super(RCRI, cls).__setup__()
        cls._order.insert(0, ('rcri_date', 'DESC'))

    @classmethod
    def search_rec_name(cls, name, clause):
        if clause[1].startswith('!') or clause[1].startswith('not '):
            bool_op = 'AND'
        else:
            bool_op = 'OR'
        return [
            bool_op,
            ('patient', ) + tuple(clause[1:]),
        ]
예제 #30
0
class PatientAmbulatoryCare(ModelSQL, ModelView):
    'Patient Ambulatory Care'
    __name__ = 'gnuhealth.patient.ambulatory_care'

    name = fields.Char('ID', readonly=True)
    patient = fields.Many2One('gnuhealth.patient', 'Patient', required=True)
    base_condition = fields.Many2One('gnuhealth.pathology', 'Base Condition')
    evaluation = fields.Many2One('gnuhealth.patient.evaluation',
        'Related Evaluation', domain=[('patient', '=', Eval('patient'))],
        depends=['patient'])
    ordering_professional = fields.Many2One('gnuhealth.healthprofessional',
        'Ordering Physician')
    health_professional = fields.Many2One('gnuhealth.healthprofessional',
        'Health Professional', readonly=True)
    procedures = fields.One2Many('gnuhealth.ambulatory_care_procedure', 'name',
        'Procedures',
        help="List of the procedures in this session. Please enter the first "
        "one as the main procedure")
    session_number = fields.Integer('Session #', required=True)
    session_start = fields.DateTime('Start', required=True)

    # Vital Signs
    systolic = fields.Integer('Systolic Pressure')
    diastolic = fields.Integer('Diastolic Pressure')
    bpm = fields.Integer('Heart Rate',
        help='Heart rate expressed in beats per minute')
    respiratory_rate = fields.Integer('Respiratory Rate',
        help='Respiratory rate expressed in breaths per minute')
    osat = fields.Integer('Oxygen Saturation',
        help='Oxygen Saturation(arterial).')
    temperature = fields.Float('Temperature',
        help='Temperature in celsius')

    warning = fields.Boolean('Warning', help="Check this box to alert the "
        "supervisor about this session. It will be shown in red in the "
        "session list")

    #Glycemia
    glycemia = fields.Integer('Glycemia', help='Blood Glucose level')

    evolution = fields.Selection([
        ('initial', 'Initial'),
        ('n', 'Status Quo'),
        ('i', 'Improving'),
        ('w', 'Worsening'),
        ], 'Evolution', required=True, help="Check your judgement of current "
        "patient condition", sort=False)
    session_end = fields.DateTime('End', required=True)
    next_session = fields.DateTime('Next Session')
    session_notes = fields.Text('Notes', required=True)

    @classmethod
    def __setup__(cls):
        super(PatientAmbulatoryCare, cls).__setup__()
        cls._error_messages.update({
            'health_professional_warning':
                    'No health professional associated to this user',
        })
        cls._order.insert(0, ('session_start', 'DESC'))

    @classmethod
    def validate(cls, records):
        super(PatientAmbulatoryCare, cls).validate(records)
        for record in records:
            record.check_health_professional()

    def check_health_professional(self):
        if not self.health_professional:
            self.raise_user_error('health_professional_warning')

    @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.ambulatory_care_sequence.id)
        return super(PatientAmbulatoryCare, cls).create(vlist)

    @staticmethod
    def default_health_professional():
        cursor = Transaction().cursor
        User = Pool().get('res.user')
        user = User(Transaction().user)
        login_user_id = int(user.id)
        cursor.execute('SELECT id FROM party_party WHERE is_healthprof=True AND \
            internal_user = %s LIMIT 1', (login_user_id,))
        partner_id = cursor.fetchone()
        if partner_id:
            cursor = Transaction().cursor
            cursor.execute('SELECT id FROM gnuhealth_healthprofessional WHERE \
                name = %s LIMIT 1', (partner_id[0],))
            doctor_id = cursor.fetchone()
            return int(doctor_id[0])

    @staticmethod
    def default_session_start():
        return datetime.now()

    @classmethod
    def copy(cls, ambulatorycares, default=None):
        if default is None:
            default = {}
        default = default.copy()
        default['name'] = None
        default['session_start'] = cls.default_session_start()
        default['session_end'] = cls.default_session_start()
        return super(PatientAmbulatoryCare, cls).copy(ambulatorycares,
            default=default)