Example #1
0
def customize_school():
    dd.inject_field('courses.Pupil',
                    'school',
                    models.ForeignKey(School,
                                      blank=True, null=True,
            help_text=_("""The regular school where this child goes.""")
                    ))
Example #2
0
def customize_school():
    dd.inject_field('courses.Pupil',
                    'school',
                    models.ForeignKey(School,
                                      blank=True, null=True,
            help_text=_("""The regular school where this child goes.""")
                    ))
Example #3
0
def inject_pricefactor_fields(sender, **kw):
    for pf in PriceFactors.get_list_items():
        dd.inject_field(
            'products.PriceRule', pf.field_name,
            pf.field_cls.field(blank=True))
        dd.inject_field(
            'contacts.Partner', pf.field_name,
            pf.field_cls.field(blank=True))
Example #4
0
def inject_pricefactor_fields(sender, **kw):
    for pf in PriceFactors.get_list_items():
        dd.inject_field(
            'products.PriceRule', pf.field_name,
            pf.field_cls.field(blank=True))
        dd.inject_field(
            'contacts.Partner', pf.field_name,
            pf.field_cls.field(blank=True))
Example #5
0
def inject_summary_fields(sender, **kw):
    SiteSummary = rt.models.working.SiteSummary
    WorkSite = rt.models.tickets.Site
    Ticket = dd.plugins.working.ticket_model
    for t in ReportingTypes.get_list_items():
        k = t.name + '_hours'
        dd.inject_field(
            SiteSummary, k, dd.DurationField(t.text, null=True, blank=True))
        dd.inject_field(
            Ticket, k, dd.DurationField(t.text, null=True, blank=True))

        def make_getter(t):
            k = t.name + '_hours'
            def getter(obj, ar):
                qs = SiteSummary.objects.filter(
                    master=obj, year__isnull=True)
                d = qs.aggregate(**{k:models.Sum(k)})
                n = d[k]
                return n
            return getter

        dd.inject_field(
            WorkSite, k, dd.VirtualField(
                dd.DurationField(t.text), make_getter(t)))


    if False:  # removed 20181211 because useless
      for ts in TicketStates.get_list_items():
        k = ts.get_summary_field()
        if k is not None:
            dd.inject_field(
                SiteSummary, k, models.IntegerField(ts.text))

            def make_getter(ts):
                k = ts.get_summary_field()
                def getter(obj, ar):
                    if ar is None:
                        return ''
                    qs = SiteSummary.objects.filter(master=obj)
                    d = qs.aggregate(**{k:models.Sum(k)})
                    n = d[k]
                    if n == 0:
                        return ''
                    sar = rt.models.tickets.TicketsBySite.request(
                        obj, param_values=dict(
                            state=ts, show_active=None))
                    # n = sar.get_total_count()
                    url = ar.renderer.request_handler(sar)
                    if url is None:
                        return str(n)
                    return E.a(str(n), href='javascript:'+url)
                return getter

            dd.inject_field(
                WorkSite, k, dd.VirtualField(
                    dd.DisplayField(ts.text), make_getter(ts)))
Example #6
0
def customize_contacts(sender, **kw):
    """
    Injects application-specific fields to :mod:`contacts <lino_xl.lib.contacts>`.
    """
    dd.inject_field(
        contacts.RoleType,
        'use_in_contracts',
        models.BooleanField(
            verbose_name=_("usable in contracts"),
            default=True,
            help_text=_(
                "Whether Links of this type can be used "
                "as contact person of a job contract.")))
Example #7
0
def customize_siteconfig():
    """
    Injects application-specific fields to :class:`SiteConfig <lino.modlib.system.SiteConfig>`.
    """
    dd.inject_field(
        'system.SiteConfig',
        'system_note_type',
        dd.ForeignKey(
            'notes.EventType',
            blank=True, null=True,
            verbose_name=_("Default system note type"),
            help_text=_("""\
Note Type used by system notes.
If this is empty, then system notes won't create any entry to the Notes table.""")))
Example #8
0
def customize_siteconfig():
    """
    Injects application-specific fields to :class:`SiteConfig <lino.modlib.system.SiteConfig>`.
    """
    dd.inject_field(
        'system.SiteConfig', 'system_note_type',
        dd.ForeignKey('notes.EventType',
                      blank=True,
                      null=True,
                      verbose_name=_("Default system note type"),
                      help_text=_("""\
Note Type used by system notes.
If this is empty, then system notes won't create any entry to the Notes table."""
                                  )))
Example #9
0
def inject_partner_field(sender=None, **kwargs):

    User = sender.models.users.User

    if dd.is_installed('contacts'):
        Partner = sender.models.contacts.Partner
        if not issubclass(User, Partner):
            dd.inject_field(User, 'partner', dd.ForeignKey(
                'contacts.Partner', blank=True, null=True,
                related_name='users_by_partner',
                on_delete=models.PROTECT))
            # a related_name is needed so that Avanti can have aClient
            # who inherits from both Partner and UserAuthored
            return
    dd.inject_field(User, 'partner', dd.DummyField())
Example #10
0
def inject_tradetype_fields(sender, **kw):
    """This defines certain database fields related to your
    :class:`TradeTypes`.

    """
    for tt in TradeTypes.items():
        if tt.partner_account_field_name is not None:
            dd.inject_field(
                'system.SiteConfig', tt.partner_account_field_name,
                dd.ForeignKey('accounts.Account',
                              verbose_name=tt.partner_account_field_label,
                              related_name='configs_by_' +
                              tt.partner_account_field_name,
                              blank=True,
                              null=True))
        if tt.vat_account_field_name is not None:
            dd.inject_field(
                'system.SiteConfig', tt.vat_account_field_name,
                dd.ForeignKey('accounts.Account',
                              verbose_name=tt.vat_account_field_label,
                              related_name='configs_by_' +
                              tt.vat_account_field_name,
                              blank=True,
                              null=True))
        if tt.base_account_field_name is not None:
            dd.inject_field(
                'system.SiteConfig', tt.base_account_field_name,
                dd.ForeignKey('accounts.Account',
                              verbose_name=tt.base_account_field_label,
                              related_name='configs_by_' +
                              tt.base_account_field_name,
                              blank=True,
                              null=True))
            dd.inject_field(
                'products.Product', tt.base_account_field_name,
                dd.ForeignKey('accounts.Account',
                              verbose_name=tt.base_account_field_label,
                              related_name='products_by_' +
                              tt.base_account_field_name,
                              blank=True,
                              null=True))
        if tt.price_field_name is not None:
            dd.inject_field(
                'products.Product', tt.price_field_name,
                dd.PriceField(verbose_name=tt.price_field_label,
                              blank=True,
                              null=True))
Example #11
0
def inject_partner_field(sender=None, **kwargs):

    User = sender.models.users.User

    if dd.is_installed('contacts'):
        Partner = sender.models.contacts.Partner
        if not issubclass(User, Partner):
            dd.inject_field(
                User, 'partner',
                dd.ForeignKey('contacts.Partner',
                              blank=True,
                              null=True,
                              related_name='users_by_partner',
                              on_delete=models.PROTECT))
            # a related_name is needed so that Avanti can have aClient
            # who inherits from both Partner and UserAuthored
            return
    dd.inject_field(User, 'partner', dd.DummyField())
