Example #1
0
def render_vrije_dagen_page(output_folder: Path):

    table = VBlock([
        Table(
            vrije_dagen_overzicht(),
            TableConfig(
                headers=[
                    'Naam', 'Vorig jaar', 'Dit jaar nieuw',
                    'Dit jaar beschikbaar', 'Totaal', 'Pool'
                ],
                aligns=['left', 'right', 'right', 'right', 'right', 'right'],
                formats=['', '.5', '.5', '.5', '.5', '.5'],
                totals=[0, 0, 0, 0, 0, 1],
            ),
        ),
    ])

    page = Page([
        TextBlock('Vrije dagen', HEADER_SIZE),
        table,
        TextBlock(
            f'Pool = Dagen van vorig jaar + Dagen dit jaar * deel van het jaar dat is geweest ({fraction_of_the_year_past()*100:.0f}%).'
        ),
    ])
    page.render(output_folder / 'freedays.html')
Example #2
0
def render_onderhanden_werk_page(output_folder: Path):
    day = Day()
    page = Page([
        TextBlock(f'Onderhanden werk per {day.strftime("%d/%m")}',
                  HEADER_SIZE),
        onderhanden_werk_list(day)
    ])
    page.render(output_folder / 'onderhanden.html')
Example #3
0
def render_dashboard(output_folder):
    page = Page([
        HBlock([
            commerce_block(),
            operations_block(),
            finance_block(),
            hr_block()
        ])
    ])
    page.render(output_folder / "dashboard.html")
Example #4
0
def render_billable_page(output_folder: Path):
    users = sorted(tuple_of_productie_users())
    fromday = Day().plus_months(-6)
    period = Period(fromday)
    cols = 3
    rows = len(users) // cols + 1
    grid = Grid(rows, cols)
    row = 0
    col = 0
    for user in users:
        labels, hours = billable_trend_person_week(user, period)  # {weekno: hours} dict
        hours_data = HoursData(period, [user])
        chart = BarChart(
            hours,
            ChartConfig(
                width=400,
                height=220,
                colors=['#ddeeff'],
                bottom_labels=labels,
                max_y_axis=40,
                y_axis_max_ticks=5,
            ),
        )
        user_block = VBlock(
            [
                TextBlock(
                    f'{user} {hours_data.effectivity():.0f}%  / {hours_data.billable_perc():.0f}%', font_size=MID_SIZE
                ),
                chart,
            ]
        )
        grid.set_cell(row, col, user_block)
        col += 1
        if col == cols:
            col = 0
            row += 1

    page = Page(
        [
            TextBlock('Billable uren', HEADER_SIZE),
            TextBlock(
                'Billable uren per week het afgelopen halfjaar.<br/><br/>'
                + 'Grafiek toont uren gewerkt op billable projecten zonder rekening te houden met correcties.<br/>'
                + 'Percentages zijn effectiviteit en billable.',
                color="gray",
            ),
            grid,
        ]
    )
    page.render(output_folder / 'billable.html')
Example #5
0
def render_verzuim_page(output_folder: Path):
    timesheet = Timesheet()
    months = 3
    period = Period(Day().plus_months(-months))
    table = VBlock([
        Table(
            verzuim_list(period),
            TableConfig(
                headers=["Naam", "Dag", "soort", "Dagen"],
                aligns=["left", "left", "left", "right"],
                formats=[
                    "",
                    "",
                    "",
                    ".5",
                ],
                totals=[0, 0, 0, 1],
            ),
        ),
    ])

    verzuim = verzuimpercentage(period)
    verzuim_color = dependent_color(verzuim, 3, 1.5)
    page = Page([
        TextBlock("Verzuim", HEADER_SIZE),
        TextBlock(f"De afgelopen {months} maanden", color=GRAY),
        HBlock([
            VBlock([
                TextBlock("Geboekte uren", DEF_SIZE, color="gray", padding=5),
                TextBlock("Verzuim uren", DEF_SIZE, color="gray"),
                TextBlock("Verzuimopercentage", DEF_SIZE, color="gray"),
            ]),
            VBlock([
                TextBlock(
                    timesheet.normal_hours(period),
                    DEF_SIZE,
                    text_format=".",
                    padding=5,
                ),
                TextBlock(timesheet.absence_hours(period),
                          DEF_SIZE,
                          text_format="."),
                TextBlock(verzuim, verzuim_color, text_format="%1"),
            ]),
        ]),
        table,
    ])
    page.render(output_folder / "absence.html")
Example #6
0
def render_maandrapportage_page(monthly_folder, output_folder: Path):
    lines = []
    files = sorted(
        [f for f in monthly_folder.iterdir() if f.suffix == '.html'])
    for file in files:
        month_num = int(file.stem.split('_')[1])
        htmlpath = monthly_folder / file
        pdfpath = os.path.relpath(htmlpath.with_suffix('.pdf'),
                                  start=output_folder)
        htmlpath = os.path.relpath(htmlpath, start=output_folder)
        lines += [
            HBlock([
                TextBlock(MAANDEN[month_num - 1], url=htmlpath),
                TextBlock('pdf', url=pdfpath)
            ])
        ]
    page = Page([TextBlock('Maandrapportages', HEADER_SIZE)] + lines)
    page.render(output_folder / 'maandrapportages.html')
def render_resultaat_vergelijking_page():

    omzet = VBlock([
        TextBlock('Omzet vergelijking', MID_SIZE),
        LineChart(
            [
                omzet_per_maand(),
                omzet_begroot_per_maand(),
                omzet_vorig_jaar_per_maand()
            ],
            ChartConfig(
                width=900,
                height=600,
                labels=[
                    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
                    "Sep", "Oct", "Nov", "Dec"
                ],
                colors=['#4285f4', '#f4b400', '#db4437'],
                bottom_labels=['Omzet', 'Omzet begroot', 'Omzet vorig jaar'],
            ),
        ),
    ])

    winst = VBlock([
        TextBlock('Winst vergelijking', MID_SIZE),
        LineChart(
            [
                winst_per_maand(),
                winst_begroot_per_maand(),
                winst_vorig_jaar_per_maand()
            ],
            ChartConfig(
                width=900,
                height=600,
                labels=MAANDEN,
                colors=['#4285f4', '#f4b400', '#db4437'],
                bottom_labels=['Winst', 'Winst begroot', 'Winst vorig jaar'],
            ),
        ),
    ])

    page = Page([TextBlock('Resultaat', HEADER_SIZE), VBlock([omzet, winst])])

    page.render('output/resultaat_vergelijking.html')
Example #8
0
def render_travelbase_page(output_folder):
    bookings = get_bookings_per_week(booking_type='bookings')
    if not isinstance(bookings, pd.DataFrame):
        return  # An error occurred, no use to proceed
    totals = [(brand, bookings[brand].sum()) for brand in BRANDS]
    totals_table = Table(
        totals,
        TableConfig(aligns=['left', 'right'], formats=['', '0'], totals=[0,
                                                                         1]))
    page = Page([
        TextBlock('Travelbase', HEADER_SIZE),
        TextBlock(
            'Aantal boekingen per week. Weken lopen van maandag t/m zondag.',
            color='gray'),
        bar_chart(bookings, 600, 400),
        totals_table,
    ])

    page.render(output_folder / 'travelbase.html')
Example #9
0
def render_operations_page(output_folder: Path, year: int = None):
    weeks = 20
    if year:
        # Use given year. Create page with year name in it
        html_page = f'operations {year}.html'
    else:
        # Use the current year (default)
        year = int(datetime.datetime.today().strftime('%Y'))
        html_page = 'operations.html'
    total_period = Period(f'{year}-01-01', f'{year + 1}-01-01')
    page = Page([
        TextBlock('Operations KPI'
                  's', HEADER_SIZE),
        TextBlock(
            f"Belangrijkste KPI's per week de afgelopen {weeks} weken",
            color="gray",
        ),
        kpi_block(weeks=weeks, total_period=total_period, total_title='YTD'),
    ])
    page.render(output_folder / html_page)
Example #10
0
def render_maandrapportage(output_folder, year, month):
    yuki_result = YukiResult(year, month)
    page = Page([
        VBlock([
            TextBlock(f'Maandrapportage {MAANDEN[month - 1].lower()}, {year}',
                      HEADER_SIZE),
            hours_block(year, month),
            profit_and_loss_block(yuki_result, year, month),
            balance_block(yuki_result, year, month),
            # HBlock([cash_block(), debiteuren_block()]),
            cashflow_analysis_block(yuki_result, year, month),
        ])
    ])
    htmlpath = output_folder / f'{year}_{month:02}.html'
    page.render(htmlpath, template='maandrapportage.html')

    # Generate PDF
    pdfpath = htmlpath.with_suffix('.pdf')
    options = {"enable-local-file-access": None}
    pdfkit.from_file(str(htmlpath), str(pdfpath), options=options)
