def update_sample(content, record): """ Custom code for updating a sample because of special requirements for storage location and sample type. :param content: The sample object that has to be modified :param record: This object has a dictionary, items, that has the values that are to be changed. :return: The updated sample object """ # set and unset the storage locations for k, v in record.items(): if k == 'StorageLocation': storage_location_results = search(portal_type='StoragePosition', Title=v) if not storage_location_results: storage_location_results = search( portal_type='StoragePosition', uid=v) storage_location = storage_location_results and get_object( storage_location_results[0]) or None wf_tool = get_tool("portal_workflow") location_status = wf_tool.getStatusOf( 'bika_storageposition_workflow', storage_location) if location_status and location_status.get("review_state", None) == "available": current_location = content.getStorageLocation() if current_location: doActionFor(current_location, 'liberate') # assign the sample to the storage location content.setStorageLocation(storage_location) sample_status = wf_tool.getStatusOf('bika_sample_workflow', content) if sample_status and sample_status.get( "review_state", None) == "sample_received": doActionFor(storage_location, 'occupy') else: doActionFor(storage_location, 'reserve') if k == 'SampleType': sample_type_results = search(portal_type="SampleType", title=v) if not sample_type_results: sample_type_results = search(portal_type="SampleType", uid=v) sample_type = sample_type_results and get_object( sample_type_results[0]) or None if isinstance(sample_type, tuple): sample_type = sample_type[0] content.setSampleType(sample_type) return content
def create_project(container, portal_type, **data): """ Create a project via API """ container = get_object(container) title = data.get("title", "") if not title: fail(404, "Title is required.") obj = bika_create_object(container, portal_type, **data) st_titles = data.get("SampleType", "") st_uids = [] if st_titles and type(st_titles) is list: for st_title in st_titles: brains = search(portal_type="SampleType", title=st_title) if brains: st_uids.append(brains[0].UID) if st_uids: obj.setSampleType(st_uids) return obj
def create_sample(container, **data): """ create a sample from here that doesnt go via api create :param container: :param data: :return: Sample object """ container = get_object(container) request = req.get_request() # we need to resolve the SampleType to a full object sample_type = data.get("SampleType", None) if sample_type is None: fail(400, "Please provide a SampleType") # TODO We should handle the same values as in the DataManager for this field # (UID, path, objects, dictionaries ...) sample_type_results = search(portal_type="SampleType", title=sample_type) if not sample_type_results: sample_type_results = search(portal_type="SampleType", uid=sample_type) # StorageLocation storage_location = data.get("StorageLocation", None) if storage_location is None: fail(400, "Please provide a StorageLocation") linked_sample_list = search(portal_type="Sample", title=data.get('LinkedSample', '')) linked_sample = linked_sample_list and linked_sample_list[0].getObject( ) or None try: volume = str(data.get('Volume')) float_volume = float(volume) if not float_volume: fail(400, "Please provide a correct Volume") except: raise # TODO We should handle the same values as in the DataManager for this field # (UID, path, objects, dictionaries ...) storage_location_results = search(portal_type='StoragePosition', Title=storage_location) if not storage_location_results: storage_location_results = search(portal_type='StoragePosition', uid=storage_location) # set the values and call the create function values = { "title": data.get('title', ''), "description": data.get("description", ""), "Project": container, #because the container is in fact the project this sample belongs to. "AllowSharing": data.get('AllowSharing', 0), "StorageLocation": storage_location_results and get_object(storage_location_results[0]) or None, "SampleType": sample_type_results and get_object(sample_type_results[0]) or None, "SubjectID": data.get("SubjectID", ""), "Barcode": data.get("Barcode", ""), "Volume": volume, "Unit": data.get("Unit", ""), "LinkedSample": linked_sample, "DateCreated": data.get("DateCreated", ""), } api_source = data.get('APISource', None) if api_source: values['APISource'] = api_source return create_smp(container, request, values)
def create_storage(container, portal_type, **data): """ Create a storage unit and (un-)managed storage via API """ def set_inputs_into_schema(instance, temperature, department, unit_type): # Set field values across each object if possible schema = instance.Schema() if temperature and 'Temperature' in schema: instance.Schema()['Temperature'].set(instance, temperature) if department and 'Department' in schema: instance.Schema()['Department'].set(instance, department) if unit_type and 'UnitType' in schema: instance.Schema()['UnitType'].set(instance, unit_type) def set_storage_types(instance, storage_interfaces): schema = instance.Schema() if storage_interfaces and 'StorageTypes' in schema: instance.Schema()['StorageTypes'].set(instance, storage_interfaces) for storage_interface in storage_interfaces: inter = resolve(storage_interface) alsoProvides(instance, inter) container = get_object(container) # variables for storage unit department_title = data.get("department", "") temperature = data.get("temperature", "") unit_type = data.get("unit_type", "") department = None if container.portal_type == "StorageUnit": department = container.getDepartment() temperature = container.getTemperature() else: brains = search(portal_type="Department", title=department_title) if not brains: department = brains[0].getObject() # variables for managed storage if portal_type == "ManagedStorage": number_positions = data.get("number_positions", "") x_axis = data.get("x_axis", "") y_axis = data.get("y_axis", "") try: x_axis = x_axis and int(x_axis) or '' y_axis = y_axis and int(y_axis) or '' number_positions = number_positions and int(number_positions) or '' except ValueError: fail(401, "Number positions, X axis and Y axis must be integers.") if not number_positions or not x_axis or not y_axis: fail( 400, "Number positions, X axis and Y axis are required to create storage positions." ) # common variables prefix = data.get("prefix", "") leading_zeros = data.get("leading_zeros", "") if not prefix or not leading_zeros: fail( 400, "Prefix and leading_zeros are required to construct storage unit title and Id." ) number_items = data.get("number_items", "") try: number_items = number_items and int(number_items) or 1 except ValueError: fail(401, "Number items must be integer.") seq_start = data.get("seq_start", "") try: seq_start = seq_start and int(seq_start) or 1 except ValueError: fail(401, "Id sequence start must be integer.") sequence = range(seq_start, seq_start + number_items) units = [] for x in sequence: id_obj = prefix + '-' + str(x).zfill(len(leading_zeros) + 1) title_obj = prefix + ' ' + str(x).zfill(len(leading_zeros) + 1) instance = api.content.create(container=container, type=portal_type, id=id_obj, title=title_obj) if instance.portal_type == "StorageUnit": set_inputs_into_schema(instance, temperature, department, unit_type) elif instance.portal_type == "UnmanagedStorage": set_storage_types(instance, ["baobab.lims.interfaces.IStockItemStorage"]) elif instance.portal_type == "ManagedStorage": instance.setXAxis(x_axis) instance.setYAxis(y_axis) set_storage_types( instance, ["baobab.lims.interfaces.ISampleStorageLocation"]) positions = storage_positions(instance, number_positions) for position in positions: set_storage_types( position, ["baobab.lims.interfaces.ISampleStorageLocation"]) position.reindexObject() instance.reindexObject() units.append(instance) return units
def set(self, instance, value, **kw): # noqa """Set the value of the refernce field """ ref = [] # The value is an UID if api.is_uid(value): ref.append(api.get_object_by_uid(value)) # The value is already an object if api.is_at_content(value): ref.append(value) # The value is a dictionary # -> handle it like a catalog query if u.is_dict(value): results = api.search(portal_type=self.allowed_types, **value) ref = map(api.get_object, results) # The value is a list if u.is_list(value): for item in value: # uid if api.is_uid(item): ref.append(api.get_object_by_uid(item)) continue # object if api.is_at_content(item): ref.append(api.get_object(item)) continue # path if api.is_path(item): ref.append(api.get_object_by_path(item)) continue # dict (catalog query) if u.is_dict(item): results = api.search(portal_type=self.allowed_types, **item) objs = map(api.get_object, results) ref.extend(objs) continue # Plain string # -> do a catalog query for title if isinstance(item, basestring): results = api.search(portal_type=self.allowed_types, title=item) objs = map(api.get_object, results) ref.extend(objs) continue # The value is a physical path if api.is_path(value): ref.append(api.get_object_by_path(value)) # Handle non multi valued fields if not self.multi_valued and len(ref) > 1: raise ValueError("Multiple values given for single valued field {}" .format(self.field)) return self._set(instance, ref, **kw)
def set(self, instance, value, **kw): # noqa """Set the value of the refernce field """ ref = [] # The value is an UID if api.is_uid(value): ref.append(api.get_object_by_uid(value)) # The value is already an object if api.is_at_content(value): ref.append(value) # The value is a dictionary # -> handle it like a catalog query if u.is_dict(value): results = api.search(portal_type=self.allowed_types, **value) ref = map(api.get_object, results) # The value is a list if u.is_list(value): for item in value: # uid if api.is_uid(item): ref.append(api.get_object_by_uid(item)) continue # object if api.is_at_content(item): ref.append(api.get_object(item)) continue # path if api.is_path(item): ref.append(api.get_object_by_path(item)) continue # dict (catalog query) if u.is_dict(item): results = api.search(portal_type=self.allowed_types, **item) objs = map(api.get_object, results) ref.extend(objs) continue # Plain string # -> do a catalog query for title if isinstance(item, basestring): results = api.search(portal_type=self.allowed_types, title=item) objs = map(api.get_object, results) ref.extend(objs) continue # The value is a physical path if api.is_path(value): ref.append(api.get_object_by_path(value)) # Handle non multi valued fields if not self.multi_valued and len(ref) > 1: raise ValueError( "Multiple values given for single valued field {}".format( self.field)) return self._set(instance, ref, **kw)