Last active
December 13, 2023 13:33
-
-
Save goroba/7a51b5477a2e9030b6ced4ff577d8124 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/enums.py | |
class IndicatorType(StrEnum): | |
PEOPLE = 'PEOPLE' | |
QUANTITY = 'QUANTITY' | |
QUALITY = 'QUALITY' | |
FINANCE = 'FINANCE' | |
# app/services/indicators/evaluators/base.py | |
Evaluable = TypeVar('Evaluable') # Это может быть Client, Account, Project, etc. | |
class IndicatorEvaluator(DataTypeAwared, Generic[Evaluable]): | |
@property | |
def code(self) -> str: | |
raise NotImplemented() | |
@property | |
def title(self) -> str: | |
raise NotImplemented() | |
@property | |
def description(self) -> str: | |
raise NotImplemented() | |
@property | |
def indicator_type(self) -> IndicatorType: | |
raise NotImplemented() | |
def evaluate(self, evaluable: Evaluable) -> str: | |
value = str(self.do_evaluation(evaluable)) | |
validate_value(value, self) | |
return value | |
def do_evaluation(self, evaluable: Evaluable) -> Any: | |
raise NotImplemented() | |
# app/services/indicators/evaluators/projects/base.py | |
class ProjectIndicatorEvaluator(IndicatorEvaluator[Project]): | |
... | |
# app/services/indicators/evaluators/accounts/base.py | |
class AccountIndicatorEvaluator(IndicatorEvaluator[Account]): | |
... | |
# app/services/indicators/evaluators/projects/duration.py | |
class DurationIndicatorEvaluator(ProjectIndicatorEvaluator): | |
@property | |
def code(self) -> str: | |
return 'projects.duration' | |
@property | |
def title(self) -> str: | |
return 'Project Duration' | |
@property | |
def description(self) -> str: | |
return 'Evaluate project duration in full months. Calculates the period since the start of the very first timer for the project till now.' | |
@property | |
def indicator_type(self) -> IndicatorType: | |
return IndicatorType.QUANTITY | |
@property | |
def data_type(self) -> DataType: | |
return DataType.INTEGER # измеряем в полных месяцах | |
@property | |
def data_options(self) -> list[str] | None: | |
return None | |
def do_evaluation(project: Project) -> int: | |
return int(math.floor(3.4)) | |
# app/services/indicators/evaluators/projects/active_employees_number.py | |
class ActiveEmployeesNumberIndicatorEvaluator(ProjectIndicatorEvaluator): | |
@property | |
def code(self) -> str: | |
return 'projects.active_employees_number' | |
@property | |
def title(self) -> str: | |
return 'Project Active Employees Number' | |
@property | |
def description(self) -> str: | |
return 'Evaluate the number of employees for the project. Calculates number of distinct users that ran timers for the previous 30 days for the project.' | |
@property | |
def indicator_type(self) -> IndicatorType: | |
return IndicatorType.PEOPLE | |
@property | |
def data_type(self) -> DataType: | |
return DataType.INTEGER | |
@property | |
def data_options(self) -> list[str] | None: | |
return None | |
def do_evaluation(project: Project) -> int: | |
return 84 | |
# app/services/indicators/evaluators/projects/hours_spent.py | |
class HoursSpentIndicatorEvaluator(ProjectIndicatorEvaluator): | |
@property | |
def code(self) -> str: | |
return 'project.hours_spent' | |
@property | |
def title(self) -> str: | |
return 'Number of hours spent' | |
@property | |
def description(self) -> str: | |
return 'Evaluate number of hours spent the project. This is a summary duration of all timers for the project.' | |
@property | |
def indicator_type(self) -> IndicatorType: | |
return IndicatorType.QUANTITY | |
@property | |
def data_type(self) -> DataType: | |
return DataType.INTEGER | |
@property | |
def data_options(self) -> list[str] | None: | |
return None | |
def do_evaluation(project: Project) -> int: | |
return int(10827.5 // 60) # минуты в timer.duration конвертирыем в часы | |
# app/services/indicators/evaluators/accounts/duration.py | |
class DurationIndicatorEvaluator(AccountIndicatorEvaluator): | |
@property | |
def code(self) -> str: | |
return 'accounts.duration' | |
def do_evaluation(account: Account) -> int: | |
return int(math.floor(3.4)) | |
... | |
# Период с момента запуска первого таймера для проекта этого аккаунта | |
# app/services/indicators/evaluators/accounts/active_employees_number.py | |
class ActiveEmployeesNumberIndicatorEvaluator(AccountIndicatorEvaluator): | |
@property | |
def code(self) -> str: | |
return 'accounts.active_employees_number' | |
def do_evaluation(account: Account) -> int: | |
return 84 | |
... | |
# все distinct юзеры, кто запускал таймеры для проектов данного акканта за последние 30 дней | |
# app/services/indicators/evaluators/accounts/hours_spent.py | |
class HoursSpentIndicatorEvaluator(AccountIndicatorEvaluator): | |
@property | |
def code(self) -> str: | |
return 'accounts.hours_spent' | |
def do_evaluation(account: Account) -> int: | |
return int(10827.5 // 60) # минуты в timer.duration конвертирыем в часы | |
# сколько всего времени затрекано на всех проектах данного аккаунта | |
# app/services/indicators/evaluators/__init__.py | |
# сюда пока что выносим только индикаторы для проектов, т.к. для аккаунтов эти индикаторы нужны в расчетах рангов и пока не используются в бизнес-правилах | |
indicator_evaluators = { | |
DurationIndicatorEvaluator.code: DurationIndicatorEvaluator, | |
ActiveEmployeesNumberIndicatorEvaluator.code: ActiveEmployeesNumberIndicatorEvaluator, | |
HoursSpentIndicatorEvaluator.code: HoursSpentIndicatorEvaluator, | |
} | |
def has_indicator_evaluator(evaluator_code: str) -> bool: | |
return evaluator_code in indicator_evaluators | |
def get_indicator_evaluator(evaluator_code: str) -> IndicatorEvaluator: | |
try: | |
return indicator_evaluators[evaluator_code]() | |
except Exception: | |
raise ValueError('Indicator evaluator is not implemented.') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment