Example #1
0
 def pretty_planned_hours(self):
     return _(
         "%(planned_hours)s in %(weeks)s weeks (%(per_week)s per week)") % {
             "planned_hours": hours(self.planned_hours),
             "weeks": len(self.weeks),
             "per_week": hours(self.planned_hours / len(self.weeks)),
         }
Example #2
0
def timer(request):
    return render(
        request,
        "timer.html",
        {
            "hours": {
                "today": hours(request.user.hours["today"]),
                "week": hours(request.user.hours["week"]),
            },
        },
    )
Example #3
0
def list_timestamps(request):
    form = SignedEmailUserForm(request.GET, request=request)
    if not form.is_valid():
        return JsonResponse({"errors": form.errors.as_json()}, status=400)

    user = form.cleaned_data["user"]
    slices = Timestamp.objects.slices(user)
    daily_hours = sum(
        (slice["logged_hours"].hours
         for slice in slices if slice.get("logged_hours")),
        Z1,
    )
    return JsonResponse({
        "success":
        True,
        "user":
        str(user),
        "hours":
        daily_hours,
        "timestamps": [{
            "timestamp":
            "{:>5} - {:>5} {:^7} {}".format(
                local_date_format(slice.get("starts_at"), fmt="H:i") or "?  ",
                local_date_format(slice.get("ends_at"), fmt="H:i") or "?  ",
                "({})".format(hours(slice.elapsed_hours, plus_sign=True))
                if slice.elapsed_hours is not None else "?",
                slice["description"] or "-",
            ),
            "elapsed":
            slice.elapsed_hours,
            "comment":
            slice.get("comment", ""),
        } for slice in slices],
    })
Example #4
0
 def amount(row):
     if row["service"].effort_rate is not None:
         return currency(row["not_archived"])
     elif row["logged_hours"]:
         return format_html(
             '{} <small class="bg-warning px-1">{}</small>',
             currency(row["not_archived"]),
             _("%s logged but no hourly rate defined.") %
             hours(row["logged_hours"]),
         )
     return currency(row["logged_cost"])
Example #5
0
def classify_logging_delay(delay):
    explanation = _("Average logging time is %s after noon.") % hours(delay)

    if delay < 3:
        return _("Promptly"), "success", explanation
    elif delay < 8:
        return _("Same day"), "light", explanation
    elif delay < 30:
        return _("Next day"), "caveat", explanation

    explanation = _("Average logging delay is %s.") % days(delay / 24)
    return _("Late"), "danger", explanation
Example #6
0
 def test_formats_hours(self):
     """Number formatting"""
     for value, result in [
         (Decimal("42.22"), "42.2h"),
         (Decimal("42.27"), "42.3h"),
         (Decimal("3"), "3.0h"),
         (Decimal("-123"), "-123.0h"),
         (Decimal("0.003"), "0.0h"),
         (Decimal("-0.003"), "0.0h"),
         (Decimal("12345"), "12’345.0h"),
         (None, "0.0h"),
     ]:
         with self.subTest(value=value, result=result):
             self.assertEqual(formats.hours(value), result)
Example #7
0
 def services_row_with_details(self, service):
     is_optional = getattr(service, "is_optional", False)
     return [
         (
             MarkupParagraph(
                 "<b>%s</b> %s<br/>%s" % (
                     sanitize(service.title),
                     _("(optional)") if is_optional else "",
                     sanitize(service.description),
                 ),
                 self.style.normal,
             ),
             "",
             "",
         ),
         (
             MarkupParagraph(
                 ", ".join(
                     filter(
                         None,
                         [
                             ("%s %s à %s/h" % (
                                 hours(service.effort_hours),
                                 service.effort_type,
                                 currency(service.effort_rate),
                             )) if service.effort_hours
                             and service.effort_rate else "",
                             ("{} {}".format(currency(service.cost),
                                             _("fixed costs")))
                             if service.cost else "",
                         ],
                     )),
                 self.style.normalWithExtraLeading,
             ),
             MarkupParagraph(
                 "<i>%s</i>" % currency(service.service_cost.quantize(Z)),
                 self.style.right,
             ) if is_optional else "",
             "" if is_optional else currency(
                 service.service_cost.quantize(Z)),
         ),
     ]
