예제 #1
0
파일: models.py 프로젝트: einarfelix/xl
def inject_summary_fields(sender, **kw):
    SiteSummary = rt.models.working.SiteSummary
    UserSummary = rt.models.working.UserSummary
    WorkSite = rt.models.tickets.Site
    Ticket = dd.plugins.working.ticket_model
    for t in ReportingTypes.get_list_items():
        k = t.name + '_hours'
        dd.inject_field(SiteSummary, k,
                        dd.DurationField(t.text, null=True, blank=True))
        dd.inject_field(UserSummary, k,
                        dd.DurationField(t.text, null=True, blank=True))
        dd.inject_field(Ticket, k,
                        dd.DurationField(t.text, null=True, blank=True))

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

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

            return getter

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

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

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

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

                    return getter

                dd.inject_field(
                    WorkSite, k,
                    dd.VirtualField(dd.DisplayField(ts.text), make_getter(ts)))
예제 #2
0
class InvestedTime(dd.Table):
    @dd.virtualfield(dd.DurationField(_("Time")))
    def invested_time(cls, obj, ar):
        return obj._invested_time

    @dd.displayfield(_("Description"))
    def my_description(cls, obj, ar):
        mi = ar.master_instance
        if mi is None:
            return
        lst = [obj.summary]
        tpl = u"{0}: {1}"
        # if obj.site is not None and obj.site == mi.interesting_for:
        #     lst.append(_("site-specific"))
        if obj.site is not None:  # and obj.site != mi.interesting_for:
            lst.append(tpl.format(ensureUtf(_("Site")), ensureUtf(obj.site)))
        if obj.user is not None:
            lst.append(tpl.format(ensureUtf(_("Author")), ensureUtf(obj.user)))
        # if obj.project is not None:
        #     lst.append(tpl.format(
        #         ensureUtf(_("Project")), ensureUtf(obj.project)))
        # if obj.topic is not None:
        #     lst.append(tpl.format(
        #         ensureUtf(_("Topic")), ensureUtf(obj.topic)))
        return E.p(*join_elems(lst, '. '))
예제 #3
0
class TimeInvestment(Commentable):
    class Meta:
        abstract = True

    closed = models.BooleanField(_("Closed"), default=False)

    planned_time = dd.DurationField(_("Planned time"), blank=True, null=True)
예제 #4
0
파일: models.py 프로젝트: einarfelix/xl
class EventType(mixins.BabelNamed, Referrable, mixins.Sequenced, MailableType):
    templates_group = 'cal/Event'
    ref_max_length = 4

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

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

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

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

    planner_column = PlannerColumns.field(blank=True)

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

    default_duration = dd.DurationField(_("Default duration"),
                                        blank=True,
                                        null=True)
예제 #5
0
        def w(rpttype, verbose_name):
            def func(fld, obj, ar):
                return obj._root2tot.get(rpttype, None)

            return dd.VirtualField(dd.DurationField(verbose_name), func)
예제 #6
0
def rpttype2vf(func, rpttype, verbose_name):
    return dd.VirtualField(dd.DurationField(verbose_name), func)
예제 #7
0
class Site(Referrable, ContactRelated, Starrable, DateRange):
    class Meta:
        app_label = 'tickets'
        verbose_name = pgettext("Ticketing", "Site")
        verbose_name_plural = pgettext("Ticketing", "Sites")
        abstract = dd.is_abstract_model(__name__, 'Site')

    ref_max_length = 20
    workflow_state_field = "state"

    #     partner = dd.ForeignKey('contacts.Partner', blank=True, null=True)
    #     # responsible_user = dd.ForeignKey(
    #     #     'users.User', verbose_name=_("Responsible"),
    #     #     blank=True, null=True)
    #     name = models.CharField(_("Designation"), max_length=200)
    child_starrables = [(milestone_model, 'site', None),
                        ('tickets.Ticket', 'site', None)]

    description = dd.RichTextField(_("Description"), blank=True)
    remark = models.CharField(_("Remark"), max_length=200, blank=True)
    name = models.CharField(_("Designation"), max_length=200, unique=True)
    reporting_type = ReportingTypes.field(blank=True)
    deadline = models.DateField(verbose_name=_("Deadline"),
                                blank=True,
                                null=True)

    state = SiteStates.field(default='draft')
    group = dd.ForeignKey('groups.Group', null=True, blank=True)
    hours_paid = dd.DurationField(_("Hours paid"), blank=True, null=True)
    private = models.BooleanField(_("Private"), default=False)

    def __str__(self):
        return self.ref or self.name

    def get_change_observers(self, ar=None):
        for s in rt.models.tickets.Subscription.objects.filter(site=self):
            yield (s.user, s.user.mail_mode)

    def get_row_permission(self, ar, state, ba):
        """
        User has permission if:
        is tickets staff
        if a member of it's group
        is subscribed
        is contact person
        is contact person of org

        Currently only checks for is group member and role...
        """

        if not super(Site, self).get_row_permission(ar, state, ba):
            return False

        if ((self.group and
             self.group.members.filter(user__id=ar.get_user().id).count() == 0)
                and not ar.get_user().user_type.has_required_roles(
                    [TicketsStaff])):
            return False
        return True

    @classmethod
    def get_user_queryset(cls, user):
        qs = super(Site, cls).get_user_queryset(user)
        if user.is_anonymous:
            qs = qs.filter(private=False)
        elif not user.user_type.has_required_roles([TicketsStaff]):
            qs = qs.filter(Q(private=False)
                           | Q(group__members__user=user)).distinct()
        return qs

    @classmethod
    def add_param_filter(cls,
                         qs,
                         lookup_prefix='',
                         show_exposed=None,
                         **kwargs):
        qs = super(Site, cls).add_param_filter(qs, **kwargs)
        exposed_states = SiteStates.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

    @dd.htmlbox(_("Description"))
    def parsed_description(self, ar):
        if ar is None:
            return ''
        html = ''
        if self.description:
            html += ar.parse_memo(self.description)
        return html

    def get_overview_elems(self, ar):
        elems = []
        if self.ref:
            txt = "{} {}".format(self.ref, self.name)
        else:
            txt = self.name
        elems.append(E.h2(txt))
        if self.description:
            elems += rich_text_to_elems(ar, self.description)
        return elems
