def share(): """ Show the list of desk to with the item can be push """ item = application.getItemByUUID(request.args(0)) if item is None: raise HTTP(404) query = (db.desk.id != session.desk_id) query &= auth.accessible_query('push_items', db.desk) posible_desk = db(query).select() fld_to_desk = Field('to_desk', 'integer') fld_to_desk.label = T("Push to organization desk") fld_to_desk.comment = T("Select where to push the item") fld_to_desk.requires = IS_EMPTY_OR( IS_IN_SET([(desk.id, desk.name) for desk in posible_desk])) fld_personal_desk = Field('to_person_desk', 'integer') fld_personal_desk.label = T("Push to other person desk") fld_personal_desk.comment = T("Select a person from the list.") # list of person on orgs persons = [] # search up all the persons orgs = db(db.organization.users.contains(auth.user.id)).select() for org in orgs: x = [db.auth_user(id=y) for y in org.users if y != auth.user.id] persons.extend(x) persons = list(set(persons)) fld_personal_desk.requires = IS_EMPTY_OR( IS_IN_SET([(per.id, "{} {}".format(per.first_name, per.last_name)) for per in persons])) fld_cond = Field('cond', 'boolean', default=False) fld_cond.label = T('To other person?') form = SQLFORM.factory(fld_to_desk, fld_personal_desk, fld_cond, submit_button=T("Send"), table_name='share') if form.process().accepted: src = session.desk_id if form.vars.cond: # send the item to other user other_user = db.auth_user(form.vars.to_person_desk) target = application.getUserDesk(other_user).id else: # send the item to the selected desk target = form.vars.to_desk if target: ct = application.getContentType(item.item_type) ct.shareItem(item.unique_id, src, target) response.js = "$('#metaModal').modal('hide');" response.flash = None return locals()
def define_tables(self,db,migrate): from gluon import current logging.debug('defining tables (migrate=%s)' % migrate) now = datetime.datetime.now() db.define_table( 'scheduler_task', Field('application_name',requires=IS_NOT_EMPTY(), default=None,writable=False), Field('task_name',requires=IS_NOT_EMPTY()), Field('group_name',default='main',writable=False), Field('status',requires=IS_IN_SET(TASK_STATUS), default=QUEUED,writable=False), Field('function_name', requires=IS_IN_SET(sorted(self.tasks.keys()))), Field('args','text',default='[]',requires=TYPE(list)), Field('vars','text',default='{}',requires=TYPE(dict)), Field('enabled','boolean',default=True), Field('start_time','datetime',default=now), Field('next_run_time','datetime',default=now), Field('stop_time','datetime',default=now+datetime.timedelta(days=1)), Field('repeats','integer',default=1,comment="0=unlimted"), Field('period','integer',default=60,comment='seconds'), Field('timeout','integer',default=60,comment='seconds'), Field('times_run','integer',default=0,writable=False), Field('last_run_time','datetime',writable=False,readable=False), Field('assigned_worker_name',default='',writable=False), migrate=migrate,format='%(task_name)s') if hasattr(current,'request'): db.scheduler_task.application_name.default=current.request.application db.define_table( 'scheduler_run', Field('scheduler_task','reference scheduler_task'), Field('status',requires=IS_IN_SET(RUN_STATUS)), Field('start_time','datetime'), Field('stop_time','datetime'), Field('output','text'), Field('result','text'), Field('traceback','text'), Field('worker_name',default=self.worker_name), migrate=migrate) db.define_table( 'scheduler_worker', Field('worker_name'), Field('first_heartbeat','datetime'), Field('last_heartbeat','datetime'), Field('status',requires=IS_IN_SET(WORKER_STATUS)), migrate=migrate) db.commit()
def customise_hms_hospital_resource(r, tablename): if r.representation == "geojson": # Don't represent the facility_status as numbers are smaller to xmit current.s3db.hms_status.facility_status.represent = None return # Limit options to just those used & relabel them for context hms_facility_type_opts = { 1: T("Hospital"), #2: T("Field Hospital"), #3: T("Specialized Hospital"), #11: T("Health center"), #12: T("Health center with beds"), #13: T("Health center without beds"), #21: T("Dispensary"), #31: T("Long-term care"), #41: T("Emergency Treatment Centre"), 41: T("ETC"), 42: T("Triage"), 43: T("Holding Center"), 44: T("Transit Center"), #98: T("Other"), #99: T("Unknown"), } hms_facility_status_opts = { #1: T("Normal"), 1: T("Functioning"), #2: T("Compromised"), #3: T("Evacuating"), 4: T("Closed"), 5: T("Pending"), #99: T("No Response") } from gluon import IS_EMPTY_OR, IS_IN_SET s3db = current.s3db NONE = current.messages["NONE"] field = s3db.hms_hospital.facility_type field.represent = lambda opt: hms_facility_type_opts.get(opt, NONE) field.requires = IS_EMPTY_OR(IS_IN_SET(hms_facility_type_opts)) field = s3db.hms_status.facility_status field.represent = lambda opt: hms_facility_status_opts.get(opt, NONE) field.requires = IS_EMPTY_OR(IS_IN_SET(hms_facility_status_opts))
def share(): """ Show the list of desk to with the item can be push """ item = application.getItemByUUID(request.args(0)) if item is None: raise HTTP(404) query = (db.desk.id != session.desk_id) query &= auth.accessible_query('push_items', db.desk) posible_desk = db(query).select() fld_to_desk = Field('to_desk', 'integer') fld_to_desk.label = T("Push to") fld_to_desk.comment = T("Select where to push the item") fld_to_desk.requires = IS_IN_SET([(desk.id, desk.name) for desk in posible_desk]) form = SQLFORM.factory(fld_to_desk, submit_button=T("Send"), table_name='share') if form.process().accepted: # send the item to the selected desk ct = application.getContentType(item.item_type) ct.shareItem(item.unique_id, session.desk_id, form.vars.to_desk) response.js = "$('#metaModal').modal('hide');" return locals()
def customise_pr_contact_resource(r, tablename): table = current.s3db.pr_contact field = table.contact_description field.readable = field.writable = False field = table.value field.label = current.T("Number or Address") field = table.contact_method from gluon import IS_IN_SET all_opts = current.msg.CONTACT_OPTS subset = ( "SMS", "EMAIL", "HOME_PHONE", "WORK_PHONE", "FACEBOOK", "TWITTER", "SKYPE", "OTHER", ) contact_methods = [(k, all_opts[k]) for k in subset if k in all_opts] field.requires = IS_IN_SET(contact_methods, zero=None) field.default = "SMS"
def customise_dc_question_resource(r, tablename): from gluon import IS_IN_SET from s3 import S3Represent, S3SQLCustomForm crud_form = S3SQLCustomForm((T("Type"), "field_type"), (T("Question"), "name"), (T("Make question mandatory"), "require_not_empty"), (T("Choices"), "options"), (T("Add graphic"), "file"), ) type_opts = {1: T("Text box"), 2: T("Number question"), 6: T("Multiple choice question"), 12: T("Likert-scale"), 13: T("Heatmap"), } s3db = current.s3db table = s3db.dc_question table.field_type.represent = S3Represent(options=type_opts) table.field_type.requires = IS_IN_SET(type_opts) table.require_not_empty.comment = None s3db.configure("dc_question", crud_form = crud_form, list_fields = [(T("Type"), "field_type"), (T("Question"), "name"), (T("Mandatory"), "require_not_empty"), ] )
def grid(db): """ Return an SQLFORM.grid to manage poems. """ createargs = editargs = viewargs = { 'fields': ['chapter', 'published', 'intro_hanzi', 'intro_en'] } fields = [ db.poem.chapter, db.poem.published, db.poem.intro_hanzi, db.poem.intro_en ] maxtextlengths = {'poem.published': 50} onupdate = lambda form: decache(int(form.vars.chapter), db) db.poem.published.represent = lambda value, row: value.strftime(date_format ) db.poem.chapter.requires = IS_IN_SET(range(1, 82), zero=None) grid = SQLFORM.grid(db.poem, createargs=createargs, csv=False, editargs=editargs, fields=fields, maxtextlengths=maxtextlengths, oncreate=onupdate, onupdate=onupdate, orderby=db.poem.chapter, paginate=None, searchable=False, viewargs=viewargs) return grid
def meta(): """ Edit/Show item metadata info """ item = application.getItemByUUID(request.args(0)) if item is None: raise HTTP(404) contentType = application.getContentType(item.item_type) l_names = [(r.language_tag, r.english_name) for r in db( db.languages.id > 0).select(orderby=db.languages.english_name)] db.item.language_tag.requires = IS_IN_SET(l_names, zero=None) # issue #5 hidde some fields from metadata db.item.provider.readable = False db.item.provider.writable = False db.item.provider_service.readable = False db.item.provider_service.writable = False db.item.copyright_holder.readable = False db.item.copyright_holder.writable = False db.item.copyright_url.readable = False db.item.copyright_url.writable = False db.item.copyright_notice.readable = False db.item.copyright_notice.writable = False db.item.pubstatus.readable = False db.item.pubstatus.writable = False form = SQLFORM(db.item, record=item) if form.process().accepted: # session.flash = "Done !" # send an email to all the users who has access to this item application.notifyChanges(item.unique_id) application.indexItem(item.unique_id) if request.ajax: response.js = "$('#metaModal').modal('hide');" else: redirect(application.getItemURL(item.unique_id)) return locals()
def bulk_update(): """ Controller function to perform a programmatic update to a field in one table. """ response = current.response db = current.db myrecs = None form = SQLFORM.factory(Field('table', requires=IS_IN_SET(db.tables)), Field('field'), Field('query'), Field('new_value')) if form.process().accepted: query = eval(form.vars.query) try: recs = db(query) recs.update(**{form.vars.field: form.vars.new_value}) myrecs = recs.select() response.flash = 'update succeeded' except Exception: print traceback.format_exc(5) elif form.errors: myrecs = BEAUTIFY(form.errors) response.flash = 'form has errors' return form, myrecs
def customise_proc_order_resource(r, tablename): """ @ToDo: Explanatory Text Javascript to total price client-side (pass details to JS from controller rather than hardcoding in the JS) onaccept to total price server-side (avoid hacking) Redirect to the Payments page (PayPal currently) Later: Instance Size Instance Location Order in different Currencies """ from gluon import IS_IN_SET from s3 import S3SQLCustomForm, S3Represent s3db = current.s3db # Filtered components s3db.add_components(tablename, proc_order_tag = ({"name": "term", "joinby": "order_id", "filterby": {"tag": "term"}, "multiple": False, }, {"name": "hours", "joinby": "order_id", "filterby": {"tag": "hours"}, "multiple": False, }, {"name": "hours_free", "joinby": "order_id", "filterby": {"tag": "hours_free"}, "multiple": False, }, ), ) # Individual settings for specific tag components components_get = s3db.resource(tablename).components.get get_vars_get = r.get_vars.get service_only = get_vars_get("service") if service_only: hours_default = 10 hours_options = {10: "10 Hours. USD 750", 40: "40 Hours. USD 2880", 80: "80 Hours. USD 5600", } else: term_options = {"MO": T("Monthly. USD 50"), "YR": T("Annual. USD 500"), } term_default = get_vars_get("term", "YR") term = components_get("term") f = term.table.value f.default = term_default f.represent = S3Represent(options = term_options) f.requires = IS_IN_SET(term_options, zero=None) hours_default = 0 hours_options = {0: "0", 10: "10. +USD 750", # Basic Branding, Minor Modifications 40: "40. +USD 2880", # Full Branding, Multiple Modifications 80: "80. +USD 5600", # Significant Customisation } hours = components_get("hours") f = hours.table.value f.default = hours_default f.represent = S3Represent(options = hours_options) f.requires = IS_IN_SET(hours_options, zero=None) if service_only: crud_form = S3SQLCustomForm((T("Service Hours"), "hours.value"), (T("Or Enter Manually"), "hours_free.value"), # Hide by default ) else: crud_form = S3SQLCustomForm((T("Term"), "term.value"), (T("Service Hours"), "hours.value"), ) current.response.s3.crud.submit_button = "Order" s3db.configure(tablename, crud_form = crud_form, ) # Add custom callback (& keep default) s3db.add_custom_callback(tablename, "create_onaccept", proc_order_create_onaccept, )
def define_tables(self, db, migrate): from gluon.dal import DEFAULT logger.debug('defining tables (migrate=%s)', migrate) now = self.now db.define_table('scheduler_task', Field('application_name', requires=IS_NOT_EMPTY(), default=None, writable=False), Field('task_name', default=None), Field('group_name', default='main'), Field('status', requires=IS_IN_SET(TASK_STATUS), default=QUEUED, writable=False), Field('function_name', requires=IS_IN_SET(sorted(self.tasks.keys())) if self.tasks else DEFAULT), Field('uuid', length=255, requires=IS_NOT_IN_DB(db, 'scheduler_task.uuid'), unique=True, default=web2py_uuid), Field('args', 'text', default='[]', requires=TYPE(list)), Field('vars', 'text', default='{}', requires=TYPE(dict)), Field('enabled', 'boolean', default=True), Field('start_time', 'datetime', default=now, requires=IS_DATETIME()), Field('next_run_time', 'datetime', default=now), Field('stop_time', 'datetime'), Field('repeats', 'integer', default=1, comment="0=unlimited", requires=IS_INT_IN_RANGE(0, None)), Field('retry_failed', 'integer', default=0, comment="-1=unlimited", requires=IS_INT_IN_RANGE(-1, None)), Field('period', 'integer', default=60, comment='seconds', requires=IS_INT_IN_RANGE(0, None)), Field('prevent_drift', 'boolean', default=False, comment='Cron-like start_times between runs'), Field('timeout', 'integer', default=60, comment='seconds', requires=IS_INT_IN_RANGE(0, None)), Field('sync_output', 'integer', default=0, comment="update output every n sec: 0=never", requires=IS_INT_IN_RANGE(0, None)), Field('times_run', 'integer', default=0, writable=False), Field('times_failed', 'integer', default=0, writable=False), Field('last_run_time', 'datetime', writable=False, readable=False), Field('assigned_worker_name', default='', writable=False), on_define=self.set_requirements, migrate=self.__get_migrate('scheduler_task', migrate), format='%(task_name)s') db.define_table('scheduler_run', Field('task_id', 'reference scheduler_task'), Field('status', requires=IS_IN_SET(RUN_STATUS)), Field('start_time', 'datetime'), Field('stop_time', 'datetime'), Field('run_output', 'text'), Field('run_result', 'text'), Field('traceback', 'text'), Field('worker_name', default=self.worker_name), migrate=self.__get_migrate('scheduler_run', migrate)) db.define_table('scheduler_worker', Field('worker_name', length=255, unique=True), Field('first_heartbeat', 'datetime'), Field('last_heartbeat', 'datetime'), Field('status', requires=IS_IN_SET(WORKER_STATUS)), Field('is_ticker', 'boolean', default=False, writable=False), Field('group_names', 'list:string', default=self.group_names), migrate=self.__get_migrate('scheduler_worker', migrate)) if migrate is not False: db.commit()
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False s3db = current.s3db if r.interactive or r.representation == "aadata": if r.vars.get("location.level__ne"): s3.crud_strings["gis_location"] = Storage( title_list=T("Administrative Areas"), ) else: s3.crud_strings["gis_location"] = Storage( #label_create = T("Record Disaster"), #title_display = T("Disaster Details"), title_list=T("Locations")) # Remove level column & filter list_fields = s3db.get_config("gis_location", "list_fields") list_fields.remove("level") filter_widgets = s3db.get_config("gis_location", "filter_widgets") # NB Fragile: dependent on filters defined in gis/location controller filter_widgets.pop(1) if r.method == "import": l10n_languages = settings.L10n.languages l10n_languages["ky"] = "Kyrgyz" l10n_languages["ru"] = "Russian" l10n_languages["hy"] = "Armenian" l10n_languages["az"] = "Azerbaijani" l10n_languages["ka"] = "Georgian" l10n_languages["kk"] = "Kazakh" l10n_languages["tg"] = "Tajik" l10n_languages["tk"] = "Turkmen" l10n_languages["uk"] = "Ukraine" l10n_languages["uz"] = "Uzbek" from gluon import IS_IN_SET s3db.gis_location_name.language.requires = IS_IN_SET( l10n_languages) else: table = s3db.gis_location # Custom filtered components for custom list_fields s3db.add_components( "gis_location", gis_location_name={ "name": "name_ru", "joinby": "location_id", "filterby": "language", "filterfor": ("ru", ), }, gis_location_tag=( { "name": "pcode", "joinby": "location_id", "filterby": "tag", "filterfor": ("PCode", ), }, { "name": "lat_lon_source", "joinby": "location_id", "filterby": "tag", "filterfor": ("LatLon Source", ), }, { "name": "lat_lon_date", "joinby": "location_id", "filterby": "tag", "filterfor": ("LatLon Date", ), }, ), ) from s3 import S3MultiSelectWidget, S3SQLCustomForm, S3SQLInlineComponent table.parent.widget = S3MultiSelectWidget(multiple=False) crud_form = S3SQLCustomForm( "name", #"name_ru.name_l10n", S3SQLInlineComponent( "name_ru", label=T("Russian Name"), multiple=False, fields=[("", "name_l10n")], ), "level", S3SQLInlineComponent( "pcode", label=T("PCode"), multiple=False, fields=[("", "value")], ), S3SQLInlineComponent( "lat_lon_source", label=T("Lat/Lon Source"), multiple=False, fields=[("", "value")], ), S3SQLInlineComponent( "lat_lon_date", label=T("Lat/Lon Date"), multiple=False, fields=[("", "value")], ), #"pcode.value", "parent", ) NONE = current.messages["NONE"] levels = current.gis.get_location_hierarchy() table.level.represent = lambda l: levels[l] if l else NONE field = table.inherited field.label = T("Mapped?") field.represent = lambda inherited: T("No") if inherited else T( "Yes") filter_widgets = s3db.get_config("gis_location", "filter_widgets") # Remove L2 & L3 filters # NB Fragile: dependent on filters defined in gis/location controller filter_widgets.pop() filter_widgets.pop() s3db.configure( "gis_location", crud_form=crud_form, filter_widgets=filter_widgets, list_fields=[ "name", # @ToDo: Investigate whether we can support this style & hence not need to define custom components #(T("Russian Name"), "name.name_l10n?location_name.language=ru"), #("PCode", "tag.value?location_tag.tag=PCode"), (T("Russian Name"), "name_ru.name_l10n"), "level", ("PCode", "pcode.value"), "L0", "L1", "L2", "inherited", ]) return True
def define_tables(self, db, migrate): from gluon import current from gluon.dal import DEFAULT logging.debug('defining tables (migrate=%s)' % migrate) now = self.now() db.define_table('scheduler_task', Field('application_name', requires=IS_NOT_EMPTY(), default=None, writable=False), Field('task_name', default=None), Field('group_name', default='main', writable=False), Field('status', requires=IS_IN_SET(TASK_STATUS), default=QUEUED, writable=False), Field('function_name', requires=IS_IN_SET(sorted(self.tasks.keys())) if self.tasks else DEFAULT), Field('uuid', requires=IS_NOT_IN_DB(db, 'scheduler_task.uuid'), unique=True, default=web2py_uuid), Field('args', 'text', default='[]', requires=TYPE(list)), Field('vars', 'text', default='{}', requires=TYPE(dict)), Field('enabled', 'boolean', default=True), Field('start_time', 'datetime', default=now, requires=IS_NOT_EMPTY()), Field('next_run_time', 'datetime', default=now), Field('stop_time', 'datetime'), Field('repeats', 'integer', default=1, comment="0=unlimited", requires=IS_INT_IN_RANGE(0, None)), Field('retry_failed', 'integer', default=0, comment="-1=unlimited", requires=IS_INT_IN_RANGE(-1, None)), Field('period', 'integer', default=60, comment='seconds', requires=IS_INT_IN_RANGE(0, None)), Field('timeout', 'integer', default=60, comment='seconds', requires=IS_INT_IN_RANGE(0, None)), Field('sync_output', 'integer', default=0, comment="update output every n sec: 0=never", requires=IS_INT_IN_RANGE(0, None)), Field('times_run', 'integer', default=0, writable=False), Field('times_failed', 'integer', default=0, writable=False), Field('last_run_time', 'datetime', writable=False, readable=False), Field('assigned_worker_name', default='', writable=False), migrate=migrate, format='%(task_name)s') if hasattr(current, 'request'): db.scheduler_task.application_name.default = '%s/%s' % ( current.request.application, current.request.controller) db.define_table('scheduler_run', Field('scheduler_task', 'reference scheduler_task'), Field('status', requires=IS_IN_SET(RUN_STATUS)), Field('start_time', 'datetime'), Field('stop_time', 'datetime'), Field('output', 'text'), Field('result', 'text'), Field('traceback', 'text'), Field('worker_name', default=self.worker_name), migrate=migrate) db.define_table('scheduler_worker', Field('worker_name', unique=True), Field('first_heartbeat', 'datetime'), Field('last_heartbeat', 'datetime'), Field('status', requires=IS_IN_SET(WORKER_STATUS)), Field('is_ticker', 'boolean', default=False, writable=False), Field('group_names', 'list:string', default=self.group_names), migrate=migrate) db.commit()
def customise_project_activity_resource(r, tablename): s3db = current.s3db tablename = "project_activity" # Custom Filtered Components s3db.add_components( tablename, project_activity_organisation=( # Agency { "name": "agency", "joinby": "activity_id", "filterby": { "role": 1, }, #"multiple": False, }, # Partners { "name": "partner", "joinby": "activity_id", "filterby": { "role": 2, }, #"multiple": False, }, # Donors { "name": "donor", "joinby": "activity_id", "filterby": { "role": 3, }, #"multiple": False, }, ), project_activity_tag=( # Modality { "name": "modality", "joinby": "activity_id", "filterby": { "tag": "modality", }, "multiple": False, }, # Number { "name": "number", "joinby": "activity_id", "filterby": { "tag": "number", }, "multiple": False, }, )) # Individual settings for specific tag components from gluon import IS_EMPTY_OR, IS_IN_SET, IS_INT_IN_RANGE components_get = r.resource.components.get donor = components_get("donor") donor.table.organisation_id.default = None partner = components_get("partner") partner.table.organisation_id.default = None modality = components_get("modality") modality.table.value.requires = IS_EMPTY_OR( IS_IN_SET(("Cash", "In-kind"))) number = components_get("number") number.table.value.requires = IS_EMPTY_OR(IS_INT_IN_RANGE()) s3db.project_activity_data.unit.requires = IS_EMPTY_OR( IS_IN_SET(("People", "Households"))) from s3 import S3LocationFilter, S3OptionsFilter, S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineLink crud_form = S3SQLCustomForm( S3SQLInlineLink( "event", field="event_id", label=T("Disaster"), multiple=False, #required = True, ), S3SQLInlineComponent( "agency", name="agency", label=T("Agency"), fields=[ ("", "organisation_id"), ], #multiple = False, required=True, ), # @ToDo: MultiSelectWidget is nicer UI but S3SQLInlineLink # requires the link*ed* table as component (not the # link table as applied here) and linked components # cannot currently be filtered by link table fields # (=> should solve the latter rather than the former) # @ToDo: Fix Create Popups S3SQLInlineComponent( "partner", name="partner", label=T("Implementing Partner"), fields=[ ("", "organisation_id"), ], ), S3SQLInlineComponent( "donor", name="donor", label=T("Donor"), fields=[ ("", "organisation_id"), ], ), "location_id", S3SQLInlineLink( "sector", field="sector_id", filter=False, label=T("Sector"), multiple=False, ), (T("Relief Items/Activity"), "name"), S3SQLInlineComponent( "modality", name="modality", label=T("Modality"), fields=[ ("", "value"), ], multiple=False, ), S3SQLInlineComponent( "number", name="number", label=T("Number of Items/Kits/Activities"), fields=[ ("", "value"), ], multiple=False, ), (T("Activity Date (Planned/Start Date)"), "date"), (T("Activity Date (Completion Date)"), "end_date"), S3SQLInlineComponent( "activity_data", label="", fields=[ (T("People / Households"), "unit"), (T("Total Number People/HH Targeted"), "target_value"), (T("Total Number Of People/HH Reache"), "value"), ], multiple=False, ), (T("Activity Status"), "status_id"), "comments", ) filter_widgets = [ S3OptionsFilter("event.event_type_id"), S3OptionsFilter( "event__link.event_id" ), # @ToDo: Filter this list dynamically based on Event Type S3OptionsFilter("sector_activity.sector_id"), S3LocationFilter( "location_id", # These levels are for SHARE/LK levels=("L2", "L3", "L4"), ), S3OptionsFilter( "status_id", cols=4, label=T("Status"), ), ] s3db.configure( tablename, crud_form=crud_form, filter_widgets=filter_widgets, list_fields=[ (T("Disaster"), "event__link.event_id"), (T("Agency"), "agency.organisation_id"), (T("Implementing Partner"), "partner.organisation_id"), (T("Donor"), "donor.organisation_id"), (T("District"), "location_id$L1"), (T("DS Division"), "location_id$L2"), (T("GN Division"), "location_id$L3"), (T("Sector"), "sector_activity.sector_id"), (T("Relief Items/Activity"), "name"), (T("Modality"), "modality.value"), (T("Number of Items/Kits/Activities"), "number.value"), (T("Activity Date (Planned/Start Date)"), "date"), (T("Activity Date (Completion Date)"), "end_date"), (T("People / Households"), "activity_data.unit"), (T("Total Number People/HH Targeted"), "activity_data.target_value"), (T("Total Number Of People/HH Reached"), "activity_data.value"), (T("Activity Status"), "status_id"), "comments", ], )
def register(self, r, **attr): """ Register a test result @param r: the S3Request instance @param attr: controller attributes """ if r.http not in ("GET", "POST"): r.error(405, current.ERROR.BAD_METHOD) if not r.interactive: r.error(415, current.ERROR.BAD_FORMAT) T = current.T db = current.db s3db = current.s3db auth = current.auth request = current.request response = current.response s3 = response.s3 settings = current.deployment_settings # Page title and intro text title = T("Register Test Result") # Get intro text from CMS ctable = s3db.cms_post ltable = s3db.cms_post_module join = ltable.on((ltable.post_id == ctable.id) & \ (ltable.module == "disease") & \ (ltable.resource == "case_diagnostics") & \ (ltable.deleted == False)) query = (ctable.name == "TestResultRegistrationIntro") & \ (ctable.deleted == False) row = db(query).select( ctable.body, join=join, cache=s3db.cache, limitby=(0, 1), ).first() intro = row.body if row else None # Instantiate Consent Tracker consent = s3db.auth_Consent( processing_types=["CWA_ANONYMOUS", "CWA_PERSONAL"]) table = s3db.disease_case_diagnostics # Configure disease_id field = table.disease_id if field.writable: default_disease = None offset = 1 else: default_disease = field.default field.readable = False offset = 0 # Probe date is mandatory field = table.probe_date requires = field.requires if isinstance(requires, IS_EMPTY_OR): field.requires = requires.other # Configure device_id field = table.device_id field.readable = field.writable = True dtable = s3db.disease_testing_device query = (dtable.device_class == "RAT") & \ (dtable.approved == True) & \ (dtable.available == True) if default_disease: query = (dtable.disease_id == default_disease) & query field.requires = IS_ONE_OF( db(query), "disease_testing_device.id", field.represent, ) cwa_options = ( ("NO", T("Do not report")), ("ANONYMOUS", T("Issue anonymous contact tracing code")), ("PERSONAL", T("Issue personal test certificate")), ) formfields = [ # -- Test Result -- table.site_id, table.disease_id, table.probe_date, table.device_id, table.result, # -- Report to CWA -- Field( "report_to_cwa", "string", requires=IS_IN_SET(cwa_options, sort=False, zero=""), default="NO", label=T("Report test result to %(system)s") % CWA, ), Field( "last_name", label=T("Last Name"), ), Field( "first_name", label=T("First Name"), ), s3_date( "date_of_birth", label=T("Date of Birth"), month_selector=True, ), Field( "dcc_option", "boolean", default=False, label=T("Provide Digital %(title)s Certificate") % {"title": "COVID-19 Test"}, ), Field( "consent", label="", widget=consent.widget, ), ] # Required fields required_fields = [] # Subheadings subheadings = ( (0, T("Test Result")), (4 + offset, CWA["system"]), ) # Generate labels (and mark required fields in the process) labels, has_required = s3_mark_required( formfields, mark_required=required_fields, ) s3.has_required = has_required # Form buttons REGISTER = T("Submit") buttons = [ INPUT( _type="submit", _value=REGISTER, ), ] # Construct the form response.form_label_separator = "" form = SQLFORM.factory(table_name="test_result", record=None, hidden={"_next": request.vars._next}, labels=labels, separator="", showid=False, submit_button=REGISTER, delete_label=auth.messages.delete_label, formstyle=settings.get_ui_formstyle(), buttons=buttons, *formfields) # Identify form for CSS & JS Validation form.add_class("result-register") # Add Subheadings if subheadings: for pos, heading in subheadings[::-1]: form[0].insert(pos, DIV(heading, _class="subheading")) # Inject scripts script = "/%s/static/themes/RLP/js/testresult.js" % r.application if script not in s3.scripts: s3.scripts.append(script) s3.jquery_ready.append("S3EnableNavigateAwayConfirm()") if form.accepts( request.vars, current.session, formname="register", onvalidation=self.validate, ): formvars = form.vars # Create disease_case_diagnostics record testresult = { "result": formvars.get("result"), } if "site_id" in formvars: testresult["site_id"] = formvars["site_id"] if "disease_id" in formvars: testresult["disease_id"] = formvars["disease_id"] if "probe_date" in formvars: testresult["probe_date"] = formvars["probe_date"] if "device_id" in formvars: testresult["device_id"] = formvars["device_id"] record_id = table.insert(**testresult) if not record_id: raise RuntimeError("Could not create testresult record") testresult["id"] = record_id # Set record owner auth = current.auth auth.s3_set_record_owner(table, record_id) auth.s3_make_session_owner(table, record_id) # Onaccept s3db.onaccept(table, testresult, method="create") response.confirmation = T("Test Result registered") report_to_cwa = formvars.get("report_to_cwa") if report_to_cwa == "NO": # Do not report to CWA, just forward to read view self.next = r.url(id=record_id, method="read") else: # Report to CWA and show test certificate dcc_option = False if report_to_cwa == "ANONYMOUS": processing_type = "CWA_ANONYMOUS" cwa_report = CWAReport(record_id) elif report_to_cwa == "PERSONAL": dcc_option = formvars.get("dcc_option") processing_type = "CWA_PERSONAL" cwa_report = CWAReport( record_id, anonymous=False, first_name=formvars.get("first_name"), last_name=formvars.get("last_name"), dob=formvars.get("date_of_birth"), dcc=dcc_option, ) else: processing_type = cwa_report = None if cwa_report: # Register consent if processing_type: cwa_report.register_consent( processing_type, formvars.get("consent"), ) # Send to CWA success = cwa_report.send() if success: response.information = T( "Result reported to %(system)s") % CWA retry = False else: response.error = T("Report to %(system)s failed") % CWA retry = True # Store DCC data if dcc_option: cwa_data = cwa_report.data from .dcc import DCC try: hcert = DCC.from_result( cwa_data.get("hash"), record_id, cwa_data.get("fn"), cwa_data.get("ln"), cwa_data.get("dob"), ) except ValueError as e: hcert = None response.warning = str(e) if hcert: hcert.save() else: # Remove DCC flag if hcert could not be generated cwa_report.dcc = False S3CustomController._view("RLPPTM", "certificate.html") # Title field = table.disease_id if cwa_report.disease_id and field.represent: disease = field.represent(cwa_report.disease_id) title = "%s %s" % (disease, T("Test Result")) else: title = T("Test Result") return { "title": title, "intro": None, # TODO "form": cwa_report.formatted(retry=retry), } else: response.information = T( "Result not reported to %(system)s") % CWA self.next = r.url(id=record_id, method="read") return None elif form.errors: current.response.error = T( "There are errors in the form, please check your input") # Custom View S3CustomController._view("RLPPTM", "testresult.html") return { "title": title, "intro": intro, "form": form, }
def customise_req_req_resource(r, tablename): from gluon import IS_EMPTY_OR, IS_IN_SET, SPAN from s3 import S3DateFilter, S3LocationFilter, S3OptionsFilter, S3Represent, S3TextFilter s3db = current.s3db req_status_opts = { 0: SPAN( T("None"), _class="req_status_none", ), 1: SPAN( T("Partial"), _class="req_status_partial", ), 2: SPAN( T("Complete"), _class="req_status_complete", ), } f = s3db.req_req.req_status f.readable = f.writable = True f.represent = S3Represent(options=req_status_opts) f.requires = IS_EMPTY_OR(IS_IN_SET(req_status_opts)) f = s3db.req_req.security_req f.readable = f.writable = True f.label = T("Needs Financing?") filter_widgets = [ S3TextFilter( [ #"committer_id$first_name", #"committer_id$middle_name", #"committer_id$last_name", "req_item.item_id", "site_id$name", "comments", #"req_id$name", #"organisation_id$name" ], label=T("Search"), #comment = T("Search for a commitment by Committer name, Request ID, Site or Organization."), comment=T("Search for a request by Item, Site or Comments"), ), S3LocationFilter( "site_id$location_id", levels=("L1", "L2"), ), S3OptionsFilter("req_item.item_id", ), S3OptionsFilter( "req_status", cols=3, options=req_status_opts, ), S3OptionsFilter( "security_req", cols=2, ), #S3OptionsFilter("commit_status", # cols = 3, # hidden = True, # ), #S3OptionsFilter("transit_status", # cols = 3, # hidden = True, # ), #S3OptionsFilter("fulfil_status", # cols = 3, # hidden = True, # ), S3OptionsFilter( "site_id", hidden=True, ), S3OptionsFilter( "created_by", label=T("Logged By"), hidden=True, ), S3DateFilter( "date", # Better to default (easier to customise/consistency) #label = T("Date Requested"), hide_time=True, input_labels={ "ge": "From", "le": "To" }, comment=T("Search for requests made between these dates."), hidden=True, ), #S3DateFilter("date_required", # # Better to default (easier to customise/consistency) # #label = T("Date Needed By"), # hide_time = True, # input_labels = {"ge": "From", "le": "To"}, # comment = T("Search for requests required between these dates."), # hidden = True, # ), ] list_fields = [ "date", "site_id", "req_status", "req_item.item_id", "security_req", ] s3db.configure( "req_req", filter_widgets=filter_widgets, list_fields=list_fields, )
def customise_req_need_resource(r, tablename): s3db = current.s3db tablename = "req_need" # Custom Filtered Components s3db.add_components( tablename, req_need_tag=( # Verified { "name": "verified", "joinby": "need_id", "filterby": { "tag": "verified", }, "multiple": False, }, )) # Individual settings for specific tag components from gluon import IS_EMPTY_OR, IS_IN_SET components_get = r.resource.components.get verified = components_get("verified") f = verified.table.value f.requires = IS_EMPTY_OR(IS_IN_SET((True, False))) auth = current.auth if auth.s3_has_role("ADMIN"): f.default = True else: user = auth.user if user and user.organisation_id: f.default = True else: f.default = False f.writable = False from s3 import S3LocationFilter, S3OptionsFilter, S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineLink crud_form = S3SQLCustomForm( S3SQLInlineLink( "event", field="event_id", label=T("Disaster"), multiple=False, #required = True, ), "location_id", "date", "priority", S3SQLInlineLink( "sector", field="sector_id", filter=False, label=T("Sector"), multiple=False, ), "summary", S3SQLInlineComponent( "verified", name="verified", label=T("Verified"), fields=[ ("", "value"), ], multiple=False, ), "status", "comments", ) filter_widgets = [ S3OptionsFilter("event.event_type_id"), S3OptionsFilter( "event__link.event_id" ), # @ToDo: Filter this list dynamically based on Event Type S3OptionsFilter("sector__link.sector_id"), S3LocationFilter( "location_id", # These levels are for SHARE/LK levels=("L2", "L3", "L4"), ), S3OptionsFilter( "status", cols=3, label=T("Status"), ), S3OptionsFilter( "verified.value", cols=2, label=T("Verified"), ), ] s3db.configure( tablename, crud_form=crud_form, filter_widgets=filter_widgets, list_fields=[ (T("Disaster"), "event__link.event_id"), # These levels/Labels are for SHARE/LK (T("District"), "location_id$L2"), (T("DS"), "location_id$L3"), (T("GN"), "location_id$L4"), "date", "priority", "summary", "sector__link.sector_id", (T("Status"), "status"), (T("Verified"), "verified.value"), ], )
def __call__(self): request = current.request response = current.response from gluon import Field, SQLFORM, IS_NOT_EMPTY, IS_EMAIL, IS_IN_SET, IS_EMPTY_OR from s3 import s3_mark_required, S3StringWidget T = current.T formstyle = current.deployment_settings.get_ui_formstyle() fields = [Field("address", label = T("Your e-mail address"), requires = IS_EMAIL(), widget = lambda *args, **kwargs: \ S3StringWidget(placeholder="*****@*****.**")(_type="email", *args, **kwargs), ), Field("subject", label = T("Subject"), requires = IS_EMPTY_OR(IS_IN_SET(("Solution Development", "Workshop / Training", "SAHANA Deployment / Support", "Other / General Inquiry", ), zero = "What can we do for you?", sort = False, )), ), Field("message", "text", label = T("Message"), requires = IS_NOT_EMPTY(), ), ] labels, required = s3_mark_required(fields) response.form_label_separator = "" form = SQLFORM.factory( formstyle=formstyle, labels=labels, submit_button=T("Send Message"), _id="mailform", *fields, ) if form.accepts( request.post_vars, current.session, formname="default/index/contact", #onvalidation = onvalidation, keepvalues=False, hideerror=False, ): form_vars = form.vars subject = "Request on AidIQ website" if form_vars.subject: subject = "%s: %s" % (subject, form_vars.subject) result = current.msg.send_email( to=current.deployment_settings.get_mail_approver(), subject=form_vars.subject, message=form_vars.message, reply_to=form_vars.address, ) if result: response.confirmation = "Thank you for your message - we'll be in touch shortly" appname = request.application s3 = response.s3 sappend = s3.scripts.append if s3.cdn: if s3.debug: sappend( "//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.js" ) else: sappend( "//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js" ) else: if s3.debug: sappend("/%s/static/scripts/jquery.validate.js" % appname) else: sappend("/%s/static/scripts/jquery.validate.min.js" % appname) sappend("/%s/static/themes/AidIQ/js/contact.js" % appname) response.title = "Contact Us | AidIQ.com" self._view(THEME, "contact.html") return { "form": DIV(form, _class="form-container"), }
def customise_disease_case_diagnostics_resource(r, tablename): db = current.db s3db = current.s3db table = s3db.disease_case_diagnostics if r.interactive and r.method != "report": # Enable project link and make it mandatory field = table.project_id field.readable = field.writable = True field.comment = None requires = field.requires if isinstance(requires, (list, tuple)): requires = requires[0] if isinstance(requires, IS_EMPTY_OR): field.requires = requires.other # If there is only one project, default the selector + make r/o ptable = s3db.project_project rows = db(ptable.deleted == False).select( ptable.id, cache=s3db.cache, limitby=(0, 2), ) if len(rows) == 1: field.default = rows[0].id field.writable = False # Enable disease link and make it mandatory field = table.disease_id field.readable = field.writable = True field.comment = None requires = field.requires if isinstance(requires, (list, tuple)): requires = requires[0] if isinstance(requires, IS_EMPTY_OR): field.requires = requires.other # If there is only one disease, default the selector + make r/o dtable = s3db.disease_disease rows = db(dtable.deleted == False).select( dtable.id, cache=s3db.cache, limitby=(0, 2), ) if len(rows) == 1: field.default = rows[0].id field.writable = False # Default result date field = table.result_date field.default = current.request.utcnow.date() # Formal test types # TODO move to lookup table? type_options = ( ("LFD", T("LFD Antigen Test")), ("PCR", T("PCR Test")), ("SER", T("Serum Antibody Test")), ("OTH", T("Other")), ) field = table.test_type field.default = "LFD" field.writable = False # fixed for now field.requires = IS_IN_SET( type_options, zero="", sort=False, ) field.represent = S3Represent(options=dict(type_options)) # Formal results result_options = ( ("NEG", T("Negative")), ("POS", T("Positive")), ("INC", T("Inconclusive")), ) field = table.result field.requires = IS_IN_SET( result_options, zero="", sort=False, ) field.represent = S3Represent(options=dict(result_options)) # Custom list_fields list_fields = [ "project_id", "disease_id", "test_type", "result_date", "result", ] # Custom form from s3 import S3SQLCustomForm crud_form = S3SQLCustomForm( "project_id", "disease_id", "test_type", "result_date", "result", ) # Filters from s3 import S3DateFilter, S3OptionsFilter filter_widgets = [ S3DateFilter( "result_date", label=T("Date"), ), S3OptionsFilter("disease_id", hidden=True), S3OptionsFilter("project_id", hidden=True), S3OptionsFilter( "test_type", options=OrderedDict(type_options), hidden=True, ), S3OptionsFilter( "result", options=OrderedDict(result_options), hidden=True, ), ] # Report options facts = ((T("Number of Tests"), "count(id)"), ) axes = [ "result", "test_type", "disease_id", "project_id", ] report_options = { "rows": axes, "cols": axes, "fact": facts, "defaults": { "rows": axes[1], "cols": axes[0], "fact": facts[0], "totals": True, }, } s3db.configure( "disease_case_diagnostics", crud_form=crud_form, filter_widgets=filter_widgets, list_fields=list_fields, report_options=report_options, ) crud_strings = current.response.s3.crud_strings crud_strings["disease_case_diagnostics"] = Storage( label_create=T("Register Test Result"), title_display=T("Test Result"), title_list=T("Test Results"), title_update=T("Edit Test Result"), title_upload=T("Import Test Results"), label_list_button=T("List Test Results"), label_delete_button=T("Delete Test Result"), msg_record_created=T("Test Result added"), msg_record_modified=T("Test Result updated"), msg_record_deleted=T("Test Result deleted"), msg_list_empty=T("No Test Results currently registered"))
# item in CONTENT_TYPE_REG, it should not be readed or writed by users # and should be writen only one, in the creation of the item. Field('item_type', 'string', length='100', default='text'), Field( 'unique_id', 'string', length=64, default=uuid.uuid4(), writable=False, readable=False ), ) db.item._before_insert.append(_get_slugline) db.item._before_update.append(_update_slugline) db.item.id.readable = False db.item.id.writable = False db.item.item_type.readable = False db.item.item_type.writable = False db.item.copyright_url.label = T('Copyright URL') db.item.pubstatus.requires = IS_IN_SET(PUB_STATUS, zero=None) db.item.pubstatus.label = T('Status') db.item.headline.requires = IS_NOT_EMPTY() db.item.headline.label = T('Headline') db.item.headline.comment = T('Headline or descriptive title') db.item.headline.requires = IS_NOT_EMPTY() db.item.language_tag.label = T('Language') db.item.keywords.label = T("Keywords") db.item.keywords.requires = IS_NOT_EMPTY() db.item.keywords.comment = T("One keyword per line") db.item.section_page.label = T("Section") db.item.section_page.comment = T( "Section or page in with this item is intended to be used") db.item.located.label = T("Located") db.item.located.comment = T( """