def linkage(self, members): """Link coaches and swimmers.""" if self.is_active is False: return super().linkage(members) if self.data[A_COACHES]: for coach in self.data[A_COACHES]: guid = members.by_guid[coach[A_GUID]] if guid.is_active: self.coaches.append(guid) guid.add_coach_session(self) else: if self.ignore_attendance is False: issue(self, E_INACTIVE, "(Coach)") if A_LAST_ATTENDED in coach: lastseen = coach[A_LAST_ATTENDED] if lastseen: guid.set_lastseen(lastseen) else: if self.is_active: issue(self, E_NO_COACH) # super() has already done member links, now search for last seen... if A_MEMBERS in self.data: for swimmer in self.data[A_MEMBERS]: guid = members.by_guid[swimmer[A_GUID]] guid.add_session(self) if A_LAST_ATTENDED in swimmer: lastseen = swimmer[A_LAST_ATTENDED] if lastseen: guid.set_lastseen(lastseen)
def check_name(self): """Check capitilisation of name.""" firstname = self.data[A_FIRSTNAME] lastname = self.data[A_LASTNAME] knownas = self.data[A_KNOWNAS] ka_upper = True if knownas: ka_upper = knownas[0].isupper() fn_upper = firstname[0].isupper() ln_upper = lastname[0].isupper() if fn_upper and ln_upper and ka_upper: return if (fn_upper is False) or (ln_upper is False): issue(self, E_NAME_CAPITAL, "fixable", -1) fix = {} if fn_upper is False: fix[A_FIRSTNAME] = firstname.title() if ln_upper is False: fix[A_LASTNAME] = lastname.title() if ka_upper is False: fix[A_KNOWNAS] = knownas.title() self.fixit(fix, "Capitalisation of name") return issue(self, E_NAME_CAPITAL, f"Knownas = {knownas}", -1, "fixable") fix = {} fix[A_KNOWNAS] = knownas.title() self.fixit(fix, f"Capitalisation of {knownas}")
def check_type(self, xtype): """Check the member type check box config.""" cfg = get_config(self.scm, C_TYPES, xtype, C_GROUPS) name = get_config(self.scm, C_TYPES, xtype, C_NAME) if name is None: name = xtype jobtitle = get_config(self.scm, C_TYPES, xtype, C_JOBTITLE) if cfg: found = False for group in cfg: if self.find_group(group): found = True break if found is False: if self.in_ignore_group is False: if self.in_ignore_swimmer is False: issue(self, E_TYPE_GROUP, name) if jobtitle: if self.jobtitle: return issue(self, E_NO_JOB, f"{name}", 0, "fixable") fix = {} fix["JobTitle"] = xtype.title() self.fixit(fix, f"Add jobtitle: {name}")
def check_age(self, xmin, xmax, group): """Check swimmer within age group.""" if self.age and (self.age < xmin): issue(self, E_TOO_YOUNG, f"{group}: {self.age}") if self.age and (self.age > xmax): if not self.is_coach: issue(self, E_TOO_OLD, f"{group}: {self.age}")
def linkage(self, members): """Link members.""" if (A_MEMBERS in self.data) and (len(self.data[A_MEMBERS]) > 0): for swimmer in self.data[A_MEMBERS]: if swimmer[A_GUID] not in members.by_guid: msg = ( f"GUID {swimmer[A_GUID]} missing in list - email address only?" ) debug(msg, 7) continue guid = members.by_guid[swimmer[A_GUID]] if guid.is_active: self.members.append(guid) else: name = guid.name issue(self, E_INACTIVE, f"member {name}", 0, "Fixable") if self.newdata and (A_MEMBERS in self.newdata): fix = self.newdata else: fix = {} fix[A_MEMBERS] = self.data[A_MEMBERS].copy() remove = {A_GUID: guid.guid} fix[A_MEMBERS].remove(remove) self.fixit(fix, f"Delete {guid.name} (inactive)")
def check_two_groups(swimmer): """Check if swimmer in two groups.""" if get_config(swimmer.scm, C_GROUPS, C_GROUP) is None: return # No config, so ignore error. g_count = 0 errmsg = "" for group in swimmer.groups: nosession = get_config(swimmer.scm, C_GROUPS, C_GROUP, group.name, C_NO_CLUB_SESSIONS) if nosession is True: continue unique = get_config(swimmer.scm, C_GROUPS, C_GROUP, group.name, C_UNIQUE) if unique is None: unique = True if unique: g_count += 1 if g_count > 1: errmsg += f", {group.name}" else: errmsg += group.name if g_count > 1: if swimmer.print_exception(EXCEPTION_TWOGROUPS): issue(swimmer, E_TWO_GROUPS, errmsg)
def check_login(swimmer): """Check if the login is OK.""" if swimmer.username: min_age = get_config(swimmer.scm, C_SWIMMERS, C_USERNAME, C_MIN_AGE) if min_age: if swimmer.age and (swimmer.age < min_age): issue(swimmer, E_LOGIN_TOO_YOUNG, f"Age: {swimmer.age}")
def check_category(self): """Check the member categoty.""" cat = self.data[A_ASA_CATEGORY] if cat == "": return if cat not in CAT_VALID: issue(self, E_CATEGORY, cat)
def linkage_parent(self, members): """Link parents.""" for parent in self.data[A_PARENTS]: guid = members.by_guid[parent[A_GUID]] if guid == self.guid: issue(self, E_OWNPARENT) self._parents.append(guid)
def check_email(self): """Check email.""" email = self.email if email is None: if self.print_exception(EXCEPTION_NOEMAIL) is False: return issue(self, E_NO_EMAIL, f"{self.first_group}") else: space = re.search(" ", email) if space: issue(self, E_EMAIL_SPACE, f"{email}")
def analyse_coach(coach): """Analyse a coach...""" if coach.coach_role is False: if get_config(coach.scm, C_COACHES, C_ROLE, C_MANDATORY): issue(coach, E_NO_ROLE_COACH) if len(coach.coach_sessions) == 0: if coach.print_exception(EXCEPTION_NOSESSIONS): issue(coach, E_NO_SESSIONS) coach.check_dbs("Coach")
def check_conduct(member, my_codes): """Analyse a code of conduct.""" # pylint: disable=too-many-branches if get_config(member.scm, C_CONDUCT) is None: return type_dict = { CTYPE_SWIMMER: member.is_swimmer, CTYPE_PARENT: member.is_parent, CTYPE_COACH: member.is_coach, CTYPE_COMMITTEE: member.is_committee_member, CTYPE_VOLUNTEER: member.is_volunteer, CTYPE_POLO: member.is_polo, CTYPE_SYNCHRO: member.is_synchro, } codes = member.scm.conduct.entities for code in codes: ignores = get_config(member.scm, C_CONDUCT, code.name, C_IGNORE_GROUP) found_ignore = False if ignores: for ignore in ignores: if member.find_group(ignore): found_ignore = True if found_ignore: continue types = get_config(member.scm, C_CONDUCT, code.name, C_TYPES) if types is None: return for atype in types: found = False func = type_dict[atype] if func is True: for my_code in my_codes: if my_code == code: found = True break if found is False: issue(member, E_NO_CONDUCT, f"{code.name}") if code.newdata and (A_MEMBERS in code.newdata): fix = code.newdata else: fix = {} fix[A_MEMBERS] = code.data[A_MEMBERS].copy() add = {A_GUID: member.guid} fix[A_MEMBERS].append(add) code.fixit(fix, f"Add {member.name}")
def check_role_permissions(self, member): """Check out a role permissions.""" lookup = get_config(self.scm, C_ROLES, C_ROLE, self.name) if lookup is None: return if (C_CHECK_PERMISSIONS in lookup) and lookup[C_CHECK_PERMISSIONS]: check_coach_permissions(member, self) if (C_CHECK_RESTRICTIONS in lookup) and lookup[C_CHECK_RESTRICTIONS]: if len(member.restricted) == 0: issue(member, E_NO_RESTRICTIONS, f"Role: {self.name}")
def analyse(self): """Analyse the role.""" cfg = get_config(self.scm, C_ROLES, C_ROLE) unused = get_config(self.scm, C_ROLES, C_LOGIN, C_UNUSED) if len(self.members) == 0: issue(self, E_NO_SWIMMERS, "Role") return for member in self.members: self.check_role_member(member, unused) if cfg and (self.name in cfg): self.check_role_permissions(member)
def check_max_sessions(swimmer): """Check not exceeding max numbr of sessions allowed""" max_session = get_config(swimmer.scm, C_GROUPS, C_GROUP, swimmer.first_group, C_MAX_SESSIONS) if max_session: num_sessions = len(swimmer.sessions) if num_sessions > max_session: for session in swimmer.sessions: if session.exclude_max: num_sessions = num_sessions - 1 if num_sessions > max_session: sessions = swimmer.print_swimmer_sessions(False) issue(swimmer, E_MAX_SESSIONS, f"{len(swimmer.sessions)}: \n{sessions}")
def check_asa(swimmer): """Check ASA (Swim England) number is OK.""" if swimmer.asa_number is None: cfg_synchro = get_config(swimmer.scm, C_TYPES, CTYPE_SYNCHRO, C_CHECK_SE_NUMBER) cfg_polo = get_config(swimmer.scm, C_TYPES, CTYPE_POLO, C_CHECK_SE_NUMBER) err = True if swimmer.is_polo and (cfg_polo is False): err = False if swimmer.is_synchro and (cfg_synchro is False): err = False if err: issue(swimmer, E_ASA)
def analyse_parent(parent): """Analyse a parent...""" # pylint: disable=too-many-branches active = False inactive = None for swimmer in parent.swimmers: if swimmer.is_active: active = True else: inactive = swimmer.name if active is False: if inactive is None: issue(parent, E_NO_CHILD, "fixable") fix = {} fix[A_ISPARENT] = "0" parent.fixit(fix, "Remove 'is parent'") else: issue(parent, E_INACTIVE, f"child {inactive}") newmember = True for swimmer in parent.swimmers: if swimmer.newstarter is False: newmember = False break if (newmember is True) and parent.swimmers: parent.set_joined_today() age = get_config(parent.scm, C_PARENTS, C_AGE, C_MIN_AGE) if parent.age and (parent.age < age): issue(parent, E_PARENT_AGE) age = get_config(parent.scm, C_PARENTS, C_AGE, C_CHILD) for swimmer in parent.swimmers: if active and swimmer.age and (swimmer.age >= age): issue(swimmer, E_PARENT_AGE_TOO_OLD, f"{swimmer.age}, {parent.name}") login = get_config(parent.scm, C_PARENTS, C_LOGIN, C_MANDATORY) if login and (parent.username is None) and parent.email: issue(parent, E_NO_LOGIN, "Parent (fixable)") fix = {} fix[A_USERNAME] = parent.email parent.fixit(fix, f"Create login, username: {parent.email}")
def check_coach_permissions(coach, role): """Check a coaches permissions.""" # pylint: disable=too-many-branches debug(f"Permission check: {coach.name}, {role.name}", 7) if coach.is_coach is False: issue(coach, E_NOT_A_COACH, f"Role: {role.name} (fixable)") fix = {} fix[A_ISCOACH] = "1" coach.fixit(fix, "Add 'Is a coach'") coach.set_in_coach_role() if coach.is_swimmer is False: if len(coach.sessions) > 0: issue(coach, E_COACH_WITH_SESSIONS, f"Role: {role.name}") if coach.print_exception(EXCEPTION_PERMISSIONS) is False: return fix = {} fixed = False data = coach.data["SessionRestrictions"] if data: fix["SessionRestrictions"] = data.copy() else: fix["SessionRestrictions"] = [] msg = "Fix permissions:\n" for session in coach.coach_sessions: match = False for permission in coach.restricted: if session == permission: match = True break if match is False: issue(coach, E_PERMISSION_MISSING, session.full_name) fix["SessionRestrictions"].append({A_GUID: session.guid}) msg += f" Add {session.name}\n" fixed = True for permission in coach.restricted: match = False for session in coach.coach_sessions: if session == permission: match = True break if match is False: issue(coach, E_PERMISSION_EXTRA, permission.full_name) fix["SessionRestrictions"].remove({A_GUID: permission.guid}) fixed = True msg += f" Remove {session.name}\n" if fixed: coach.fixit(fix, msg)
def check_parents(swimmer): """Check consistence between swimmer and parent email.""" # pylint: disable=too-many-branches email = None match = False count = 0 confirm_error = False confirm_verify = get_config(swimmer.scm, C_SWIMMERS, C_CONF_DIFF, C_VERIFY) max_age = get_config(swimmer.scm, C_SWIMMERS, C_PARENT, C_MAX_AGE) if swimmer.email: email = swimmer.email.split(";") for parent in swimmer.parents: count += 1 if parent.is_active is False: issue(parent, E_INACTIVE, f"Swimmer {swimmer.name}") if match is False: match = check_parent_email_match(email, parent) if confirm_verify: confirm_error = check_confirmed_diff(swimmer, parent) if confirm_error: issue(swimmer, E_CONFIRM_DIFF, f"Parent {parent.name}") if (swimmer.parents and swimmer.age and (match is False) and (swimmer.age <= max_age)): if swimmer.print_exception(EXCEPTION_EMAILDIFF): err = f"{swimmer.email} - {swimmer.parents[0].email}" issue(swimmer, E_EMAIL_MATCH, err) if count == 0: mandatory = get_config(swimmer.scm, C_SWIMMERS, C_PARENT, C_MANDATORY) if mandatory and max_age: if swimmer.age and (swimmer.age <= max_age): msg = f"{swimmer.first_group}, Age: {swimmer.age}" issue(swimmer, E_NO_PARENT, msg) if count > 2: issue(swimmer, E_NUM_PARENTS)
def get_notes(self): """Extract Facebook name from Notes.""" notes = self.notes if notes is None: return note = FACEBOOK_RE.findall(notes) if note: for facebook in note: facebook = facebook.strip() self.facebook.append(facebook) debug(f"Found Facebook name in notes '{facebook}'", 8) note = API_RE.findall(notes) if note is None: return for api in note: exclusion = API_TEXT_RE.search(api) expiry = DATE_RE.search(api) when = self.scm.today gotdate = False if expiry: date = expiry.group(0) when = get_date(date, "%d-%m-%Y") gotdate = True else: expiry = DATE2_RE.search(api) if expiry: date = expiry.group(0) when = get_date(date, "%d/%m/%Y") gotdate = True if when: excl = exclusion.group(0).strip() if (self.scm.today - when).days <= 0: self.ignore_errors.append(excl) debug(f"Found API token in notes {api}", 8) else: debug(f"Token expired {api}", 8) elif gotdate: issue(self, E_DATE, f"Notes: {api}")
def analyse(self): """Analyse the conduct entry.""" # A better way of doing this would be to add # the attribute to the swimmer in linkage. # This approach breaks the model. Oh well. ignores = get_config(self.scm, C_CONDUCT, self.name, C_IGNORE_GROUP) c_date_str = get_config(self.scm, C_CONDUCT, self.name, C_DATE) if c_date_str is None: c_date_str = "1900-01-01" c_date = datetime.datetime.strptime(c_date_str, SCM_DATE_FORMAT) for member in self.data[A_MEMBERS]: if member[A_DATEAGREED]: m_date = datetime.datetime.strptime(member[A_DATEAGREED], SCM_DATE_FORMAT) if m_date >= c_date: continue person = self.scm.members.by_guid[member[A_GUID]] if person.confirmed_date: # Will get a not confirmed error later in not set found_ignore = False if ignores: for ignore in ignores: if person.find_group(ignore): found_ignore = True if found_ignore: continue issue(person, E_NO_CONDUCT_DATE, self.name, 0, person.first_group) codes = get_config(self.scm, C_LISTS, C_CONDUCT) if codes: for code in codes: if self.name == code: msg = f"{self.name} missing" self.scm.lists.add(msg, person)
def check_confirmation(self): """Check confimation status.""" expiry = get_config(self.scm, C_MEMBERS, C_CONFIRMATION, C_EXPIRY) align = get_config(self.scm, C_MEMBERS, C_CONFIRMATION, C_ALIGN_QUARTER) xlist = get_config(self.scm, C_LISTS, C_CONFIRMATION) q_offset = 0 if align: q_offset = self.scm.q_offset if self.confirmed_date: gap = (self.scm.today - self.confirmed_date).days if gap > (expiry + q_offset): issue(self, E_CONFIRMATION_EXPIRED, f"{self.first_group}") self.scm.members.count_not_confirmed += 1 if xlist: self._list_add(E_CONFIRMATION_EXPIRED) else: issue(self, E_NOT_CONFIRMED, f"{self.first_group}") self.scm.members.count_not_confirmed += 1 if xlist: self._list_add(E_NOT_CONFIRMED)
def check_duplicate(self, member): """See if member already exists before adding.""" firtname = member[A_FIRSTNAME] lastname = member[A_LASTNAME] name = f"{firtname} {lastname}" if name in self.by_name: if member[A_ACTIVE] == "1" and self.by_name[name].is_active: act1 = member[A_ACTIVE] act2 = self.by_name[name].is_active debug(f"{name}: {act1}-{act2}", 6) issue(self.by_name[name], E_DUPLICATE, name) else: active = self.by_name[name].is_active if member[A_ACTIVE] == "0" and active is False: issue(self.by_name[name], E_DUPLICATE, "BOTH inactive", 9) else: issue(self.by_name[name], E_DUPLICATE, "One is inactive", -1) return if name in self.knownas: if member[A_ACTIVE] == "1" and self.knownas[name].is_active: issue(self.knownas[name], E_DUPLICATE, name, 0, "(Known as)") else: issue(self.knownas[name], E_DUPLICATE, "One is inactive (Known as)", -1)
def check_lastseen(swimmer): """Check when swimemr was last seen.""" if swimmer.lastseen is None: if len(swimmer.sessions) > 0: # if no session, don't have data about when they have been seen check = True for session in swimmer.sessions: if get_config( swimmer.scm, C_SESSIONS, C_SESSION, session.name, C_IGNORE_ATTENDANCE, ): check = False continue if check: issue(swimmer, E_NEVERSEEN) else: gap = (swimmer.scm.today - swimmer.lastseen).days absence = get_config(swimmer.scm, C_SWIMMERS, C_ABSENCE, C_TIME) if gap > absence: when = swimmer.lastseen.strftime(PRINT_DATE_FORMAT) issue(swimmer, E_ABSENT, f"Last seen: {when}")
def analyse_swimmer(swimmer): """Analyse a swimmer...""" # pylint: disable=too-many-branches if swimmer.in_ignore_group: return if swimmer.in_ignore_swimmer: return if len(swimmer.groups) == 0: if swimmer.print_exception(EXCEPTION_NOGROUPS): issue(swimmer, E_NO_GROUP) if swimmer.dob is None: issue(swimmer, E_DOB) if swimmer.gender is None: issue(swimmer, E_GENDER) if swimmer.date_joined is None: issue(swimmer, E_DATE_JOINED) check_asa(swimmer) check_lastseen(swimmer) check_two_groups(swimmer) check_login(swimmer) if swimmer.is_swimmer: check_parents(swimmer) check_max_sessions(swimmer) return if swimmer.is_synchro: if get_config(swimmer.scm, C_TYPES, CTYPE_SYNCHRO, C_PARENTS) is False: pass else: check_parents(swimmer) return if swimmer.is_polo: if get_config(swimmer.scm, C_TYPES, CTYPE_POLO, C_PARENTS) is False: pass else: check_parents(swimmer)
def analyse(self): """Analyse existing lists.""" if len(self.members) == 0: issue(self, E_NO_SWIMMERS, "List") return for member in self.members: if member.is_active is False: # Never get here as entity linkage prevents it. msg = f"Inactive but on email list {self.name} (fixable)" issue(member, E_LIST_ERROR, msg) if self.newdata and (A_MEMBERS in self.newdata): fix = self.newdata else: fix = {} fix[A_MEMBERS] = self.data[A_MEMBERS].copy() fix[A_MEMBERS].remove({A_GUID: member.guid}) self.fixit(fix, f"Delete {member.name}") if member.email is None: issue(member, E_LIST_ERROR, f"No email, but on email list {self.name}")
def check_inactive(self): """Check an inactive member.""" lastmod = self.last_modified_date if lastmod: gap = (self.scm.today - lastmod).days inactive = get_config(self.scm, C_MEMBERS, C_INACTIVE, C_TIME) if inactive and (gap > inactive): when = lastmod.strftime(PRINT_DATE_FORMAT) issue(self, E_INACTIVE_TOOLONG, f"Last Modified: {when}") if self.check_attribute(A_DATELEFT): return if lastmod: issue(self, E_NO_LEAVE_DATE, "fixable", -1) fix = {} fix[A_DATELEFT] = lastmod.strftime(SCM_DATE_FORMAT) self.fixit(fix, f"Add dataleft = {fix[A_DATELEFT]}") return issue(self, E_NO_LEAVE_DATE, "", -1)
def populate(self): """Search for entries and fill the list.""" # pylint: disable=too-many-branches, too-many-statements cfg = get_config(self.scm, C_LISTS, C_LIST, self.name) # set defaults min_age = 0 if C_MIN_AGE in cfg: min_age = cfg[C_MIN_AGE] max_age = 999 if C_MAX_AGE in cfg: max_age = cfg[C_MAX_AGE] min_age_eoy = 0 if C_MIN_AGE_EOY in cfg: min_age_eoy = cfg[C_MIN_AGE_EOY] max_age_eoy = 999 if C_MAX_AGE_EOY in cfg: max_age_eoy = cfg[C_MAX_AGE_EOY] min_year = 1900 if C_MIN_YEAR in cfg: min_year = cfg[C_MIN_YEAR] max_year = 2200 if C_MAX_YEAR in cfg: max_year = cfg[C_MAX_YEAR] for member in self.scm.members.entities: if member.is_active is False: continue if member.in_ignore_group: continue if member.age and (member.age < min_age): continue if member.age and (member.age > max_age): continue if member.age_eoy and (member.age_eoy < min_age_eoy): continue if member.age_eoy and (member.age_eoy > max_age_eoy): continue if member.dob and (member.dob.year > max_year): continue if member.dob and (member.dob.year < min_year): continue if C_GROUP in cfg: if member.find_group(cfg[C_GROUP]) is False: continue if C_UNIQUE in cfg: if len(member.groups) > 1: if C_ALLOW_GROUP not in cfg: continue if member.find_group(cfg[C_ALLOW_GROUP]) is False: continue if C_GENDER in cfg: gender = cfg[C_GENDER] xgender = "F" if gender == "male": xgender = "M" if member.gender != xgender: continue if C_TYPE in cfg: xtype = cfg[C_TYPE] if check_type(member, xtype) is False: continue if member.email is None: if member.print_exception(EXCEPTION_NOEMAIL): msg = f"No email, but required for email list {self.name}" issue(member, E_LIST_ERROR, msg) continue self.add_member(member)
def analyse(self): """Analyse the group.""" # pylint: disable=too-many-branches # pylint: disable=too-many-statements # pylint: disable=too-many-locals no_session = False check_dbs = False wanted_session = None allowed = None xtype = None ignore = None confirm = None if self.config: ignore = self.config_item(C_IGNORE_GROUP) no_session = self.config_item(C_NO_SESSIONS) check_dbs = self.config_item(C_CHECK_DBS) wanted_sessions = self.config_item(C_SESSIONS) allowed = self.config_item(C_NO_SESSION_ALLOWED) xtype = self.config_item(C_TYPE) confirm = self.config_item(C_CONFIRMATION) if ignore: debug(f"Ignoring group {self.name}", 7) return if len(self.members) == 0: issue(self, E_NO_SWIMMERS, "Group") return if no_session: for member in self.members: if len(member.sessions) > 0: name = member.sessions[0].name issue(member, E_SESSIONS, f"Group: {self.name}, Session: {name}") if confirm: try: date = datetime.datetime.strptime(confirm, SCM_CSV_DATE_FORMAT) confirm = date except ValueError: notify( f"*** Error in date format in config file for groups config: {confirm} ***\n" ) confirm = None for member in self.members: self.check_age(member) if check_dbs: member.check_dbs(self.name) if confirm: err = False if member.confirmed_date: gap = (confirm - member.confirmed_date).days if gap >= 0: err = True else: err = True if err: issue(member, E_CONFIRMATION_EXPIRED, f"Group: {self.name}") msg = f"Confirmation Expired for Group: {member.name}" member.scm.lists.add(msg, member) if member.newstarter: continue if wanted_session: for session in wanted_sessions: if check_in_session(member, session, allowed) is False: res1 = self.print_exception( EXCEPTION_NONSWIMMINGMASTER) res2 = self.print_exception(EXCEPTION_GROUPNOSESSION) if res1 or res2: issue(member, E_NOT_IN_SESSION, f"Group: {self.name}") break if xtype: if check_type(member, xtype): continue if xtype == CTYPE_SWIMMER: # if swimmers wanted, allow it to be a coach if check_type(member, CTYPE_COACH) is True: continue msg = f"Group: {self.name}, Type required: {xtype} (fixable)" issue(member, E_TYPE, msg) fix = {} attr = None if xtype == CTYPE_MASTER: attr = "Masters" if xtype == CTYPE_SWIMMER: attr = "IsASwimmer" if xtype == CTYPE_SYNCHRO: attr = "SynchronisedSwimming" if xtype == CTYPE_COACH: attr = "IsACoach" if xtype == CTYPE_POLO: attr = "WaterPolo" if attr: fix[attr] = "1" member.fixit(fix, f"Add type: {attr}")
def analyse(self): """Analyse the member.""" # pylint: disable=too-many-branches # pylint: disable=too-many-statements if self.is_active is False: self.check_inactive() return self.check_name() found = False if self.is_coach: self.check_type(CTYPE_COACH) analyse_coach(self) found = True if self.newstarter: return if self.is_swimmer: self.check_type(CTYPE_SWIMMER) found = True if self.is_master: self.check_type(CTYPE_MASTER) found = True if self.is_synchro: self.check_type(CTYPE_SYNCHRO) found = True if self.is_polo: self.check_type(CTYPE_POLO) found = True if self.is_swimmer or self.is_polo or self.is_synchro or self.is_openwater: analyse_swimmer(self) if self.is_parent: self.check_type(CTYPE_PARENT) analyse_parent(self) found = True if self.is_volunteer: vol = get_config(self.scm, C_TYPES, CTYPE_VOLUNTEER, C_IGNORE_COACH) ctte = get_config(self.scm, C_TYPES, CTYPE_VOLUNTEER, C_IGNORE_COMMITTEE) if vol or ctte or self.is_coach: pass else: self.check_type(CTYPE_VOLUNTEER) found = True if self.is_committee_member: found = True self.check_type(CTYPE_COMMITTEE) if A_ASA_CATEGORY in self.data: self.check_category() if self.jobtitle: if ( (self.is_volunteer is not True) and (self.is_committee_member is not True) and (self.is_coach is not True) ): cfg = get_config(self.scm, C_JOBTITLE, C_IGNORE) if self.jobtitle not in cfg: issue(self, E_JOB, self.jobtitle) if found: if self.in_ignore_swimmer: return self.check_email() self.check_confirmation() # Must come after analyse_swimmer check_conduct(self, self._conduct) return for group in self.groups: if get_config(self.scm, C_GROUPS, C_GROUP, group.name, C_IGNORE_UNKNOWN): continue issue(self, E_UNKNOWN)