예제 #1
0
 def _connect(self):
     self._conn = Connection('secret.json')
     self._conn.connect()
예제 #2
0
class ReportGenerator(object):

    def __init__(self):
        self._conn = None
        self._mgr = None
        self._section = None
        self._term = None

    def _connect(self):
        self._conn = Connection('secret.json')
        self._conn.connect()

    def _initialise(self):
        self._mgr = Manager()
        self._mgr.load(self._conn)
        if not os.path.exists('temp_images'):
            os.makedirs('temp_images')

    def run(self):

        if len(sys.argv) < 3:
            print('ERROR: term and section have not been set! ')
            return

        print('Connecting to OSM...')
        self._connect()
        self._initialise()

        self._set_term(sys.argv[1:3])
        if self._term is None:
            return

        print('Retrieving badge data...')
        scheme = AwardScheme(self._section.name + '-award.json')
        print('-> Loaded award scheme definition')
        self._term.load_badges(self._conn)
        badge_map = {}
        for badge in self._term.badges:
            badge_map[badge.badge_id] = badge
        print('-> Loaded badges')

        print('Generating report...')
        filename = ensureExtension(sys.argv[2]+'-Badge Progress', '.docx')
        document = Document()
        self._generate_header_footer(document)
        self._generate_report(scheme, document, badge_map)

        print('Saving to %s...' % (filename, ))
        document.save(filename)

        print('Done')

    def _set_term(self, args):
        term_name = args[0]
        self._set_section(args[1:])

        print('Setting term...')
        if term_name == 'current':
            term = self._section.current_term()
            if term is None:
                print('-> Currently not in a term')
                return
            else:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return
        
        for term in self._section.terms:
            if term.name == term_name:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return
            
        print('-> Unknown term: %s' % (term_name, ))

    def _set_section(self, args):
        print('Setting section...')
        section = self._mgr.find_section(args[0])
        if section is None:
            print('-> Unknown section: %s' % (args[0], ))
        else:
            self._section = section
            print('-> Section set to %s' % (str(section), ))
    
    def _generate_header_footer(self, document):
        now = date.today()
        section = document.sections[0]
        section.header.paragraphs[0].text = 'Badge Progress Report'
        section.footer.paragraphs[0].text = 'Generated ' + now.strftime('%d %B %Y')

    def _generate_report(self, scheme, document, badge_map):
        for badge in scheme.badges:
            paragraph = document.add_paragraph(badge.name)
            paragraph.style = document.styles['Heading 1']
            counts, labels = [], []
            for part in badge.parts:
                progress = 0
                part.badge = badge_map[part.id]
                part.badge.load_progress(self._conn)
                print('-> Loaded "%s"...' % (part.badge.name,))
                for person in part.badge.progress:
                    progress += len(person.parts)

                mean = progress * 100 / len(part.badge.progress)
                completion = mean / len(part.badge.parts)
                labels.append(part.name)
                counts.append(completion)
            
            fig, ax = plt.subplots(1, 1, figsize=(5, len(badge.parts)))
            ax.set_xlim(0, 100)
            ax.set_xlabel('Percentage completed')
            ax.barh(labels, counts)
            badge_path = os.path.join('temp_images', badge.name + '.png')
            fig.savefig(badge_path, bbox_inches='tight', dpi=300)
            document.add_picture(badge_path, width=Cm(16))
            print('-> Generated "%s"...' % (badge.name,))
예제 #3
0
class ReportGenerator(object):
    def __init__(self):
        self._conn = None
        self._mgr = None
        self._section = None
        self._term = None

    def _connect(self):
        self._conn = Connection('secret.json')
        self._conn.connect()

    def _initialise(self):
        self._mgr = Manager()
        self._mgr.load(self._conn)

    def run(self):
        print('Connecting to OSM...')
        self._connect()
        self._initialise()

        if len(sys.argv) < 3:
            print('ERROR: term and section have not been set! ')
            return

        self._set_term(sys.argv[1:3])
        if self._term is None:
            return

        print('Retrieving term programme...')
        report = self._term.load_programme(self._conn, include_attendance=True)

        print('Generating report...')
        filename = ensureExtension(sys.argv[2] + '-Attendence', '.xlsx')
        workbook = xlsxwriter.Workbook(filename)
        self._generate_report(report, workbook)

        print('Saving to %s...' % (filename, ))
        workbook.close()

        print('Done')

    def _set_term(self, args):
        term_name = args[0]
        self._set_section(args[1:])

        print('Setting term...')
        if term_name == 'current':
            term = self._section.current_term()
            if term is None:
                print('-> Currently not in a term')
                return
            else:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return

        for term in self._section.terms:
            if term.name == term_name:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return

        print('-> Unknown term: %s' % (term_name, ))

    def _set_section(self, args):
        print('Setting section...')
        section = self._mgr.find_section(args[0])
        if section is None:
            print('-> Unknown section: %s' % (args[0], ))
        else:
            self._section = section
            print('-> Section set to %s' % (str(section), ))

    def _generate_report(self, report, workbook):
        bold = workbook.add_format({'bold': True, 'font_size': 12})
        for meeting in report:
            msg = '-> Processing meeting ' + meeting.name + ' on ' + meeting.date.strftime(
                '%d-%m-%Y')
            print(msg.encode('ascii', 'ignore'))
            ws_name = meeting.date.strftime('%d-%m-%Y') + ' ' + meeting.name
            if len(ws_name) > 30:
                ws_name = ws_name[0:27] + '...'
            worksheet = workbook.add_worksheet(ws_name)
            worksheet.write('A1', meeting.name, bold)
            worksheet.write('A2', 'First Name', bold)
            worksheet.write('B2', 'Family Name', bold)
            worksheet.write('C2', 'Patrol', bold)
            row = 2
            for member in meeting.members:
                worksheet.write(row, 0, member.first_name)
                worksheet.write(row, 1, member.last_name)
                worksheet.write(row, 2, member.patrol)
                row += 1
