예제 #1
0
class Meetings(dd.Table):
    """Base table for all Meetings.
    """
    required_roles = dd.login_required((OfficeUser,))
    model = 'meetings.Meeting'
    detail_layout = MeetingDetail()
    insert_layout = dd.InsertLayout("""name
    ref room
    start_date
    """, window_size = (40, 10,))
    column_names = "start_date name ref site room workflow_buttons *"
    # order_by = ['start_date']
    # order_by = 'line__name room__name start_date'.split()
    # order_by = ['name']
    order_by = ['-start_date', '-start_time']
    auto_fit_column_widths = True


    parameters = mixins.ObservedDateRange(
        user=dd.ForeignKey(
            settings.SITE.user_model,
            blank=True, null=True),
        show_active=dd.YesNo.field(
            _("Active"), blank=True,
            help_text=_("Whether to show rows in some active state")),
        state=MeetingStates.field(blank=True),
        member=dd.ForeignKey(dd.resolve_model('contacts.Partner'),
            verbose_name=_("Member"), blank=True,
            help_text=_("Show rows that this person is a member")),
    )
    params_layout = """user room state show_active member
    start_date end_date """

    # simple_parameters = 'line teacher state user'.split()

    @classmethod
    def get_request_queryset(self, ar, **kwargs):
        # dd.logger.info("20160223 %s", self)
        qs = super(Meetings, self).get_request_queryset(ar, **kwargs)
        if isinstance(qs, list):
            return qs
        pv = ar.param_values

        qs = self.model.add_param_filter(
            qs, show_active=pv.show_active)

        if pv.state:
            qs = qs.filter(state=pv.state)

        if pv.member:
            sqs = rt.models.stars.Star.for_model('meetings.Meeting', user=pv.member)
            stared_ticket_ids = sqs.values_list('owner_id')
            qs = qs.filter(pk__in=stared_ticket_ids)

        if pv.start_date:
            # dd.logger.info("20160512 start_date is %r", pv.start_date)
            qs = PeriodEvents.started.add_filter(qs, pv)
            # qs = qs.filter(start_date__gte=pv.start_date)
        if pv.end_date:
            qs = PeriodEvents.ended.add_filter(qs, pv)
            # qs = qs.filter(end_date__lte=pv.end_date)
        # dd.logger.info("20160512 %s", qs.query)
        return qs
예제 #2
0
파일: models.py 프로젝트: DarioGT/lino
class Memo(dd.Model):
    owner_type = dd.ForeignKey(ContentType, blank=True, null=True)
    owner_id = models.PositiveIntegerField(blank=True, null=True)
    owner = dd.GenericForeignKey('owner_type', 'owner_id')

    text = models.CharField(max_length=200)
예제 #3
0
파일: ui.py 프로젝트: einarfelix/xl
class Days(dd.VirtualTable):
    # every row is a Day instance. Note that Day can be overridden.

    # required_roles = dd.login_required((OfficeUser, OfficeOperator))
    required_roles = dd.login_required(OfficeUser)
    column_names = "detail_link *"
    parameters = ObservedDateRange(
        user=dd.ForeignKey('users.User', null=True, blank=True))
    model = 'calview.Day'
    editable = False
    navigation_mode = "day"  # or "week" or "month"
    abstract = True

    @classmethod
    def get_navinfo(cls, ar, day):
        assert isinstance(day, Day)
        day.navigation_mode = ar.actor.navigation_mode  # so that str() gives the right formar
        ni = dict(recno=day.pk, message=str(day))

        if cls.navigation_mode == "month":
            ni.update(next=date2pk(day.skipmonth(1)))
            ni.update(prev=date2pk(day.skipmonth(-1)))
            ni.update(first=day.pk - 365)
            ni.update(last=day.pk + 365)
        elif cls.navigation_mode == "week":
            ni.update(next=day.pk + 7)
            ni.update(prev=day.pk - 7)
            ni.update(first=date2pk(day.skipmonth(-1)))
            ni.update(last=date2pk(day.skipmonth(1)))
        elif cls.navigation_mode == "day":
            ni.update(next=day.pk + 1)
            ni.update(prev=day.pk - 1)
            ni.update(first=date2pk(day.skipmonth(-1)))
            ni.update(last=date2pk(day.skipmonth(1)))
        else:
            raise Exception("Invalid navigation_mode {}".format(
                cls.navigation_mode))
        return ni

    @dd.virtualfield(models.IntegerField(_("Day number")))
    def day_number(cls, obj, ar):
        return obj.pk

    @classmethod
    def get_pk_field(cls):
        # return pk_field
        # return PK_FIELD
        # return cls.get_data_elem('day_number')
        return cls.day_number.return_type

    @classmethod
    def get_row_by_pk(cls, ar, pk):
        """
        pk is the offset from beginning_of_time
        """
        #if pk is None:
        #    pk = "0"
        # return dd.today(int(pk))
        # if ar is None:
        #     return cls.model(int(pk))
        # return cls.model(int(pk), ar.actor.navigation_mode)
        return cls.model(int(pk), ar, cls.navigation_mode)

    @classmethod
    def get_request_queryset(cls, ar, **filter):
        home = cls.get_row_by_pk(ar, 0)
        ni = cls.get_navinfo(ar, home)

        pv = ar.param_values
        date = pv.start_date or dd.today(ni['first'])
        last = pv.end_date or dd.today(ni['last'])
        if cls.navigation_mode == "day":
            step = lambda x: x + timedelta(days=1)
        elif cls.navigation_mode == "week":
            step = lambda x: x + timedelta(days=7)
        else:
            step = lambda x: DurationUnits.months.add_duration(x, 1)

        while date <= last:
            yield cls.get_row_by_pk(ar, date2pk(date))
            date = step(date)
예제 #4
0
파일: models.py 프로젝트: einarfelix/xl
 def setup_parameters(cls, fields):
     fields.update(
         place=dd.ForeignKey('countries.Place', blank=True, null=True))
     super(Address, cls).setup_parameters(fields)
예제 #5
0
class Coaching(UserAuthored, mixins.DatePeriod, dd.ImportedFields,
               ChangeObservable):
    """A Coaching ("Begleitung" in German and "intervention" in French) is
    when a given client is being coached by a given user during a
    given period.  

    For example in :ref:`welfare` that used is a social assistant.

    """
    class Meta:
        app_label = 'coachings'
        verbose_name = _("Coaching")
        verbose_name_plural = _("Coachings")

    # user = models.ForeignKey(
    #     settings.SITE.user_model,
    #     verbose_name=_("Coach"),
    #     related_name="%(app_label)s_%(class)s_set_by_user",
    # )

    allow_cascaded_delete = ['client']
    workflow_state_field = 'state'

    client = dd.ForeignKey(client_model, related_name="coachings_by_client")
    type = dd.ForeignKey('coachings.CoachingType', blank=True, null=True)
    primary = models.BooleanField(
        _("Primary"),
        default=False,
        help_text=_("""There's at most one primary coach per client. \
        Enabling this field will automatically make the other \
        coachings non-primary."""))

    ending = models.ForeignKey('coachings.CoachingEnding',
                               related_name="%(app_label)s_%(class)s_set",
                               blank=True,
                               null=True)

    @classmethod
    def on_analyze(cls, site):
        super(Coaching, cls).on_analyze(site)
        cls.declare_imported_fields('''client user primary end_date''')

    @dd.chooser()
    def ending_choices(cls, type):
        qs = CoachingEnding.objects.filter(Q(type__isnull=True) | Q(type=type))
        return qs.order_by("seqno")

    def disabled_fields(self, ar):
        rv = super(Coaching, self).disabled_fields(ar)
        if settings.SITE.is_imported_partner(self.client):
            if self.primary:
                return self._imported_fields
            return set(['primary'])
        return rv

    def on_create(self, ar):
        """
        Default value for the `user` field is the requesting user.
        """
        if self.user_id is None:
            u = ar.get_user()
            if u is not None:
                self.user = u
        super(Coaching, self).on_create(ar)

    def disable_delete(self, ar=None):
        if ar is not None and settings.SITE.is_imported_partner(self.client):
            if self.primary:
                return _(
                    "Cannot delete companies and persons imported from TIM")
        return super(Coaching, self).disable_delete(ar)

    def before_ui_save(self, ar, **kw):
        #~ logger.info("20121011 before_ui_save %s",self)
        super(Coaching, self).before_ui_save(ar, **kw)
        if not self.type:
            self.type = ar.get_user().coaching_type
        if not self.start_date:
            self.start_date = settings.SITE.today()
        if self.ending and not self.end_date:
            self.end_date = settings.SITE.today()

    #~ def update_system_note(self,note):
    #~ note.project = self.client

    def __str__(self):
        #~ return _("Coaching of %(client)s by %(user)s") % dict(client=self.client,user=self.user)
        #~ return self.user.username+' / '+self.client.first_name+' '+self.client.last_name[0]
        cl = self.client
        if cl.first_name:
            return self.user.username + ' / ' + cl.last_name + ' ' + cl.first_name[
                0]
        return self.user.username + ' / ' + cl.last_name

    def after_ui_save(self, ar, cw):
        super(Coaching, self).after_ui_save(ar, cw)
        if self.primary:
            for c in self.client.coachings_by_client.exclude(id=self.id):
                if c.primary:
                    c.primary = False
                    c.save()
                    ar.set_response(refresh_all=True)
        #~ return kw

    #~ def get_row_permission(self,user,state,ba):
    #~ """
    #~ """
    #~ logger.info("20121011 get_row_permission %s %s",self,ba)
    #~ if isinstance(ba.action,actions.SubmitInsert):
    #~ if not user.coaching_type:
    #~ return False
    #~ return super(Coaching,self).get_row_permission(user,state,ba)

    def full_clean(self, *args, **kw):
        if not self.start_date and not self.end_date:
            self.start_date = settings.SITE.today()
        if not self.type and self.user:
            self.type = self.user.coaching_type
        super(Coaching, self).full_clean(*args, **kw)

    #~ def save(self,*args,**kw):
    #~ super(Coaching,self).save(*args,**kw)

    def summary_row(self, ar, **kw):
        return [ar.href_to(self.client), " (%s)" % self.state.text]

    # def get_related_project(self):
    #     return self.client

    def get_change_owner(self, ar):
        return self.client

    def get_change_observers(self):
        return self.client.get_change_observers()
예제 #6
0
파일: models.py 프로젝트: einarfelix/xl
    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 *
예제 #7
0
파일: models.py 프로젝트: einarfelix/xl
class Order(Certifiable, RegistrableVoucher, RecurrenceSet, EventGenerator,
            Duplicable, ProjectRelated):
    class Meta:
        app_label = 'orders'
        abstract = dd.is_abstract_model(__name__, 'Order')
        verbose_name = _("Order")
        verbose_name_plural = _('Orders')

    state = OrderStates.field(default='draft')

    # order_area = OrderAreas.field(default='default')
    # client = dd.ForeignKey(
    #     "presto.Client",
    #     related_name="%(app_label)s_%(class)s_set_by_client",
    #     blank=True, null=True)
    #
    invoice_recipient = dd.ForeignKey('contacts.Partner',
                                      verbose_name=_("Invoice recipient"),
                                      related_name='orders_by_recipient',
                                      blank=True,
                                      null=True)

    subject = models.CharField(_("Our reference"), max_length=200, blank=True)
    # site_field_name = 'room'

    # line = dd.ForeignKey('orders.Line')
    # event_type = dd.ForeignKey('cal.EventType', null=True, blank=True)
    # room = dd.ForeignKey('cal.Room', blank=True)
    description = dd.TextField(_("Description"), blank=True)
    remark = models.TextField(_("Remark"), blank=True)
    # entry_date = models.DateField(
    #     verbose_name=_("Entry date"))
    max_date = models.DateField(blank=True,
                                null=True,
                                verbose_name=_("Generate events until"))

    # order_state = OrderStates.field(default='draft')

    # quick_search_fields = 'name'

    # max_places = models.PositiveIntegerField(
    #     pgettext("in a order", "Available places"),
    #     help_text=("Maximum number of participants"),
    #     blank=True, null=True)
    #
    # name = models.CharField(_("Designation"), max_length=100, blank=True)
    # enrolments_until = models.DateField(
    #     _("Enrolments until"), blank=True, null=True)
    #
    # print_presence_sheet = PrintPresenceSheet(show_in_bbar=False)
    # print_presence_sheet_html = PrintPresenceSheet(
    #     show_in_bbar=False,
    #     build_method='weasy2html',
    #     label=format_lazy(u"{}{}",_("Presence sheet"), _(" (HTML)")))

    def full_clean(self, *args, **kwargs):
        if self.entry_date is None:
            self.entry_date = dd.today()
        super(Order, self).full_clean(*args, **kwargs)

    # @dd.displayfield(_("Print"))
    # def print_actions(self, ar):
    #     if ar is None:
    #         return ''
    #     elems = []
    #     elems.append(ar.instance_action_button(
    #         self.print_presence_sheet))
    #     elems.append(ar.instance_action_button(
    #         self.print_presence_sheet_html))
    #     return E.p(*join_elems(elems, sep=", "))

    # def on_duplicate(self, ar, master):
    #     self.state = OrderStates.draft
    #     super(Order, self).on_duplicate(ar, master)
    #
    def update_cal_until(self):
        return self.max_date

    def get_partner(self):
        if self.invoice_recipient is not None:
            return self.invoice_recipient
        if self.project is not None:
            return self.project.get_partner()

    def get_wanted_movements(self):
        return []

    # @classmethod
    # def add_param_filter(
    #         cls, qs, lookup_prefix='', show_exposed=None, **kwargs):
    #     qs = super(Order, cls).add_param_filter(qs, **kwargs)
    #     exposed_states = OrderStates.filter(is_exposed=True)
    #     fkw = dict()
    #     fkw[lookup_prefix + 'state__in'] = exposed_states
    #     if show_exposed == dd.YesNo.no:
    #         qs = qs.exclude(**fkw)
    #     elif show_exposed == dd.YesNo.yes:
    #         qs = qs.filter(**fkw)
    #     return qs

    @classmethod
    def get_registrable_fields(cls, site):
        for f in super(Order, cls).get_registrable_fields(site):
            yield f
        yield 'name'

    def update_cal_rset(self):
        return self

    def update_cal_from(self, ar):
        """Note: if recurrency is weekly or per_weekday, actual start may be
        later than self.start_date

        """
        # if self.state in (OrderStates.draft, OrderStates.cancelled):
        # if self.state == OrderStates.cancelled:
        #     ar.info("No start date because state is %s", self.state)
        #     return None
        return self.start_date

    def update_cal_event_type(self):
        if self.journal.room_id:
            return self.journal.room.event_type

    def update_cal_summary(self, et, i):
        if self.every_unit == Recurrencies.once:
            return str(self)
        return "%s %s" % (dd.babelattr(et, 'event_label'), i)

    # def get_events_user(self):
    #     """The user of generated events is not the order manager (author) but
    #     the teacher.
    #
    #     """
    #     if self.teacher:
    #         return self.teacher.get_as_user() or self.user
    #     return self.user

    def suggest_cal_guests(self, event):
        """Look up enrolments of this order and suggest them as guests."""
        # logger.info("20140314 suggest_guests")
        Enrolment = rt.models.orders.Enrolment
        qs = Enrolment.objects.filter(order=self).order_by('id')
        for obj in qs:
            # if obj.is_guest_for(event):
            g = obj.make_guest_for(event)
            if g is not None:
                yield g

    def before_auto_event_save(self, event):
        """
        Set room and start_time/end_time for automatic events.
        """
        assert not settings.SITE.loading_from_dump
        assert event.owner == self
        event.order = self
        event.room = self.journal.room
        event.start_time = self.start_time
        event.end_time = self.end_time
        super(Order, self).before_auto_event_save(event)

    @dd.displayfield(_("Calendar entries"))
    def events_text(self, ar=None):
        return ', '.join([
            day_and_month(e.start_date)
            for e in self.events_by_order().order_by('start_date')
        ])

    def events_by_order(self, **kwargs):
        ct = rt.models.contenttypes.ContentType.objects.get_for_model(
            self.__class__)
        kwargs.update(owner_type=ct, owner_id=self.id)
        return rt.models.cal.Event.objects.filter(**kwargs)

    @dd.requestfield(_("Enrolments"))
    def enrolments(self, ar):
        return self.get_enrolments()

    def get_enrolments(self, **pv):
        return rt.models.orders.EnrolmentsByOrder.request(self,
                                                          param_values=pv)
예제 #8
0
class ChatMessage(UserAuthored, Created, Previewable):
    class Meta(object):
        app_label = 'chat'
        verbose_name = _("Chat message")
        verbose_name_plural = _("Chat messages")
        ordering = ['created', 'id']

    # message_type = MessageTypes.field(default="change")

    seen = models.DateTimeField(_("seen"), null=True, editable=False)
    sent = models.DateTimeField(_("sent"), null=True, editable=False)
    group = dd.ForeignKey('chat.ChatGroup',
                          blank=True,
                          null=True,
                          verbose_name=_(u'Group'),
                          related_name="messages")
    hash = dd.CharField(_("Hash"), max_length=25, null=True, blank=True)

    # body = dd.RichTextField(_("Body"), editable=False, format='html')

    def __str__(self):
        return "{}: {}".format(self.user, self.body)

        # return _("About {0}").format(self.owner)

    # return self.message
    # return _("Notify {0} about change on {1}").format(
    #     self.user, self.owner)

    def send_global_message(self):
        # message = {
        #     "id": self.pk,
        #     # "subject": str(self.subject),
        #     "user": self.user,
        #     "body": html2text(self.body),
        #     "created": self.created.strftime("%a %d %b %Y %H:%M"),
        # }
        logger.info("Sending Message %s:#%s" % (self.user, self.pk))
        send_global_chat(self)
        # self.sent = timezone.now()
        # self.save()

    @classmethod
    def markAsSeen(Cls, data):
        group_id = data['body'][0]
        # msg_ids = [chat[3] for chat in data['body'][1]]
        ChatProps.objects.filter(chat__group__pk=group_id,
                                 user=data['user'],
                                 seen__isnull=True).update(seen=timezone.now())

    @classmethod
    def onRecive(Cls, data):
        print(data)
        args = dict(user=data['user'],
                    body=data['body']['body'],
                    group_id=data['body']['group_id'],
                    hash=data['body']['hash'])
        newMsg = Cls(**args)
        newMsg.full_clean()
        newMsg.save()
        newMsg.after_ui_create()
        newMsg.send_global_message()

    def after_ui_create(self, *args):
        for sub in self.group.ChatGroupsMembers.all().select_related("user"):
            props = ChatProps(chat=self, user=sub.user)
            props.full_clean()
            props.save()

        # super(ChatMessage, self).after_ui_save()

    @dd.action(_("ChatsMsg"))
    def getChats(self, ar):
        # return ar.success(rows=[])

        # doto, have work.
        last_ten_seen = ChatProps.objects.filter(seen__isnull=False).order_by(
            '-created').select_related("chat")[:10]
        unseen = ChatProps.objects.filter(
            user=ar.get_user(), chat=self,
            seen__isnull=True).order_by('-created').select_related("chat")

        last_ten_in_ascending_order = reversed(last_ten_seen)
        unseen_in_ascending_order = reversed(unseen)
        rows = [[(c.chat.user.username, ar.parse_memo(c.chat.body),
                  c.chat.created, c.seen, c.chat.pk, c.chat.user.id)
                 for c in last_ten_in_ascending_order],
                [(c.chat.user.username, ar.parse_memo(c.chat.body),
                  c.chat.created, c.seen, c.chat.pk, c.chat.user.id)
                 for c in unseen_in_ascending_order]]
        return ar.success(rows=rows)
예제 #9
0
파일: ui.py 프로젝트: TonisPiip/cosi
class ExpectedMovements(dd.VirtualTable):
    """
    A virtual table of :class:`DueMovement` rows, showing
    all "expected" "movements (payments)".

    Subclassed by :class:`lino_cosi.lib.finan.models.SuggestionsByVoucher`.


    """
    row_height = 4
    required_roles = dd.required(AccountingReader)
    label = _("Debts")
    icon_name = 'book_link'
    #~ column_names = 'match due_date debts payments balance'
    column_names = 'due_date:15 balance debts payments'
    auto_fit_column_widths = True
    # variable_row_height = True
    parameters = dd.ParameterPanel(
        date_until=models.DateField(_("Date until"), blank=True, null=True),
        trade_type=TradeTypes.field(blank=True),
        from_journal=dd.ForeignKey('ledger.Journal', blank=True),
        for_journal=dd.ForeignKey('ledger.Journal',
                                  blank=True,
                                  verbose_name=_("Clearable by")),
        account=dd.ForeignKey('accounts.Account', blank=True),
        partner=dd.ForeignKey('contacts.Partner', blank=True),
        project=dd.ForeignKey(dd.plugins.ledger.project_model, blank=True),
    )
    params_layout = "trade_type date_until from_journal " \
                    "for_journal project partner account"

    @classmethod
    def get_dc(cls, ar=None):
        return DEBIT

    @classmethod
    def get_data_rows(cls, ar, **flt):
        #~ if ar.param_values.journal:
        #~ pass
        pv = ar.param_values
        # if pv is None:
        #     raise Exception("No pv in %s" % ar)
        if pv.trade_type:
            flt.update(account=pv.trade_type.get_partner_account())
        if pv.partner:
            flt.update(partner=pv.partner)
        if pv.account:
            flt.update(account=pv.account)
        if pv.project:
            flt.update(project=pv.project)
        if pv.date_until is not None:
            flt.update(value_date__lte=pv.date_until)
        if pv.for_journal is not None:
            accounts = rt.modules.accounts.Account.objects.filter(
                matchrule__journal=pv.for_journal).distinct()
            flt.update(account__in=accounts)
        if pv.from_journal is not None:
            flt.update(voucher__journal=pv.from_journal)
        return get_due_movements(cls.get_dc(ar), **flt)

    @classmethod
    def get_pk_field(self):
        return rt.modules.ledger.Movement._meta.pk

    @classmethod
    def get_row_by_pk(cls, ar, pk):
        # for i in ar.data_iterator:
        #     if i.id == pk:
        #         return i
        # raise Exception("Not found: %s in %s" % (pk, ar))
        mvt = rt.modules.ledger.Movement.objects.get(pk=pk)
        dm = DueMovement(cls.get_dc(ar), mvt)
        dm.collect_all()
        return dm

    @dd.displayfield(_("Info"))
    def info(self, row, ar):
        elems = []
        if row.project:
            elems.append(ar.obj2html(row.project))
        if row.partner:
            elems.append(ar.obj2html(row.partner))
            # elems.append(row.partner.address)
        if row.bank_account:
            elems.append(ar.obj2html(row.bank_account))
        if row.account:
            elems.append(ar.obj2html(row.account))
        # return E.span(*join_elems(elems, ' / '))
        return E.span(*join_elems(elems, E.br))
        # return E.span(*elems)

    @dd.displayfield(_("Match"))
    def match(self, row, ar):
        return row.match

    @dd.virtualfield(
        models.DateField(
            _("Due date"),
            help_text=_("Due date of the eldest debt in this match group")))
    def due_date(self, row, ar):
        return row.due_date

    @dd.displayfield(_("Debts"),
                     help_text=_("List of invoices in this match group"))
    def debts(self, row, ar):
        return E.span(*join_elems([  # E.p(...) until 20150128
            ar.obj2html(i.voucher.get_mti_leaf()) for i in row.debts
        ]))

    @dd.displayfield(_("Payments"),
                     help_text=_("List of payments in this match group"))
    def payments(self, row, ar):
        return E.span(*join_elems([  # E.p(...) until 20150128
            ar.obj2html(i.voucher.get_mti_leaf()) for i in row.payments
        ]))

    @dd.virtualfield(dd.PriceField(_("Balance")))
    def balance(self, row, ar):
        return row.balance

    @dd.virtualfield(dd.ForeignKey('contacts.Partner'))
    def partner(self, row, ar):
        return row.partner

    @dd.virtualfield(dd.ForeignKey(dd.plugins.ledger.project_model))
    def project(self, row, ar):
        return row.project

    @dd.virtualfield(dd.ForeignKey('accounts.Account'))
    def account(self, row, ar):
        return row.account

    @dd.virtualfield(
        dd.ForeignKey('sepa.Account', verbose_name=_("Bank account")))
    def bank_account(self, row, ar):
        return row.bank_account
