Exemple #1
0
    def postp(r, output):
        if r.interactive:
            # Normal Action Buttons
            s3_action_buttons(r)
            # Custom Action Buttons for Enable/Disable
            table = r.table
            query = (table.deleted == False)
            rows = db(query).select(table.id,
                                    table.enabled,
                                    )
            restrict_e = [str(row.id) for row in rows if not row.enabled]
            restrict_d = [str(row.id) for row in rows if row.enabled]

            from s3 import s3_str
            s3.actions += [dict(label=s3_str(T("Enable")),
                                _class="action-btn",
                                url=URL(args=["[id]", "enable"]),
                                restrict = restrict_e),
                           dict(label=s3_str(T("Disable")),
                                _class="action-btn",
                                url = URL(args = ["[id]", "disable"]),
                                restrict = restrict_d),
                           ]
            if not s3task._is_alive():
                # No Scheduler Running
                s3.actions += [dict(label=s3_str(T("Poll")),
                                    _class="action-btn",
                                    url = URL(args = ["[id]", "poll"]),
                                    restrict = restrict_d)
                               ]
        return output
Exemple #2
0
    def people_affected(cls):
        """
            Count total number of affected people by demographic type
        """

        db = current.db
        s3db = current.s3db

        table = s3db.req_need_line

        query = (table.deleted == False)
        demographic = table.parameter_id
        represent = demographic.represent
        total = table.value.sum()

        rows = db(query).select(demographic,
                                total,
                                groupby = demographic,
                                orderby = ~(total),
                                limitby = (0, 5),
                                )
        values = []
        for row in rows:
            value = row[total]
            parameter_id = row[demographic]
            values.append({"label": s3_str(represent(parameter_id)),
                           "value": value if value else 0,
                           "filterKey": parameter_id,
                           })

        return [{"key": s3_str(current.T("People Affected")),
                 "values": values,
                 },
                ]
Exemple #3
0
            def custom_postp(r, output):
                # Call standard postp
                if callable(standard_postp):
                    output = standard_postp(r, output)

                from gluon import URL
                from s3 import s3_str

                if workflow == "issue":
                    s3.actions = [
                        {
                            "label":
                            s3_str(T("Issue")),
                            "url":
                            URL(
                                f="asset",
                                args=["[id]", "log", "assignperson"],
                            ),
                            "_class":
                            "action-btn",
                        },
                    ]
                elif workflow == "return":
                    s3.actions = [
                        {
                            "label": s3_str(T("Return")),
                            "url": URL(
                                f="asset",
                                args=["[id]", "log", "return"],
                            ),
                            "_class": "action-btn",
                        },
                    ]

                return output
Exemple #4
0
    def postp(r, output):
        if r.interactive:
            # Normal Action Buttons
            s3_action_buttons(r)
            # Custom Action Buttons for Enable/Disable
            table = r.table
            query = (table.deleted == False)
            rows = db(query).select(
                table.id,
                table.enabled,
            )
            restrict_e = [str(row.id) for row in rows if not row.enabled]
            restrict_d = [str(row.id) for row in rows if row.enabled]

            from s3 import s3_str
            s3.actions += [
                dict(label=s3_str(T("Enable")),
                     _class="action-btn",
                     url=URL(args=["[id]", "enable"]),
                     restrict=restrict_e),
                dict(label=s3_str(T("Disable")),
                     _class="action-btn",
                     url=URL(args=["[id]", "disable"]),
                     restrict=restrict_d),
            ]
            if not s3task._is_alive():
                # No Scheduler Running
                s3.actions += [
                    dict(label=s3_str(T("Poll")),
                         _class="action-btn",
                         url=URL(args=["[id]", "poll"]),
                         restrict=restrict_d)
                ]
        return output
Exemple #5
0
    def get_sms_content(row):
        """
            prepare the content for SMS
        """

        from gluon.languages import lazyT
        itable = current.s3db.cap_info
        event_type_id = row["cap_info.event_type_id"]
        priority_id = row["cap_info.priority"]

        if not isinstance(event_type_id, lazyT):
            event_type = itable.event_type_id.represent(event_type_id)
        else:
            event_type = event_type_id

        if priority_id and priority_id != "-":
            if not isinstance(priority_id, lazyT):
                priority = itable.priority.represent(priority_id)
            else:
                priority = priority_id
        else:
            priority = T("None")

        sms_body = \
T("""%(Status)s %(MessageType)s for %(AreaDescription)s with %(Priority)s priority %(EventType)s issued by %(SenderName)s at %(Date)s (ID:%(Identifier)s) \n\n""") % \
            dict(Status = s3_str(row["cap_alert.status"]),
                 MessageType = s3_str(row["cap_alert.msg_type"]),
                 AreaDescription = s3_str(row["cap_area.name"]),
                 Priority = s3_str(priority),
                 EventType = s3_str(event_type),
                 SenderName = s3_str(row["cap_info.sender_name"]),
                 Date = s3_str(row["cap_alert.sent"]),
                 Identifier = s3_str(row["cap_alert.identifier"]))

        return s3_str(sms_body)
Exemple #6
0
def set_priority_js():
    """ Output json for priority field """

    wptable = s3db.cap_warning_priority

    rows = db(wptable).select(
        wptable.name,
        wptable.urgency,
        wptable.severity,
        wptable.certainty,
        wptable.color_code,
        orderby=wptable.name,
    )

    from gluon.serializers import json as jsons
    from s3 import s3_str
    p_settings = [(s3_str(T(r.name)), r.urgency, r.severity, r.certainty, r.color_code)\
                 for r in rows]

    priority_conf = '''S3.cap_priorities=%s''' % jsons(p_settings)
    js_global = s3.js_global
    if not priority_conf in js_global:
        js_global.append(priority_conf)

    return
Exemple #7
0
    def render_list(self, value, labels, show_link=True):
        """
            Helper method to render list-type representations from
            bulk()-results.

            @param value: the list
            @param labels: the labels as returned from bulk()
            @param show_link: render references as links, should
                              be the same as used with bulk()
        """

        show_link = show_link and self.show_link

        values = [v for v in value if v is not None]
        if not len(values):
            return ""

        if show_link:
            labels_ = (labels[v] if v in labels else self.default
                       for v in values)
        else:
            labels_ = sorted(
                s3_str(labels[v]) if v in labels else self.default
                for v in values)

        if current.auth.permission.format == "xls":
            return ", ".join(labels_)

        html = UL(_class="service-list")
        for label in labels_:
            html.append(LI(label))

        return html
Exemple #8
0
    def get_email_subject(row):
        """
            prepare the subject for Email
        """

        from gluon.languages import lazyT
        itable = current.s3db.cap_info
        event_type_id = row["cap_info.event_type_id"]
        priority_id = row["cap_info.priority"]

        if not isinstance(event_type_id, lazyT):
            event_type = itable.event_type_id.represent(event_type_id)
        else:
            event_type = event_type_id

        if priority_id and priority_id != "-":
            if not isinstance(priority_id, lazyT):
                priority = itable.priority.represent(priority_id)
            else:
                priority = priority_id
        else:
            priority = T("None")

        subject = "[%s] %s %s" % (s3_str(row["cap_info.sender_name"]),
                                  event_type,
                                  priority)

        return subject
Exemple #9
0
    def write(self, sheet, rowindex, colindex, label, style="odd"):
        """
            Write a label/value into the XLS worksheet

            @param sheet: the worksheet
            @param rowindex: the row index
            @param colindex: the column index
            @param label: the label/value to write
            @param style: style name (S3XLS styles)
        """

        styles = self.styles
        if not styles:
            self.styles = styles = S3XLS._styles()

        style = styles.get(style)
        if not style:
            import xlwt
            style = xlwt.XFStyle()

        label = s3_str(label)

        # Adjust column width
        col = sheet.col(colindex)
        curwidth = col.width or 0
        adjwidth = max(len(label) * 240, 2480) if label else 2480
        col.width = max(curwidth, adjwidth)

        row = sheet.row(rowindex)
        row.write(colindex, label, style)
Exemple #10
0
    def write(self, sheet, rowindex, colindex, label, style="odd"):
        """
            Write a label/value into the XLS worksheet

            @param sheet: the worksheet
            @param rowindex: the row index
            @param colindex: the column index
            @param label: the label/value to write
            @param style: style name (S3XLS styles)
        """

        styles = self.styles
        if not styles:
            self.styles = styles = S3XLS._styles()

        style = styles.get(style)
        if not style:
            import xlwt
            style = xlwt.XFStyle()

        label = s3_str(label)

        # Adjust column width
        col = sheet.col(colindex)
        curwidth = col.width or 0
        adjwidth = max(len(label) * 240, 2480) if label else 2480
        col.width = max(curwidth, adjwidth)

        row = sheet.row(rowindex)
        row.write(colindex, label, style)
Exemple #11
0
    def needs_by_status(cls):
        """
            Count need lines per status
            - for all open Events
        """

        db = current.db
        s3db = current.s3db

        table = s3db.req_need_line
        etable = s3db.event_event
        ltable = s3db.event_event_need

        # Extract the data
        status = table.status
        number = table.id.count()
        query = (etable.closed == False) & \
                (etable.id == ltable.event_id) & \
                (ltable.need_id == table.need_id) & \
                (table.deleted == False)

        rows = db(query).select(status, number, groupby = status)

        # Build data structure for chart renderer
        rows = dict((row[status], row[number]) for row in rows)
        data = []
        for code, label, color in cls.REQ_STATUS[::-1]: # clockwise
            value = rows.get(code)
            data.append({"label": s3_str(label),
                         "value": value if value else 0,
                         "color": color,
                         "filterKey": code,
                         })

        return data
Exemple #12
0
    def needs_by_status(cls):
        """
            Count need lines per status
        """

        db = current.db

        # Extract the data
        table = current.s3db.req_need_line
        status = table.status
        number = table.id.count()
        query = (table.deleted == False)
        rows = db(query).select(status, number, groupby=status)

        # Build data structure for chart renderer
        rows = dict((row[status], row[number]) for row in rows)
        data = []
        for code, label, color in cls.REQ_STATUS:
            value = rows.get(code)
            data.append({
                "label": s3_str(label),
                "value": value if value else 0,
                "color": color,
                "filterKey": code,
            })

        return data
Exemple #13
0
    def needs_by_status(cls):
        """
            Count need lines per status
        """

        db = current.db

        # Extract the data
        table = current.s3db.req_need_line
        status = table.status
        number = table.id.count()
        query = (table.deleted == False)
        rows = db(query).select(status, number, groupby = status)

        # Build data structure for chart renderer
        rows = dict((row[status], row[number]) for row in rows)
        data = []
        for code, label, color in cls.REQ_STATUS:
            value = rows.get(code)
            data.append({"label": s3_str(label),
                         "value": value if value else 0,
                         "color": color,
                         "filterKey": code,
                         })

        return data