예제 #4
0
class ReportGenerator(object):
    def __init__(self):
        self._conn = None
        self._mgr = None
        self._section = None
        self._term = None
        self._badge_order = None

    def _connect(self):
        self._conn = Connection('secret.json')
        self._conn.connect()

    def _initialise(self):
        self._mgr = Manager()
        self._mgr.load(self._conn)

    def run(self):
        if len(sys.argv) < 3:
            print('ERROR: term and section have not been set! ')
            return

        print('Connecting to OSM...')
        self._connect()
        self._initialise()

        self._set_term(sys.argv[1:3])
        if self._term is None:
            return

        order_path = 'report-order-' + sys.argv[2] + '.json'
        print('Retrieving badge order from ' + order_path + '...')
        self._badge_order = BadgeOrder(order_path)

        print('Retrieving badge report...')
        report = self._term.load_badges_by_person(self._conn)

        print('Generating report...')
        filename = ensureExtension(sys.argv[2] + '-Badge Report', '.docx')
        document = Document()
        self._generate_report(report, document)
        self._badge_order.save(order_path)

        print('Saving to %s...' % (filename, ))
        document.save(filename)

        print('Done')

    def _set_term(self, args):
        term_name = args[0]
        self._set_section(args[1:])

        print('Setting term...')
        if term_name == 'current':
            term = self._section.current_term()
            if term is None:
                print('-> Currently not in a term')
                return
            else:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return

        for term in self._section.terms:
            if term.name == term_name:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return

        print('-> Unknown term: %s' % (term_name, ))

    def _set_section(self, args):
        print('Setting section...')
        section = self._mgr.find_section(args[0])
        if section is None:
            print('-> Unknown section: %s' % (args[0], ))
        else:
            self._section = section
            print('-> Section set to %s' % (str(section), ))

    def _generate_report(self, report, document):
        headingStyle = document.styles.add_style('TableHeading',
                                                 WD_STYLE_TYPE.PARAGRAPH)
        headingStyle.font.bold = True

        section = document.sections[0]
        new_width, new_height = section.page_height, section.page_width
        section.orientation = WD_ORIENT.LANDSCAPE
        section.page_width = new_width
        section.page_height = new_height
        section.left_margin = Cm(1)
        section.right_margin = Cm(1)
        section.top_margin = Cm(1.5)
        section.bottom_margin = Cm(1.5)

        section.header.paragraphs[0].text = 'Badge Report'
        now = date.today()
        section.footer.paragraphs[0].text = 'Generated ' + now.strftime(
            '%d %B %Y')
        table = document.add_table(rows=1, cols=2, style='Table Grid')
        table.columns[0].width = Cm(5)
        table.columns[1].width = Cm(21)
        cells = table.rows[0].cells
        cells[0].text = 'Person'
        cells[1].text = 'Badges'
        cells[0].width = Cm(5)
        cells[1].width = Cm(21)
        clearFormatting(cells[0].paragraphs[0], headingStyle)
        clearFormatting(cells[1].paragraphs[0], headingStyle)
        set_repeat_table_header(table.rows[0])
        for person in [p for p in report if p.is_active]:
            cells = table.add_row().cells
            name = '%s %s' % (person.first_name, person.last_name)
            print('...adding row for %s...' % (name, ))
            cells[0].text = name
            clearFormatting(cells[0].paragraphs[0])
            para = cells[1].paragraphs[0]
            clearFormatting(para)
            cells[0].width = Cm(4)
            cells[1].width = Cm(22)
            person.badges.sort(key=self._sort_order)
            all_badges = {
                b.badge_id: True
                for b in person.badges if b.completed
            }
            for badge in person.badges:
                if self._badge_order.remove_with(badge.badge_id) in all_badges:
                    continue

                _, file_extension = os.path.splitext(badge.picture)
                badge_path = os.path.join('badge_images',
                                          badge.name + file_extension)
                if not os.path.exists(badge_path):
                    print('...retrieving badge image for %s...' %
                          (badge.name, ))
                    self._conn.download_binary(badge.picture, badge_path)
                if badge.completed:
                    para.add_run().add_picture(badge_path, width=Cm(2))
                    para.add_run(' ')
        preventDocumentBreak(document)

    def _sort_order(self, badge):
        return self._badge_order.get_order(badge.badge_id, badge.name)