Example #11
0
def render_debiteuren_page(output_folder: Path):
    debiteuren = debiteuren_leeftijd_analyse()
    if not isinstance(debiteuren, pd.DataFrame):
        return  # Error occurred, no use to proceed
    page = Page([
        TextBlock('Debiteuren', HEADER_SIZE),
        Table(
            debiteuren,
            TableConfig(
                headers=[
                    'klant', 'openstaand', '<30 dg', '30-60 dg', '60-90 dg',
                    '> 90 dg'
                ],
                aligns=['left', 'right', 'right', 'right', 'right', 'right'],
                formats=['', '.', '.', '.', '.', '.'],
                totals=[0, 1, 1, 1, 1, 1],
                row_linking=lambda line, value:
                'https://oberview.oberon.nl/facturen/openstaand',
            ),
        ),
    ])
    page.render(output_folder / 'debiteuren.html')
Example #12
0
def render_sales_page(output_folder: Path):

    sales_trajecten = VBlock([
        TextBlock('Actieve&nbsp;salestrajecten', MID_SIZE),
        Table(
            sales_waarde_details(),
            TableConfig(
                headers=[
                    'klant', 'project', 'grootte', 'kans', 'fase', 'waarde',
                    'bron'
                ],
                aligns=[
                    'left', 'left', 'right', 'right', 'left', 'right', 'left'
                ],
                formats=['', '', '€', '%', '', '€', ''],
                totals=[0, 0, 1, 0, 0, 1, 0],
            ),
        ),
    ])

    pijplijn = VBlock([
        TextBlock('Werk&nbsp;in&nbsp;de&nbsp;pijplijn', MID_SIZE),
        TextBlock('Moet uit Simplicate komen'),
        # Table(
        #     werk_in_pijplijn_details(),
        #     TableConfig(
        #         headers=['klant', 'project', '% af', 'onderhanden', 'eigenaar'],
        #         aligns=['left', 'left', 'right', 'right', 'left'],
        #         formats=['', '', '%', '€', ''],
        #         totals=[0, 0, 0, 1, 0],
        #     ),
        # ),
    ])

    page = Page(
        [TextBlock('Sales', HEADER_SIZE),
         HBlock([sales_trajecten, pijplijn])])

    page.render(output_folder / 'sales.html')
Example #13
0
def render_productiviteit_page():
    tables = HBlock([
        Table(
            productiviteit_overzicht(),
            block_id='overzicht',
            headers=[
                'persoon',
                'omzet',
                'uren',
                'per uur',
                'geboekt',
                'productief',
                '% productief',
                'billable',
                '% billable',
            ],
            aligns=[
                'left', 'right', 'right', 'right', 'right', 'right', 'right',
                'right', 'right'
            ],
            formats=['', '€', '.', '€', '.', '.', '%', '.', '%'],
            totals=[0, 1, 1, 0, 1, 1, 0, 1, 0],
        )
    ])

    for user in tuple_of_productie_users():
        data = productiviteit_persoon(user)
        target = user_target(user)
        if target:
            total = sum([row[3] for row in data])
            perc = (total / user_target_now(user) - 1) * 100
            percstr = do_format(perc, '+%')
            targetstr = f'target: € {target:,.0f}'.replace(',', '.')
        else:
            targetstr = percstr = ''
        tables.add_block(
            Table(
                data,
                block_id='productiviteit_' + user,
                headers=[user, targetstr, percstr, 'omzet', 'uren', 'per uur'],
                aligns=['left', 'left', 'left', 'right', 'right', 'right'],
                formats=['', '', '', '€', '.', '€'],
                totals=[0, 0, 0, 1, 1, 0],
            ))

    page = Page([
        TextBlock('Productiviteit', HEADER_SIZE),
        VBlock([TextBlock('Under construction', color='red'), tables])
    ])
    page.add_onloadcode('make_users_clickable();')
    page.render('output/productiviteit.html')

    for user in tuple_of_productie_users():
        productiviteit_table = Table(
            productiviteit_persoon(user),
            headers=[user, '', '', 'omzet', 'uren', 'per uur'],
            aligns=['left', 'left', 'left', 'right', 'right', 'right'],
            formats=['', '', '', '€', '.', '€'],
            totals=[0, 0, 0, 1, 1, 0],
        )

        chartdata = [{
            'x': rec['datum'].strftime('%Y-%m-%d'),
            'y': rec['hours']
        } for rec in billable_trend_person(user)]
        chart = ScatterChart(400,
                             400,
                             values=chartdata,
                             color='#6666cc',
                             fill_color='#ddeeff',
                             y_start=0,
                             x_type='date')

        page = Page([
            TextBlock(f'Productiviteit {user}', HEADER_SIZE), chart,
            productiviteit_table
        ])
        page.render(f'output/productiviteit_{user}.html')