Example #12
0
def inject_tradetype_fields(sender, **kw):
    """This defines certain database fields related to your
    :class:`TradeTypes`.

    """
    for tt in TradeTypes.items():
        if tt.partner_account_field_name is not None:
            dd.inject_field(
                'system.SiteConfig',
                tt.partner_account_field_name,
                dd.ForeignKey(
                    'accounts.Account',
                    verbose_name=tt.partner_account_field_label,
                    related_name='configs_by_' + tt.partner_account_field_name,
                    blank=True, null=True))
        if tt.vat_account_field_name is not None:
            dd.inject_field('system.SiteConfig', tt.vat_account_field_name,
                            dd.ForeignKey(
                                'accounts.Account',
                                verbose_name=tt.vat_account_field_label,
                                related_name='configs_by_' +
                                tt.vat_account_field_name,
                                blank=True, null=True))
        if tt.base_account_field_name is not None:
            dd.inject_field('system.SiteConfig', tt.base_account_field_name,
                            dd.ForeignKey(
                                'accounts.Account',
                                verbose_name=tt.base_account_field_label,
                                related_name='configs_by_' +
                                tt.base_account_field_name,
                                blank=True, null=True))
            dd.inject_field('products.Product', tt.base_account_field_name,
                            dd.ForeignKey(
                                'accounts.Account',
                                verbose_name=tt.base_account_field_label,
                                related_name='products_by_' +
                                tt.base_account_field_name,
                                blank=True, null=True))
        if tt.price_field_name is not None:
            dd.inject_field('products.Product', tt.price_field_name,
                            dd.PriceField(verbose_name=tt.price_field_label,
                                          blank=True, null=True))
Example #13
0
def inject_tradetype_fields(sender, **kw):
    """This defines certain database fields related to your
    :class:`TradeTypes`.

    """
    # print(20200622, list([i.invoice_account_field_name for i in TradeTypes.items()]))
    for tt in TradeTypes.items():
        if tt.invoice_account_field_name is not None:
            dd.inject_field(
                'contacts.Partner', tt.invoice_account_field_name,
                dd.ForeignKey('ledger.Account',
                              verbose_name=tt.invoice_account_field_label,
                              on_delete=models.PROTECT,
                              related_name='partners_by_' +
                              tt.invoice_account_field_name,
                              blank=True,
                              null=True))
        if tt.base_account_field_name is not None:
            dd.inject_field(
                'products.Product', tt.base_account_field_name,
                dd.ForeignKey('ledger.Account',
                              verbose_name=tt.base_account_field_label,
                              on_delete=models.PROTECT,
                              related_name='products_by_' +
                              tt.base_account_field_name,
                              blank=True,
                              null=True))
        if tt.price_field_name is not None:
            dd.inject_field(
                'products.Product', tt.price_field_name,
                dd.PriceField(verbose_name=tt.price_field_label,
                              blank=True,
                              null=True))
Example #14
0
def customize_siteconfig():

    dd.inject_field(
        'system.SiteConfig',
        'propgroup_skills',
        models.ForeignKey(
            'properties.PropGroup',
            blank=True, null=True,
            verbose_name=_("Skills Property Group"),
            related_name='skills_sites',
            help_text=_(
                "The property group to be used as master "
                "for the SkillsByPerson table.")))
    dd.inject_field(
        'system.SiteConfig',
        'propgroup_softskills',
        models.ForeignKey(
            'properties.PropGroup',
            blank=True, null=True,
            verbose_name=_("Soft Skills Property Group"),
            related_name='softskills_sites',
            help_text=_(
                "The property group to be used as master "
                "for the SoftSkillsByPerson table.")))
    dd.inject_field(
        'system.SiteConfig',
        'propgroup_obstacles',
        models.ForeignKey(
            'properties.PropGroup',
            blank=True, null=True,
            verbose_name=_("Obstacles Property Group"),
            related_name='obstacles_sites',
            help_text=_(
                "The property group to be used as master "
                "for the ObstaclesByPerson table.")))
Example #15
0
def inject_tradetype_fields(sender, **kw):
    """This defines certain database fields related to your
    :class:`TradeTypes`.

    """
    for tt in TradeTypes.items():
        if tt.invoice_account_field_name is not None:
            dd.inject_field(
                'contacts.Partner', tt.invoice_account_field_name,
                dd.ForeignKey(
                    'ledger.Account',
                    verbose_name=tt.invoice_account_field_label,
                    on_delete=models.PROTECT,
                    related_name='partners_by_' + tt.invoice_account_field_name,
                    blank=True, null=True))
        if tt.base_account_field_name is not None:
            dd.inject_field(
                'products.Product', tt.base_account_field_name,
                dd.ForeignKey(
                    'ledger.Account',
                    verbose_name=tt.base_account_field_label,
                    on_delete=models.PROTECT,
                    related_name='products_by_' + tt.base_account_field_name,
                    blank=True, null=True))
        if tt.price_field_name is not None:
            dd.inject_field(
                'products.Product', tt.price_field_name,
                dd.PriceField(verbose_name=tt.price_field_label,
                              blank=True, null=True))
Example #16
0
def customize_siteconfig(sender, **kw):
    """
    Injects application-specific fields to
    :class:`SiteConfig <lino.models.SiteConfig>`.
    """

    dd.inject_field('system.SiteConfig',
                    'job_office',
                    models.ForeignKey('contacts.Company',
                                      blank=True, null=True,
                                      verbose_name=_("Local job office"),
                                      related_name='job_office_sites',
            help_text="""The Company whose contact persons 
            will be choices for `Person.job_office_contact`."""))

    dd.inject_field('system.SiteConfig',
                    'residence_permit_upload_type',
                    models.ForeignKey("uploads.UploadType",
                                      blank=True, null=True,
                                      verbose_name=_(
                                          "Upload Type for residence permit"),
                                      related_name='residence_permit_sites'))

    dd.inject_field('system.SiteConfig',
                    'work_permit_upload_type',
                    #~ UploadType.objects.get(pk=2)
                    models.ForeignKey("uploads.UploadType",
                                      blank=True, null=True,
                                      verbose_name=_(
                                          "Upload Type for work permit"),
                                      related_name='work_permit_sites'))

    dd.inject_field('system.SiteConfig',
                    'driving_licence_upload_type',
                    models.ForeignKey("uploads.UploadType",
                                      blank=True, null=True,
                                      verbose_name=_(
                                          "Upload Type for driving licence"),
                                      related_name='driving_licence_sites'))
Example #17
0
settings.SITE.add_user_field('newcomer_quota', models.IntegerField(
    _("Newcomers Quota"),
    default=0,
    help_text="""\
Wieviel Arbeitszeit dieser Benutzer für Neuanträge zur Verfügung steht
(100 = ganztags, 50 = halbtags, 0 = gar nicht).
Wenn zwei Benutzer die gleiche Belastungspunktzahl haben,
aber einer davon sich nur zu 50% um Neuanträge kümmert,
gilt er als doppelt so belastet wie sein Kollege.
"""))


dd.inject_field(
    'pcsw.Client',
    'broker',
    dd.ForeignKey(
        'newcomers.Broker',
        blank=True, null=True,
        help_text=_("The Broker who sent this Newcomer.")))

dd.inject_field(
    'pcsw.Client',
    'faculty',
    dd.ForeignKey(
        'newcomers.Faculty',
        blank=True, null=True,
        help_text=_("The Faculty this client has been attributed to.")),
    active=True)


Example #18
0
    class NotesByProject(NotesByX):
        master_key = 'project'
        # stay_in_grid = True


class NotesByOwner(NotesByX):
    master_key = 'owner'


class NotesByCompany(NotesByX):
    master_key = 'company'


class NotesByPerson(NotesByX):
    master_key = 'contact_person'



dd.inject_field(
    'system.SiteConfig',
    'system_note_type',
    dd.ForeignKey(
        'notes.EventType',
        blank=True, null=True,
        verbose_name=_("Default system note type"),
        help_text=_("""\
Note Type used by system notes.
If this is empty, then system notes won't create any entry to the Notes table.""")))


Example #19
0
    title = models.CharField(_("Description"), max_length=200, blank=True)


