Ejemplo n.º 1
0
Archivo: misc.py Proyecto: cerha/pytis
def mark_products(product_id=None, mark=True):
    """Mark/unmark all products."""
    assert isinstance(mark, bool)
    assert product_id is None or isinstance(product_id, (int, tuple, list))
    row = pd.Row((('marked', pd.bval(mark)),))
    if product_id is None:
        condition = pd.EQ('marked', pd.bval(not mark))
    elif isinstance(product_id, (list, tuple)):
        condition = pd.OR(*[pd.EQ('product_id', pd.ival(x)) for x in product_id])
    else:
        condition = pd.EQ('product_id', pd.ival(product_id))
    import pytis.extensions
    return pytis.extensions.dbupdate_many('misc.Products', condition=condition, update_row=row)
Ejemplo n.º 2
0
Archivo: help.py Proyecto: cerha/pytis
class ItemsHelp(Specification):
    _ITEM_KIND = None
    public = True
    table = 'e_pytis_help_spec_items'

    def fields(self):
        return (
            Field('item_id'),
            Field('kind'),
            Field('spec_name', not_null=True, codebook='help.Help', value_column='spec_name'),
            Field('identifier', _("Identifier"), width=30, editable=Editable.NEVER),
            Field('content', _("Description"), width=80, height=15, compact=True,
                  text_format=pp.TextFormat.LCG, attachment_storage=self._attachment_storage),
            Field('label', _("Title"), width=30, virtual=True,
                  editable=pp.Editable.NEVER, computer=computer(self._label)),
            Field('removed', _("Removed"), editable=Editable.NEVER),
            Field('changed', _("Changed"), editable=Editable.NEVER,
                  computer=computer(lambda r, content: True)),
        )

    def row_style(self, row):
        return not row['changed'].value() and pp.Style(background='#ffd') or None

    def _attachment_storage(self, record):
        return pp.DbAttachmentStorage('e_pytis_help_spec_attachments', 'spec_name',
                                      record['spec_name'].value())

    def _label(self, record, spec_name, kind, identifier):
        if not kind or not identifier:
            return None
        resolver = pytis.util.resolver()
        try:
            view_spec = resolver.get(spec_name, 'view_spec')
        except pytis.util.ResolverError:
            return identifier
        kwargs = dict(unnest=True) if kind == 'action' else {}
        items = getattr(view_spec, kind + 's')(**kwargs)
        item = pytis.util.find(identifier, items, key=lambda x: x.id())
        if item:
            if kind in ('field',):
                return item.label()
            elif kind in ('action', 'binding'):
                return item.title()
            else:
                return item.name()
        else:
            return identifier

    def condition(self):
        return pd.EQ('kind', pd.sval(self._ITEM_KIND))
    columns = ('identifier', 'label', 'changed', 'removed')
    layout = ('identifier', 'label', 'content')
    profiles = pp.Profiles((pp.Profile('active', _("Active"),
                                       filter=pd.EQ('removed', pd.bval(False)),
                                       columns=('identifier', 'label', 'changed')),),
                           default='active')
Ejemplo n.º 3
0
 def _update_spec_help(self, spec_name):
     if self._done.get(spec_name):
         return
     self._done[spec_name] = True
     resolver = pytis.util.resolver()
     try:
         view_spec = resolver.get(spec_name, 'view_spec')
     except pytis.util.ResolverError as e:
         print(e)
         return
     description = view_spec.description()
     help_text = (view_spec.help() or '').strip() or None
     self._update(self._spec_help_data, dict(spec_name=spec_name),
                  description=description, help=help_text)
     data = self._spec_help_items_data
     for kind, items in (('field', view_spec.fields()),
                         ('profile', view_spec.profiles().unnest()),
                         ('binding', view_spec.bindings()),
                         ('action', view_spec.actions(unnest=True))):
         for item in items:
             self._update(data, dict(spec_name=spec_name, kind=kind,
                                     identifier=item.id()),
                          content=item.descr())
         # Items which were modified (content changed by hand) are kept with
         # the 'removed' flag set, since the texts may be reused for other
         # items in case of identifier change or other rearrangements.  It
         # will also automatically resurrect texts for items which are
         # removed temporarily (eg. commented out) which is quite common
         # during development.  Items which were not ever modified or have
         # no content may be safely deleted (they contain no hand-edited
         # data).
         conds = [pd.EQ('spec_name', pd.sval(spec_name)),
                  pd.EQ('kind', pd.sval(kind)),
                  pd.NOT(pd.ANY_OF('identifier', *[pd.sval(item.id()) for item in items])),
                  ]
         data.delete_many(pd.AND(*(conds + [pd.OR(pd.EQ('changed', pd.bval(False)),
                                                  pd.EQ('content', pd.sval(None)))])))
         data.update_many(pd.AND(*(conds + [pd.EQ('removed', pd.bval(False))])),
                          pd.Row(self._values(data, removed=True)))