예제 #8
0
파일: models.py 프로젝트: einarfelix/xl
class Session(UserAuthored, Started, Ended, Workable):
    class Meta:
        app_label = 'working'
        verbose_name = _("Session")
        verbose_name_plural = _('Sessions')
        abstract = dd.is_abstract_model(__name__, 'Session')

    ticket = dd.ForeignKey(dd.plugins.working.ticket_model,
                           related_name="sessions_by_ticket")

    session_type = dd.ForeignKey('working.SessionType', null=True, blank=True)
    summary = models.CharField(_("Summary"),
                               max_length=200,
                               blank=True,
                               help_text=_("Summary of the session."))
    description = dd.RichTextField(_("Description"), blank=True)
    # break_time = models.TimeField(
    #     blank=True, null=True,
    #     verbose_name=_("Break Time"))
    break_time = dd.DurationField(_("Break Time"), blank=True, null=True)
    faculty = dd.ForeignKey('skills.Skill',
                            related_name="sessions_by_faculty",
                            blank=True,
                            null=True)

    reporting_type = ReportingTypes.field(blank=True)
    is_fixing = models.BooleanField(_("Fixing"), default=False)
    if settings.USE_TZ:
        time_zone = TimeZones.field()
    else:
        time_zone = dd.DummyField()

    end_session = EndThisSession()
    show_today = ShowMySessionsByDay('start_date')

    # print_activity_report = PrintActivityReport()

    def __str__(self):
        if self.start_time and self.end_time:
            return u"%s %s-%s" % (
                self.start_date.strftime(settings.SITE.date_format_strftime),
                self.start_time.strftime(settings.SITE.time_format_strftime),
                self.end_time.strftime(settings.SITE.time_format_strftime))
        return "%s # %s" % (self._meta.verbose_name, self.pk)

    def get_ticket(self):
        return self.ticket

    def on_create(self, ar):
        super(Session, self).on_create(ar)
        if settings.USE_TZ:
            self.time_zone = self.user.time_zone or \
                             rt.models.about.TimeZones.default

    def get_time_zone(self):
        return self.time_zone

    def full_clean(self, *args, **kwargs):
        if self.user_id and not self.time_zone:
            # can be removed when all production sites have migrated:
            self.time_zone = self.user.time_zone or \
                             rt.models.about.TimeZones.default

        if not settings.SITE.loading_from_dump:
            if self.start_time is None:
                self.set_datetime('start', timezone.now())
                # value = timezone.now()
                # if pytz:
                #     tz = pytz.timezone(self.get_timezone())
                #     value = value.astimezone(tz)
                # self.start_time = value.time()
            if self.start_date is None:
                self.start_date = dd.today()
            # if self.ticket_id is not None and self.faculty_id is None:
            #     self.faculty = self.ticket.faculty
            if self.end_time is not None:
                if self.end_date is None:
                    self.end_date = self.start_date
            if self.ticket_id:
                self.ticket.on_worked(self)

        super(Session, self).full_clean(*args, **kwargs)

    def unused_save(self, *args, **kwargs):
        if not settings.SITE.loading_from_dump:
            if self.start_date is None:
                self.start_date = dd.today()
            if self.start_time is None:
                self.start_time = timezone.now().time()
        super(Session, self).save(*args, **kwargs)

    def get_reporting_type(self):
        if self.reporting_type:
            return self.reporting_type
        t = self.get_ticket()
        if t.ticket_type and t.ticket_type.reporting_type:
            return t.ticket_type.reporting_type
        if t.site and t.site.reporting_type:
            return t.site.reporting_type
        # if t.project and t.project.reporting_type:
        #     return t.project.reporting_type
        return dd.plugins.working.default_reporting_type

    # def after_ui_save(self, ar, cw):
    #     super(Session, self).after_ui_save(ar, cw)
    #     if self.ticket_id:
    #         self.ticket.on_worked(self, ar, cw)

    def get_root_project(self):
        """Return the root project for this session (or None if session has no
        ticket).

        """
        if self.ticket and self.ticket.project:
            return self.ticket.project.get_parental_line()[0]

    def get_duration(self):
        """Return the duration in hours as a
        :class:`lino.utils.quantities.Quantity`.  This inherits from
        :meth:`StartedEnded
        <lino_xl.lib.cal.mixins.StartedEnded.get_duration>` but
        removes :attr:`break_time` if specified.

        """
        diff = super(Session, self).get_duration()
        if diff and self.break_time:
            diff -= self.break_time
        return diff

        # if self.end_time is None:
        #     diff = datetime.timedelta()
        # else:
        #     diff = self.get_datetime('end') - self.get_datetime('start')
        #     if self.break_time is not None:
        #         diff -= self.break_time
        # return Duration(diff)

    @dd.displayfield(_("Ticket #"))
    def ticket_no(self, ar):
        if ar is None:
            return self.ticket_id
        return self.ticket.obj2href(ar)  # self.ticket_id)

    @dd.displayfield(_("Site"))
    def site_ref(self, ar):
        if not self.ticket:
            return ''
        site = self.ticket.site
        if site is None:
            return ''
        if ar is None:
            return str(site)
        return site.obj2href(ar)