Exemple #14
0
    def ucce_masterkey_context(masterkey):
        """
            Provide context information for a masterkey (populates session
            in mobile app when linking to this masterkey)

            Args:
                masterkey: the auth_masterkey Row

            Returns:
                JSON-serializable dict with the context data
        """

        db = current.db
        s3db = current.s3db

        context = {}

        # Look up the project linked to the master key
        ptable = s3db.project_project
        ltable = s3db.project_project_masterkey

        query = (ltable.id == masterkey.id) & \
                (ltable.deleted == False) & \
                (ptable.id == ltable.project_id) & \
                (ptable.deleted == False)
        project = db(query).select(ptable.id,
                                   ptable.name,
                                   limitby = (0, 1),
                                   ).first()
        if project:
            # Provide the project title
            context["projectTitle"] = project.name

            # Provide a list of available translations in this project
            languages = []

            # Use translated language names
            from s3 import IS_ISO639_2_LANGUAGE_CODE, s3_str
            represent = IS_ISO639_2_LANGUAGE_CODE.represent_local

            # Look up the languages
            ttable = s3db.project_project_target
            l10ntable = s3db.dc_target_l10n
            query = (ttable.project_id == project.id) & \
                    (ttable.deleted == False) & \
                    (ttable.target_id == l10ntable.target_id) & \
                    (l10ntable.language != None)

            # Build the language list
            rows = db(query).select(l10ntable.language)
            seen = set()
            for row in rows:
                code = row.language
                if code not in seen:
                    languages.append((code, s3_str(represent(code))))
                seen.add(code)

            context["surveyLanguages"] = languages

        return context
Exemple #15
0
    def draw_value(self,
                   x,
                   y,
                   value,
                   width=120,
                   height=40,
                   size=7,
                   bold=True,
                   valign=None):
        """
            Helper function to draw a centered text above position (x, y);
            allows the text to wrap if it would otherwise exceed the given
            width

            Args:
                x: drawing position
                y: drawing position
                value: the text to render
                width: the maximum available width (points)
                height: the maximum available height (points)
                size: the font size (points)
                bold: use bold font
                valign: vertical alignment ("top"|"middle"|"bottom"),
                        default "bottom"

            Returns:
                The actual height of the text element drawn
        """

        # Preserve line breaks by replacing them with <br/> tags
        value = s3_str(value).strip("\n").replace('\n', '<br />\n')

        styleSheet = getSampleStyleSheet()
        style = styleSheet["Normal"]
        style.fontName = BOLD if bold else NORMAL
        style.fontSize = size
        style.leading = size + 2
        style.splitLongWords = False
        style.alignment = TA_CENTER

        para = Paragraph(value, style)
        aW, aH = para.wrap(width, height)

        while ((aH > height or aW > width) and style.fontSize > 4):
            # Reduce font size to make fit
            style.fontSize -= 1
            style.leading = style.fontSize + 2
            para = Paragraph(value, style)
            aW, aH = para.wrap(width, height)

        if valign == "top":
            vshift = aH
        elif valign == "middle":
            vshift = aH / 2.0
        else:
            vshift = 0

        para.drawOn(self.canv, x - para.width / 2, y - vshift)
        return aH
Exemple #16
0
        def onapprove(record):
            # Normal onapprove
            s3db.cap_alert_approve(record)

            # Sync FTP Repository
            current.s3task.async("cap_ftp_sync")

            # Twitter Post
            if settings.get_cap_post_to_twitter():
                try:
                    import tweepy
                except ImportError:
                    current.log.debug("tweepy module needed for sending tweets")
                else:
                    T = current.T
                    db = current.db
                    alert_id = int(record["id"])
                    atable = s3db.cap_alert
                    itable = s3db.cap_info
        
                    arow = db(atable.id == alert_id).select(atable.status,
                                                            atable.sender,
                                                            atable.sent,
                                                            limitby=(0, 1)).first()
                    query = (itable.alert_id == alert_id) & \
                            (itable.deleted != True)
                    irows = db(query).select(itable.headline,
                                             itable.web)
                    # @ToDo: shorten url
                    # @ToDo: Handle the multi-message nicely?
                    # @ToDo: Send resource url with tweet
                    for irow in irows:
                        twitter_text = \
("""%(Status)s: %(Headline)s
%(SENDER)s: %(SenderName)s
%(WEBSITE)s: %(Website)s""") % dict(Status = arow.status,
                                    Headline = s3_str(irow.headline),
                                    SENDER = T("Sender"),
                                    SenderName = s3_str(arow.sender),
                                    WEBSITE = T("Website"),
                                    Website = irow.web)
                        try:
                            current.msg.send_tweet(text=twitter_text)
                        except tweepy.error.TweepError, e:
                            current.log.debug("Sending tweets failed: %s" % e)
Exemple #17
0
    def people_affected(cls):
        """
            Count total number of affected people by demographic type
            - for all open Events
        """

        db = current.db
        s3db = current.s3db

        table = s3db.req_need_line
        etable = s3db.event_event
        ltable = s3db.event_event_need

        query = (etable.closed == False) & \
                (etable.id == ltable.event_id) & \
                (ltable.need_id == table.need_id) & \
                (table.deleted == False)

        demographic = table.parameter_id
        represent = demographic.represent
        total = table.value.sum()

        rows = db(query).select(
            demographic,
            total,
            groupby=demographic,
            orderby=~(total),
            limitby=(0, 5),
        )
        values = []
        for row in rows:
            value = row[total]
            parameter_id = row[demographic]
            values.append({
                "label": s3_str(represent(parameter_id)),
                "value": value if value else 0,
                "filterKey": parameter_id,
            })

        return [
            {
                "key": s3_str(current.T("People Affected")),
                "values": values,
            },
        ]
Exemple #18
0
    def represent_row(self, row, prefix=None):
        """
            Represent a single Row

            @param row: the req_need Row
        """

        # Custom Row (with the tag left-joined)
        req_number = row["req_need_tag.value"]
        if req_number:
            return s3_str(req_number)
        else:
            # Fallback to name
            name = row["req_need.name"]
            if name:
                return s3_str(name)
            else:
                return current.messages["NONE"]
Exemple #19
0
    def represent_row(self, row, prefix=None):
        """
            Represent a single Row

            @param row: the req_need Row
        """

        # Custom Row (with the tag left-joined)
        req_number = row["req_need_tag.value"]
        if req_number:
            return s3_str(req_number)
        else:
            # Fallback to name
            name = row["req_need.name"]
            if name:
                return s3_str(name)
            else:
                return current.messages["NONE"]
Exemple #20
0
        def onapprove(record):
            # Normal onapprove
            s3db.cap_alert_approve(record)
            # Sync FTP Repository
            current.s3task. async ("cap_ftp_sync")

            # Twitter Post
            if settings.get_cap_post_to_twitter() and \
               record["scope"] != "Private":
                try:
                    import tweepy
                except ImportError:
                    current.log.debug(
                        "tweepy module needed for sending tweets")
                else:
                    alert_id = int(record["id"])
                    atable = s3db.cap_alert
                    itable = s3db.cap_info

                    arow = db(atable.id == alert_id).select(
                        atable.status, limitby=(0, 1)).first()
                    query = (itable.alert_id == alert_id) & \
                            (itable.deleted != True)
                    irows = db(query).select(itable.headline,
                                             itable.sender_name, itable.web)
                    # @ToDo: shorten url
                    # @ToDo: Handle the multi-message nicely?
                    # @ToDo: Send resource url with tweet
                    for irow in irows:
                        twitter_text = \
("""%(Status)s: %(Headline)s
%(SENDER)s: %(SenderName)s
%(WEBSITE)s: %(Website)s%(Profile)s""") % dict(Status = arow.status,
                                               Headline = s3_str(irow.headline),
                                               SENDER = T("Sender"),
                                               SenderName = s3_str(irow.sender_name),
                                               WEBSITE = T("Website"),
                                               Website = irow.web,
                                               Profile = "/profile",
                                               )
                        try:
                            current.msg.send_tweet(text=twitter_text)
                        except tweepy.error.TweepError, e:
                            current.log.debug("Sending tweets failed: %s" % e)
Exemple #21
0
def cap_AreaRowOptionsBuilder(alert_id, caller=None):
    """
        Build the options for the cap_area associated with alert_id
        with the translated name (if available)
        @param caller: currently used by assign method
    """

    atable = s3db.cap_area

    if caller:
        assign = caller == "assign"
    else:
        assign = None
    if assign:
        query = (atable.is_template == True) & (atable.deleted != True)
    else:
        query = (atable.alert_id == alert_id) & (atable.deleted != True)

    rows = db(query).select(atable.id,
                            atable.template_area_id,
                            atable.name,
                            orderby=atable.id)
    values = [row.id for row in rows]
    count = len(values)
    if count:
        from s3 import s3_str
        if count == 1:
            query_ = (atable.id == values[0])
        else:
            query_ = (atable.id.belongs(values))

        ltable = s3db.cap_area_name
        if assign:
            left = [ltable.on((ltable.area_id == atable.id) & \
                              (ltable.language == session.s3.language)),
                    ]
        else:
            left = [ltable.on((ltable.area_id == atable.template_area_id) & \
                              (ltable.language == session.s3.language)),
                    ]

        fields = [atable.name,
                  ltable.name_l10n,
                  ]
        rows_ = db(query_).select(left=left,
                                  limitby=(0, count),
                                  *fields)

        cap_area_options = {}
        for row_ in rows_:
                cap_area_options[row_["cap_area.name"]] = \
                            s3_str(row_["cap_area_name.name_l10n"] or \
                                   row_["cap_area.name"])

        return cap_area_options
Exemple #22
0
def cap_AreaRowOptionsBuilder(alert_id, caller=None):
    """
        Build the options for the cap_area associated with alert_id
        with the translated name (if available)
        @param caller: currently used by assign method
    """

    atable = s3db.cap_area

    if caller:
        assign = caller == "assign"
    else:
        assign = None
    if assign:
        query = (atable.is_template == True) & (atable.deleted != True)
    else:
        query = (atable.alert_id == alert_id) & (atable.deleted != True)

    rows = db(query).select(atable.id,
                            atable.template_area_id,
                            atable.name,
                            orderby=atable.id)
    values = [row.id for row in rows]
    count = len(values)
    if count:
        from s3 import s3_str
        if count == 1:
            query_ = (atable.id == values[0])
        else:
            query_ = (atable.id.belongs(values))

        ltable = s3db.cap_area_name
        if assign:
            left = [ltable.on((ltable.area_id == atable.id) & \
                              (ltable.language == session.s3.language)),
                    ]
        else:
            left = [ltable.on((ltable.area_id == atable.template_area_id) & \
                              (ltable.language == session.s3.language)),
                    ]

        fields = [
            atable.name,
            ltable.name_l10n,
        ]
        rows_ = db(query_).select(left=left, limitby=(0, count), *fields)

        cap_area_options = {}
        for row_ in rows_:
            cap_area_options[row_["cap_area.name"]] = \
                        s3_str(row_["cap_area_name.name_l10n"] or \
                               row_["cap_area.name"])

        return cap_area_options
Exemple #23
0
    def json(self):
        """
            Produce the notification emails as JSON-serializable dict

            @returns: a dict of dicts of the structure:
                         {recipient_type: {email, subject, message}}
        """

        data = self.data()
        if not data:
            return {}

        for key, value in list(data.items()):
            if value is None:
                data[key] = "-"
            else:
                data[key] = s3_str(value)

        output = {
            "delegationID": self.delegation_id,
            "data": data,
            "email": {},
            "autoSelect": {},
            "cc": data.get("coordinator_email"),
            "templates": {},
        }

        recipients = self.recipients
        for recipient in ("organisation", "volunteer", "office"):

            config = recipients.get(recipient)
            if not config:
                continue
            template_name, auto_select = config

            templates = self.templates(template_name)
            if templates:
                output["templates"][recipient] = {
                    "subject": templates[0],
                    "message": templates[1],
                }
            else:
                continue

            if recipient == "office":
                email = data.get("volunteer_office_email")
            else:
                email = data.get("%s_email" % recipient)
            if email:
                output["email"][recipient] = email

            output["autoSelect"][recipient] = auto_select

        return output
