Exemplo n.º 1
0
    def merge(self, r, **attr):
        """
            Merge form for two records

            @param r: the S3Request
            @param **attr: the controller attributes for the request

            @note: this method can always only be POSTed, and requires
                   both "selected" and "mode" in post_vars, as well as
                   the duplicate bookmarks list in session.s3
        """

        T = current.T
        session = current.session
        response = current.response

        output = dict()
        tablename = self.tablename

        # Get the duplicate bookmarks
        s3 = session.s3
        DEDUPLICATE = self.DEDUPLICATE
        if DEDUPLICATE in s3:
            bookmarks = s3[DEDUPLICATE]
            if tablename in bookmarks:
                record_ids = bookmarks[tablename]

        # Process the post variables
        post_vars = r.post_vars
        mode = post_vars.get("mode")
        selected = post_vars.get("selected", "")
        selected = selected.split(",")
        if mode == "Inclusive":
            ids = selected
        elif mode == "Exclusive":
            ids = [i for i in record_ids if i not in selected]
        else:
            # Error
            ids = []
        if len(ids) != 2:
            r.error(501, T("Please select exactly two records"),
                    next = r.url(id=0, vars={}))

        # Get the selected records
        table = self.table
        query = (table._id == ids[0]) | (table._id == ids[1])
        orderby = table.created_on if "created_on" in table else None
        rows = current.db(query).select(orderby=orderby,
                                        limitby=(0, 2))
        if len(rows) != 2:
            r.error(404, current.ERROR.BAD_RECORD, next = r.url(id=0, vars={}))
        original = rows[0]
        duplicate = rows[1]

        # Prepare form construction
        formfields = [f for f in table if f.readable or f.writable]

        ORIGINAL, DUPLICATE, KEEP = self.ORIGINAL, self.DUPLICATE, self.KEEP
        keep_o = KEEP.o in post_vars and post_vars[KEEP.o]
        keep_d = KEEP.d in post_vars and post_vars[KEEP.d]

        trs = []
        init_requires = self.init_requires
        for f in formfields:

            # Render the widgets
            oid = "%s_%s" % (ORIGINAL, f.name)
            did = "%s_%s" % (DUPLICATE, f.name)
            sid = "swap_%s" % f.name
            init_requires(f, original[f], duplicate[f])
            if keep_o or not any((keep_o, keep_d)):
                owidget = self.widget(f, original[f], _name=oid, _id=oid)
            else:
                try:
                    owidget = s3_represent_value(f, value=original[f])
                except:
                    owidget = s3_unicode(original[f])
            if keep_d or not any((keep_o, keep_d)):
                dwidget = self.widget(f, duplicate[f], _name=did, _id=did)
            else:
                try:
                    dwidget = s3_represent_value(f, value=duplicate[f])
                except:
                    dwidget = s3_unicode(duplicate[f])

            # Swap button
            if not any((keep_o, keep_d)):
                swap = INPUT(_value="<-->",
                             _class="swap-button",
                             _id=sid,
                             _type="button")
            else:
                swap = DIV(_class="swap-button")

            if owidget is None or dwidget is None:
                continue

            # Render label row
            label = f.label
            trs.append(TR(TD(label, _class="w2p_fl"),
                          TD(),
                          TD(label, _class="w2p_fl")))

            # Append widget row
            trs.append(TR(TD(owidget, _class="mwidget"),
                          TD(swap),
                          TD(dwidget, _class="mwidget")))

        # Show created_on/created_by for each record
        if "created_on" in table:
            original_date = original.created_on
            duplicate_date = duplicate.created_on
            if "created_by" in table:
                represent = table.created_by.represent
                original_author = represent(original.created_by)
                duplicate_author = represent(duplicate.created_by)
                created = T("Created on %s by %s")
                original_created = created % (original_date, original_author)
                duplicate_created = created % (duplicate_date, duplicate_author)
            else:
                created = T("Created on %s")
                original_created = created % original_date
                duplicate_created = created % duplicate_date
        else:
            original_created = ""
            duplicate_created = ""

        # Page title and subtitle
        output["title"] = T("Merge records")
        #output["subtitle"] = self.crud_string(tablename, "title_list")

        # Submit buttons
        if keep_o or not any((keep_o, keep_d)):
            submit_original = INPUT(_value=T("Keep Original"),
                                    _type="submit", _name=KEEP.o, _id=KEEP.o)
        else:
            submit_original = ""

        if keep_d or not any((keep_o, keep_d)):
            submit_duplicate = INPUT(_value=T("Keep Duplicate"),
                                     _type="submit", _name=KEEP.d, _id=KEEP.d)
        else:
            submit_duplicate = ""

        # Build the form
        form = FORM(TABLE(
                        THEAD(
                            TR(TH(H3(T("Original"))),
                               TH(),
                               TH(H3(T("Duplicate"))),
                            ),
                            TR(TD(original_created),
                               TD(),
                               TD(duplicate_created),
                               _class="authorinfo",
                            ),
                        ),
                        TBODY(trs),
                        TFOOT(
                            TR(TD(submit_original),
                               TD(),
                               TD(submit_duplicate),
                            ),
                        ),
                    ),
                    # Append mode and selected - required to get back here!
                    hidden = {
                        "mode": "Inclusive",
                        "selected": ",".join(ids),
                    }
                )

        output["form"] = form

        # Add RESET and CANCEL options
        output["reset"] = FORM(INPUT(_value=T("Reset"),
                                     _type="submit",
                                     _name="reset", _id="form-reset"),
                               A(T("Cancel"), _href=r.url(id=0, vars={}), _class="action-lnk"),
                               hidden = {"mode": mode,
                                         "selected": ",".join(ids)})

        # Process the merge form
        formname = "merge_%s_%s_%s" % (tablename,
                                       original[table._id],
                                       duplicate[table._id])
        if form.accepts(post_vars, session,
                        formname=formname,
                        onvalidation=lambda form: self.onvalidation(tablename, form),
                        keepvalues=False,
                        hideerror=False):

            s3db = current.s3db

            if form.vars[KEEP.d]:
                prefix = "%s_" % DUPLICATE
                original, duplicate = duplicate, original
            else:
                prefix = "%s_" % ORIGINAL

            data = Storage()
            for key in form.vars:
                if key.startswith(prefix):
                    fname = key.split("_", 1)[1]
                    data[fname] = form.vars[key]

            search = False
            resource = s3db.resource(tablename)
            try:
                resource.merge(original[table._id],
                               duplicate[table._id],
                               update=data)
            except current.auth.permission.error:
                r.unauthorized()
            except KeyError:
                r.error(404, current.ERROR.BAD_RECORD)
            except:
                import sys
                r.error(424,
                        T("Could not merge records. (Internal Error: %s)") %
                            sys.exc_info()[1],
                        next=r.url())
            else:
                # Cleanup bookmark list
                if mode == "Inclusive":
                    bookmarks[tablename] = [i for i in record_ids if i not in ids]
                    if not bookmarks[tablename]:
                        del bookmarks[tablename]
                        search = True
                elif mode == "Exclusive":
                    bookmarks[tablename].extend(ids)
                    if not selected:
                        search = True
                # Confirmation message
                # @todo: Having the link to the merged record in the confirmation
                # message would be nice, but it's currently not clickable there :/
                #result = A(T("Open the merged record"),
                        #_href=r.url(method="read",
                                    #id=original[table._id],
                                    #vars={}))
                response.confirmation = T("Records merged successfully.")

            # Go back to bookmark list
            if search:
                self.next = r.url(method="", id=0, vars={})
            else:
                self.next = r.url(id=0, vars={})

        # View
        response.view = self._view(r, "merge.html")

        return output
Exemplo n.º 2
0
    def _datalist(self, r, widget, **attr):
        """
            Generate a dataList

            @param r: the S3Request instance
            @param widget: the widget as a tuple: (label, tablename, icon, filter)
            @param attr: controller attributes for the request
        """

        context = widget.get("context", None)
        if context:
            context = "(%s)" % context
            current.s3db.context = S3FieldSelector(context) == r.id

        tablename = widget.get("tablename", None)
        resource = current.s3db.resource(tablename, context=True)
        table = resource.table

        # Config Options:
        # 1st choice: Widget
        # 2nd choice: get_config
        # 3rd choice: Default
        config = resource.get_config
        list_fields = widget.get("list_fields", config("list_fields", None))
        list_layout = widget.get("list_layout", config("list_layout", None))
        orderby = widget.get(
            "orderby", config("list_orderby", ~resource.table.created_on))

        filter = widget.get("filter", None)
        if filter:
            resource.add_filter(filter)

        # Use the widget-index to create a unique ID
        listid = "profile-list-%s-%s" % (tablename, widget["index"])

        c, f = tablename.split("_", 1)

        # Permission to create new items?
        # @ToDo: Special check for creating resources on Organisation profile
        if current.auth.s3_has_permission("create", table):
            if filter:
                vars = filter.serialize_url(filter)
            else:
                vars = Storage()
            vars.refresh = listid
            if context:
                vars[context] = r.id
            create = A(
                I(_class="icon icon-plus-sign small-add"),
                _href=URL(c=c, f=f, args=["create.popup"], vars=vars),
                _class="s3_modal",
            )
        else:
            create = ""

        # Page size
        pagesize = 4
        representation = r.representation
        if representation == "dl":
            # Ajax-update
            get_vars = r.get_vars
            record_id = get_vars.get("record", None)
            if record_id is not None:
                # Ajax-update of a single record
                resource.add_filter(S3FieldSelector("id") == record_id)
                start, limit = 0, 1
            else:
                # Ajax-update of full page
                start = get_vars.get("start", None)
                limit = get_vars.get("limit", None)
                if limit is not None:
                    try:
                        start = int(start)
                        limit = int(limit)
                    except ValueError:
                        start, limit = 0, 4
                else:
                    start = None
        else:
            # Page-load
            start, limit = 0, 4

        # Ajax-delete items?
        if representation == "dl" and r.http in ("DELETE", "POST"):
            if "delete" in r.get_vars:
                return self._dl_ajax_delete(r, resource)
            else:
                r.error(405, r.ERROR.BAD_METHOD)

        # dataList
        datalist, numrows, ids = resource.datalist(fields=list_fields,
                                                   start=start,
                                                   limit=limit,
                                                   listid=listid,
                                                   orderby=orderby,
                                                   layout=list_layout)
        # Render the list
        ajaxurl = r.url(vars={"update": widget["index"]}, representation="dl")
        data = datalist.html(ajaxurl=ajaxurl, pagesize=pagesize)
        if numrows == 0:
            msg = P(I(_class="icon-folder-open-alt"),
                    BR(),
                    S3CRUD.crud_string(resource.tablename, "msg_no_match"),
                    _class="empty_card-holder")
            data.insert(1, msg)

        if representation == "dl":
            # This is an Ajax-request, so we don't need the wrapper
            current.response.view = "plain.html"
            return data

        label = widget.get("label", "")
        if label:
            label = current.T(label)
        icon = widget.get("icon", "")
        if icon:
            icon = TAG[""](I(_class=icon), " ")

        # Render the widget
        output = DIV(create,
                     H4(icon, label, _class="profile-sub-header"),
                     DIV(data, _class="card-holder"),
                     _class="span6")

        return output
Exemplo n.º 3
0
def customize_project_project(**attr):
    """
        Customize project_project controller
    """

    db = current.db
    s3db = current.s3db
    s3 = current.response.s3
    tablename = "project_project"
    # Load normal model
    table = s3db[tablename]

    # Custom Components
    s3db.add_components(
        tablename,
        project_drrpp={
            "joinby": "project_id",
            "multiple": False,
        },
        project_output="project_id",
        doc_document=(  # Files
            {
                "name": "file",
                "joinby": "doc_id",
                "filterby": "url",
                "filterfor": ["", None],
            },
            # Links
            {
                "name": "url",
                "joinby": "doc_id",
                "filterby": "file",
                "filterfor": ["", None],
            },
        ),
    )

    # Custom CRUD Strings
    crud_strings = s3.crud_strings
    crud_strings.project_project.title_search = T("Project List")

    # Custom Fields
    table.name.label = T("Project Title")
    s3db.project_project.budget.label = T("Total Funding (USD)")
    location_id = s3db.project_location.location_id
    location_id.label = ""

    # Limit to just Countries
    location_id.requires = s3db.gis_country_requires
    # Use dropdown, not AC
    location_id.widget = None

    # In DRRPP this is a free field
    table = s3db.project_organisation
    table.comments.label = T("Role")
    table.comments.widget = SQLFORM.widgets.string.widget
    table.amount.label = T("Amount")
    table = s3db.doc_document
    table.file.widget = lambda field, value, download_url: \
        SQLFORM.widgets.upload.widget(field, value, download_url, _size = 15)
    table.comments.widget = SQLFORM.widgets.string.widget

    # If not logged in, contact person is required
    logged_in = current.auth.is_logged_in()
    if not logged_in:
        table = s3db.project_drrpp
        table.focal_person.required = True
        table.email.required = True
        table.email.requires = IS_EMAIL()

    # Custom dataTable
    s3["dataTable_sDom"] = 'ripl<"dataTable_table"t>p'

    # Don't show export buttons for XLS/XML
    s3.formats = Storage(xls=None, xml=None)

    # Remove rheader
    attr["rheader"] = None

    # Only show 10 Project by default to improve load time
    attr["dt_lengthMenu"] = [[10, 50, -1], [10, 50, T("All")]]
    s3.dataTable_iDisplayLength = 10

    # Custom PreP
    standard_prep = s3.prep

    def custom_prep(r):

        resource = r.resource

        # Call standard prep
        if callable(standard_prep):
            result = standard_prep(r)
            if not result:
                return False

        # Customize list_fields
        if r.method == "review":
            list_fields = [
                "id",
                "created_on",
                "modified_on",
                "name",
                "start_date",
                (T("Countries"), "location.location_id"),
                (T("Hazards"), "hazard.name"),
                (T("Lead Organization"), "organisation_id"),
                (T("Donors"), "donor.organisation_id"),
            ]
        elif r.representation == "xls":
            # All readable Fields should be exported
            list_fields = [
                "id",
                "name",
                "code",
                "description",
                "status_id",
                "start_date",
                "end_date",
                "drrpp.duration",
                (T("Countries"), "location.location_id"),
                "drrpp.L1",
                (T("Hazards"), "hazard.name"),
                (T("Themes"), "theme.name"),
                "objectives",
                "drrpp.activities",
                "output.name",
                "drr.hfa",
                "drrpp.rfa",
                "drrpp.pifacc",
                "drrpp.jnap",
                (T("Lead Organization"), "organisation_id"),
                (T("Partners"), "partner.organisation_id"),
                (T("Donors"), "donor.organisation_id"),
                "budget",
                "currency",
                "drrpp.focal_person",
                "drrpp.organisation_id",
                "drrpp.email",
                "url.url",
                "drrpp.parent_project",
                "comments",
            ]
            if logged_in:
                list_fields.extend([
                    "created_by",
                    "created_on",
                    "modified_by",
                    "modified_on",
                ])
        else:
            list_fields = [
                "id",
                "name",
                "start_date",
                (T("Countries"), "location.location_id"),
                (T("Hazards"), "hazard.name"),
                (T("Lead Organization"), "organisation_id"),
                (T("Donors"), "donor.organisation_id"),
            ]

        resource.configure(list_fields=list_fields)

        # Customize report_options
        if r.method == "report":
            report_fields = [
                "name",
                (T("Countries"), "location.location_id"),
                (T("Hazards"), "hazard.name"),
                (T("Themes"), "theme.name"),
                (T("HFA Priorities"), "drr.hfa"),
                (T("RFA Priorities"), "drrpp.rfa"),
                (T("Lead Organization"), "organisation_id"),
                (T("Partner Organizations"), "partner.organisation_id"),
                (T("Donors"), "donor.organisation_id"),
            ]

            # Report Settings for charts
            if "chart" in r.get_vars and r.representation != "json":
                crud_strings[tablename].title_report = T("Project Graph")
                report_fact_default = "count(id)"
                report_facts = [(T("Number of Projects"), "count(id)")]
                show_table = False
            else:
                crud_strings[tablename].title_report = T("Project Matrix")
                report_fact_default = "count(id)"
                report_facts = [
                    (T("Number of Projects"), "count(id)"),
                    (T("Number of Countries"), "count(location.location_id)"),
                    (T("Number of Hazards"), "count(hazard.id)"),
                    (T("Number of Themes"), "count(theme.id)"),
                    (T("Number of HFA Priorities"), "count(drr.hfa)"),
                    (T("Number of RFA Priorities"), "count(drrpp.rfa)"),
                    (T("Number of Lead Organizations"),
                     "count(organisation_id)"),
                    (T("Number of Partner Organizations"),
                     "count(partner.organisation_id)"),
                    (T("Number of Donors"), "count(donor.organisation_id)"),
                ]
                show_table = True
            report_options = Storage(rows=report_fields,
                                     cols=report_fields,
                                     fact=report_facts,
                                     defaults=Storage(
                                         rows="hazard.name",
                                         cols="location.location_id",
                                         fact=report_fact_default,
                                         totals=True,
                                         table=show_table,
                                     ))
            resource.configure(report_options=report_options)
            current.deployment_settings.ui.hide_report_options = True

        if r.interactive:

            # Don't show Update/Delete button on Search table
            if r.method is None and not r.id:
                resource.configure(editable=False, deletable=False)

            # JS to show/hide Cook Island fields
            s3.scripts.append("/%s/static/themes/DRRPP/js/drrpp.js" %
                              current.request.application)

            if r.method == "read":
                table_pl = s3db.project_location
                table_l = s3db.gis_location
                countries = [
                    row.name
                    for row in db((table_pl.project_id == r.record.id)
                                  & (table_pl.location_id == table_l.id)).
                    select(table_l.name)
                ]
                if not ("Cook Islands" in countries and len(countries) == 1):
                    s3db.project_drrpp.L1.readable = False
                    s3db.project_drrpp.pifacc.readable = False
                    s3db.project_drrpp.jnap.readable = False

            # Filter Options
            project_hfa_opts = s3db.project_hfa_opts()
            hfa_options = dict(
                (key, "HFA %s" % key) for key in project_hfa_opts)
            #hfa_options[None] = NONE # to search NO HFA
            project_rfa_opts = s3db.project_rfa_opts()
            rfa_options = dict(
                (key, "RFA %s" % key) for key in project_rfa_opts)
            #rfa_options[None] = NONE # to search NO RFA
            project_pifacc_opts = s3db.project_pifacc_opts()
            pifacc_options = dict(
                (key, "PIFACC %s" % key) for key in project_pifacc_opts)
            #pifacc_options[None] = NONE # to search NO PIFACC
            project_jnap_opts = s3db.project_jnap_opts()
            jnap_options = dict(
                (key, "JNAP %s" % key) for key in project_jnap_opts)
            #jnap_options[None] = NONE # to search NO JNAP

            # Filter widgets
            from s3 import S3TextFilter, S3OptionsFilter
            filter_widgets = [
                S3TextFilter(
                    [
                        "name",
                        "code",
                        "description",
                        "location.location_id",
                        "hazard.name",
                        "theme.name",
                    ],
                    label=T("Search Projects"),
                    comment=T(
                        "Search for a Project by name, code, or description."),
                ),
                S3OptionsFilter(
                    "status_id",
                    label=T("Status"),
                    cols=4,
                ),
                S3OptionsFilter(
                    "location.location_id",
                    label=T("Country"),
                    cols=3,
                    hidden=True,
                ),
                #S3OptionsFilter("drrpp.L1",
                #                label = T("Cook Islands"),
                #                cols = 3,
                #                hidden = True,
                #               ),
                S3OptionsFilter(
                    "hazard.id",
                    label=T("Hazard"),
                    options=s3db.project_hazard_options,
                    help_field=s3db.project_hazard_help_fields,
                    cols=4,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "theme.id",
                    label=T("Theme"),
                    options=s3db.project_theme_options,
                    help_field=s3db.project_theme_help_fields,
                    cols=4,
                    # Don't group
                    size=None,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "drr.hfa",
                    label=T("HFA"),
                    options=hfa_options,
                    help_field=project_hfa_opts,
                    cols=5,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "drrpp.rfa",
                    label=T("RFA"),
                    options=rfa_options,
                    help_field=project_rfa_opts,
                    cols=6,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "drrpp.pifacc",
                    label=T("PIFACC"),
                    options=pifacc_options,
                    help_field=project_pifacc_opts,
                    cols=6,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "drrpp.jnap",
                    label=T("JNAP"),
                    options=jnap_options,
                    help_field=project_jnap_opts,
                    cols=6,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "organisation_id",
                    label=T("Lead Organisation"),
                    cols=3,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "partner.organisation_id",
                    label=T("Partners"),
                    cols=3,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "donor.organisation_id",
                    label=T("Donors"),
                    cols=3,
                    hidden=True,
                )
            ]

            resource.configure(filter_widgets=filter_widgets)
        return True

    s3.prep = custom_prep

    # Custom Crud Form
    from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineComponentCheckbox
    crud_form = S3SQLCustomForm(
        "name",
        "code",
        "description",
        "status_id",
        "start_date",
        "end_date",
        "drrpp.duration",
        S3SQLInlineComponent("location",
                             label=T("Countries"),
                             fields=["location_id"],
                             orderby="location_id$name",
                             render_list=True),
        "drrpp.L1",
        S3SQLInlineComponentCheckbox(
            "hazard",
            label=T("Hazards"),
            field="hazard_id",
            option_help="comments",
            cols=4,
        ),
        S3SQLInlineComponentCheckbox(
            "theme",
            label=T("Themes"),
            field="theme_id",
            option_help="comments",
            cols=3,
        ),
        "objectives",
        "drrpp.activities",
        # Outputs
        S3SQLInlineComponent(
            "output",
            label=T("Outputs"),
            fields=["name", "status"],
        ),
        "drr.hfa",
        "drrpp.rfa",
        "drrpp.pifacc",
        "drrpp.jnap",
        "organisation_id",
        # Partner Orgs
        S3SQLInlineComponent(
            "organisation",
            name="partner",
            label=T("Partner Organizations"),
            fields=[
                "organisation_id",
                "comments",  # NB This is labelled 'Role' in DRRPP
            ],
            filterby=dict(field="role", options=[2, 9]),
            default={"role": 2}),
        # Donors
        S3SQLInlineComponent("organisation",
                             name="donor",
                             label=T("Donor(s)"),
                             fields=[
                                 "organisation_id",
                                 "amount",
                                 "currency",
                             ],
                             filterby=dict(field="role", options=[3]),
                             default={"role": 3}),
        "budget",
        "drrpp.local_budget",
        "drrpp.local_currency",
        "drrpp.focal_person",
        "drrpp.organisation_id",
        "drrpp.email",
        # Files
        S3SQLInlineComponent("document",
                             name="file",
                             label=T("Files"),
                             fields=["file", "comments"],
                             filterby=dict(
                                 field="file",
                                 options="",
                                 invert=True,
                             )),
        # Links
        S3SQLInlineComponent("document",
                             name="url",
                             label=T("Links"),
                             fields=["url", "comments"],
                             filterby=dict(
                                 field="url",
                                 options=None,
                                 invert=True,
                             )),
        "drrpp.parent_project",
        "comments",
    )

    s3db.configure(
        tablename,
        crud_form=crud_form,
        subheadings={
            1: "hazard",
            2: "theme",
            3: "objectives",
            4: "drr_hfa",
            5: "drrpp_rfa",
            6: "drrpp_pifacc",
            7: "drrpp_jnap",
            8: "organisation_id",
        },
    )

    return attr