Ejemplo n.º 4
0
 def _update_spec_help(self, spec_name):
     if self._done.get(spec_name):
         return
     self._done[spec_name] = True
     resolver = pytis.util.resolver()
     try:
         view_spec = resolver.get(spec_name, 'view_spec')
     except pytis.util.ResolverError as e:
         print e
         return
     description = view_spec.description()
     help_text = (view_spec.help() or '').strip() or None
     self._update(self._spec_help_data, dict(spec_name=spec_name),
                  description=description, help=help_text)
     data = self._spec_help_items_data
     for kind, items in (('field', view_spec.fields()),
                         ('profile', view_spec.profiles().unnest()),
                         ('binding', view_spec.bindings()),
                         ('action', view_spec.actions(unnest=True))):
         for item in items:
             self._update(data, dict(spec_name=spec_name, kind=kind,
                                     identifier=item.id()),
                          content=item.descr())
         # Items which were modified (content changed by hand) are kept with
         # the 'removed' flag set, since the texts may be reused for other
         # items in case of identifier change or other rearrangements.  It
         # will also automatically resurrect texts for items which are
         # removed temporarily (eg. commented out) which is quite common
         # during development.  Items which were not ever modified or have
         # no content may be safely deleted (they contain no hand-edited
         # data).
         conds = [pd.EQ('spec_name', pd.sval(spec_name)),
                  pd.EQ('kind', pd.sval(kind)),
                  pd.NOT(pd.ANY_OF('identifier', *[pd.sval(item.id()) for item in items])),
                  ]
         data.delete_many(pd.AND(*(conds + [pd.OR(pd.EQ('changed', pd.bval(False)),
                                                  pd.EQ('content', pd.sval(None)))])))
         data.update_many(pd.AND(*(conds + [pd.EQ('removed', pd.bval(False))])),
                          pd.Row(self._values(data, removed=True)))