Exemple #24
0
        def custom_postp(r, output):
            # Call standard postp
            if callable(standard_postp):
                output = standard_postp(r, output)

            if ERT_LEADER:
                # Don't open Projects: Open Activities
                from gluon import URL
                from s3 import s3_str

                s3.actions = [dict(label=s3_str(T("Open")), _class="action-btn", url=URL(args=["[id]", "activity"]))]

            return output
Exemple #25
0
    def needs_by_category(cls):
        """
            Count current case activities by need type
        """

        db = current.db
        s3db = current.s3db

        atable = s3db.br_case_activity
        stable = s3db.br_case_activity_status

        join = stable.on((stable.id == atable.status_id) & \
                         (stable.is_closed == False))

        today = current.request.utcnow.date()
        query = ((atable.date == None) | (atable.date <= today)) & \
                ((atable.end_date == None) | (atable.end_date >= today)) & \
                (atable.person_id != None) & \
                (atable.need_id != None) & \
                (atable.deleted == False)

        number = atable.id.count()
        rows = db(query).select(
            atable.need_id,
            number,
            join=join,
            groupby=atable.need_id,
            orderby=~number,
            limitby=(0, 5),
        )

        represent = atable.need_id.represent
        labels = represent.bulk([row.br_case_activity.need_id for row in rows])

        values = []
        for row in rows:
            value = row[number]
            need_id = row.br_case_activity.need_id
            need = labels.get(need_id)
            values.append({
                "label": str(need),
                "color": cls.get_color(need_id),
                "value": value if value else 0,
            })

        return [
            {
                "key": s3_str(current.T("Current Need Reports")),
                "values": values,
            },
        ]
Exemple #26
0
    def offers_by_category(cls):
        """
            Count current assistance offers by need type
        """

        db = current.db
        s3db = current.s3db

        atable = s3db.br_assistance_offer

        today = current.request.utcnow.date()
        query = (atable.status == "APR") & \
                (atable.availability == "AVL") & \
                ((atable.date == None) | (atable.date <= today)) & \
                ((atable.end_date == None) | (atable.end_date >= today)) & \
                (atable.pe_id != None) & \
                (atable.need_id != None) & \
                (atable.deleted == False)

        number = atable.id.count()
        rows = db(query).select(
            atable.need_id,
            number,
            groupby=atable.need_id,
            orderby=~number,
            limitby=(0, 5),
        )

        represent = atable.need_id.represent
        labels = represent.bulk(
            [row.br_assistance_offer.need_id for row in rows])

        values = []
        for row in rows:
            value = row[number]
            need_id = row.br_assistance_offer.need_id
            need = labels.get(need_id)
            values.append({
                "label": str(need),
                "color": cls.get_color(need_id),
                "value": value if value else 0,
            })

        return [
            {
                "key": s3_str(current.T("Current Relief Offers")),
                "values": values,
            },
        ]
Exemple #27
0
    def draw_value(self, x, y, value, width=120, height=40, size=7, bold=True, valign=None):
        """
            Helper function to draw a centered text above position (x, y);
            allows the text to wrap if it would otherwise exceed the given
            width

            @param x: drawing position
            @param y: drawing position
            @param value: the text to render
            @param width: the maximum available width (points)
            @param height: the maximum available height (points)
            @param size: the font size (points)
            @param bold: use bold font
            @param valign: vertical alignment ("top"|"middle"|"bottom"),
                           default "bottom"

            @returns: the actual height of the text element drawn
        """

        # Preserve line breaks by replacing them with <br/> tags
        value = s3_str(value).strip("\n").replace('\n','<br />\n')

        stylesheet = getSampleStyleSheet()
        style = stylesheet["Normal"]
        style.fontName = BOLD if bold else NORMAL
        style.fontSize = size
        style.leading = size + 2
        style.splitLongWords = False
        style.alignment = TA_CENTER

        para = Paragraph(value, style)
        aw, ah = para.wrap(width, height)

        while((ah > height or aw > width) and style.fontSize > 4):
            # Reduce font size to make fit
            style.fontSize -= 1
            style.leading = style.fontSize + 2
            para = Paragraph(value, style)
            aw, ah = para.wrap(width, height)

        if valign == "top":
            vshift = ah
        elif valign == "middle":
            vshift = ah / 2.0
        else:
            vshift = 0

        para.drawOn(self.canv, x - para.width / 2, y - vshift)
        return ah
Exemple #28
0
    def represent_row(self, row):
        """
            Represent a single Row

            Args:
                row: the org_site Row
        """

        name = row["org_site.name"]

        if not name:
            return self.default

        if self.show_type:
            instance_type = row["org_site.instance_type"]
            facility_types = row.get("facility_types")

            if facility_types:
                represent = current.s3db.org_site_facility_type.facility_type_id.represent
                type_names = represent.multiple(facility_types)
                name = "%s (%s)" % (name, type_names)
            else:
                instance_type = current.auth.org_site_types.get(
                    instance_type, None)
                if instance_type:
                    name = "%s (%s)" % (name, instance_type)

        organisation_id = row.get("org_organisation.id")
        root_org = row.get("org_organisation.root_organisation")
        ns = None
        parent = None
        if root_org == self.root_org:
            if organisation_id != self.organisation_id:
                parent = self.org_labels.get(organisation_id)
        else:
            ns = self.org_labels.get(root_org)
            if root_org != organisation_id:
                parent = self.org_labels.get(organisation_id)

        if ns:
            if parent:
                name = "ᛜᛜ%s > %s > %s" % (ns, parent, name)
            else:
                name = "ᛜᛜ%s > %s" % (ns, name)
        elif parent:
            name = "ᛜ%s > %s" % (parent, name)

        return s3_str(name)
Exemple #29
0
        def custom_postp(r, output):
            # Call standard postp
            if callable(standard_postp):
                output = standard_postp(r, output)

            if ERT_LEADER:
                # Don't open Projects: Open Activities
                from gluon import URL
                from s3 import s3_str
                s3.actions = [
                    dict(label=s3_str(T("Open")),
                         _class="action-btn",
                         url=URL(args=["[id]", "activity"])),
                ]

            return output
Exemple #30
0
    def link(self, k, v, row=None):
        """
            Represent a (key, value) as hypertext link.
            - same as default, except with k and v reversed ;)

            @param k: the key [here: the shipment code]
            @param v: the representation of the key [here: the record ID]

            @param row: the row with this key
        """

        if self.linkto:
            k = s3_str(k)
            return A(k, _href=self.linkto.replace("[id]", v) \
                                         .replace("%5Bid%5D", v))
        else:
            return k
Exemple #31
0
    def represent_row(self, row, prefix=None):
        """
            Represent a single Row

            @param row: the project_activity Row
        """

        # Custom Row (with the Orgs left-joined)
        organisation_id = row["project_activity_organisation.organisation_id"]
        if organisation_id:
            return self.org_represent(organisation_id)
        else:
            # Fallback to name
            name = row["project_activity.name"]
            if name:
                return s3_str(name)
            else:
                return current.messages["NONE"]
Exemple #32
0
    def represent_row(self, row, prefix=None):
        """
            Represent a single Row

            @param row: the project_activity Row
        """

        # Custom Row (with the Orgs left-joined)
        organisation_id = row["project_activity_organisation.organisation_id"]
        if organisation_id:
            return self.org_represent(organisation_id)
        else:
            # Fallback to name
            name = row["project_activity.name"]
            if name:
                return s3_str(name)
            else:
                return current.messages["NONE"]
Exemple #33
0
 def write_details_to_csv(csv_file, statistic, data):
     cnt = 0
     writerow = csv_file.writerow
     for (location, details) in data.items():
         loc = location_list[location]
         for key in sorted(details.keys()):
             row = details[key]
             source = row[2]
             source_url = ""
             url = urlparse.urlparse(source)
             if url[0] != "":
                 source_url = source
                 (head, tail) = split(url[2])
                 source = tail.replace("%20", " ")
             cnt += 1
             writerow([
                 statistic, row[0], loc[0], loc[1], loc[2], loc[3], key,
                 s3_str(source), row[1], source_url
             ])
Exemple #34
0
    def draw_label(self, x, y, colname, default=""):
        """
            Helper function to draw a centered label below position (x, y)

            @param x: drawing position
            @param y: drawing position
            @param colname: the column name of the field to look up the label
            @param default: the default label (if label cannot be looked up),
                            pass colname=None to enforce using the default
        """

        if colname:
            label = self.labels.get(colname, default)
        else:
            label = default

        c = self.canv
        c.setFont(NORMAL, 5)
        c.drawCentredString(x, y - 6, s3_str(label))
Exemple #35
0
    def draw_label(self, x, y, colname, default=""):
        """
            Helper function to draw a centered label below position (x, y)

            @param x: drawing position
            @param y: drawing position
            @param colname: the column name of the field to look up the label
            @param default: the default label (if label cannot be looked up),
                            pass colname=None to enforce using the default
        """

        if colname:
            label = self.labels.get(colname, default)
        else:
            label = default

        c = self.canv
        c.setFont(NORMAL, 5)
        c.drawCentredString(x, y - 6, s3_str(label))
Exemple #36
0
    def draw_field(self, x, y, colname, size=7, bold=True):
        """
            Helper function to draw a centered field value of self.item above
            position (x, y)

            @param x: drawing position
            @param y: drawing position
            @param colname: the column name of the field to look up the value
            @param size: the font size (points)
            @param bold: use bold font
        """

        c = self.canv

        font = BOLD if bold else NORMAL

        value = self.item.get(colname)
        if value:
            c.setFont(font, size)
            c.drawCentredString(x, y, s3_str(value))
Exemple #37
0
    def draw_field(self, x, y, colname, size=7, bold=True):
        """
            Helper function to draw a centered field value of self.item above
            position (x, y)

            @param x: drawing position
            @param y: drawing position
            @param colname: the column name of the field to look up the value
            @param size: the font size (points)
            @param bold: use bold font
        """

        c = self.canv

        font = BOLD if bold else NORMAL

        value = self.item.get(colname)
        if value:
            c.setFont(font, size)
            c.drawCentredString(x, y, s3_str(value))
Exemple #38
0
    def represent_row(self, row):
        """
            Represent a row

            @param row: the Row
        """

        pentity = row.pr_pentity
        instance_type = pentity.instance_type

        item = object.__getattribute__(row, instance_type)
        if instance_type == "pr_person":
            if self.as_string:
                pe_str = current.T("private")
            else:
                pe_str = SPAN(current.T("private"), _class="free-hint")
        elif "name" in item:
            pe_str = s3_str(item["name"])
        else:
            pe_str = "?"

        return pe_str
Exemple #39
0
    def get_sms_content(row):
        """
            prepare the content for SMS
        """

        from gluon.languages import lazyT
        itable = current.s3db.cap_info
        event_type_id = row["cap_info.event_type_id"]
        priority_id = row["cap_info.priority"]

        if not isinstance(event_type_id, lazyT):
            event_type = itable.event_type_id.represent(event_type_id)
        else:
            event_type = event_type_id

        if priority_id and priority_id != "-":
            if not isinstance(priority_id, lazyT):
                priority = itable.priority.represent(priority_id)
            else:
                priority = priority_id
        else:
            priority = T("None")

        sms_body = \
T("""%(Status)s %(MessageType)s for %(AreaDescription)s with %(Priority)s
priority %(EventType)s issued by %(SenderName)s at %(Date)s (ID:%(Identifier)s)""") % \
            dict(Status = s3_str(row["cap_alert.status"]),
                 MessageType = s3_str(row["cap_alert.msg_type"]),
                 AreaDescription = s3_str(row["cap_area.name"]),
                 Priority = s3_str(priority),
                 EventType = s3_str(event_type),
                 SenderName = s3_str(row["cap_info.sender_name"]),
                 Date = s3_str(row["cap_alert.sent"]),
                 Identifier = s3_str(row["cap_alert.identifier"]))

        return sms_body
