def _connect(self): self._conn = Connection('secret.json') self._conn.connect()
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,))
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
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)
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]
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 }] })