Ejemplo n.º 5
0
class Help(Specification):
    public = True
    table = 'ev_pytis_help'
    title = _("Help")
    def fields(self):
        return (
            Field('help_id',
                  # The computer is only used for help pages (, editable=pp.Editable.NEVER, editable=pp.Editable.NEVER, editable=pp.Editable.NEVER, editable=pp.Editable.NEVER, editable=Editable.NEVERwith page_id) so
                  # we don't need to care about other kinds of help_id.  New
                  # record is always a new page.
                  computer=computer(lambda r, page_id: 'page/%d' % page_id)),
            Field('fullname', _("Fullname"), width=50, editable=Editable.NEVER),
            Field('spec_name', _("Specification Name"), width=50, editable=Editable.NEVER),
            Field('page_id', default=nextval('e_pytis_help_pages_page_id_seq')),
            Field('position'),
            Field('position_nsub'),
            Field('title', _("Title"), width=20, editable=computer(self._is_page),
                  type=_TreeOrderLTree(tree_column_id='position', subcount_column_id='position_nsub'),
                  ),
            Field('description', _("Description"), width=70, editable=computer(self._is_page),),
            Field('content', _("Content"), width=80, height=20, compact=True,
                  text_format=pp.TextFormat.LCG, attachment_storage=self._attachment_storage),
            Field('menu_help', _(u"Menu item description"), width=80, height=20, compact=True,
                  text_format=pp.TextFormat.LCG, attachment_storage=self._attachment_storage),
            Field('spec_description', _("Brief form description"), width=80, height=3, compact=True),
            Field('spec_help', _("Detailed form help"), width=80, height=20, compact=True,
                  text_format=pp.TextFormat.LCG, attachment_storage=self._attachment_storage),
            Field('parent', _("Parent item"), not_null=False,
                  codebook='help.HelpParents', value_column='page_id',
                  editable=computer(self._is_page),
                  runtime_filter=computer(self._parent_filter),
                  descr=_("Choose the directly superordinate item in menu hierarchy. Leave "
                          "empty for pages at the top level menu.")),
            Field('ord', _("Ordering"), width=8, fixed=True, type=pd.Integer, maximum=999998,
                  editable=computer(self._is_page),
                  descr=_("Enter a number denoting the order of the item in menu between "
                          "pages of the same hierarchy level.  Leave empty to put the item "
                          "automatically to bottom.")),
            Field('removed', _("Removed"), editable=Editable.NEVER),
            Field('changed', _("Changed"), editable=Editable.NEVER),
            )
    def row_style(self, row):
        return not row['changed'].value() and pp.Style(background='#ffd') or None

    def _is_page(self, record, page_id):
        return record.new() or page_id is not None

    def _parent_filter(self, page_id):
        return pd.NE('page_id', pd.ival(None))

    def _attachment_storage(self, record):
        if record['page_id'].value():
            table, ref = ('e_pytis_help_pages_attachments', 'page_id')
        elif record['spec_name'].value():
            table, ref = ('e_pytis_help_spec_attachments', 'spec_name')
        else:
            # The attachments are not allowed for some special pages, such as the menu root page.
            return None
        return pp.DbAttachmentStorage(table, ref, record[ref].value())
    
    def redirect(self, record):
        if record['page_id'].value() is not None:
            return None
        elif record['spec_name'].value() is not None:
            return 'help.SpecHelp'
        elif record['fullname'].value() is not None:
            return 'help.MenuHelp'
        else:
            return 'help.NoHelp'
    def bindings(self):
        return (
            Binding('content', _("Content"), uri=lambda r: 'help:'+r['help_id'].value()),
            Binding('fields', _("Fields"), 'help.FieldItemsHelp', 'spec_name'),
            Binding('profiles', _("Profiles"), 'help.ProfileItemsHelp', 'spec_name'),
            Binding('actions', _("Actions"), 'help.ActionItemsHelp', 'spec_name'),
            Binding('bindings', _("Side Forms"), 'help.BindingItemsHelp', 'spec_name'),
            )

    layout = ('title', 'description', 'parent', 'ord', 'content')
    cb = CodebookSpec(display='title')
    columns = ('title', 'description', 'spec_name', 'changed', 'removed')
    sorting = ('position', pd.ASCENDENT),
    profiles = pp.Profiles((pp.Profile('active', _("Active"),
                                       filter=pd.EQ('removed', pd.bval(False)),
                                       columns=('title', 'description', 'spec_name', 'removed')),),
                           default='active')
