Doctor.get_clients_vocabulary()   C
last analyzed

Complexity

Conditions 11

Size

Total Lines 41
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 41
rs 5.4
c 0
b 0
f 0
cc 11
nop 1

How to fix   Complexity   

Complexity

Complex classes like bika.health.content.doctor.Doctor.get_clients_vocabulary() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.HEALTH.
4
#
5
# SENAITE.HEALTH is free software: you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by the Free
7
# Software Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2019 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
from Products.Archetypes import atapi
22
from Products.Archetypes.public import ReferenceField
23
from Products.Archetypes.public import Schema
24
from Products.Archetypes.public import SelectionWidget
25
from Products.Archetypes.public import StringField
26
from Products.Archetypes.public import StringWidget
27
from bika.health import bikaMessageFactory as _
28
from bika.health.config import *
29
from bika.health.interfaces import IDoctor
30
from bika.lims import api
31
from bika.lims import idserver
32
from bika.lims.catalog.analysisrequest_catalog import \
33
    CATALOG_ANALYSIS_REQUEST_LISTING
34
from bika.lims.content.contact import Contact
35
from zope.interface import implements
36
37
schema = Contact.schema.copy() + Schema((
38
    StringField('DoctorID',
39
        required=1,
40
        searchable=True,
41
        widget=StringWidget(
42
            label=_('Doctor ID'),
43
        ),
44
    ),
45
    ReferenceField(
46
        'PrimaryReferrer',
47
        vocabulary='get_clients_vocabulary',
48
        allowed_types=('Client',),
49
        relationship='DoctorClient',
50
        required=0,
51
        widget=SelectionWidget(
52
            format='select',
53
            description=_('Associate the doctor to a client. '
54
                          'This doctor will not be accessible from '
55
                          'other clients.'),
56
            label=_('Client'),
57
        ),
58
    ),
59
))
60
61
62
class Doctor(Contact):
63
    implements(IDoctor)
64
    _at_rename_after_creation = True
65
    displayContentsTab = False
66
    schema = schema
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable schema does not seem to be defined.
Loading history...
67
68
    def _renameAfterCreation(self, check_auto_id=False):
69
        """Autogenerate the ID of the object based on core's ID formatting
70
        settings for this type
71
        """
72
        idserver.renameAfterCreation(self)
73
74
    def getSamples(self, full_objects=False):
75
        """
76
        Returns the Samples this Doctor is assigned to
77
        :return:
78
        """
79
        query = dict(portal_type="Sample", getDoctorUID=self.UID())
80
        brains = api.search(query, "bika_catalog")
81
        if full_objects:
82
            return map(lambda brain: api.get_object(brain), brains)
83
        return brains
84
85
    def getAnalysisRequests(self, full_objects=False):
86
        """
87
        Returns the Analysis Requests this Doctor is assigned to
88
        :return:
89
        """
90
        query = dict(portal_type='AnalysisRequest', getDoctorUID=self.UID())
91
        brains = api.search(query, CATALOG_ANALYSIS_REQUEST_LISTING)
92
        if full_objects:
93
            return map(lambda brain: api.get_object(brain), brains)
94
        return brains
95
96
    def getBatches(self, full_objects=False):
97
        """
98
        Returns the Batches this Doctor is assigned to
99
        :return:
100
        """
101
        query = dict(portal_type='Batch', getDoctorUID=self.UID())
102
        brains = api.search(query, 'bika_catalog')
103
        if full_objects:
104
            return map(lambda brain: api.get_object(brain), brains)
105
        return brains
106
107
    def get_clients_vocabulary(self):
108
        """
109
        Vocabulary list with clients
110
        :return: A DisplayList object
111
        """
112
        if self.getBatches() or self.getAnalysisRequests():
113
            # Allow to change the client if there are no ARs associated
114
            client = self.getPrimaryReferrer()
115
            if not client:
116
                # Maybe all Batches and ARs assigned to this Doctor belong to
117
                # the same Client.. If so, just assign this client by default
118
                client_uids = map(lambda ar: ar.getClientUID,
119
                                  self.getAnalysisRequests())
120
                client_uids = list(set(client_uids))
121
                if len(client_uids) > 1:
122
                    # More than one client assigned!
123
                    return DisplayList([('', '')])
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable DisplayList does not seem to be defined.
Loading history...
124
                clients = map(lambda batch: batch.getClient(),
125
                              self.getBatches(full_objects=True))
126
                client_uids += map(lambda client: api.get_uid(client), clients)
127
                client_uids = list(set(client_uids))
128
                if len(client_uids) > 1:
129
                    # More than one client assigned!
130
                    return DisplayList([('', '')])
131
132
                client = api.get_object_by_uid(client_uids[0])
133
134
            return DisplayList([(api.get_uid(client), client.Title())])
135
136
        # If the current user is a client contact, do not display other clients
137
        client = api.get_current_client()
138
        if client:
139
            return DisplayList([(api.get_uid(client), client.Title())])
140
141
        # Search for clients
142
        query = dict(portal_type='Client', is_active=True,
143
                     sort_order='ascending', sort_on='title')
144
        brains = api.search(query, 'portal_catalog')
145
        clients = map(lambda brain: [api.get_uid(brain), brain.Title], brains)
146
        clients.insert(0, ['', ''])
147
        return DisplayList(clients)
148
149
    def getPrimaryReferrerUID(self):
150
        primary_referrer = self.getPrimaryReferrer()
151
        if primary_referrer:
152
            return primary_referrer.UID()
153
154
    def current_user_can_edit(self):
155
        """Returns true if the current user can edit this Doctor.
156
        """
157
        user_client = api.get_current_client()
158
        if user_client:
159
            # The current user is a client contact. This user can only edit
160
            # this doctor if it has the same client assigned
161
            client_uid = api.get_uid(user_client)
162
            doctor_client = self.getPrimaryReferrer()
163
            return doctor_client and api.get_uid(doctor_client) == client_uid
164
        return True
165
166
atapi.registerType(Doctor, PROJECTNAME)
167