if False:
    """Install a post_init signal listener for each concrete subclass of
    VatDocument.  The following trick worked...  but best is to store
    it in VatRegime, not per voucher.

    """
    def set_default_item_vat(sender, instance=None, **kwargs):
        instance.item_vat = settings.SITE.get_item_vat(instance)
        # print("20130902 set_default_item_vat", instance)

    @dd.receiver(dd.post_analyze)
    def on_post_analyze(sender, **kw):
        for m in rt.models_by_base(VatDocument):
            dd.post_init.connect(set_default_item_vat, sender=m)
            # print('20130902 on_post_analyze installed receiver for',m)


dd.inject_field(
    'contacts.Partner', 'vat_regime',
    VatRegimes.field(blank=True,
                     help_text=_("The default VAT regime for \
        sales and purchases of this partner.")))

dd.inject_field('contacts.Company', 'vat_id',
                models.CharField(_("VAT id"), max_length=200, blank=True))

from .ui import *
Example #20
0
def set_excerpts_actions(sender, **kw):
    # logger.info("20180114 %s.set_excerpts_actions()", __name__)
    # in case ExcerptType is overridden
    ExcerptType = sender.modules.excerpts.ExcerptType
    Excerpt = sender.modules.excerpts.Excerpt

    try:
        etypes = [(obj, obj.content_type)
                  for obj in ExcerptType.objects.all().order_by('id')]
    except (OperationalError, ProgrammingError, UnresolvedChoice) as e:
        dd.logger.debug("Failed to set excerpts actions : %s", e)
        # Happens e.g. when the database has not yet been migrated
        etypes = []

    for atype, ct in etypes:
        if ct is not None:
            bm = ct.model_class()
            if bm is None:
                # e.g. database contains types for models that existed
                # before but have been removed
                continue
            for m in rt.models_by_base(bm):
                an = atype.get_action_name()
                if not hasattr(m, an):
                    m.define_action(**{an: CreateExcerpt(
                        atype, six.text_type(atype))})
                # dd.logger.info("Added print action to %s", m)

                # if atype.certifying and not issubclass(m, Certifiable):
                #     m.define_action(
                #         clear_printed=ClearCache())

    # An attestable model must also inherit
    # :class:`lino.mixins.printable.BasePrintable` or some subclass
    # thereof.

    for i in Shortcuts.items():

        def f(obj, ar):
            if ar is None:
                return ''
            if obj is None:
                return E.div()
            try:
                et = ExcerptType.objects.get(shortcut=i)
            except ExcerptType.DoesNotExist:
                return E.div()
            items = []
            if True:
                sar = ar.spawn(
                    ExcerptsByOwner,
                    master_instance=obj,
                    param_values=dict(excerpt_type=et))
                n = sar.get_total_count()
                if n > 0:
                    ex = sar.sliced_data_iterator[0]
                    items.append(ar.obj2html(ex, _("Last")))

                    ba = sar.bound_action
                    btn = sar.renderer.action_button(
                        obj, sar, ba, "%s (%d)" % (_("All"), n),
                        icon_name=None)
                    items.append(btn)

                ia = getattr(obj, et.get_action_name())
                btn = ar.instance_action_button(
                    ia, _("Create"), icon_name=None)
                items.append(btn)

            else:
                ot = ContentType.objects.get_for_model(obj.__class__)
                qs = Excerpt.objects.filter(
                    owner_id=obj.pk, owner_type=ot, excerpt_type=et)
                if qs.count() > 0:
                    ex = qs[0]
                    txt = ExcerptsByOwner.format_excerpt(ex)
                    items.append(ar.obj2html(ex, txt))
            return E.div(*join_elems(items, ', '))

        vf = dd.VirtualField(dd.DisplayField(i.text), f)
        dd.inject_field(i.model_spec, i.name, vf)
Example #21
0
    model = User
    column_names = 'username person company is_superuser is_staff *'


if settings.SITE.is_installed('contacts'):
    """
    Don't inject fields if contacts is just being imported from some other module.
    """

    from lino.models import SiteConfig

    dd.inject_field(
        SiteConfig, 'site_company',
        models.ForeignKey(
            Company,
            blank=True,
            null=True,
            verbose_name=_("The company that runs this site"),
            related_name='site_company_sites',
        ), """The Company to be used as sender in documents.""")

NAME = "contacts"
LABEL = _("Contacts")


def setup_main_menu(config, site, profile, m):
    m.add_action(Companies)
    m.add_action(Persons)
    #~ m.add_action(Contacts)

Example #22
0
#
#

def preview(obj, ar):
    return obj.html or obj.text

def spam(obj):
    """Checks if the message is spam or not
    """
    if obj.subject.startswith("*****SPAM*****"):
        return True
    else:
        return False


dd.inject_field('django_mailbox.Message', 'preview',
                dd.VirtualField(dd.HtmlBox(_("Preview")), preview))
dd.inject_field('django_mailbox.Message', 'ticket',
                dd.ForeignKey('tickets.Ticket', blank=True, null=True))

dd.update_field('django_mailbox.Message', 'from_header', format="plain")


from .ui import *

@dd.schedule_often(10)
def get_new_mail():
    for mb in rt.models.django_mailbox.Mailbox.objects.filter(active=True):
        mails = mb.get_new_mail()
        for mail in mails:
            if spam(mail):
                mail.spam = True
Example #23
0
def set_excerpts_actions(sender, **kw):
    """Installs (1) print management actions on models for which there is
    an excerpt type and (2) the excerpt shortcut fields defined in
    :class:`lino.modlib.excerpts.choicelists.Shortcuts`.

    """
    # logger.info("20140401 %s.set_attest_actions()", __name__)

    # in case ExcerptType is overridden
    ExcerptType = sender.modules.excerpts.ExcerptType
    Excerpt = sender.modules.excerpts.Excerpt

    try:
        etypes = [(obj, obj.content_type)
                  for obj in ExcerptType.objects.all()]
    except (OperationalError, ProgrammingError):
        # logger.warning("Failed to set excerpts actions : %s", e)
        # Happens e.g. when the database has not yet been migrated
        etypes = []

    for atype, ct in etypes:
        if ct is not None:
            m = ct.model_class()
            if m is not None:  # e.g. database contains types for
                               # models that existed before but have
                               # been removed
                an = atype.get_action_name()
                m.define_action(**{an: CreateExcerpt(atype, unicode(atype))})
                # if atype.primary:
                #     if atype.certifying:
                #         m.define_action(
                #             clear_printed=ClearPrinted())

    # An attestable model must also inherit
    # :class:`lino.mixins.printable.BasePrintable` or some subclass
    # thereof.

    for i in Shortcuts.items():

        def f(obj, ar):
            if ar is None:
                return ''
            if obj is None:
                return E.div()
            try:
                et = ExcerptType.objects.get(shortcut=i)
            except ExcerptType.DoesNotExist:
                return E.div()
            items = []
            if True:
                sar = ar.spawn(
                    ExcerptsByOwner,
                    master_instance=obj,
                    param_values=dict(excerpt_type=et))
                n = sar.get_total_count()
                if n > 0:
                    ex = sar.sliced_data_iterator[0]
                    items.append(ar.obj2html(ex, _("Last")))

                    ba = sar.bound_action
                    btn = sar.renderer.action_button(
                        obj, sar, ba, "%s (%d)" % (_("All"), n),
                        icon_name=None)
                    items.append(btn)
    
                ia = getattr(obj, et.get_action_name())
                btn = ar.instance_action_button(
                    ia, _("Create"), icon_name=None)
                items.append(btn)

            else:
                ot = ContentType.objects.get_for_model(obj.__class__)
                qs = Excerpt.objects.filter(
                    owner_id=obj.pk, owner_type=ot, excerpt_type=et)
                if qs.count() > 0:
                    ex = qs[0]
                    txt = ExcerptsByOwner.format_excerpt(ex)
                    items.append(ar.obj2html(ex, txt))
            return E.div(*join_elems(items, ', '))
    
        vf = dd.VirtualField(dd.DisplayField(i.text), f)
        dd.inject_field(i.model_spec, i.name, vf)
