def __call__(self): form = self.request.form plone.protect.CheckAuthenticator(self.request.form) plone.protect.PostOnly(self.request.form) came_from = 'came_from' in form and form['came_from'] or 'add' wftool = getToolByName(self.context, 'portal_workflow') uc = getToolByName(self.context, 'uid_catalog') bsc = getToolByName(self.context, 'bika_setup_catalog') errors = {} form_parts = json.loads(self.request.form['parts']) # First make a list of non-empty columns columns = [] for column in range(int(form['col_count'])): name = 'ar.%s' % column ar = form.get(name, None) if ar and 'Analyses' in ar.keys(): columns.append(column) if len(columns) == 0: ajax_form_error(errors, message=t(_("No analyses have been selected"))) return json.dumps({'errors': errors}) # Now some basic validation required_fields = [ field.getName() for field in AnalysisRequestSchema.fields() if field.required ] for column in columns: formkey = "ar.%s" % column ar = form[formkey] # check that required fields have values for field in required_fields: # This one is still special. if field in ['RequestID']: continue # And these are not required if this is a secondary AR if ar.get('Sample', '') != '' and field in [ 'SamplingDate', 'SampleType' ]: continue if not ar.get(field, ''): ajax_form_error(errors, field, column) # Return errors if there are any if errors: return json.dumps({'errors': errors}) # Get the prices from the form data prices = form.get('Prices', None) # Initialize the Anlysis Request collection ARs = [] # if a new profile is created automatically, # this flag triggers the status message new_profile = None # The actual submission for column in columns: # Get partitions from the form data if form_parts: partitions = form_parts[str(column)] else: partitions = [] # Get the form data using the appropriate form key formkey = "ar.%s" % column values = form[formkey].copy() # resolved values is formatted as acceptable by archetypes # widget machines resolved_values = {} for k, v in values.items(): # Analyses, we handle that specially. if k == 'Analyses': continue # Insert the reference *_uid values instead of titles. if "_uid" in k: v = values[k] v = v.split(",") if v and "," in v else v fname = k.replace("_uid", "") resolved_values[fname] = v continue # we want to write the UIDs and ignore the title values if k + "_uid" in values: continue resolved_values[k] = values[k] # Get the analyses from the form data analyses = values["Analyses"] # Gather the specifications from the form specs = json.loads(form['copy_to_new_specs']).get(str(column), {}) if not specs: specs = json.loads(form['specs']).get(str(column), {}) if specs: specs = dicts_to_dict(specs, 'keyword') # Modify the spec with all manually entered values for service_uid in analyses: min_element_name = "ar.%s.min.%s" % (column, service_uid) max_element_name = "ar.%s.max.%s" % (column, service_uid) error_element_name = "ar.%s.error.%s" % (column, service_uid) service_keyword = bsc(UID=service_uid)[0].getKeyword if min_element_name in form: if service_keyword not in specs: specs[service_keyword] = {} specs[service_keyword]["keyword"] = service_keyword specs[service_keyword]["min"] = form[min_element_name] specs[service_keyword]["max"] = form[max_element_name] specs[service_keyword]["error"] = form[error_element_name] # Selecting a template sets the hidden 'parts' field to template values. # Selecting a profile will allow ar_add.js to fill in the parts field. # The result is the same once we are here. if not partitions: partitions = [{ 'services': [], 'container': None, 'preservation': '', 'separate': False }] # Apply DefaultContainerType to partitions without a container default_container_type = resolved_values.get( 'DefaultContainerType', None) if default_container_type: container_type = bsc(UID=default_container_type)[0].getObject() containers = container_type.getContainers() for partition in partitions: if not partition.get("container", None): partition['container'] = containers # Retrieve the catalogue reference to the client client = uc(UID=resolved_values['Client'])[0].getObject() # Create the Analysis Request ar = create_analysisrequest(client, self.request, resolved_values, analyses=analyses, partitions=partitions, specifications=specs.values(), prices=prices) # Add the created analysis request to the list ARs.append(ar.getId()) # Display the appropriate message after creation if len(ARs) > 1: message = _("Analysis requests ${ARs} were successfully created.", mapping={'ARs': safe_unicode(', '.join(ARs))}) else: message = _("Analysis request ${AR} was successfully created.", mapping={'AR': safe_unicode(ARs[0])}) self.context.plone_utils.addPortalMessage(message, 'info') # Automatic label printing # Won't print labels for Register on Secondary ARs new_ars = None if came_from == 'add': new_ars = [ar for ar in ARs if ar[-2:] == '01'] if 'register' in self.context.bika_setup.getAutoPrintStickers( ) and new_ars: return json.dumps({ 'success': message, 'stickers': new_ars, 'stickertemplate': self.context.bika_setup.getAutoStickerTemplate() }) else: return json.dumps({'success': message})
def __call__(self): form = self.request.form plone.protect.CheckAuthenticator(self.request.form) plone.protect.PostOnly(self.request.form) uc = getToolByName(self.context, 'uid_catalog') bsc = getToolByName(self.context, 'bika_setup_catalog') portal_catalog = getToolByName(self.context, 'portal_catalog') # Load the form data from request.state. If anything goes wrong here, # put a bullet through the whole process. try: states = json.loads(form['state']) except Exception as e: message = t(_('Badly formed state: ${errmsg}', mapping={'errmsg': e.message})) ajax_form_error(self.errors, message=message) return json.dumps({'errors': self.errors}) # Validate incoming form data required = [field.getName() for field in AnalysisRequestSchema.fields() if field.required] + ["Analyses"] # First remove all states which are completely empty; if all # required fields are not present, we assume that the current # AR had no data entered, and can be ignored nonblank_states = {} for arnum, state in states.items(): for key, val in state.items(): if val \ and "%s_hidden" % key not in state \ and not key.endswith('hidden'): nonblank_states[arnum] = state break # in valid_states, all ars that pass validation will be stored valid_states = {} for arnum, state in nonblank_states.items(): # Secondary ARs are a special case, these fields are not required if state.get('Sample', ''): if 'SamplingDate' in required: required.remove('SamplingDate') if 'SampleType' in required: required.remove('SampleType') # fields flagged as 'hidden' are not considered required because # they will already have default values inserted in them for fieldname in required: if fieldname + '_hidden' in state: required.remove(fieldname) missing = [f for f in required if not state.get(f, '')] # If there are required fields missing, flag an error if missing: msg = t(_('Required fields have no values: ' '${field_names}', mapping={'field_names': ', '.join(missing)})) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # This ar is valid! valid_states[arnum] = state # - Expand lists of UIDs returned by multiValued reference widgets # - Transfer _uid values into their respective fields for arnum in valid_states.keys(): for field, value in valid_states[arnum].items(): if field.endswith('_uid') and ',' in value: valid_states[arnum][field] = value.split(',') elif field.endswith('_uid'): valid_states[arnum][field] = value if self.errors: return json.dumps({'errors': self.errors}) # Now, we will create the specified ARs. ARs = [] for arnum, state in valid_states.items(): # Create the Analysis Request ar = crar( portal_catalog(UID=state['Client'])[0].getObject(), self.request, state ) ARs.append(ar.Title()) # Display the appropriate message after creation if len(ARs) > 1: message = _('Analysis requests ${ARs} were successfully created.', mapping={'ARs': safe_unicode(', '.join(ARs))}) else: message = _('Analysis request ${AR} was successfully created.', mapping={'AR': safe_unicode(ARs[0])}) self.context.plone_utils.addPortalMessage(message, 'info') # Automatic label printing won't print "register" labels for Secondary. ARs #This was a hack and is still a hack but will work more widely new_ars = [ar for ar in ARs if ar[-1] == '1'] if 'register' in self.context.bika_setup.getAutoPrintStickers() \ and new_ars: return json.dumps({ 'success': message, 'stickers': new_ars, 'stickertemplate': self.context.bika_setup.getAutoStickerTemplate() }) else: return json.dumps({'success': message})
def validate_form(self): form = self.request.form plone.protect.CheckAuthenticator(self.request.form) plone.protect.PostOnly(self.request.form) uc = getToolByName(self.context, 'uid_catalog') bsc = getToolByName(self.context, 'bika_setup_catalog') portal_catalog = getToolByName(self.context, 'portal_catalog') # Load the form data from request.state. If anything goes wrong here, # put a bullet through the whole process. try: states = json.loads(form['state']) except Exception as e: message = t( _('Badly formed state: ${errmsg}', mapping={'errmsg': e.message})) ajax_form_error(self.errors, message=message) return json.dumps({'errors': self.errors}) # Validate incoming form data required = [ field.getName() for field in AnalysisRequestSchema.fields() if field.required ] + ["Analyses"] # First remove all states which are completely empty; if all # required fields are not present, we assume that the current # AR had no data entered, and can be ignored nonblank_states = {} for arnum, state in states.items(): for key, val in state.items(): if val \ and "%s_hidden" % key not in state \ and not key.endswith('hidden'): nonblank_states[arnum] = state break # in valid_states, all ars that pass validation will be stored self.valid_states = {} for arnum, state in nonblank_states.items(): secondary = False # Secondary ARs are a special case, these fields are not required if state.get('Sample', ''): if 'SamplingDate' in required: required.remove('SamplingDate') if 'SampleType' in required: required.remove('SampleType') secondary = True # If this is not a Secondary AR, make sure that Sample Type UID is valid. This shouldn't # happen, but making sure just in case. else: st_uid = state.get('SampleType', None) if not st_uid or not bsc(portal_type='SampleType', UID=st_uid): msg = t(_("Not a valid Sample Type.")) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # checking if sampling date is not future if state.get('SamplingDate', ''): samplingdate = state.get('SamplingDate', '') try: samp_date = datetime.datetime.strptime( samplingdate.strip(), "%Y-%m-%d %H:%M") except ValueError: print traceback.format_exc() msg = \ "Bad time formatting: Getting '{}' but expecting an" \ " string with '%Y-%m-%d %H:%M' format." \ .format(samplingdate) ajax_form_error(self.errors, arnum=arnum, message=msg) continue today = date.today() if not secondary and today > samp_date.date(): msg = t(_("Expected Sampling Date can't be in the past")) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # If Sampling Date is not set, we are checking whether it is the user left it empty, # or it is because we have Sampling Workflow Disabled elif not self.context.bika_setup.getSamplingWorkflowEnabled(): # Date Sampled is required in this case date_sampled = state.get('DateSampled', '') if not date_sampled: msg = \ "Date Sampled Field is required." ajax_form_error(self.errors, arnum=arnum, message=msg) continue try: date_sampled = datetime.datetime.strptime( date_sampled.strip(), "%Y-%m-%d %H:%M") except ValueError: print traceback.format_exc() msg = \ "Bad time formatting: Getting '{}' but expecting an" \ " string with '%Y-%m-%d %H:%M' format." \ .format(date_sampled) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # fields flagged as 'hidden' are not considered required because # they will already have default values inserted in them for fieldname in required: if fieldname + '_hidden' in state: required.remove(fieldname) missing = [f for f in required if not state.get(f, '')] # If there are required fields missing, flag an error if missing: msg = t( _('Required fields have no values: ' '${field_names}', mapping={'field_names': ', '.join(missing)})) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # This ar is valid! self.valid_states[arnum] = state # - Expand lists of UIDs returned by multiValued reference widgets # - Transfer _uid values into their respective fields for arnum in self.valid_states.keys(): for field, value in self.valid_states[arnum].items(): if field.endswith('_uid') and ',' in value: self.valid_states[arnum][field] = value.split(',') elif field.endswith('_uid'): self.valid_states[arnum][field] = value
def __call__(self): form = self.request.form plone.protect.CheckAuthenticator(self.request.form) plone.protect.PostOnly(self.request.form) came_from = 'came_from' in form and form['came_from'] or 'add' wftool = getToolByName(self.context, 'portal_workflow') uc = getToolByName(self.context, 'uid_catalog') bsc = getToolByName(self.context, 'bika_setup_catalog') errors = {} form_parts = json.loads(self.request.form['parts']) # First make a list of non-empty columns columns = [] for column in range(int(form['col_count'])): name = 'ar.%s' % column ar = form.get(name, None) if ar and 'Analyses' in ar.keys(): columns.append(column) if len(columns) == 0: ajax_form_error(errors, message=t(_("No analyses have been selected"))) return json.dumps({'errors':errors}) # Now some basic validation required_fields = [field.getName() for field in AnalysisRequestSchema.fields() if field.required] for column in columns: formkey = "ar.%s" % column ar = form[formkey] # Secondary ARs don't have sample fields present in the form data # if 'Sample_uid' in ar and ar['Sample_uid']: # adapter = getAdapter(self.context, name='getWidgetVisibility') # wv = adapter().get('secondary', {}).get('invisible', []) # required_fields = [x for x in required_fields if x not in wv] # check that required fields have values for field in required_fields: # This one is still special. if field in ['RequestID']: continue # And these are not required if this is a secondary AR if ar.get('Sample', '') != '' and field in [ 'SamplingDate', 'SampleType' ]: continue if not ar.get(field, ''): ajax_form_error(errors, field, column) # Return errors if there are any if errors: return json.dumps({'errors': errors}) # Get the prices from the form data prices = form.get('Prices', None) # Initialize the Anlysis Request collection ARs = [] # if a new profile is created automatically, # this flag triggers the status message new_profile = None # The actual submission for column in columns: # Get partitions from the form data if form_parts: partitions = form_parts[str(column)] else: partitions = [] # Get the form data using the appropriate form key formkey = "ar.%s" % column values = form[formkey].copy() # resolved values is formatted as acceptable by archetypes # widget machines resolved_values = {} for k, v in values.items(): # Analyses, we handle that specially. if k == 'Analyses': continue if "%s_uid" % k in values: v = values["%s_uid" % k] if v and "," in v: v = v.split(",") resolved_values[k] = values["%s_uid" % k] else: resolved_values[k] = values[k] # Get the analyses from the form data analyses = values["Analyses"] # Gather the specifications from the form data # no defaults are applied here - the defaults should already be # present in the form data specifications = {} for analysis in analyses: for service_uid in analyses: min_element_name = "ar.%s.min.%s"%(column, service_uid) max_element_name = "ar.%s.max.%s"%(column, service_uid) error_element_name = "ar.%s.error.%s"%(column, service_uid) if min_element_name in form: specifications[service_uid] = { "min": form[min_element_name], "max": form[max_element_name], "error": form[error_element_name] } # Selecting a template sets the hidden 'parts' field to template values. # Selecting a profile will allow ar_add.js to fill in the parts field. # The result is the same once we are here. if not partitions: partitions = [{ 'services': [], 'container': None, 'preservation': '', 'separate': False }] # Apply DefaultContainerType to partitions without a container default_container_type = resolved_values.get( 'DefaultContainerType', None ) if default_container_type: container_type = bsc(UID=default_container_type)[0].getObject() containers = container_type.getContainers() for partition in partitions: if not partition.get("container", None): partition['container'] = containers # Retrieve the catalogue reference to the client client = uc(UID=resolved_values['Client'])[0].getObject() # Create the Analysis Request ar = create_analysisrequest( client, self.request, resolved_values, analyses, partitions, specifications, prices ) # Add the created analysis request to the list ARs.append(ar.getId()) # Display the appropriate message after creation if len(ARs) > 1: message = _("Analysis requests ${ARs} were successfully created.", mapping={'ARs': safe_unicode(', '.join(ARs))}) else: message = _("Analysis request ${AR} was successfully created.", mapping={'AR': safe_unicode(ARs[0])}) self.context.plone_utils.addPortalMessage(message, 'info') # Automatic label printing # Won't print labels for Register on Secondary ARs new_ars = None if came_from == 'add': new_ars = [ar for ar in ARs if ar[-2:] == '01'] if 'register' in self.context.bika_setup.getAutoPrintLabels() and new_ars: return json.dumps({ 'success': message, 'labels': new_ars, 'labelsize': self.context.bika_setup.getAutoLabelSize() }) else: return json.dumps({'success': message})
def validate_form(self): form = self.request.form plone.protect.CheckAuthenticator(self.request.form) plone.protect.PostOnly(self.request.form) uc = getToolByName(self.context, 'uid_catalog') bsc = getToolByName(self.context, 'bika_setup_catalog') portal_catalog = getToolByName(self.context, 'portal_catalog') # Load the form data from request.state. If anything goes wrong here, # put a bullet through the whole process. try: states = json.loads(form['state']) except Exception as e: message = t(_('Badly formed state: ${errmsg}', mapping={'errmsg': e.message})) ajax_form_error(self.errors, message=message) return json.dumps({'errors': self.errors}) # Validate incoming form data required = [field.getName() for field in AnalysisRequestSchema.fields() if field.required] + ["Analyses"] # First remove all states which are completely empty; if all # required fields are not present, we assume that the current # AR had no data entered, and can be ignored nonblank_states = {} for arnum, state in states.items(): for key, val in state.items(): if val \ and "%s_hidden" % key not in state \ and not key.endswith('hidden'): nonblank_states[arnum] = state break # in valid_states, all ars that pass validation will be stored self.valid_states = {} for arnum, state in nonblank_states.items(): secondary = False # Secondary ARs are a special case, these fields are not required if state.get('Sample', ''): if 'SamplingDate' in required: required.remove('SamplingDate') if 'SampleType' in required: required.remove('SampleType') secondary = True # If this is not a Secondary AR, make sure that Sample Type UID is valid. This shouldn't # happen, but making sure just in case. else: st_uid = state.get('SampleType', None) if not st_uid or not bsc(portal_type='SampleType', UID=st_uid): msg = t(_("Not a valid Sample Type.")) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # checking if sampling date is not future if state.get('SamplingDate', ''): samplingdate = state.get('SamplingDate', '') try: samp_date = datetime.datetime.strptime( samplingdate.strip(), "%Y-%m-%d %H:%M") except ValueError: print traceback.format_exc() msg = \ "Bad time formatting: Getting '{}' but expecting an" \ " string with '%Y-%m-%d %H:%M' format." \ .format(samplingdate) ajax_form_error(self.errors, arnum=arnum, message=msg) continue today = date.today() if not secondary and today > samp_date.date(): msg = t(_("Expected Sampling Date can't be in the past")) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # If Sampling Date is not set, we are checking whether it is the user left it empty, # or it is because we have Sampling Workflow Disabled elif not self.context.bika_setup.getSamplingWorkflowEnabled(): # Date Sampled is required in this case date_sampled = state.get('DateSampled', '') if not date_sampled: msg = \ "Date Sampled Field is required." ajax_form_error(self.errors, arnum=arnum, message=msg) continue try: date_sampled = datetime.datetime.strptime( date_sampled.strip(), "%Y-%m-%d %H:%M") except ValueError: print traceback.format_exc() msg = \ "Bad time formatting: Getting '{}' but expecting an" \ " string with '%Y-%m-%d %H:%M' format." \ .format(date_sampled) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # fields flagged as 'hidden' are not considered required because # they will already have default values inserted in them for fieldname in required: if fieldname + '_hidden' in state: required.remove(fieldname) missing = [f for f in required if not state.get(f, '')] # If there are required fields missing, flag an error if missing: msg = t(_('Required fields have no values: ' '${field_names}', mapping={'field_names': ', '.join(missing)})) ajax_form_error(self.errors, arnum=arnum, message=msg) continue # This ar is valid! self.valid_states[arnum] = state # - Expand lists of UIDs returned by multiValued reference widgets # - Transfer _uid values into their respective fields for arnum in self.valid_states.keys(): for field, value in self.valid_states[arnum].items(): if field.endswith('_uid') and ',' in value: self.valid_states[arnum][field] = value.split(',') elif field.endswith('_uid'): self.valid_states[arnum][field] = value
def __call__(self): form = self.request.form plone.protect.CheckAuthenticator(self.request.form) plone.protect.PostOnly(self.request.form) came_from = "came_from" in form and form["came_from"] or "add" wftool = getToolByName(self.context, "portal_workflow") uc = getToolByName(self.context, "uid_catalog") bsc = getToolByName(self.context, "bika_setup_catalog") errors = {} form_parts = json.loads(self.request.form["parts"]) # First make a list of non-empty columns columns = [] for column in range(int(form["col_count"])): name = "ar.%s" % column ar = form.get(name, None) if ar and "Analyses" in ar.keys(): columns.append(column) if len(columns) == 0: ajax_form_error(errors, message=t(_("No analyses have been selected"))) return json.dumps({"errors": errors}) # Now some basic validation required_fields = [field.getName() for field in AnalysisRequestSchema.fields() if field.required] for column in columns: formkey = "ar.%s" % column ar = form[formkey] # check that required fields have values for field in required_fields: # This one is still special. if field in ["RequestID"]: continue # And these are not required if this is a secondary AR if ar.get("Sample", "") != "" and field in ["SamplingDate", "SampleType"]: continue if not ar.get(field, ""): ajax_form_error(errors, field, column) # Return errors if there are any if errors: return json.dumps({"errors": errors}) # Get the prices from the form data prices = form.get("Prices", None) # Initialize the Anlysis Request collection ARs = [] # if a new profile is created automatically, # this flag triggers the status message new_profile = None # The actual submission for column in columns: # Get partitions from the form data if form_parts: partitions = form_parts[str(column)] else: partitions = [] # Get the form data using the appropriate form key formkey = "ar.%s" % column values = form[formkey].copy() # resolved values is formatted as acceptable by archetypes # widget machines resolved_values = {} for k, v in values.items(): # Analyses, we handle that specially. if k == "Analyses": continue # Insert the reference *_uid values instead of titles. if "_uid" in k: v = values[k] v = v.split(",") if v and "," in v else v fname = k.replace("_uid", "") resolved_values[fname] = v continue # we want to write the UIDs and ignore the title values if k + "_uid" in values: continue resolved_values[k] = values[k] # Get the analyses from the form data analyses = values["Analyses"] # Gather the specifications from the form specs = json.loads(form["copy_to_new_specs"]).get(str(column), {}) if not specs: specs = json.loads(form["specs"]).get(str(column), {}) if specs: specs = dicts_to_dict(specs, "keyword") # Modify the spec with all manually entered values for service_uid in analyses: min_element_name = "ar.%s.min.%s" % (column, service_uid) max_element_name = "ar.%s.max.%s" % (column, service_uid) error_element_name = "ar.%s.error.%s" % (column, service_uid) service_keyword = bsc(UID=service_uid)[0].getKeyword if min_element_name in form: if service_keyword not in specs: specs[service_keyword] = {} specs[service_keyword]["keyword"] = service_keyword specs[service_keyword]["min"] = form[min_element_name] specs[service_keyword]["max"] = form[max_element_name] specs[service_keyword]["error"] = form[error_element_name] # Selecting a template sets the hidden 'parts' field to template values. # Selecting a profile will allow ar_add.js to fill in the parts field. # The result is the same once we are here. if not partitions: partitions = [{"services": [], "container": None, "preservation": "", "separate": False}] # Apply DefaultContainerType to partitions without a container default_container_type = resolved_values.get("DefaultContainerType", None) if default_container_type: container_type = bsc(UID=default_container_type)[0].getObject() containers = container_type.getContainers() for partition in partitions: if not partition.get("container", None): partition["container"] = containers # Retrieve the catalogue reference to the client client = uc(UID=resolved_values["Client"])[0].getObject() # Create the Analysis Request ar = create_analysisrequest( client, self.request, resolved_values, analyses=analyses, partitions=partitions, specifications=specs.values(), prices=prices, ) # Add the created analysis request to the list ARs.append(ar.getId()) # Display the appropriate message after creation if len(ARs) > 1: message = _( "Analysis requests ${ARs} were successfully created.", mapping={"ARs": safe_unicode(", ".join(ARs))} ) else: message = _("Analysis request ${AR} was successfully created.", mapping={"AR": safe_unicode(ARs[0])}) self.context.plone_utils.addPortalMessage(message, "info") # Automatic label printing # Won't print labels for Register on Secondary ARs new_ars = None if came_from == "add": new_ars = [ar for ar in ARs if ar[-2:] == "01"] if "register" in self.context.bika_setup.getAutoPrintStickers() and new_ars: return json.dumps( { "success": message, "stickers": new_ars, "stickertemplate": self.context.bika_setup.getAutoStickerTemplate(), } ) else: return json.dumps({"success": message})