Exemple #1
0
    def check_role_member(self, member, unused):
        """Check out a role member."""
        if member.is_active is False:
            issue(member, E_INACTIVE, f"Member of role {self.name} (fixable)")
            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 from role {self.name}")

        if member.username is None:
            issue(member, E_NO_LOGIN, f"Member of role {self.name}, so cannot login")

        if get_config(self.scm, C_ROLES, C_ROLE, self.name, C_IS_COACH):
            if member.is_coach is False:
                issue(member, E_COACH_ROLE, f"Role: {self.name}")

        if get_config(self.scm, C_ROLES, C_VOLUNTEER, C_MANDATORY):
            if member.is_volunteer is False:
                issue(member, E_VOLUNTEER, f"Role: {self.name} (fixable)")
                fix = {}
                fix[A_ISVOLUNTEER] = "1"
                member.fixit(fix, "Mark as volunteer")

        if member.last_login:
            if (self.scm.today - member.last_login).days > unused:
                issue(
                    member,
                    E_UNUSED_LOGIN,
                    f"Role: {self.name} [Last login: {member.last_login}]",
                )
        else:
            issue(member, E_UNUSED_LOGIN, f"Role: {self.name} [Never]")
Exemple #2
0
    def read_data(self, scm):
        """Read each file."""
        self.scm = scm

        home = str(Path.home())
        mydir = os.path.join(home, CONFIG_DIR)

        cfg = get_config(scm, C_FACEBOOK, C_FILES)
        if cfg:
            for facebook in cfg:
                face = FacebookPage()
                filename = os.path.join(mydir, facebook)
                res = face.readfile(filename, scm)
                if res:
                    self.facebook.append(face)
                    if face.parse() is False:
                        return False
                else:
                    return False
            return True

        cfg = get_config(scm, C_FACEBOOK, C_GROUPS)
        if cfg:
            for facebook in cfg:
                face = FacebookPage()
                res = face.readurl(facebook, scm)
                if res:
                    self.facebook.append(face)
                else:
                    return False

            return True

        return False
Exemple #3
0
    def _list_add(self, err):
        """Add a member to a confirmation list."""
        msg = "Not confirmed"
        if err == E_CONFIRMATION_EXPIRED:
            msg = "Confirmation expired"

        xtype = " (Other)"
        if self.is_parent:
            xtype = " (Parent)"
        if self.is_polo:
            xtype = " (Water Polo)"
            cfg = get_config(self.scm, C_TYPES, CTYPE_POLO, C_NAME)
            if cfg:
                xtype = f" ({cfg})"
        if self.is_synchro:
            xtype = " (Synchro)"
            cfg = get_config(self.scm, C_TYPES, CTYPE_SYNCHRO, C_NAME)
            if cfg:
                xtype = f" ({cfg})"
        if self.is_swimmer:
            xtype = " (Swimmer)"

        msg += xtype

        self.scm.lists.add(msg, self)
Exemple #4
0
    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}")
Exemple #5
0
    def update(self):
        """Create a new list to add to SCM."""
        cfg = get_config(self.scm, C_LISTS)
        if cfg is None:
            return

        if get_config(self.scm, C_LISTS, C_EDIT) is not True:
            notify("List update prohibited by config.\n")
            return

        lists = get_config(self.scm, C_LISTS, C_LIST)
        self._suffix = get_config(self.scm, C_LISTS, C_SUFFIX)

        if lists:
            for xlist in lists:
                newlist = NewList(self.scm, xlist, self._url)
                self.newlists.append(newlist)
                newlist.populate()

        # Separate for loop, as add_to_list may have created some too
        for xlist in self.newlists:
            xlist.generate_data(self._suffix)

            if xlist.upload() is None:
                pass  # not sure what to do, just carry on!
