Spaces:
Runtime error
Runtime error
from datetime import datetime | |
from typing import Dict, List | |
import pandas as pd | |
from dateutil.parser import parse | |
from type_alias import EARLY_MODE, LATE_MODE | |
class WorkingTime(object): | |
def __init__(self, date: datetime, checkin: str, checkout: str, | |
config) -> None: | |
self.MORNING_IN = parse(config.WORKING_TIME.MORNING_IN) | |
self.MORNING_OUT = parse(config.WORKING_TIME.MORNING_OUT) | |
self.AFTERNOON_IN = parse(config.WORKING_TIME.AFTERNOON_IN) | |
self.AFTERNOON_OUT = parse(config.WORKING_TIME.AFTERNOON_OUT) | |
self.LATE_TIME: Dict[str, int] = dict( | |
morning_in=config.LATE.MORNING_IN, | |
morning_out=config.LATE.MORNING_OUT, | |
afternoon_in=config.LATE.AFTERNOON_IN, | |
afternoon_out=config.LATE.AFTERNOON_OUT) | |
self.ROUND_GAP = config.WORKING_TIME.ROUND_GAP | |
self.date = datetime.strftime(date, "%d/%m/%Y") | |
self.error: bool = False | |
if checkin == 0: | |
# self.checkin = -1 | |
self.error = True | |
else: | |
self.checkin = parse(checkin) | |
if self.checkin < self.MORNING_IN: | |
self.checkin = parse("08:00") | |
if checkout == 0: | |
# self.checkout = -1 | |
self.error = True | |
else: | |
self.checkout = parse(checkout) | |
if self.checkout > self.AFTERNOON_OUT: | |
self.checkout = parse("17:00") | |
def __repr__(self) -> str: | |
return "{" + ";\n".join(f"{k}={getattr(self, k)}" | |
for k in self.__dict__) + "}" | |
def get_late_checkin(self, time: datetime, mode: LATE_MODE) -> int: | |
is_penalty_count: int = 0 | |
if mode == 'morning_in': | |
target_time: datetime = self.MORNING_IN | |
acceptable: int = self.LATE_TIME.get('MORNING_IN', 30) | |
elif mode == 'afternoon_in': | |
target_time: datetime = self.AFTERNOON_IN | |
acceptable: int = self.LATE_TIME.get('AFTERNOON_IN', 30) | |
if time < target_time: | |
return 0 | |
late_time = (time - target_time).seconds // 60 | |
if late_time > acceptable: | |
is_penalty_count = 1 | |
return is_penalty_count * late_time | |
def get_early_checkout(self, time: datetime, mode: EARLY_MODE) -> int: | |
is_penalty_count: int = 0 | |
if mode == 'morning_out': | |
target_time: datetime = self.MORNING_OUT | |
acceptable: int = self.LATE_TIME.get('MORNING_OUT', 0) | |
elif mode == 'afternoon_out': | |
target_time: datetime = self.AFTERNOON_OUT | |
acceptable: int = self.LATE_TIME.get('AFTERNOON_OUT', 0) | |
if time > target_time: | |
return 0 | |
early_time = (target_time - time).seconds // 60 | |
if early_time > acceptable: | |
is_penalty_count = 1 | |
return is_penalty_count * early_time | |
def morning_shift(self): | |
if self.error: | |
return 0 | |
if self.checkin > self.MORNING_OUT: | |
return 0 | |
if self.checkout < self.MORNING_IN: | |
return 0 | |
late_checkin_penalty = self.get_late_checkin(time=self.checkin, | |
mode='morning_in') | |
early_checkout_penalty = self.get_early_checkout(time=self.checkout, | |
mode='morning_out') | |
return (self.MORNING_OUT - self.MORNING_IN | |
).seconds // 60 - late_checkin_penalty - early_checkout_penalty | |
def afternoon_shift(self): | |
if self.error: | |
return 0 | |
if self.checkout < self.AFTERNOON_IN: | |
return 0 | |
if self.checkin > self.AFTERNOON_OUT: | |
return 0 | |
late_checkin_penalty = self.get_late_checkin(time=self.checkin, | |
mode='afternoon_in') | |
early_checkout_penalty = self.get_early_checkout(time=self.checkout, | |
mode='afternoon_out') | |
return (self.AFTERNOON_OUT - self.AFTERNOON_IN | |
).seconds // 60 - late_checkin_penalty - early_checkout_penalty | |
def working_time(self): | |
return self.morning_shift() + self.afternoon_shift() | |
def normalize(self, num: int) -> int: | |
gap = 15 | |
return round(num / gap) * gap | |
def to_tuple(self): | |
if self.error: | |
return self.date, 0 | |
return self.date, self.normalize(self.working_time()) | |
class Employee(object): | |
def __init__(self, | |
id: str, | |
name: str, | |
workdate: Dict[str, int] = {}) -> None: | |
self.id = id | |
self.name = name | |
self.workdate = workdate | |
def __repr__(self) -> str: | |
return "{" + ";\n".join(f"{k}={getattr(self, k)}" | |
for k in self.__dict__) + "}" | |
class WorkingTable(object): | |
def __init__(self) -> None: | |
pass | |
def make_table(self, employees: List[Employee]): | |
id_list: List[str] = [] | |
name_list: List[str] = [] | |
work_date: List[Dict] = [] | |
for employee in employees: | |
id_list.append(employee.id) | |
name_list.append(employee.name) | |
work_date.append(employee.workdate) | |
work_df: pd.DataFrame = pd.DataFrame(work_date, dtype=int) | |
info_df: pd.DataFrame = pd.DataFrame({ | |
'Mã nhân viên': id_list, | |
'Tên nhân viên': name_list | |
}) | |
working_table: pd.DataFrame = pd.concat(objs=[info_df, work_df], | |
axis=1) | |
return working_table | |