Exemple #40
0
    def inject_js(widget_id, options):
        """
            Helper function to inject static JS and instantiate
            the foodRegistration widget

            @param widget_id: the node ID where to instantiate the widget
            @param options: dict of widget options (JSON-serializable)
        """

        T = current.T

        s3 = current.response.s3
        appname = current.request.application

        # Custom Ajax-URL
        options["ajaxURL"] = URL(
            c="dvr",
            f="case_event",
            args=["register_food.json"],
        )
        options["selectAllText"] = s3_str(T("Select All"))

        # Custom JS
        scripts = s3.scripts
        # @Todo: minify?
        #if s3.debug:
        #    script = "/%s/static/themes/DRK/js/food.js" % appname
        #else:
        #    script = "/%s/static/themes/DRK/js/food.min.js" % appname
        script = "/%s/static/themes/DRK/js/food.js" % appname
        scripts.append(script)

        # Instantiate widget
        scripts = s3.jquery_ready
        script = '''$('#%(id)s').foodRegistration(%(options)s)''' % \
                 {"id": widget_id, "options": json.dumps(options)}
        if script not in scripts:
            scripts.append(script)
Exemple #41
0
    def inject_js(widget_id, options):
        """
            Helper function to inject static JS and instantiate
            the foodRegistration widget

            @param widget_id: the node ID where to instantiate the widget
            @param options: dict of widget options (JSON-serializable)
        """

        T = current.T

        s3 = current.response.s3
        appname = current.request.application

        # Custom Ajax-URL
        options["ajaxURL"] = URL(c = "dvr",
                                 f = "case_event",
                                 args = ["register_food.json"],
                                 )
        options["selectAllText"] = s3_str(T("Select All"))

        # Custom JS
        scripts = s3.scripts
        # @Todo: minify?
        #if s3.debug:
        #    script = "/%s/static/themes/DRK/js/food.js" % appname
        #else:
        #    script = "/%s/static/themes/DRK/js/food.min.js" % appname
        script = "/%s/static/themes/DRK/js/food.js" % appname
        scripts.append(script)

        # Instantiate widget
        scripts = s3.jquery_ready
        script = '''$('#%(id)s').foodRegistration(%(options)s)''' % \
                 {"id": widget_id, "options": json.dumps(options)}
        if script not in scripts:
            scripts.append(script)
Exemple #42
0
def set_priority_js():
    """ Output json for priority field """

    wptable = s3db.cap_warning_priority

    rows = db(wptable).select(wptable.name,
                              wptable.urgency,
                              wptable.severity,
                              wptable.certainty,
                              wptable.color_code,
                              orderby = wptable.name,
                              )

    from gluon.serializers import json as jsons
    from s3 import s3_str
    p_settings = [(s3_str(T(r.name)), r.urgency, r.severity, r.certainty, r.color_code)\
                 for r in rows]

    priority_conf = '''S3.cap_priorities=%s''' % jsons(p_settings)
    js_global = s3.js_global
    if not priority_conf in js_global:
        js_global.append(priority_conf)

    return
Exemple #43
0
    def pr_subscription_filter_row_options():
        """
            Build the options for the pr_subscription filter datatable from query
            @ToDo complete this for locations
        """

        db = current.db
        s3db = current.s3db
        auth = current.auth
        has_role = auth.s3_has_role
        stable = s3db.pr_subscription
        ftable = s3db.pr_filter

        if current.request.get_vars["option"] == "manage_recipient" and \
           (has_role("ALERT_EDITOR") or has_role("ALERT_APPROVER")):
                # Admin based subscription
                query = (stable.deleted != True) & \
                        (stable.owned_by_group != None)
        else:
            # Self Subscription
            query = (stable.deleted != True) & \
                    (stable.owned_by_group == None) & \
                    (stable.owned_by_user == auth.user.id)

        left = ftable.on(ftable.id == stable.filter_id)
        rows = db(query).select(stable.filter_id,
                                ftable.query,
                                left=left)
        if len(rows) > 0:
            T = current.T
            etable = s3db.event_event_type
            ptable = s3db.cap_warning_priority
            filter_options = {}
            for row in rows:
                event_type = None
                priorities_id = []
                languages = []

                filters = json.loads(row.pr_filter.query)
                filters = [filter for filter in filters if filter[1] is not None]
                if len(filters) > 0:
                    for filter in filters:
                        # Get the prefix
                        prefix = s3_str(filter[0]).strip("[]")
                        # Get the value for prefix
                        values = filter[1].split(",")
                        if prefix == "event_type_id__belongs":
                            event_type_id = s3_str(values[0])
                            row_ = db(etable.id == event_type_id).select(\
                                                        etable.name,
                                                        limitby=(0, 1)).first()
                            event_type = row_.name
                        elif prefix == "priority__belongs":
                            priorities_id = [int(s3_str(value)) for value in values]
                            rows_ = db(ptable.id.belongs(priorities_id)).select(ptable.name)
                            priorities = [row_.name for row_ in rows_]
                        elif prefix == "language__belongs":
                            languages = [s3_str(value) for value in values]
                    if event_type is not None:
                        display_text = "<b>%s:</b> %s" % (T("Event Type"), event_type)
                    else:
                        display_text = "<b>%s</b>" % (T("Event Type: None"))
                    if len(priorities_id) > 0:
                        display_text = "%s<br/><b>%s</b>: %s" % (display_text, T("Priorities"), priorities)
                    else:
                        display_text = "%s<br/><b>%s</b>" % (display_text, T("Priorities: None"))
                    if len(languages) > 0:
                        display_text = "%s<br/><b>%s</b>:%s" % (display_text, T("Languages"), languages)
                    else:
                        display_text = "%s<br/><b>%s</b>" % (display_text, T("Languages: None"))
                    filter_options[row["pr_subscription.filter_id"]] = display_text
                else:
                    filter_options[row["pr_subscription.filter_id"]] = T("No filters")

            return filter_options
Exemple #44
0
    def get_html_email_content(row):
        """
            prepare the content for html email
        """

        from gluon.languages import lazyT
        itable = current.s3db.cap_info
        event_type_id = row["cap_info.event_type_id"]
        priority_id = row["cap_info.priority"]

        if not isinstance(event_type_id, lazyT):
            event_type = itable.event_type_id.represent(event_type_id)
        else:
            event_type = event_type_id

        if priority_id and \
           priority_id != "-":
            if not isinstance(priority_id, lazyT):
                priority = itable.priority.represent(priority_id)
            else:
                priority = priority_id
        else:
            priority = T("None")

        category = itable.category.represent(row["cap_info.category"])

        response_type = itable.response_type.represent(row["cap_info.response_type"])

        subject = \
        T("%(Scope)s %(Status)s Alert") % \
            dict(Scope = s3_str(row["cap_alert.scope"]),
                 Status = s3_str(row["cap_alert.status"]))
        headline = H2(T((s3_str(row["cap_info.headline"]))))
        id = T("ID: %(Identifier)s") % dict(Identifier = s3_str(row["cap_alert.identifier"]))
        body1 = \
T("""%(Priority)s message %(MessageType)s 
in effect for %(AreaDescription)s""") % dict(\
                    Priority = s3_str(priority),
                    MessageType = s3_str(row["cap_alert.msg_type"]),
                    AreaDescription = s3_str(row["cap_area.name"]))
        body2 = \
        T("This %(Severity)s %(EventType)s is %(Urgency)s and is %(Certainty)s") %\
            dict(Severity = s3_str(row["cap_info.severity"]),
                 EventType = s3_str(event_type),
                 Urgency = s3_str(row["cap_info.urgency"]),
                 Certainty = s3_str(row["cap_info.certainty"]))
        body3 = \
T("""Message %(Identifier)s: %(EventType)s (%(Category)s) issued by 
%(SenderName)s sent at %(Date)s from %(Source)s""") % \
                 dict(Identifier = s3_str(row["cap_alert.identifier"]),
                      EventType = s3_str(event_type),
                      Category = s3_str(category),
                      SenderName = s3_str(row["cap_info.sender_name"]),
                      Date = s3_str(row["cap_alert.sent"]),
                      Source = s3_str(row["cap_alert.source"]))
        body4 = T("Alert Description: %(AreaDescription)s") % \
                dict(AreaDescription = s3_str(row["cap_area.name"]))
        body5 = T("Expected Response: %(ResponseType)s") % \
                dict(ResponseType = s3_str(response_type))
        body6 = T("Instructions: %(Instruction)s") % \
                dict(Instruction=s3_str(row["cap_info.instruction"]))
        body7 = \
T("Alert is effective from %(Effective)s and expires on %(Expires)s") % \
                dict(Effective = s3_str(row["cap_info.effective"]),
                     Expires = s3_str(row["cap_info.expires"]))
        body8 = T("For more details visit %(URL)s or contact %(Contact)s") % \
                dict(URL = s3_str(row["cap_info.web"]),
                     Contact = s3_str(row["cap_info.contact"]))
        body9 = A(T("VIEW ALERT ON THE WEB"),
                    _href = "%s/%s" % (s3_str(row["cap_info.web"]), "profile"))
        return TAG[""](HR(), BR(),
                       body9,
                       BR(), BR(),
                       subject, headline,
                       BR(),
                       id,
                       BR(), BR(),
                       body1,
                       BR(),
                       body2,
                       BR(), BR(),
                       body3,
                       BR(), BR(),
                       body4,
                       BR(), BR(),
                       body5,
                       BR(), BR(),
                       body6,
                       BR(), BR(),
                       body7,
                       BR(), BR(),
                       body8,                       
                       BR())
