def remove_stale_css(portal): """Removes stale CSS """ logger.info("Removing stale css ...") for css in CSS_TO_REMOVE: logger.info("Unregistering CSS %s" % css) portal.portal_css.unregisterResource(css)
def setup_content_actions(portal): """Add "patients" and "doctors" action views inside Client view """ logger.info("Setup content actions ...") client_type = portal.portal_types.getTypeInfo("Client") remove_action(client_type, "patients") client_type.addAction(id="patients", name="Patients", action="string:${object_url}/patients", permission=ViewPatients, category="object", visible=True, icon_expr="string:${portal_url}/images/patient.png", link_target="", description="", condition="") remove_action(client_type, "doctors") client_type.addAction(id="doctors", name="Doctors", action="string:${object_url}/doctors", permission=permissions.View, category="object", visible=True, icon_expr="string:${portal_url}/images/doctor.png", link_target="", description="", condition="") logger.info("Setup content actions [DONE]")
def remove_stale_css(portal): """Removes stale CSS """ logger.info("Removing stale css ...") for css in CSS_TO_REMOVE: logger.info("Unregistering CSS %s" % css) portal.portal_css.unregisterResource(css)
def setup_workflows(portal): """Setup workflows """ logger.info("Setting up workflows ...") for wf_id, settings in WORKFLOWS_TO_UPDATE.items(): update_workflow(wf_id, settings) logger.info("Setting up workflows [DONE]")
def setup_id_formatting(portal, format=None): """Setup default ID Formatting for health content types """ if not format: logger.info("Setup ID formatting ...") for formatting in ID_FORMATTING: setup_id_formatting(portal, format=formatting) logger.info("Setup ID formatting [DONE]") return bs = portal.bika_setup p_type = format.get("portal_type", None) if not p_type: return id_map = bs.getIDFormatting() id_format = filter(lambda idf: idf.get("portal_type", "") == p_type, id_map) if id_format: logger.info("ID Format for {} already set: '{}' [SKIP]".format( p_type, id_format[0]["form"])) return form = format.get("form", "") if not form: logger.info("Param 'form' for portal type {} not set [SKIP") return logger.info("Applying format '{}' for {}".format(form, p_type)) ids = list() for record in id_map: if record.get('portal_type', '') == p_type: continue ids.append(record) ids.append(format) bs.setIDFormatting(ids)
def update_rolemappings_for_shareable(portal): """Updates the workflow for shareable objects. """ logger.info("Updating role mappings for shareable objects ...") wf = api.get_tool("portal_workflow") def update_rolemappings_for(portal_type, folder, workflow): objs = folder.objectValues(portal_type) total = len(objs) for num, obj in enumerate(objs): if num and num % 100 == 0: logger.info("Updating role mappings for {} {}/{}".format( portal_type, num, total)) workflow.updateRoleMappingsFor(obj) obj.reindexObject(idxs=["allowedRolesAndUsers"]) # Patients wf = wf.getWorkflowById("senaite_health_patient_workflow") update_rolemappings_for("Patient", portal.patients, wf) # Doctors wf = wf.getWorkflowById("senaite_health_doctor_workflow") update_rolemappings_for("Doctor", portal.doctors, wf) # Batches wf = wf.getWorkflowById("senaite_batch_workflow") update_rolemappings_for("Batch", portal.batches, wf) logger.info("Updating role mappings for shareable objects [DONE]")
def move_doctors_to_clients(portal): """Moves the doctors into their assigned Client, if any """ logger.info("Moving Doctors inside Clients...") query = {"portal_type": "Doctor"} doctors = map(api.get_object, api.search(query, "portal_catalog")) map(move_doctor_to_client, doctors) logger.info("Moving Doctors inside Clients [DONE]")
def _linkUser(self, user): """Set the UID of the current Contact in the User properties and update all relevant own properties. """ logger.warn("MONKEY PATCHING __linkUser") KEY = "linked_contact_uid" username = user.getId() contact = self.getContactByUsername(username) # User is linked to another contact (fix in UI) if contact and contact.UID() != self.UID(): raise ValueError("User '{}' is already linked to Contact '{}'".format( username, contact.Title())) # User is linked to multiple other contacts (fix in Data) if isinstance(contact, list): raise ValueError( "User '{}' is linked to multiple Contacts: '{}'".format( username, ",".join(map(lambda x: x.Title(), contact)))) # XXX: Does it make sense to "remember" the UID as a User property? tool = user.getTool() try: user.getProperty(KEY) except ValueError: logger.info("Adding User property {}".format(KEY)) tool.manage_addProperty(KEY, "", "string") # Set the UID as a User Property uid = self.UID() user.setMemberProperties({KEY: uid}) logger.info("Linked Contact UID {} to User {}".format( user.getProperty(KEY), username)) # Set the Username self.setUsername(user.getId()) # Update the Email address from the user self.setEmailAddress(user.getProperty("email")) # somehow the `getUsername` index gets out of sync self.reindexObject() # N.B. Local owner role and client group applies only to client # contacts, but not lab contacts. if IClient.providedBy(self.aq_parent): # Grant local Owner role self._addLocalOwnerRole(username) # Add user to "Clients" group self._addUserToGroup(username, group="Clients") # SENAITE.HEALTH-specific! # Add user to "InternalClients" group if is_internal_client(self.aq_parent): self._addUserToGroup(username, group="InternalClients") return True
def update_rolemappings_for(portal_type, folder, workflow): objs = folder.objectValues(portal_type) total = len(objs) for num, obj in enumerate(objs): if num and num % 100 == 0: logger.info("Updating role mappings for {} {}/{}".format( portal_type, num, total)) workflow.updateRoleMappingsFor(obj) obj.reindexObject(idxs=["allowedRolesAndUsers"])
def del_metadata(catalog_id, column): logger.info("Removing '{}' metadata from '{}' ...".format( column, catalog_id)) catalog = api.get_tool(catalog_id) if column not in catalog.schema(): logger.info("Metadata '{}' not in catalog '{}' [SKIP]".format( column, catalog_id)) return catalog.delColumn(column)
def del_index(catalog_id, name): """Removes the given index from the catalog """ catalog = api.get_tool(catalog_id) if name not in catalog.indexes(): logger.info("Index '{}' not in catalog '{}'".format(name, catalog_id)) return False catalog.delIndex(name) logger.info("Index '{}' removed from '{}'".format(name, catalog_id)) return True
def update_patients_role_mappings(portal): """Updates the role mappings for patients folder cause we've changed the workflow bound to this type and we've added permission to Delete Objects """ logger.info("Updating role mappings of patients folder ...") wf_tool = api.get_tool("portal_workflow") workflow = wf_tool.getWorkflowById("senaite_health_patients_workflow") workflow.updateRoleMappingsFor(portal.patients) portal.patients.reindexObject() logger.info("Updating role mappings of patients folder [DONE]")
def remove_sample_actions(portal): """Remove the "Sample" action view from inside Patient and Doctor objects """ logger.info("Removing Samples action view from Patients ...") patient_type = portal.portal_types.getTypeInfo("Patient") remove_action(patient_type, "samples") logger.info("Removing Samples action view from Doctors ...") doctor_type = portal.portal_types.getTypeInfo("Doctor") remove_action(doctor_type, "samples")
def del_index(catalog_id, name): """Removes the given index from the catalog """ catalog = api.get_tool(catalog_id) if name not in catalog.indexes(): logger.info("Index '{}' not in catalog '{}'".format(name, catalog_id)) return False catalog.delIndex(name) logger.info("Index '{}' removed from '{}'".format(name, catalog_id)) return True
def del_column(catalog_id, name): """Removes the given metadata column from the catalog """ catalog = api.get_tool(catalog_id) if name not in catalog.schema(): logger.info("Column '{}' not in catalog '{}'".format(name, catalog_id)) return False catalog.delColumn(name) logger.info("Column '{}' removed from '{}'".format(name, catalog_id)) return True
def remove_sample_actions(portal): """Remove the "Sample" action view from inside Patient and Doctor objects """ logger.info("Removing Samples action view from Patients ...") patient_type = portal.portal_types.getTypeInfo("Patient") remove_action(patient_type, "samples") logger.info("Removing Samples action view from Doctors ...") doctor_type = portal.portal_types.getTypeInfo("Doctor") remove_action(doctor_type, "samples")
def del_column(catalog_id, name): """Removes the given metadata column from the catalog """ catalog = api.get_tool(catalog_id) if name not in catalog.schema(): logger.info("Column '{}' not in catalog '{}'".format(name, catalog_id)) return False catalog.delColumn(name) logger.info("Column '{}' removed from '{}'".format(name, catalog_id)) return True
def set_field_value(instance, field_name, value): """Sets the value to a Schema field """ if field_name == "id": logger.warn("Assignment of id is not allowed") return logger.info("Field {} = {}".format(field_name, repr(value))) instance = api.get_object(instance) field = instance.Schema() and instance.Schema().getField(field_name) or None if not field: api.fail("No field {} found for {}".format(field_name, repr(instance))) field.set(instance, value)
def update_workflow(workflow_id, settings): logger.info("Updating workflow '{}' ...".format(workflow_id)) wf_tool = api.get_tool("portal_workflow") workflow = wf_tool.getWorkflowById(workflow_id) if not workflow: logger.warn("Workflow '{}' not found [SKIP]".format(workflow_id)) states = settings.get("states", {}) for state_id, values in states.items(): update_workflow_state(workflow, state_id, values) transitions = settings.get("transitions", {}) for transition_id, values in transitions.items(): update_workflow_transition(workflow, transition_id, values)
def sort_nav_bar(portal): """Sort items in the navigation bar """ logger.info("Sorting items from navigation bar ...") sorted_ids = [ "clients", "internal_clients", "analysisrequests", "batches", "patients", "doctors", ] portal.moveObjectsToTop(ids=sorted_ids)
def install_senaite_panic(portal): """Install the senaite.panic addon """ qi = api.get_tool("portal_quickinstaller") profile = "senaite.panic" if profile not in qi.listInstallableProfiles(): logger.error( "Profile '{}' not found. Forgot to run buildout?".format(profile)) return if qi.isProductInstalled(profile): logger.info("'{}' is installed".format(profile)) return qi.installProduct(profile)
def update_workflows(portal): """Updates the affected workflows """ logger.info("Updating workflows ...") # Re-import rolemap and workflow tools setup = portal.portal_setup setup.runImportStepFromProfile(profile, "rolemap") setup.runImportStepFromProfile(profile, "workflow") # Update role mappings for Patient objects ut = UpgradeUtils(portal) ut.recursiveUpdateRoleMappings(portal.patients, commit_window=500) commit_transaction()
def update_workflows(portal): """Updates the affected workflows """ logger.info("Updating workflows ...") # Re-import rolemap and workflow tools setup = portal.portal_setup setup.runImportStepFromProfile(profile, "rolemap") setup.runImportStepFromProfile(profile, "workflow") # Update role mappings for Patient objects ut = UpgradeUtils(portal) ut.recursiveUpdateRoleMappings(portal.patients, commit_window=500) commit_transaction()
def setup_roles_permissions(portal): """Setup the top-level permissions for new roles. The new role is added to the roles that already have the permission granted (acquire=1) """ logger.info("Setup roles permissions ...") for role_name, permissions in ROLES: for permission in permissions: add_permission_for_role(portal, permission, role_name) # Add "Add AnalysisRequest" permission for Clients in base analysisrequests # This makes the "Add" button to appear in AnalysisRequestsFolder view analysis_requests = portal.analysisrequests add_permission_for_role(analysis_requests, AddAnalysisRequest, "Client") logger.info("Setup roles permissions [DONE]")
def setup_batches_ownership(portal): """Walks-through all batches and set the role "Owner" to all the client contacts that belong to the same client as the batch, if any """ logger.info("Setup Batches/Cases ownership ...") batches = portal.batches.objectValues("Batch") total = len(batches) for num, batch in enumerate(batches): if num % 100 == 0: logger.info("Setup Batches ownership {}/{}".format(num, total)) purge_owners_for(batch) if num % 1000 == 0: commit_transaction() commit_transaction()
def setup_patients_ownership(portal): """Set the role "Owner" to all the client contacts that belong to the same client as the patient, if any """ logger.info("Applying Patients ownership ...") brains = api.search(dict(portal_type="Patient"), CATALOG_PATIENTS) total = len(brains) for num, brain in enumerate(brains): if num % 100 == 0: logger.info("Applying Patients Ownership {}/{}".format(num, total)) purge_owners_for(api.get_object(brain)) if num % 1000 == 0: commit_transaction() commit_transaction()
def setup_patients_ownership(portal): """Set the role "Owner" to all the client contacts that belong to the same client as the patient, if any """ logger.info("Applying Patients ownership ...") brains = api.search(dict(portal_type="Patient"), CATALOG_PATIENTS) total = len(brains) for num, brain in enumerate(brains): if num % 100 == 0: logger.info("Applying Patients Ownership {}/{}".format(num, total)) purge_owners_for(api.get_object(brain)) if num % 1000 == 0: commit_transaction() commit_transaction()
def setupEthnicities(bika_setup): """ Creates standard ethnicities """ ethnicities = ['Native American', 'Asian', 'Black', 'Native Hawaiian or Other Pacific Islander', 'White', 'Hispanic or Latino'] for ethnicityName in ethnicities: folder = bika_setup.bika_ethnicities # Generating a temporal object _id = folder.invokeFactory('Ethnicity', id=tmpID()) obj = folder[_id] # Setting its values obj.edit(title=ethnicityName, description='') obj.unmarkCreationFlag() renameAfterCreation(obj) logger.info("Standard ethnicities enabled")
def hide_doctors_from_navbar(portal): """Hide doctor items to be displayed in the navigation bar """ logger.info("Hiding Doctors from navbar ...") # Plone uses exclude_from_nav metadata column to know if the object # has to be displayed in the navigation bar. This metadata column only # exists in portal_catalog and while with other portal types this might # not be required, this is necessary for Doctors, cause they are # stored in portal_catalog catalog = api.get_tool("portal_catalog") for doctor in portal.doctors.objectValues(): # We don't need to reindex everything, but the metadata only. So we # just use any index catalog.reindexObject(doctor, idxs=["title"], update_metadata=1) logger.info("Hiding Doctors from navbar [DONE]")
def setup_ethnicities(portal): """ Creates standard ethnicities """ logger.info("Setup default ethnicities ...") ethnicities = [ 'Native American', 'Asian', 'Black', 'Native Hawaiian or Other Pacific Islander', 'White', 'Hispanic or Latino' ] folder = portal.bika_setup.bika_ethnicities for ethnicityName in ethnicities: _id = folder.invokeFactory('Ethnicity', id=tmpID()) obj = folder[_id] obj.edit(title=ethnicityName, description='') obj.unmarkCreationFlag() renameAfterCreation(obj) logger.info("Setup default ethnicities [DONE]")
def resolve_identifier_type(identifier_id): """Search for an identifier type with an ID that matches with the id passed in. If no identifier type is found, creates a new one """ setup = api.get_setup() folder = setup.bika_identifiertypes id_types = folder.objectValues() for id_type in id_types: if api.get_title(id_type) == identifier_id: return id_type # Create a new identifier type logger.info("Creating new Identifier Type: {}".format(identifier_id)) obj = _createObjectByType('IdentifierType', folder, tmpID()) obj.edit(title=identifier_id, description=identifier_id) obj.unmarkCreationFlag() renameAfterCreation(obj) return obj
def setup_user_groups(portal): logger.info("Setup User Groups ...") portal_groups = portal.portal_groups for group_name, roles in GROUPS: if group_name not in portal_groups.listGroupIds(): portal_groups.addGroup(group_name, title=group_name, roles=roles) logger.info("Group '{}' with roles '{}' added".format( group_name, ", ".join(roles))) else: logger.info("Group '{}' already exist [SKIP]".format(group_name)) logger.info("Setup User Groups [DONE]")
def post_install(portal_setup): """Runs after the last import step of the *default* profile This handler is registered as a *post_handler* in the generic setup profile :param portal_setup: SetupTool """ logger.info("SENAITE Health post-install handler [BEGIN]") context = portal_setup._getImportContext(DEFAULT_PROFILE_ID) portal = context.getSite() # When installing senaite health together with core, health's skins are not # set before core's, even if after-before is set in profiles/skins.xml # Ensure health's skin layer(s) always gets priority over core's portal_setup.runImportStepFromProfile(DEFAULT_PROFILE_ID, "skins") # Setup catalogs # TODO use upgrade.utils.setup_catalogs instead! setup_health_catalogs(portal) # Setup portal permissions setup_roles_permissions(portal) # Setup user groups (e.g. Doctors) setup_user_groups(portal) # Setup site structure setup_site_structure(context) # Setup "Owner" roles for batches to client contacts setup_batches_ownership(portal) # Setup javascripts setup_javascripts(portal) # Setup content actions setup_content_actions(portal) # Setup ID formatting for Health types setup_id_formatting(portal) # Setup default ethnicities setup_ethnicities(portal) logger.info("SENAITE Health post-install handler [DONE]")
def setupEthnicities(bika_setup): """ Creates standard ethnicities """ ethnicities = [ 'Native American', 'Asian', 'Black', 'Native Hawaiian or Other Pacific Islander', 'White', 'Hispanic or Latino' ] for ethnicityName in ethnicities: folder = bika_setup.bika_ethnicities # Generating a temporal object _id = folder.invokeFactory('Ethnicity', id=tmpID()) obj = folder[_id] # Setting its values obj.edit(title=ethnicityName, description='') obj.unmarkCreationFlag() renameAfterCreation(obj) logger.info("Standard ethnicities enabled")
def _unlinkUser(self): """Remove the UID of the current Contact in the User properties and update all relevant own properties. """ logger.warn("MONKEY PATCHING __unlinkUser") KEY = "linked_contact_uid" # Nothing to do if no user is linked if not self.hasUser(): return False user = self.getUser() username = user.getId() # Unset the UID from the User Property user.setMemberProperties({KEY: ""}) logger.info("Unlinked Contact UID from User {}".format( user.getProperty(KEY, ""))) # Unset the Username self.setUsername(None) # Unset the Email self.setEmailAddress(None) # somehow the `getUsername` index gets out of sync self.reindexObject() # N.B. Local owner role and client group applies only to client # contacts, but not lab contacts. if IClient.providedBy(self.aq_parent): # Revoke local Owner role self._delLocalOwnerRole(username) # Remove user from "Clients" group self._delUserFromGroup(username, group="Clients") # SENAITE.HEALTH-specific! # Remove user from "InternalClients" group if is_internal_client(self.aq_parent): self._delUserFromGroup(username, group="InternalClients") return True
def upgrade(tool): portal = aq_parent(aq_inner(tool)) ut = UpgradeUtils(portal) ver_from = ut.getInstalledVersion(product) # Since this upgrade is precisely meant to establish a version regardless # of the version numbering at bikalims/bika.health, we don't want this check # to be performed. # if ut.isOlderVersion(product, version): # logger.info("Skipping upgrade of {0}: {1} > {2}".format( # product, ufrom, version)) # # The currently installed version is more recent than the target # # version of this upgradestep # return True logger.info("Upgrading {0}: {1} -> {2}".format(product, ver_from, version)) # Do nothing, we just only want the profile version to be 1.0.0 logger.info("{0} upgraded to version {1}".format(product, version)) return True
def upgrade(tool): portal = aq_parent(aq_inner(tool)) ut = UpgradeUtils(portal) ver_from = ut.getInstalledVersion(product) # Since this upgrade is precisely meant to establish a version regardless # of the version numbering at bikalims/bika.health, we don't want this check # to be performed. # if ut.isOlderVersion(product, version): # logger.info("Skipping upgrade of {0}: {1} > {2}".format( # product, ufrom, version)) # # The currently installed version is more recent than the target # # version of this upgradestep # return True logger.info("Upgrading {0}: {1} -> {2}".format(product, ver_from, version)) # Do nothing, we just only want the profile version to be 1.0.0 logger.info("{0} upgraded to version {1}".format(product, version)) return True
def update_workflow_transition(workflow, transition_id, settings): logger.info("Updating workflow '{}', transition: '{}'".format( workflow.id, transition_id)) if transition_id not in workflow.transitions: workflow.transitions.addTransition(transition_id) transition = workflow.transitions.get(transition_id) transition.setProperties(title=settings.get("title"), new_state_id=settings.get("new_state"), after_script_name=settings.get( "after_script", ""), actbox_name=settings.get("action", settings.get("title"))) guard = transition.guard or Guard() guard_props = { "guard_permissions": "", "guard_roles": "", "guard_expr": "" } guard_props = settings.get("guard", guard_props) guard.changeFromProperties(guard_props) transition.guard = guard
def upgrade(tool): portal = tool.aq_inner.aq_parent ut = UpgradeUtils(portal) ver_from = ut.getInstalledVersion(product) if ut.isOlderVersion(product, version): logger.info("Skipping upgrade of {0}: {1} > {2}".format( product, ver_from, version)) return True logger.info("Upgrading {0}: {1} -> {2}".format(product, ver_from, version)) # -------- ADD YOUR STUFF HERE -------- # Ensure health's skins have always priority over core's setup = portal.portal_setup setup.runImportStepFromProfile(profile, "skins") setup.runImportStepFromProfile(profile, 'workflow') setup.runImportStepFromProfile(profile, "typeinfo") # Allow clients to list, add and edit doctors apply_doctor_permissions_for_clients(portal, ut) logger.info("{0} upgraded to version {1}".format(product, version)) return True
def upgrade(tool): portal = tool.aq_inner.aq_parent ut = UpgradeUtils(portal) ver_from = ut.getInstalledVersion(product) if ut.isOlderVersion(product, version): logger.info("Skipping upgrade of {0}: {1} > {2}".format( product, ver_from, version)) return True logger.info("Upgrading {0}: {1} -> {2}".format(product, ver_from, version)) # -------- ADD YOUR STUFF HERE -------- ut.delIndexAndColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getPatient') ut.delIndexAndColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getDoctor') ut.addColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getPatientID') ut.addIndexAndColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getPatientTitle', 'FieldIndex') # In case if upgrade was already run after PR #72 got accepted ut.delColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getPatientURL') ut.addColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getPatientURL') ut.addColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getClientPatientID') ut.addIndexAndColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getDoctorTitle', 'FieldIndex') # In case if upgrade was already run after PR #72 got accepted ut.delColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getDoctorURL') ut.addColumn(CATALOG_ANALYSIS_REQUEST_LISTING, 'getDoctorURL') ut.addIndex(CATALOG_PATIENTS, 'listing_searchable_text', 'TextIndexNG3') ut.refreshCatalogs() logger.info("{0} upgraded to version {1}".format(product, version)) return True
def add_doctor_action_for_client(portal): """ Adds doctor action for client portal_type programmatically :param portal: The portal object :return: None """ client = portal.portal_types.getTypeInfo("Client") for action in client.listActionInfos(): if action.get('id', None) == 'doctors': logger.info("Already existing 'doctor' action for client portal_type") return None client.addAction( id="doctors", name="Doctors", action="string:${object_url}/doctors", permission=permissions.View, category="object", visible=True, icon_expr="string:${portal_url}/images/doctor.png", link_target="", description="", condition="") logger.info("'doctor' action for client portal_type added")
def folderitems(self, full_objects=False): logger.info("*** Bika Health's folderitems ***") pm = getToolByName(self.context, "portal_membership") member = pm.getAuthenticatedMember() # We will use this list for each element roles = member.getRoles() # delete roles user doesn't have permissions if 'Manager' not in roles \ and 'LabManager' not in roles \ and 'LabClerk' not in roles: self.remove_column('getPatientID') self.remove_column('getClientPatientID') self.remove_column('getPatientTitle') self.remove_column('getDoctorTitle') # Otherwise show the columns in the list else: for rs in self.review_states: i = rs['columns'].index('BatchID') + 1 rs['columns'].insert(i, 'getClientPatientID') rs['columns'].insert(i, 'getPatientID') rs['columns'].insert(i, 'getPatientTitle') rs['columns'].insert(i, 'getDoctorTitle') return super(AnalysisRequestsView, self).folderitems( full_objects=False, classic=False)
def upgrade(tool): portal = tool.aq_inner.aq_parent setup = portal.portal_setup ut = UpgradeUtils(portal) ver_from = ut.getInstalledVersion(PROJECTNAME) if ut.isOlderVersion(PROJECTNAME, version): logger.info("Skipping upgrade of {0}: {1} > {2}".format( PROJECTNAME, ver_from, version)) return True logger.info("Upgrading {0}: {1} -> {2}".format(PROJECTNAME, ver_from, version)) # -------- ADD YOUR STUFF BELOW -------- setup.runImportStepFromProfile(profile, "browserlayer") setup.runImportStepFromProfile(profile, "typeinfo") setup.runImportStepFromProfile(profile, "skins") # Setup catalogs setup_catalogs(CATALOGS_BY_TYPE, INDEXES, COLUMNS) # Remove indexes and metadata columns remove_indexes_and_metadata() # Setup permissions setup_roles_permissions(portal) # Setup ID Formatting setup_id_formatting(portal) # Add "Patients" and "Doctors" action views in Client type setup_content_actions(portal) # Remove "Samples" action views from Doctors and Patients remove_sample_actions(portal) # Setup "Owner" roles for patients to client contacts setup_patients_ownership(portal) # Setup "Owner" roles for batches to client contacts setup_batches_ownership(portal) # Update workflows update_workflows(portal) # remove stale CSS remove_stale_css(portal) logger.info("{0} upgraded to version {1}".format(PROJECTNAME, version)) return True
def upgrade(tool): portal = tool.aq_inner.aq_parent ut = UpgradeUtils(portal) ver_from = ut.getInstalledVersion(product) if ut.isOlderVersion(product, version): logger.info("Skipping upgrade of {0}: {1} > {2}".format( product, ver_from, version)) return True logger.info("Upgrading {0}: {1} -> {2}".format(product, ver_from, version)) ut.addIndex(CATALOG_PATIENTS, 'getClientPatientID', 'FieldIndex') ut.refreshCatalogs() logger.info("{0} upgraded to version {1}".format(product, version)) return True
def apply_doctor_permissions_for_clients(portal, ut): # Add doctor action for client portal_type add_doctor_action_for_client(portal) # Allow client contacts to list/add/edit Doctors workflow_tool = api.get_tool("portal_workflow") workflow = workflow_tool.getWorkflowById('bika_doctor_workflow') catalog = api.get_tool('portal_catalog') # Adding new index and columns in portal_catalog for doctors ut.addIndexAndColumn('portal_catalog', 'allowedRolesAndUsers', 'FieldIndex') ut.addIndex('portal_catalog', 'getPrimaryReferrerUID', 'FieldIndex') brains = catalog(portal_type='Doctor') counter = 0 total = len(brains) logger.info( "Changing permissions for doctor objects: {0}".format(total)) for brain in brains: allowed = brain.allowedRolesAndUsers or [] if 'Client' not in allowed: obj = api.get_object(brain) workflow.updateRoleMappingsFor(obj) obj.reindexObject() counter += 1 if counter % 100 == 0: logger.info( "Changing permissions for doctor objects: " + "{0}/{1}".format(counter, total)) logger.info( "Changed permissions for doctor objects: " + "{0}/{1}".format(counter, total)) # Allowing client to view clients folder add_permission_for_role(portal.doctors, permissions.View, 'Client') add_permission_for_role(portal.doctors, AddDoctor, 'Client')
def setup_catalogs(catalogs_by_type, indexes_by_catalog, columns_by_catalog): """Setup Plone catalogs """ logger.info("Setup Catalogs ...") # Setup catalogs by type for type_name, catalogs in catalogs_by_type: at = api.get_tool("archetype_tool") # get the current registered catalogs current_catalogs = at.getCatalogsByType(type_name) # get the desired catalogs this type should be in desired_catalogs = map(api.get_tool, catalogs) # check if the catalogs changed for this portal_type if set(desired_catalogs).difference(current_catalogs): # fetch the brains to reindex brains = api.search({"portal_type": type_name}) # updated the catalogs at.setCatalogsByType(type_name, catalogs) logger.info("Assign '%s' type to Catalogs %s" % (type_name, catalogs)) for brain in brains: obj = api.get_object(brain) logger.info("Reindexing '%s'" % repr(obj)) obj.reindexObject() # Setup catalog indexes to_index = [] for catalog, name, meta_type in indexes_by_catalog: c = api.get_tool(catalog) indexes = c.indexes() if name in indexes: logger.info("Index '%s' already in Catalog [SKIP]" % name) continue logger.info("Adding Index '%s' for field '%s' to catalog '%s" % (meta_type, name, catalog)) if meta_type == "ZCTextIndex": addZCTextIndex(c, name) else: c.addIndex(name, meta_type) to_index.append((c, name)) logger.info("Added Index '%s' for field '%s' to catalog [DONE]" % (meta_type, name)) for catalog, name in to_index: logger.info("Indexing new index '%s' ..." % name) catalog.manage_reindexIndex(name) logger.info("Indexing new index '%s' [DONE]" % name) # Setup catalog metadata columns for catalog, name in columns_by_catalog: c = api.get_tool(catalog) if name not in c.schema(): logger.info("Adding Column '%s' to catalog '%s' ..." % (name, catalog)) c.addColumn(name) logger.info("Added Column '%s' to catalog '%s' [DONE]" % (name, catalog)) else: logger.info("Column '%s' already in catalog '%s' [SKIP]" % (name, catalog)) continue