Пример #1
0
    def _load_config_file(self, config_file_yaml):
        ''' A config.yaml configuration file is expected to be in the same directory as this script
        '''
        try:
            config_file = os.path.join(
                os.path.dirname(os.path.realpath(__file__)), config_file_yaml)
            self.config = yaml.load(open(config_file, 'r'),
                                    Loader=yaml.SafeLoader)
            self._username = self.config['username']
            self._password = self.config['password']
            self._dog_mode = self.config[
                'dog_mode'] if 'dog_mode' in self.config else False

            self._google_spreadsheet_key = self.config[
                'google_spreadsheet_key'] if 'google_spreadsheet_key' in self.config else None
            self._google_client_secret = self.config[
                'google_client_secret'] if 'google_client_secret' in self.config else None

            self._box_user_id = self.config[
                'box_user_id'] if 'box_user_id' in self.config else None
            self._box_file_id = self.config[
                'box_file_id'] if 'box_file_id' in self.config else None
            self._box_jwt = self.config[
                'box_jwt'] if 'box_jwt' in self.config else None

            if not (self._google_spreadsheet_key and self._google_client_secret
                    ) and not (self._box_user_id and self._box_file_id
                               and self._box_jwt):
                Log.error(
                    f'ERROR: Incomplete mentor spreadsheet configuration: {config_file}'
                )
                return False

            if self._dog_mode:
                Log.warn('** Dog Mode is Active **')

            self.BASE_ANIMAL_TYPE = 'feline_and_critters' if not self._dog_mode else 'canine'

        except yaml.YAMLError as err:
            Log.error(
                f'ERROR: Unable to parse configuration file: {config_file}, {err}'
            )
            return False

        except IOError as err:
            Log.error(
                f'ERROR: Unable to read configuration file: {config_file}, {err}'
            )
            return False

        except KeyError as err:
            Log.error(
                f'ERROR: Missing value in configuration file: {config_file}, {err}'
            )
            return False

        return True
Пример #2
0
    def check_for_surgery_sheet(self, worksheet):
        if any(worksheet.title in substr
               for substr in self._SURGERY_SHEET_NAMES):
            surgery_rows = worksheet.get_values(
                'A1',
                f'H{worksheet.rows}',
                include_tailing_empty=False,
                include_tailing_empty_rows=False)
            date_col = -1
            patient_col = -1
            for col in range(0, len(surgery_rows[0])):
                # Allow for an extra header row (accounting for differences between Feline and Canine)
                #
                if any('date' in substr for substr in [
                        str(surgery_rows[0][col]).lower(),
                        str(surgery_rows[1][col]).lower()
                ]):
                    date_col = col
                elif 'patient' in (str(surgery_rows[0][col]).lower(),
                                   str(surgery_rows[1][col]).lower()):
                    patient_col = col

            if date_col != -1 and patient_col != -1:
                for row in range(1, len(surgery_rows)):
                    try:
                        a_number = surgery_rows[row][patient_col]
                        if a_number.isdigit():
                            a_number = int(a_number)
                            # If there are multiple entries for a given a_number, assume the first is the most recent.
                            #
                            if a_number not in self._surgery_dates:
                                self._surgery_dates[int(
                                    a_number)] = surgery_rows[row][date_col]
                    except Exception as e:
                        Log.warn(
                            f'{worksheet.title} column {patient_col}, row {row} is empty. Assuming this is the end of the list.'
                        )
                        break
            else:
                Log.error(
                    f'Surgery form is not in expected format (date_col={date_col}, patient_col={patient_col}. Skipping.'
                )

            Log.debug(
                f'Loaded {len(self._surgery_dates)} entries from the surgery sheet'
            )
            return True

        return False