Example #8
0
def user_stats_pdf(data):
    with io.BytesIO() as buf:
        pdf = PDFDocument(buf, font_size=7)
        pdf.init_report()

        awt_columns = [9.5 * mm for i in range(12)]
        awt_columns.append(12 * mm)
        awt_columns.insert(0, pdf.bounds.E - pdf.bounds.W - sum(awt_columns))
        awt_table_style = pdf.style.tableHead + (("TOPPADDING", (0, 1),
                                                  (-1, -1), 3), )

        pdf.h1(data["user"])
        pdf.spacer(1 * mm)
        pdf.p(_("annual working time"))
        pdf.spacer(3 * mm)

        table = []
        table.append(
            [data["months"]["year"]] +
            [date_format(day, "M")
             for day in data["months"]["months"]] + [_("Total")])

        table.append([_("target days for full time employment")] +
                     data["months"]["target_days"] +
                     [data["totals"]["target_days"]])
        table.append([_("pensum")] +
                     ["%.0f%%" % p for p in data["months"]["percentage"]] +
                     ["%.0f%%" % data["totals"]["percentage"]])
        table.append([_("vacation days available")] + [
            days(value) for value in data["months"]["available_vacation_days"]
        ] + [days(data["totals"]["available_vacation_days"])])
        table.append([
            "%s (%s)" % (
                _("target time"),
                data["months"]["year"].pretty_working_time_per_day,
            )
        ] + [hours(value) for value in data["months"]["target"]] +
                     [hours(data["totals"]["target"])])
        table.append([_("vacation days taken")] + [
            days(value) if value else ""
            for value in data["months"]["absence_vacation"]
        ] + [days(data["totals"]["absence_vacation"])])
        table.append([_("sickness days")] + [
            days(value) if value else ""
            for value in data["months"]["absence_sickness"]
        ] + [days(data["totals"]["absence_sickness"])])
        if data["totals"]["absence_paid"]:
            table.append([_("Paid leave")] + [
                days(value) if value else ""
                for value in data["months"]["absence_paid"]
            ] + [days(data["totals"]["absence_paid"])])
        if data["totals"]["absence_correction"]:
            table.append([_("Working time correction")] + [
                days(value) if value else ""
                for value in data["months"]["absence_correction"]
            ] + [days(data["totals"]["absence_correction"])])
        if data["totals"]["vacation_days_correction"]:
            table.append([_("vacation days correction")] + [
                days(value) if value else ""
                for value in data["months"]["vacation_days_correction"]
            ] + [days(data["totals"]["vacation_days_correction"])])
        table.append(
            [_("countable absence hours")] +
            [hours(value) if value else ""
             for value in data["absences_time"]] +
            [hours(data["totals"]["absences_time"])])
        table.append([_("logged hours")] + [
            hours(value) if value else "" for value in data["months"]["hours"]
        ] + [hours(data["totals"]["hours"])])
        table.append(
            [_("working time")] +
            [hours(value) if value else "" for value in data["working_time"]] +
            [hours(data["totals"]["working_time"])])
        table.append([_("net work hours per month")] +
                     [hours(value) for value in data["monthly_sums"]] + [""])

        pdf.table(table, awt_columns, awt_table_style)
        pdf.spacer(1 * mm)

        table = []
        table.append([_("running net work hours")] +
                     [hours(value) for value in data["running_sums"]] +
                     [hours(data["totals"]["running_sum"])])

        if data["totals"]["vacation_days_credit"]:
            table.append([_("vacation days credit")] + [""] * 12 +
                         [days(data["totals"]["vacation_days_credit"])])

        table.append([_("balance")] + [""] * 12 +
                     [hours(data["totals"]["balance"])])

        pdf.table(
            table,
            awt_columns,
            awt_table_style + (("FONT", (0, 0),
                                (-1, 0), "Rep", pdf.style.fontSize), ),
        )
        pdf.spacer()

        table = []
        for employment in data["employments"]:
            table.append([
                employment,
                employment.percentage,
                "%.0f" % employment.vacation_weeks,
                employment.notes,
            ])

        if table:
            pdf.table(
                [[
                    _("employment"),
                    _("percentage"),
                    _("vacation weeks"),
                    _("notes")
                ]] + table,
                pdf.table_columns((35 * mm, 15 * mm, 20 * mm, None)),
                awt_table_style + (("ALIGN", (0, 0), (-1, -1), "LEFT"), ),
            )
            pdf.spacer()

        for key, reason in [
            ("absence_vacation", _("vacation days")),
            ("absence_sickness", _("sickness days")),
            ("absence_paid", _("Paid leave")),
            ("absence_correction", _("Working time correction")),
        ]:
            table = [[
                absence.pretty_period,
                days(absence.days), absence.description
            ] for absence in data["absences"][key]]
            if table:
                pdf.table(
                    [[reason, "", ""]] + table,
                    pdf.table_columns((35 * mm, 15 * mm, None)),
                    awt_table_style + (("ALIGN", (0, 0), (-1, -1), "LEFT"), ),
                )
                pdf.spacer()

        pdf.p(
            _("Generated on %(day)s") %
            {"day": local_date_format(dt.date.today())})

        pdf.generate()
        return buf.getvalue()
Example #9
0
 def pretty_working_time_per_day(self):
     return "%s/%s" % (hours(self.working_time_per_day), _("day"))
Example #10
0
 def pretty_working_time_per_day(self):
     return "{}/{}".format(hours(self.working_time_per_day), _("day"))
Example #11
0
 def __str__(self):
     u = self.user.get_short_name()
     h = hours(self.planned_hours)
     return f"{self.title} ({u}, {h}, {self.pretty_from_until})"
Example #12
0
 def __str__(self):
     return "{} ({})".format(self.title, hours(self.planned_hours))