예제 #10
0
class Controllable(dd.Model):
    """Mixin for models that are "controllable" by another database object.

    Defines three fields :attr:`owned_type`, :attr:`owned_id` and
    :attr:`owned`. And a class attribute :attr:`owner_label`.

    For example in :mod:`lino.modlibs.cal`, the owner of a Task or Event
    is some other database object that caused the task's or event's
    creation.

    Or in :mod:`lino.modlib.sales` and :mod:`lino.modlib.purchases`,
    an invoice may cause one or several Tasks to be automatically generated
    when a certain payment mode is specified.

    Controllable objects are "governed" or "controlled" by their
    controller (stored in a field called :attr:`owner`): If the
    controller gets modified, it may decide to delete or modify some
    or all of her controlled objects.

    Non-automatic tasks always have an empty :attr:`owner` field.
    Some fields are read-only on an automatic Task because it makes no
    sense to modify them.

    .. attribute:: owner
    .. attribute:: owner_id
    .. attribute:: owner_type

    """
    # Translators: will also be concatenated with '(type)' '(object)'
    owner_label = _('Controlled by')
    """The labels (`verbose_name`) of the fields `owned_type`, `owned_id`
    and `owned` are derived from this attribute which may be overridden by
    subclasses. """

    controller_is_optional = True
    """Whether the controller is optional (i.e. whether the :attr:`owner`
    field may be NULL)

    """
    class Meta:
        abstract = True

    owner_type = dd.ForeignKey(ContentType,
                               editable=True,
                               blank=controller_is_optional,
                               null=controller_is_optional,
                               verbose_name=string_concat(
                                   owner_label, ' ', _('(type)')))

    owner_id = dd.GenericForeignKeyIdField(owner_type,
                                           editable=True,
                                           blank=controller_is_optional,
                                           null=controller_is_optional,
                                           verbose_name=string_concat(
                                               owner_label, ' ',
                                               _('(object)')))

    owner = dd.GenericForeignKey('owner_type',
                                 'owner_id',
                                 verbose_name=owner_label)

    def update_owned_instance(self, controllable):
        """If this (acting as a controller) is itself controlled, forward the
        call to the controller.

        """
        if self.owner:
            self.owner.update_owned_instance(controllable)
        super(Controllable, self).update_owned_instance(controllable)

    def save(self, *args, **kw):
        if settings.SITE.loading_from_dump:
            super(Controllable, self).save(*args, **kw)
        else:
            if self.owner:
                self.owner.update_owned_instance(self)
            super(Controllable, self).save(*args, **kw)
            if self.owner:
                self.owner.after_update_owned_instance(self)
예제 #11
0
파일: models.py 프로젝트: DarioGT/lino
class Address(AddressLocation):
    """Inherits fields from
    :class:`lino.modlib.countries.CountryRegionCity` (country, region,
    city. zip_code) and :class:`lino.modlib.contacts.AddresssLocation`
    (street, street_no, ...)

    .. attribute:: partner

    .. attribute:: address_type

    .. attribute:: data_source
    
        Pointer to :class:`choicelists.DataSources`.

        Specifies how this information entered into our database.

    .. attribute:: primary
    
        Whether this address is the primary address of its owner.
        Setting this field will automatically uncheck any previousl
        primary addresses and update the owner's address fields.

    """

    class Meta:
        verbose_name = _("Address")
        verbose_name_plural = _("Addresses")

    data_source = DataSources.field(
        editable=False,
        default=DataSources.manually.as_callable)
    # address_type = AddressTypes.field(blank=True, null=True)
    address_type = AddressTypes.field(
        default=AddressTypes.official.as_callable)
    partner = dd.ForeignKey(
        'contacts.Partner',
        related_name='addresses_by_partner')
    remark = dd.CharField(_("Remark"), max_length=50, blank=True)

    primary = models.BooleanField(
        _("Primary"),
        default=False,
        help_text=_(
            "Checking this field will automatically uncheck any "
            "previous primary addresses and update "
            "the partner's address data fields."))

    allow_cascaded_delete = ['partner']

    def __unicode__(self):
        return self.address_location(', ')

    def after_ui_save(self, ar, cw):
        super(Address, self).after_ui_save(ar, cw)
        mi = self.partner
        if mi is None:
            return
        if self.primary:
            for o in mi.addresses_by_partner.exclude(id=self.id):
                if o.primary:
                    o.primary = False
                    o.save()
                    ar.set_response(refresh_all=True)
        mi.sync_primary_address(ar.request)

    def living_at_text(self):
        lines = list(self.address_location_lines())
        return self.address_type.living_text + ' ' + ', '.join(lines)
예제 #12
0
파일: mixins.py 프로젝트: TonisPiip/xl
class BeIdCardHolder(dd.Model):
    """Mixin for models which represent an eid card holder.
    Currently only Belgian eid cards are tested.
    Concrete subclasses must also inherit from :mod:`lino.mixins.Born`.

    .. attribute:: national_id

        The SSIN. It is a *nullable char field* declared *unique*. It
        is not validated directly because that would cause problems
        with legacy data where SSINs need manual control. See also
        :class:`BeIdCardHolderChecker`.

    .. attribute:: nationality

        The nationality. This is a pointer to
        :class:`countries.Country
        <lino_xl.lib.statbel.countries.models.Country>` which should
        contain also entries for refugee statuses.

        Note that the nationality is *not* being read from eID card
        because it is stored there as a language and gender specific
        plain text.

    .. attribute:: image

        Virtual field which displays the picture.

    """
    class Meta:
        abstract = True

    validate_national_id = False
    """Whether to validate the :attr:`national_id` immediately before
    saving a record.  If this is `False`, the :attr:`national_id`
    might contain invalid values which would then cause plausibility
    problems.

    """

    national_id = dd.NullCharField(
        max_length=200,
        unique=True,
        verbose_name=_("National ID")
        #~ blank=True,verbose_name=_("National ID")
        # ~ ,validators=[ssin.ssin_validator] # 20121108
    )

    birth_country = dd.ForeignKey("countries.Country",
                                  blank=True,
                                  null=True,
                                  verbose_name=_("Birth country"),
                                  related_name='by_birth_place')

    birth_place = models.CharField(
        _("Birth place"),
        max_length=200,
        blank=True,
        #~ null=True
    )
    nationality = dd.ForeignKey('countries.Country',
                                blank=True,
                                null=True,
                                related_name='by_nationality',
                                verbose_name=_("Nationality"))
    card_number = models.CharField(
        max_length=20,
        blank=True,  # null=True,
        verbose_name=_("eID card number"))
    card_valid_from = models.DateField(blank=True,
                                       null=True,
                                       verbose_name=_("ID card valid from"))
    card_valid_until = models.DateField(blank=True,
                                        null=True,
                                        verbose_name=_("until"))

    card_type = BeIdCardTypes.field(blank=True)

    card_issuer = models.CharField(
        max_length=50,
        blank=True,  # null=True,
        verbose_name=_("eID card issuer"))
    "The administration who issued this ID card."

    read_beid = BeIdReadCardAction()
    find_by_beid = FindByBeIdAction()

    noble_condition = models.CharField(
        max_length=50,
        blank=True,  # null=True,
        verbose_name=_("noble condition"),
        help_text=_("The eventual noble condition of this person."))

    beid_readonly_fields = set(
        'noble_condition card_valid_from card_valid_until \
        card_issuer card_number card_type'.split())

    def disabled_fields(self, ar):
        rv = super(BeIdCardHolder, self).disabled_fields(ar)
        if not ar.get_user().profile.has_required_roles([dd.SiteStaff]):
            rv |= self.beid_readonly_fields
        #~ logger.info("20130808 beid %s", rv)
        return rv

    def has_valid_card_data(self, today=None):
        if not self.card_number:
            return False
        if self.card_valid_until < (today or dd.today()):
            return False
        return True

    def full_clean(self):
        if self.validate_national_id and self.national_id:
            self.national_id = ssin.parse_ssin(self.national_id)
        super(BeIdCardHolder, self).full_clean()

    @dd.displayfield(_("eID card"), default='<br/><br/><br/><br/>')
    def eid_info(self, ar):
        "Display some information about the eID card."
        attrs = dict(class_="lino-info")
        if ar is None:
            return E.div(**attrs)
        must_read = False
        elems = []
        if self.card_number:
            elems += [
                "%s %s (%s)" %
                (ugettext("Card no."), self.card_number, self.card_type)
            ]
            if self.card_issuer:
                elems.append(", %s %s" %
                             (ugettext("issued by"), self.card_issuer))
                #~ card_issuer = _("issued by"),
            if self.card_valid_until is not None:
                valid = ", %s %s %s %s" % (
                    ugettext("valid from"), dd.dtos(self.card_valid_from),
                    ugettext("until"), dd.dtos(self.card_valid_until))
                if self.card_valid_until < dd.today():
                    must_read = True
                    elems.append(E.b(valid))
                    elems.append(E.br())
                else:
                    elems.append(valid)

            else:
                must_read = True
        else:
            must_read = True
        if must_read:
            msg = _("Must read eID card!")
            if dd.plugins.beid:
                elems.append(
                    ar.instance_action_button(self.read_beid,
                                              msg,
                                              icon_name=None))
            else:
                elems.append(msg)
            # same red as in lino.css for .x-grid3-row-red td
            # ~ attrs.update(style="background-color:#FA7F7F; padding:3pt;")
            attrs.update(class_="lino-info-red")
        return E.div(*elems, **attrs)

    def get_beid_diffs(obj, attrs):
        """Return two lists, one with the objects to save, and another with
        text lines to build a confirmation message explaining which
        changes are going to be applied after confirmation.

        The default implemantion is for the simple case where the
        holder is also a contacts.AddressLocation and the address is
        within the same database row.

        """
        raise Exception("not tested")
        diffs = []
        objects = []
        # model = holder_model()
        model = obj.__class__  # the holder
        for fldname, new in attrs.items():
            fld = get_field(model, fldname)
            old = getattr(obj, fldname)
            if old != new:
                diffs.append("%s : %s -> %s" % (unicode(
                    fld.verbose_name), dd.obj2str(old), dd.obj2str(new)))
                setattr(obj, fld.name, new)
        return objects, diffs

    @dd.htmlbox()
    def image(self, ar):
        url = self.get_image_url(ar)
        return E.a(E.img(src=url, width="100%"), href=url, target="_blank")
        # s = '<img src="%s" width="100%%"/>' % url
        # s = '<a href="%s" target="_blank">%s</a>' % (url, s)
        # return s

    def get_image_url(self, ar):
        if self.card_number:
            parts = get_image_parts(self.card_number)
            return settings.SITE.build_media_url(*parts)
        return settings.SITE.build_static_url("contacts.Person.jpg")

    def get_image_path(self):
        return get_image_path(self.card_number)

    def make_demo_picture(self):
        """Create a demo picture for this card holder. """
        if not self.card_number:
            raise Exception("20150730")
        src = self.mf(MALE, FEMALE)
        dst = self.get_image_path()
        # dst = settings.SITE.cache_dir.child(
        #     'media', 'beid', self.card_number + '.jpg')
        if dst.needs_update([src]):
            logger.info("Create demo picture %s", dst)
            settings.SITE.makedirs_if_missing(dst.parent)
            src.copy(dst)
        else:
            logger.info("Demo picture %s is up-to-date", dst)