Example #14
0
def render_resultaat_berekening(output_folder: Path):

    page = Page([HBlock([winst_berekening_block()])])
    page.render(output_folder / 'resultaat_berekening.html')
Example #15
0
def render_winstgevendheid_page(output_folder: Path, period=None):
    if period:
        period_description = f'Van {period.fromday} tot {period.untilday}'
    if not period:
        period = Period(Day().plus_months(-12))  # Laatste 12 maanden
        period_description = 'De laatste 12 maanden.'
    client_data = winst_per_klant(period)
    per_client = VBlock([
        TextBlock('Per klant', MID_SIZE),
        Table(
            client_data,
            TableConfig(
                id="winst_per_klant",
                headers=list(client_data.columns),
                aligns=[
                    'left', 'right', 'right', 'right', 'right', 'right',
                    'right', 'right'
                ],
                formats=['', '.', '€', '€', '€', '€', '€', '€'],
                totals=[False, True, True, True, True, True, False, False],
            ),
        ),
    ])

    project_data = winst_per_project(period)
    per_project = VBlock([
        TextBlock('Per project', MID_SIZE),
        Table(
            project_data,
            TableConfig(
                id="winst_per_project",
                headers=list(project_data.columns),
                aligns=[
                    'left', 'left', 'right', 'right', 'right', 'right',
                    'right', 'right', 'right'
                ],
                formats=['', '', '.', '€', '€', '€', '€', '€', '€'],
                totals=[
                    False, False, True, True, True, True, True, False, False
                ],
            ),
        ),
    ])

    person_data = winst_per_persoon(period)
    per_person = VBlock([
        TextBlock('Per persoon (voorlopig)', MID_SIZE),
        Table(
            person_data,
            TableConfig(
                id="winst_per_persoon",
                headers=list(person_data.columns),
                aligns=['left', 'right', 'right', 'right'],
                formats=['', '.', '€', '€'],
                totals=[False, True, True, True],
            ),
        ),
    ])

    page = Page([
        TextBlock('Winstgevendheid', HEADER_SIZE),
        TextBlock(
            f'''{period_description} Uitgaande van een productiviteit van {PRODUCTIVITEIT * 100:.0f}% 
                               en €{OVERIGE_KOSTEN_PER_FTE_PER_MAAND} per persoon per maand bureaukosten.''',
            color=GRAY,
        ),
        HBlock([per_client, per_project, per_person]),
    ])
    page.render(output_folder / 'winstgevendheid.html')
Example #16
0
    return grid


def render_onderhanden_werk_page(output_folder: Path):
    day = Day()
    page = Page([
        TextBlock(f'Onderhanden werk per {day.strftime("%d/%m")}',
                  HEADER_SIZE),
        onderhanden_werk_list(day)
    ])
    page.render(output_folder / 'onderhanden.html')


if __name__ == '__main__':
    os.chdir('..')
    load_cache()

    days = [Day('2022-1-1'), Day()]
    for test_day in days:
        test_page = Page([
            TextBlock(f'Onderhanden werk per {test_day.strftime("%d/%m")}',
                      HEADER_SIZE),
            onderhanden_werk_list(test_day),
        ])
        if test_day == Day():
            test_page.render(get_output_folder() / 'onderhanden.html')
        else:
            test_page.render(get_output_folder() /
                             f'onderhanden{test_day}.html')
        print(test_day, ohw_sum(test_day, minimal_intesting_value=1000))
Example #17
0
def render_detailpage():
    data = [[key, saved_cache[key]] for key in sorted(saved_cache.keys())]
    page = Page([Table(data)])
    page.render('output/details.html')