コード例 #1
0
ファイル: models.py プロジェクト: DarioGT/lino
class Concept(mixins.BabelNamed):
    """A word and its translation in different languages.
    """
    class Meta:
        verbose_name = _("Concept")
        verbose_name_plural = _("Concepts")

    abbr = dd.BabelCharField(_("Abbreviation"), max_length=30, blank=True)
    wikipedia = dd.BabelCharField(_("Wikipedia"), max_length=200, blank=True)

    definition = dd.BabelTextField(_("Definition"), blank=True)
    is_jargon_domain = models.BooleanField(
        _("Jargon domain"),
        help_text=
        _("Whether this concept designates a domain of specialized vocabulary."
          ),
        default=False)

    def summary_row(self, ar=None):
        if self.abbr:
            return [
                "%s (%s)" %
                (dd.babelattr(self, 'name'), dd.babelattr(self, 'abbr'))
            ]
        return [dd.babelattr(self, 'name')]
コード例 #2
0
ファイル: mixins.py プロジェクト: DarioGT/lino
class ExcerptTitle(BabelNamed):
    """Mixin for models like
    :class:`lino_welfare.modlib.aids.models.AidType` and
    :class:`lino.modlib.courses.models.Line`.

    .. attribute:: name

        The designation of this row as seen by the user e.g. when
        selecting an instance of this model.

        One field for every :attr:`language <lino.core.site.Site.language>`.

    .. attribute:: excerpt_title

        The text to print as title in confirmations.
        One field for every :attr:`language <lino.core.site.Site.language>`.
        If this is empty, then :attr:`name` is used.

    """
    class Meta:
        abstract = True

    excerpt_title = dd.BabelCharField(
        _("Excerpt title"),
        max_length=200,
        blank=True,
        help_text=_("The title to be used when printing an excerpt."))

    def get_excerpt_title(self):
        return dd.babelattr(self, 'excerpt_title') or unicode(self)
コード例 #3
0
class CompanyType(mixins.BabelNamed):
    class Meta(object):
        app_label = 'contacts'  # avoid RemovedInDjango19Warning
        abstract = dd.is_abstract_model(__name__, 'CompanyType')
        verbose_name = _("Organization type")
        verbose_name_plural = _("Organization types")

    abbr = dd.BabelCharField(_("Abbreviation"), max_length=30, blank=True)
コード例 #4
0
ファイル: models.py プロジェクト: DarioGT/lino
class EventType(mixins.BabelNamed, mixins.Sequenced, MailableType):
    """The possible value of the :attr:`Event.type` field.
    Example content:

    .. lino2rst::

       rt.show(cal.EventTypes, limit=5)

    .. attribute:: is_appointment

        Whether events of this type should be considered
        "appointments" (i.e. whose time and place have been agreed
        upon with other users or external parties).

        The table (:class:`EventsByDay` and
        :class:`MyEvents`) show only events whose type has the
        `is_appointment` field checked.

    """
    templates_group = 'cal/Event'

    class Meta:
        app_label = 'cal'
        abstract = dd.is_abstract_model(__name__, 'EventType')
        verbose_name = _("Calendar Event Type")
        verbose_name_plural = _("Calendar Event Types")
        ordering = ['seqno']

    description = dd.RichTextField(_("Description"), blank=True, format='html')
    is_appointment = models.BooleanField(_("Event is an appointment"),
                                         default=True)
    all_rooms = models.BooleanField(_("Locks all rooms"), default=False)
    locks_user = models.BooleanField(
        _("Locks the user"),
        help_text=_("Whether events of this type make the user unavailable "
                    "for other locking events at the same time."),
        default=False)

    start_date = models.DateField(verbose_name=_("Start date"),
                                  blank=True,
                                  null=True)
    event_label = dd.BabelCharField(_("Event label"),
                                    max_length=200,
                                    blank=True)
    # , default=_("Calendar entry"))
    # default values for a Babelfield don't work as expected

    max_conflicting = models.PositiveIntegerField(
        _("Simultaneous events"),
        help_text=_("How many conflicting events should be tolerated."),
        default=1)

    def __unicode__(self):
        # when selecting an Event.event_type it is more natural to
        # have the event_label. It seems that the current `name` field
        # is actually never used.
        return settings.SITE.babelattr(self, 'event_label') \
            or settings.SITE.babelattr(self, 'name')
