def percentage_directe_werknemers(): """DDA Cijfer. Is het percentage productiemedewerkers tov het geheel""" period = Period(Day().plus_months(-6)) productie_users = tuple_of_productie_users() return (100 * beschikbare_uren_volgens_rooster( period, employees=productie_users)[0] / beschikbare_uren_volgens_rooster(period)[0])
def hours_block(year, month): month_names = [] data = [] for m in range(month): month_names += [TextBlock(MAANDEN[m])] fromday = Day(year, m + 1, 1) untilday = fromday.plus_months(1) period = Period(fromday, untilday) data += [HoursData(period)] headers = month_names + ['', 'YTD'] curyear = datetime.datetime.today().strftime('%Y') total_period = Period(curyear + '-01-01') data += [None, HoursData(total_period)] grid = kpi_grid(headers, data) chart = None if month >= 3: # Voor maart heeft een grafiekje niet veel zin chart = BarChart( [d.omzet for d in data[:-2]], # -2 is lelijk maar haalt de total col eraf ChartConfig( width=60 * month, height=150, colors=['#ddeeff'], bottom_labels=[MAANDEN[m] for m in range(month)], y_axis_max_ticks=5, ), ) return VBlock([ TextBlock('Billable uren', MID_SIZE), TextBlock( '''Beschikbare uren zijn alle uren die we hebben na afrek van vrije dagen en verzuim.<br/> Klant uren zijn alle uren besteed aan werk voor klanten. <br/> Billable uren is wat er over is na correcties. <br/> Omzet is de omzet gemaakt in die uren.''', color=GRAY, ), grid, VBlock([TextBlock('Omzet op uren per maand'), chart], css_class="no-print"), ])
def testqueries(): df = hours_dataframe() def get_diff(row): return row['tariff'] and not (row['tariff'] > 0) # diff = df.apply( get_diff, axis=1 ) users = None # ['Jurriaan Ruitenberg'] #['Caspar Geerlings', 'Kevin Lobine'] day = Day('2021-01-08') end_day = Day('2021-02-01') period = Period(day, end_day) oud = geboekt_oud(period, users=users, only_clients=1, only_billable=1) oudsum = int(oud['hours'].sum() + oud['corrections'].sum()) oudhours = int(oud['hours'].sum()) oudcorr = int(oud['corrections'].sum()) nieuw = geboekt_nieuw(period, users=users, only_clients=1, only_billable=1) nieuwsum = int(nieuw['hours'].sum() + nieuw['corrections'].sum()) nieuwhours = int(nieuw['hours'].sum()) nieuwcorr = int(nieuw['corrections'].sum()) if oudsum != nieuwsum: a = 1 while day < end_day: print(day) next = day.next() period = Period(day, next) oud = geboekt_oud(period, users=users, only_clients=1, only_billable=1) oud_per_user = oud.groupby(['employee'])[['corrections']].sum() oudsum = int(oud['corrections'].sum()) nieuw = geboekt_nieuw(period, users=users, only_clients=1, only_billable=1) nieuw_per_user = nieuw.groupby(['employee'])[['corrections']].sum() nieuwsum = int(nieuw['corrections'].sum()) if oudsum != nieuwsum: a = 1 day = next pass
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')
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
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 update_omzet_per_week(): """Tabel van dag, omzet waarbij dag steeds de maandag is van de week waar het om gaat""" trends = TrendLines() trend_name = 'omzet_per_week' last_day = trends.second_last_registered_day( trend_name) # Always recalculate the last since hours may have changed y, m, d = str(last_day).split('-') last_day = BeautifulDate( int(y), int(m), int(d)) - MO # Last Monday on or before the last calculated day last_sunday = D.today() - SU for monday in drange(last_day, last_sunday, 7 * days): sunday = monday + 6 * days period = Period(monday, monday + 7 * days) week_turnover = get_turnover_from_simplicate(period) # if monday < BeautifulDate(2021, 1, 1): # week_turnover += get_turnover_from_extranet(monday, sunday) trends.update(trend_name, week_turnover, monday)
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_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)
def verzuim_block(): period = Period(Day().plus_months(-3)) verzuim = verzuimpercentage(period) verzuim_color = dependent_color(verzuim, 3, 1.5) return VBlock( [ TextBlock("Verzuim", MID_SIZE), TextBlock("Verzuimpercentage de laatste 3 maanden", DEF_SIZE, color=GRAY), TextBlock( verzuim, MID_SIZE, text_format="%1", color=verzuim_color, tooltip= "Gemiddeld bij DDA in 2019: 3.0%. Groen bij 1,5%, rood bij 3%", ), ], link="absence.html", )
) for i in range(1, 8)] untilday = period.untilday if period.untilday else Day() ending_day_of_roster = min(timetable.get("end_date", "9999"), untilday.str) while day.str < ending_day_of_roster: index = day.week_number() % 2 tot += table[day.day_of_week()][index] day = day.next() # Vrij timesheet = Timesheet() leave = timesheet.leave_hours(period, employees) # Ziek absence = timesheet.absence_hours(period, employees) return float(tot), float(leave), float(absence) if __name__ == "__main__": os.chdir("..") load_cache() h = hours_dataframe() period_ = Period("2021-06-01", "2021-10-01") # Get the list of current employees employees_ = set(hours_dataframe(period_).employee.unique()) for e in employees_: r, v, z = beschikbare_uren_volgens_rooster(period_, [e])
# 3. Get the balance for this year this_year_balance = this_year.groupby(['employee_name']).sum('hours')['hours'] / 8 # 4. Get the days # 4. Put them all in one overview overview = pd.concat([year_start, this_year_new, this_year_balance], axis=1).fillna(0) overview.columns = ['year_start', 'this_year_new', 'this_year_balance'] # 5. Plus extra calculated columns overview['available'] = overview.apply(lambda x: x['year_start'] + x['this_year_balance'], axis=1) # Pool = Last + Year * Frac - Done overview['pool'] = overview.apply(lambda x: x['year_start'] + x['this_year_new'] * frac, axis=1) overview.reset_index(level=0, inplace=True) return overview def vrije_dagen_pool(): vrije_dagen_overschot = vrije_dagen_overzicht()['pool'].sum() FTEs = aantal_fte() return vrije_dagen_overschot / FTEs if __name__ == '__main__': os.chdir('..') period = Period(Day().plus_days(-10)) print(verzuim_list(period)) print(verzuim_list2(period))
def flatten_json(y): out = {} def flatten(x, name=""): if type(x) is dict: for a in x: flatten(x[a], name + a + "_") elif type(x) is list: i = 0 for a in x: flatten(a, name + str(i) + "_") i += 1 else: out[name[:-1]] = x flatten(y) return out if __name__ == "__main__": os.chdir("..") load_cache() day = Day("2022-01-01") sim = simplicate() invoiced = invoiced_per_customer(sim, Period("2021-01-01", "2022-01-01")) pass # ohw = ohw_list(date) # print(ohw) # print(ohw['ohw'].sum())
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')
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)