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')
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")
def commerce_block(): minimal_interesting_amount = 20000 sales_waarde_value = sales_waarde() top_sales = top_x_sales(minimal_amount=minimal_interesting_amount) sales_waarde_color = dependent_color(sales_waarde_value, 250000, 350000) commerce = VBlock([ TextBlock("Commerce", HEADER_SIZE), TextBlock("Saleswaarde", MID_SIZE, padding=10), TextBlock( "Verwachte omzet maal kans van alle actieve<br/>salestrajecten.", color=GRAY, ), TextBlock( sales_waarde_value, HEADER_SIZE, text_format="K", color=sales_waarde_color, tooltip="Som van openstaande trajecten<br/>maal hun kans.", ), TrendLines().chart("sales_waarde", 250, 150, min_y_axis=0, x_start=months_ago(6)), VBlock( [ TextBlock(f"Top {len(top_sales)} sales kansen", MID_SIZE), TextBlock( f"Met een verwachte waarde van minimaal € {minimal_interesting_amount}.", color=GRAY, ), Table( top_sales, TableConfig(headers=[], aligns=["left", "right"], formats=["", "€"]), ), ], link="sales.html", ), # klanten_block() travelbase_block(), ]) return commerce
def corrections_block(): weeks_back = 4 interesting_correction = 8 period = Period(Day().plus_weeks(-weeks_back)) def corrections_percentage_coloring(value): return dependent_color(value, red_treshold=5, green_treshold=3) def project_link(_, fullline): return f"https://oberon.simplicate.com/projects/{fullline[0]}/hours" result = VBlock( [ TextBlock("Correcties", MID_SIZE), HBlock( [ TextBlock( corrections_percentage(period), MID_SIZE, text_format="%", color=corrections_percentage_coloring, ), TextBlock( f"correcties op uren van<br/> week {period.fromday.week_number()} " + f"tot en met week {period.fromday.week_number() + weeks_back - 1}.", color=GRAY, ), ], padding=70, ), Table( largest_corrections(interesting_correction, period), TableConfig( headers=[], aligns=["left", "left", "right"], hide_columns=[0], row_linking=project_link, ), ), ], link="corrections.html", ) return result
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')
def klanten_block(): klanten = VBlock( [ TextBlock("Klanten", MID_SIZE), TextBlock("Top 3 klanten laatste 6 maanden", DEF_SIZE, padding=10, color=GRAY), Table( top_x_klanten_laatste_zes_maanden(3), TableConfig( headers=[], aligns=["left", "right", "right"], formats=["", "€", "%"], totals=[0, 0, 1], ), ), ], link="clients.html", ) return klanten
def render_sales_page(output_folder: Path): sales_trajecten = VBlock([ TextBlock('Actieve 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 in de 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')
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')
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')