Ejemplo n.º 6
0
Archivo: misc.py Proyecto: cerha/pytis
class Products(Specification):
    public = True
    table = dbdefs.Products
    title = _("Products")
    layout = TabGroup((_("Product"),
                       ('product_id', 'product', 'count', 'price', 'marked')),
                      (_("Notes"),
                       ('since', 'notes')))
    grouping_functions = (
        ('f_date_year', _("Year"), pd.DateTime, pd.Integer()),
        ('f_date_month', _("Month"), pd.DateTime, pd.Integer()),
    )
    profiles = (
        pp.Profile('marked', _("Marked"), filter=pd.EQ('marked', pd.bval(True))),
        pp.Profile('unmarked', _("Unmarked"), filter=pd.EQ('marked', pd.bval(False))),
    )

    def _customize_fields(self, fields):
        fields.set_property('width', product_id=3, product=30, count=12, price=12, notes=50)
        fields.modify('product_id', column_width=6, fixed=True, editable=Editable.ALWAYS)
        fields.modify('product', style=lambda r: (pp.Style(overstrike=True)
                                                  if r['count'].value() == 0
                                                  else None))
        fields.modify('count', style=lambda r: (pp.Style(foreground='#f00')
                                                if r['count'].value() <= 5
                                                else None))
        fields.modify('price', type=pd.Monetary(not_null=True))
        fields.modify('since', descr=_("Date when the product was first included."),
                      default=pd.DateTime.datetime)
        fields.modify('notes', descr=_("Arbitrary internal notes about given product."),
                      height=3, text_format=pp.TextFormat.LCG)

    def prints(self):
        return (
            PrintAction('product-page', _("Product Page"), 'Products.ProductPage',
                        handler=self._print_handler),
            PrintAction('product-info', _("Product Info"), 'Products.ProductInfo'),
        )

    def _print_handler(self, row):
        """Demonstration of using PrintAction handler.

        The output document is created by merging the output of two printout
        results.

        """
        from PyPDF2 import PdfFileMerger, PdfFileReader
        merger = PdfFileMerger()
        for lang in ('cs', 'en'):
            output = io.BytesIO()
            pytis.form.printout(
                'Products', 'Products.ProductPage',
                parameters=dict([(k, row[k].export()) for k in ('product_id', 'product', 'price')],
                                language=lang),
                language=lang, output_file=output,
            )
            merger.append(PdfFileReader(io.BytesIO(output.getvalue())))
        with tempfile.NamedTemporaryFile(suffix='.pdf') as f:
            merger.write(f)
            f.flush()
            os.fsync(f)
            pytis.form.launch_file(f.name)
            time.sleep(1)

    def _content(self, record):
        par = os.path.pardir
        return pytis.util.lcg_node(
            (
                lcg.fieldset((
                    (_("Price"), record['price'].export()),
                    (_("Available since"), lcg.LocalizableDateTime(record['since'].value())),
                )),
                lcg.sec(_("Notes"), lcg.Parser().parse(record['notes'].value()), name='notes')
                if record['notes'].value() else lcg.Content(),
            ),
            title=record['product'].value(),
            resource_path=(os.path.normpath(os.path.join(__file__, par, par, par, par, 'css')),),
            resources=('pytis-demo-product.css',),
        )

    def bindings(self):
        return (
            Binding('webform', _("Product Info"), content=self._content,
                    descr=_("Shows web page generated from LCG structured text.")),
        )

    def actions(self):
        return (Action('toggle', _("Mark/unmark"), self._mark, hotkey='m'),
                Action('mark_all', _("Mark all"), self._mark, hotkey='Ctrl-a', mark_all=True),
                Action('unmark_all', _("Unmark all"), self._mark, hotkey='Ctrl-u', mark_all=True,
                       mark=False),
                Action('mark_selected', _("Mark selected"), self._mark_selected,
                       context=pp.ActionContext.SELECTION),
                Action('prices', _("Update prices"), self._update_prices),
                Action('print', _("Print price"), self._print),
                )

    def row_style(self, row):
        if row['count'].value() <= row.form.query_fields.row['min_count'].value():
            return pp.Style(background='#fdd')
        elif row['marked'].value():
            return pp.Style(background='#ffd')
        else:
            return None

    query_fields = QueryFields(
        (Field('min_count', _("Highlight low count"),
               type=pytis.data.Integer(not_null=True), default=10),),
        autoinit=True,
    )

    def _mark(self, row, mark_all=False, mark=True):
        if mark_all:
            product_id = None
        else:
            product_id = row["product_id"].value()
            mark = not row["marked"].value()
        count = pytis.form.run_procedure('misc', 'mark_products', product_id=product_id, mark=mark)
        app.echo(_("Marked %d rows") % count)

    def _mark_selected(self, rows):
        count = pytis.form.run_procedure('misc', 'mark_products',
                                         product_id=[r['product_id'].value() for r in rows],
                                         mark=True)
        app.echo(_("Marked %d rows") % count)

    def _update_prices(self, row):
        # This serves for testing user transactions.
        true_value = pd.Value(pd.Boolean(), True)
        condition = pd.EQ('marked', true_value)
        transaction = pd.transaction()
        try:
            def process(row):
                return row['product_id']
            product_ids = row.data().select_map(process, condition=condition)
            for product_id in product_ids:
                if not pytis.form.run_form(pytis.form.PopupEditForm, 'misc.Products',
                                           select_row=product_id,
                                           transaction=transaction):
                    app.error("Transaction aborted")
                    transaction.rollback()
                    return
        except Exception:
            transaction.rollback()
            raise
        transaction.commit()

    def _print(self, row):
        pytis.form.printout('misc.Products', 'misc.StandalonePrint', row)