コード例 #5
0
class ExcerptTitle(BabelNamed):
    class Meta:
        abstract = True

    excerpt_title = dd.BabelCharField(
        _("Excerpt title"),
        max_length=200,
        blank=True,
        help_text=_(
            "The title to be used when printing an excerpt."))

    def get_excerpt_title(self):
        return dd.babelattr(self, 'excerpt_title') or str(self)
コード例 #6
0
ファイル: models.py プロジェクト: einarfelix/xl
class EventType(mixins.BabelNamed, Referrable, mixins.Sequenced, MailableType):
    templates_group = 'cal/Event'
    ref_max_length = 4

    class Meta:
        app_label = 'cal'
        abstract = dd.is_abstract_model(__name__, 'EventType')
        verbose_name = _("Calendar entry type")
        verbose_name_plural = _("Calendar entry types")
        ordering = ['seqno']

    description = dd.RichTextField(_("Description"), blank=True, format='html')
    is_appointment = models.BooleanField(_("Appointment"), default=True)
    all_rooms = models.BooleanField(_("Locks all rooms"), default=False)
    locks_user = models.BooleanField(_("Locks the user"), default=False)
    force_guest_states = models.BooleanField(_("Automatic presences"),
                                             default=False)
    fill_presences = models.BooleanField(_("Fill guests"), default=False)

    start_date = models.DateField(verbose_name=_("Start date"),
                                  blank=True,
                                  null=True)
    event_label = dd.BabelCharField(_("Entry label"),
                                    max_length=200,
                                    blank=True)
    # , default=_("Calendar entry"))
    # default values for a Babelfield don't work as expected

    max_conflicting = models.PositiveIntegerField(_("Simultaneous entries"),
                                                  default=1)
    max_days = models.PositiveIntegerField(_("Maximum days"), default=1)
    transparent = models.BooleanField(_("Transparent"), default=False)

    planner_column = PlannerColumns.field(blank=True)

    # default_duration = models.TimeField(
    #     _("Default duration"), blank=True, null=True)

    default_duration = dd.DurationField(_("Default duration"),
                                        blank=True,
                                        null=True)
コード例 #7
0
ファイル: models.py プロジェクト: einarfelix/xl
class PropChoice(dd.Model):
    class Meta:
        verbose_name = _("Property Choice")
        verbose_name_plural = _("Property Choices")
        unique_together = ['type', 'value']

    type = dd.ForeignKey(PropType, verbose_name=_("Property Type"))
    value = models.CharField(max_length=settings.SITE.propvalue_max_length,
                             verbose_name=_("Value"))
    text = dd.BabelCharField(max_length=200,
                             verbose_name=_("Designation"),
                             blank=True)

    def save(self, *args, **kw):
        if not self.text:
            self.text = self.value
        r = super(PropChoice, self).save(*args, **kw)
        return r

    def __str__(self):
        return dd.babelattr(self, 'text')
コード例 #8
0
class PropChoice(dd.Model):
    """A Choice for a given PropType.  `text` is the text to be displayed
    in combo boxes.
    
    `value` is the value to be stored in :attr:`PropValue.value`, it
    must be unique for all PropChoices of a given PropType.
    
    Choices for a given PropType will be sorted on `value` (we might
    make this more customizable if necessary by adding a new field
    `sort_text` and/or an option to sort on text instead of value)
    
    When configuring your property choices, be aware of the fact that
    existing property occurences will *not* change when you change the
    `value` of a property choice.

    """
    class Meta:
        verbose_name = _("Property Choice")
        verbose_name_plural = _("Property Choices")
        unique_together = ['type', 'value']

    type = models.ForeignKey(PropType, verbose_name=_("Property Type"))
    value = models.CharField(max_length=settings.SITE.propvalue_max_length,
                             verbose_name=_("Value"))
    text = dd.BabelCharField(max_length=200,
                             verbose_name=_("Designation"),
                             blank=True)

    def save(self, *args, **kw):
        if not self.text:
            self.text = self.value
        r = super(PropChoice, self).save(*args, **kw)
        return r

    def __unicode__(self):
        return dd.babelattr(self, 'text')