Exemple #45
0
    def registration_ajax(self, r, **attr):
        """
            Ajax response method, expects a JSON input like:

                {l: the PE label (from the input field),
                 c: boolean to indicate whether to just check
                    the PE label or to register payments
                 t: the event type code
                 x: [array of PE labels,
                     only when registering for multiple persons
                     ]
                 }

            @param r: the S3Request instance
            @param attr: controller parameters
            @return: JSON response, structure:

                    {l: the actual PE label (to update the input field),
                     p: the person details,
                     d: the family details,
                     f: [{n: the flag name
                          i: the flag instructions
                          },
                         ...],
                     b: profile picture URL,
                     i: {<event_code>: [<msg>, <blocked_until_datetime>]},

                     x: [{l: the family member PE label,
                          n: the family member full name,
                          d: the family member date of birth,
                          p: the family member profile picture URL,
                          r: {<event_code>: [<msg>, <blocked_until_datetime>]},
                          },
                         ],

                     s: whether the action is permitted or not

                     e: form error (for label field)

                     a: error message
                     w: warning message
                     m: success message
                     }
        """

        T = current.T
        s3db = current.s3db

        # Load JSON data from request body
        s = r.body
        s.seek(0)
        try:
            data = json.load(s)
        except (ValueError, TypeError):
            r.error(400, current.ERROR.BAD_REQUEST)


        # Initialize processing variables
        output = {}

        error = None

        alert = None
        message = None
        warning = None

        permitted = False
        flags = []

        # Identify the person
        pe_label = data.get("l")
        person = self.get_person(pe_label)

        if person is None:
            error = s3_str(T("No person found with this ID number"))

        else:
            # Get flag info
            flag_info = s3db.dvr_get_flag_instructions(person.id,
                                                       action = "id-check",
                                                       )
            permitted = flag_info["permitted"]

            check = data.get("c")
            if check:

                output["l"] = person.pe_label

                # Person details
                person_details = self.person_details(person)
                output["p"] = s3_str(person_details)

                # Profile picture
                profile_picture = self.profile_picture(person)
                output["b"] = profile_picture

                # Household Size
                details = s3db.dvr_get_household_size(person.id,
                                                      dob = person.date_of_birth,
                                                      )
                if details:
                    output["d"] = {"d": details}

                # Family Members
                family_members = self.get_family_members(person)
                if family_members:
                    output["x"] = family_members

                # Flag Info
                info = flag_info["info"]
                for flagname, instructions in info:
                    flags.append({"n": s3_str(T(flagname)),
                                  "i": s3_str(T(instructions)),
                                  })

                # Blocking periods for events
                event_types = self.get_event_types()
                blocked = self.get_blocked_events(person.id)
                intervals = {}
                for type_id, info in blocked.items():
                    event_type = event_types.get(type_id)
                    if not event_type:
                        continue
                    code = event_type.code
                    msg, dt = info
                    intervals[code] = (s3_str(msg),
                                       "%sZ" % s3_encode_iso_datetime(dt),
                                       )
                output["i"] = intervals
            else:
                # Check event code and permission
                type_id = None
                event_code = data.get("t")
                if not event_code:
                    alert = T("No event type specified")
                elif not permitted:
                    alert = T("Event registration not permitted")
                else:
                    event_type = self.get_event_type(event_code)
                    if not event_type:
                        alert = T("Invalid event type: %s") % event_code
                    else:
                        type_id = event_type.id

                if type_id:

                    family_labels = data.get("x")
                    if family_labels:
                        # Register event for multiple family members

                        # Get family members and interval rules
                        family_members = self.get_family_members(person,
                                                                 include_ids = True,
                                                                 )
                        family_members = dict((m["l"], m) for m in family_members)

                        registered = 0
                        alerts = []
                        for label in family_labels:

                            # Get the family member person_id
                            member = family_members.get(label)
                            if not member:
                                continue
                            member_id = member.get("id")

                            # Check interval rules
                            rules = member.get("r")
                            if rules and event_code in rules:
                                # Event type is currently blocked for this
                                # family member
                                alerts.append(": ".join((s3_str(member["n"]),
                                                         s3_str(rules[event_code][0]),
                                                         )))
                            else:
                                # Ok - register the event
                                self.register_event(member_id, type_id)
                                registered += 1

                        if alerts:
                            alert = ", ".join(alerts)
                        if registered:
                            message = T("%(number)s registrations successful") % \
                                       {"number": registered}
                        elif not alerts:
                            alert = T("Could not register event")

                    else:

                        # Check whether event type is blocked for this person
                        person_id = person.id
                        blocked = self.get_blocked_events(person_id,
                                                          type_id = type_id,
                                                          )
                        if type_id in blocked:
                            # Event type is currently blocked for this person
                            alert = blocked[type_id][0]
                        else:
                            # Ok - register the event
                            success = self.register_event(person.id, type_id)
                            if success:
                                message = T("Event registered")
                            else:
                                alert = T("Could not register event")

        # Add messages to output
        if alert:
            output["a"] = s3_str(alert)
        if error:
            output["e"] = s3_str(error)
        if message:
            output["m"] = s3_str(message)
        if warning:
            output["w"] = s3_str(warning)

        # Add flag info to output
        output["s"] = permitted
        output["f"] = flags

        current.response.headers["Content-Type"] = "application/json"
        return json.dumps(output)
Exemple #46
0
    def needs_by_district(cls):
        """
            Count need lines per district and status (top 5 districts)
            - for all open Events
        """

        T = current.T
        db = current.db
        s3db = current.s3db

        table = s3db.req_need_line
        ntable = s3db.req_need
        etable = s3db.event_event
        ltable = s3db.event_event_need

        status = table.status
        number = table.id.count()
        location = ntable.location_id

        base_query = (etable.closed == False) & \
                     (etable.id == ltable.event_id) & \
                     (ltable.need_id == ntable.id) & \
                     (ntable.id == table.need_id) & \
                     (table.deleted == False)

        # Get the top-5 locations by number of need lines
        query = base_query & (location != None)
        rows = db(query).select(
            location,
            number,
            groupby=location,
            orderby=~(number),
            limitby=(0, 5),
        )
        locations = [row[location] for row in rows]

        data = []
        if locations:
            # Get labels for locations
            location_represent = S3Represent(lookup="gis_location",
                                             fields=["L2"])
            location_labels = location_represent.bulk(locations)

            # Count need lines per status and location
            query = base_query & (location.belongs(locations))
            rows = db(query).select(
                location,
                status,
                number,
                groupby=(status, location),
            )

            # Group results as {status: {location: number}}
            per_status = {}
            for row in rows:
                row_status = row[status]
                if row_status in per_status:
                    per_status[row_status][row[location]] = row[number]
                else:
                    per_status[row_status] = {row[location]: row[number]}

            # Build data structure for chart renderer
            # - every status gives a series
            # - every district gives a series entry
            for code, label, color in cls.REQ_STATUS:
                series = {
                    "key": s3_str(T(label)),
                    "color": color,
                    "filterKey": code,
                }
                values = []
                per_location = per_status.get(code)
                for location_id in locations:
                    if per_location:
                        value = per_location.get(location_id)
                    else:
                        value = None
                    location_label = location_labels.get(location_id)
                    item = {
                        "label": location_label,
                        "value": value if value else 0,
                        "filterKey": location_label,
                    }
                    values.append(item)
                series["values"] = values
                data.append(series)

        return data
Exemple #47
0
    def get_family_members(self, person, include_ids=False):
        """
            Get infos for all family members of person

            @param person: the person (Row)
            @param include_ids: include the person record IDs

            @returns: array with family member infos, format:
                            [{i: the person record ID (if requested)
                              l: pe_label,
                              n: fullname,
                              d: dob_formatted,
                              p: picture_URL,
                              r: {
                                event_code: {
                                    m: message,
                                    e: earliest_date_ISO
                                }
                              }, ...
                             ]
        """

        db = current.db
        s3db = current.s3db

        ptable = s3db.pr_person
        itable = s3db.pr_image
        gtable = s3db.pr_group
        mtable = s3db.pr_group_membership
        ctable = s3db.dvr_case
        stable = s3db.dvr_case_status

        # Get all case groups this person belongs to
        person_id = person.id
        query = ((mtable.person_id == person_id) & \
                 (mtable.deleted != True) & \
                 (gtable.id == mtable.group_id) & \
                 (gtable.group_type == 7))
        rows = db(query).select(gtable.id)
        group_ids = set(row.id for row in rows)

        members = {}

        if group_ids:
            join = [ptable.on(ptable.id == mtable.person_id),
                    ctable.on((ctable.person_id == ptable.id) & \
                              (ctable.archived == False) & \
                              (ctable.deleted == False)),
                    ]

            left = [stable.on(stable.id == ctable.status_id),
                    itable.on((itable.pe_id == ptable.pe_id) & \
                              (itable.profile == True) & \
                              (itable.deleted == False)),
                    ]

            query = (mtable.group_id.belongs(group_ids)) & \
                    (mtable.deleted != True) & \
                    (stable.is_closed != True)
            rows = db(query).select(ptable.id,
                                    ptable.pe_label,
                                    ptable.first_name,
                                    ptable.last_name,
                                    ptable.date_of_birth,
                                    itable.image,
                                    join = join,
                                    left = left,
                                    )

            for row in rows:
                member_id = row.pr_person.id
                if member_id not in members:
                    members[member_id] = row

        output = []

        if members:

            # All event types and blocking rules
            event_types = self.get_event_types()
            intervals = self.get_interval_rules(set(members.keys()))

            for member_id, data in members.items():

                member = data.pr_person
                picture = data.pr_image

                # Person data
                data = {"l": member.pe_label,
                        "n": s3_fullname(member),
                        "d": S3DateTime.date_represent(member.date_of_birth),
                        }

                # Record ID?
                if include_ids:
                    data["id"] = member_id

                # Profile picture URL
                if picture.image:
                    data["p"] = URL(c = "default",
                                    f = "download",
                                    args = picture.image,
                                    )

                # Blocking rules
                event_rules = intervals.get(member_id)
                if event_rules:
                    rules = {}
                    for event_type_id, rule in event_rules.items():
                        code = event_types.get(event_type_id).code
                        rules[code] = (s3_str(rule[0]),
                                       "%sZ" % s3_encode_iso_datetime(rule[1]),
                                       )
                    data["r"] = rules

                # Add info to output
                output.append(data)

        return output
Exemple #48
0
                                      itable.web)

            if record["scope"] != "Private" and len(rows_):
                # Google Cloud Messaging
                stable = s3db.pr_subscription
                ctable = s3db.pr_contact
    
                query = (stable.pe_id == ctable.pe_id) & \
                        (ctable.contact_method == "GCM") & \
                        (ctable.value != None) & \
                        (ctable.deleted != True) & \
                        (stable.deleted != True) & \
                        (stable.method.like("%GCM%"))
                rows = db(query).select(ctable.value)
                if len(rows):
                    registration_ids = [s3_str(row.value) for row in rows]
                    for row_ in rows_:
                        title = "[%s] %s %s" % (row_.cap_info.sender_name,
                                                itable.event_type_id.represent(row_.cap_info.event_type_id),
                                                itable.priority.represent(row_.cap_info.priority),
                                                )
                        async_task("cap_gcm", args=[title,
                                                    "%s/%s" % (s3_str(row_.cap_info.web), "profile"),
                                                    s3_str(row_.cap_info.headline),
                                                    json.dumps(registration_ids),
                                                    ])
                # Twitter Post
                if settings.get_cap_post_to_twitter():
                    try:
                        import tweepy
                    except ImportError:
Exemple #49
0
    def get_interval_rules(self, person_ids):
        """
            Get interval (blocking) rules for persons

            @param person_ids: list|tuple|set of person record IDs
            @return: rules dict, format:
                        {person_id:
                            {event_type_id: (message, earliest_datetime),
                             ...
                             },
                         ...
                         }
        """

        T = current.T

        db = current.db
        s3db = current.s3db

        now = current.request.utcnow
        day_start = now.replace(hour=0,
                                minute=0,
                                second=0,
                                microsecond=0,
                                )
        next_day = day_start + datetime.timedelta(days=1)

        output = {}

        table = s3db.dvr_case_event
        event_type_id = table.type_id
        person_id = table.person_id

        # Get event types to check
        event_types = self.get_event_types()

        # Check impermissible combinations
        etable = s3db.dvr_case_event_exclusion
        query = (table.person_id.belongs(person_ids)) & \
                (table.date >= day_start) & \
                (table.deleted == False) & \
                (etable.excluded_by_id == table.type_id) & \
                (etable.deleted == False)

        rows = db(query).select(table.person_id,
                                etable.type_id,
                                etable.excluded_by_id,
                                )
        collisions = {}
        for row in rows:
            event = row.dvr_case_event
            exclusion = row.dvr_case_event_exclusion

            pid = event.person_id
            if pid in collisions:
                excluded = collisions[pid]
            else:
                excluded = collisions[pid] = {}

            tid = exclusion.type_id
            if tid in excluded:
                excluded[tid].append(exclusion.excluded_by_id)
            else:
                excluded[tid] = [exclusion.excluded_by_id]

        for pid, excluded in collisions.items():

            if pid not in output:
                rules = output[pid] = {}
            else:
                rules = output[pid]

            for tid, excluded_by_ids in excluded.items():

                event_type = event_types.get(tid)
                if not event_type:
                    continue

                excluded_by_names = []
                seen = set()
                for excluded_by_id in excluded_by_ids:
                    if excluded_by_id in seen:
                        continue
                    else:
                        seen.add(excluded_by_id)
                    excluded_by_type = event_types.get(excluded_by_id)
                    if not excluded_by_type:
                        continue
                    excluded_by_names.append(s3_str(T(excluded_by_type.name)))

                if excluded_by_names:
                    msg = T("%(event)s already registered today, not combinable") % \
                            {"event": ", ".join(excluded_by_names)
                             }
                    rules[tid] = (msg, next_day)

        # Helper function to build event type sub-query
        def type_query(items):
            if len(items) == 1:
                return (event_type_id == items[0])
            elif items:
                return (event_type_id.belongs(set(items)))
            else:
                return None

        # Check maximum occurences per day
        check = [tid for tid, row in event_types.items()
                 if row.max_per_day and tid != "_default"
                 ]
        q = type_query(check)
        if q is not None:

            # Get number of events per type and person today
            cnt = table.id.count()
            query = (table.person_id.belongs(person_ids)) & q & \
                    (table.date >= day_start) & \
                    (table.deleted != True)
            rows = db(query).select(person_id,
                                    event_type_id,
                                    cnt,
                                    groupby = (person_id, event_type_id),
                                    )

            # Check limit
            for row in rows:

                number = row[cnt]

                pid = row[person_id]
                if pid not in output:
                    rules = output[pid] = {}
                else:
                    rules = output[pid]

                tid = row[event_type_id]
                if tid in rules:
                    continue

                event_type = event_types[tid]
                limit = event_type.max_per_day

                if number >= limit:
                    if number > 1:
                        msg = T("%(event)s already registered %(number)s times today") % \
                                {"event": T(event_type.name),
                                 "number": number,
                                 }
                    else:
                        msg = T("%(event)s already registered today") % \
                                {"event": T(event_type.name),
                                 }
                    rules[tid] = (msg, next_day)

        # Check minimum intervals
        check = [tid for tid, row in event_types.items()
                 if row.min_interval and tid != "_default"
                 ]
        q = type_query(check)
        if q is not None:

            # Get the last events for these types per person
            query = (table.person_id.belongs(person_ids)) & q & \
                    (table.deleted != True)
            timestamp = table.date.max()
            rows = db(query).select(person_id,
                                    event_type_id,
                                    timestamp,
                                    groupby = (person_id, event_type_id),
                                    )

            # Check intervals
            represent = table.date.represent
            for row in rows:

                latest = row[timestamp]

                pid = row[person_id]
                if pid not in output:
                    rules = output[pid] = {}
                else:
                    rules = output[pid]

                tid = row[event_type_id]
                if tid in rules:
                    continue

                event_type = event_types[tid]
                interval = event_type.min_interval

                if latest:
                    earliest = latest + datetime.timedelta(hours=interval)
                    if earliest > now:
                        msg = T("%(event)s already registered on %(timestamp)s") % \
                                    {"event": T(event_type.name),
                                     "timestamp": represent(latest),
                                     }
                        rules[tid] = (msg, earliest)

        return output