Exemple #6
0
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)
Exemple #7
0
    def readfile(self, file, scm):
        """Read CSV file."""
        self._filename = file
        self._scm = scm

        self.cfg_file = ntpath.basename(file)

        notify(f"Reading {self.cfg_file}...\n")

        cfg_dob_format = get_config(scm, C_FILES, self.cfg_file, C_MAPPING,
                                    C_DOB_FORMAT)
        if cfg_dob_format is None:
            cfg_dob_format = SCM_DATE_FORMAT

        cfg_dob = get_config(scm, C_FILES, self.cfg_file, C_MAPPING, A_DOB)
        if cfg_dob is None:
            cfg_dob = A_DOB

        cfg_cat = get_config(scm, C_FILES, self.cfg_file, C_MAPPING,
                             A_ASA_CATEGORY)
        if cfg_cat is None:
            cfg_cat = A_ASA_CATEGORY

        try:
            count = 0
            with open(file, newline="", encoding="utf-8-sig") as csvfile:
                csv_reader = csv.DictReader(csvfile)

                for row in csv_reader:
                    count += 1
                    if count == 0:
                        continue
                    self._csv.append(row)

                    # Fix DOB
                    if cfg_dob in row:
                        try:
                            row[cfg_dob] = datetime.datetime.strptime(
                                row[cfg_dob], cfg_dob_format)
                        except ValueError as error:
                            notify(f"Date format error in CSV:\n{error}\n")
                            return False
                    if cfg_cat in row:
                        cat = CAT_RE.search(row[cfg_cat])
                        if cat:
                            row[cfg_cat] = cat.group(0)

            notify(f"Read {file}...\n")
            return True

        except EnvironmentError:
            notify(f"Cannot open csv file: {file}\n")
            return False

        except csv.Error as error:
            notify(f"Error in csv file: {file}\n{error}\n")
            return False

        notify("Unknown error\n")
        return False
Exemple #8
0
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}")
Exemple #9
0
    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)
Exemple #10
0
def se_check(scm, members):
    """Check members against the SE database."""
    home = str(Path.home())
    cookiefile = os.path.join(home, CONFIG_DIR, SE_COOKIES)

    base_url = get_config(scm, C_SWIM_ENGLAND, C_BASE_URL)
    if base_url is False:
        notify("Swim England config missing\n")
        return None

    notify(f"Opening browser for {base_url}...\n")

    browser = start_browser(scm)

    if browser is None:
        return None

    read_cookies(browser, cookiefile, base_url, None)

    check_url = get_config(scm, C_SWIM_ENGLAND, C_CHECK_URL)
    test_id_url = get_config(scm, C_SWIM_ENGLAND, C_TEST_ID)

    browser.get(f"{check_url}{test_id_url}")
    try:
        browser.find_element_by_xpath("//table[1]/tbody/tr[2]/td[2]")

    except selenium.common.exceptions.NoSuchElementException:
        msg = """Please solve the 'I am not a robot', and then press enter here.
If you cannot solve the capture try deleting the file 'se_cookies.json'
in the config directory.
"""
        interact_yesno(msg)
        write_cookies(browser, cookiefile, None)

    res = ""
    for member in members:
        if member.is_active is False:
            continue
        if member.asa_number is None:
            continue

        url = f"{check_url}{member.asa_number}"
        browser.get(url)

        res += check_member(browser, member)

    browser.close()

    return res