예제 #5
0
class ReportGenerator(object):
    def __init__(self):
        self._conn = None
        self._mgr = None
        self._section = None
        self._term = None

    def _connect(self):
        self._conn = Connection('secret.json')
        self._conn.connect()

    def _initialise(self):
        self._mgr = Manager()
        self._mgr.load(self._conn)

    def run(self):
        if len(sys.argv) < 3:
            print('ERROR: term and section have not been set! ')
            return

        print('Connecting to OSM...')
        self._connect()
        self._initialise()

        self._set_term(sys.argv[1:3])
        if self._term is None:
            return

        print('Retrieving members...')
        members = self._term.load_members(self._conn, include_data=True)

        print('Retrieving term programme...')
        programme = self._term.load_programme(self._conn)
        now = date.today()
        night = programme[0]

        print('Generating sign-in sheet(s)...')
        night_to_find = 'next'
        if len(sys.argv) > 3:
            night_to_find = sys.argv[3]

        if night_to_find == 'next':
            for day in programme:
                night = day
                if day.date >= now:
                    break
            self.generate_sign_in_for_night(members, night)
        elif night_to_find == 'last':
            for day in programme:
                if day.date > now:
                    break
                night = day
            self.generate_sign_in_for_night(members, night)
        elif night_to_find == 'all':
            for day in programme:
                self.generate_sign_in_for_night(members, day)
        else:
            print('Unknown night selection option: "' + night_to_find + '"')

        print('Done')

    def generate_sign_in_for_night(self, members, night):
        print('Generating sign-in for "' + night.name + '"...')
        template = ensureExtension(sys.argv[2] + '-Signin-Template', '.docx')
        filename = ensureExtension(
            sys.argv[2] + ' Sign in Sheet - ' + night.date.strftime('%Y%m%d'),
            '.docx')
        document = Document(template)
        self._generate_report(members, document, night)

        print('Saving to %s...' % (filename, ))
        document.save(filename)

    def _set_term(self, args):
        term_name = args[0]
        self._set_section(args[1:])

        print('Setting term...')
        if term_name == 'current':
            term = self._section.current_term()
            if term is None:
                print('-> Currently not in a term')
                return
            else:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return

        for term in self._section.terms:
            if term.name == term_name:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return

        print('-> Unknown term: %s' % (term_name, ))

    def _set_section(self, args):
        print('Setting section...')
        section = self._mgr.find_section(args[0])
        if section is None:
            print('-> Unknown section: %s' % (args[0], ))
        else:
            self._section = section
            print('-> Section set to %s' % (str(section), ))

    def _generate_report(self, members, doc, night):
        for para in doc.paragraphs:
            for run in para.runs:
                if run.text == '{{date}}':
                    run.text = night.date.strftime('%d %B %Y')
                if run.text == '{{activity}}':
                    run.text = night.name

        print('...extracting data')
        report_data = []
        for person in members:
            if (person.patrol == 'Leaders') or not person.is_active:
                continue

            name = '%s %s' % (person.first_name.strip(),
                              person.last_name.strip())
            try:
                contact = person.custom_data['contact_primary_1']
            except KeyError:
                try:
                    contact = person.custom_data['contact_primary_2']
                except KeyError:
                    contact = None

            if not contact is None:
                contact_person = '%s %s' % (contact['first_name'].strip(),
                                            contact['last_name'].strip())
                try:
                    contact_number = contact['mobile_phone']
                except KeyError:
                    try:
                        contact_number = contact['home_phone']
                    except KeyError:
                        contact_number = ''
            report_data.append([name, contact_person, contact_number])

        print('...populating table')
        report_data.sort(key=lambda r: r[0])
        row = 1
        table = doc.tables[0]
        for person in report_data:
            try:
                cells = table.rows[row].cells
            except IndexError:
                print(
                    '!! ERROR !! Table full - unable to add additional members !! EROR !!'
                )
            row += 1
            print('...adding row for %s...' % (person[0], ))
            cells[1].text = person[0]
            cells[4].text = person[1]
            cells[5].text = person[2]