Exemple #50
0
    def xls(self, r, **attr):
        """
            Export the performance indicators as XLS data sheet

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

        T = current.T
        s3db = current.s3db

        try:
            import xlwt
        except ImportError:
            raise HTTP(503, body="XLWT not installed")

        title = s3_str(T("Performance Indicators"))
        write = self.write

        # Create workbook and sheet
        book = xlwt.Workbook(encoding="utf-8")
        sheet = book.add_sheet(title)

        # Get the statistics
        resource = self.resource
        table = resource.table
        indicators = self.indicators(resource)

        # Title and Report Dates (from filter)
        write(sheet, 0, 0, title, style="header")
        dates = []
        get_vars = r.get_vars
        field = table.date
        for fvar in ("~.date__ge", "~.date__le"):
            dtstr = get_vars.get(fvar)
            if dtstr:
                try:
                    dt = s3_decode_iso_datetime(dtstr).date()
                except (ValueError, AttributeError):
                    dt = None
                else:
                    dates.append(field.represent(dt))
            else:
                dates.append("...")
        if dates:
            write(sheet, 1, 0, " -- ".join(dates))

        # Basic performance indicators
        rowindex = 3
        # Total number of consultations
        write(sheet, rowindex, 0, T("Total Number of Consultations"))
        write(sheet, rowindex, 1, indicators.get("total_responses", ""))

        rowindex += 1
        write(sheet, rowindex, 0, T("Total Number of Clients"))
        write(sheet, rowindex, 1, indicators.get("total_clients", ""))

        rowindex += 1
        write(sheet, rowindex, 0, T("Average Duration of Consultations (minutes)"))
        avg_hours_per_response = indicators.get("avg_hours_per_response")
        if avg_hours_per_response:
            avg_minutes_per_response = int(round(avg_hours_per_response * 60))
        else:
            avg_minutes_per_response = ""
        write(sheet, rowindex, 1, avg_minutes_per_response)

        rowindex += 1
        write(sheet, rowindex, 0, T("Average Number of Consultations per Client"))
        write(sheet, rowindex, 1, indicators.get("avg_responses_per_client", ""))

        # Distribution
        rowindex = 8
        write(sheet, rowindex, 0, T("Distribution of Clients"))

        write(sheet, rowindex, 1, T("Single"))
        write(sheet, rowindex, 2, indicators.get("singles", ""))

        rowindex += 1
        write(sheet, rowindex, 1, T("Family"))
        write(sheet, rowindex, 2, indicators.get("families", ""))

        rowindex += 1
        write(sheet, rowindex, 1, T("Group Counseling"))

        rowindex += 1
        write(sheet, rowindex, 1, T("Individual Counseling"))
        write(sheet, rowindex, 2, indicators.get("total_responses", ""))

        # Top-5's
        rowindex = 13
        write(sheet, rowindex, 0, T("Top 5 Countries of Origin"))
        top_5_nationalities = indicators.get("top_5_nationalities")
        if top_5_nationalities:
            dtable = s3db.pr_person_details
            field = dtable.nationality
            for rank, nationality in enumerate(top_5_nationalities):
                write(sheet, rowindex, 1, "%s - %s" % (rank + 1, field.represent(nationality)))
                rowindex += 1

        rowindex += 1
        write(sheet, rowindex, 0, T("Top 5 Counseling Reasons"))
        top_5_needs = indicators.get("top_5_needs")
        if top_5_needs:
            ttable = s3db.dvr_response_theme
            field = ttable.need_id
            for rank, need in enumerate(top_5_needs):
                write(sheet, rowindex, 1, "%s - %s" % (rank + 1, field.represent(need)))
                rowindex += 1

        # Output
        output = StringIO()
        book.save(output)
        output.seek(0)

        # Response headers
        from gluon.contenttype import contenttype
        disposition = "attachment; filename=\"%s\"" % "indicators.xls"
        response = current.response
        response.headers["Content-Type"] = contenttype(".xls")
        response.headers["Content-disposition"] = disposition

        from gluon.streamer import DEFAULT_CHUNK_SIZE
        return response.stream(output,
                               chunk_size=DEFAULT_CHUNK_SIZE,
                               request=r,
                               )
Exemple #51
0
    def draw(self):
        """
            Draw the card (one side)

            Instance attributes (NB draw-function should not modify them):
            - self.canv...............the canvas (provides the drawing methods)
            - self.resource...........the resource
            - self.item...............the data item (dict)
            - self.labels.............the field labels (dict)
            - self.backside...........this instance should render the backside
                                      of a card
            - self.multiple...........there are multiple cards per page
            - self.width..............the width of the card (in points)
            - self.height.............the height of the card (in points)

            NB Canvas coordinates are relative to the lower left corner of the
               card's frame, drawing must not overshoot self.width/self.height
        """

        T = current.T

        c = self.canv
        w = self.width
        #h = self.height
        common = self.common

        orange = HexColor(0xEE4229)

        item = self.item
        raw = item["_row"]

        # Get the org logo
        logos = common.get("logos")
        if logos:
            root_org = raw["org_organisation.root_organisation"]
            logo = logos.get(root_org)
        else:
            logo = None

        if not self.backside:

            draw_field = self.draw_field
            draw_value = self.draw_value
            draw_label = self.draw_label

            # Horizontal alignments
            LEFT = w / 4 - 5
            CENTER = w / 2 - 5
            RIGHT = w * 3 / 4 - 5

            # Vertical alignments
            TOP = 200
            LOWER = [76, 58, 40]
            BOTTOM = 16

            # Org Logo
            if logo:
                self.draw_image(logo, LEFT, TOP, width=60, height=60, valign="middle", halign="center")

            # Get the profile picture
            pictures = common.get("pictures")
            if pictures:
                picture = pictures.get(raw["pr_person.pe_id"])
                if picture:
                    self.draw_image(picture, RIGHT, TOP, width=60, height=60, valign="middle", halign="center")

            # Center fields in reverse order so that vertical positions
            # can be adjusted for very long and hence wrapping strings
            y = 98

            # Organisation/Branch
            org_name = s3_str(item.get("org_organisation.name"))
            aH = draw_value(CENTER, y, org_name, height=16, size=8)
            draw_label(CENTER, y, "hrm_human_resource.organisation_id")

            # Job Title
            y += aH + 12
            job_title = s3_str(item.get("hrm_human_resource.job_title_id"))
            aH = draw_value(CENTER, y, job_title, height=16, size=8)
            draw_label(CENTER, y, "hrm_human_resource.job_title_id")

            # Name
            y += aH + 12
            name = s3_format_fullname(fname = raw["pr_person.first_name"],
                                      mname = raw["pr_person.middle_name"],
                                      lname = raw["pr_person.last_name"],
                                      truncate = False,
                                      )
            draw_value(CENTER, y, name, height=24, size=10)
            draw_label(CENTER, y, None, T("Name"))

            # IDs
            draw_field(LEFT, LOWER[0], "pr_national_id_identity.value")
            draw_label(LEFT, LOWER[0], None, T("ID"))
            # TODO only volunteers can have this? (Adjust label by HR type?)
            draw_field(RIGHT, LOWER[0], "hrm_human_resource.code")
            draw_label(RIGHT, LOWER[0], None, T("Volunteer ID"))

            # Medical Details
            draw_field(LEFT, LOWER[1], "pr_physical_description.blood_type")
            draw_label(LEFT, LOWER[1], None, T("Blood Type"))
            draw_field(RIGHT, LOWER[1], "pr_physical_description.allergic")
            draw_label(RIGHT, LOWER[1], None, T("Allergic"))

            # Issuing/Expirey Dates
            # TODO adjust interval per org (org_idcard)
            today = current.request.now.date()
            format_date = current.calendar.format_date
            issued_on = format_date(today)
            expires_on = format_date(today + relativedelta(months=24))

            c.setFont(BOLD, 7)
            c.drawCentredString(LEFT, LOWER[2], issued_on)
            draw_label(LEFT, LOWER[2], None, T("Issued on"))
            c.setFont(BOLD, 7)
            c.drawCentredString(RIGHT, LOWER[2], expires_on)
            draw_label(RIGHT, LOWER[2], None, T("Expires on"))

            # Barcode
            code = raw["hrm_human_resource.code"]
            if code:
                self.draw_barcode(s3_str(code), CENTER, BOTTOM, height=12, halign="center")

            # Graphics
            c.setFillColor(orange)
            c.rect(0, 0, w, 12, fill=1, stroke=0)
            c.rect(w - 12, 0, 12, 154, fill=1, stroke=0)

            # Add a utting line with multiple cards per page
            if self.multiple:
                c.setDash(1, 2)
                self.draw_outline()
        else:
            # Horizontal alignments
            CENTER = w / 2

            # Vertical alignments
            TOP = 200
            BOTTOM = 16

            # TODO Mission statement

            # TODO IFRC membership statement

            # TODO Signature and caption

            # Barcode
            code = raw["hrm_human_resource.code"]
            if code:
                self.draw_barcode(s3_str(code), CENTER, BOTTOM, height=12, halign="center")

            # Graphics
            if logo:
                self.draw_image(logo, CENTER, TOP, width=60, height=60, valign="middle", halign="center")
            c.setFillColor(orange)
            c.rect(0, 0, w, 10, fill=1, stroke=0)
Exemple #52
0
    def needs_by_district(cls):
        """
            Count need lines per district and status (top 5 districts)
            - for all open Events
        """

        T = current.T
        db = current.db
        s3db = current.s3db

        table = s3db.req_need_line
        ntable = s3db.req_need
        etable = s3db.event_event
        ltable = s3db.event_event_need

        status = table.status
        number = table.id.count()
        location = ntable.location_id

        base_query = (etable.closed == False) & \
                     (etable.id == ltable.event_id) & \
                     (ltable.need_id == ntable.id) & \
                     (ntable.id == table.need_id) & \
                     (table.deleted == False)

        # Get the top-5 locations by number of need lines
        query = base_query & (location != None)
        rows = db(query).select(location,
                                number,
                                groupby = location,
                                orderby = ~(number),
                                limitby = (0, 5),
                                )
        locations = [row[location] for row in rows]

        data = []
        if locations:
            # Get labels for locations
            location_represent = S3Represent(lookup="gis_location", fields=["L2"])
            location_labels = location_represent.bulk(locations)

            # Count need lines per status and location
            query = base_query & (location.belongs(locations))
            rows = db(query).select(location,
                                    status,
                                    number,
                                    groupby = (status, location),
                                    )

            # Group results as {status: {location: number}}
            per_status = {}
            for row in rows:
                row_status = row[status]
                if row_status in per_status:
                    per_status[row_status][row[location]] = row[number]
                else:
                    per_status[row_status] = {row[location]: row[number]}

            # Build data structure for chart renderer
            # - every status gives a series
            # - every district gives a series entry
            for code, label, color in cls.REQ_STATUS:
                series = {"key": s3_str(T(label)),
                          "color": color,
                          "filterKey": code,
                          }
                values = []
                per_location = per_status.get(code)
                for location_id in locations:
                    if per_location:
                        value = per_location.get(location_id)
                    else:
                        value = None
                    location_label = location_labels.get(location_id)
                    item = {"label": location_label,
                            "value": value if value else 0,
                            "filterKey": location_label,
                            }
                    values.append(item)
                series["values"] = values
                data.append(series)

        return data
Exemple #53
0
    def get_interval_rules(self, person_ids):
        """
            Get interval (blocking) rules for persons

            @param person_ids: list|tuple|set of person record IDs
            @return: rules dict, format:
                        {person_id:
                            {event_type_id: (message, earliest_datetime),
                             ...
                             },
                         ...
                         }
        """

        T = current.T

        db = current.db
        s3db = current.s3db

        now = current.request.utcnow
        day_start = now.replace(
            hour=0,
            minute=0,
            second=0,
            microsecond=0,
        )
        next_day = day_start + datetime.timedelta(days=1)

        output = {}

        table = s3db.dvr_case_event
        event_type_id = table.type_id
        person_id = table.person_id

        # Get event types to check
        event_types = self.get_event_types()

        # Check impermissible combinations
        etable = s3db.dvr_case_event_exclusion
        query = (table.person_id.belongs(person_ids)) & \
                (table.date >= day_start) & \
                (table.deleted == False) & \
                (etable.excluded_by_id == table.type_id) & \
                (etable.deleted == False)

        rows = db(query).select(
            table.person_id,
            etable.type_id,
            etable.excluded_by_id,
        )
        collisions = {}
        for row in rows:
            event = row.dvr_case_event
            exclusion = row.dvr_case_event_exclusion

            pid = event.person_id
            if pid in collisions:
                excluded = collisions[pid]
            else:
                excluded = collisions[pid] = {}

            tid = exclusion.type_id
            if tid in excluded:
                excluded[tid].append(exclusion.excluded_by_id)
            else:
                excluded[tid] = [exclusion.excluded_by_id]

        for pid, excluded in collisions.items():

            if pid not in output:
                rules = output[pid] = {}
            else:
                rules = output[pid]

            for tid, excluded_by_ids in excluded.items():

                event_type = event_types.get(tid)
                if not event_type:
                    continue

                excluded_by_names = []
                seen = set()
                for excluded_by_id in excluded_by_ids:
                    if excluded_by_id in seen:
                        continue
                    else:
                        seen.add(excluded_by_id)
                    excluded_by_type = event_types.get(excluded_by_id)
                    if not excluded_by_type:
                        continue
                    excluded_by_names.append(s3_str(T(excluded_by_type.name)))

                if excluded_by_names:
                    msg = T("%(event)s already registered today, not combinable") % \
                            {"event": ", ".join(excluded_by_names)
                             }
                    rules[tid] = (msg, next_day)

        # Helper function to build event type sub-query
        def type_query(items):
            if len(items) == 1:
                return (event_type_id == items[0])
            elif items:
                return (event_type_id.belongs(set(items)))
            else:
                return None

        # Check maximum occurences per day
        check = [
            tid for tid, row in event_types.items()
            if row.max_per_day and tid != "_default"
        ]
        q = type_query(check)
        if q is not None:

            # Get number of events per type and person today
            cnt = table.id.count()
            query = (table.person_id.belongs(person_ids)) & q & \
                    (table.date >= day_start) & \
                    (table.deleted != True)
            rows = db(query).select(
                person_id,
                event_type_id,
                cnt,
                groupby=(person_id, event_type_id),
            )

            # Check limit
            for row in rows:

                number = row[cnt]

                pid = row[person_id]
                if pid not in output:
                    rules = output[pid] = {}
                else:
                    rules = output[pid]

                tid = row[event_type_id]
                if tid in rules:
                    continue

                event_type = event_types[tid]
                limit = event_type.max_per_day

                if number >= limit:
                    if number > 1:
                        msg = T("%(event)s already registered %(number)s times today") % \
                                {"event": T(event_type.name),
                                 "number": number,
                                 }
                    else:
                        msg = T("%(event)s already registered today") % \
                                {"event": T(event_type.name),
                                 }
                    rules[tid] = (msg, next_day)

        # Check minimum intervals
        check = [
            tid for tid, row in event_types.items()
            if row.min_interval and tid != "_default"
        ]
        q = type_query(check)
        if q is not None:

            # Get the last events for these types per person
            query = (table.person_id.belongs(person_ids)) & q & \
                    (table.deleted != True)
            timestamp = table.date.max()
            rows = db(query).select(
                person_id,
                event_type_id,
                timestamp,
                groupby=(person_id, event_type_id),
            )

            # Check intervals
            represent = table.date.represent
            for row in rows:

                latest = row[timestamp]

                pid = row[person_id]
                if pid not in output:
                    rules = output[pid] = {}
                else:
                    rules = output[pid]

                tid = row[event_type_id]
                if tid in rules:
                    continue

                event_type = event_types[tid]
                interval = event_type.min_interval

                if latest:
                    earliest = latest + datetime.timedelta(hours=interval)
                    if earliest > now:
                        msg = T("%(event)s already registered on %(timestamp)s") % \
                                    {"event": T(event_type.name),
                                     "timestamp": represent(latest),
                                     }
                        rules[tid] = (msg, earliest)

        return output
Exemple #54
0
    def get_family_members(self, person, include_ids=False):
        """
            Get infos for all family members of person

            @param person: the person (Row)
            @param include_ids: include the person record IDs

            @returns: array with family member infos, format:
                            [{i: the person record ID (if requested)
                              l: pe_label,
                              n: fullname,
                              d: dob_formatted,
                              p: picture_URL,
                              r: {
                                event_code: {
                                    m: message,
                                    e: earliest_date_ISO
                                }
                              }, ...
                             ]
        """

        db = current.db
        s3db = current.s3db

        ptable = s3db.pr_person
        itable = s3db.pr_image
        gtable = s3db.pr_group
        mtable = s3db.pr_group_membership
        ctable = s3db.dvr_case
        stable = s3db.dvr_case_status

        # Get all case groups this person belongs to
        person_id = person.id
        query = ((mtable.person_id == person_id) & \
                 (mtable.deleted != True) & \
                 (gtable.id == mtable.group_id) & \
                 (gtable.group_type == 7))
        rows = db(query).select(gtable.id)
        group_ids = set(row.id for row in rows)

        members = {}

        if group_ids:
            join = [ptable.on(ptable.id == mtable.person_id),
                    ctable.on((ctable.person_id == ptable.id) & \
                              (ctable.archived == False) & \
                              (ctable.deleted == False)),
                    ]

            left = [stable.on(stable.id == ctable.status_id),
                    itable.on((itable.pe_id == ptable.pe_id) & \
                              (itable.profile == True) & \
                              (itable.deleted == False)),
                    ]

            query = (mtable.group_id.belongs(group_ids)) & \
                    (mtable.deleted != True) & \
                    (stable.is_closed != True)
            rows = db(query).select(
                ptable.id,
                ptable.pe_label,
                ptable.first_name,
                ptable.last_name,
                ptable.date_of_birth,
                itable.image,
                join=join,
                left=left,
            )

            for row in rows:
                member_id = row.pr_person.id
                if member_id not in members:
                    members[member_id] = row

        output = []

        if members:

            # All event types and blocking rules
            event_types = self.get_event_types()
            intervals = self.get_interval_rules(set(members.keys()))

            for member_id, data in members.items():

                member = data.pr_person
                picture = data.pr_image

                # Person data
                data = {
                    "l": member.pe_label,
                    "n": s3_fullname(member),
                    "d": S3DateTime.date_represent(member.date_of_birth),
                }

                # Record ID?
                if include_ids:
                    data["id"] = member_id

                # Profile picture URL
                if picture.image:
                    data["p"] = URL(
                        c="default",
                        f="download",
                        args=picture.image,
                    )

                # Blocking rules
                event_rules = intervals.get(member_id)
                if event_rules:
                    rules = {}
                    for event_type_id, rule in event_rules.items():
                        code = event_types.get(event_type_id).code
                        rules[code] = (
                            s3_str(rule[0]),
                            "%sZ" % s3_encode_iso_datetime(rule[1]),
                        )
                    data["r"] = rules

                # Add info to output
                output.append(data)

        return output
Exemple #55
0
    def registration_ajax(self, r, **attr):
        """
            Ajax response method, expects a JSON input like:

                {l: the PE label (from the input field),
                 c: boolean to indicate whether to just check
                    the PE label or to register payments
                 t: the event type code
                 x: [array of PE labels,
                     only when registering for multiple persons
                     ]
                 }

            @param r: the S3Request instance
            @param attr: controller parameters
            @return: JSON response, structure:

                    {l: the actual PE label (to update the input field),
                     p: the person details,
                     d: the family details,
                     f: [{n: the flag name
                          i: the flag instructions
                          },
                         ...],
                     b: profile picture URL,
                     i: {<event_code>: [<msg>, <blocked_until_datetime>]},

                     x: [{l: the family member PE label,
                          n: the family member full name,
                          d: the family member date of birth,
                          p: the family member profile picture URL,
                          r: {<event_code>: [<msg>, <blocked_until_datetime>]},
                          },
                         ],

                     s: whether the action is permitted or not

                     e: form error (for label field)

                     a: error message
                     w: warning message
                     m: success message
                     }
        """

        T = current.T
        s3db = current.s3db

        # Load JSON data from request body
        s = r.body
        s.seek(0)
        try:
            data = json.load(s)
        except (ValueError, TypeError):
            r.error(400, current.ERROR.BAD_REQUEST)

        # Initialize processing variables
        output = {}

        error = None

        alert = None
        message = None
        warning = None

        permitted = False
        flags = []

        # Identify the person
        pe_label = data.get("l")
        person = self.get_person(pe_label)

        if person is None:
            error = s3_str(T("No person found with this ID number"))

        else:
            # Get flag info
            flag_info = s3db.dvr_get_flag_instructions(
                person.id,
                action="id-check",
            )
            permitted = flag_info["permitted"]

            check = data.get("c")
            if check:

                output["l"] = person.pe_label

                # Person details
                person_details = self.person_details(person)
                output["p"] = s3_str(person_details)

                # Profile picture
                profile_picture = self.profile_picture(person)
                output["b"] = profile_picture

                # Household Size
                details = s3db.dvr_get_household_size(
                    person.id,
                    dob=person.date_of_birth,
                )
                if details:
                    output["d"] = {"d": details}

                # Family Members
                family_members = self.get_family_members(person)
                if family_members:
                    output["x"] = family_members

                # Flag Info
                info = flag_info["info"]
                for flagname, instructions in info:
                    flags.append({
                        "n": s3_str(T(flagname)),
                        "i": s3_str(T(instructions)),
                    })

                # Blocking periods for events
                event_types = self.get_event_types()
                blocked = self.get_blocked_events(person.id)
                intervals = {}
                for type_id, info in blocked.items():
                    event_type = event_types.get(type_id)
                    if not event_type:
                        continue
                    code = event_type.code
                    msg, dt = info
                    intervals[code] = (
                        s3_str(msg),
                        "%sZ" % s3_encode_iso_datetime(dt),
                    )
                output["i"] = intervals
            else:
                # Check event code and permission
                type_id = None
                event_code = data.get("t")
                if not event_code:
                    alert = T("No event type specified")
                elif not permitted:
                    alert = T("Event registration not permitted")
                else:
                    event_type = self.get_event_type(event_code)
                    if not event_type:
                        alert = T("Invalid event type: %s") % event_code
                    else:
                        type_id = event_type.id

                if type_id:

                    family_labels = data.get("x")
                    if family_labels:
                        # Register event for multiple family members

                        # Get family members and interval rules
                        family_members = self.get_family_members(
                            person,
                            include_ids=True,
                        )
                        family_members = dict(
                            (m["l"], m) for m in family_members)

                        registered = 0
                        alerts = []
                        for label in family_labels:

                            # Get the family member person_id
                            member = family_members.get(label)
                            if not member:
                                continue
                            member_id = member.get("id")

                            # Check interval rules
                            rules = member.get("r")
                            if rules and event_code in rules:
                                # Event type is currently blocked for this
                                # family member
                                alerts.append(": ".join((
                                    s3_str(member["n"]),
                                    s3_str(rules[event_code][0]),
                                )))
                            else:
                                # Ok - register the event
                                self.register_event(member_id, type_id)
                                registered += 1

                        if alerts:
                            alert = ", ".join(alerts)
                        if registered:
                            message = T("%(number)s registrations successful") % \
                                       {"number": registered}
                        elif not alerts:
                            alert = T("Could not register event")

                    else:

                        # Check whether event type is blocked for this person
                        person_id = person.id
                        blocked = self.get_blocked_events(
                            person_id,
                            type_id=type_id,
                        )
                        if type_id in blocked:
                            # Event type is currently blocked for this person
                            alert = blocked[type_id][0]
                        else:
                            # Ok - register the event
                            success = self.register_event(person.id, type_id)
                            if success:
                                message = T("Event registered")
                            else:
                                alert = T("Could not register event")

        # Add messages to output
        if alert:
            output["a"] = s3_str(alert)
        if error:
            output["e"] = s3_str(error)
        if message:
            output["m"] = s3_str(message)
        if warning:
            output["w"] = s3_str(warning)

        # Add flag info to output
        output["s"] = permitted
        output["f"] = flags

        current.response.headers["Content-Type"] = "application/json"
        return json.dumps(output)
Exemple #56
0
    def draw(self):
        """
            Draw the card (one side)

            Instance attributes (NB draw-function should not modify them):
            - self.canv...............the canvas (provides the drawing methods)
            - self.resource...........the resource
            - self.item...............the data item (dict)
            - self.labels.............the field labels (dict)
            - self.backside...........this instance should render the backside
                                      of a card
            - self.multiple...........there are multiple cards per page
            - self.width..............the width of the card (in points)
            - self.height.............the height of the card (in points)

            NB Canvas coordinates are relative to the lower left corner of the
               card's frame, drawing must not overshoot self.width/self.height
        """

        T = current.T

        c = self.canv
        w = self.width
        #h = self.height
        common = self.common

        blue = HexColor(0x27548F)

        item = self.item
        raw = item["_row"]

        root_org = raw["org_organisation.root_organisation"]

        # Get the localized root org name
        org_names = common.get("root_org_names")
        if org_names:
            root_org_name = org_names.get(root_org)

        #draw_field = self.draw_field
        draw_value = self.draw_value
        draw_label = self.draw_label

        code = raw["pr_person.pe_label"]

        if not self.backside:

            # Horizontal alignments
            LEFT = w / 4 - 5
            CENTER = w / 2 - 5
            RIGHT = w * 3 / 4 - 5

            # Vertical alignments
            TOP = 200
            #LOWER = [76, 58, 40]
            BOTTOM = 16

            # Organisation name
            if root_org_name:
                draw_value(LEFT, TOP, root_org_name,
                           width = 55,
                           height = 55,
                           size = 10,
                           valign = "middle",
                           )

            # Get the profile picture
            pictures = common.get("pictures")
            if pictures:
                picture = pictures.get(raw["pr_person.pe_id"])
                if picture:
                    self.draw_image(picture, RIGHT, TOP,
                                    width = 60,
                                    height = 55,
                                    valign = "middle",
                                    halign = "center",
                                    )

            # Center fields in reverse order so that vertical positions
            # can be adjusted for very long and hence wrapping strings
            y = 98

            # ID
            ah = draw_value(CENTER, y, code, height=24, size=8)
            draw_label(CENTER, y, None, T("ID Number"))

            # Name
            y += ah + 12
            name = s3_format_fullname(fname = raw["pr_person.first_name"],
                                      mname = raw["pr_person.middle_name"],
                                      lname = raw["pr_person.last_name"],
                                      truncate = False,
                                      )
            draw_value(CENTER, y, name, height=24, size=10)
            draw_label(CENTER, y, None, T("Name"))

            # Barcode
            if code:
                self.draw_barcode(s3_str(code), CENTER, BOTTOM,
                                  height = 12,
                                  halign = "center",
                                  maxwidth = w - 15,
                                  )

            # Graphics
            c.setFillColor(blue)
            c.rect(0, 0, w, 12, fill=1, stroke=0)
            c.rect(w - 12, 0, 12, 154, fill=1, stroke=0)

            # Add a utting line with multiple cards per page
            if self.multiple:
                c.setDash(1, 2)
                self.draw_outline()
        else:
            # Horizontal alignments
            CENTER = w / 2

            # Vertical alignments
            TOP = 200
            MIDDLE = 85
            BOTTOM = 16

            # QR Code
            if code:
                identity = "%s//%s:%s:%s" % (code,
                                             raw["pr_person.first_name"] or "",
                                             raw["pr_person.middle_name"] or "",
                                             raw["pr_person.last_name"] or "",
                                             )
                self.draw_qrcode(identity, CENTER, MIDDLE,
                                 size=60, halign="center", valign="center")
            # Barcode
            if code:
                self.draw_barcode(s3_str(code), CENTER, BOTTOM,
                                  height = 12,
                                  halign = "center",
                                  maxwidth = w - 15
                                  )

            # Graphics
            c.setFillColor(blue)
            c.rect(0, 0, w, 10, fill=1, stroke=0)
Exemple #57
0
    def get_html_email_content(row):
        """
            prepare the content for html email
        """

        subject = \
        T("%(Scope)s %(Status)s Alert: %(Headline)s (ID: %(Identifier)s)") % \
            dict(Scope = s3_str(row["cap_alert.scope"]),
                 Status = s3_str(row["cap_alert.status"]),
                 Headline = s3_str(row["cap_info.headline"]),
                 Identifier = s3_str(row["cap_alert.identifier"]))
        body1 = \
T("""%(Priority)s priority %(MessageType)s 
message in effect for %(AreaDescription)s""") % dict(\
                    Priority = s3_str(row["cap_info.priority"]),
                    MessageType = s3_str(row["cap_alert.msg_type"]),
                    AreaDescription = s3_str(row["cap_area.name"]))
        body2 = \
        T("This %(Severity)s %(EventType)s is %(Urgency)s and is %(Certainty)s") %\
            dict(Severity = s3_str(row["cap_info.severity"]),
                 EventType = s3_str(row["cap_info.event_type_id"]),
                 Urgency = s3_str(row["cap_info.urgency"]),
                 Certainty = s3_str(row["cap_info.certainty"]))
        body3 = \
T("""Message %(Identifier)s: %(EventType)s (%(Category)s) issued by 
%(SenderName)s sent at %(Date)s from %(Source)s""") % \
                 dict(Identifier = s3_str(row["cap_alert.identifier"]),
                      EventType = s3_str(row["cap_info.event_type_id"]),
                      Category = s3_str(row["cap_info.category"]),
                      SenderName = s3_str(row["cap_info.sender_name"]),
                      Date = s3_str(row["cap_alert.sent"]),
                      Source = s3_str(row["cap_alert.source"]))
        body4 = T("Alert Description: %(AreaDescription)s") % \
                dict(AreaDescription = s3_str(row["cap_area.name"]))
        body5 = T("Expected Response: %(ResponseType)s") % \
                dict(ResponseType = s3_str(row["cap_info.response_type"]))
        body6 = T("Instructions: %(Instruction)s") % \
                dict(Instruction=s3_str(row["cap_info.instruction"]))
        body7 = \
T("Alert is effective from %(Effective)s and expires on %(Expires)s") % \
                dict(Effective = s3_str(row["cap_info.effective"]),
                     Expires = s3_str(row["cap_info.expires"]))
        body8 = T("For more details visit %(URL)s or contact %(Contact)s") % \
                dict(URL = s3_str(row["cap_info.web"]),
                     Contact = s3_str(row["cap_info.contact"]))
        body9 = A(T("VIEW ALERT ON THE WEB"),
                    _href = URL(s3_str(row["cap_info.web"]), "/profile"))
        return TAG[""](HR(), BR(),
                       subject,
                       BR(), BR(),
                       body1,
                       BR(),
                       body2,
                       BR(), BR(),
                       body3,
                       BR(), BR(),
                       body4,
                       BR(), BR(),
                       body5,
                       BR(), BR(),
                       body6,
                       BR(), BR(),
                       body7,
                       BR(), BR(),
                       body8,
                       BR(), BR(),
                       body9,
                       BR())