예제 #13
0
파일: desktop.py 프로젝트: forexblog/xl
class Coachings(dd.Table):
    required_roles = dd.login_required(CoachingsStaff)
    model = 'coachings.Coaching'

    parameters = mixins.ObservedDateRange(
        coached_by=dd.ForeignKey(
            'users.User',
            blank=True, null=True,
            verbose_name=_("Coached by"),
            help_text="""Nur Begleitungen dieses Benutzers."""),
        and_coached_by=dd.ForeignKey(
            'users.User',
            blank=True, null=True,
            verbose_name=_("and by"),
            help_text="""... und auch Begleitungen dieses Benutzers."""),
        observed_event=dd.PeriodEvents.field(
            blank=True, default=dd.PeriodEvents.as_callable('active')),
        primary_coachings=dd.YesNo.field(
            _("Primary coachings"),
            blank=True, help_text="""Accompagnements primaires."""),
        coaching_type=dd.ForeignKey(
            'coachings.CoachingType',
            blank=True, null=True,
            help_text="""Nur Begleitungen dieses Dienstes."""),
        ending=dd.ForeignKey(
            'coachings.CoachingEnding',
            blank=True, null=True,
            help_text="""Nur Begleitungen mit diesem Beendigungsgrund."""),
    )
    params_layout = """
    start_date end_date observed_event coached_by and_coached_by
    primary_coachings coaching_type ending
    """
    params_panel_hidden = True

    #~ @classmethod
    #~ def param_defaults(self,ar,**kw):
        #~ kw = super(Coachings,self).param_defaults(ar,**kw)
        #~ D = datetime.date
        #~ kw.update(start_date = D.today())
        #~ kw.update(end_date = D.today())
        #~ return kw

    @classmethod
    def get_request_queryset(self, ar, **filter):
        qs = super(Coachings, self).get_request_queryset(ar, **filter)
        pv = ar.param_values
        coaches = []
        for u in (pv.coached_by, pv.and_coached_by):
            if u is not None:
                coaches.append(u)
        if len(coaches):
            qs = qs.filter(user__in=coaches)

        ce = pv.observed_event
        if ce is not None:
            qs = ce.add_filter(qs, pv)

        if pv.primary_coachings == dd.YesNo.yes:
            qs = qs.filter(primary=True)
        elif pv.primary_coachings == dd.YesNo.no:
            qs = qs.filter(primary=False)
        if pv.coaching_type is not None:
            qs = qs.filter(type=pv.coaching_type)
        if pv.ending is not None:
            qs = qs.filter(ending=pv.ending)
        return qs

    @classmethod
    def get_title_tags(self, ar):
        for t in super(Coachings, self).get_title_tags(ar):
            yield t

        pv = ar.param_values

        if pv.observed_event:
            yield six.text_type(pv.observed_event)

        if pv.coached_by:
            s = six.text_type(self.parameters['coached_by'].verbose_name) + \
                ' ' + six.text_type(pv.coached_by)
            if pv.and_coached_by:
                s += " %s %s" % (six.text_type(_('and')),
                                 pv.and_coached_by)
            yield s

        if pv.primary_coachings:
            yield six.text_type(self.parameters['primary_coachings'].verbose_name) \
                + ' ' + six.text_type(pv.primary_coachings)

    @classmethod
    def get_create_permission(self, ar):
        """Reception clerks can see coachings, but cannot modify them nor add
        new ones.

        """
        
        if not ar.get_user().user_type.has_required_roles([CoachingsUser]):
        #if not ar.get_user().user_type.coaching_level:
            return False
        return super(Coachings, self).get_create_permission(ar)
예제 #14
0
class Delivery(dd.Model):

    client1 = dd.ForeignKey(Client1)
    product = dd.ForeignKey(Product)
    designation = models.CharField("Designation",default='give_same_Product_Name', max_length=40, null=True,blank=True)
    #price = models.DecimalField("Price", decimal_places=2, max_digits=10)
    price=dd.PriceField(default=0)
    discount=dd.QuantityField(null=True ,blank=True)
    #date = models.DateField(auto_now=True) for update auto_now_add for create
    date = models.DateField(auto_now_add=True)
    hour = models.TimeField(auto_now_add=True)
    qty=dd.QuantityField(default='1')
    total_d=dd.PriceField(default=0)

    def __str__(self):

        if self.discount is None:
            self.total_d=self.total()
            self.reduce()

            return "%s x %s  = %s EUR" % (self.qty, self.price, self.total_d)
        else:
            self.total_d=self.total()
            self.reduce()


            return "%s x %s  (-%s) = %s EUR" % (self.qty,  self.price, self.discount, self.total_d)


    def total(self):
        if self.discount is None:
            return self.qty * self.price
        else:
            return self.qty * (1 - self.discount) * self.price

    def reduce(self):

        for self.p in Product.objects.all():

             #if self.p.product_name =='apple' :
              #self.p.product_qt = 999
              #self.p.save()

#  collect the product_name
  #       if self.p.product_name == self.product.product_name:
  #          self.designation = self.product.product_name
  #          self.save()

         if self.p.product_price == self.product.product_price:
           self.price = self.product.product_price
           self.save()

         if self.p.product_name == self.designation:
            self.p.last_qt= self.qty
            self.p.save()
            self.p.rest_qt=self.p.product_qt - self.qty
            self.p.save()
            self.p.new_qt=True
            self.p.save()
         if self.p.product_name == self.product.product_name:
               self.designation = self.product.product_name + '+'
               self.save()

         if self.p.product_name == self.product.product_name:
               self.p.product_qt = self.product.rest_qt
               self.p.save()
예제 #15
0

class ClientCoachingsChecker(ClientChecker):
    verbose_name = _("Check coachings")

    def get_checkdata_problems(self, obj, fix=False):
        if obj.client_state == ClientStates.coached:
            if obj.is_obsolete:
                yield (False, _("Both coached and obsolete."))
        if obj.client_state != ClientStates.coached:
            today = dd.today()
            period = (today, today)
            qs = obj.get_coachings(period)
            if qs.count():
                yield (False, _("Not coached, but with active coachings."))

ClientCoachingsChecker.activate()


dd.inject_field(
    'users.User', 'coaching_type',
    dd.ForeignKey(
        'coachings.CoachingType',
        blank=True, null=True))

dd.inject_field(
    'users.User', 'coaching_supervisor',
    models.BooleanField(
        _("Coaching supervisor"),
        default=False))
예제 #16
0
파일: ui.py 프로젝트: TonisPiip/cosi
class Movements(dd.Table):
    """
    The base table for all tables working on :class:`Movement`.
    Defines filtering parameters and general behaviour.

    Subclassed by e.g. :class:`AllMovements`,
    :class:`MovementsByVoucher`,
    :class:`MovementsByAccount` and :class:`MovementsByPartner`.

    See also :class:`lino_cosi.lib.ledger.models.Movement`.
    """

    model = 'ledger.Movement'
    required_roles = dd.login_required(LedgerUser)
    column_names = 'value_date voucher_link description \
    debit credit match_link cleared *'

    sum_text_column = 2

    editable = False
    parameters = mixins.ObservedPeriod(
        year=FiscalYears.field(blank=True),
        journal_group=JournalGroups.field(blank=True),
        partner=dd.ForeignKey('contacts.Partner', blank=True, null=True),
        project=dd.ForeignKey(dd.plugins.ledger.project_model,
                              blank=True,
                              null=True),
        account=dd.ForeignKey('accounts.Account', blank=True, null=True),
        journal=JournalRef(blank=True),
        cleared=dd.YesNo.field(_("Show cleared movements"), blank=True))
    params_layout = """
    start_date end_date cleared
    journal_group journal year project partner account"""

    @classmethod
    def get_request_queryset(cls, ar):
        qs = super(Movements, cls).get_request_queryset(ar)

        pv = ar.param_values
        if pv.cleared == dd.YesNo.yes:
            qs = qs.filter(cleared=True)
        elif pv.cleared == dd.YesNo.no:
            qs = qs.filter(cleared=False)

        # if ar.param_values.partner:
        #     qs = qs.filter(partner=ar.param_values.partner)
        # if ar.param_values.paccount:
        #     qs = qs.filter(account=ar.param_values.paccount)
        if pv.year:
            qs = qs.filter(voucher__accounting_period__year=pv.year)
        if pv.journal_group:
            qs = qs.filter(voucher__journal__journal_group=pv.journal_group)
        if pv.journal:
            qs = qs.filter(voucher__journal=pv.journal)
        return qs

    @classmethod
    def get_sum_text(self, ar, sums):
        bal = sums['debit'] - sums['credit']
        return _("Balance {1} ({0} movements)").format(ar.get_total_count(),
                                                       bal)

    @classmethod
    def get_simple_parameters(cls):
        p = super(Movements, cls).get_simple_parameters()
        p.add('partner')
        p.add('project')
        # p.add('journal_group')
        # p.add('year')
        p.add('account')
        return p

    @classmethod
    def get_title_tags(cls, ar):
        for t in super(Movements, cls).get_title_tags(ar):
            yield t
        pv = ar.param_values
        if pv.journal is not None:
            yield pv.journal.ref
        if pv.journal_group is not None:
            yield unicode(pv.journal_group)
        if pv.year is not None:
            yield unicode(pv.year)
        if pv.cleared == dd.YesNo.no:
            yield unicode(_("only uncleared"))
        elif pv.cleared == dd.YesNo.yes:
            yield unicode(_("only cleared"))

    @dd.displayfield(_("Description"))
    def description(cls, self, ar):
        if ar is None:
            return ''
        elems = []
        elems.append(ar.obj2html(self.account))
        voucher = self.voucher.get_mti_leaf()
        if voucher.narration:
            elems.append(voucher.narration)
        p = voucher.get_partner()
        if p is not None:
            elems.append(ar.obj2html(p))
        if self.project:
            elems.append(ar.obj2html(self.project))
        return E.p(*join_elems(elems, " / "))