コード例 #9
0
ファイル: models.py プロジェクト: einarfelix/xl
class Page(Referrable, Hierarchical, Sequenced, Publishable):
    class Meta:
        verbose_name = _("Node")
        verbose_name_plural = _("Nodes")

    title = dd.BabelCharField(_("Title"), max_length=200, blank=True)
    body = dd.BabelTextField(_("Body"), blank=True, format='plain')
    raw_html = models.BooleanField(_("raw html"), default=False)

    @classmethod
    def get_dashboard_items(cls, user):
        obj = cls.get_by_ref('index', None)
        if obj is not None:
            yield obj

    def get_absolute_url(self, **kwargs):
        if self.ref:
            if self.ref != 'index':
                return dd.plugins.pages.build_plain_url(self.ref, **kwargs)
        return dd.plugins.pages.build_plain_url(**kwargs)

    def get_sidebar_caption(self):
        if self.title:
            return dd.babelattr(self, 'title')
        if self.ref == 'index':
            return str(_('Home'))
        if self.ref:
            return self.ref
        return str(self.id)

        #~ if self.ref or self.parent:
        #~ return self.ref
        #~ return unicode(_('Home'))

    def get_sidebar_item(self, request, other):
        kw = dict()
        add_user_language(kw, request)
        url = self.get_absolute_url(**kw)
        a = E.a(self.get_sidebar_caption(), href=url)
        if self == other:
            return E.li(a, **{'class': 'active'})
        return E.li(a)

    def get_sidebar_html(self, request):
        items = []
        #~ loop over top-level nodes
        for n in Page.objects.filter(parent__isnull=True).order_by('seqno'):
            #~ items += [li for li in n.get_sidebar_items(request,self)]
            items.append(n.get_sidebar_item(request, self))
            if self.is_parented(n):
                children = []
                for ch in n.children.order_by('seqno'):
                    children.append(ch.get_sidebar_item(request, self))
                if len(children):
                    items.append(E.ul(*children, **{'class': 'nav nav-list'}))

        e = E.ul(*items, **{'class': 'nav nav-list'})
        return tostring_pretty(e)

    def get_sidebar_menu(self, request):
        qs = Page.objects.filter(parent__isnull=True)
        #~ qs = self.children.all()
        yield ('/', 'index', str(_('Home')))
        #~ yield ('/downloads/', 'downloads', 'Downloads')
        #~ yield ('/about', 'about', 'About')
        #~ if qs is not None:
        for obj in qs:
            if obj.ref and obj.title:
                yield ('/' + obj.ref, obj.ref, dd.babelattr(obj, 'title'))
コード例 #10
0
class Page(mixins.Referrable, mixins.Hierarchical, mixins.Sequenced):
    """
    Deserves more documentation.
    """

    class Meta:
        verbose_name = _("Node")
        verbose_name_plural = _("Nodes")

    title = dd.BabelCharField(_("Title"), max_length=200, blank=True)
    body = dd.BabelTextField(_("Body"), blank=True, format='plain')

    raw_html = models.BooleanField(_("raw html"), default=False)

    def get_absolute_url(self):
        if self.ref:
            if self.ref != 'index':
                return PAGES.build_plain_url(self.ref)
        return PAGES.build_plain_url()

    def get_sidebar_caption(self):
        if self.title:
            return dd.babelattr(self, 'title')
        if self.ref == 'index':
            return unicode(_('Home'))
        if self.ref:
            return self.ref
        return str(self.id)

        #~ if self.ref or self.parent:
            #~ return self.ref
        #~ return unicode(_('Home'))

    def get_sidebar_item(self, request, other):
        a = E.a(self.get_sidebar_caption(), href=self.get_absolute_url())
        if self == other:
            return E.li(a, class_='active')
        return E.li(a)

    def get_sidebar_html(self, request):
        items = []
        #~ loop over top-level nodes
        for n in Page.objects.filter(parent__isnull=True).order_by('seqno'):
            #~ items += [li for li in n.get_sidebar_items(request,self)]
            items.append(n.get_sidebar_item(request, self))
            if self.is_parented(n):
                children = []
                for ch in n.children.order_by('seqno'):
                    children.append(ch.get_sidebar_item(request, self))
                if len(children):
                    items.append(E.ul(*children, class_='nav nav-list'))

        e = E.ul(*items, class_='nav nav-list')
        return E.tostring_pretty(e)

    def get_sidebar_menu(self, request):
        #~ qs = self.get_siblings()
        qs = Page.objects.filter(parent__isnull=True)
        #~ qs = self.children.all()
        yield ('/', 'index', unicode(_('Home')))
            #~ yield ('/downloads/', 'downloads', 'Downloads')
        #~ yield ('/about', 'about', 'About')
        #~ if qs is not None:
        for obj in qs:
            if obj.ref and obj.title:
                yield ('/' + obj.ref, obj.ref, dd.babelattr(obj, 'title'))