Пример #3
0
    def _output_results(self, animal_data, foster_parents, persons_data,
                        animals_not_in_foster, current_mentee_status,
                        csv_filename):
        ''' Output all of our new super amazing results to a csv file
        '''
        Log.success(f'Writing results to {csv_filename}...')
        csv_rows = []

        csv_rows.append([])
        csv_rows[-1].append('Kitten-Scraper Notes')
        csv_rows[-1].append('Loss Rate')
        csv_rows[-1].append('Name')
        csv_rows[-1].append('E-mail')
        csv_rows[-1].append('Phone')
        csv_rows[-1].append('Person ID')
        csv_rows[-1].append('Foster Experience')
        csv_rows[-1].append('Date Animals Received')
        if self._dog_mode:
            csv_rows[-1].append('"Name, Breed, Color"')
        csv_rows[-1].append('Animal Details')
        csv_rows[-1].append('Special Animal Message')

        # Build a row for each foster parent
        #
        for person_number in sorted(foster_parents,
                                    key=lambda p: persons_data[p]['notes']):
            person_data = persons_data[person_number]
            name = person_data['full_name']
            report_notes = person_data['notes']
            loss_rate = round(person_data['loss_rate'])
            animals_with_this_person = foster_parents[person_number]
            animal_details, animal_details_brief = self._get_animal_details_string(
                animals_with_this_person, animal_data)

            prev_animals_fostered = person_data['prev_animals_fostered']
            foster_experience = 'NEW' if not prev_animals_fostered else prev_animals_fostered

            special_message = ''
            for a_number in animals_with_this_person:
                msg = animal_data[a_number]['message']
                if msg:
                    special_message += '{}{}: {}'.format(
                        '\r\r' if special_message else '', a_number, msg)

            cell_number = person_data['cell_phone']
            home_number = person_data['home_phone']
            phone = ''
            if len(cell_number) >= 10:  # ignore incomplete phone numbers
                phone = f'(C) {cell_number}'
            if len(home_number) >= 10:  # ignore incomplete phone numbers
                phone += '{}(H) {}'.format('\r' if phone else '', home_number)

            emails_str = ''
            for email in person_data['emails']:
                emails_str += '{}{}'.format('\r' if emails_str else '', email)

            # I will assume all animals in this group went into foster on the same date. This should usually be true
            # since this is designed to processed with a "daily report".
            #
            date_received = animal_data[
                animals_with_this_person[0]]['status_date']

            # Explicitly wrap numbers/datestr with ="{}" to avoid Excel auto-formatting issues
            #
            csv_rows.append([])
            csv_rows[-1].append(f'"{report_notes}"')
            csv_rows[-1].append(f'"{loss_rate}%"')
            csv_rows[-1].append(f'"{name}"')
            csv_rows[-1].append(f'"{emails_str}"')
            csv_rows[-1].append(f'"{phone}"')
            csv_rows[-1].append(f'="{person_number}"')
            csv_rows[-1].append(f'"{foster_experience}"')
            csv_rows[-1].append(f'="{date_received}"')
            if self._dog_mode:
                csv_rows[-1].append(f'"{animal_details_brief}"')
            csv_rows[-1].append(f'"{animal_details}"')
            csv_rows[-1].append(f'"{special_message}"')

            print('{} (Experience: {}, Loss Rate: {}%) {}{}{}'.format(
                name, foster_experience, loss_rate, Log.GREEN,
                report_notes.replace('\r', ', '), Log.END))
        with open(csv_filename, 'w') as outfile:
            for row in csv_rows:
                outfile.write(','.join(row))
                outfile.write('\n')

            if not foster_parents:
                outfile.write(
                    '*** None of the animals in this report are currently in foster\n'
                )
                Log.warn(
                    'None of the animals in this report are currently in foster. Nothing to do!'
                )

            if animals_not_in_foster:
                outfile.write('\n\n\n*** Animals not in foster\n')
                Log.warn('\nAnimals not in foster')
                for a_number in animals_not_in_foster:
                    outfile.write('{} {} - {}\n'.format(
                        a_number, animal_data[a_number]['type'],
                        animal_data[a_number]['status']))
                    print('{} {} - {}'.format(a_number,
                                              animal_data[a_number]['type'],
                                              animal_data[a_number]['status']))

            if current_mentee_status:
                outfile.write(
                    '\n\nMentor,Active Mentees,Last Assigned (days ago)\n')
                for current in current_mentee_status:
                    days_ago = (datetime.now() - current['most_recent']
                                ).days if current['most_recent'] else 'N/A'
                    outfile.write(
                        f'{current["mentor"]},{current["active_count"]},{days_ago}\n'
                    )