예제 #17
0
class Coaching(UserAuthored, mixins.DateRange, dd.ImportedFields, ChangeNotifier):

    class Meta:
        app_label = 'coachings'
        verbose_name = _("Coaching")
        verbose_name_plural = _("Coachings")
        abstract = dd.is_abstract_model(__name__, 'Coaching')

    # user = dd.ForeignKey(
    #     settings.SITE.user_model,
    #     verbose_name=_("Coach"),
    #     related_name="%(app_label)s_%(class)s_set_by_user",
    # )

    allow_cascaded_delete = ['client']
    workflow_state_field = 'state'
    manager_roles_required = dd.login_required(CoachingsStaff)

    client = dd.ForeignKey(client_model, related_name="coachings_by_client")
    type = dd.ForeignKey('coachings.CoachingType', blank=True, null=True)
    primary = models.BooleanField(_("Primary"), default=False)

    ending = dd.ForeignKey(
        'coachings.CoachingEnding',
        related_name="%(app_label)s_%(class)s_set",
        blank=True, null=True)

    @classmethod
    def on_analyze(cls, site):
        super(Coaching, cls).on_analyze(site)
        cls.declare_imported_fields('''client user primary end_date''')

    @dd.chooser()
    def ending_choices(cls, type):
        qs = CoachingEnding.objects.filter(
            Q(type__isnull=True) | Q(type=type))
        return qs.order_by("seqno")

    # def disabled_fields(self, ar):
    #     rv = super(Coaching, self).disabled_fields(ar)
    #     if settings.SITE.is_imported_partner(self.client):
    #         if self.primary:
    #             rv |= self._imported_fields
    #         rv.add('primary')
    #     return rv

    def on_create(self, ar):
        """
        Default value for the `user` field is the requesting user.
        """
        if self.user_id is None:
            u = ar.get_user()
            if u is not None:
                self.user = u
        super(Coaching, self).on_create(ar)

    def disable_delete(self, ar=None):
        if ar is not None and settings.SITE.is_imported_partner(self.client):
            if self.primary:
                return _("Cannot delete companies and persons imported from TIM")
        return super(Coaching, self).disable_delete(ar)

    def before_ui_save(self, ar, cw):
        #~ logger.info("20121011 before_ui_save %s",self)
        super(Coaching, self).before_ui_save(ar, cw)
        if not self.type:
            self.type = ar.get_user().coaching_type
        if not self.start_date:
            self.start_date = settings.SITE.today()
        if self.ending and not self.end_date:
            self.end_date = settings.SITE.today()

    #~ def update_system_note(self,note):
        #~ note.project = self.client

    def __str__(self):
        #~ return _("Coaching of %(client)s by %(user)s") % dict(client=self.client,user=self.user)
        #~ return self.user.username+' / '+self.client.first_name+' '+self.client.last_name[0]
        if not self.client_id:
            return super(Coaching, self).__str__()
        cl = self.client
        if self.user_id is None:
            return "{} {}".format(
                self.__class__._meta.verbose_name, cl)
        if cl.first_name:
            return self.user.username + ' / ' + cl.last_name + ' ' + cl.first_name[0]
        return self.user.username + ' / ' + cl.last_name

    def adapt_primary(self):
        if self.primary:
            qs = self.client.coachings_by_client.exclude(id=self.id)
            if dd.plugins.coachings.multiple_primary_coachings:
                qs = qs.filter(type=self.type)
            for c in qs:
                if c.primary:
                    c.primary = False
                    c.save()
                    return True

    def after_ui_save(self, ar, cw):
        super(Coaching, self).after_ui_save(ar, cw)
        if self.adapt_primary():
            ar.set_response(refresh_all=True)
        #~ return kw

    #~ def get_row_permission(self,user,state,ba):
        #~ """
        #~ """
        #~ logger.info("20121011 get_row_permission %s %s",self,ba)
        #~ if isinstance(ba.action,actions.SubmitInsert):
            #~ if not user.coaching_type:
                #~ return False
        #~ return super(Coaching,self).get_row_permission(user,state,ba)

    def full_clean(self, *args, **kw):
        if not self.start_date and not self.end_date:
            self.start_date = settings.SITE.today()
        if not self.type and self.user:
            self.type = self.user.coaching_type
        super(Coaching, self).full_clean(*args, **kw)

    #~ def save(self,*args,**kw):
        #~ super(Coaching,self).save(*args,**kw)

    def summary_row(self, ar, **kw):
        return [ar.href_to(self.client), " (%s)" % self.state.text]

    # def get_related_project(self):
    #     return self.client

    def get_change_owner(self):
        return self.client
예제 #18
0
파일: models.py 프로젝트: TonisPiip/cosi
class Transaction(dd.Model):
    """A transaction within a bank statement.

    This data is automaticaly imported by :class:`ImportStatements`.


    
    .. attribute:: statement

    .. attribute:: seqno

    .. attribute:: booking_date

    .. attribute:: value_date

    .. attribute:: transfer_type

       The actual historic name of the :attr:`txcd`.

    .. attribute:: txcd

        The Bank Transaction Code (`<BkTxCd>`) or "transfer type".
        Actually it is the "proprietary" part of this code.

    .. attribute:: txcd_issuer

        The issuer or the :attr:`txcd`.

    .. attribute:: txcd_text

        Virtual field with the textual translated description of the
        :attr:`txcd`.  Currently this works only for Belgian codes
        where :attr:`txcd_issuer` is `"BBA"` as defined in
        :mod:`lino_cosi.lib.b2c.febelfin`).

    .. attribute:: remote_account
    .. attribute:: remote_bic
    .. attribute:: remote_owner
    .. attribute:: remote_owner_address
    .. attribute:: remote_owner_city
    .. attribute:: remote_owner_postalcode
    .. attribute:: remote_owner_country_code

    """
    class Meta:
        app_label = 'b2c'
        abstract = dd.is_abstract_model(__name__, 'Transaction')
        verbose_name = _("Transaction")
        verbose_name_plural = _("Transactions")

    statement = dd.ForeignKey('b2c.Statement')
    seqno = models.IntegerField(
        _('No.'),
        help_text=_(
            "The sequence number of this transaction in the statement."))
    # unique_import_id = models.CharField(_('Unique import ID'), max_length=128)
    # movement_number = models.CharField(_("Ref of Mov"), null=False, max_length=32)
    # movement_date = models.DateField(_('Movement date'), null=True, blank=True)
    amount = dd.PriceField(_('Amount'), null=True, blank=True)
    # partner = models.ForeignKey('contacts.Partner', related_name='b2c_movement', null=True)
    # partner_name = models.CharField(_('Partner name'), max_length=35, blank=True)
    remote_account = models.CharField(_("IBAN"), blank=True, max_length=64)
    remote_bic = BICField(verbose_name=_("BIC"), blank=True)
    # ref = models.CharField(_('Ref'), max_length=35, blank=True)
    message = models.TextField(_('Message'), blank=True)
    eref = models.CharField(_('End to end reference'),
                            max_length=128,
                            blank=True)
    remote_owner = models.CharField(_('Remote owner'),
                                    max_length=128,
                                    blank=True)
    remote_owner_address = models.TextField(_('Remote owner adress'),
                                            blank=True)
    remote_owner_city = models.CharField(_('Remote owner city'),
                                         max_length=32,
                                         blank=True)
    remote_owner_postalcode = models.CharField(_('Remote owner postal code'),
                                               max_length=10,
                                               blank=True)
    remote_owner_country_code = models.CharField(
        _('Remote owner country code'), max_length=4, blank=True)
    txcd = models.CharField(_('Transfer type'), max_length=32, blank=True)
    txcd_issuer = models.CharField(_('TxCd issuer'), max_length=35, blank=True)
    booking_date = models.DateField(_('Execution date'), null=True, blank=True)
    value_date = models.DateField(_('Value date'), null=True, blank=True)

    @dd.displayfield(_("Remote account"))
    def remote_html(self, ar):
        elems = []
        elems += [self.remote_account, " "]
        elems += ["(BIC:", self.remote_bic, ")"]
        elems.append(E.br())
        elems += [E.b(self.remote_owner), ", "]
        elems.append(E.br())
        elems += [" / ".join(self.remote_owner_address.splitlines()), ", "]
        elems += [self.remote_owner_postalcode, " "]
        elems += [self.remote_owner_city, " "]
        elems += [self.remote_owner_country_code]
        return E.div(*elems)

    @dd.displayfield(_("Message"))
    def message_html(self, ar):
        from django.utils.translation import ugettext as _
        elems = []
        # elems += [_("Date"), dd.fds(self.transaction_date), " "]
        # elems += [_("Amount"), ' ', E.b(unicode(self.amount)), " "]
        # self.booking_date
        elems += self.message  # .splitlines()
        elems.append(E.br())
        # elems += [_("ref:"), ': ', self.ref, ' ']
        elems += [_("eref:"), ': ', self.eref]
        elems.append(E.br())
        elems += [E.b(self.txcd_text), ' ']
        elems += [_("Value date"), ': ', E.b(dd.fds(self.value_date)), " "]
        elems += [_("Booking date"), ': ', E.b(dd.fds(self.booking_date)), " "]
        return E.div(*elems)

    @dd.displayfield(_("BkTxCd"))
    def txcd_text(self, ar):
        if self.txcd_issuer == 'BBA':
            # until we get a list of German translations, users in
            # Eupen prefer FR over EN
            with translation.override('fr'):
                return force_text(code2desc(self.txcd[:4]))
        return "{0}:{1}".format(self.txcd_issuer, self.txcd)
예제 #19
0
파일: models.py 프로젝트: einarfelix/xl
class Enrolment(dd.Model):
    # invoiceable_date_field = 'request_date'
    # workflow_state_field = 'state'
    allow_cascaded_copy = 'order'
    allow_cascaded_delete = 'order'

    class Meta:
        app_label = 'orders'
        abstract = dd.is_abstract_model(__name__, 'Enrolment')
        verbose_name = _("Enrolment")
        verbose_name_plural = _('Enrolments')
        unique_together = ('order', 'worker')

    # order_layout = OrderLayouts.field(blank=True, editable=False)

    quick_search_fields = worker_name_fields

    #~ teacher = dd.ForeignKey(Teacher)
    order = dd.ForeignKey('orders.Order', related_name="enrolments_by_order")
    worker = dd.ForeignKey(worker_model, related_name="enrolments_by_worker")
    guest_role = dd.ForeignKey("cal.GuestRole",
                               blank=True,
                               null=True,
                               verbose_name=_("Role in calendar entries"))
    remark = models.CharField(_("Remark"), max_length=200, blank=True)

    @dd.chooser()
    def worker_choices(cls, order):
        worker = dd.resolve_model(worker_model)
        return worker.objects.all()

    # def create_worker_choice(self, text):
    #     """
    #     Called when an unknown worker name was given.
    #     Try to auto-create it.
    #     """
    #     worker = dd.resolve_model(worker_model)
    #     kw = parse_name(text)
    #     if len(kw) != 2:
    #         raise ValidationError(
    #             "Cannot find first and last names in %r to \
    #             auto-create worker", text)
    #     p = worker(**kw)
    #     p.full_clean()
    #     p.save()
    #     return p

    def get_overview_elems(self, ar):
        if self.order_id:
            return [self.order.obj2href(ar)]
        return [self.obj2href(ar)]

    def get_guest_role(self):
        return self.guest_role

    def make_guest_for(self, event):
        gr = self.get_guest_role()
        if gr is not None:
            return rt.models.cal.Guest(event=event,
                                       partner=self.worker,
                                       role=gr)

    def __str__(self):
        return "%s / %s" % (self.order, self.worker)

    def get_print_language(self):
        return self.worker.language

    def get_body_template(self):
        """Overrides :meth:`lino.core.model.Model.get_body_template`."""
        return self.order.body_template

    def get_excerpt_title(self):
        return self.order.get_excerpt_title()