コード例 #11
0
class Journal(mixins.BabelNamed, mixins.Sequenced, mixins.Referrable,
              PrintableType):
    """The model used to store **journals**.
    See :ref:`cosi.specs.ledger.journals`.

    **Fields:**

    .. attribute:: ref
    .. attribute:: trade_type

        Pointer to :class:`TradeTypes`.

    .. attribute:: voucher_type

        Pointer to an item of :class:`VoucherTypes`.

    .. attribute:: journal_group

        Pointer to an item of :class:`JournalGroups`.

    .. attribute:: yearly_numbering

        Whether the
        :attr:`number<lino_cosi.lib.ledger.models.Voucher.number>` of
        vouchers should restart at 1 every year.

    .. attribute:: force_sequence

    .. attribute:: account
    .. attribute:: printed_name
    .. attribute:: dc

        The primary booking direction.

        In a journal of *sales invoices* this should be *Debit*
        (checked), because a positive invoice total should be
        *debited* from the customer's account.

        In a journal of *purchase invoices* this should be *Credit*
        (not checked), because a positive invoice total should be
        *credited* from the supplier's account.

        In a journal of *bank statements* this should be *Debit*
        (checked), because a positive balance change should be
        *debited* from the bank's general account.

        In a journal of *payment orders* this should be *Credit* (not
        checked), because a positive total means an "expense" and
        should be *credited* from the journal's general account.

        In all financial vouchers, the amount of every item increases
        the total if its direction is opposite of the primary
        direction.

    .. attribute:: auto_check_clearings

        Whether to automatically check and update the 'cleared' status
        of involved transactions when (de)registering a voucher of
        this journal.

        This can be temporarily disabled e.g. by batch actions in
        order to save time.

    .. attribute:: template

        See :attr:`PrintableType.template
        <lino.mixins.printable.PrintableType.template>`.

    """
    class Meta:
        app_label = 'ledger'
        verbose_name = _("Journal")
        verbose_name_plural = _("Journals")

    trade_type = TradeTypes.field(blank=True)
    voucher_type = VoucherTypes.field()
    journal_group = JournalGroups.field()
    auto_check_clearings = models.BooleanField(
        _("Check clearing"),
        default=True,
        help_text=_("Automatically update the cleared status of involved "
                    "transactions when (de)registering a voucher of this "
                    "journal"))
    force_sequence = models.BooleanField(_("Force chronological sequence"),
                                         default=False)
    account = dd.ForeignKey('accounts.Account', blank=True, null=True)
    printed_name = dd.BabelCharField(_("Printed document designation"),
                                     max_length=100,
                                     blank=True)
    dc = DebitOrCreditField(_("Primary booking direction"))
    yearly_numbering = models.BooleanField(_("Yearly numbering"),
                                           default=False)

    # invert_due_dc = models.BooleanField(
    #     _("Invert booking direction"),
    #     help_text=_("Whether to invert booking direction of due movement."),
    #     default=True)

    # @dd.chooser()
    # def account_choices(cls, chart):
    #     fkw = dict(type=AccountTypes.bank_accounts)
    #     return rt.modules.accounts.Account.objects.filter(chart=chart, **fkw)

    def get_doc_model(self):
        """The model of vouchers in this Journal.

        """
        # print self,DOCTYPE_CLASSES, self.doctype
        return self.voucher_type.model
        #~ return DOCTYPES[self.doctype][0]

    def get_doc_report(self):
        return self.voucher_type.table_class
        #~ return DOCTYPES[self.doctype][1]

    def get_voucher(self, year=None, number=None, **kw):
        cl = self.get_doc_model()
        kw.update(journal=self, accounting_period__year=year, number=number)
        return cl.objects.get(**kw)

    def create_voucher(self, **kw):
        """Create an instance of this Journal's voucher model
        (:meth:`get_doc_model`).

        """
        cl = self.get_doc_model()
        kw.update(journal=self)
        try:
            doc = cl()
            # ~ doc = cl(**kw) # wouldn't work. See Django ticket #10808
            #~ doc.journal = self
            for k, v in kw.items():
                setattr(doc, k, v)
            #~ print 20120825, kw
        except TypeError:
            #~ print 20100804, cl
            raise
        doc.on_create(None)
        #~ doc.full_clean()
        #~ doc.save()
        return doc

    def get_allowed_accounts(self, **kw):
        if self.trade_type:
            kw[self.trade_type.name + '_allowed'] = True
        # kw.update(chart=self.chart)
        return rt.modules.accounts.Account.objects.filter(**kw)

    def get_next_number(self, voucher):
        # ~ self.save() # 20131005 why was this?
        cl = self.get_doc_model()
        flt = dict()
        if self.yearly_numbering:
            flt.update(accounting_period__year=voucher.accounting_period.year)
        d = cl.objects.filter(journal=self,
                              **flt).aggregate(models.Max('number'))
        number = d['number__max']
        #~ logger.info("20121206 get_next_number %r",number)
        if number is None:
            return 1
        return number + 1

    def __str__(self):
        # s = super(Journal, self).__str__()
        s = dd.babelattr(self, 'name')
        if self.ref:
            s += " (%s)" % self.ref
            #~ return '%s (%s)' % (d.BabelNamed.__unicode__(self),self.ref or self.id)
        return s
        #~ return self.ref +'%s (%s)' % mixins.BabelNamed.__unicode__(self)
        #~ return self.id +' (%s)' % mixins.BabelNamed.__unicode__(self)

    def save(self, *args, **kw):
        #~ self.before_save()
        r = super(Journal, self).save(*args, **kw)
        self.after_save()
        return r

    def after_save(self):
        pass

    def full_clean(self, *args, **kw):
        if self.dc is None:
            if self.trade_type:
                self.dc = self.trade_type.dc
            elif self.account:
                self.dc = self.account.type.dc
            else:
                self.dc = DEBIT  # cannot be NULL

        if not self.name:
            self.name = self.id
        #~ if not self.pos:
        #~ self.pos = self.__class__.objects.all().count() + 1
        super(Journal, self).full_clean(*args, **kw)

    def disable_voucher_delete(self, doc):
        # print "pre_delete_voucher", doc.number, self.get_next_number()
        if self.force_sequence:
            if doc.number + 1 != self.get_next_number(doc):
                return _("%s is not the last voucher in journal" %
                         unicode(doc))

    def get_template_groups(self):
        """Here we override the class method by an instance method.  This
        means that we must also override all other methods of
        Printable who call the *class* method.  This is currently only
        :meth:`template_choices`.

        """
        return [self.voucher_type.model.get_template_group()]

    @dd.chooser(simple_values=True)
    def template_choices(cls, build_method, voucher_type):
        # Overrides PrintableType.template_choices to not use the class
        # method `get_template_groups`.

        if not voucher_type:
            return []
        #~ print 20131006, voucher_type
        template_groups = [voucher_type.model.get_template_group()]
        return cls.get_template_choices(build_method, template_groups)