Exemple #11
0
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)
Exemple #12
0
    def check_dbs(self, xtype):
        """Check DBS and Safeguarding."""
        if self.print_exception(EXCEPTION_NODBS) is False:
            debug(f"DBS Exception ignored: {self.name}", 7)
            return

        dbs_date = self.set_date(A_DBS_RENEWAL_DATE)
        safe_date = self.set_date(A_SAFEGUARDING_RENEWAL_DATE)
        notice = get_config(self.scm, C_MEMBERS, C_DBS, C_EXPIRY)

        if dbs_date:
            days = (dbs_date - self.scm.today).days
            if days < 0:
                dbs_date_str = dbs_date.strftime(PRINT_DATE_FORMAT)
                issue(self, E_DBS_EXPIRED, f"{xtype}, expired {dbs_date_str}")
            elif days < notice:
                dbs_date_str = dbs_date.strftime(PRINT_DATE_FORMAT)
                issue(self, E_DBS_EXPIRED, f"{xtype}, expires {dbs_date_str}")
        else:
            issue(self, E_NO_DBS, f"{xtype}")

        if self.print_exception(EXCEPTION_NOSAFEGUARD) is False:
            debug(f"Safeguard Exception ignored: {self.name}", 7)
            return

        if safe_date:
            if (safe_date - self.scm.today).days < 0:
                safe_date_str = safe_date.strftime(PRINT_DATE_FORMAT)
                issue(self, E_SAFEGUARD_EXPIRED, f"{xtype}, expired {safe_date_str}")
            elif (safe_date - self.scm.today).days < notice:
                safe_date_str = safe_date.strftime(PRINT_DATE_FORMAT)
                issue(self, E_SAFEGUARD_EXPIRED, f"{xtype}, expires {safe_date_str}")
        else:
            issue(self, E_NO_SAFEGUARD, f"{xtype}")
Exemple #13
0
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}")
Exemple #14
0
 def newstarter(self):
     """Is the member a new stater."""
     grace = get_config(self.scm, C_MEMBERS, C_NEWSTARTER, C_GRACE)
     if grace and self._date_joined:
         if (self.scm.today - self._date_joined).days < grace:
             return True
     return False
Exemple #15
0
    def check_swim(self, swim):
        """Check a swim time to see if it as a record."""
        check_event = swim[S_EVENT]
        if check_event in self.records:
            event = self.records[check_event]
            if swim[S_FTIME] >= event[S_FTIME]:
                return

        self.records[check_event] = swim

        sloc = swim[S_LOCATION]
        newrec = (
            f"New record: {check_event}, {swim[S_NAME]}, {swim[S_TIMESTR]}, {sloc}\n"
        )
        self.newrecords[check_event] = newrec

        if get_config(self.scm, C_RECORDS, C_OVERALL_FASTEST):
            split_event = swim[S_EVENT].split()
            split_event[1] = OVERALL
            o_event = " ".join(str(item) for item in split_event)
            if o_event in self.records:
                event = self.records[o_event]
                if swim[S_FTIME] >= event[S_FTIME]:
                    return

            o_swim = swim.copy()
            o_swim[S_EVENT] = o_event
            self.records[o_event] = o_swim
Exemple #16
0
    def api_write(self, entity, create):
        """Write data back to SCM."""
        club = self._config[C_CLUB]
        user_agent = USER_AGENT.replace("###CLUB_NAME###", club)

        headers = {
            "content-type": "application/json",
            "User-Agent": user_agent,
            "Authorization-Token": self._key,
        }

        if get_config(entity.scm, C_ALLOW_UPDATE) is False:
            notify("Update prohibited by config.\n")
            return None

        debug(f"URL:\n{entity.url}", 9)
        debug(f"Headers:\n{headers}", 8)

        data = entity.newdata
        if create:
            debug(f"Post request:\n{data}", 7)
            response = requests.post(entity.url, json=data, headers=headers)
        else:
            debug(f"Put request:\n{data}", 7)
            response = requests.put(entity.url, json=data, headers=headers)
        if response.ok:
            return response

        if response.status_code == 404:  # Worked, but not found
            return False

        notify(f"\nErroring posting data {entity.name}\n")
        notify(response.reason)
        notify("\n")
        return None
Exemple #17
0
    def analyse(self):
        """Analyse the conduct class."""
        if get_config(self.scm, C_CONDUCT) is None:
            return

        for code in self.entities:
            code.analyse()
