def check_if_has_run_today(): output_folder = get_output_folder() updater_file = output_folder / 'last_updated.txt' if updater_file.is_file(): with open(updater_file) as f: last_updated = Day(f.read()) if last_updated == Day(): print('Script has already run today: exiting') sys.exit() with open(updater_file, 'w') as f: f.write(str(Day()))
def main(): '''What it says: the main function''' cd_to_script_path() output_folder = get_output_folder() clear_the_cache = process_command_line_params() if clear_the_cache: clear_cache() load_cache() module_initialisations() copy_resources(output_folder) render_all_pages(output_folder)
DEF_SIZE, width=260, color=RED, ) for err in errs ] return VBlock([TextBlock("Errors", MID_SIZE)] + error_lines) # def project_type_chart(): # # Omzet per type project pie chart # data = omzet_per_type_project() # project_types = data['project_type'].tolist() # project_turnovers = omzet_per_type_project()['turnover'].tolist() # return PieChart( # 260, 520, 'omzet per type project', project_types, project_turnovers, ['#55C', '#C55', '#5C5', '#555', '#5CC'] # ) # # # def product_type_chart(): # # Omzet per product pie chart # product_types = omzet_per_type_product()['product_type'].tolist() # product_turnovers = omzet_per_type_product()['turnover'].tolist() # return PieChart( # 240, 520, 'omzet per product', product_types, product_turnovers, ['#5c5', '#C55', '#55C', '#555', '#5CC'] # ) if __name__ == "__main__": os.chdir("..") load_cache() render_dashboard(get_output_folder())
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') if __name__ == '__main__': os.chdir('..') render_vrije_dagen_page(get_output_folder())
), ), ]) 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') if __name__ == '__main__': os.chdir('..') render_resultaat_vergelijking_page(get_output_folder())
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))
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') if __name__ == '__main__': os.chdir('..') render_billable_page(get_output_folder())
corrections_coloring = lambda value: dependent_color( value.correcties_perc(), CORRECTIONS_RED, CORRECTIONS_GREEN) return kpi_grid( week_numbers, hours_data, verbose=verbose, effectivity_coloring=effectivity_coloring, corrections_coloring=corrections_coloring, ) def operations_data(weeks, total_period=None, total_title=''): monday = Day().last_monday() hours_data = [] headers = [] for w in range(weeks): monday_earlier = monday.plus_days(-7) period = Period(monday_earlier, monday) hours_data = [HoursData(period)] + hours_data headers = [monday_earlier.strftime('wk %W')] + headers monday = monday_earlier if total_period: headers += ['', total_title] hours_data += [None, HoursData(total_period)] return headers, hours_data if __name__ == '__main__': os.chdir('..') render_operations_page(get_output_folder())
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') if __name__ == '__main__': os.chdir('..') render_productiviteit_page(get_output_folder())
def report(render_year, render_month): print(f'\nGenerating report for {MAANDEN[render_month - 1]} {render_year}') render_maandrapportage(get_monthly_folder(), render_year, render_month) render_maandrapportage_page(get_monthly_folder(), get_output_folder())
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') if __name__ == '__main__': os.chdir('..') render_sales_page(get_output_folder())
max_y_axis=max_value, y_axis_max_ticks=5, ) return MultiScatterChart(chartdata, chart_config) def bar_chart(data, width, height): chartdata = [] for brand in BRANDS: values = [int(row[brand]) for _, row in data.iterrows()] chartdata += [values] z = list(zip(*chartdata)) max_value = max([sum(series) for series in zip(*chartdata)]) max_value = 100 * math.ceil(max_value / 100) chart_config = ChartConfig( width=width, height=height, colors=BAR_COLORS, min_y_axis=0, max_y_axis=max_value, y_axis_max_ticks=5, labels=BRANDS, bottom_labels=data['week'].tolist(), ) return StackedBarChart(chartdata, chart_config) if __name__ == '__main__': os.chdir(os.path.dirname(os.path.dirname(__file__))) render_travelbase_page(get_output_folder())
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') if __name__ == '__main__': os.chdir('..') period = Period('2021-01-01', '2022-01-01') render_winstgevendheid_page(get_output_folder(), period)
yuki_winst = omzet_tm_laatste_maand - projectkosten_tm_laatste_maand - kosten_tm_laatste_maand werkelijk = winst_werkelijk() begroot = winst_begroot() log('Yuki winst', yuki_winst) log('Winst werkelijk', werkelijk) log('Winst begroot', begroot) add_row( grid, 'Winst', yuki_winst, '', werkelijk, begroot, bold=True, ) return VBlock([TextBlock('Winstberekening', MID_SIZE), grid], block_id="Winstberekening") def render_resultaat_berekening(output_folder: Path): page = Page([HBlock([winst_berekening_block()])]) page.render(output_folder / 'resultaat_berekening.html') if __name__ == '__main__': os.chdir('..') clear_cache() render_resultaat_berekening(get_output_folder())
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') if __name__ == '__main__': os.chdir('..') render_debiteuren_page(get_output_folder())
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") if __name__ == "__main__": os.chdir("..") render_verzuim_page(get_output_folder())