예제 #6
0
class ReportGenerator(object):
    def __init__(self):
        self._conn = None
        self._mgr = None
        self._section = None
        self._term = None

    def _connect(self):
        self._conn = Connection('secret.json')
        self._conn.connect()

    def _initialise(self):
        self._mgr = Manager()
        self._mgr.load(self._conn)
        if not os.path.exists('temp_images'):
            os.makedirs('temp_images')

    def run(self):
        print('Connecting to OSM...')
        self._connect()
        self._initialise()

        if len(sys.argv) < 3:
            print('ERROR: term and section have not been set! ')
            return

        self._set_term(sys.argv[1:3])
        if self._term is None:
            return

        print('Retrieving badge data...')
        scheme = AwardScheme(self._section.name + '-award.json')
        print('-> Loaded award scheme definition')
        self._term.load_badges(self._conn)
        badge_map = {}
        for badge in self._term.badges:
            badge_map[badge.badge_id] = badge
        print('-> Loaded badges')

        print('Retrieving members...')
        members = self._term.load_members(self._conn)
        print('-> Loaded members')

        print('Generating report...')
        filename = ensureExtension(sys.argv[2] + '-Badge Status', '.xlsx')
        workbook = xlsxwriter.Workbook(filename)
        self._generate_report(scheme, members, badge_map, workbook)

        print('Saving to %s...' % (filename, ))
        workbook.close()

        print('Done')

    def _set_term(self, args):
        term_name = args[0]
        self._set_section(args[1:])

        print('Setting term...')
        if term_name == 'current':
            term = self._section.current_term()
            if term is None:
                print('-> Currently not in a term')
                return
            else:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return

        for term in self._section.terms:
            if term.name == term_name:
                self._term = term
                print('-> Term set to %s' % (str(term), ))
                return

        print('-> Unknown term: %s' % (term_name, ))

    def _set_section(self, args):
        print('Setting section...')
        section = self._mgr.find_section(args[0])
        if section is None:
            print('-> Unknown section: %s' % (args[0], ))
        else:
            self._section = section
            print('-> Section set to %s' % (str(section), ))

    def _generate_report(self, scheme, members, badge_map, workbook):
        bold_format = workbook.add_format({'bold': True, 'font_size': 12})
        progress_format = workbook.add_format({'num_format': '0.00'})
        for badge in scheme.badges:
            print('-> Processing ' + badge.name)
            ws_name = badge.name
            if len(ws_name) > 30:
                ws_name = ws_name[0:27] + '...'
            worksheet = workbook.add_worksheet(ws_name)
            worksheet.write('A1', badge.name, bold_format)
            worksheet.write('A2', 'First Name', bold_format)
            worksheet.write('B2', 'Family Name', bold_format)
            worksheet.write('C2', 'Awarded', bold_format)

            row = 3 if badge.group else 2
            member_map = {}
            for member in members:
                if member.patrol != 'Leaders':
                    member_map[member.member_id] = row
                    worksheet.write(row, 0, member.first_name)
                    worksheet.write(row, 1, member.last_name)
                    row += 1

            if not badge.complete_id is None:
                complete_badge = badge_map[badge.complete_id]
                complete_badge.load_progress(self._conn)
                print('-> Loaded "%s"...' % (complete_badge.name, ))
                for member in complete_badge.progress:
                    worksheet.write(member_map[member.member_id], 2,
                                    'Yes' if member.completed else 'No')

            column = 3
            for part in badge.parts:
                worksheet.write(1, column, part.name, bold_format)
                part.badge = badge_map[part.id]
                if not part.badge.progress_loaded:
                    part.badge.load_progress(self._conn)
                    print('-> Loaded "%s"...' % (part.badge.name, ))
                part_progress = {}

                part_count = 1
                groups = {}
                if part.group:
                    last_part = ''
                    part_count = 0
                    for badge_part in part.badge.parts:
                        this_part = badge_part.name.strip()
                        if last_part != this_part:
                            last_part = this_part
                            worksheet.write(2, column + part_count, last_part,
                                            bold_format)
                            groups[last_part] = []
                            part_count += 1
                        groups[last_part].append(badge_part.part_id)
                else:
                    groups['all'] = len(part.badge.parts)

                print('--> Calculating progress')
                for item in part.badge.progress:
                    if item.completed:
                        part_progress[item.member_id] = [
                            1.0 for _ in range(part_count)
                        ]
                    else:
                        if part.group:
                            part_progress[item.member_id] = [
                                0.0 for _ in range(part_count)
                            ]
                            pos = 0
                            for grp_list in groups.values():
                                count = 0
                                for id in grp_list:
                                    if id in item.parts:
                                        count += 1
                                actual_progress = count / len(grp_list)
                                part_progress[
                                    item.member_id][pos] = actual_progress
                                pos += 1
                        else:
                            total = len(item.parts)
                            part_progress[item.member_id] = [
                                total / groups['all']
                            ]

                print('--> Exporting')
                for member in member_map.keys():
                    row = member_map[member]
                    item_progress = part_progress[member]
                    for loop in range(part_count):
                        worksheet.write(row, column + loop,
                                        item_progress[loop], progress_format)

                column += part_count

            last_column = xlsxwriter.utility.xl_col_to_name(column - 1)
            last_row = str(len(members) + (3 if badge.group else 2))
            range_to_format = ('D4' if badge.group else
                               'D3') + ':' + last_column + last_row
            worksheet.conditional_format(
                range_to_format, {
                    'type':
                    'icon_set',
                    'icon_style':
                    '5_arrows',
                    'icons': [{
                        'criteria': '>',
                        'type': 'number',
                        'value': 0.99
                    }, {
                        'criteria': '>',
                        'type': 'number',
                        'value': 0.75
                    }, {
                        'criteria': '>',
                        'type': 'number',
                        'value': 0.50
                    }, {
                        'criteria': '>',
                        'type': 'number',
                        'value': 0.25
                    }]
                })