Coverage for app/logic/certification.py: 100%

49 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-01-29 16:34 +0000

1from peewee import JOIN, DoesNotExist, Case 

2 

3from app.models.certification import Certification 

4from app.models.certificationRequirement import CertificationRequirement 

5from app.models.requirementMatch import RequirementMatch 

6from app.models.eventParticipant import EventParticipant 

7 

8def getCertRequirementsWithCompletion(*, certification, username): 

9 """ 

10 Function to differentiate between simple requirements and requirements completion checking. 

11 See: `getCertRequirements` 

12 """ 

13 return getCertRequirements(certification, username) 

14 

15def getCertRequirements(certification=None, username=None): 

16 """ 

17 Return the requirements for all certifications, or for one if requested. 

18 

19 Keyword arguments: 

20 certification -- The id or object for a certification to request 

21 username -- The username to check for completion 

22 

23 Returns: 

24 A list of dictionaries with all certification data and requirements. If `certification` 

25 is given, returns only a list of requirement objects for the given certification. If  

26 `username` is given, the requirement objects have a `completed` attribute. 

27 """ 

28 reqList = (Certification.select(Certification, CertificationRequirement) 

29 .join(CertificationRequirement, JOIN.LEFT_OUTER, attr="requirement") 

30 .order_by(Certification.id, CertificationRequirement.order.asc(nulls="LAST"))) 

31 

32 if certification: 

33 if username: 

34 # I don't know how to add something to a select, so we have to recreate the whole query :( 

35 completedCase = Case(None, ((EventParticipant.user_id.is_null(True), 0),), 1) 

36 reqList = (Certification 

37 .select(Certification, CertificationRequirement, completedCase.alias("completed")) 

38 .join(CertificationRequirement, JOIN.LEFT_OUTER, attr="requirement") 

39 .join(RequirementMatch, JOIN.LEFT_OUTER) 

40 .join(EventParticipant, JOIN.LEFT_OUTER, on=(RequirementMatch.event == EventParticipant.event)) 

41 .where(EventParticipant.user.is_null(True) | (EventParticipant.user == username)) 

42 .order_by(Certification.id, CertificationRequirement.order.asc(nulls="LAST"))) 

43 

44 # we have to add the is not null check so that `cert.requirement` always exists 

45 reqList = reqList.where(Certification.id == certification, CertificationRequirement.id.is_null(False)) 

46 reqList = reqList.distinct() 

47 

48 certs = [] 

49 for cert in reqList: 

50 if username: 

51 cert.requirement.completed = bool(cert.__dict__['completed']) 

52 certs.append(cert.requirement) 

53 return certs 

54 

55 #return [cert.requirement for cert in reqList] 

56 

57 certs = {} 

58 for cert in reqList: 

59 if cert.id not in certs.keys(): 

60 certs[cert.id] = {"data": cert, "requirements": []} 

61 

62 if getattr(cert, 'requirement', None): 

63 certs[cert.id]["requirements"].append(cert.requirement) 

64 

65 return certs 

66 

67def updateCertRequirements(certId, newRequirements): 

68 """ 

69 Update the certification requirements in the database to match the provided list of requirement data. 

70 

71 The order of the list matters. Any ids that are in the database and not in `newRequirements` will be  

72 removed. IDs that do not exist in the database will be created (and given a new, auto-generated ID). 

73 

74 Arguments: 

75 certId - The id of the certification whose requirements we are updating 

76 newRequirements - a list of dictionaries. Each dictionary needs 'id', 'required', 'frequency', and 'name'. 

77 

78 Returns: 

79 A list of CertificationRequirement objects corresponding to the given `newRequirements` list. 

80 """ 

81 # check for missing ids to remove 

82 saveIds = [requirementData['id'] for requirementData in newRequirements] 

83 CertificationRequirement.delete().where(CertificationRequirement.id.not_in(saveIds)).execute() 

84 

85 

86 # update existing and add new requirements 

87 requirements = [] 

88 for order, requirementData in enumerate(newRequirements): 

89 try: 

90 newRequirement = CertificationRequirement.get_by_id(requirementData['id']) 

91 except DoesNotExist: 

92 newRequirement = CertificationRequirement() 

93 

94 newRequirement.certification = certId 

95 newRequirement.isRequired = bool(requirementData['required']) 

96 newRequirement.frequency = requirementData['frequency'] 

97 newRequirement.name = requirementData['name'] 

98 newRequirement.order = order 

99 newRequirement.save() 

100 

101 requirements.append(newRequirement) 

102 

103 return requirements 

104 

105def updateCertRequirementForEvent(event, requirement): 

106 """ 

107 Add a certification requirement to an event.  

108 Replaces the requirement for an event if the event already exists. 

109 

110 Arguments: 

111 event - an Event object or id 

112 requirement - a CertificationRequirement object or id 

113 """ 

114 # delete existing matches for our event 

115 for match in RequirementMatch.select().where(RequirementMatch.event == event): 

116 match.delete_instance() 

117 

118 RequirementMatch.create(event=event, requirement=requirement)