Exemplo n.º 4
0
    def _manage_subscriptions(self, resources, filters):
        """
            Custom form to manage subscriptions

            @param resources: available resources config
            @param filters: filter widgets
        """

        from gluon.sqlhtml import SQLFORM
        from gluon.validators import IS_IN_SET
        from s3.s3widgets import S3GroupedOptionsWidget

        # L10n
        T = current.T
        labels = Storage(
            RESOURCES=T("Subscribe To"),
            NOTIFY_ON=T("Notify On"),
            FREQUENCY=T("Frequency"),
            NOTIFY_BY=T("Notify By"),
            MORE=T("More Options"),
            LESS=T("Less Options"),
        )
        messages = Storage(
            ERROR=T("Error: could not update notification settings"),
            SUCCESS=T("Notification settings updated"),
        )

        # Get current subscription settings resp. form defaults
        subscription = self._get_subscription()

        # Formstyle bootstrap
        formstyle = SQLFORM.formstyles.bootstrap

        # Initialize form
        form = FORM(_id="subscription-form",
                    hidden={"subscription-filters": ""})

        # Deactivated: resource selector
        #options = []
        #selected_resources = set()
        #subscribed = subscription["resources"]
        #for idx, rconfig in enumerate(resources):
        #options.append((idx, rconfig["label"]))
        #if subscribed:
        #for s in subscribed:
        #if s.resource == rconfig["resource"] and \
        #s.url == rconfig["url"]:
        #selected_resources.add(idx)

        #dummy = Storage(name="resources", requires = IS_IN_SET(options))
        #selector = S3GroupedOptionsWidget(cols=2)
        #row = ("resource_selector__row",
        #"%s:" % labels.RESOURCES,
        #selector(dummy,
        #list(selected_resources),
        #_id="resource_selector"),
        #"")
        #fieldset = formstyle(form, [row])
        #form.append(fieldset)

        # Filters
        filter_form = S3FilterForm(filters, clear=False)
        fieldset = FIELDSET(filter_form.fields(None, subscription["get_vars"]),
                            _id="subscription-filter-form")
        form.append(fieldset)

        # Notification options
        rows = []
        stable = current.s3db.pr_subscription

        selector = S3GroupedOptionsWidget(cols=1)
        rows.append(("trigger_selector__row", "%s:" % labels.NOTIFY_ON,
                     selector(stable.notify_on,
                              subscription["notify_on"],
                              _id="trigger_selector"), ""))

        switch = S3GroupedOptionsWidget(cols=1, multiple=False, sort=False)
        rows.append(("frequency_selector__row", "%s:" % labels.FREQUENCY,
                     switch(stable.frequency,
                            subscription["frequency"],
                            _id="frequency_selector"), ""))

        # Deactivated: method selector
        #rows.append(("method_selector__row",
        #"%s:" % labels.NOTIFY_BY,
        #selector(stable.method,
        #subscription["method"],
        #_id="method_selector"),
        #""))

        fieldset = formstyle(form, rows)
        fieldset.insert(
            0,
            DIV(SPAN([I(_class="icon-reorder"), labels.MORE],
                     _class="toggle-text",
                     _style="display:none"),
                SPAN([I(_class="icon-reorder"), labels.LESS],
                     _class="toggle-text"),
                _id="notification-options",
                _class="control-group"))
        form.append(fieldset)

        # Submit button
        row = ("submit__row", "",
               INPUT(_type="submit", _value="Update Settings"), "")

        fieldset = formstyle(form, [row])
        form.append(fieldset)

        # Script (to extract filters on submit and toggle options visibility)
        script = """
$('#notification-options').click(function() {
  $(this).siblings().toggle();
  $(this).children().toggle();
});
$('#notification-options').siblings().toggle();
$('#notification-options').children().toggle();
$('#subscription-form').submit(function() {
  $('input[name="subscription-filters"]')
  .val(JSON.stringify(S3.search.getCurrentFilters($(this))));
});
"""
        response = current.response
        response.s3.jquery_ready.append(script)

        # Accept form
        if form.accepts(current.request.post_vars,
                        current.session,
                        formname="subscription",
                        keepvalues=True):

            formvars = form.vars

            listify = lambda x: None if not x else x if type(
                x) is list else [x]

            # Fixed resource selection:
            subscription["subscribe"] = [resources[0]]
            # Alternatively, with resource selector:
            #subscribe = listify(formvars.resources)
            #if subscribe:
            #subscription["subscribe"] = \
            #[r for idx, r in enumerate(resources)
            #if str(idx) in subscribe]

            subscription["filters"] = form.request_vars \
                                      .get("subscription-filters", None)

            subscription["notify_on"] = listify(formvars.notify_on)
            subscription["frequency"] = formvars.frequency
            # Fixed method:
            subscription["method"] = ["EMAIL"]
            # Alternatively, with method selector:
            #subscription["method"] = listify(formvars.method)

            success = self._update_subscription(subscription)

            if success:
                response.confirmation = messages.SUCCESS
            else:
                response.error = messages.ERROR

        return form
Exemplo n.º 5
0
# Uncomment to disable Inline Forms in Requests module
settings.req.inline_forms = False
settings.req.req_type = ["Stock"]
settings.req.use_commit = False
#settings.inv.collapse_tabs = True
# Should Requests ask whether Transportation is required?
settings.req.ask_transport = True

# =============================================================================
# Template Modules
# Comment/uncomment modules here to disable/enable them
settings.modules = OrderedDict([
    # Core modules which shouldn't be disabled
    ("default", Storage(
            name_nice = "RMS",
            restricted = False, # Use ACLs to control access to this module
            access = None,      # All Users (inc Anonymous) can see this module in the default menu & access the controller
            module_type = None  # This item is not shown in the menu
        )),
    ("admin", Storage(
            name_nice = T("Administration"),
            #description = "Site Administration",
            restricted = True,
            access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
            module_type = None  # This item is handled separately for the menu
        )),
    ("appadmin", Storage(
            name_nice = T("Administration"),
            #description = "Site Administration",
            restricted = True,
            module_type = None  # No Menu
        )),
Exemplo n.º 6
0
 def test_pickling(self):
     """ Test storage pickling """
     s = Storage(a=1)
     sd = pickle.dumps(s, pickle.HIGHEST_PROTOCOL)
     news = pickle.loads(sd)
     self.assertEqual(news.a, 1)
Exemplo n.º 7
0
# Enable this to change the label for 'Mobile Phone'
settings.ui.label_mobile_phone = "Cell Phone"
# Enable this to change the label for 'Postcode'
settings.ui.label_postcode = "ZIP Code"
# PDF to Letter
settings.base.paper_size = T("Letter")

# Comment/uncomment modules here to disable/enable them
settings.modules = OrderedDict([
    # Core modules which shouldn't be disabled
    (
        "default",
        Storage(
            name_nice=T("Home"),
            restricted=False,  # Use ACLs to control access to this module
            access=
            None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
            module_type=None  # This item is not shown in the menu
        )),
    (
        "admin",
        Storage(
            name_nice=T("Administration"),
            #description = "Site Administration",
            restricted=True,
            access=
            "|1|",  # Only Administrators can see this module in the default menu & access the controller
            module_type=None  # This item is handled separately for the menu
        )),
    (
        "appadmin",
Exemplo n.º 8
0
    def get_user(self):
        self.request = current.request
        self.ssl_client_raw_cert = self.request.env.ssl_client_raw_cert

        # rebuild the certificate passed by the env
        # this is double work, but it is the only way
        # since we cannot access the web server ssl engine directly

        if self.ssl_client_raw_cert:

            x509 = X509.load_cert_string(self.ssl_client_raw_cert,
                                         X509.FORMAT_PEM)
            # extract it from the cert
            self.serial = (self.request.env.ssl_client_serial
                           or ("%x" % x509.get_serial_number()).upper())

            subject = x509.get_subject()

            # Reordering the subject map to a usable Storage map
            # this allows us a cleaner syntax:
            # cn = self.subject.cn
            self.subject = Storage(
                filter(
                    None,
                    map(
                        lambda x: (
                            x,
                            map(
                                lambda y: y.get_data().as_text(),
                                subject.get_entries_by_nid(subject.nid[x]),
                            ),
                        ),
                        subject.nid.keys(),
                    ),
                ))

        # We did not get the client cert?
        if not self.ssl_client_raw_cert:
            return None

        # Try to reconstruct some useful info for web2py auth machinery

        p = profile = dict()

        username = p["username"] = reduce(
            lambda a, b: "%s | %s" % (a, b), self.subject.CN
            or self.subject.commonName)
        p["first_name"] = reduce(lambda a, b: "%s | %s" % (a, b),
                                 self.subject.givenName or username)
        p["last_name"] = reduce(lambda a, b: "%s | %s" % (a, b),
                                self.subject.surname)
        p["email"] = reduce(
            lambda a, b: "%s | %s" % (a, b),
            self.subject.Email or self.subject.emailAddress,
        )

        # IMPORTANT WE USE THE CERT SERIAL AS UNIQUE KEY FOR THE USER
        p["registration_id"] = self.serial

        # If the auth table has a field certificate it will be used to
        # save a PEM encoded copy of the user certificate.

        p["certificate"] = self.ssl_client_raw_cert

        return profile
Exemplo n.º 9
0
    def model(self):

        T = current.T
        db = current.db

        crud_strings = current.response.s3.crud_strings
        define_table = self.define_table
        location_id = self.gis_location_id

        # -----------------------------------------------------------
        # Water Zone Types
        #
        tablename = "water_zone_type"
        define_table(tablename, Field(
            "name",
            label=T("Name"),
        ), s3_comments(), *s3_meta_fields())

        # CRUD strings
        ADD_ZONE_TYPE = T("Create Zone Type")
        crud_strings[tablename] = Storage(
            label_create=ADD_ZONE_TYPE,
            title_display=T("Zone Type Details"),
            title_list=T("Zone Types"),
            title_update=T("Edit Zone Type"),
            title_upload=T("Import Zone Types"),
            label_list_button=T("List Zone Types"),
            label_delete_button=T("Delete Zone Type"),
            msg_record_created=T("Zone Type added"),
            msg_record_modified=T("Zone Type updated"),
            msg_record_deleted=T("Zone Type deleted"),
            msg_list_empty=T("No Zone Types currently registered"))

        zone_type_represent = S3Represent(lookup=tablename)

        self.configure(
            tablename,
            deduplicate=S3Duplicate(),
        )

        # -----------------------------------------------------------
        # Water Zones
        # - e.g. Floods
        #
        tablename = "water_zone"
        define_table(
            tablename, Field(
                "name",
                label=T("Name"),
            ),
            Field(
                "zone_type_id",
                db.water_zone_type,
                label=T("Type"),
                represent=zone_type_represent,
                requires=IS_EMPTY_OR(
                    IS_ONE_OF(db,
                              "water_zone_type.id",
                              zone_type_represent,
                              sort=True)),
                comment=S3PopupLink(
                    c="water",
                    f="zone_type",
                    label=ADD_ZONE_TYPE,
                    tooltip=
                    T("Select a Zone Type from the list or click 'Add Zone Type'"
                      ),
                ),
            ),
            location_id(widget=S3LocationSelector(
                catalog_layers=True,
                points=False,
                polygons=True,
            ), ), s3_comments(), *s3_meta_fields())

        # CRUD strings
        crud_strings[tablename] = Storage(
            label_create=T("Create Zone"),
            title_display=T("Zone Details"),
            title_list=T("Zones"),
            title_update=T("Edit Zone"),
            title_upload=T("Import Zones"),
            label_list_button=T("List Zones"),
            label_delete_button=T("Delete Zone"),
            msg_record_created=T("Zone added"),
            msg_record_modified=T("Zone updated"),
            msg_record_deleted=T("Zone deleted"),
            msg_list_empty=T("No Zones currently registered"))

        zone_represent = S3Represent(lookup=tablename)

        # -----------------------------------------------------------------------------
        # Rivers
        tablename = "water_river"
        define_table(
            tablename, Field(
                "name",
                label=T("Name"),
                requires=IS_NOT_EMPTY(),
            ),
            location_id(widget=S3LocationSelector(
                catalog_layers=True,
                points=False,
                polygons=True,
            )), s3_comments(), *s3_meta_fields())

        # CRUD strings
        ADD_RIVER = T("Create River")
        crud_strings[tablename] = Storage(
            label_create=ADD_RIVER,
            title_display=T("River Details"),
            title_list=T("Rivers"),
            title_update=T("Edit River"),
            label_list_button=T("List Rivers"),
            msg_record_created=T("River added"),
            msg_record_modified=T("River updated"),
            msg_record_deleted=T("River deleted"),
            msg_list_empty=T("No Rivers currently registered"))

        #represent = S3Represent(lookup = tablename)
        #river_id = S3ReusableField("river_id", "reference %s" % tablename,
        #                           label = T("River"),
        #                           ondelete = "RESTRICT",
        #                           represent = represent,
        #                           requires = IS_EMPTY_OR(IS_ONE_OF(db, "water_river.id", represent)),
        #                           comment = S3PopupLink(c = "water",
        #                                                 f = "river",
        #                                                 title = ADD_RIVER,
        #                                                 ),
        #                           )

        # -----------------------------------------------------------------------------
        # Gauges
        #
        # @ToDo: Link together ones on same river with upstream/downstream relationships
        #
        flowstatus_opts = {
            1: T("Normal"),
            2: T("High"),
            3: T("Very High"),
            4: T("Low")
        }

        tablename = "water_gauge"
        define_table(tablename,
                     Field("name",
                           label = T("Name"),
                           ),
                     Field("code",
                           label = T("Code"),
                           ),
                     #super_link("source_id", "doc_source_entity"),
                     location_id(),
                     Field("url",
                           label = T("URL"),
                           represent = lambda url: \
                                       A(url, _href=url, _target="blank"),
                           requires = IS_EMPTY_OR(IS_URL()),
                           ),
                     Field("image_url",
                           label = T("Image URL"),
                           ),
                     Field("discharge", "integer",
                           label = T("Discharge (cusecs)"),
                           ),
                     Field("status", "integer",
                           label = T("Flow Status"),
                           represent = lambda opt: \
                            flowstatus_opts.get(opt, opt),
                           requires = IS_EMPTY_OR(IS_IN_SET(flowstatus_opts)),
                           ),
                     s3_comments(),
                     *s3_meta_fields())

        crud_strings[tablename] = Storage(
            label_create=T("Create Gauge"),
            title_display=T("Gauge Details"),
            title_list=T("Gauges"),
            title_update=T("Edit Gauge"),
            title_map=T("Map of Gauges"),
            label_list_button=T("List Gauges"),
            msg_record_created=T("Gauge added"),
            msg_record_modified=T("Gauge updated"),
            msg_record_deleted=T("Gauge deleted"),
            msg_list_empty=T("No Gauges currently registered"))

        # -----------------------------------------------------------------------------
        # Debris Basins
        # http://dpw.lacounty.gov/wrd/sediment/why_move_dirt.cfm
        #
        #tablename = "water_debris_basin"
        #define_table(tablename,
        #             Field("name",
        #                   label = T("Name"),
        #                   ),
        #             location_id(),
        #             s3_comments(),
        #             *s3_meta_fields())

        #crud_strings[tablename] = Storage(
        #    label_create = T("Create Debris Basin"),
        #    title_display = T("Debris Basin Details"),
        #    title_list = T("Debris Basins"),
        #    title_update = T("Edit Debris Basin"),
        #    title_map = T("Map of Debris Basins"),
        #    label_list_button = T("List Debris Basins"),
        #    msg_record_created = T("Debris Basin added"),
        #    msg_record_modified = T("Debris Basin updated"),
        #    msg_record_deleted = T("Debris Basin deleted"),
        #    msg_list_empty = T("No Debris Basins currently registered"))

        # -----------------------------------------------------------------------------
        # Reservoirs
        # Water Storage areas
        #
        #tablename = "water_reservoir"
        #define_table(tablename,
        #             Field("name",
        #                   label = T("Name"),
        #                   ),
        #             location_id(),
        #             s3_comments(),
        #             *s3_meta_fields())

        #crud_strings[tablename] = Storage(
        #    label_create = T("Create Reservoir"),
        #    title_display = T("Reservoir Details"),
        #    title_list = T("Reservoirs"),
        #    title_update = T("Edit Reservoir"),
        #    title_map = T("Map of Reservoirs"),
        #    label_list_button = T("List Reservoirs"),
        #    msg_record_created = T("Reservoir added"),
        #    msg_record_modified = T("Reservoir updated"),
        #    msg_record_deleted = T("Reservoir deleted"),
        #    msg_list_empty = T("No Reservoirs currently registered"))

        # ---------------------------------------------------------------------
        # Pass names back to global scope (s3.*)
        #
        return {}
Exemplo n.º 10
0
    def model(self):

        T = current.T
        db = current.db

        # ---------------------------------------------------------------------
        # Scenarios
        #
        #  Scenarios are Templates for Incidents to plan what resources are required
        #

        tablename = "scenario_scenario"
        self.define_table(
            tablename,
            self.event_incident_type_id(),
            Field(
                "name",
                notnull=True,
                length=64,  # Mayon compatiblity
                label=T("Name"),
            ),
            s3_comments(),
            *s3_meta_fields())

        self.configure(
            tablename,
            # Open Map Config to set the default Location
            create_next=URL(args=["[id]", "config"]),
            deduplicate=self.scenario_duplicate,
        )

        # CRUD strings
        current.response.s3.crud_strings[tablename] = Storage(
            label_create=T("Create Scenario"),
            title_display=T("Scenario Details"),
            title_list=T("Scenarios"),
            title_update=T("Edit Scenario"),
            title_upload=T("Import Scenarios"),
            label_list_button=T("List Scenarios"),
            label_delete_button=T("Delete Scenario"),
            msg_record_created=T("Scenario added"),
            msg_record_modified=T("Scenario updated"),
            msg_record_deleted=T("Scenario deleted"),
            msg_list_empty=T("No Scenarios currently registered"))

        # Components
        self.add_components(
            tablename,
            # Tasks
            project_task={
                "link": "scenario_task",
                "joinby": "scenario_id",
                "key": "task_id",
                # @ToDo: Widget to handle embedded LocationSelector
                #"actuate": "embed",
                "actuate": "link",
                "autocomplete": "name",
                "autodelete": False,
            },
            # Human Resources
            hrm_human_resource={
                "link": "scenario_human_resource",
                "joinby": "scenario_id",
                "key": "human_resource_id",
                # @ToDo: Widget to handle embedded AddPersonWidget
                #"actuate": "embed",
                "actuate": "link",
                "autocomplete": "name",
                "autodelete": False,
            },
            # Assets
            asset_asset={
                "link": "scenario_asset",
                "joinby": "scenario_id",
                "key": "asset_id",
                "actuate": "embed",
                "autocomplete": "name",
                "autodelete": False,
            },
            # Facilities
            scenario_site="scenario_id",
            # Organisations
            org_organisation={
                "link": "scenario_organisation",
                "joinby": "scenario_id",
                "key": "organisation_id",
                "actuate": "embed",
                "autocomplete": "name",
                "autodelete": False,
            },
            # Map Config as a component of Scenarios
            gis_config={
                "link": "scenario_config",
                "joinby": "scenario_id",
                "multiple": False,
                "key": "config_id",
                "actuate": "replace",
                "autocomplete": "name",
                "autodelete": True,
            },
        )

        represent = S3Represent(lookup=tablename)
        scenario_id = S3ReusableField(
            "scenario_id",
            "reference %s" % tablename,
            label=T("Scenario"),
            ondelete="SET NULL",
            represent=represent,
            requires=IS_EMPTY_OR(
                IS_ONE_OF(
                    db,
                    "scenario_scenario.id",
                    represent,
                    orderby="scenario_scenario.name",
                    sort=True,
                )),
            sortby="name",
            # Comment these to use a Dropdown & not an Autocomplete
            #widget = S3AutocompleteWidget()
            #comment = DIV(_class="tooltip",
            #              _title="%s|%s" % (T("Scenario"),
            #                                current.messages.AUTOCOMPLETE_HELP))
        )

        # ---------------------------------------------------------------------
        # Pass names back to global scope (s3.*)
        #
        return dict(scenario_scenario_id=scenario_id, )
Exemplo n.º 11
0
def events():
    session.forget(response)
    start = request.vars.start
    end = request.vars.end

    try:
        start = datetime.datetime.fromtimestamp(int(start))
    except:
        start = request.now - datetime.timedelta(days=15)
    try:
        end = datetime.datetime.fromtimestamp(int(end))
    except:
        end = request.now + datetime.timedelta(days=15)

    evts = []

    all_episodes = db((db.episodes.seriesid == db.series.seriesid)
                      & (db.episodes.firstaired < end)
                      & (db.episodes.firstaired >= start)
                      & (db.seasons_settings.series_id == db.series.id)
                      & (db.episodes.seasonnumber ==
                         db.seasons_settings.seasonnumber)).select(
                             db.series.ALL, db.seasons_settings.ALL,
                             db.episodes.ALL)

    missing = {}
    for row in all_episodes:
        series_id, seasonnumber = row.seasons_settings.series_id, row.seasons_settings.seasonnumber
        key = "%s_%s" % (series_id, seasonnumber)
        if key not in missing:
            try:
                missing[key] = sj.loads(row.seasons_settings.season_status)
            except:
                pass
        icon = ''
        if row.episodes.inserted_on and row.seasons_settings.updated_on:
            cmp_to = max(row.episodes.inserted_on.date(),
                         row.episodes.firstaired)
            if cmp_to > row.seasons_settings.updated_on.date():
                icon = 'icon-refresh'
        if row.episodes.firstaired > request.now.date():
            icon = 'icon-calendar'
        if icon not in ('icon-refresh', 'icon-calendar'):
            try:
                icon = row.episodes.epnumber in missing[key][
                    'missing'] and 'icon-remove' or 'icon-ok'
            except:
                icon = 'icon-remove'
        rec_ = Storage()
        if icon == 'icon-remove':
            #check if we have a record in db.downloads
            rec = db(db.downloads.episode_id == row.episodes.id).select(
                limitby=(0, 1), orderby=~db.downloads.id).first()
            if rec and rec.episode_id:
                icon = 'icon-magnet'
                rec_ = rec
        evts.append(
            dict(id=row.episodes.id,
                 title="%s - S%.2dE%.2d - %s" %
                 (row.series.name, row.episodes.seasonnumber,
                  row.episodes.epnumber, row.episodes.name),
                 start=row.episodes.firstaired.strftime('%Y-%m-%dT%H:%M:%SZ'),
                 url=URL('series',
                         'index',
                         args=[row.series.id],
                         anchor="episode_%s" % (row.episodes.id)),
                 icon=str(
                     XML(
                         A(I(_class="%s icon-white" % icon),
                           _rel="tooltip",
                           _href=rec_.magnet,
                           _title=rec_.magnet)))))
    return sj.dumps(evts)
Exemplo n.º 12
0
def config(settings):
    """
        Template settings: 'Skeleton' designed to be copied to quickly create
                           custom templates

        All settings which are to configure a specific template are located
        here. Deployers should ideally not need to edit any other files outside
        of their template folder.
    """

    T = current.T

    #settings.base.system_name = T("Sahana Skeleton")
    #settings.base.system_name_short = T("Sahana")

    # PrePopulate data
    settings.base.prepopulate += ("skeleton", )
    #settings.base.prepopulate_demo += ("skeleton/Demo",)

    # Theme (folder to use for views/layout.html)
    #settings.base.theme = "skeleton"

    # Authentication settings
    # Should users be allowed to register themselves?
    #settings.security.self_registration = False
    # Do new users need to verify their email address?
    #settings.auth.registration_requires_verification = True
    # Do new users need to be approved by an administrator prior to being able to login?
    #settings.auth.registration_requires_approval = True
    #settings.auth.registration_requests_organisation = True

    # Approval emails get sent to all admins
    settings.mail.approver = "ADMIN"

    # Restrict the Location Selector to just certain countries
    # NB This can also be over-ridden for specific contexts later
    # e.g. Activities filtered to those of parent Project
    #settings.gis.countries = ("US",)
    # Uncomment to display the Map Legend as a floating DIV
    settings.gis.legend = "float"
    # Uncomment to Disable the Postcode selector in the LocationSelector
    #settings.gis.postcode_selector = False # @ToDo: Vary by country (include in the gis_config!)
    # Uncomment to show the Print control:
    # http://eden.sahanafoundation.org/wiki/UserGuidelines/Admin/MapPrinting
    #settings.gis.print_button = True

    # L10n settings
    # Languages used in the deployment (used for Language Toolbar, GIS Locations, etc)
    # http://www.loc.gov/standards/iso639-2/php/code_list.php
    #settings.L10n.languages = OrderedDict([
    #    ("ar", "Arabic"),
    #    ("bs", "Bosnian"),
    #    #("dv", "Divehi"), # Maldives
    #    ("en", "English"),
    #    ("fr", "French"),
    #    ("de", "German"),
    #    ("el", "Greek"),
    #    ("es", "Spanish"),
    #    #("id", "Bahasa Indonesia"),
    #    ("it", "Italian"),
    #    ("ja", "Japanese"),
    #    ("km", "Khmer"), # Cambodia
    #    ("ko", "Korean"),
    #    #("lo", "Lao"),
    #    #("mg", "Malagasy"),
    #    ("mn", "Mongolian"),
    #    #("ms", "Malaysian"),
    #    ("my", "Burmese"), # Myanmar
    #    ("ne", "Nepali"),
    #    ("prs", "Dari"), # Afghan Persian
    #    ("ps", "Pashto"), # Afghanistan, Pakistan
    #    ("pt", "Portuguese"),
    #    ("pt-br", "Portuguese (Brazil)"),
    #    ("ru", "Russian"),
    #    ("tet", "Tetum"),
    #    #("si", "Sinhala"), # Sri Lanka
    #    #("ta", "Tamil"), # India, Sri Lanka
    #    ("th", "Thai"),
    #    ("tl", "Tagalog"), # Philippines
    #    ("tr", "Turkish"),
    #    ("ur", "Urdu"), # Pakistan
    #    ("vi", "Vietnamese"),
    #    ("zh-cn", "Chinese (Simplified)"), # Mainland China
    #    ("zh-tw", "Chinese (Taiwan)"),
    #])
    # Default language for Language Toolbar (& GIS Locations in future)
    #settings.L10n.default_language = "en"
    # Uncomment to Hide the language toolbar
    #settings.L10n.display_toolbar = False
    # Default timezone for users
    #settings.L10n.timezone = "Europe/Berlin"
    # Number formats (defaults to ISO 31-0)
    # Decimal separator for numbers (defaults to ,)
    settings.L10n.decimal_separator = "."
    # Thousands separator for numbers (defaults to space)
    settings.L10n.thousands_separator = ","
    # Uncomment this to Translate Layer Names
    #settings.L10n.translate_gis_layer = True
    # Uncomment this to Translate Location Names
    #settings.L10n.translate_gis_location = True
    # Uncomment this to Translate Organisation Names/Acronyms
    #settings.L10n.translate_org_organisation = True
    # Finance settings
    #settings.fin.currencies = {
    #    "EUR" : "Euros",
    #    "GBP" : "Great British Pounds",
    #    "USD" : "United States Dollars",
    #}
    #settings.fin.currency_default = "USD"

    # Security Policy
    # http://eden.sahanafoundation.org/wiki/S3AAA#System-widePolicy
    # 1: Simple (default): Global as Reader, Authenticated as Editor
    # 2: Editor role required for Update/Delete, unless record owned by session
    # 3: Apply Controller ACLs
    # 4: Apply both Controller & Function ACLs
    # 5: Apply Controller, Function & Table ACLs
    # 6: Apply Controller, Function, Table ACLs and Entity Realm
    # 7: Apply Controller, Function, Table ACLs and Entity Realm + Hierarchy
    # 8: Apply Controller, Function, Table ACLs, Entity Realm + Hierarchy and Delegations
    #
    #settings.security.policy = 7 # Organisation-ACLs

    # -------------------------------------------------------------------------
    # Comment/uncomment modules here to disable/enable them
    # Modules menu is defined in modules/eden/menu.py
    settings.modules = OrderedDict([
        # Core modules which shouldn't be disabled
        (
            "default",
            Storage(
                name_nice=T("Home"),
                restricted=False,  # Use ACLs to control access to this module
                access=
                None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
                module_type=None  # This item is not shown in the menu
            )),
        (
            "admin",
            Storage(
                name_nice=T("Administration"),
                #description = "Site Administration",
                restricted=True,
                access=
                "|1|",  # Only Administrators can see this module in the default menu & access the controller
                module_type=None  # This item is handled separately for the menu
            )),
        (
            "appadmin",
            Storage(
                name_nice=T("Administration"),
                #description = "Site Administration",
                restricted=True,
                module_type=None  # No Menu
            )),
        (
            "errors",
            Storage(
                name_nice=T("Ticket Viewer"),
                #description = "Needed for Breadcrumbs",
                restricted=False,
                module_type=None  # No Menu
            )),
        #("sync", Storage(
        #    name_nice = T("Synchronization"),
        #    #description = "Synchronization",
        #    restricted = True,
        #    access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
        #    module_type = None  # This item is handled separately for the menu
        #)),
        #("tour", Storage(
        #    name_nice = T("Guided Tour Functionality"),
        #    module_type = None,
        #)),
        #("translate", Storage(
        #    name_nice = T("Translation Functionality"),
        #    #description = "Selective translation of strings based on module.",
        #    module_type = None,
        #)),
        (
            "gis",
            Storage(
                name_nice=T("Map"),
                #description = "Situation Awareness & Geospatial Analysis",
                restricted=True,
                module_type=6,  # 6th item in the menu
            )),
        (
            "pr",
            Storage(
                name_nice=T("Person Registry"),
                #description = "Central point to record details on People",
                restricted=True,
                access=
                "|1|",  # Only Administrators can see this module in the default menu (access to controller is possible to all still)
                module_type=10)),
        (
            "org",
            Storage(
                name_nice=T("Organizations"),
                #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities',
                restricted=True,
                module_type=1)),
        #("hrm", Storage(
        #    name_nice = T("Staff"),
        #    #description = "Human Resources Management",
        #    restricted = True,
        #    module_type = 2,
        #)),
        #("vol", Storage(
        #    name_nice = T("Volunteers"),
        #    #description = "Human Resources Management",
        #    restricted = True,
        #    module_type = 2,
        #)),
        (
            "cms",
            Storage(
                name_nice=T("Content Management"),
                #description = "Content Management System",
                restricted=True,
                module_type=10,
            )),
        #("doc", Storage(
        #    name_nice = T("Documents"),
        #    #description = "A library of digital resources, such as photos, documents and reports",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("msg", Storage(
        #    name_nice = T("Messaging"),
        #    #description = "Sends & Receives Alerts via Email & SMS",
        #    restricted = True,
        #    # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules.
        #    module_type = None,
        #)),
        #("supply", Storage(
        #    name_nice = T("Supply Chain Management"),
        #    #description = "Used within Inventory Management, Request Management and Asset Management",
        #    restricted = True,
        #    module_type = None, # Not displayed
        #)),
        #("inv", Storage(
        #    name_nice = T("Warehouses"),
        #    #description = "Receiving and Sending Items",
        #    restricted = True,
        #    module_type = 4
        #)),
        #("asset", Storage(
        #    name_nice = T("Assets"),
        #    #description = "Recording and Assigning Assets",
        #    restricted = True,
        #    module_type = 5,
        #)),
        # Vehicle depends on Assets
        #("vehicle", Storage(
        #    name_nice = T("Vehicles"),
        #    #description = "Manage Vehicles",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("req", Storage(
        #    name_nice = T("Requests"),
        #    #description = "Manage requests for supplies, assets, staff or other resources. Matches against Inventories where supplies are requested.",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("project", Storage(
        #    name_nice = T("Projects"),
        #    #description = "Tracking of Projects, Activities and Tasks",
        #    restricted = True,
        #    module_type = 2
        #)),
        #("cr", Storage(
        #    name_nice = T("Shelters"),
        #    #description = "Tracks the location, capacity and breakdown of victims in Shelters",
        #    restricted = True,
        #    module_type = 10
        #)),
        #("hms", Storage(
        #    name_nice = T("Hospitals"),
        #    #description = "Helps to monitor status of hospitals",
        #    restricted = True,
        #    module_type = 10
        #)),
        #("dvr", Storage(
        #   name_nice = T("Disaster Victim Registry"),
        #   #description = "Allow affected individuals & households to register to receive compensation and distributions",
        #   restricted = True,
        #   module_type = 10,
        #)),
        #("event", Storage(
        #    name_nice = T("Events"),
        #    #description = "Activate Events (e.g. from Scenario templates) for allocation of appropriate Resources (Human, Assets & Facilities).",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("transport", Storage(
        #   name_nice = T("Transport"),
        #   restricted = True,
        #   module_type = 10,
        #)),
        #("stats", Storage(
        #    name_nice = T("Statistics"),
        #    #description = "Manages statistics",
        #    restricted = True,
        #    module_type = None,
        #)),
    ])
Exemplo n.º 13
0
    def merge(self,
              original_id,
              duplicate_id,
              replace=None,
              update=None,
              main=True):
        """
            Merge a duplicate record into its original and remove the
            duplicate, updating all references in the database.

            @param original_id: the ID of the original record
            @param duplicate_id: the ID of the duplicate record
            @param replace: list fields names for which to replace the
                            values in the original record with the values
                            of the duplicate
            @param update: dict of {field:value} to update the final record
            @param main: internal indicator for recursive calls

            @status: work in progress
            @todo: de-duplicate components and link table entries

            @note: virtual references (i.e. non-SQL, without foreign key
                   constraints) must be declared in the table configuration
                   of the referenced table like:

                   s3db.configure(tablename, referenced_by=[(tablename, fieldname)])

                   This does not apply for list:references which will be found
                   automatically.

            @note: this method can only be run from master resources (in order
                   to find all components). To merge component records, you have
                   to re-define the component as a master resource.

            @note: CLI calls must db.commit()
        """

        self.main = main

        db = current.db
        resource = self.resource
        table = resource.table
        tablename = resource.tablename

        # Check for master resource
        if resource.parent:
            self.raise_error("Must not merge from component", SyntaxError)

        # Check permissions
        auth = current.auth
        has_permission = auth.s3_has_permission
        permitted = has_permission("update", table,
                                   record_id = original_id) and \
                    has_permission("delete", table,
                                   record_id = duplicate_id)
        if not permitted:
            self.raise_error("Operation not permitted", auth.permission.error)

        # Load all models
        s3db = current.s3db
        if main:
            s3db.load_all_models()

        # Get the records
        original = None
        duplicate = None
        query = table._id.belongs([original_id, duplicate_id])
        if "deleted" in table.fields:
            query &= (table.deleted != True)
        rows = db(query).select(table.ALL, limitby=(0, 2))
        for row in rows:
            record_id = row[table._id]
            if str(record_id) == str(original_id):
                original = row
                original_id = row[table._id]
            elif str(record_id) == str(duplicate_id):
                duplicate = row
                duplicate_id = row[table._id]
        msg = "Record not found: %s.%s"
        if original is None:
            self.raise_error(msg % (tablename, original_id), KeyError)
        if duplicate is None:
            self.raise_error(msg % (tablename, duplicate_id), KeyError)

        # Find all single-components
        single = Storage()
        for alias in resource.components:
            component = resource.components[alias]
            if not component.multiple:
                single[component.tablename] = component

        # Is this a super-entity?
        is_super_entity = table._id.name != "id" and \
                          "instance_type" in table.fields

        # Find all references
        referenced_by = list(table._referenced_by)

        # Append virtual references
        virtual_references = s3db.get_config(tablename, "referenced_by")
        if virtual_references:
            referenced_by.extend(virtual_references)

        # Find and append list:references
        for t in db:
            for f in t:
                ftype = str(f.type)
                if ftype[:14] == "list:reference" and \
                   ftype[15:15+len(tablename)] == tablename:
                    referenced_by.append((t._tablename, f.name))

        update_record = self.update_record
        delete_record = self.delete_record
        fieldname = self.fieldname

        # Update all references
        define_resource = s3db.resource
        for referee in referenced_by:

            if isinstance(referee, Field):
                tn, fn = referee.tablename, referee.name
            else:
                tn, fn = referee

            se = s3db.get_config(tn, "super_entity")
            if is_super_entity and \
               (isinstance(se, (list, tuple)) and tablename in se or \
                se == tablename):
                # Skip instance types of this super-entity
                continue

            # Reference field must exist
            if tn not in db or fn not in db[tn].fields:
                continue

            rtable = db[tn]
            if tn in single:
                component = single[tn]
                if component.link is not None:
                    component = component.link

                if fn == component.fkey:
                    # Single component => must reduce to one record
                    join = component.get_join()
                    pkey = component.pkey
                    lkey = component.lkey or component.fkey

                    # Get the component records
                    query = (table[pkey] == original[pkey]) & join
                    osub = db(query).select(limitby=(0, 1)).first()
                    query = (table[pkey] == duplicate[pkey]) & join
                    dsub = db(query).select(limitby=(0, 1)).first()

                    ctable = component.table

                    if dsub is None:
                        # No duplicate => skip this step
                        continue
                    elif not osub:
                        # No original => re-link the duplicate
                        dsub_id = dsub[ctable._id]
                        data = {lkey: original[pkey]}
                        success = update_record(ctable, dsub_id, dsub, data)
                    elif component.linked is not None:
                        # Duplicate link => remove it
                        dsub_id = dsub[component.table._id]
                        delete_record(ctable, dsub_id)
                    else:
                        # Two records => merge them
                        osub_id = osub[component.table._id]
                        dsub_id = dsub[component.table._id]
                        cresource = define_resource(component.tablename)
                        cresource.merge(osub_id, dsub_id,
                                        replace=replace,
                                        update=update,
                                        main=False)
                    continue

            # Find the foreign key
            rfield = rtable[fn]
            ktablename, key, multiple = s3_get_foreign_key(rfield)
            if not ktablename:
                if str(rfield.type) == "integer":
                    # Virtual reference
                    key = table._id.name
                else:
                    continue

            # Find the referencing records
            if multiple:
                query = rtable[fn].contains(duplicate[key])
            else:
                query = rtable[fn] == duplicate[key]
            rows = db(query).select(rtable._id, rtable[fn])

            # Update the referencing records
            for row in rows:
                if not multiple:
                    data = {fn:original[key]}
                else:
                    keys = [k for k in row[fn] if k != duplicate[key]]
                    if original[key] not in keys:
                        keys.append(original[key])
                    data = {fn:keys}
                update_record(rtable, row[rtable._id], row, data)

        # Merge super-entity records
        super_entities = resource.get_config("super_entity")
        if super_entities is not None:

            if not isinstance(super_entities, (list, tuple)):
                super_entities = [super_entities]

            for super_entity in super_entities:

                super_table = s3db.table(super_entity)
                if not super_table:
                    continue
                superkey = super_table._id.name

                skey_o = original[superkey]
                if not skey_o:
                    msg = "No %s found in %s.%s" % (superkey,
                                                    tablename,
                                                    original_id)
                    current.log.warning(msg)
                    s3db.update_super(table, original)
                    skey_o = original[superkey]
                if not skey_o:
                    continue
                skey_d = duplicate[superkey]
                if not skey_d:
                    msg = "No %s found in %s.%s" % (superkey,
                                                    tablename,
                                                    duplicate_id)
                    current.log.warning(msg)
                    continue

                sresource = define_resource(super_entity)
                sresource.merge(skey_o, skey_d,
                                replace=replace,
                                update=update,
                                main=False)

        # Merge and update original data
        data = Storage()
        if replace:
            for k in replace:
                fn = fieldname(k)
                if fn and fn in duplicate:
                    data[fn] = duplicate[fn]
        if update:
            for k, v in update.items():
                fn = fieldname(k)
                if fn in table.fields:
                    data[fn] = v
        if len(data):
            r = None
            p = Storage([(fn, "__deduplicate_%s__" % fn)
                         for fn in data
                         if table[fn].unique and \
                            table[fn].type == "string" and \
                            data[fn] == duplicate[fn]])
            if p:
                r = Storage([(fn, original[fn]) for fn in p])
                update_record(table, duplicate_id, duplicate, p)
            update_record(table, original_id, original, data)
            if r:
                update_record(table, duplicate_id, duplicate, r)

        # Delete the duplicate
        if not is_super_entity:
            self.merge_realms(table, original, duplicate)
            delete_record(table, duplicate_id, replaced_by=original_id)

        # Success
        return True
Exemplo n.º 14
0
class S3Merge(S3Method):
    """ Interactive Record Merger """

    DEDUPLICATE = "deduplicate"

    ORIGINAL = "original"
    DUPLICATE = "duplicate"
    KEEP = Storage(o="keep_original", d="keep_duplicate")

    # -------------------------------------------------------------------------
    def apply_method(self, r, **attr):
        """
            Apply Merge methods

            @param r: the S3Request
            @param attr: dictionary of parameters for the method handler

            @return: output object to send to the view
        """

        output = dict()

        auth = current.auth
        system_roles = auth.get_system_roles()
        if not auth.s3_has_role(system_roles.ADMIN):
            r.unauthorized()

        if r.method == "deduplicate":
            if r.http in ("GET", "POST"):
                if "remove" in r.get_vars:
                    remove = r.get_vars["remove"].lower() in ("1", "true")
                else:
                    remove = False
                if remove:
                    output = self.unmark(r, **attr)
                elif self.record_id:
                    if r.component and not r.component.multiple:
                        if r.http == "POST":
                            output = self.mark(r, **attr)
                        else:
                            # This does really not make much sense here
                            # => duplicate list is filtered per master
                            # and hence there is always only one record
                            output = self.duplicates(r, **attr)
                    else:
                        output = self.mark(r, **attr)
                else:
                    output = self.duplicates(r, **attr)
            elif r.http == "DELETE":
                output = self.unmark(r, **attr)
            else:
                r.error(405, current.ERROR.BAD_METHOD)
        else:
            r.error(405, current.ERROR.BAD_METHOD)

        return output

    # -------------------------------------------------------------------------
    def mark(self, r, **attr):
        """
            Bookmark the current record for de-duplication

            @param r: the S3Request
            @param attr: the controller parameters for the request
        """

        s3 = current.session.s3

        DEDUPLICATE = self.DEDUPLICATE

        if DEDUPLICATE not in s3:
            bookmarks = s3[DEDUPLICATE] = Storage()
        else:
            bookmarks = s3[DEDUPLICATE]

        record_id = str(self.record_id)
        if record_id:
            tablename = self.tablename
            if tablename not in bookmarks:
                records = bookmarks[tablename] = []
            else:
                records = bookmarks[tablename]
            if record_id not in records:
                records.append(record_id)
        else:
            return self.duplicates(r, **attr)

        return current.xml.json_message()

    # -------------------------------------------------------------------------
    def unmark(self, r, **attr):
        """
            Remove a record from the deduplicate list

            @param r: the S3Request
            @param attr: the controller parameters for the request
        """

        s3 = current.session.s3
        DEDUPLICATE = self.DEDUPLICATE

        success = current.xml.json_message()

        if DEDUPLICATE not in s3:
            return success
        else:
            bookmarks = s3[DEDUPLICATE]
        tablename = self.tablename
        if tablename not in bookmarks:
            return success
        else:
            records = bookmarks[tablename]

        record_id = str(self.record_id)
        if record_id:
            if record_id in records:
                records.remove(record_id)
            if not records:
                bookmarks.pop(tablename)
        else:
            bookmarks.pop(tablename)
        return success

    # -------------------------------------------------------------------------
    @classmethod
    def bookmark(cls, r, tablename, record_id):
        """
            Get a bookmark link for a record in order to embed it in the
            view, also renders a link to the duplicate bookmark list to
            initiate the merge process from

            @param r: the S3Request
            @param tablename: the table name
            @param record_id: the record ID
        """

        auth = current.auth
        system_roles = auth.get_system_roles()
        if not auth.s3_has_role(system_roles.ADMIN):
            return ""
        if r.component and not r.component.multiple:
            # Cannot de-duplicate single-components
            return ""

        s3 = current.session.s3
        DEDUPLICATE = cls.DEDUPLICATE

        remove = DEDUPLICATE in s3 and \
                 tablename in s3[DEDUPLICATE] and \
                 str(record_id) in s3[DEDUPLICATE][tablename] and \
                 True or False

        mark = "mark-deduplicate action-lnk"
        unmark = "unmark-deduplicate action-lnk"
        deduplicate = "deduplicate action-lnk"

        if remove:
            mark += " hide"
        else:
            unmark += " hide"
            deduplicate += " hide"

        T = current.T
        link = DIV(A(T("Mark as duplicate"),
                       _class=mark),
                   A(T("Unmark as duplicate"),
                       _class=unmark),
                   A("",
                     _href=r.url(method="deduplicate", vars={}),
                     _id="markDuplicateURL",
                     _class="hide"),
                   A(T("De-duplicate"),
                     _href=r.url(method="deduplicate", target=0, vars={}),
                     _class=deduplicate),
                   _id="markDuplicate")

        return link

    # -------------------------------------------------------------------------
    def duplicates(self, r, **attr):
        """
            Renders a list of all currently duplicate-bookmarked
            records in this resource, with option to select two
            and initiate the merge process from here

            @param r: the S3Request
            @param attr: the controller attributes for the request
        """

        s3 = current.response.s3
        session_s3 = current.session.s3

        resource = self.resource
        tablename = self.tablename

        if r.http == "POST":
            return self.merge(r, **attr)

        # Bookmarks
        record_ids = []
        DEDUPLICATE = self.DEDUPLICATE
        if DEDUPLICATE in session_s3:
            bookmarks = session_s3[DEDUPLICATE]
            if tablename in bookmarks:
                record_ids = bookmarks[tablename]
        query = FS(resource._id.name).belongs(record_ids)
        resource.add_filter(query)

        # Representation
        representation = r.representation

        # List fields
        list_fields = resource.list_fields()

        # Start/Limit
        get_vars = r.get_vars
        if representation == "aadata":
            start = get_vars.get("iDisplayStart", None)
            limit = get_vars.get("iDisplayLength", None)
            sEcho = int(get_vars.sEcho or 0)
        else: # catch all
            start = 0
            limit = s3.ROWSPERPAGE
        if limit is not None:
            try:
                start = int(start)
                limit = int(limit)
            except ValueError:
                start = None
                limit = None # use default
        else:
            start = None # use default
        if s3.dataTable_iDisplayLength:
            display_length = s3.dataTable_iDisplayLength
        else:
            display_length = 25
        if limit is None:
            limit = 2 * display_length

        # Datatable Filter
        totalrows = None
        if representation == "aadata":
            searchq, orderby, left = resource.datatable_filter(list_fields,
                                                               get_vars)
            if searchq is not None:
                totalrows = resource.count()
                resource.add_filter(searchq)
        else:
            orderby, left = None, None

        # Get the records
        data = resource.select(list_fields,
                               start=start,
                               limit=limit,
                               orderby=orderby,
                               left=left,
                               count=True,
                               represent=True)


        displayrows = data["numrows"]
        if totalrows is None:
            totalrows = displayrows

        # Generate a datatable
        dt = S3DataTable(data["rfields"], data["rows"])

        datatable_id = "s3merge_1"

        if representation == "aadata":
            output = dt.json(totalrows,
                             displayrows,
                             datatable_id,
                             sEcho,
                             dt_bulk_actions = [(current.T("Merge"),
                                                 "merge", "pair-action")])

        elif representation == "html":
            # Initial HTML response
            T = current.T
            output = {"title": T("De-duplicate Records")}

            url = r.url(representation="aadata")

            #url = "/%s/%s/%s/deduplicate.aadata" % (r.application,
                                                    #r.controller,
                                                    #r.function)
            items =  dt.html(totalrows,
                             displayrows,
                             datatable_id,
                             dt_ajax_url=url,
                             dt_displayLength=display_length,
                             dt_bulk_actions = [(T("Merge"),
                                                 "merge", "pair-action")])

            output["items"] = items
            s3.actions = [{"label": str(T("View")),
                           "url": r.url(target="[id]", method="read"),
                           "_class": "action-btn",
                           },
                          ]

            if len(record_ids) < 2:
                output["add_btn"] = DIV(
                    SPAN(T("You need to have at least 2 records in this list in order to merge them."),
                         # @ToDo: Move to CSS
                         _style="float:left;padding-right:10px;"),
                    A(T("Find more"),
                      _href=r.url(method="", id=0, component_id=0, vars={}))
                )
            else:
                output["add_btn"] = DIV(
                    SPAN(T("Select 2 records from this list, then click 'Merge'.")),
                )

            s3.dataTableID = [datatable_id]
            current.response.view = self._view(r, "list.html")

        else:
            r.error(501, current.ERROR.BAD_FORMAT)

        return output

    # -------------------------------------------------------------------------
    def merge(self, r, **attr):
        """
            Merge form for two records

            @param r: the S3Request
            @param **attr: the controller attributes for the request

            @note: this method can always only be POSTed, and requires
                   both "selected" and "mode" in post_vars, as well as
                   the duplicate bookmarks list in session.s3
        """

        T = current.T
        session = current.session
        response = current.response

        output = dict()
        tablename = self.tablename

        # Get the duplicate bookmarks
        s3 = session.s3
        DEDUPLICATE = self.DEDUPLICATE
        if DEDUPLICATE in s3:
            bookmarks = s3[DEDUPLICATE]
            if tablename in bookmarks:
                record_ids = bookmarks[tablename]

        # Process the post variables
        post_vars = r.post_vars
        mode = post_vars.get("mode")
        selected = post_vars.get("selected", "")
        selected = selected.split(",")
        if mode == "Inclusive":
            ids = selected
        elif mode == "Exclusive":
            ids = [i for i in record_ids if i not in selected]
        else:
            # Error
            ids = []
        if len(ids) != 2:
            r.error(501, T("Please select exactly two records"),
                    next = r.url(id=0, vars={}))

        # Get the selected records
        table = self.table
        query = (table._id == ids[0]) | (table._id == ids[1])
        orderby = table.created_on if "created_on" in table else None
        rows = current.db(query).select(orderby=orderby,
                                        limitby=(0, 2))
        if len(rows) != 2:
            r.error(404, current.ERROR.BAD_RECORD, next = r.url(id=0, vars={}))
        original = rows[0]
        duplicate = rows[1]

        # Prepare form construction
        formfields = [f for f in table if f.readable or f.writable]

        ORIGINAL, DUPLICATE, KEEP = self.ORIGINAL, self.DUPLICATE, self.KEEP
        keep_o = KEEP.o in post_vars and post_vars[KEEP.o]
        keep_d = KEEP.d in post_vars and post_vars[KEEP.d]

        trs = []
        init_requires = self.init_requires
        for f in formfields:

            # Render the widgets
            oid = "%s_%s" % (ORIGINAL, f.name)
            did = "%s_%s" % (DUPLICATE, f.name)
            sid = "swap_%s" % f.name
            init_requires(f, original[f], duplicate[f])
            if keep_o or not any((keep_o, keep_d)):
                owidget = self.widget(f, original[f], _name=oid, _id=oid)
            else:
                try:
                    owidget = s3_represent_value(f, value=original[f])
                except:
                    owidget = s3_unicode(original[f])
            if keep_d or not any((keep_o, keep_d)):
                dwidget = self.widget(f, duplicate[f], _name=did, _id=did)
            else:
                try:
                    dwidget = s3_represent_value(f, value=duplicate[f])
                except:
                    dwidget = s3_unicode(duplicate[f])

            # Swap button
            if not any((keep_o, keep_d)):
                swap = INPUT(_value="<-->",
                             _class="swap-button",
                             _id=sid,
                             _type="button")
            else:
                swap = DIV(_class="swap-button")

            if owidget is None or dwidget is None:
                continue

            # Render label row
            label = f.label
            trs.append(TR(TD(label, _class="w2p_fl"),
                          TD(),
                          TD(label, _class="w2p_fl")))

            # Append widget row
            trs.append(TR(TD(owidget, _class="mwidget"),
                          TD(swap),
                          TD(dwidget, _class="mwidget")))

        # Show created_on/created_by for each record
        if "created_on" in table:
            original_date = original.created_on
            duplicate_date = duplicate.created_on
            if "created_by" in table:
                represent = table.created_by.represent
                original_author = represent(original.created_by)
                duplicate_author = represent(duplicate.created_by)
                created = T("Created on %s by %s")
                original_created = created % (original_date, original_author)
                duplicate_created = created % (duplicate_date, duplicate_author)
            else:
                created = T("Created on %s")
                original_created = created % original_date
                duplicate_created = created % duplicate_date
        else:
            original_created = ""
            duplicate_created = ""

        # Page title and subtitle
        output["title"] = T("Merge records")
        #output["subtitle"] = self.crud_string(tablename, "title_list")

        # Submit buttons
        if keep_o or not any((keep_o, keep_d)):
            submit_original = INPUT(_value=T("Keep Original"),
                                    _type="submit", _name=KEEP.o, _id=KEEP.o)
        else:
            submit_original = ""

        if keep_d or not any((keep_o, keep_d)):
            submit_duplicate = INPUT(_value=T("Keep Duplicate"),
                                     _type="submit", _name=KEEP.d, _id=KEEP.d)
        else:
            submit_duplicate = ""

        # Build the form
        form = FORM(TABLE(
                        THEAD(
                            TR(TH(H3(T("Original"))),
                               TH(),
                               TH(H3(T("Duplicate"))),
                            ),
                            TR(TD(original_created),
                               TD(),
                               TD(duplicate_created),
                               _class="authorinfo",
                            ),
                        ),
                        TBODY(trs),
                        TFOOT(
                            TR(TD(submit_original),
                               TD(),
                               TD(submit_duplicate),
                            ),
                        ),
                    ),
                    # Append mode and selected - required to get back here!
                    hidden = {
                        "mode": "Inclusive",
                        "selected": ",".join(ids),
                    }
                )

        output["form"] = form

        # Add RESET and CANCEL options
        output["reset"] = FORM(INPUT(_value=T("Reset"),
                                     _type="submit",
                                     _name="reset", _id="form-reset"),
                               A(T("Cancel"), _href=r.url(id=0, vars={}), _class="action-lnk"),
                               hidden = {"mode": mode,
                                         "selected": ",".join(ids)})

        # Process the merge form
        formname = "merge_%s_%s_%s" % (tablename,
                                       original[table._id],
                                       duplicate[table._id])
        if form.accepts(post_vars, session,
                        formname=formname,
                        onvalidation=lambda form: self.onvalidation(tablename, form),
                        keepvalues=False,
                        hideerror=False):

            s3db = current.s3db

            if form.vars[KEEP.d]:
                prefix = "%s_" % DUPLICATE
                original, duplicate = duplicate, original
            else:
                prefix = "%s_" % ORIGINAL

            data = Storage()
            for key in form.vars:
                if key.startswith(prefix):
                    fname = key.split("_", 1)[1]
                    data[fname] = form.vars[key]

            search = False
            resource = s3db.resource(tablename)
            try:
                resource.merge(original[table._id],
                               duplicate[table._id],
                               update=data)
            except current.auth.permission.error:
                r.unauthorized()
            except KeyError:
                r.error(404, current.ERROR.BAD_RECORD)
            except:
                import sys
                r.error(424,
                        T("Could not merge records. (Internal Error: %s)") %
                            sys.exc_info()[1],
                        next=r.url())
            else:
                # Cleanup bookmark list
                if mode == "Inclusive":
                    bookmarks[tablename] = [i for i in record_ids if i not in ids]
                    if not bookmarks[tablename]:
                        del bookmarks[tablename]
                        search = True
                elif mode == "Exclusive":
                    bookmarks[tablename].extend(ids)
                    if not selected:
                        search = True
                # Confirmation message
                # @todo: Having the link to the merged record in the confirmation
                # message would be nice, but it's currently not clickable there :/
                #result = A(T("Open the merged record"),
                        #_href=r.url(method="read",
                                    #id=original[table._id],
                                    #vars={}))
                response.confirmation = T("Records merged successfully.")

            # Go back to bookmark list
            if search:
                self.next = r.url(method="", id=0, vars={})
            else:
                self.next = r.url(id=0, vars={})

        # View
        response.view = self._view(r, "merge.html")

        return output

    # -------------------------------------------------------------------------
    @classmethod
    def onvalidation(cls, tablename, form):
        """
            Runs the onvalidation routine for this table, and maps
            form fields and errors to regular keys

            @param tablename: the table name
            @param form: the FORM
        """

        ORIGINAL, DUPLICATE, KEEP = cls.ORIGINAL, cls.DUPLICATE, cls.KEEP

        if form.vars[KEEP.d]:
            prefix = "%s_" % DUPLICATE
        else:
            prefix = "%s_" % ORIGINAL

        data = Storage()
        for key in form.vars:
            if key.startswith(prefix):
                fname = key.split("_", 1)[1]
                data[fname] = form.vars[key]

        errors = current.s3db.onvalidation(tablename, data, method="update")
        if errors:
            for fname in errors:
                form.errors["%s%s" % (prefix, fname)] = errors[fname]
        return

    # -------------------------------------------------------------------------
    @staticmethod
    def init_requires(field, o, d):
        """
            Initialize all IS_NOT_IN_DB to allow override of
            both original and duplicate value

            @param field: the Field
            @param o: the original value
            @param d: the duplicate value
        """

        allowed_override = [str(o), str(d)]

        requires = field.requires
        if field.unique and not requires:
            field.requires = IS_NOT_IN_DB(current.db, str(field),
                                          allowed_override=allowed_override)
        else:
            if not isinstance(requires, (list, tuple)):
                requires = [requires]
            for r in requires:
                if hasattr(r, "allowed_override"):
                    r.allowed_override = allowed_override
                if hasattr(r, "other") and \
                   hasattr(r.other, "allowed_override"):
                    r.other.allowed_override = allowed_override
        return

    # -------------------------------------------------------------------------
    @staticmethod
    def widget(field, value, download_url=None, **attr):
        """
            Render a widget for the Field/value

            @param field: the Field
            @param value: the value
            @param download_url: the download URL for upload fields
            @param attr: the HTML attributes for the widget

            @note: upload fields currently not rendered because the
                   upload widget wouldn't render the current value,
                   hence pointless for merge
            @note: custom widgets must allow override of both _id
                   and _name attributes
        """

        widgets = SQLFORM.widgets
        ftype = str(field.type)

        if ftype == "id":
            inp = None
        elif ftype == "upload":
            inp = None
            #if field.widget:
                #inp = field.widget(field, value,
                                   #download_url=download_url, **attr)
            #else:
                #inp = widgets.upload.widget(field, value,
                                            #download_url=download_url, **attr)
        elif field.widget:
            if isinstance(field.widget, (S3LocationSelectorWidget, S3LocationSelectorWidget2)):
                # Workaround - location selector does not support
                # renaming of the fields => switch to dropdown
                level = None
                if value:
                    try:
                        level = s3db.gis_location[value].level
                    except:
                        pass
                widget = S3LocationDropdownWidget(level, value)
                field.requires = IS_EMPTY_OR(IS_ONE_OF(current.db, "gis_location.id"))
                inp = widget(field, value, **attr)
            else:
                inp = field.widget(field, value, **attr)
        elif ftype == "boolean":
            inp = widgets.boolean.widget(field, value, **attr)
        elif widgets.options.has_options(field):
            if not field.requires.multiple:
                inp = widgets.options.widget(field, value, **attr)
            else:
                inp = widgets.multiple.widget(field, value, **attr)
        elif ftype[:5] == "list:":
            inp = widgets.list.widget(field, value, **attr)
        elif ftype == "text":
            inp = widgets.text.widget(field, value, **attr)
        elif ftype == "password":
            inp = widgets.password.widget(field, value, **attr)
        elif ftype == "blob":
            inp = None
        else:
            ftype = ftype in widgets and ftype or "string"
            inp = widgets[ftype].widget(field, value, **attr)

        return inp
Exemplo n.º 15
0
    def model(self):

        T = current.T
        db = current.db
        add_component = self.add_component
        configure = self.configure
        crud_strings = current.response.s3.crud_strings
        define_table = self.define_table

        # ---------------------------------------------------------------------
        # Series
        # - lists of Posts displaying in recent-first mode
        #

        tablename = "cms_series"
        table = define_table(
            tablename,
            Field("name", notnull=True, label=T("Name")),
            Field("avatar",
                  "boolean",
                  default=False,
                  label=T("Show author picture?")),
            Field("replies",
                  "boolean",
                  default=False,
                  label=T("Comments permitted?")),
            s3_comments(),
            # Multiple Roles (@ToDo: Implement the restriction)
            s3_roles_permitted(readable=False, writable=False),
            *s3_meta_fields())

        # CRUD Strings
        ADD_SERIES = T("Add Series")
        crud_strings[tablename] = Storage(
            title_create=ADD_SERIES,
            title_display=T("Series Details"),
            title_list=T("Series"),
            title_update=T("Edit Series"),
            title_search=T("Search Series"),
            title_upload=T("Import Series"),
            subtitle_create=T("Add New Series"),
            label_list_button=T("List Series"),
            label_create_button=ADD_SERIES,
            msg_record_created=T("Series added"),
            msg_record_modified=T("Series updated"),
            msg_record_deleted=T("Series deleted"),
            msg_list_empty=T("No series currently defined"))

        # Reusable field
        series_id = S3ReusableField("series_id",
                                    table,
                                    readable=False,
                                    writable=False,
                                    requires=IS_NULL_OR(
                                        IS_ONE_OF(db, "cms_series.id",
                                                  "%(name)s")),
                                    ondelete="CASCADE")

        # Resource Configuration
        configure(tablename,
                  onaccept=self.series_onaccept,
                  create_next=URL(f="series", args=["[id]", "post"]))

        # Components
        add_component("cms_post", cms_series="series_id")

        # ---------------------------------------------------------------------
        # Posts
        # - single blocks of rich text which can be embedded into a page,
        #   be viewed as full pages or as part of a Series
        #

        modules = {}
        _modules = current.deployment_settings.modules
        for module in _modules:
            if module in ["appadmin", "errors", "sync"]:
                continue
            modules[module] = _modules[module].name_nice

        tablename = "cms_post"
        table = define_table(tablename,
                             series_id(),
                             Field("module",
                                   requires=IS_NULL_OR(
                                                IS_IN_SET_LAZY(lambda: \
                                            sort_dict_by_values(modules))),
                                   comment=T("If you specify a module then this will be used as the text in that module's index page"),
                                   label=T("Module")),
                             Field("name", notnull=True,
                                   comment=T("This isn't visible to the published site, but is used to allow menu items to point to the page"),
                                   label=T("Name")),
                             Field("title",
                                   comment=T("The title of the page, as seen in the browser (optional)"),
                                   label=T("Title")),
                             Field("body", "text", notnull=True,
                                   widget = s3_richtext_widget,
                                   label=T("Body")),
                             Field("avatar", "boolean",
                                   default=False,
                                   label=T("Show author picture?")),
                             Field("replies", "boolean",
                                   default=False,
                                   label=T("Comments permitted?")),
                             #Field("published", "boolean",
                             #      default=True,
                             #      label=T("Published")),
                             s3_comments(),
                             # Multiple Roles (@ToDo: Implement the restriction)
                             s3_roles_permitted(
                                                readable = False,
                                                writable = False
                                                ),
                             *s3_meta_fields())

        # CRUD Strings
        ADD_POST = T("Add Post")
        crud_strings[tablename] = Storage(
            title_create=ADD_POST,
            title_display=T("Post Details"),
            title_list=T("Posts"),
            title_update=T("Edit Post"),
            title_search=T("Search Posts"),
            title_upload=T("Import Posts"),
            subtitle_create=T("Add New Post"),
            label_list_button=T("List Posts"),
            label_create_button=ADD_POST,
            msg_record_created=T("Post added"),
            msg_record_modified=T("Post updated"),
            msg_record_deleted=T("Post deleted"),
            msg_list_empty=T("No posts currently defined"))

        # Reusable field
        post_id = S3ReusableField("post_id", table,
                                  label = T("Post"),
                                  sortby="name",
                                  requires = IS_NULL_OR(
                                                IS_ONE_OF(db, "cms_post.id",
                                                          "%(name)s")),
                                  represent = lambda id, row=None: \
                                                (id and [db.cms_post[id].name] or [NONE])[0],
                                  comment = S3AddResourceLink(c="cms",
                                                              f="post",
                                                              title=ADD_POST,
                                                              tooltip=T("A block of rich text which could be embedded into a page, viewed as a complete page or viewed as a list of news items.")),
                                  ondelete = "CASCADE")

        # Resource Configuration
        configure(tablename, onaccept=self.post_onaccept)

        # Components
        add_component("cms_comment", cms_post="post_id")

        # ---------------------------------------------------------------------
        # Comments
        # - threaded comments on Posts
        #
        # @ToDo: Attachments?
        #
        # Parent field allows us to:
        #  * easily filter for top-level threads
        #  * easily filter for next level of threading
        #  * hook a new reply into the correct location in the hierarchy
        #
        tablename = "cms_comment"
        table = define_table(
            tablename,
            Field("parent",
                  "reference cms_comment",
                  requires=IS_NULL_OR(IS_ONE_OF(db, "cms_comment.id")),
                  readable=False), post_id(),
            Field("body", "text", notnull=True, label=T("Comment")),
            *s3_meta_fields())

        # Resource Configuration
        configure(tablename,
                  list_fields=["id", "post_id", "created_by", "modified_on"])

        # ---------------------------------------------------------------------
        # Pass variables back to global scope (s3db.*)
        #
        return Storage()
Exemplo n.º 16
0
def config(settings):
    """
        Settings for an outbreak of an infectious disease, such as Ebola:
        http://eden.sahanafoundation.org/wiki/Deployments/Ebola
    """

    T = current.T

    settings.base.system_name = T("Sahana Ebola Response")
    settings.base.system_name_short = T("Sahana")

    # PrePopulate data
    settings.base.prepopulate += ("Disease", "default/users")

    # Theme (folder to use for views/layout.html)
    settings.base.theme = "Disease"
    # Uncomment to show a default cancel button in standalone create/update forms
    settings.ui.default_cancel_button = True

    # Authentication settings
    # Should users be allowed to register themselves?
    #settings.security.self_registration = False
    # Do new users need to verify their email address?
    settings.auth.registration_requires_verification = True
    # Do new users need to be approved by an administrator prior to being able to login?
    #settings.auth.registration_requires_approval = True
    #settings.auth.registration_requests_organisation = True

    # Approval emails get sent to all admins
    settings.mail.approver = "ADMIN"

    # Restrict the Location Selector to just certain countries
    # NB This can also be over-ridden for specific contexts later
    # e.g. Activities filtered to those of parent Project
    settings.gis.countries = ("GN", "LR", "ML", "NG", "SL", "SN")
    # Uncomment to display the Map Legend as a floating DIV
    settings.gis.legend = "float"
    # Uncomment to open Location represent links in a Popup Window
    settings.gis.popup_location_link = True

    # L10n settings
    # Languages used in the deployment (used for Language Toolbar & GIS Locations)
    # http://www.loc.gov/standards/iso639-2/php/code_list.php
    settings.L10n.languages = OrderedDict([
        ("en", "English"),
        ("fr", "Français"),
    ])
    # Default language for Language Toolbar (& GIS Locations in future)
    #settings.L10n.default_language = "en"
    # Uncomment to Hide the language toolbar
    #settings.L10n.display_toolbar = False
    # Default timezone for users
    #settings.L10n.utc_offset = "+0100"
    # Number formats (defaults to ISO 31-0)
    # Decimal separator for numbers (defaults to ,)
    settings.L10n.decimal_separator = "."
    # Thousands separator for numbers (defaults to space)
    settings.L10n.thousands_separator = ","

    # Security Policy
    # http://eden.sahanafoundation.org/wiki/S3AAA#System-widePolicy
    # 1: Simple (default): Global as Reader, Authenticated as Editor
    # 2: Editor role required for Update/Delete, unless record owned by session
    # 3: Apply Controller ACLs
    # 4: Apply both Controller & Function ACLs
    # 5: Apply Controller, Function & Table ACLs
    # 6: Apply Controller, Function, Table ACLs and Entity Realm
    # 7: Apply Controller, Function, Table ACLs and Entity Realm + Hierarchy
    # 8: Apply Controller, Function, Table ACLs, Entity Realm + Hierarchy and Delegations
    #
    #settings.security.policy = 7 # Organisation-ACLs

    # RSS feeds
    #settings.frontpage.rss = [
    #    {"title": "Eden",
    #     # Trac timeline
    #     "url": "http://eden.sahanafoundation.org/timeline?ticket=on&changeset=on&milestone=on&wiki=on&max=50&daysback=90&format=rss"
    #    },
    #    {"title": "Twitter",
    #     # @SahanaFOSS
    #     #"url": "https://search.twitter.com/search.rss?q=from%3ASahanaFOSS" # API v1 deprecated, so doesn't work, need to use 3rd-party service, like:
    #     "url": "http://www.rssitfor.me/getrss?name=@SahanaFOSS"
    #     # Hashtag
    #     #url: "http://search.twitter.com/search.atom?q=%23eqnz" # API v1 deprecated, so doesn't work, need to use 3rd-party service, like:
    #     #url: "http://api2.socialmention.com/search?q=%23eqnz&t=all&f=rss"
    #    }
    #]

    # -----------------------------------------------------------------------------
    # Summary Pages
    # - this is currently the default
    #settings.ui.summary = ({"common": True,
    #                        "name": "add",
    #                        "widgets": [{"method": "create"}],
    #                        },
    #                       {"common": True,
    #                        "name": "cms",
    #                        "widgets": [{"method": "cms"}]
    #                        },
    #                       {"name": "table",
    #                        "label": "Table",
    #                        "widgets": [{"method": "datatable"}]
    #                        },
    #                       {"name": "charts",
    #                        "label": "Report",
    #                        "widgets": [{"method": "report", "ajax_init": True}]
    #                        },
    #                       {"name": "map",
    #                        "label": "Map",
    #                        "widgets": [{"method": "map", "ajax_init": True}],
    #                        },
    #                       )

    # -----------------------------------------------------------------------------
    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))

    settings.customise_hms_hospital_resource = customise_hms_hospital_resource

    # -----------------------------------------------------------------------------
    def customise_disease_stats_data_resource(r, tablename):

        s3db = current.s3db
        # Load model & set defaults
        table = s3db.disease_stats_data

        # Add a TimePlot tab to summary page
        summary = settings.get_ui_summary()
        settings.ui.summary = list(summary) + [{
            "name":
            "timeplot",
            "label":
            "Progression",
            "widgets": [{
                "method": "timeplot",
                "ajax_init": True,
            }],
        }]

        # Default parameter filter
        def default_parameter_filter(selector, tablename=None):
            ptable = s3db.stats_parameter
            query = (ptable.deleted == False) & \
                    (ptable.name == "Cases")
            row = current.db(query).select(ptable.parameter_id,
                                           limitby=(0, 1)).first()
            if row:
                return row.parameter_id
            else:
                return None

        # Set filter defaults
        resource = r.resource
        filter_widgets = resource.get_config("filter_widgets", [])
        for filter_widget in filter_widgets:
            if filter_widget.field == "parameter_id":
                filter_widget.opts.default = default_parameter_filter
            elif filter_widget.field == "location_id$level":
                filter_widget.opts.default = "L2"

    settings.customise_disease_stats_data_resource = customise_disease_stats_data_resource

    # -----------------------------------------------------------------------------
    def customise_stats_demographic_data_resource(r, tablename):

        s3db = current.s3db
        # Load model & set defaults
        table = s3db.stats_demographic_data

        # Default parameter filter
        def default_parameter_filter(selector, tablename=None):
            ptable = s3db.stats_parameter
            query = (ptable.deleted == False) & \
                    (ptable.name == "Population Total")
            row = current.db(query).select(ptable.parameter_id,
                                           limitby=(0, 1)).first()
            if row:
                return row.parameter_id
            else:
                return None

        # Set filter defaults
        resource = r.resource
        filter_widgets = resource.get_config("filter_widgets", [])
        for filter_widget in filter_widgets:
            if filter_widget.field == "parameter_id":
                filter_widget.opts.default = default_parameter_filter
            elif filter_widget.field == "location_id$level":
                filter_widget.opts.default = "L2"

    settings.customise_stats_demographic_data_resource = customise_stats_demographic_data_resource

    # -----------------------------------------------------------------------------
    # Comment/uncomment modules here to disable/enable them
    # Modules menu is defined in modules/eden/menu.py
    settings.modules = OrderedDict([
        # Core modules which shouldn't be disabled
        (
            "default",
            Storage(
                name_nice=T("Home"),
                restricted=False,  # Use ACLs to control access to this module
                access=
                None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
                module_type=None  # This item is not shown in the menu
            )),
        (
            "admin",
            Storage(
                name_nice=T("Administration"),
                #description = "Site Administration",
                restricted=True,
                access=
                "|1|",  # Only Administrators can see this module in the default menu & access the controller
                module_type=None  # This item is handled separately for the menu
            )),
        (
            "appadmin",
            Storage(
                name_nice=T("Administration"),
                #description = "Site Administration",
                restricted=True,
                module_type=None  # No Menu
            )),
        (
            "errors",
            Storage(
                name_nice=T("Ticket Viewer"),
                #description = "Needed for Breadcrumbs",
                restricted=False,
                module_type=None  # No Menu
            )),
        #("sync", Storage(
        #    name_nice = T("Synchronization"),
        #    #description = "Synchronization",
        #    restricted = True,
        #    access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
        #    module_type = None  # This item is handled separately for the menu
        #)),
        #("tour", Storage(
        #    name_nice = T("Guided Tour Functionality"),
        #    module_type = None,
        #)),
        #("translate", Storage(
        #    name_nice = T("Translation Functionality"),
        #    #description = "Selective translation of strings based on module.",
        #    module_type = None,
        #)),
        (
            "gis",
            Storage(
                name_nice=T("Map"),
                #description = "Situation Awareness & Geospatial Analysis",
                restricted=True,
                module_type=6,  # 6th item in the menu
            )),
        (
            "pr",
            Storage(
                name_nice=T("Person Registry"),
                #description = "Central point to record details on People",
                restricted=True,
                access=
                "|1|",  # Only Administrators can see this module in the default menu (access to controller is possible to all still)
                module_type=10)),
        (
            "org",
            Storage(
                name_nice=T("Organizations"),
                #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities',
                restricted=True,
                module_type=10)),
        (
            "stats",
            Storage(
                name_nice=T("Statistics"),
                #description = "Manages statistics",
                restricted=True,
                module_type=7,
            )),
        # Primary target usecase currently
        (
            "hms",
            Storage(
                name_nice=T("Hospitals"),
                #description = "Helps to monitor status of hospitals",
                restricted=True,
                module_type=2)),
        (
            "disease",
            Storage(
                name_nice=T("Disease Tracking"),
                #description = "Helps to track cases and trace contacts in disease outbreaks",
                restricted=True,
                module_type=1)),
        # Access to Procedures is key: either attach files or write directly in rich-text forms
        (
            "cms",
            Storage(
                name_nice=T("Content Management"),
                #description = "Content Management System",
                restricted=True,
                module_type=10,
            )),
        (
            "doc",
            Storage(
                name_nice=T("Documents"),
                #description = "A library of digital resources, such as photos, documents and reports",
                restricted=True,
                module_type=10,
            )),
        # Doesn't seem like an easily-adaptable model:
        #("patient", Storage(
        #    name_nice = T("Patient Tracking"),
        #    #description = "Tracking of Patients",
        #    restricted = True,
        #    module_type = 10
        #)),
        # Possible usecase: HR
        #("hrm", Storage(
        #    name_nice = T("Staff"),
        #    #description = "Human Resources Management",
        #    restricted = True,
        #    module_type = 2,
        #)),
        # Possible usecase: Logistics
        #("supply", Storage(
        #    name_nice = T("Supply Chain Management"),
        #    #description = "Used within Inventory Management, Request Management and Asset Management",
        #    restricted = True,
        #    module_type = None, # Not displayed
        #)),
        #("inv", Storage(
        #    name_nice = T("Warehouses"),
        #    #description = "Receiving and Sending Items",
        #    restricted = True,
        #    module_type = 4
        #)),
        #("req", Storage(
        #    name_nice = T("Requests"),
        #    #description = "Manage requests for supplies, assets, staff or other resources. Matches against Inventories where supplies are requested.",
        #    restricted = True,
        #    module_type = 10,
        #)),
        # Possible support Modules
        #("event", Storage(
        #    name_nice = T("Events"),
        #    #description = "Activate Events (e.g. from Scenario templates) for allocation of appropriate Resources (Human, Assets & Facilities).",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("msg", Storage(
        #    name_nice = T("Messaging"),
        #    #description = "Sends & Receives Alerts via Email & SMS",
        #    restricted = True,
        #    # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules.
        #    module_type = None,
        #)),
    ])
Exemplo n.º 17
0
    def add_element_to(
        self,
        parent,
        lazy=None,
    ):
        """
            Append the XML Element for this node to a parent element

            @param parent: the parent Element
            @param lazy: list of lazy representation nodes (written to)

            @returns: a list of rmap entries for any location references
                      in the record, suitable for S3XML.latlon()
        """

        table = self.table

        # Replace user ID representation by lazy method
        auth_user_represent = Storage()
        if hasattr(current, "auth_user_represent"):
            user_ids = ("created_by", "modified_by", "owned_by_user")
            for fn in user_ids:
                if hasattr(table, fn):
                    f = table[fn]
                    auth_user_represent[fn] = f.represent
                    f.represent = current.auth_user_represent

        xml = current.xml

        resource = self.resource
        record = self.record

        # Generate the XML for this record
        postprocess = resource.get_config("xml_post_render")
        element = xml.resource(
            parent,
            self.table,
            record,
            fields=self.dfields,
            alias=self.alias,
            lazy=lazy,
            url=self.url,
            llrepr=self.llrepr,
            postprocess=postprocess,
        )

        # Add the <reference> elements
        rmap, lref = self.rmap()
        xml.add_references(
            element,
            rmap,
            show_ids=xml.show_ids,
            lazy=lazy,
        )

        if self.master:
            # GIS-encode the element
            # @ToDo: Do this 1/tree not 1/record
            xml.gis_encode(
                self.resource,
                record,
                element,
                location_data=self.location_data,
            )

        # Generate the XML for all sub-nodes
        for node in self.components:
            clref = node.add_element_to(element, lazy=lazy)
            lref.extend(clref)

        self.element = element

        # Restore normal user_id representations
        for fn in auth_user_represent:
            table[fn].represent = auth_user_represent[fn]

        return lref
Exemplo n.º 18
0
def config(settings):
    """
        Human Resources generic template
    """

    T = current.T

    settings.base.system_name = T("Sahana Human Resources")
    settings.base.system_name_short = T("Sahana HR")

    # PrePopulate data
    settings.base.prepopulate += ("HR", )
    #settings.base.prepopulate_demo += ("HR/Demo",)

    # Theme (folder to use for views/layout.html)
    #settings.base.theme = "HR"

    # Authentication settings
    # Should users be allowed to register themselves?
    #settings.security.self_registration = False
    # Do new users need to verify their email address?
    #settings.auth.registration_requires_verification = True
    # Do new users need to be approved by an administrator prior to being able to login?
    #settings.auth.registration_requires_approval = True
    #settings.auth.registration_requests_organisation = True

    # Approval emails get sent to all admins
    settings.mail.approver = "ADMIN"

    # Uncomment to display the Map Legend as a floating DIV
    settings.gis.legend = "float"

    # Number formats (defaults to ISO 31-0)
    # Decimal separator for numbers (defaults to ,)
    settings.L10n.decimal_separator = "."
    # Thousands separator for numbers (defaults to space)
    settings.L10n.thousands_separator = ","

    # Security Policy
    # http://eden.sahanafoundation.org/wiki/S3AAA#System-widePolicy
    # 1: Simple (default): Global as Reader, Authenticated as Editor
    # 2: Editor role required for Update/Delete, unless record owned by session
    # 3: Apply Controller ACLs
    # 4: Apply both Controller & Function ACLs
    # 5: Apply Controller, Function & Table ACLs
    # 6: Apply Controller, Function, Table ACLs and Entity Realm
    # 7: Apply Controller, Function, Table ACLs and Entity Realm + Hierarchy
    # 8: Apply Controller, Function, Table ACLs, Entity Realm + Hierarchy and Delegations
    #
    #settings.security.policy = 7 # Organisation-ACLs

    # -------------------------------------------------------------------------
    # Setup
    settings.setup.wizard_questions += [
        {
            "question": "Will you record data for multiple Organisations?",
            "setting": "hrm.multiple_orgs",
            "options": {
                True: "Yes",
                False: "No"
            },
        },
        {
            "question": "Do you need support for Branch Organisations?",
            "setting": "org.branches",
            "options": {
                True: "Yes",
                False: "No"
            },
        },
    ]

    # -------------------------------------------------------------------------
    # Comment/uncomment modules here to disable/enable them
    # Modules menu is defined in modules/eden/menu.py
    settings.modules = OrderedDict([
        # Core modules which shouldn't be disabled
        (
            "default",
            Storage(
                name_nice=T("Home"),
                restricted=False,  # Use ACLs to control access to this module
                access=
                None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
                module_type=None  # This item is not shown in the menu
            )),
        (
            "admin",
            Storage(
                name_nice=T("Administration"),
                #description = "Site Administration",
                restricted=True,
                access=
                "|1|",  # Only Administrators can see this module in the default menu & access the controller
                module_type=None  # This item is handled separately for the menu
            )),
        (
            "appadmin",
            Storage(
                name_nice=T("Administration"),
                #description = "Site Administration",
                restricted=True,
                module_type=None  # No Menu
            )),
        (
            "errors",
            Storage(
                name_nice=T("Ticket Viewer"),
                #description = "Needed for Breadcrumbs",
                restricted=False,
                module_type=None  # No Menu
            )),
        (
            "setup",
            Storage(
                name_nice=T("Setup"),
                #description = "Configuration Wizard",
                restricted=False,
                module_type=None  # No Menu
            )),
        #("sync", Storage(
        #    name_nice = T("Synchronization"),
        #    #description = "Synchronization",
        #    restricted = True,
        #    access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
        #    module_type = None  # This item is handled separately for the menu
        #)),
        #("tour", Storage(
        #    name_nice = T("Guided Tour Functionality"),
        #    module_type = None,
        #)),
        #("translate", Storage(
        #    name_nice = T("Translation Functionality"),
        #    #description = "Selective translation of strings based on module.",
        #    module_type = None,
        #)),
        (
            "gis",
            Storage(
                name_nice=T("Map"),
                #description = "Situation Awareness & Geospatial Analysis",
                restricted=True,
                module_type=6,  # 6th item in the menu
            )),
        (
            "pr",
            Storage(
                name_nice=T("Person Registry"),
                #description = "Central point to record details on People",
                restricted=True,
                access=
                "|1|",  # Only Administrators can see this module in the default menu (access to controller is possible to all still)
                module_type=10)),
        (
            "org",
            Storage(
                name_nice=T("Organizations"),
                #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities',
                restricted=True,
                module_type=1)),
        (
            "hrm",
            Storage(
                name_nice=T("Staff"),
                #description = "Human Resources Management",
                restricted=True,
                module_type=2,
            )),
        (
            "vol",
            Storage(
                name_nice=T("Volunteers"),
                #description = "Human Resources Management",
                restricted=True,
                module_type=2,
            )),
        (
            "cms",
            Storage(
                name_nice=T("Content Management"),
                #description = "Content Management System",
                restricted=True,
                module_type=10,
            )),
        (
            "doc",
            Storage(
                name_nice=T("Documents"),
                #description = "A library of digital resources, such as photos, documents and reports",
                restricted=True,
                module_type=10,
            )),
        (
            "msg",
            Storage(
                name_nice=T("Messaging"),
                #description = "Sends & Receives Alerts via Email & SMS",
                restricted=True,
                # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules.
                module_type=None,
            )),
        #("supply", Storage(
        #    name_nice = T("Supply Chain Management"),
        #    #description = "Used within Inventory Management, Request Management and Asset Management",
        #    restricted = True,
        #    module_type = None, # Not displayed
        #)),
        #("inv", Storage(
        #    name_nice = T("Warehouses"),
        #    #description = "Receiving and Sending Items",
        #    restricted = True,
        #    module_type = 4
        #)),
        #("asset", Storage(
        #    name_nice = T("Assets"),
        #    #description = "Recording and Assigning Assets",
        #    restricted = True,
        #    module_type = 5,
        #)),
        # Vehicle depends on Assets
        #("vehicle", Storage(
        #    name_nice = T("Vehicles"),
        #    #description = "Manage Vehicles",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("req", Storage(
        #    name_nice = T("Requests"),
        #    #description = "Manage requests for supplies, assets, staff or other resources. Matches against Inventories where supplies are requested.",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("project", Storage(
        #    name_nice = T("Projects"),
        #    #description = "Tracking of Projects, Activities and Tasks",
        #    restricted = True,
        #    module_type = 2
        #)),
        #("cr", Storage(
        #    name_nice = T("Shelters"),
        #    #description = "Tracks the location, capacity and breakdown of victims in Shelters",
        #    restricted = True,
        #    module_type = 10
        #)),
        #("hms", Storage(
        #    name_nice = T("Hospitals"),
        #    #description = "Helps to monitor status of hospitals",
        #    restricted = True,
        #    module_type = 10
        #)),
        #("dvr", Storage(
        #   name_nice = T("Disaster Victim Registry"),
        #   #description = "Allow affected individuals & households to register to receive compensation and distributions",
        #   restricted = True,
        #   module_type = 10,
        #)),
        (
            "event",
            Storage(
                name_nice=T("Events"),
                #description = "Activate Events (e.g. from Scenario templates) for allocation of appropriate Resources (Human, Assets & Facilities).",
                restricted=True,
                module_type=10,
            )),
        #("transport", Storage(
        #   name_nice = T("Transport"),
        #   restricted = True,
        #   module_type = 10,
        #)),
        #("stats", Storage(
        #    name_nice = T("Statistics"),
        #    #description = "Manages statistics",
        #    restricted = True,
        #    module_type = None,
        #)),
    ])


# END =========================================================================
Exemplo n.º 19
0
def config(settings):
    """
        Disease Tracking
    """

    T = current.T

    settings.base.system_name = T("Sahana Disease Tracking")
    #settings.base.system_name_short = T("Sahana")

    # PrePopulate data
    settings.base.prepopulate += ("Disease", )
    #settings.base.prepopulate_demo += ("Disease/Demo",)

    # Theme (folder to use for views/layout.html)
    #settings.base.theme = "skeleton"
    # Custom Logo
    #settings.ui.menu_logo = "/%s/static/themes/<templatename>/img/logo.png" % current.request.application

    # Authentication settings
    # Should users be allowed to register themselves?
    #settings.security.self_registration = False
    # Do new users need to verify their email address?
    settings.auth.registration_requires_verification = True
    # Do new users need to be approved by an administrator prior to being able to login?
    settings.auth.registration_requires_approval = True
    # Required for access to default realm permissions
    #settings.auth.registration_link_user_to = ["staff"]
    #settings.auth.registration_link_user_to_default = ["staff"]

    settings.auth.registration_requests_organisation = True
    settings.auth.registration_requests_site = True

    # Approval emails get sent to all admins
    settings.mail.approver = "ADMIN"

    # Restrict the Location Selector to just certain countries
    # NB This can also be over-ridden for specific contexts later
    # e.g. Activities filtered to those of parent Project
    #settings.gis.countries = ("US",)
    # Uncomment to display the Map Legend as a floating DIV, so that it is visible on Summary Map
    settings.gis.legend = "float"
    # Uncomment to Disable the Postcode selector in the LocationSelector
    #settings.gis.postcode_selector = False # @ToDo: Vary by country (include in the gis_config!)
    # Uncomment to show the Print control:
    # http://eden.sahanafoundation.org/wiki/UserGuidelines/Admin/MapPrinting
    #settings.gis.print_button = True

    # Default language for Language Toolbar (& GIS Locations in future)
    #settings.L10n.default_language = "en"
    # Uncomment to Hide the language toolbar
    #settings.L10n.display_toolbar = False
    # Default timezone for users
    #settings.L10n.timezone = "Europe/Berlin"
    # Number formats (defaults to ISO 31-0)
    # Decimal separator for numbers (defaults to ,)
    settings.L10n.decimal_separator = "."
    # Thousands separator for numbers (defaults to space)
    settings.L10n.thousands_separator = ","
    # Uncomment this to Translate Layer Names
    #settings.L10n.translate_gis_layer = True
    # Uncomment this to Translate Location Names
    #settings.L10n.translate_gis_location = True
    # Uncomment this to Translate Organisation Names/Acronyms
    #settings.L10n.translate_org_organisation = True
    # Finance settings
    #settings.fin.currencies = {
    #    "EUR" : "Euros",
    #    "GBP" : "Great British Pounds",
    #    "USD" : "United States Dollars",
    #}
    #settings.fin.currency_default = "USD"

    # Security Policy
    # http://eden.sahanafoundation.org/wiki/S3AAA#System-widePolicy
    # 1: Simple (default): Global as Reader, Authenticated as Editor
    # 2: Editor role required for Update/Delete, unless record owned by session
    # 3: Apply Controller ACLs
    # 4: Apply both Controller & Function ACLs
    # 5: Apply Controller, Function & Table ACLs
    # 6: Apply Controller, Function, Table ACLs and Entity Realm
    # 7: Apply Controller, Function, Table ACLs and Entity Realm + Hierarchy
    # 8: Apply Controller, Function, Table ACLs, Entity Realm + Hierarchy and Delegations

    settings.security.policy = 7  # Organisation-ACLs with Hierarchy

    def rgims_realm_entity(table, row):
        """
            Assign a Realm Entity to records
        """

        tablename = table._tablename
        if tablename not in ("inv_recv", "inv_send"):
            # Normal lookup
            return 0

        # For these tables we need to assign the site_id's realm not organisation_id's
        db = current.db
        stable = db.org_site
        record = db(stable.site_id == row.site_id).select(stable.realm_entity,
                                                          limitby=(0,
                                                                   1)).first()
        if record:
            return record.realm_entity

        # Normal lookup
        return 0

    settings.auth.realm_entity = rgims_realm_entity

    settings.req.req_type = ["Stock"]

    # -------------------------------------------------------------------------
    # Comment/uncomment modules here to disable/enable them
    # Modules menu is defined in modules/eden/menu.py
    settings.modules = OrderedDict([
        # Core modules which shouldn't be disabled
        (
            "default",
            Storage(
                name_nice=T("Home"),
                restricted=False,  # Use ACLs to control access to this module
                access=
                None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
                module_type=None  # This item is not shown in the menu
            )),
        (
            "admin",
            Storage(
                name_nice=T("Administration"),
                #description = "Site Administration",
                restricted=True,
                access=
                "|1|",  # Only Administrators can see this module in the default menu & access the controller
                module_type=None  # This item is handled separately for the menu
            )),
        (
            "appadmin",
            Storage(
                name_nice=T("Administration"),
                #description = "Site Administration",
                restricted=True,
                module_type=None  # No Menu
            )),
        (
            "errors",
            Storage(
                name_nice=T("Ticket Viewer"),
                #description = "Needed for Breadcrumbs",
                restricted=False,
                module_type=None  # No Menu
            )),
        #("sync", Storage(
        #    name_nice = T("Synchronization"),
        #    #description = "Synchronization",
        #    restricted = True,
        #    access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
        #    module_type = None  # This item is handled separately for the menu
        #)),
        #("translate", Storage(
        #    name_nice = T("Translation Functionality"),
        #    #description = "Selective translation of strings based on module.",
        #    module_type = None,
        #)),
        (
            "gis",
            Storage(
                name_nice=T("Map"),
                #description = "Situation Awareness & Geospatial Analysis",
                restricted=True,
                module_type=6,  # 6th item in the menu
            )),
        (
            "pr",
            Storage(
                name_nice=T("Person Registry"),
                #description = "Central point to record details on People",
                restricted=True,
                access=
                "|1|",  # Only Administrators can see this module in the default menu (access to controller is possible to all still)
                module_type=10)),
        (
            "org",
            Storage(
                name_nice=T("Organizations"),
                #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities',
                restricted=True,
                module_type=1)),
        (
            "cms",
            Storage(
                name_nice=T("Content Management"),
                #description = "Content Management System",
                restricted=True,
                module_type=10,
            )),
        (
            "doc",
            Storage(
                name_nice=T("Documents"),
                #description = "A library of digital resources, such as photos, documents and reports",
                restricted=True,
                module_type=10,
            )),
        (
            "hms",
            Storage(
                name_nice=T("Hospitals"),
                #description = "Helps to monitor status of hospitals",
                restricted=True,
                module_type=2,
            )),
        (
            "disease",
            Storage(
                name_nice=T("Disease Tracking"),
                #description = "Helps to monitor status of cases",
                restricted=True,
                module_type=1,
            )),
        (
            "stats",
            Storage(
                name_nice=T("Statistics"),
                #description = "Manages statistics",
                restricted=True,
                module_type=None,
            )),
        # HRM is required for access to default realm permissions
        (
            "hrm",
            Storage(
                name_nice=T("Staff"),
                #description = "Human Resources Management",
                restricted=True,
                module_type=10,
            )),
        (
            "supply",
            Storage(
                name_nice=T("Supply Chain Management"),
                #description = "Used within Inventory Management, Request Management and Asset Management",
                restricted=True,
                module_type=None,  # Not displayed
            )),
        (
            "inv",
            Storage(
                name_nice=T("Warehouses"),
                #description = "Receiving and Sending Items",
                restricted=True,
                module_type=10,
            )),
        (
            "req",
            Storage(
                name_nice=T("Requests"),
                #description = "Manage requests for supplies, assets, staff or other resources. Matches against Inventories where supplies are requested.",
                restricted=True,
                module_type=3,
            )),
        #("vol", Storage(
        #    name_nice = T("Volunteers"),
        #    #description = "Human Resources Management",
        #    restricted = True,
        #    module_type = 2,
        #)),
        #("msg", Storage(
        #    name_nice = T("Messaging"),
        #    #description = "Sends & Receives Alerts via Email & SMS",
        #    restricted = True,
        #    # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules.
        #    module_type = None,
        #)),
        #("asset", Storage(
        #    name_nice = T("Assets"),
        #    #description = "Recording and Assigning Assets",
        #    restricted = True,
        #    module_type = 5,
        #)),
        # Vehicle depends on Assets
        #("vehicle", Storage(
        #    name_nice = T("Vehicles"),
        #    #description = "Manage Vehicles",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("project", Storage(
        #    name_nice = T("Projects"),
        #    #description = "Tracking of Projects, Activities and Tasks",
        #    restricted = True,
        #    module_type = 2
        #)),
        #("cr", Storage(
        #    name_nice = T("Shelters"),
        #    #description = "Tracks the location, capacity and breakdown of victims in Shelters",
        #    restricted = True,
        #    module_type = 10
        #)),
        #("br", Storage(
        #   name_nice = T("Beneficiary Registry"),
        #   #description = "Allow affected individuals & households to register to receive compensation and distributions",
        #   restricted = True,
        #   module_type = 10,
        #)),
        #("event", Storage(
        #    name_nice = T("Events"),
        #    #description = "Activate Events (e.g. from Scenario templates) for allocation of appropriate Resources (Human, Assets & Facilities).",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("transport", Storage(
        #   name_nice = T("Transport"),
        #   restricted = True,
        #   module_type = 10,
        #)),
    ])

    # -----------------------------------------------------------------------------
    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))

    settings.customise_hms_hospital_resource = customise_hms_hospital_resource

    # -----------------------------------------------------------------------------
    def customise_disease_stats_data_resource(r, tablename):

        s3db = current.s3db
        # Load model & set defaults
        table = s3db.disease_stats_data

        # Add a TimePlot tab to summary page
        summary = settings.get_ui_summary()
        settings.ui.summary = list(summary) + [{
            "name":
            "timeplot",
            "label":
            "Progression",
            "widgets": [{
                "method": "timeplot",
                "ajax_init": True,
            }],
        }]

        # Default parameter filter
        def default_parameter_filter(selector, tablename=None):
            ptable = s3db.stats_parameter
            query = (ptable.deleted == False) & \
                    (ptable.name == "Cases")
            row = current.db(query).select(ptable.parameter_id,
                                           limitby=(0, 1)).first()
            if row:
                return row.parameter_id
            else:
                return None

        # Set filter defaults
        resource = r.resource
        filter_widgets = resource.get_config("filter_widgets", [])
        for filter_widget in filter_widgets:
            if filter_widget.field == "parameter_id":
                filter_widget.opts.default = default_parameter_filter
            elif filter_widget.field == "location_id$level":
                filter_widget.opts.default = "L2"

    settings.customise_disease_stats_data_resource = customise_disease_stats_data_resource

    # -----------------------------------------------------------------------------
    def customise_stats_demographic_data_resource(r, tablename):

        s3db = current.s3db
        # Load model & set defaults
        table = s3db.stats_demographic_data

        # Default parameter filter
        def default_parameter_filter(selector, tablename=None):
            ptable = s3db.stats_parameter
            query = (ptable.deleted == False) & \
                    (ptable.name == "Population Total")
            row = current.db(query).select(ptable.parameter_id,
                                           limitby=(0, 1)).first()
            if row:
                return row.parameter_id
            else:
                return None

        # Set filter defaults
        resource = r.resource
        filter_widgets = resource.get_config("filter_widgets", [])
        for filter_widget in filter_widgets:
            if filter_widget.field == "parameter_id":
                filter_widget.opts.default = default_parameter_filter
            elif filter_widget.field == "location_id$level":
                filter_widget.opts.default = "L2"

    settings.customise_stats_demographic_data_resource = customise_stats_demographic_data_resource
Exemplo n.º 20
0
def LOAD(c=None,
         f='index',
         args=None,
         vars=None,
         extension=None,
         target=None,
         ajax=False,
         ajax_trap=False,
         url=None,
         user_signature=False,
         timeout=None,
         times=1,
         content='loading...',
         **attr):
    """  LOADs a component into the action's document

    Args:
        c(str): controller
        f(str): function
        args(tuple or list): arguments
        vars(dict): vars
        extension(str): extension
        target(str): id of the target
        ajax(bool): True to enable AJAX bahaviour
        ajax_trap(bool): True if `ajax` is set to `True`, traps
            both links and forms "inside" the target
        url(str): overrides `c`,`f`,`args` and `vars`
        user_signature(bool): adds hmac signature to all links
            with a key that is different for every user
        timeout(int): in milliseconds, specifies the time to wait before
            starting the request or the frequency if times is greater than
            1 or "infinity"
        times(integer or str): how many times the component will be requested
            "infinity" or "continuous" are accepted to reload indefinitely the
            component
    """
    from html import TAG, DIV, URL, SCRIPT, XML
    if args is None:
        args = []
    vars = Storage(vars or {})
    target = target or 'c' + str(random.random())[2:]
    attr['_id'] = target
    request = current.request
    if '.' in f:
        f, extension = f.rsplit('.', 1)
    if url or ajax:
        url = url or URL(request.application,
                         c,
                         f,
                         r=request,
                         args=args,
                         vars=vars,
                         extension=extension,
                         user_signature=user_signature)
        # timing options
        if isinstance(times, basestring):
            if times.upper() in ("INFINITY", "CONTINUOUS"):
                times = "Infinity"
            else:
                raise TypeError("Unsupported times argument %s" % times)
        elif isinstance(times, int):
            if times <= 0:
                raise ValueError(
                    "Times argument must be greater than zero, 'Infinity' or None"
                )
        else:
            raise TypeError("Unsupported times argument type %s" % type(times))
        if timeout is not None:
            if not isinstance(timeout, (int, long)):
                raise ValueError("Timeout argument must be an integer or None")
            elif timeout <= 0:
                raise ValueError(
                    "Timeout argument must be greater than zero or None")
            statement = "$.web2py.component('%s','%s', %s, %s);" \
                % (url, target, timeout, times)
            attr['_data-w2p_timeout'] = timeout
            attr['_data-w2p_times'] = times
        else:
            statement = "$.web2py.component('%s','%s');" % (url, target)
        attr['_data-w2p_remote'] = url
        if not target is None:
            return DIV(content, **attr)

    else:
        if not isinstance(args, (list, tuple)):
            args = [args]
        c = c or request.controller
        other_request = Storage(request)
        other_request['env'] = Storage(request.env)
        other_request.controller = c
        other_request.function = f
        other_request.extension = extension or request.extension
        other_request.args = List(args)
        other_request.vars = vars
        other_request.get_vars = vars
        other_request.post_vars = Storage()
        other_response = Response()
        other_request.env.path_info = '/' + \
            '/'.join([request.application, c, f] +
                     map(str, other_request.args))
        other_request.env.query_string = \
            vars and URL(vars=vars).split('?')[1] or ''
        other_request.env.http_web2py_component_location = \
            request.env.path_info
        other_request.cid = target
        other_request.env.http_web2py_component_element = target
        other_request.restful = request.restful  # Needed when you call LOAD() on a controller who has some actions decorates with @request.restful()
        other_response.view = '%s/%s.%s' % (c, f, other_request.extension)

        other_environment = copy.copy(current.globalenv)  # NASTY

        other_response._view_environment = other_environment
        other_response.generic_patterns = \
            copy.copy(current.response.generic_patterns)
        other_environment['request'] = other_request
        other_environment['response'] = other_response

        ## some magic here because current are thread-locals

        original_request, current.request = current.request, other_request
        original_response, current.response = current.response, other_response
        page = run_controller_in(c, f, other_environment)
        if isinstance(page, dict):
            other_response._vars = page
            other_response._view_environment.update(page)
            run_view_in(other_response._view_environment)
            page = other_response.body.getvalue()
        current.request, current.response = original_request, original_response
        js = None
        if ajax_trap:
            link = URL(request.application,
                       c,
                       f,
                       r=request,
                       args=args,
                       vars=vars,
                       extension=extension,
                       user_signature=user_signature)
            js = "$.web2py.trap_form('%s','%s');" % (link, target)
        script = js and SCRIPT(js, _type="text/javascript") or ''
        return TAG[''](DIV(XML(page), **attr), script)
Exemplo n.º 21
0
    def __receive(self, r, **attr):
        """
            Respond to an incoming push

            @param r: the S3Request
            @param attr: the controller attributes
        """

        _debug("S3Sync.__receive")

        s3db = current.s3db
        db = current.db

        # Identify the sending repository
        repository = Storage(id=None)
        if "repository" in r.vars:
            ruid = r.vars["repository"]
            rtable = s3db.sync_repository
            row = db(rtable.uuid == ruid).select(limitby=(0, 1)).first()
            if row:
                repository = row
        if not repository.id or \
           not repository.accept_push:
            r.error(403, current.ERROR.NOT_PERMITTED)

        # Get strategy and policy
        default_update_policy = S3ImportItem.POLICY.NEWER
        default_conflict_policy = S3ImportItem.POLICY.MASTER

        ttable = s3db.sync_task
        query = (ttable.repository_id == repository.id) & \
                (ttable.resource_name == r.tablename) & \
                (ttable.deleted != True)
        task = db(query).select(limitby=(0, 1)).first()
        last_sync = None
        if task:
            strategy = task.strategy
            update_policy = task.update_policy or default_update_policy
            conflict_policy = task.conflict_policy or default_conflict_policy
            if update_policy not in ("THIS", "OTHER"):
                last_sync = task.last_pull
        else:
            policies = S3ImportItem.POLICY
            p = r.get_vars.get("update_policy", None)
            values = {"THIS": "OTHER", "OTHER": "THIS"}
            switch = lambda p: p in values and values[p] or p
            if p and p in policies:
                p = switch(p)
                update_policy = policies[p]
            else:
                update_policy = default_update_policy
            p = r.get_vars.get("conflict_policy", None)
            if p and p in policies:
                p = switch(p)
                conflict_policy = policies[p]
            else:
                conflict_policy = default_conflict_policy
            msince = r.get_vars.get("msince", None)
            if msince is not None:
                last_sync = s3_parse_datetime(msince)
            s = r.get_vars.get("strategy", None)
            if s:
                s = str(s).split(",")
                methods = S3ImportItem.METHOD
                strategy = [
                    method for method in methods.values() if method in s
                ]
            else:
                strategy = ttable.strategy.default

        # Other parameters
        ignore_errors = True

        # Get the source
        source = r.read_body()

        # Import resource
        resource = r.resource
        onconflict = lambda item: self.onconflict(item, repository, resource)
        try:
            output = resource.import_xml(source,
                                         format="xml",
                                         ignore_errors=ignore_errors,
                                         strategy=strategy,
                                         update_policy=update_policy,
                                         conflict_policy=conflict_policy,
                                         last_sync=last_sync,
                                         onconflict=onconflict)
        except IOError:
            current.auth.permission.fail()
        except SyntaxError:
            e = sys.exc_info()[1]
            r.error(400, e)

        log = self.log

        if resource.error_tree is not None:
            # Validation error (log in any case)
            if ignore_errors:
                result = log.WARNING
            else:
                result = log.FATAL
            message = "%s" % resource.error
            for element in resource.error_tree.findall("resource"):
                error_msg = element.get("error", "unknown error")

                error_fields = element.findall("data[@error]")
                if error_fields:
                    for field in error_fields:
                        error_msg = field.get("error", "unknown error")
                        if error_msg:
                            msg = "(UID: %s) %s.%s=%s: %s" % \
                                    (element.get("uuid", None),
                                     element.get("name", None),
                                     field.get("field", None),
                                     field.get("value", field.text),
                                     error_msg)
                            message = "%s, %s" % (message, msg)
                else:
                    msg = "(UID: %s) %s: %s" % \
                          (element.get("uuid", None),
                           element.get("name", None),
                           error_msg)
                    message = "%s, %s" % (message, msg)
        else:
            result = log.SUCCESS
            message = "data received from peer"

        log.write(repository_id=repository.id,
                  resource_name=resource.tablename,
                  transmission=log.IN,
                  mode=log.PUSH,
                  result=result,
                  message=message)

        return output
Exemplo n.º 22
0
    def __call__(self,
                 c=None,
                 f='index',
                 args=None,
                 vars=None,
                 extension=None,
                 target=None,
                 ajax=False,
                 ajax_trap=False,
                 url=None,
                 user_signature=False,
                 content='loading...',
                 **attr):
        if args is None:
            args = []
        vars = Storage(vars or {})
        import globals
        target = target or 'c' + str(random.random())[2:]
        attr['_id'] = target
        request = self.environment['request']
        if '.' in f:
            f, extension = f.rsplit('.', 1)
        if url or ajax:
            url = url or html.URL(request.application,
                                  c,
                                  f,
                                  r=request,
                                  args=args,
                                  vars=vars,
                                  extension=extension,
                                  user_signature=user_signature)
            script = html.SCRIPT('$.web2py.component("%s","%s")' %
                                 (url, target),
                                 _type="text/javascript")
            return html.TAG[''](script, html.DIV(content, **attr))
        else:
            if not isinstance(args, (list, tuple)):
                args = [args]
            c = c or request.controller

            other_request = Storage(request)
            other_request['env'] = Storage(request.env)
            other_request.controller = c
            other_request.function = f
            other_request.extension = extension or request.extension
            other_request.args = List(args)
            other_request.vars = vars
            other_request.get_vars = vars
            other_request.post_vars = Storage()
            other_response = globals.Response()
            other_request.env.path_info = '/' + \
                '/'.join([request.application, c, f] +
                         map(str, other_request.args))
            other_request.env.query_string = \
                vars and html.URL(vars=vars).split('?')[1] or ''
            other_request.env.http_web2py_component_location = \
                request.env.path_info
            other_request.cid = target
            other_request.env.http_web2py_component_element = target
            other_response.view = '%s/%s.%s' % (c, f, other_request.extension)
            other_environment = copy.copy(self.environment)
            other_response._view_environment = other_environment
            other_response.generic_patterns = \
                copy.copy(current.response.generic_patterns)
            other_environment['request'] = other_request
            other_environment['response'] = other_response

            ## some magic here because current are thread-locals

            original_request, current.request = current.request, other_request
            original_response, current.response = current.response, other_response
            page = run_controller_in(c, f, other_environment)
            if isinstance(page, dict):
                other_response._vars = page
                other_response._view_environment.update(page)
                run_view_in(other_response._view_environment)
                page = other_response.body.getvalue()
            current.request, current.response = original_request, original_response
            js = None
            if ajax_trap:
                link = html.URL(request.application,
                                c,
                                f,
                                r=request,
                                args=args,
                                vars=vars,
                                extension=extension,
                                user_signature=user_signature)
                js = "$.web2py.trap_form('%s','%s');" % (link, target)
            script = js and html.SCRIPT(js, _type="text/javascript") or ''
            return html.TAG[''](html.DIV(html.XML(page), **attr), script)
Exemplo n.º 23
0
import datetime
if (db(table_product.created_on < request.now -
       datetime.timedelta(minutes=60)).count()
        or not db(table_product.id > 0).count()):
    table_product.truncate()
    for i in range(5):
        table_product.insert(name='p%s' % i, status='old')
    for i in range(5, 12):
        table_product.insert(name='p%s' % i, status='new')
    session.flash = 'the database has been refreshed'
    redirect(URL('index'))

### fake authentication ########################################################

from gluon.storage import Storage
session.auth = Storage(hmac_key='test', user=Storage(email='*****@*****.**'))

### demo functions #############################################################


def index():
    SQLFORM.grid = SolidGrid(
        renderstyle=True)  # override the original grid function

    from plugin_tablecheckbox import TableCheckbox
    tablecheckbox = TableCheckbox()

    # Insert an extra element to select an action
    tablecheckbox.components.insert(
        0,
        SELECT('new',
Exemplo n.º 24
0
 def get(self):
     session = Storage()
     session.update(cPickle.loads(self.row.session_data))
     return session
Exemplo n.º 25
0
def ifrc_realm_entity(table, row):
    """
        Assign a Realm Entity to records
    """

    tablename = table._tablename

    # Do not apply realms for Master Data
    # @ToDo: Restore Realms and add a role/functionality support for Master Data  
    if tablename in ["hrm_certificate",
                     "hrm_department",
                     "hrm_job_role",
                     "hrm_job_title",
                     "hrm_course",
                     "hrm_programme",
                     ]:
        return None

    db = current.db
    s3db = current.s3db

    # Entity reference fields
    EID = "pe_id"
    #OID = "organisation_id"
    SID = "site_id"
    #GID = "group_id"
    PID = "person_id"

    # Owner Entity Foreign Key
    realm_entity_fks = dict(pr_contact = EID,
                            pr_physical_description = EID,
                            pr_address = EID,
                            pr_image = EID,
                            pr_identity = PID,
                            pr_education = PID,
                            pr_note = PID,
                            hrm_human_resource = SID,
                            inv_recv = SID,
                            inv_recv_item = "req_id",
                            inv_send = SID,
                            inv_track_item = "track_org_id",
                            inv_adj_item = "adj_id",
                            req_req_item = "req_id"
                            )

    # Default Foreign Keys (ordered by priority)
    default_fks = ["catalog_id",
                   "project_id",
                   "project_location_id"
                   ]

    # Link Tables
    realm_entity_link_table = dict(
        project_task = Storage(tablename = "project_task_project",
                               link_key = "task_id"
                               )
        )
    if tablename in realm_entity_link_table:
        # Replace row with the record from the link table
        link_table = realm_entity_link_table[tablename]
        table = s3db[link_table.tablename]
        rows = db(table[link_table.link_key] == row.id).select(table.id,
                                                               limitby=(0, 1))
        if rows:
            # Update not Create
            row = rows.first()

    # Check if there is a FK to inherit the realm_entity
    realm_entity = 0
    fk = realm_entity_fks.get(tablename, None)
    for default_fk in [fk] + default_fks:
        if default_fk in table.fields:
            fk = default_fk
            # Inherit realm_entity from parent record
            if fk == EID:
                ftable = s3db.pr_person
                query = ftable[EID] == row[EID]
            else:
                ftablename = table[fk].type[10:] # reference tablename
                ftable = s3db[ftablename]
                query = (table.id == row.id) & \
                        (table[fk] == ftable.id)
            record = db(query).select(ftable.realm_entity,
                                      limitby=(0, 1)).first()
            if record:
                realm_entity = record.realm_entity
                break
            #else:
            # Continue to loop through the rest of the default_fks
            # Fall back to default get_realm_entity function
    
    use_user_organisation = False
    # Suppliers & Partners are owned by the user's organisation
    if realm_entity == 0 and tablename == "org_organisation":
        ott = s3db.org_organisation_type
        row = table[row.id]
        row = db(table.organisation_type_id == ott.id).select(ott.name,
                                                              limitby=(0, 1)
                                                              ).first()
        
        if row and row.name != "Red Cross / Red Crescent":
            use_user_organisation = True

    # Groups are owned by the user's organisation
    elif tablename in ["pr_group"]:
        use_user_organisation = True

    user = current.auth.user
    if use_user_organisation and user:
        # @ToDo - this might cause issues if the user's org is different from the realm that gave them permissions to create the Org 
        realm_entity = s3db.pr_get_pe_id("org_organisation",
                                         user.organisation_id)

    return realm_entity
Exemplo n.º 26
0
 def get(self):
     session = Storage()
     with open(self.filename, 'rb+') as f:
         session.update(cPickle.load(f))
     return session
Exemplo n.º 27
0
    return attr


settings.ui.customize_org_organisation = customize_org_organisation

# =============================================================================
# Enabled Modules
settings.modules = OrderedDict([
    # Core modules which shouldn't be disabled
    (
        "default",
        Storage(
            name_nice=T("Home"),
            restricted=False,  # Use ACLs to control access to this module
            access=
            None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
            module_type=None  # This item is not shown in the menu
        )),
    (
        "admin",
        Storage(
            name_nice=T("Administration"),
            #description = "Site Administration",
            restricted=True,
            access=
            "|1|",  # Only Administrators can see this module in the default menu & access the controller
            module_type=None  # This item is handled separately for the menu
        )),
    (
        "appadmin",
Exemplo n.º 28
0
Arquivo: org.py Projeto: xetch/eden
    def testRootOrgUpdate(self):
        """ Test the root organisation is updated when adding a branch link """

        db = current.db
        s3db = current.s3db
        otable = s3db.org_organisation
        ltable = s3db.org_organisation_branch

        # Insert organisation records
        org1 = Storage(name="RootOrgUpdateTest1")
        org1_id = otable.insert(**org1)
        self.assertNotEqual(org1_id, None)
        org1["id"] = org1_id
        s3db.update_super(otable, org1)
        s3db.onaccept(otable, org1, method="create")

        org2 = Storage(name="RootOrgUpdateTest2")
        org2_id = otable.insert(**org2)
        self.assertNotEqual(org2_id, None)
        org2["id"] = org2_id
        s3db.update_super(otable, org2)
        s3db.onaccept(otable, org2, method="create")

        org3 = Storage(name="RootOrgUpdateTest3")
        org3_id = otable.insert(**org3)
        self.assertNotEqual(org3_id, None)
        org3["id"] = org3_id
        s3db.update_super(otable, org3)
        s3db.onaccept(otable, org3, method="create")

        # Make org3 a branch of org2
        link = Storage(organisation_id=org2_id, branch_id=org3_id)
        link_id = ltable.insert(**link)
        self.assertNotEqual(link_id, None)
        link["id"] = link_id
        s3db.onaccept(ltable, link, method="create")

        # Check root_organisations
        check = (org2_id, org3_id)
        rows = db(otable.id.belongs(check)).select(otable.id,
                                                   otable.root_organisation)
        self.assertNotEqual(rows, None)
        self.assertEqual(len(rows), 2)
        for row in rows:
            self.assertEqual(row.root_organisation, org2_id)

        # Make org2 a branch of org1
        link = Storage(organisation_id=org1_id, branch_id=org2_id)
        link_id = ltable.insert(**link)
        self.assertNotEqual(link_id, None)
        link["id"] = link_id
        s3db.onaccept(ltable, link, method="create")

        # Check root_organisations
        check = (org1_id, org2_id, org3_id)
        rows = db(otable.id.belongs(check)).select(otable.id,
                                                   otable.root_organisation)
        self.assertNotEqual(rows, None)
        self.assertEqual(len(rows), 3)
        for row in rows:
            self.assertEqual(row.root_organisation, org1_id)
Exemplo n.º 29
0
    def custom_prep(r):

        resource = r.resource

        # Call standard prep
        if callable(standard_prep):
            result = standard_prep(r)
            if not result:
                return False

        # Customize list_fields
        if r.method == "review":
            list_fields = [
                "id",
                "created_on",
                "modified_on",
                "name",
                "start_date",
                (T("Countries"), "location.location_id"),
                (T("Hazards"), "hazard.name"),
                (T("Lead Organization"), "organisation_id"),
                (T("Donors"), "donor.organisation_id"),
            ]
        elif r.representation == "xls":
            # All readable Fields should be exported
            list_fields = [
                "id",
                "name",
                "code",
                "description",
                "status_id",
                "start_date",
                "end_date",
                "drrpp.duration",
                (T("Countries"), "location.location_id"),
                "drrpp.L1",
                (T("Hazards"), "hazard.name"),
                (T("Themes"), "theme.name"),
                "objectives",
                "drrpp.activities",
                "output.name",
                "drr.hfa",
                "drrpp.rfa",
                "drrpp.pifacc",
                "drrpp.jnap",
                (T("Lead Organization"), "organisation_id"),
                (T("Partners"), "partner.organisation_id"),
                (T("Donors"), "donor.organisation_id"),
                "budget",
                "currency",
                "drrpp.focal_person",
                "drrpp.organisation_id",
                "drrpp.email",
                "url.url",
                "drrpp.parent_project",
                "comments",
            ]
            if logged_in:
                list_fields.extend([
                    "created_by",
                    "created_on",
                    "modified_by",
                    "modified_on",
                ])
        else:
            list_fields = [
                "id",
                "name",
                "start_date",
                (T("Countries"), "location.location_id"),
                (T("Hazards"), "hazard.name"),
                (T("Lead Organization"), "organisation_id"),
                (T("Donors"), "donor.organisation_id"),
            ]

        resource.configure(list_fields=list_fields)

        # Customize report_options
        if r.method == "report":
            report_fields = [
                "name",
                (T("Countries"), "location.location_id"),
                (T("Hazards"), "hazard.name"),
                (T("Themes"), "theme.name"),
                (T("HFA Priorities"), "drr.hfa"),
                (T("RFA Priorities"), "drrpp.rfa"),
                (T("Lead Organization"), "organisation_id"),
                (T("Partner Organizations"), "partner.organisation_id"),
                (T("Donors"), "donor.organisation_id"),
            ]

            # Report Settings for charts
            if "chart" in r.get_vars and r.representation != "json":
                crud_strings[tablename].title_report = T("Project Graph")
                report_fact_default = "count(id)"
                report_facts = [(T("Number of Projects"), "count(id)")]
                show_table = False
            else:
                crud_strings[tablename].title_report = T("Project Matrix")
                report_fact_default = "count(id)"
                report_facts = [
                    (T("Number of Projects"), "count(id)"),
                    (T("Number of Countries"), "count(location.location_id)"),
                    (T("Number of Hazards"), "count(hazard.id)"),
                    (T("Number of Themes"), "count(theme.id)"),
                    (T("Number of HFA Priorities"), "count(drr.hfa)"),
                    (T("Number of RFA Priorities"), "count(drrpp.rfa)"),
                    (T("Number of Lead Organizations"),
                     "count(organisation_id)"),
                    (T("Number of Partner Organizations"),
                     "count(partner.organisation_id)"),
                    (T("Number of Donors"), "count(donor.organisation_id)"),
                ]
                show_table = True
            report_options = Storage(rows=report_fields,
                                     cols=report_fields,
                                     fact=report_facts,
                                     defaults=Storage(
                                         rows="hazard.name",
                                         cols="location.location_id",
                                         fact=report_fact_default,
                                         totals=True,
                                         table=show_table,
                                     ))
            resource.configure(report_options=report_options)
            current.deployment_settings.ui.hide_report_options = True

        if r.interactive:

            # Don't show Update/Delete button on Search table
            if r.method is None and not r.id:
                resource.configure(editable=False, deletable=False)

            # JS to show/hide Cook Island fields
            s3.scripts.append("/%s/static/themes/DRRPP/js/drrpp.js" %
                              current.request.application)

            if r.method == "read":
                table_pl = s3db.project_location
                table_l = s3db.gis_location
                countries = [
                    row.name
                    for row in db((table_pl.project_id == r.record.id)
                                  & (table_pl.location_id == table_l.id)).
                    select(table_l.name)
                ]
                if not ("Cook Islands" in countries and len(countries) == 1):
                    s3db.project_drrpp.L1.readable = False
                    s3db.project_drrpp.pifacc.readable = False
                    s3db.project_drrpp.jnap.readable = False

            # Filter Options
            project_hfa_opts = s3db.project_hfa_opts()
            hfa_options = dict(
                (key, "HFA %s" % key) for key in project_hfa_opts)
            #hfa_options[None] = NONE # to search NO HFA
            project_rfa_opts = s3db.project_rfa_opts()
            rfa_options = dict(
                (key, "RFA %s" % key) for key in project_rfa_opts)
            #rfa_options[None] = NONE # to search NO RFA
            project_pifacc_opts = s3db.project_pifacc_opts()
            pifacc_options = dict(
                (key, "PIFACC %s" % key) for key in project_pifacc_opts)
            #pifacc_options[None] = NONE # to search NO PIFACC
            project_jnap_opts = s3db.project_jnap_opts()
            jnap_options = dict(
                (key, "JNAP %s" % key) for key in project_jnap_opts)
            #jnap_options[None] = NONE # to search NO JNAP

            # Filter widgets
            from s3 import S3TextFilter, S3OptionsFilter
            filter_widgets = [
                S3TextFilter(
                    [
                        "name",
                        "code",
                        "description",
                        "location.location_id",
                        "hazard.name",
                        "theme.name",
                    ],
                    label=T("Search Projects"),
                    comment=T(
                        "Search for a Project by name, code, or description."),
                ),
                S3OptionsFilter(
                    "status_id",
                    label=T("Status"),
                    cols=4,
                ),
                S3OptionsFilter(
                    "location.location_id",
                    label=T("Country"),
                    cols=3,
                    hidden=True,
                ),
                #S3OptionsFilter("drrpp.L1",
                #                label = T("Cook Islands"),
                #                cols = 3,
                #                hidden = True,
                #               ),
                S3OptionsFilter(
                    "hazard.id",
                    label=T("Hazard"),
                    options=s3db.project_hazard_options,
                    help_field=s3db.project_hazard_help_fields,
                    cols=4,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "theme.id",
                    label=T("Theme"),
                    options=s3db.project_theme_options,
                    help_field=s3db.project_theme_help_fields,
                    cols=4,
                    # Don't group
                    size=None,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "drr.hfa",
                    label=T("HFA"),
                    options=hfa_options,
                    help_field=project_hfa_opts,
                    cols=5,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "drrpp.rfa",
                    label=T("RFA"),
                    options=rfa_options,
                    help_field=project_rfa_opts,
                    cols=6,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "drrpp.pifacc",
                    label=T("PIFACC"),
                    options=pifacc_options,
                    help_field=project_pifacc_opts,
                    cols=6,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "drrpp.jnap",
                    label=T("JNAP"),
                    options=jnap_options,
                    help_field=project_jnap_opts,
                    cols=6,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "organisation_id",
                    label=T("Lead Organisation"),
                    cols=3,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "partner.organisation_id",
                    label=T("Partners"),
                    cols=3,
                    hidden=True,
                ),
                S3OptionsFilter(
                    "donor.organisation_id",
                    label=T("Donors"),
                    cols=3,
                    hidden=True,
                )
            ]

            resource.configure(filter_widgets=filter_widgets)
        return True
Exemplo n.º 30
0
    def member_onaccept(form):
        """ On-accept for Member records """

        db = current.db
        s3db = current.s3db
        auth = current.auth
        settings = current.deployment_settings

        utable = current.auth.settings.table_user
        ptable = s3db.pr_person
        ltable = s3db.pr_person_user
        mtable = db.member_membership

        # Get the full record
        _id = form.vars.id
        if _id:
            query = (mtable.id == _id)
            record = db(query).select(mtable.id,
                                      mtable.person_id,
                                      mtable.organisation_id,
                                      mtable.deleted,
                                      limitby=(0, 1)).first()
        else:
            return

        data = Storage()

        # Affiliation, record ownership and component ownership
        # @ToDo
        #s3db.pr_update_affiliations(mtable, record)

        # realm_entity for the pr_person record
        person_id = record.person_id
        person = Storage(id=person_id)
        if settings.get_auth_person_realm_member_org():
            # Set pr_person.realm_entity to the human_resource's organisation pe_id
            organisation_id = record.organisation_id
            entity = s3db.pr_get_pe_id("org_organisation", organisation_id)
            if entity:
                auth.set_realm_entity(ptable,
                                      person,
                                      entity=entity,
                                      force_update=True)

        # Update the location ID from the Home Address
        atable = s3db.pr_address
        query = (atable.pe_id == ptable.pe_id) & \
                (ptable.id == record.person_id) & \
                (atable.type == 1) & \
                (atable.deleted == False)
        address = db(query).select(atable.location_id, limitby=(0, 1)).first()
        if address:
            data.location_id = address.location_id

        # Add record owner (user)
        query = (ptable.id == record.person_id) & \
                (ltable.pe_id == ptable.pe_id) & \
                (utable.id == ltable.user_id)
        user = db(query).select(utable.id,
                                utable.organisation_id,
                                utable.site_id,
                                limitby=(0, 1)).first()
        if user:
            data.owned_by_user = user.id

        if not data:
            return
        record.update_record(**data)