def mark_unfilled_fields_empty(interview_metadata_dict): """Given an interview metadata dictionary, transform any un-filled fields into DAEmpty()""" for field_dict in interview_metadata_dict.get( 'field_list', []) + interview_metadata_dict.get( 'built_in_fields_used', []): try: field = field_dict[ 'variable'] # Our list of fields is a dictionary except: continue # Make sure we don't try to define a method # Also, don't set any signatures to DAEmpty if not map_names(field).endswith( '.signature') and not '(' in map_names(field): if not defined(map_names(field)): define(map_names(field), '') # set to special Docassemble empty object #define(map_names(field), DAEmpty()) # set to special Docassemble empty object # Handle special case of an address that we skipped filling in on the form elif map_names(field).endswith('address.on_one_line()'): individual_name = map_names(field).partition('.on_one_line')[0] if not defined( individual_name + '.address' ): # here we're checking for an empty street address attribute define( individual_name, '' ) # at this point this should be something like user.address elif map_names(field).endswith('address.line_two()'): individual_name = map_names(field).partition('.line_two')[0] if not defined(individual_name + '.city'): define(individual_name, '')
def mark_unfilled_fields_empty(interview_metadata_dict): """Sets the listed fields that are not yet defined to an empty string. Requires an interview metadata dictionary as input parameter. Aid for filling in a PDF. This will not set ALL fields in the interview empty; only ones mentiond in the specific metadata dict.""" # There are two dictionaries in the interview-specific metadata that list fields # fields and built_in_fields used. Some older interviews may use `field_list` # We loop over each field and check if it's already defined in the Docassemble interview's namespace # If it isn't, we set it to an empty string. for field_dict in interview_metadata_dict[ 'field_list'] + interview_metadata_dict[ 'built_in_fields_used'] + interview_metadata_dict['fields']: try: field = field_dict[ 'variable'] # Our list of fields is a dictionary except: continue # Make sure we don't try to define a method # Also, don't set any signatures to DAEmpty # This will not work on a method call, other than the 3 we explicitly handle: # address.line_two(), address.on_one_line(), and address.block() # Empty strings will break this if field and not map_names(field).endswith( '.signature') and not '(' in map_names(field): if not defined(map_names(field)): define(map_names(field), '') # set to an empty string #define(map_names(field), 'DAEmpty()') # set to special Docassemble empty object. Should work in DA > 1.1.4 # Handle special case of an address that we skipped filling in on the form elif map_names(field).endswith('address.on_one_line()'): address_obj_name = map_names(field).partition('.on_one_line')[0] if not defined( address_obj_name + '.address' ): # here we're checking for an empty street address attribute # define(individual_name, '') # at this point this should be something like user.address try: exec(address_obj_name + "= DAEmpty()") except: pass # define(address_obj_name, DAEmpty()) elif map_names(field).endswith('address.line_two()'): address_obj_name = map_names(field).partition('.line_two')[0] if not defined(address_obj_name + '.city' ): # We check for an undefined city attribute try: exec(address_obj_name + "= DAEmpty()") except: pass elif map_names(field).endswith('address.block()'): address_obj_name = map_names(field).partition('.block')[0] if not defined(address_obj_name + '.address' ): # We check for an undefined street address try: exec(address_obj_name + "= DAEmpty()") except: pass
def space(var_name, prefix=' ', suffix=''): """If the value as a string is defined, return it prefixed/suffixed. Defaults to prefix of a space. Helps build a sentence with less cruft. Equivalent to SPACE function in HotDocs.""" if defined(var_name): return prefix + showifdef(var_name) + suffix else: return ''
def space(var_name, prefix=' ', suffix=''): """If the value as a string is defined, return it prefixed/suffixed. Defaults to prefix of a space. Helps build a sentence with less cruft. Equivalent to SPACE function in HotDocs.""" if var_name and isinstance(var_name, str) and re.search( r'[A-Za-z][A-Za-z0-9\_]*', var_name) and defined(var_name) and value(var_name): return prefix + showifdef(var_name) + suffix else: return ''
def new_entry(name="", court_name="", court_emails=dict(), files=[]) -> str: """ Creates a new upload entry in the database Args: name (str): the name of who is completing the form doc_name (str): the name of the document court_name (str): the name of the court to file file_path (str): the path of the assembled file (on disk) Returns (str): A unique ID corresponding to the current submission """ if court_name not in court_emails: # in our system, this should never happen, but will leave in for debugging raise ValueError(f"Court {court_name} does not exist") connection = connect(**db_config) submission_id = None with connection.cursor() as cursor: # create a new interview submission cursor.execute( "INSERT INTO interviews (timestamp, name, court_name, user_id) VALUES (%s, %s, %s, %s) RETURNING id", (datetime.now(), name, court_name, get_user_id())) submission_id = cursor.fetchone()[0] # save the file metadata (NOT the files themselves) for file in files: sensitive = defined("file.sensitive") and file.sensitive cursor.execute( "INSERT INTO files (number, filename, mimetype, sensitive, submission_id) VALUES (%s, %s, %s, %s, %s)", (file.number, file.filename, file.mimetype, sensitive, submission_id)) connection.commit() connection.close() return str(submission_id)
def optional(field: str): """Returns the value of the field, if it exists, otherwise empty""" return DAEmpty() if not defined(field) else value(field)
def set_attribute_to_value(field_list, object_type, attribute, target_value=DAEmpty()): """If any item in the list matches object_type, set the specified attribute to DAEmpty() or other value desired""" for field in field_list: if defined(field) and isinstance(value(field), object_type): define(field + '.' + attribute, target_value)
def question_id(message): if defined("debug_enabled") and debug_enabled: return "[" + message + "] " else: return ""
def send_attachments(name="", court_name="", court_emails=dict(), files=[], submission_id="") -> bool: """ Sends one or nore non-sensitive applications and submission info to the email of the court, court_name The email includes the user's name, submission id, and a list of non-sensitive forms. If there are any sensitive forms in the files list, they will not be sent. Instead, the recipient will be instructed to access the submission on our own site. Args: name (str): the name of the submitter court_name (str): the name of the court that should be receiving this email court_emails (dict): a dictionary mapping court names to emails files (List[DAFile]): a list of DAFiles (possibly sensitive) to be sent submission_id (str): the unique id for this submission Raises: ValueError if court_name is not in the court_emails dict Returns (bool): True if the email was sent successfully, false otherwise """ if court_name not in court_emails: # in our system, this should never happen, but will leave in for debugging raise ValueError(f"Court {court_name} does not exist") attachments = [ file for file in files if not defined("file.sensitive") or not file.sensitive ] court_email = court_emails[court_name] filenames = [file.filename for file in attachments] filenames_str = "\n".join(filenames) submission_url = url_for_submission(id=submission_id) if len(attachments) != len(files): if len(attachments) == 0: body = dedent(f""" Dear {court_name}: {name} has submitted {len(files)} online. However, these file(s) have sensitive information, and will not be sent over email. Please access these forms with the following submission id: {submission_url}. """) attachments = None else: body = dedent(f""" Dear {court_name}: You are receiving {len(attachments)} files from {name}: {filenames_str} However, there are also {len(files) - len(attachments)} forms which are sensitive that will not be sent over email. Please access these forms with the following submission id: {submission_url}. """) else: body = dedent(f""" Dear {court_name}: You are receiving {len(attachments)} files from {name}: {filenames_str} The reference ID for these forms is {submission_url}. """) return send_email(to=court_email, subject=f"Online form submission {submission_id}", body=body, attachments=attachments)