Coverage for bc/kwai-bc-training/src/kwai_bc_training/trainings/training.py: 89%

56 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2024-01-01 00:00 +0000

1"""Module for defining a training entity.""" 

2 

3from dataclasses import dataclass, field, replace 

4from typing import ClassVar, Self, Type 

5 

6from kwai_core.domain.entity import DataclassEntity 

7from kwai_core.domain.value_objects.identifier import IntIdentifier 

8from kwai_core.domain.value_objects.owner import Owner 

9from kwai_core.domain.value_objects.period import Period 

10from kwai_core.domain.value_objects.text import LocaleText 

11from kwai_core.domain.value_objects.unique_id import UniqueId 

12 

13from kwai_bc_training.coaches.coach import CoachEntity 

14from kwai_bc_training.teams.team import TeamEntity 

15from kwai_bc_training.trainings.training_schedule import ( 

16 TrainingScheduleEntity, 

17) 

18 

19 

20class TrainingCoachIdentifier(IntIdentifier): 

21 """Identifier for a coach appointed to a training.""" 

22 

23 

24@dataclass(kw_only=True, frozen=True, slots=True) 

25class TrainingCoachEntity(DataclassEntity): 

26 """A coach attached to a training.""" 

27 

28 ID: ClassVar[Type] = TrainingCoachIdentifier 

29 

30 coach: CoachEntity 

31 owner: Owner 

32 present: bool = False 

33 type: int = 0 

34 payed: bool = False 

35 remark: str = "" 

36 

37 

38class TrainingIdentifier(IntIdentifier): 

39 """Identifier for a training.""" 

40 

41 

42@dataclass(kw_only=True, eq=False, slots=True, frozen=True) 

43class TrainingEntity(DataclassEntity): 

44 """A training entity. 

45 

46 Attributes: 

47 texts: A tuple with text content 

48 schedule: The related training schedule, when the training was created from a schedule. 

49 coaches: A frozenset of assigned coaches. 

50 teams: A frozenset of assigned teams. 

51 period: The period of the training. 

52 season: The season that the training belongs to (not supported yet). 

53 active: Is this training active? 

54 cancelled: Is this training cancelled? 

55 location: The location of this training 

56 remark: A remark about this training 

57 """ 

58 

59 ID: ClassVar[Type] = TrainingIdentifier 

60 

61 texts: tuple[LocaleText, ...] = field(default_factory=tuple) 

62 schedule: TrainingScheduleEntity | None = None 

63 coaches: frozenset[TrainingCoachEntity] = field(default_factory=frozenset) 

64 teams: frozenset[TeamEntity] = field(default_factory=frozenset) 

65 season: None = None 

66 period: Period 

67 active: bool = True 

68 cancelled: bool = False 

69 location: str = "" 

70 remark: str = "" 

71 

72 def add_team(self, team: TeamEntity) -> Self: 

73 """Add a team to this training.""" 

74 teams = self.teams | {team} 

75 return replace(self, teams=teams) 

76 

77 def delete_team(self, team: TeamEntity) -> Self: 

78 """Remove a team from this training.""" 

79 return replace(self, teams=self.teams - {team}) 

80 

81 def add_coach(self, coach: TrainingCoachEntity) -> Self: 

82 """Add a coach to this training.""" 

83 coaches = self.coaches | {coach} 

84 return replace(self, coaches=coaches) 

85 

86 def delete_coach(self, coach: TrainingCoachEntity) -> Self: 

87 """Remove a coach from this training.""" 

88 if coach.present: 

89 raise ValueError( 

90 "It's not allowed to remove a coach who was present on a training." 

91 ) 

92 return replace(self, coaches=self.coaches - {coach}) 

93 

94 def mark_coach_as_present(self, coach_uuid: UniqueId, present: bool = True) -> Self: 

95 """Mark a coach as present or not for this training. 

96 

97 Args: 

98 coach_uuid: The uuid of the coach to mark as present or not 

99 present: Whether the coach was present or not 

100 """ 

101 training_coaches = list( 

102 filter(lambda c: c.coach.uuid == coach_uuid, self.coaches) 

103 ) 

104 if len(training_coaches) == 0: 

105 raise ValueError( 

106 f"Coach with {coach_uuid} is not attached to this training." 

107 ) 

108 training_coach = replace(training_coaches[0], present=present) 

109 return replace( 

110 self, coaches=(self.coaches - {training_coaches[0]} | {training_coach}) 

111 ) 

112 

113 def appoint_head_coach(self, coach_uuid: UniqueId, appoint: bool = True) -> Self: 

114 """Appoint a coach as head of this training. 

115 

116 Args: 

117 coach_uuid: The uuid of the coach to appoint or not 

118 appoint: Whether the coach is appointed or not 

119 """ 

120 training_coaches = list( 

121 filter(lambda c: c.coach.uuid == coach_uuid, self.coaches) 

122 ) 

123 if len(training_coaches) == 0: 

124 raise ValueError( 

125 f"Coach with {coach_uuid} is not attached to this training." 

126 ) 

127 training_coach = replace(training_coaches[0], type=1 if appoint else 0) 

128 return replace( 

129 self, coaches=(self.coaches - {training_coaches[0]} | {training_coach}) 

130 )