예제 #20
0
class CountryCity(dd.Model):
    """Model mixin that adds two fields `country` and `city` and defines
    a context-sensitive chooser for `city`, a `create_city_choice`
    method, ...

    .. attribute:: country
    .. attribute:: zip_code
    
    .. attribute:: city
    
        A pointer to :class:`Place`.


    """
    class Meta:
        abstract = True

    country = dd.ForeignKey("countries.Country", blank=True, null=True)
    city = dd.ForeignKey('countries.Place',
                         verbose_name=_('City'),
                         blank=True,
                         null=True)
    zip_code = models.CharField(_("Zip code"), max_length=10, blank=True)

    active_fields = 'city zip_code'
    # active fields cannot be used in insert_layout

    @dd.chooser()
    def city_choices(cls, country):
        return rt.modules.countries.Place.get_cities(country)

    @dd.chooser()
    def country_choices(cls):
        return rt.modules.countries.Country.get_actual_countries()

    def create_city_choice(self, text):
        """
        Called when an unknown city name was given.
        Try to auto-create it.
        """
        if self.country is not None:
            return rt.modules.countries.Place.lookup_or_create(
                'name', text, country=self.country)

        raise ValidationError("Cannot auto-create city %r if country is empty",
                              text)

    def country_changed(self, ar):
        """
        If user changes the `country`, then the `city` gets lost.
        """
        if self.city is not None and self.country != self.city.country:
            self.city = None

    def zip_code_changed(self, ar):
        if self.country and self.zip_code:
            qs = rt.modules.countries.Place.objects.filter(
                country=self.country, zip_code=self.zip_code)
            if qs.count() > 0:
                self.city = qs[0]

    def full_clean(self, *args, **kw):
        """Fills my :attr:`zip_code` from my :attr:`city` if my `zip_code` is
        not empty and differs from that of the city.

        """
        city = self.city
        if city is None:
            self.zip_code_changed(None)
        else:
            if city.country is not None and self.country != city.country:
                self.country = city.country
            if city.zip_code:
                self.zip_code = city.zip_code
        super(CountryCity, self).full_clean(*args, **kw)
예제 #21
0
파일: models.py 프로젝트: einarfelix/xl
class Address(AddressLocation):

    class Meta:
        app_label = 'addresses'
        verbose_name = _("Address")
        verbose_name_plural = _("Addresses")

    quick_search_fields = "partner__name city__name street"

    data_source = DataSources.field(editable=False, default='manually')
    # address_type = AddressTypes.field(blank=True, null=True)
    address_type = AddressTypes.field(default='official')
    partner = dd.ForeignKey(
        dd.plugins.addresses.partner_model,
        related_name='addresses_by_partner')
    remark = dd.CharField(_("Remark"), max_length=50, blank=True)

    primary = models.BooleanField(_("Primary"), default=False)

    allow_cascaded_delete = ['partner']

    def __str__(self):
        return self.address_location(', ')

    def after_ui_save(self, ar, cw):
        super(Address, self).after_ui_save(ar, cw)
        mi = self.partner
        if mi is None:
            return
        if self.primary:
            for o in mi.addresses_by_partner.exclude(id=self.id):
                if o.primary:
                    o.primary = False
                    o.save()
                    ar.set_response(refresh_all=True)
        mi.sync_primary_address(ar.request)

    def living_at_text(self):
        lines = list(self.address_location_lines())
        return self.address_type.living_text + ' ' + ', '.join(lines)

    @classmethod
    def setup_parameters(cls, fields):
        fields.update(
            place=dd.ForeignKey('countries.Place', blank=True, null=True))
        super(Address, cls).setup_parameters(fields)

    @classmethod
    def get_request_queryset(cls, ar, **filter):
        qs = super(Address, cls).get_request_queryset(ar, **filter)
        pv = ar.param_values
        if pv.place:
            qs = qs.filter(city=pv.place)
        return qs

    @classmethod
    def get_title_tags(self, ar):
        for t in super(Address, self).get_title_tags(ar):
            yield t
        pv = ar.param_values
        if pv.place:
            yield str(pv.place)

    @classmethod
    def get_simple_parameters(cls):
        for p in  super(Address, cls).get_simple_parameters():
            yield p
        yield 'partner'
        yield 'address_type'
예제 #22
0
class Excerpt(mixins.TypedPrintable, UserAuthored, Controllable,
              mixins.ProjectRelated, ContactRelated, Mailable, Postable):
    """A printable document that describes some aspect of the current
    situation.

    .. attribute:: excerpt_type

        The type of this excerpt (ForeignKey to :class:`ExcerptType`).

    .. attribute:: owner

      The object being printed by this excerpt.
      See :attr:`Controllable.owner
      <lino.modlib.gfks.mixins.Controllable.owner>`.

    .. attribute:: company

      The optional company of the :attr:`recipient` of this
      excerpt.  See :attr:`ContactRelated.company
      <lino.modlib.contacts.mixins.ContactRelated.company>`.

    .. attribute:: contact_person

      The optional contact person of the :attr:`recipient` of this
      excerpt.  See :attr:`ContactRelated.contact_person
      <lino.modlib.contacts.mixins.ContactRelated.contact_person>`.

    .. attribute:: recipient

      The recipient of this excerpt.  See
      :attr:`ContactRelated.recipient
      <lino.modlib.contacts.mixins.ContactRelated.recipient>`

    .. attribute:: language

      The language used for printing this excerpt.

    .. attribute:: date

    .. attribute:: time

    .. method:: get_address_html

        See
        :meth:`lino.modlib.contacts.mixins.ContactRelated.get_address_html`.

        Return the address of the :attr:`recipient` of this excerpt.

    """

    manager_roles_required = dd.login_required(OfficeStaff)
    # manager_level_field = 'office_level'
    allow_cascaded_delete = "owner"

    class Meta:
        abstract = dd.is_abstract_model(__name__, 'Excerpt')
        verbose_name = _("Excerpt")
        verbose_name_plural = _("Excerpts")

    excerpt_type = dd.ForeignKey('excerpts.ExcerptType')

    body_template_content = BodyTemplateContentField(_("Body template"))

    language = dd.LanguageField()

    # if dd.is_installed('outbox'):
    #     mails_by_owner = dd.ShowSlaveTable('outbox.MailsByController')

    def get_body_template(self):
        """Return the body template to use for this excerpt."""
        owner = self.owner
        # owner is None e.g. if is a broken GFK
        if owner is not None:
            assert self.__class__ is not owner.__class__
            tplname = owner.get_body_template()
            if tplname:
                return tplname
        return self.excerpt_type.body_template

    def get_body_template_filename(self):
        tplname = self.get_body_template()
        if not tplname:
            return None
        mc = self.excerpt_type.content_type.model_class()
        tplgroup = mc.get_template_group()
        return rt.find_config_file(tplname, tplgroup)

    def get_body_template_name(self):
        tplname = self.get_body_template()
        if not tplname:
            return None
        mc = self.excerpt_type.content_type.model_class()
        tplgroup = mc.get_template_group()
        return tplgroup + '/' + tplname

    def disabled_fields(self, ar):
        rv = super(Excerpt, self).disabled_fields(ar)
        rv = rv | set(['excerpt_type', 'project'])
        if self.build_time:
            rv |= self.PRINTABLE_FIELDS
        return rv

    def __unicode__(self):
        if self.build_time:
            return naturaltime(self.build_time)
            # return _("%(owner)s (printed %(time)s)") % dict(
            #     owner=self.owner, time=naturaltime(self.build_time))
        return _("Unprinted %s #%s") % (self._meta.verbose_name, self.pk)

    def get_mailable_type(self):
        return self.excerpt_type

    def get_mailable_subject(self):
        return unicode(self.owner)  # .get_mailable_subject()

    def get_template_groups(self):
        ptype = self.get_printable_type()
        if ptype is None:
            raise Exception("20140520 Must have excerpt_type.")
        grp = ptype.content_type.model_class().get_template_group()
        return [grp, 'excerpts']

    def filename_root(self):
        # mainly because otherwise we would need to move files around on
        # existing sites
        et = self.excerpt_type
        if et is None or not et.certifying:
            return super(Excerpt, self).filename_root()
        o = self.owner
        return o._meta.app_label + '.' + o.__class__.__name__ + '-' + str(o.pk)

    def get_print_templates(self, bm, action):
        et = self.excerpt_type
        if et is not None and et.certifying:
            tpls = self.owner.get_excerpt_templates(bm)
            if tpls is not None:
                return tpls
        return super(Excerpt, self).get_print_templates(bm, action)
        # ptype = self.get_printable_type()
        # # raise Exception("20150710 %s" % self.owner)
        # if ptype is not None and ptype.template:
        #     return [ptype.template]
        # # return [bm.get_default_template(self)]
        # return [dd.plugins.excerpts.get_default_template(bm, self.owner)]

    # def get_recipient(self):
    #     rec = super(Excerpt, self).get_recipient()
    #     if rec is None and hasattr(self.owner, 'recipient'):
    #         return self.owner.recipient
    #     return rec

    # recipient = property(get_recipient)

    def get_printable_type(self):
        return self.excerpt_type

    def get_print_language(self):
        return self.language

    def unused_on_create(self, ar):
        # replaced by signal below
        super(Excerpt, self).on_create(ar)
        if not self.owner_id:
            if self.project:
                self.owner = self.project
        self.language = self.owner.get_print_language()

    @dd.chooser()
    def excerpt_type_choices(cls, owner):
        # logger.info("20150702 %s", owner)
        qs = rt.modules.excerpts.ExcerptType.objects.order_by('name')
        if owner is None:
            # e.g. when choosing on the *parameter* field
            # return qs.filter(content_type__isnull=True)
            return qs.filter()
        ct = ContentType.objects.get_for_model(owner.__class__)
        return qs.filter(content_type=ct)

    @property
    def date(self):
        "Used in templates"
        if self.build_time:
            return self.build_time.date()
        return dd.today()

    @property
    def time(self):
        "Used in templates"
        if self.build_time:
            return self.build_time.time()
        return datetime.datetime.now()

    @dd.virtualfield(dd.HtmlBox(_("Preview")))
    def preview(self, ar):
        with translation.override(self.get_print_language()):
            ctx = self.get_printable_context(ar)
            return '<div class="htmlText">%s</div>' % ctx['body']

    def get_printable_context(self, ar=None, **kw):
        """Adds a series of names to the context used when rendering printable
        documents. See :doc:`/user/templates_api`.

        """
        if self.owner is not None:
            kw = self.owner.get_printable_context(ar, **kw)
        kw = super(Excerpt, self).get_printable_context(**kw)
        kw.update(obj=self.owner)
        body = ''
        if self.excerpt_type_id is not None:
            etype = self.excerpt_type
            if etype.backward_compat:
                kw.update(this=self.owner)

            tplname = self.get_body_template_name()
            if tplname and ar is not None:
                # sar = copy(ar)
                # sar.renderer = settings.SITE.kernel.html_renderer
                env = settings.SITE.plugins.jinja.renderer.jinja_env
                template = env.get_template(tplname)
                # logger.info("body template %s (%s)", tplname, template)
                body = ar.render_jinja(template, **kw)
                # logger.info("20150811 body template %s (%s) -> %s",
                #             tplname, template, body)

        kw.update(body=body)
        return kw

    @classmethod
    def on_analyze(cls, site):
        cls.PRINTABLE_FIELDS = dd.fields_list(
            cls, "project excerpt_type  "
            "body_template_content "
            "company contact_person language "
            "user build_method")
        super(Excerpt, cls).on_analyze(site)
예제 #23
0
        app_label = 'coachings'
        verbose_name = _("Client Contact")
        verbose_name_plural = _("Client Contacts")

    #~ type = ClientContactTypes.field(blank=True)
    client = dd.ForeignKey(client_model)
    remark = models.TextField(_("Remarks"), blank=True)  # ,null=True)

    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"))

contacts = dd.resolve_app('contacts')

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


class PartnersByClientContactType(contacts.Partners):
    master_key = 'client_contact_type'
    column_names = "name address_column phone gsm email *"
    auto_fit_column_widths = True
예제 #24
0
class ExcerptType(mixins.BabelNamed, mixins.PrintableType, MailableType):
    """The type of an excerpt. Every excerpt has a mandatory field
    :attr:`Excerpt.excerpt_type` which points to an :class:`ExcerptType`
    instance.
    
    .. attribute:: name

        The designation of this excerpt type.
        One field for every :attr:`language <lino.core.site.Site.language>`.

    .. attribute:: content_type

        The database model for which this excerpt type is to be used.

    .. attribute:: build_method

        See :attr:`lino.mixinsPrintableType.build_method`.

    .. attribute:: template
 
        The main template to be used when printing an excerpt of this type.

    .. attribute:: body_template

        The body template to use when printing an excerpt of this type.

    .. attribute:: email_template

        The template to use when sending this an excerpt of this type
        by email.

    .. attribute:: shortcut

        Optional pointer to a shortcut field.  If this is not empty, then
        the given shortcut field will manage excerpts of this type.

        See also :class:`Shortcuts`.
        See also :class:`lino.modlib.excerpts.choicelists.Shortcuts`.

    """

    # templates_group = 'excerpts/Excerpt'

    class Meta:
        abstract = dd.is_abstract_model(__name__, 'ExcerptType')
        verbose_name = _("Excerpt Type")
        verbose_name_plural = _("Excerpt Types")

    certifying = models.BooleanField(
        verbose_name=_("Certifying"),
        default=False,
        help_text=_("Whether an excerpt of this type is a unique printout."))

    remark = models.TextField(verbose_name=_("Remark"), blank=True)

    body_template = models.CharField(
        max_length=200,
        verbose_name=_("Body template"),
        blank=True,
        help_text="The body template to be used when \
        rendering a printable of this type. This is a list of files \
        with extension `.body.html`.")

    content_type = dd.ForeignKey(
        'contenttypes.ContentType',
        verbose_name=_("Model"),
        related_name='excerpt_types',
        # null=True, blank=True,
        help_text=_("The model that can issue printouts of this type."))
    """The model on which excerpts of this type are going to work."""

    primary = models.BooleanField(
        _("Primary"),
        default=False,
        help_text=_("""There's at most one primary type per model. \
        Enabling this field will automatically make the other \
        types non-primary."""))

    backward_compat = models.BooleanField(
        _("Backward compatible"),
        default=False,
        help_text=_("Check this to have `this` in template context "
                    "point to owner instead of excerpt."))

    print_recipient = models.BooleanField(
        _("Print recipient"),
        default=True,
        help_text=_("Whether to print a recipient field in document."))

    print_directly = models.BooleanField(_("Print directly"), default=True)

    shortcut = Shortcuts.field(blank=True)

    def full_clean(self, *args, **kwargs):
        if self.certifying:
            if not self.primary:
                raise ValidationError(
                    _("Cannot set %(c)s without %(p)s") %
                    dict(c=_("Certifying"), p=_("Primary")))
            mc = self.content_type.model_class()
            if not issubclass(mc, Certifiable):
                raise ValidationError(
                    _("Cannot set %(c)s for non.certifiable "
                      "model %(m)s") %
                    dict(c=_("Certifying"), m=mc._meta.verbose_name))
        super(ExcerptType, self).full_clean(*args, **kwargs)

    def update_siblings(self):
        updated = 0
        if self.primary:
            for o in self.content_type.excerpt_types.exclude(id=self.id):
                if o.primary:
                    o.primary = False
                    o.save()
                    updated += 1
        return updated

    def save(self, *args, **kwargs):
        # It is important to ensure that there is really only one
        # primary ExcerptType per model because
        # :func:`set_excerpts_actions` will install these as action on
        # the model.
        super(ExcerptType, self).save(*args, **kwargs)
        self.update_siblings()

    def after_ui_save(self, ar, cw):
        super(ExcerptType, self).after_ui_save(ar, cw)
        if self.primary:
            ar.set_response(refresh_all=True)

    @classmethod
    def get_template_groups(cls):
        raise Exception("""Not used by ExcerptType. \
We override everything in Excerpt to not call the class method.""")

    @dd.chooser(simple_values=True)
    def template_choices(cls, build_method, content_type):
        tplgroups = [
            content_type.model_class().get_template_group(), 'excerpts'
        ]
        return cls.get_template_choices(build_method, tplgroups)

    @dd.chooser(simple_values=True)
    def body_template_choices(cls, content_type):
        # 20140617 don't remember why the "excerpts" group was useful here
        # tplgroups = [model_group(content_type.model_class()), 'excerpts']
        # return dd.plugins.jinja.list_templates('.body.html', *tplgroups)

        tplgroup = content_type.model_class().get_template_group()
        return dd.plugins.jinja.list_templates('.body.html', tplgroup,
                                               'excerpts')

    @dd.chooser(simple_values=True)
    def email_template_choices(cls, content_type):
        tplgroup = content_type.model_class().get_template_group()
        return dd.plugins.jinja.list_templates('.eml.html', tplgroup,
                                               'excerpts')

    @classmethod
    def get_for_model(cls, model):
        "Return the primary ExcerptType for the given model."
        ct = ContentType.objects.get_for_model(dd.resolve_model(model))
        return cls.objects.get(primary=True, content_type=ct)

    @classmethod
    def update_for_model(cls, model, **kw):
        obj = cls.get_for_model(model)
        for k, v in kw.items():
            setattr(obj, k, v)
        # obj.full_clean()
        # obj.save()
        return obj

    def get_or_create_excerpt(self, ar):
        obj = ar.selected_rows[0]
        model = self.content_type.model_class()
        if not isinstance(obj, model):
            raise Exception("%s is not an instance of %s" % (obj, model))
        Excerpt = rt.modules.excerpts.Excerpt
        ex = None
        if self.certifying:
            qs = Excerpt.objects.filter(
                excerpt_type=self,
                owner_id=obj.pk,
                owner_type=ContentType.objects.get_for_model(obj.__class__))
            qs = qs.order_by('id')
            if qs.count() > 0:
                ex = qs[0]
        if ex is None:
            akw = dict(user=ar.get_user(), owner=obj, excerpt_type=self)
            akw = obj.get_excerpt_options(ar, **akw)
            ex = Excerpt(**akw)
            ex.on_create(ar)
            ex.full_clean()
            ex.save()

        if self.certifying:
            obj.printed_by = ex
            obj.full_clean()
            obj.save()

        return ex

    def get_action_name(self):
        if self.primary:
            return 'do_print'
        else:
            return 'create_excerpt' + str(self.pk)

    @dd.displayfield(_("Model"))
    def content_type_display(self, ar):
        if ar is None:
            return ''
        model = self.content_type.model_class()
        label = "{0} ({1})".format(dd.full_model_name(model),
                                   model._meta.verbose_name)
        return ar.obj2html(self.content_type, label)
예제 #25
0
파일: models.py 프로젝트: DarioGT/lino
class Note(dd.Model):
    owner_type = dd.ForeignKey(ContentType)
    owner_id = models.PositiveIntegerField()
    owner = dd.GenericForeignKey('owner_type', 'owner_id')

    text = models.CharField(max_length=200)
예제 #26
0
파일: models.py 프로젝트: einarfelix/xl
class Uploads(Uploads):
    column_names = 'user project type file start_date end_date ' \
                   'description_link *'

    detail_layout = UploadDetail()

    insert_layout = """
    type file
    start_date end_date
    description
    """

    parameters = mixins.ObservedDateRange(
        # puser=dd.ForeignKey(
        #     'users.User', blank=True, null=True,
        #     verbose_name=_("Uploaded by")),
        upload_type=dd.ForeignKey('uploads.UploadType', blank=True, null=True),
        coached_by=dd.ForeignKey(
            'users.User',
            blank=True,
            null=True,
            verbose_name=_("Coached by"),
            help_text=_(
                "Show only uploads for clients coached by this user.")),
        observed_event=dd.PeriodEvents.field(
            _("Validity"),
            blank=True,
            default=dd.PeriodEvents.as_callable('active')))
    params_layout = "observed_event:20 start_date end_date \
    coached_by user upload_type"

    auto_fit_column_widths = True

    @classmethod
    def get_request_queryset(cls, ar, **kwargs):
        # (why was this?) use inherited method from grandparent (not
        # direct parent)
        # qs = super(LibraryUploads, cls).get_request_queryset(ar)
        qs = super(Uploads, cls).get_request_queryset(ar, **kwargs)
        pv = ar.param_values

        ce = pv.observed_event
        if ce is not None:
            qs = ce.add_filter(qs, pv)

        # if pv.puser:
        #     qs = qs.filter(user=pv.puser)

        if pv.coached_by:
            qs = qs.filter(project__coachings_by_client__user=pv.coached_by)
            # MyExpiringUploads wants only needed uploads
            qs = qs.filter(needed=True)

        # if pv.pupload_type:
        #     qs = qs.filter(type=pv.pupload_type)

        return qs

    @classmethod
    def get_title_tags(self, ar):
        for t in super(Uploads, self).get_title_tags(ar):
            yield t

        pv = ar.param_values

        if pv.observed_event:
            yield str(pv.observed_event)

        if pv.coached_by:
            yield str(self.parameters['coached_by'].verbose_name) + \
                ' ' + str(pv.coached_by)

        if pv.user:
            yield str(self.parameters['user'].verbose_name) + \
                ' ' + str(pv.user)
예제 #27
0
파일: models.py 프로젝트: TonisPiip/cosi
from lino_cosi.lib.contacts.models import Partners