Exemple #18
0
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}")
Exemple #19
0
    def __init__(self, entity, scm, url):
        """Initialise."""
        super().__init__(entity, scm, url)
        self.coaches = []
        self.swimmers = []

        self.ignore_attendance = False
        self.exclude_max = False

        cfg = get_config(self.scm, C_SESSIONS, C_SESSION, self.name,
                         C_IGNORE_ATTENDANCE)
        if cfg:
            self.ignore_attendance = cfg

        cfg = get_config(self.scm, C_SESSIONS, C_SESSION, self.name,
                         C_EXCLUDE_MAX)
        if cfg:
            self.exclude_max = cfg
Exemple #20
0
 def check_ignore(self, member):
     """Return true if swimmer in ignore list."""
     cfg_ignore = get_config(self._scm, C_FILES, self.cfg_file,
                             C_IGNORE_GROUP)
     if cfg_ignore:
         for ignore in cfg_ignore:
             if member.find_group(ignore):
                 return True
     return False
Exemple #21
0
def start_browser(scm):
    """Start Browser."""
    web_driver = get_config(scm, C_SELENIUM, C_WEB_DRIVER)
    client = get_config(scm, C_SELENIUM, C_BROWSER)

    if client is False:
        notify("Selenium config missing\n")
        return None

    browser = getattr(selenium.webdriver, client)

    try:
        return browser(web_driver)

    except selenium.common.exceptions.WebDriverException as error:
        notify(
            f"Failed to open {client} browser with: {web_driver}\n{error}\n")
        return None
Exemple #22
0
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)
Exemple #23
0
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")
Exemple #24
0
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)
Exemple #25
0
    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}")
Exemple #26
0
    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)
Exemple #27
0
    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)
Exemple #28
0
def check_confirmed_diff(swimmer, parent):
    """Check for differences in swimmer and parent."""
    # pylint: disable=R0911
    # Need them all
    child_mon = 0
    parent_mon = 0

    if swimmer.confirmed_date:
        child_mon = int((swimmer.confirmed_date.month - 1) / 3) * 3
    if parent.confirmed_date:
        parent_mon = int((parent.confirmed_date.month - 1) / 3) * 3

    if swimmer.age > get_config(swimmer.scm, C_SWIMMERS, C_PARENT, C_MAX_AGE):
        return False

    if child_mon == parent_mon:
        return False

    prefix = "Different confirmed dates"
    postfix = "- checking other details for consistency"
    debug(f"{prefix} {swimmer.name}, {parent.name} {postfix}", 8)

    if swimmer.email != parent.email:
        debug(f"email: {swimmer.email}: {parent.email}", 8)
        return True

    if swimmer.homephone != parent.homephone:
        debug(f"phone: {swimmer.homephone}: {parent.homephone}", 8)
        return True

    if swimmer.mobilephone != parent.mobilephone:
        debug(f"mobile: {swimmer.mobilephone}: {parent.mobilephone}", 8)
        return True

    if swimmer.address != parent.address:
        debug(f"address: {swimmer.address}: {parent.address}", 8)
        return True

    # Dates are different, but core attributes same
    # So set the confirmed date - to inhibit a confirm notice to parent

    if parent.confirmed_date is None:
        parent.set_confirmed(swimmer.confirmed_date)
        return False

    if swimmer.confirmed_date:
        if swimmer.confirmed_date > parent.confirmed_date:
            parent.set_confirmed(swimmer.confirmed_date)

    return False
Exemple #29
0
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}")
Exemple #30
0
    def read_baseline(self):
        """Read baseline."""
        home = str(Path.home())
        mydir = os.path.join(home, CONFIG_DIR, RECORDS_DIR)

        self.records = Record()
        filename = os.path.join(mydir, F_BASELINE)
        res = self.records.read_baseline(filename, self.scm)

        if res and get_config(self.scm, C_RECORDS, C_RELAY):
            self.relay = RelayRecord()
            filename = os.path.join(mydir, F_RELAY_BASELINE)
            res = self.relay.read_baseline(filename, self.scm)

        return res