Example #24
0

class RolesByPerson(Roles):
    """Shows all roles of a person."""
    required_roles = dd.login_required(SimpleContactsUser)
    #~ required_user_level = None
    label = _("Contact for")
    master_key = 'person'
    column_names = 'company type start_date end_date *'
    auto_fit_column_widths = True
    hidden_columns = 'id'

dd.inject_field(
    'system.SiteConfig',
    'next_partner_id',
    models.IntegerField(
        default=PARTNER_NUMBERS_START_AT,
        blank=True, null=True,
        verbose_name=_("Next partner id"),
        help_text=_("The next automatic id for any new partner.")))



@dd.receiver(dd.pre_analyze)
def company_model_alias(sender, **kw):
    """
    prepare ticket #72 which will rename Company to Organisation
    """
    sender.modules.contacts.Organisation = sender.modules.contacts.Company


@dd.receiver(dd.post_analyze)
Example #25
0
        master_key = 'project'


class NotesByOwner(NotesByX):
    master_key = 'owner'
    column_names = "date time event_type type subject user *"


class NotesByCompany(NotesByX):
    master_key = 'company'
    column_names = "date time event_type type subject user *"


class NotesByPerson(NotesByX):
    master_key = 'contact_person'
    column_names = "date time event_type type subject user *"


# system = dd.resolve_app('system')

dd.inject_field(
    'system.SiteConfig', 'system_note_type',
    dd.ForeignKey('notes.EventType',
                  blank=True,
                  null=True,
                  verbose_name=_("Default system note type"),
                  help_text=_("""\
Note Type used by system notes.
If this is empty, then system notes won't create any entry to the Notes table."""
                              )))
Example #26
0
    """
    .. attribute:: invite_client
    .. attribute:: esf_field

    """

    #~ invite_team_members = models.BooleanField(
        #~ _("Invite team members"),default=False)
    # invite_team_members = dd.ForeignKey('users.Team', blank=True, null=True)
    invite_client = models.BooleanField(_("Invite client"), default=False)
    esf_field = dd.DummyField()

dd.inject_field(
    'users.User', 'calendar',
    dd.ForeignKey(
        'cal.Calendar',
        verbose_name=_("User Calendar"),
        help_text=_("Calendar where your events are published."),
        related_name='user_calendars',
        blank=True, null=True))

dd.inject_field(
    'system.SiteConfig', 'client_calendar',
    dd.ForeignKey(
        'cal.EventType',
        verbose_name=_("Default type for client calendar events"),
        related_name='client_calendars',
        blank=True, null=True))

dd.inject_field(
    'system.SiteConfig', 'client_guestrole',
    dd.ForeignKey(
Example #27
0
def inject_summary_fields(sender, **kw):
    SiteSummary = rt.models.working.SiteSummary
    UserSummary = rt.models.working.UserSummary
    WorkSite = rt.models.tickets.Site
    Ticket = dd.plugins.working.ticket_model
    for t in ReportingTypes.get_list_items():
        k = t.name + '_hours'
        dd.inject_field(SiteSummary, k,
                        dd.DurationField(t.text, null=True, blank=True))
        dd.inject_field(UserSummary, k,
                        dd.DurationField(t.text, null=True, blank=True))
        dd.inject_field(Ticket, k,
                        dd.DurationField(t.text, null=True, blank=True))

        def make_getter(t):
            k = t.name + '_hours'

            def getter(obj, ar):
                qs = SiteSummary.objects.filter(master=obj, year__isnull=True)
                d = qs.aggregate(**{k: models.Sum(k)})
                n = d[k]
                return n

            return getter

        dd.inject_field(
            WorkSite, k,
            dd.VirtualField(dd.DurationField(t.text), make_getter(t)))

    if False:  # removed 20181211 because useless
        for ts in TicketStates.get_list_items():
            k = ts.get_summary_field()
            if k is not None:
                dd.inject_field(SiteSummary, k, models.IntegerField(ts.text))

                def make_getter(ts):
                    k = ts.get_summary_field()

                    def getter(obj, ar):
                        if ar is None:
                            return ''
                        qs = SiteSummary.objects.filter(master=obj)
                        d = qs.aggregate(**{k: models.Sum(k)})
                        n = d[k]
                        if n == 0:
                            return ''
                        sar = rt.models.tickets.TicketsBySite.request(
                            obj, param_values=dict(state=ts, show_active=None))
                        # n = sar.get_total_count()
                        url = ar.renderer.request_handler(sar)
                        if url is None:
                            return str(n)
                        return E.a(str(n), href='javascript:' + url)

                    return getter

                dd.inject_field(
                    WorkSite, k,
                    dd.VirtualField(dd.DisplayField(ts.text), make_getter(ts)))
Example #28
0
    #~ def setup_handle(self,lh):
        #~ lh.config.label = _("Site Parameters")
        #~ lh.about.label = _("About")

class SiteConfigs(dd.Table):

    """
    The table used to present the :class:`SiteConfig` row in a Detail form.
    See also :meth:`lino.Lino.get_site_config`.
    Deserves more documentation.
    """
    model = 'system.SiteConfig'
    required_roles = dd.required(SiteStaff)
    default_action = actions.ShowDetailAction()
    #~ has_navigator = False
    hide_top_toolbar = True
    #~ can_delete = perms.never
    detail_layout = """
    default_build_method
    # lino.ModelsBySite
    """

    do_build = BuildSiteCache()


if settings.SITE.user_model == 'auth.User':
    dd.inject_field(settings.SITE.user_model,
                    'profile', UserProfiles.field())
    dd.inject_field(settings.SITE.user_model, 'language', dd.LanguageField())

Example #29
0
# will clear GuestStates

import lino.modlib.cal.workflows.feedback

add = GuestStates.add_item
add('44', _("Waiting"), 'waiting')
add('45', _("Busy"), 'busy')
add('46', _("Gone"), 'gone')


#~ add = GuestStates.add_item
#~ add('21', _("Waiting"),'waiting')

dd.inject_field(
    'cal.Guest', 'waiting_since',
    models.DateTimeField(
        _("Waiting since"),
        editable=False, blank=True, null=True,
        help_text=_("Time when the visitor arrived (checked in).")))
dd.inject_field(
    'cal.Guest', 'busy_since',
    models.DateTimeField(
        _("Waiting until"),
        editable=False, blank=True, null=True,
        help_text=_("Time when the visitor was received by agent.")))
dd.inject_field(
    'cal.Guest', 'gone_since',
    models.DateTimeField(
        _("Present until"),
        editable=False, blank=True, null=True,
        help_text=_("Time when the visitor left (checked out).")))
Example #30
0
        abstract = dd.is_abstract_model(__name__, 'ClientContact')
    #~ type = ClientContactTypes.field(blank=True)
    client = dd.ForeignKey(client_model)
    remark = models.TextField(_("Remarks"), blank=True)  # ,null=True)
    
    # allow_cascaded_delete = 'client'

    def full_clean(self, *args, **kw):
        if not self.remark and not self.type \
           and not self.company and not self.contact_person:
            raise ValidationError(_("Must fill at least one field."))
        super(ClientContact, self).full_clean(*args, **kw)


dd.update_field(ClientContact, 'contact_person',
                verbose_name=_("Contact person"))


dd.inject_field(
    'contacts.Partner', 'client_contact_type',
    dd.ForeignKey(
        'clients.ClientContactType', blank=True, null=True))

from lino_xl.lib.contacts.models import Partners

class PartnersByClientContactType(Partners):
    master_key = 'client_contact_type'
    column_names = "name address_column phone gsm email *"
    auto_fit_column_widths = True

Example #31
0

class RolesByPerson(Roles):
    required_roles = dd.required(ContactsUser)
    #~ required_user_level = None
    label = _("Contact for")
    master_key = 'person'
    column_names = 'company type *'
    auto_fit_column_widths = True
    hidden_columns = 'id'


dd.inject_field(
    'system.SiteConfig', 'next_partner_id',
    models.IntegerField(
        default=PARTNER_NUMBERS_START_AT,
        blank=True,
        null=True,
        verbose_name=_("Next partner id"),
        help_text=_("The next automatic id for any new partner.")))

dd.inject_field(
    'system.SiteConfig', 'site_company',
    models.ForeignKey("contacts.Company",
                      blank=True,
                      null=True,
                      verbose_name=_("Site owner"),
                      related_name='site_company_sites',
                      help_text=_("""The organisation who runs this site.
        This is used e.g. as sender in documents.
        Or, newly created partners inherit the country of the site owner.
        """)))
Example #32
0
        ses = qs.first()
        if ses is None:
            if obj.fixed_since is not None:
                if fix:
                    obj.fixed_since = None
                    obj.full_clean()
                    obj.save()
                yield (True, _("No fixing session but marked as fixed"))
        else:
            if obj.fixed_since is None:
                if fix:
                    obj.fixed_since = ses.get_datetime('end')
                    obj.full_clean()
                    obj.save()
                yield (True, _(
                    "Fixing session exists but ticket not marked as fixed"))

TicketSessionsChecker.activate()
    

# dd.inject_field(
#     'tickets.Project',
#     'reporting_type', ReportingTypes.field(blank=True))

dd.inject_field(
    "users.User", 'open_session_on_new_ticket',
    models.BooleanField(_("Open session on new ticket"), default=False))


from .ui import *
Example #33
0
# will clear GuestStates

import lino.modlib.cal.workflows.feedback

add = GuestStates.add_item
add('44', _("Waiting"), 'waiting')
add('45', _("Busy"), 'busy')
add('46', _("Gone"), 'gone')

#~ add = GuestStates.add_item
#~ add('21', _("Waiting"),'waiting')

dd.inject_field(
    'cal.Guest', 'waiting_since',
    models.DateTimeField(
        _("Waiting since"),
        editable=False,
        blank=True,
        null=True,
        help_text=_("Time when the visitor arrived (checked in).")))
dd.inject_field(
    'cal.Guest', 'busy_since',
    models.DateTimeField(
        _("Waiting until"),
        editable=False,
        blank=True,
        null=True,
        help_text=_("Time when the visitor was received by agent.")))
dd.inject_field(
    'cal.Guest', 'gone_since',
    models.DateTimeField(
        _("Present until"),
Example #34
0
        ses = qs.first()
        if ses is None:
            if obj.fixed_since is not None:
                if fix:
                    obj.fixed_since = None
                    obj.full_clean()
                    obj.save()
                yield (True, _("No fixing session but marked as fixed"))
        else:
            if obj.fixed_since is None:
                if fix:
                    obj.fixed_since = ses.get_datetime('end')
                    obj.full_clean()
                    obj.save()
                yield (
                    True,
                    _("Fixing session exists but ticket not marked as fixed"))


TicketSessionsChecker.activate()

# dd.inject_field(
#     'tickets.Project',
#     'reporting_type', ReportingTypes.field(blank=True))

dd.inject_field(
    "users.User", 'open_session_on_new_ticket',
    models.BooleanField(_("Open session on new ticket"), default=False))

from .ui import *
Example #35
0
    update_auto_task(
        None,  # REMINDER,
        obj.user,
        reminder_date,
        summary, obj,
        done=reminder_done,
        alarm_value=delay_value,
        alarm_unit=delay2alarm(delay_type))


# Inject application-specific fields to users.User.
dd.inject_field(settings.SITE.user_model,
                'access_class',
                AccessClasses.field(
                    default=AccessClasses.public.as_callable,
                    verbose_name=_("Default access class"),
                    help_text=_(
            """The default access class for your calendar events and tasks.""")
                ))
dd.inject_field(settings.SITE.user_model,
                'event_type',
                models.ForeignKey('cal.EventType',
                                  blank=True, null=True,
                                  verbose_name=_("Default Event Type"),
        help_text=_("""The default event type for your calendar events.""")
                ))

dd.inject_field(
    'system.SiteConfig',
    'default_event_type',
    models.ForeignKey(
Example #36
0
            max_length=100,
            blank=True,
        )
        defaults.update(kw)
        models.CharField.__init__(self, *args, **defaults)

    def from_db_value(self, value, expression, connection, context):
        return CRL(hex2str(value)) if value else ''

    def to_python(self, value):
        if not value:
            return value
        if isinstance(value, CRL):
            return value
        return CRL(hex2str(value))

    def get_prep_value(self, value):
        if not value:
            return value
        assert isinstance(value, CRL)
        return str2hex(value)


dd.inject_field(countries.Place, 'crl', CrlField())
dd.inject_field(contacts.Person, 'crl', CrlField())
dd.inject_field(contacts.Person, 'died_date',
                models.DateField(
                    blank=True, null=True,
                    verbose_name=_("Died date")))
dd.inject_field(contacts.Company, 'crl', CrlField())
Example #37
0
        # of Django, not just inside a consumer.
        from channels import Group
        logger.info("Sending browser notification to %s", user.username)
        Group(groupname(user.username)).send({
            # WebSocket text frame, with JSON content
            "text": json.dumps(message),
        })

        return


dd.update_field(Message, 'user', verbose_name=_("Recipient"), editable=False)
# Message.update_controller_field(
#     null=True, blank=True, verbose_name=_("About"))

dd.inject_field('users.User', 'notify_myself',
                models.BooleanField(_('Notify myself'), default=False))

dd.inject_field('users.User', 'mail_mode',
                MailModes.field(default=MailModes.as_callable('often')))


class Messages(dd.Table):
    model = 'notify.Message'
    column_names = "created subject user seen sent *"
    # cell_edit = False

    # detail_layout = dd.DetailLayout("""
    # created user seen sent owner
    # overview
    # """, window_size=(50, 15))
Example #38
0
class Accounts(dd.Table):
    required_roles = dd.login_required(SepaStaff)
    model = 'sepa.Account'


class AccountsByPartner(Accounts):
    """Show the bank account(s) defined for a given partner. To be
    included to a detail window on partner.

    """
    required_roles = dd.login_required((ContactsUser, SepaUser))
    master_key = 'partner'
    column_names = 'iban bic remark primary *'
    order_by = ['iban']
    stay_in_grid = True
    auto_fit_column_widths = True
    insert_layout = """
    iban bic
    remark
    """

dd.inject_field(
    'ledger.Journal',
    'sepa_account',
    dd.ForeignKey('sepa.Account',
        blank=True, null=True,
        help_text=_("Your bank account to specify in payment order.")))


    
Example #39
0
    #~ def setup_handle(self,lh):
        #~ lh.config.label = _("Site Parameters")
        #~ lh.about.label = _("About")

class SiteConfigs(dd.Table):

    """
    The table used to present the :class:`SiteConfig` row in a Detail form.
    See also :meth:`lino.Lino.get_site_config`.
    Deserves more documentation.
    """
    model = 'system.SiteConfig'
    required_roles = dd.required(SiteStaff)
    default_action = actions.ShowDetailAction()
    #~ has_navigator = False
    hide_top_toolbar = True
    #~ can_delete = perms.never
    detail_layout = """
    default_build_method
    # lino.ModelsBySite
    """

    do_build = BuildSiteCache()


if settings.SITE.user_model == 'auth.User':
    dd.inject_field(settings.SITE.user_model,
                    'profile', UserProfiles.field())
    dd.inject_field(settings.SITE.user_model, 'language', dd.LanguageField())

Example #40
0
VoucherTypes.add_item_lazy(InvoicesByJournal)

class PrintableInvoicesByJournal(PrintableByJournal, Invoices):
    label = _("Purchase journal (analytic)")



class ItemsByInvoice(ItemsByVoucher):
    model = 'ana.InvoiceItem'
    column_names = "account title ana_account vat_class total_base total_vat total_incl *"
    display_mode = 'grid'



dd.inject_field(
    'ledger.Movement', 'ana_account',
    dd.ForeignKey('ana.Account', blank=True, null=True))

dd.inject_field(
    'ledger.Account', 'ana_account',
    dd.ForeignKey('ana.Account', blank=True, null=True))

dd.inject_field(
    'ledger.Account', 'needs_ana',
    models.BooleanField(_("Needs analytical account"), default=False))

# if dd.is_installed('vat'):

#     dd.inject_field(
#         'vat.InvoiceItem', 'ana_account',
#         dd.ForeignKey('ana.Account', blank=True, null=True))
Example #41
0
        # Websocket. Note how you can send to a channel or Group from any part
        # of Django, not just inside a consumer.
        from channels import Group
        Group(user.username).send({
            # WebSocket text frame, with JSON content
            "text": json.dumps(message),
        })

        return


dd.update_field(Message, 'user', verbose_name=_("Recipient"), editable=False)
# Message.update_controller_field(
#     null=True, blank=True, verbose_name=_("About"))

dd.inject_field('users.User', 'notify_myself',
                models.BooleanField(_('Notify myself'), default=False))

dd.inject_field(
    'users.User', 'mail_mode',
    MailModes.field(_('Email notification mode'),
                    default=MailModes.often.as_callable))


class Messages(dd.Table):
    "Base for all tables of messages."
    model = 'notify.Message'
    column_names = "created subject user seen sent *"

    # detail_layout = dd.DetailLayout("""
    # created user seen sent owner
    # overview
Example #42
0
    it in VatRegime, not per voucher.

    """

    def set_default_item_vat(sender, instance=None, **kwargs):
        instance.item_vat = settings.SITE.get_item_vat(instance)
        # print("20130902 set_default_item_vat", instance)

    @dd.receiver(dd.post_analyze)
    def on_post_analyze(sender, **kw):
        for m in rt.models_by_base(VatDocument):
            dd.post_init.connect(set_default_item_vat, sender=m)
            # print('20130902 on_post_analyze installed receiver for',m)


dd.inject_field(
    'contacts.Partner', 'vat_regime', VatRegimes.field(blank=True))


def get_vat_regime_choices(country=None, vat_id=None):
    vat_area = VatAreas.get_for_country(country)
    # print("20190405", vat_area)
    for r in VatRegimes.get_list_items():
        if vat_area is None or r.vat_area is None or r.vat_area == vat_area:
            if vat_id or not r.needs_vat_id:
                yield r

@dd.chooser()
def partner_vat_regime_choices(cls, country, vat_id):
    return get_vat_regime_choices(country, vat_id)

Example #43
0
# Copyright 2012-2019 Rumma & Ko Ltd
# License: BSD (see file COPYING for details)

from lino.api import dd, _

from lino_xl.lib.vat.mixins import VatDeclaration

from .choicelists import DeclarationFields

DEMO_JOURNAL_NAME = "VAT"

# print("20170711a {}".format(DeclarationFields.get_list_items()))

class Declaration(VatDeclaration):

    fields_list = DeclarationFields

    class Meta:
        app_label = 'eevat'
        verbose_name = _("Estonian VAT declaration")
        verbose_name_plural = _("Estonian VAT declarations")


for fld in DeclarationFields.get_list_items():
    dd.inject_field('eevat.Declaration', fld.name, fld.get_model_field())
Example #44
0
    fields_list = DeclarationFields
    
    class Meta:
        app_label = 'eevat'
        verbose_name = _("Estonian VAT declaration")
        verbose_name_plural = _("Estonian VAT declarations")
        
# if dd.is_installed('declarations'): # avoid autodoc failure
#     # importing the country module will fill DeclarationFields
#     import_module(dd.plugins.declarations.country_module)

from lino_xl.lib.vat.mixins import DECLARED_IN

if DECLARED_IN:
    dd.inject_field('ledger.Voucher',
                    'declared_in',
                    dd.ForeignKey(Declaration,
                                  blank=True, null=True))

# dd.inject_field('ledger.Account',
#                 'declaration_field',
#                 DeclarationFields.field(blank=True, null=True))

# dd.inject_field('ledger.Journal',
#                 'declared',
#                 models.BooleanField(default=True))

for fld in DeclarationFields.get_list_items():
    dd.inject_field('eevat.Declaration', fld.name, fld.get_model_field())

Example #45
0
        # return str(ar)
        return tostring(e)

    sender.kernel.memo_parser.register_django_model(
        'order', Order,
        cmd=cmd,
        # title=lambda obj: obj.name
    )

# class OrderItem(ProductDocItem, SequencedVoucherItem):
class OrderItem(SequencedVoucherItem):
    class Meta:
        app_label = 'orders'
        abstract = dd.is_abstract_model(__name__, 'OrderItem')
        verbose_name = _("Order item")
        verbose_name_plural = _("Order items")

    allow_cascaded_delete = 'voucher'

    voucher = dd.ForeignKey('orders.Order', related_name='items')
    # title = models.CharField(_("Heading"), max_length=200, blank=True)
    product = dd.ForeignKey('products.Product', blank=True, null=True)
    qty = dd.QuantityField(_("Quantity"), blank=True, null=True)
    # unit_price = dd.PriceField(_("Unit price"), blank=True, null=True)
    remark = models.CharField(_("Remark"), max_length=200, blank=True)



dd.inject_field('ledger.Journal', 'room', dd.ForeignKey('cal.Room', blank=True, null=True))

from .ui import *
Example #46
0
def inject_subsidization_fields(sender, **kw):
    for sub in Subsidizations.items():
        dd.inject_field(
            'art61.Contract', sub.contract_field_name(),
            models.BooleanField(verbose_name=sub.text, default=False))
Example #47
0
    journal = JournalRef()

    @dd.chooser()
    def unused_account_choices(self, journal):
        # would be nice, but doesn't work because matchrules are
        # usually entered via MatchRulesByJournal where journal is
        # always None.
        if journal:
            fkw = {journal.trade_type.name + '_allowed': True}
            return rt.modules.accounts.Account.objects.filter(**fkw)
        print("20151221 journal is None")
        return []


for tt in TradeTypes.objects():
    dd.inject_field('accounts.Account', tt.name + '_allowed',
                    models.BooleanField(verbose_name=tt.text, default=False))

dd.inject_field(
    'contacts.Partner', 'payment_term',
    models.ForeignKey('ledger.PaymentTerm',
                      blank=True,
                      null=True,
                      help_text=_("The default payment term for "
                                  "sales invoices to this customer.")))


class VoucherChecker(Checker):
    "Check for wrong ledger movements"
    verbose_name = _("Check integrity of ledger movements")
    messages = dict(
        missing=_("Missing movement {0}."),
Example #48
0
def set_upload_shortcuts(sender, **kw):
    """This is the successor for `quick_upload_buttons`."""

    # remember that models might have been overridden.
    UploadType = sender.modules.uploads.UploadType

    for i in Shortcuts.items():

        def f(obj, ar):
            if obj is None or ar is None:
                return E.div()
            try:
                utype = UploadType.objects.get(shortcut=i)
            except UploadType.DoesNotExist:
                return E.div()
            items = []
            target = sender.modules.resolve(i.target)
            sar = ar.spawn_request(actor=target,
                                   master_instance=obj,
                                   known_values=dict(type=utype))
            # param_values=dict(pupload_type=et))
            n = sar.get_total_count()
            if n == 0:
                iar = target.insert_action.request_from(sar,
                                                        master_instance=obj)
                btn = iar.ar2button(
                    None,
                    _("Upload"),
                    icon_name="page_add",
                    title=_("Upload a file from your PC to the server."))
                items.append(btn)
            elif n == 1:
                after_show = ar.get_status()
                obj = sar.data_iterator[0]
                items.append(
                    sar.renderer.href_button(dd.build_media_url(obj.file.name),
                                             _("show"),
                                             target='_blank',
                                             icon_name='page_go',
                                             style="vertical-align:-30%;",
                                             title=_(
                                                 "Open the uploaded file in a "
                                                 "new browser window")))
                after_show.update(record_id=obj.pk)
                items.append(
                    sar.window_action_button(
                        sar.ah.actor.detail_action,
                        after_show,
                        _("Edit"),
                        icon_name='application_form',
                        title=_("Edit metadata of the uploaded file.")))
            else:
                obj = sar.sliced_data_iterator[0]
                items.append(
                    ar.obj2html(obj, pgettext("uploaded file", "Last")))

                btn = sar.renderer.action_button(obj,
                                                 sar,
                                                 sar.bound_action,
                                                 _("All {0} files").format(n),
                                                 icon_name=None)
                items.append(btn)

            return E.div(*join_elems(items, ', '))

        vf = dd.VirtualField(dd.DisplayField(i.text), f)
        dd.inject_field(i.model_spec, i.name, vf)
Example #49
0
            verbose_name=_("Label"),
            max_length=100,
            blank=True,
        )
        defaults.update(kw)
        models.CharField.__init__(self, *args, **defaults)

    def from_db_value(self, value, expression, connection, context=None):
        return CRL(hex2str(value)) if value else ''

    def to_python(self, value):
        if not value:
            return value
        if isinstance(value, CRL):
            return value
        return CRL(hex2str(value))

    def get_prep_value(self, value):
        if not value:
            return value
        assert isinstance(value, CRL)
        return str2hex(value)


dd.inject_field(countries.Place, 'crl', CrlField())
dd.inject_field(contacts.Person, 'crl', CrlField())
dd.inject_field(
    contacts.Person, 'died_date',
    models.DateField(blank=True, null=True, verbose_name=_("Died date")))
dd.inject_field(contacts.Company, 'crl', CrlField())
Example #50
0
    update_auto_task(
        None,  # REMINDER,
        obj.user,
        reminder_date,
        summary, obj,
        done=reminder_done,
        alarm_value=delay_value,
        alarm_unit=delay2alarm(delay_type))


# Inject application-specific fields to users.User.
dd.inject_field(settings.SITE.user_model,
                'access_class',
                AccessClasses.field(
                    default=AccessClasses.as_callable('public'),
                    verbose_name=_("Default access class"),
                    help_text=_(
            """The default access class for your calendar events and tasks.""")
                ))
dd.inject_field(settings.SITE.user_model,
                'event_type',
                dd.ForeignKey('cal.EventType',
                                  blank=True, null=True,
                                  verbose_name=_("Default Event Type"),
        help_text=_("""The default event type for your calendar events.""")
                ))

dd.inject_field(
    'system.SiteConfig',
    'default_event_type',
    dd.ForeignKey(
Example #51
0
        adapt the `actor` of this Entry by making it an actor of the
        new Budget.
        
        TODO: this method relies on the fact that related Actors get
        duplicated *before* related Entries.  The order of `fklist` in
        `_lino_ddh`

        """
        if master is not None and self.actor is not None and self.actor.budget != master:
            self.actor = master.actor_set.get(seqno=self.actor.seqno)
        super(Entry, self).on_duplicate(ar, master)


dd.inject_field(
    'pcsw.ClientContactType',
    'is_bailiff',
    models.BooleanField(
        _("Debt collection agency"), default=False))

# dd.inject_field(
#     'system.SiteConfig',
#     'debts_bailiff_type',
#     models.ForeignKey("pcsw.ClientContactType",
#                       blank=True, null=True,
#                       verbose_name=_("Bailiff"),
#                       related_name='bailiff_type_sites',
#                       help_text=_("Client contact type for Bailiff.")))

dd.inject_field(
    'system.SiteConfig',
    'master_budget',
Example #52
0
        verbose_name_plural = _("Teams")
        abstract = dd.is_abstract_model(__name__, 'Team')


class Teams(dd.Table):
    model = 'teams.Team'
    required_roles = dd.login_required(dd.SiteStaff)
    column_names = 'ref name *'
    order_by = ["ref", "name"]

    insert_layout = """
    ref
    name
    """

    detail_layout = """
    id ref name 
    teams.UsersByTeam
    """


dd.inject_field(
    'users.User', 'team',
    dd.ForeignKey('teams.Team', blank=True, null=True))


from lino.modlib.users.desktop import Users

class UsersByTeam(Users):
    master_key = 'team'
Example #53
0
    column_names = "selected partner preview amount invoice_button *"


class InvoicingsByGenerator(dd.Table):
    required_roles = dd.login_required(LedgerUser)
    model = dd.plugins.invoicing.item_model
    label = _("Invoicings")
    master_key = 'invoiceable'
    editable = False
    column_names = "voucher qty title description:20x1 #discount " \
                   "unit_price total_incl #total_base #total_vat *"


invoiceable_label = dd.plugins.invoicing.invoiceable_label

dd.inject_field('products.Product', 'tariff',
                dd.ForeignKey('invoicing.Tariff', blank=True, null=True))

dd.inject_field(dd.plugins.invoicing.voucher_model, 'invoicing_min_date',
                dd.DateField(_("Invoiceables from"), blank=True, null=True))
dd.inject_field(dd.plugins.invoicing.voucher_model, 'invoicing_max_date',
                dd.DateField(_("until"), blank=True, null=True))

dd.inject_field(
    dd.plugins.invoicing.item_model, 'invoiceable_type',
    dd.ForeignKey(ContentType,
                  blank=True,
                  null=True,
                  verbose_name=format_lazy(u"{} {}", invoiceable_label,
                                           _('(type)'))))
dd.inject_field(
    dd.plugins.invoicing.item_model, 'invoiceable_id',
Example #54
0
        return tostring(e)

    sender.plugins.memo.parser.register_django_model(
        'order', Order,
        cmd=cmd,
        # title=lambda obj: obj.name
    )

# class OrderItem(ProductDocItem, SequencedVoucherItem):
class OrderItem(SequencedVoucherItem):
    class Meta:
        app_label = 'orders'
        abstract = dd.is_abstract_model(__name__, 'OrderItem')
        verbose_name = _("Order item")
        verbose_name_plural = _("Order items")

    allow_cascaded_delete = 'voucher'

    voucher = dd.ForeignKey('orders.Order', related_name='items')
    # title = models.CharField(_("Heading"), max_length=200, blank=True)
    product = dd.ForeignKey('products.Product', blank=True, null=True)
    qty = dd.QuantityField(_("Quantity"), blank=True, null=True)
    # unit_price = dd.PriceField(_("Unit price"), blank=True, null=True)
    remark = models.CharField(_("Remark"), max_length=200, blank=True)



dd.inject_field('ledger.Journal', 'room', dd.ForeignKey('cal.Room', blank=True, null=True))

from .ui import *
Example #55
0
    VatDocument.  The following trick worked...  but best is to store
    it in VatRegime, not per voucher.

    """
    def set_default_item_vat(sender, instance=None, **kwargs):
        instance.item_vat = settings.SITE.get_item_vat(instance)
        # print("20130902 set_default_item_vat", instance)

    @dd.receiver(dd.post_analyze)
    def on_post_analyze(sender, **kw):
        for m in rt.models_by_base(VatDocument):
            dd.post_init.connect(set_default_item_vat, sender=m)
            # print('20130902 on_post_analyze installed receiver for',m)


dd.inject_field('contacts.Partner', 'vat_regime', VatRegimes.field(blank=True))


def get_vat_regime_choices(country=None):
    vat_area = VatAreas.get_for_country(country)
    # print("20190405", vat_area)
    for r in VatRegimes.get_list_items():
        if vat_area is None or r.vat_area is None or r.vat_area == vat_area:
            yield r


@dd.chooser()
def partner_vat_regime_choices(cls, country):
    return get_vat_regime_choices(country)

Example #56
0
# GuestStates.excused.add_transition(
#     required_states='invited accepted absent gone')
# GuestStates.absent.add_transition(
#     required_states='invited accepted excused gone')
# GuestStates.present.add_transition(
#     required_states='invited accepted gone')

#~ add = GuestStates.add_item
#~ add('21', _("Waiting"),'waiting')

# We inject three fields to cal.Guest.
# Documentation and help_text are in book/docs/specs/cal.rst
dd.inject_field(
    'cal.Guest', 'waiting_since',
    models.DateTimeField(_("Waiting since"),
                         editable=False,
                         blank=True,
                         null=True))
dd.inject_field(
    'cal.Guest', 'busy_since',
    models.DateTimeField(_("Waiting until"),
                         editable=False,
                         blank=True,
                         null=True))
dd.inject_field(
    'cal.Guest', 'gone_since',
    models.DateTimeField(_("Present until"),
                         editable=False,
                         blank=True,
                         null=True))
Example #57
0
def set_upload_shortcuts(sender, **kw):
    """This is the successor for `quick_upload_buttons`."""

    # remember that models might have been overridden.
    UploadType = sender.modules.uploads.UploadType

    for i in list(Shortcuts.items()):

        def f(obj, ar):
            if obj is None or ar is None:
                return E.div()
            try:
                utype = UploadType.objects.get(shortcut=i)
            except UploadType.DoesNotExist:
                return E.div()
            items = []
            target = sender.modules.resolve(i.target)
            sar = ar.spawn_request(
                actor=target,
                master_instance=obj,
                known_values=dict(type=utype))
                # param_values=dict(pupload_type=et))
            n = sar.get_total_count()
            if n == 0:
                iar = target.insert_action.request_from(
                    sar, master_instance=obj)
                btn = iar.ar2button(
                    None, _("Upload"), icon_name="page_add",
                    title=_("Upload a file from your PC to the server."))
                items.append(btn)
            elif n == 1:
                after_show = ar.get_status()
                obj = sar.data_iterator[0]
                items.append(sar.renderer.href_button(
                    dd.build_media_url(obj.file.name),
                    _("show"),
                    target='_blank',
                    icon_name='page_go',
                    style="vertical-align:-30%;",
                    title=_("Open the uploaded file in a "
                            "new browser window")))
                after_show.update(record_id=obj.pk)
                items.append(sar.window_action_button(
                    sar.ah.actor.detail_action,
                    after_show,
                    _("Edit"), icon_name='application_form',
                    title=_("Edit metadata of the uploaded file.")))
            else:
                obj = sar.sliced_data_iterator[0]
                items.append(ar.obj2html(
                    obj, pgettext("uploaded file", "Last")))

                btn = sar.renderer.action_button(
                    obj, sar, sar.bound_action,
                    _("All {0} files").format(n),
                    icon_name=None)
                items.append(btn)

            return E.div(*join_elems(items, ', '))

        vf = dd.VirtualField(dd.DisplayField(i.text), f)
        dd.inject_field(i.model_spec, i.name, vf)
Example #58
0
    required_roles = dd.login_required(IntegrationStaff)
    model = 'active_job_search.Proof'
    detail_layout = """
    date client company id
    spontaneous response
    remarks
    """


class ProofsByClient(Proofs):
    required_roles = dd.login_required(IntegrationAgent)
    master_key = 'client'
    column_names = "date company spontaneous response *"
    auto_fit_column_widths = True


dd.inject_field(
    'pcsw.Client', 'geographic_area',
    models.CharField(
        _("Geographic area"), blank=True, max_length=200,
        help_text=_(
            "The area for which we are seeking a job.")))

dd.inject_field(
    'pcsw.Client', 'child_custody',
    models.TextField(
        _("Child custody"), blank=True,
        help_text=_("Notes concerning child custody.")))


Example #59
0
class RolesByPerson(Roles):
    """Shows all roles of a person."""
    required_roles = dd.required(SimpleContactsUser)
    #~ required_user_level = None
    label = _("Contact for")
    master_key = 'person'
    column_names = 'company type *'
    auto_fit_column_widths = True
    hidden_columns = 'id'


dd.inject_field(
    'system.SiteConfig', 'next_partner_id',
    models.IntegerField(
        default=PARTNER_NUMBERS_START_AT,
        blank=True,
        null=True,
        verbose_name=_("Next partner id"),
        help_text=_("The next automatic id for any new partner.")))


def site_setup(site):

    site.modules.countries.Places.set_detail_layout("""
    name country
    type parent zip_code id
    PlacesByPlace
    contacts.PartnersByCity
    """)

Example #60
0
def set_excerpts_actions(sender, **kw):
    """Installs (1) print management actions on models for which there is
    an excerpt type and (2) the excerpt shortcut fields defined in
    :class:`lino_xl.lib.excerpts.choicelists.Shortcuts`.

    """
    # logger.info("20140401 %s.set_attest_actions()", __name__)

    # in case ExcerptType is overridden
    ExcerptType = sender.modules.excerpts.ExcerptType
    Excerpt = sender.modules.excerpts.Excerpt

    try:
        etypes = [(obj, obj.content_type) for obj in ExcerptType.objects.all()]
    except (OperationalError, ProgrammingError, UnresolvedChoice) as e:
        dd.logger.debug("Failed to set excerpts actions : %s", e)
        # Happens e.g. when the database has not yet been migrated
        etypes = []

    for atype, ct in etypes:
        if ct is not None:
            m = ct.model_class()
            if m is not None:  # e.g. database contains types for
                # models that existed before but have
                # been removed
                an = atype.get_action_name()
                m.define_action(
                    **{an: CreateExcerpt(atype, six.text_type(atype))})
                # dd.logger.info("Added print action to %s", m)

                # if atype.certifying and not issubclass(m, Certifiable):
                #     m.define_action(
                #         clear_printed=ClearCache())

    # An attestable model must also inherit
    # :class:`lino.mixins.printable.BasePrintable` or some subclass
    # thereof.

    for i in Shortcuts.items():

        def f(obj, ar):
            if ar is None:
                return ''
            if obj is None:
                return E.div()
            try:
                et = ExcerptType.objects.get(shortcut=i)
            except ExcerptType.DoesNotExist:
                return E.div()
            items = []
            if True:
                sar = ar.spawn(ExcerptsByOwner,
                               master_instance=obj,
                               param_values=dict(excerpt_type=et))
                n = sar.get_total_count()
                if n > 0:
                    ex = sar.sliced_data_iterator[0]
                    items.append(ar.obj2html(ex, _("Last")))

                    ba = sar.bound_action
                    btn = sar.renderer.action_button(obj,
                                                     sar,
                                                     ba,
                                                     "%s (%d)" % (_("All"), n),
                                                     icon_name=None)
                    items.append(btn)

                ia = getattr(obj, et.get_action_name())
                btn = ar.instance_action_button(ia,
                                                _("Create"),
                                                icon_name=None)
                items.append(btn)

            else:
                ot = ContentType.objects.get_for_model(obj.__class__)
                qs = Excerpt.objects.filter(owner_id=obj.pk,
                                            owner_type=ot,
                                            excerpt_type=et)
                if qs.count() > 0:
                    ex = qs[0]
                    txt = ExcerptsByOwner.format_excerpt(ex)
                    items.append(ar.obj2html(ex, txt))
            return E.div(*join_elems(items, ', '))

        vf = dd.VirtualField(dd.DisplayField(i.text), f)
        dd.inject_field(i.model_spec, i.name, vf)