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

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

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

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

        output = dict()
        tablename = self.tablename

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

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

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

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

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

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

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

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

            if owidget is None or dwidget is None:
                continue

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

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

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

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

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

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

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

        output["form"] = form

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

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

            s3db = current.s3db

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

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

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

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

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

        return output
Ejemplo n.º 2
0
    def merge(self, r, **attr):
        """
            Merge form for two records

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

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

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

        output = dict()
        tablename = self.tablename

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

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

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

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

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

        trs = []
        init_requires = self.init_requires
        index = 1
        num_fields = len(formfields)

        for f in formfields:

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

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

            if owidget is None or dwidget is None:
                continue

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

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

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

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

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

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

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

        output["form"] = form

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

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

            s3db = current.s3db

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

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

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

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

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

        return output