def create_test_data(portal): """Populates with storage-like test data """ if not CREATE_TEST_DATA: return logger.info("Creating test data ...") facilities = portal.senaite_storage if len(facilities.objectValues()) > 0: logger.info("There are facilities created already [SKIP]") return def get_random(min, max): if not CREATE_TEST_DATA_RANDOM: return min return int(round(random.uniform(min, max))) # Facilities for x in range(get_random(3, 8)): facility = api.create( facilities, "StorageFacility", title="Storage facility {:02d}".format(x + 1), Phone="123456789", EmailAddress="storage{:02d}@example.com".format(x + 1), PhysicalAddress={ "address": "Av. Via Augusta 15 - 25", "city": "Sant Cugat del Valles", "zip": "08174", "state": "", "country": "Spain", }) # Fridges for i in range(get_random(2, 5)): container = api.create(facility, "StorageContainer", title="Fridge {:02d}".format(i + 1), Rows=get_random(4, 8), Columns=get_random(4, 6)) # Racks for j in range(get_random(4, container.get_capacity())): rack = api.create(container, "StorageContainer", title="Rack {:02d}".format(j + 1), Rows=get_random(3, 4), Columns=get_random(2, 3)) # Boxes for k in range(get_random(2, rack.get_capacity())): box = api.create(rack, "StorageSamplesContainer", title="Sample box {:02d}".format(k + 1), Rows=get_random(5, 10), Columns=get_random(5, 10))
def create_report(self, parent, pdf, html, uids, metadata): """Create a new report object NOTE: We limit the creation of reports to 1 to avoid conflict errors on simultaneous publication. :param parent: parent object where to create the report inside :returns: ARReport """ parent_id = api.get_id(parent) logger.info("Create Report for {} ...".format(parent_id)) # Manually update the view on the database to avoid conflict errors parent._p_jar.sync() # Create the report object report = api.create(parent, "ARReport", AnalysisRequest=api.get_uid(parent), Pdf=pdf, Html=html, ContainedAnalysisRequests=uids, Metadata=metadata) # Commit the changes transaction.commit() logger.info("Create Report for {} [DONE]".format(parent_id)) return report
def create_attachment(self, container, attachment_file, **kw): """Create an Attachment object in the given container """ filename = getattr(attachment_file, "filename", "Attachment") attachment = api.create(container, "Attachment", title=filename) attachment.edit(AttachmentFile=attachment_file, **kw) attachment.processForm() attachment.reindexObject() logger.info("Created new Attachment {} in {}".format( repr(attachment), repr(container))) return attachment
def create_object(container, portal_type, **data): """Creates an object slug :returns: The new created content object :rtype: object """ if "id" in data: # always omit the id as senaite LIMS generates a proper one id = data.pop("id") logger.warn("Passed in ID '{}' omitted! Senaite LIMS " "generates a proper ID for you".format(id)) try: # Is there any adapter registered to handle the creation of this type? adapter = queryAdapter(container, ICreate, name=portal_type) if adapter and adapter.is_creation_delegated(): logger.info("Delegating 'create' operation of '{}' in '{}'".format( portal_type, api.get_path(container))) return adapter.create_object(**data) # Special case for ARs # => return immediately w/o update if portal_type == "AnalysisRequest": obj = create_analysisrequest(container, **data) # Omit values which are already set through the helper data = u.omit(data, "SampleType", "Analyses") # Set the container as the client, as the AR lives in it data["Client"] = container return obj # Standard content creation else: # we want just a minimun viable object and set the data later obj = api.create(container, portal_type) # obj = api.create(container, portal_type, **data) except Unauthorized: fail(401, "You are not allowed to create this content") # Update the object with the given data, but omit the id try: update_object_with_data(obj, data) except APIError: # Failure in creation process, delete the invalid object # NOTE: We bypass the permission checks container._delObject(obj.id) # reraise the error raise return obj
def setup_antibiotic_classes(portal): """Setup default antibiotic classes if do not exist yet """ logger.info("Setup default antibiotic classes ...") # Get the titles of the existing classes first folder = api.get_setup().get("antibiotic_classes") existing = map(api.get_title, folder.objectValues()) # Create the antibiotic classes for ac in ANTIBIOTIC_CLASSES: if ac in existing: logger.warn("Antibiotic class {} already exists [SKIP]".format(ac)) continue logger.info("Adding antibiotic class: {}".format(ac)) api.create(folder, "AntibioticClass", title=ac) # Don't know why yet, but after adding the antibiotic classes, the folder # looses the title folder.title = "Antibiotic classes" folder.reindexObject() logger.info("Setup default antibiotic classes [DONE]")
def create_report(self, parent, pdf, html, uids, metadata, csv_text=None): """Create a new report object NOTE: We limit the creation of reports to 1 to avoid conflict errors on simultaneous publication. :param parent: parent object where to create the report inside :returns: ARReport """ parent_id = api.get_id(parent) logger.info("Create Report for {} ...".format(parent_id)) # Manually update the view on the database to avoid conflict errors parent._p_jar.sync() query = { 'portal_type': 'ARReport', 'path': { 'query': api.get_path(parent), 'depth': 1 } } brains = api.search(query, 'portal_catalog') coa_num = '{}-COA-{}'.format(parent_id, len(brains) + 1) # Create the report object report = api.create(parent, "ARReport", AnalysisRequest=api.get_uid(parent), Pdf=pdf, Html=html, CSV=csv_text, ContainedAnalysisRequests=uids, Metadata=metadata) fld = report.getField('Pdf') fld.get(report).setFilename(coa_num + ".pdf") fld.get(report).setContentType('application/pdf') fld = report.getField('CSV') fld.get(report).setFilename(coa_num + ".csv") fld.get(report).setContentType('text/csv') # Commit the changes transaction.commit() logger.info("Create Report for {} [DONE]".format(parent_id)) return report
def setup_antibiotics(portal): """Setup default antibiotics if do not exist yet """ logger.info("Setup default antibiotics ...") # Get the titles of the existing antibiotics first folder = api.get_setup().get("antibiotics") existing = map(api.get_title, folder.objectValues()) def get_antibiotic_class(name): query = { "portal_type": "AntibioticClass", "title": name, } brains = api.search(query) if len(brains) == 1: return api.get_object(brains[0]) return None # Create the antibiotic classes for name, props in ANTIBIOTICS: if name in existing: logger.warn("Antibiotic {} already exists [SKIP]".format(name)) continue logger.info("Adding antibiotic: {}".format(name)) # Get the antibiotic class by name a_class_name = props.get("antibiotic_class") a_class = get_antibiotic_class(a_class_name) if not a_class: logger.error("Antibiotic class missing: '{}' [SKIP]".format( a_class_name)) continue obj = api.create(folder, "Antibiotic", title=name) obj.antibiotic_class = api.get_uid(a_class) obj.abbreviation = props.get("abbreviation") obj.reindexObject() # After adding the antibiotic, the folder looses the title folder.title = "Antibiotics" folder.reindexObject() logger.info("Setup default antibiotics [DONE]")
def create_object(container, portal_type, **data): """Creates an object slug :returns: The new created content object :rtype: object """ if "id" in data: # always omit the id as Bika LIMS generates a proper one id = data.pop("id") logger.warn("Passed in ID '{}' omitted! Bika LIMS " "generates a proper ID for you".format(id)) try: # Special case for ARs # => return immediately w/o update if portal_type == "AnalysisRequest": obj = create_analysisrequest(container, **data) # Omit values which are already set through the helper data = u.omit(data, "SampleType", "Analyses") # Set the container as the client, as the AR lives in it data["Client"] = container # Standard content creation else: # we want just a minimun viable object and set the data later obj = api.create(container, portal_type) # obj = api.create(container, portal_type, **data) except Unauthorized: fail(401, "You are not allowed to create this content") # Update the object with the given data, but omit the id try: update_object_with_data(obj, data) #start point except APIError: # Failure in creation process, delete the invalid object container.manage_delObjects(obj.id) # reraise the error raise return obj
def create_object(container, portal_type, **data): """Creates an object slug :returns: The new created content object :rtype: object """ if "id" in data: # always omit the id as Bika LIMS generates a proper one id = data.pop("id") logger.warn("Passed in ID '{}' omitted! Bika LIMS " "generates a proper ID for you" .format(id)) try: # Special case for ARs # => return immediately w/o update if portal_type == "AnalysisRequest": obj = create_analysisrequest(container, **data) # Omit values which are already set through the helper data = u.omit(data, "SampleType", "Analyses") # Set the container as the client, as the AR lives in it data["Client"] = container # Standard content creation else: # we want just a minimun viable object and set the data later obj = api.create(container, portal_type) # obj = api.create(container, portal_type, **data) except Unauthorized: fail(401, "You are not allowed to create this content") # Update the object with the given data, but omit the id try: update_object_with_data(obj, data) #start point except APIError: # Failure in creation process, delete the invalid object container.manage_delObjects(obj.id) # reraise the error raise return obj
def setup_baseline_data(portal): """Setups baseline data for testing purposes """ setup = portal.bika_setup client = _api.create(portal.clients, "Client", Name="Happy Hills", ClientID="HH") contact = _api.create(client, "Contact", Firstname="Rita", Lastname="Mohale") sample_type = _api.create(setup.bika_sampletypes, "SampleType", title="Water", Prefix="W") lab_contact = _api.create(setup.bika_labcontacts, "LabContact", Firstname="Lab", Lastname="Manager") department = _api.create(setup.bika_departments, "Department", title="Chemistry", Manager=lab_contact) category = _api.create(setup.bika_analysiscategories, "AnalysisCategory", title="Metals", Department=department) Cu = _api.create(setup.bika_analysisservices, "AnalysisService", title="Copper", Keyword="Cu", Category=category.UID()) Fe = _api.create(setup.bika_analysisservices, "AnalysisService", title="Iron", Keyword="Fe", Category=category.UID())
def action_add(self): """Form action to add a new attachment Code taken from bika.lims.content.addARAttachment. """ form = self.request.form parent = api.get_parent(self.context) this_file = form.get('AttachmentFile_file', None) # nothing to do if the attachment file is missing if this_file is None: logger.warn( "AttachmentView.action_add_attachment: Attachment file is missing" ) return # create attachment attachmentid = self.context.generateUniqueId('Attachment') attachment = api.create(parent, "Attachment", id=attachmentid) # update the attachment with the values from the form attachment.edit( AttachmentFile=this_file, AttachmentType=form.get('AttachmentType', ''), AttachmentKeys=form.get('AttachmentKeys', ''), ReportOption=form.get('ReportOption', 'a'), ) # process and reindex attachment.processForm() attachment.reindexObject() # append the new UID to the end of the current order self.set_attachments_order(api.get_uid(attachment)) # handle analysis attachment analysis_uid = form.get("Analysis", None) if analysis_uid: rc = api.get_tool("reference_catalog") analysis = rc.lookupObject(analysis_uid) others = analysis.getAttachment() attachments = [] for other in others: attachments.append(other.UID()) attachments.append(attachment.UID()) analysis.setAttachment(attachments) if api.get_workflow_status_of(analysis) == 'attachment_due': api.do_transition_for(analysis, 'attach') else: others = self.context.getAttachment() attachments = [] for other in others: attachments.append(other.UID()) attachments.append(attachment.UID()) self.context.setAttachment(attachments) if self.request['HTTP_REFERER'].endswith('manage_results'): self.request.response.redirect('{}/manage_results'.format( self.context.absolute_url())) else: self.request.response.redirect(self.context.absolute_url())