class PartnersByInvoiceRecipient(Partners):
    label = _("Invoice senders")
    master_key = 'invoice_recipient'
    column_names = 'name id address_column *'
    window_size = (50, 15)
    params_panel_hidden = True


dd.inject_field(
    'contacts.Partner', 'invoice_recipient',
    dd.ForeignKey('contacts.Partner',
                  verbose_name=_("Invoicing address"),
                  blank=True,
                  null=True,
                  help_text=_("Redirect to another partner all invoices which "
                              "should go to this partner.")))

dd.inject_action(
    'contacts.Partner',
    show_invoice_partners=dd.ShowSlaveTable(PartnersByInvoiceRecipient))

dd.inject_field('contacts.Partner', 'paper_type',
                dd.ForeignKey('sales.PaperType', null=True, blank=True))

# class Channels(dd.ChoiceList):
#     label = _("Channel")
# add = Channels.add_item
# add('P', _("Paper"), 'paper')
# add('E', _("E-mail"), 'email')
예제 #28
0
class Link(dd.Model):
    """A link between two persons.

    .. attribute:: parent

        Pointer to the person who is "parent".

    .. attribute:: child

        Pointer to the person who is "child".

    .. attribute:: type

        The type of link.  Pointer to :class:`LinkTypes
        <lino_xl.lib.humanlinks.choicelists.LinkTypes>`.

    """
    class Meta:
        verbose_name = _("Personal Link")
        verbose_name_plural = _("Personal Links")

    type = LinkTypes.field(default=LinkTypes.as_callable('parent'))
    parent = dd.ForeignKey(config.person_model,
                           verbose_name=_("Who is..."),
                           related_name='humanlinks_children')
    child = dd.ForeignKey(config.person_model,
                          blank=True,
                          null=True,
                          verbose_name=_("To whom..."),
                          related_name='humanlinks_parents')

    @dd.displayfield(_("Type"))
    def type_as_parent(self, ar):
        # print('20140204 type_as_parent', self.type)
        return self.type.as_parent(self.parent)

    @dd.displayfield(_("Type"))
    def type_as_child(self, ar):
        # print('20140204 type_as_child', self.type)
        return self.type.as_child(self.child)

    def __str__(self):
        if self.type is None:
            return super(Link, self).__str__()
        return _("%(child)s is %(what)s") % dict(
            child=str(self.child), what=self.type_of_parent_text())

    def type_of_parent_text(self):
        return _("%(type)s of %(parent)s") % dict(
            parent=self.parent, type=self.type.as_child(self.child))

    parent_link_types = (LinkTypes.parent, LinkTypes.adoptive_parent,
                         LinkTypes.foster_parent)

    @classmethod
    def check_autocreate(cls, parent, child):
        """Check whether there is a human link of type "parent" between the
        given persons. Create one if not. If the child has already
        another parent of same sex, then it becomes a foster child,
        otherwise a natural child.

        Note that the ages are ignored here, Lino will shamelessly
        create a link even when the child is older than the parent.

        This is called from :meth:`full_clean` of
        :class:`lino_xl.lib.households.Member` to
        automatically create human links between two household
        members.

        """
        if parent is None or child is None:
            return False
        if parent == child:
            return False
            # raise ValidationError("Parent and Child must differ")
        qs = cls.objects.filter(parent=parent,
                                child=child,
                                type__in=cls.parent_link_types)
        if qs.count() == 0:
            qs = cls.objects.filter(child=child,
                                    type__in=cls.parent_link_types,
                                    parent__gender=parent.gender)
            if qs.count() == 0:
                auto_type = LinkTypes.parent
            else:
                auto_type = LinkTypes.foster_parent
            obj = cls(parent=parent, child=child, type=auto_type)
            obj.full_clean()
            obj.save()
            # dd.logger.info("20141018 autocreated %s", obj)
            return True
        return False
예제 #29
0
파일: mixins.py 프로젝트: TonisPiip/xl
class Certifiable(dd.Model):
    """Any model which inherits from this mixin becomes "certifiable".
    That is:

      - it has a `printed_by` field and a corresponding virtual field
        `printed` which point to the excerpt that is the "definitive"
        ("Certifying") printout of this object.

      - It may define a list of "certifiable" fields.
        See :meth:`get_certifiable_fields`.

    Usage example::

        from lino_xl.lib.excerpts.mixins import Certifiable

        class MyModel(dd.UserAuthored, Certifiable, dd.Duplicable):
            ...

    The :mod:`lino_xl.lib.excerpts.fixtures.std` fixture automatically
    creates a certifying :class:`ExcerptType` instance for every model
    which inherits from :class:`Certifiable`.


    .. attribute:: printed

      Displays information about when this certifiable has been printed.
      Clicking on it will display the excerpt pointed to by
      :attr:`printed_by`.

    .. attribute:: printed_by

      ForeignKey to the :class:`Excerpt` which certifies this instance.

      A :class:`Certifiable` is considered "certified" when this this is
      not `None`.

      Note that this field is a nullable ForeignKey with `on_delete
      <https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.ForeignKey.on_delete>`__
      set to ``SET_NULL``.

    """
    class Meta:
        abstract = True

    printed_by = dd.ForeignKey(
        'excerpts.Excerpt',
        verbose_name=_("Printed"),
        editable=False,
        related_name="%(app_label)s_%(class)s_set_as_printed",
        blank=True,
        null=True,
        on_delete=models.SET_NULL)

    clear_printed = ClearPrinted()

    def disabled_fields(self, ar):
        if self.printed_by_id is None:
            return set()
        return self.CERTIFIED_FIELDS

    def on_duplicate(self, ar, master):
        """After duplicating e.g. a budget which had been printed, we don't
        want the duplicate point to the same
        excerpt. :meth:`lino.mixins.duplicable.Duplicable.on_duplicate`.

        """
        super(Certifiable, self).on_duplicate(ar, master)
        self.printed_by = None

    @classmethod
    def on_analyze(cls, site):
        # Contract.user.verbose_name = _("responsible (DSBE)")
        cls.CERTIFIED_FIELDS = dd.fields_list(cls,
                                              cls.get_certifiable_fields())
        super(Certifiable, cls).on_analyze(site)

    @classmethod
    def get_printable_demo_objects(cls, excerpt_type):
        """Return an iterable of database objects for which Lino should
        generate a printable excerpt.

        This is being called by
        :mod:`lino_xl.lib.excerpts.fixtures.demo2`.

        """

        qs = cls.objects.all()
        if qs.count() > 0:
            yield qs[0]

    @classmethod
    def get_certifiable_fields(cls):
        """
        Expected to return a string with a space-separated list of field
        names.  These files will automaticaly become disabled (readonly)
        when the document is "certified". The default implementation
        returns an empty string, which means that no field will become
        disabled when the row is "certified".

        For example::

          @classmethod
          def get_certifiable_fields(cls):
              return 'date user title'

        """
        return ''

    @dd.displayfield(_("Printed"))
    def printed(self, ar):
        if ar is None:
            return ''
        ex = self.printed_by
        if ex is None:
            return ''
        return ar.obj2html(ex, naturaltime(ex.build_time))

    def clear_cache(self):
        obj = self.printed_by
        if obj is not None:
            self.printed_by = None
            self.full_clean()
            self.save()
            obj.delete()

    def get_excerpt_title(self):
        """A string to be used in templates as the title of the certifying
        document.

        """
        return unicode(self)

    def get_excerpt_templates(self, bm):
        """Return either `None` or a list of template names to be used when
        printing an excerpt controlled by this object.

        """
        return None
예제 #30
0
파일: models.py 프로젝트: einarfelix/xl
class Transaction(dd.Model):
    class Meta:
        app_label = 'b2c'
        abstract = dd.is_abstract_model(__name__, 'Transaction')
        verbose_name = _("Transaction")
        verbose_name_plural = _("Transactions")

    statement = dd.ForeignKey('b2c.Statement')
    seqno = models.IntegerField(
        _('No.'),
        help_text=_(
            "The sequence number of this transaction in the statement."))
    # unique_import_id = models.CharField(_('Unique import ID'), max_length=128)
    # movement_number = models.CharField(_("Ref of Mov"), null=False, max_length=32)
    # movement_date = models.DateField(_('Movement date'), null=True, blank=True)
    amount = dd.PriceField(_('Amount'), null=True, blank=True)
    # partner = dd.ForeignKey('contacts.Partner', related_name='b2c_movement', null=True)
    # partner_name = models.CharField(_('Partner name'), max_length=35, blank=True)
    remote_account = models.CharField(_("IBAN"), blank=True, max_length=64)
    remote_bic = BICField(verbose_name=_("BIC"), blank=True)
    # ref = models.CharField(_('Ref'), max_length=35, blank=True)
    message = models.TextField(_('Message'), blank=True)
    eref = models.CharField(_('End to end reference'),
                            max_length=128,
                            blank=True)
    remote_owner = models.CharField(_('Remote owner'),
                                    max_length=128,
                                    blank=True)
    remote_owner_address = models.TextField(_('Remote owner adress'),
                                            blank=True)
    remote_owner_city = models.CharField(_('Remote owner city'),
                                         max_length=32,
                                         blank=True)
    remote_owner_postalcode = models.CharField(_('Remote owner postal code'),
                                               max_length=10,
                                               blank=True)
    remote_owner_country_code = models.CharField(
        _('Remote owner country code'), max_length=4, blank=True)
    txcd = models.CharField(_('Transfer type'), max_length=32, blank=True)
    txcd_issuer = models.CharField(_('TxCd issuer'), max_length=35, blank=True)
    booking_date = models.DateField(_('Execution date'), null=True, blank=True)
    value_date = models.DateField(_('Value date'), null=True, blank=True)

    @dd.displayfield(_("Remote account"))
    def remote_html(self, ar):
        elems = []
        elems += [self.remote_account, " "]
        elems += ["(BIC:", self.remote_bic, ")"]
        elems.append(E.br())
        elems += [E.b(self.remote_owner), ", "]
        elems.append(E.br())
        elems += [" / ".join(self.remote_owner_address.splitlines()), ", "]
        elems += [self.remote_owner_postalcode, " "]
        elems += [self.remote_owner_city, " "]
        elems += [self.remote_owner_country_code]
        return E.div(*elems)

    @dd.displayfield(_("Message"))
    def message_html(self, ar):
        from django.utils.translation import ugettext as _
        elems = []
        # elems += [_("Date"), dd.fds(self.transaction_date), " "]
        # elems += [_("Amount"), ' ', E.b(unicode(self.amount)), " "]
        # self.booking_date
        elems += self.message  # .splitlines()
        elems.append(E.br())
        # elems += [_("ref:"), ': ', self.ref, ' ']
        elems += [_("eref:"), ': ', self.eref]
        elems.append(E.br())
        elems += [E.b(self.txcd_text), ' ']
        elems += [_("Value date"), ': ', E.b(dd.fds(self.value_date)), " "]
        elems += [_("Booking date"), ': ', E.b(dd.fds(self.booking_date)), " "]
        return E.div(*elems)

    @dd.displayfield(_("BkTxCd"))
    def txcd_text(self, ar):
        if self.txcd_issuer == 'BBA':
            # until we get a list of German translations, users in
            # Eupen prefer FR over EN
            with translation.override('fr'):
                return force_text(code2desc(self.txcd[:4]))
        return "{0}:{1}".format(self.txcd_issuer, self.txcd)