def renew_recent_resumers(): resume_date = fmt_date(datetime.date(current_year_end().year, 4, 1)) end_date = fmt_date(datetime.date(current_year_end().year, 8, 1)) query_clauses = [ ('Payment', 'date', resume_date, '>=', None), ('Payment', 'type', PaymentType.dues, '=', None), ('Member', 'end_date', end_date, '=', None), ] members = get_members_for_query(query_clauses) count = 0 message = [] for member in members: if member.is_recent_resume(): member.end_date = new_end_date item = first_or_default([ a for a in member.actions if a.action == MemberAction.card and a.status == ActionStatus.open ], None) if not item: item = Action(member_id=member.id, date=datetime.date.today(), action=MemberAction.card, comment='auto renew recent resumer', status=ActionStatus.open) member.actions.append(item) message += [member.dt_number()] save_member(member) count += 1 return '\n'.join(['{} members updated'.format(count)] + message)
def populate_member_list(self, query_clauses, clauses, page_number=1): if not query_clauses: return query_to_select_fields(self.all_sels(), query_clauses) query = get_members_for_query(query_clauses) page = query.paginate(page=page_number, per_page=15) self.total.data = page.total self.current_page.data = page_number self.total_pages.data = page.pages self.first_url = url_for('members', page=1, query_clauses=clauses) self.next_url = url_for( 'members', page=page_number + 1, query_clauses=clauses) if page.has_next else None self.prev_url = url_for( 'members', page=page_number - 1, query_clauses=clauses) if page.has_prev else None self.last_url = url_for('members', page=page.pages, query_clauses=clauses) for member in page.items: # get_all_members(select) : item_form = MemberItemForm() item_form.member_number = member.number item_form.number = member.dt_number() item_form.status = member.status.name item_form.is_active = member.is_active() item_form.member_type = member.member_type.name item_form.first_name = member.first_name item_form.last_name = member.last_name item_form.email = member.email or '' item_form.post_code = member.address.post_code item_form.country = member.address.country.name item_form.start_date = fmt_date(member.start_date) item_form.end_date = fmt_date(member.end_date) self.member_list.append_entry(item_form)
def renewal_activated(self): last_payment = self.last_payment() if last_payment and last_payment.type.name == 'pending': last_action = self.last_action() if last_action and last_action.action == MemberAction.upgrade and last_action.status == ActionStatus.open: return 'Renewal was activated {} ({})'.format( fmt_date(last_action.date), last_action.comment) else: return 'Renewal was activated {}'.format( fmt_date(last_payment.date)) else: return None
def populate_calendar_event_list(self, year): for event in get_events_for_year(year): if event.type in [ EventType.wags_vl_event, EventType.non_vl_event, EventType.non_event ] and event.venue.contact: item_form = EventCalendarItemForm() item_form.name = "WAGS - " + (event.trophy.name if event.trophy else event.venue.name) item_form.date = fmt_date(event.date, '%Y-%m-%d') item_form.location = event.venue.name item_form.all_day = 'N' if event.type in [ EventType.wags_vl_event, EventType.non_vl_event ] else 'Y' schedule = event.schedule if item_form.all_day == 'N' and len(schedule) > 0: item_form.event_start_time = schedule[0].time.strftime( '%H:%M') item_form.event_end_time = schedule[-1].time.strftime( '%H:%M') else: item_form.all_day = 'Y' item_form.link = add_http(event.venue.contact.url) item_form.link_description = 'Go to venue' self.event_calendar_list.append(item_form)
def populate_trophy(self, trophy_id): trophy = get_trophy(trophy_id) self.trophy_name.data = trophy.name self.image_url.data = url_for_html('pictures', 'trophies', trophy.name.lower() + '.jpg') extra_file = 'user/extra/' + trophy.name.lower() + '.htm' if template_exists(extra_file): self.extra.data = extra_file hist = trophy.events for event in hist: tour = first_or_default([ e for e in hist if e.date.year == event.date.year and e.type == EventType.wags_tour ], None) if event.date < datetime.date.today() \ and ((event.type == EventType.wags_vl_event and not tour) \ or (event.type == EventType.wags_tour and tour)): item_form = TrophyItemForm() item_form.venue = event.venue.name item_form.date = fmt_date(event.date) if event.winner: item_form.winner = event.winner.full_name() if event.type == EventType.wags_vl_event: item_form.score = event.winner.score_for( event.id).points item_form.average = event.average_score else: item_form.score = item_form.average = '' else: item_form.winner = item_form.score = item_form.average = '' self.winners.append_entry(item_form)
def add_news_item(self): item_type = self.item_to_add.data if item_type == NewsItemType.account_update: item = NewsItem(text='Accounts updated in members area', link='', title='') elif item_type == NewsItemType.handicap_update: item = NewsItem(text='Handicaps updated', link='/wagsuser/handicaps', title='show current handicaps') elif item_type == NewsItemType.event_result: event = get_latest_event(include_tours=True) item = NewsItem(text='Results for {} updated'.format(event.venue.name), link='/wagsuser/events/{}/results'.format(event.id), title='show results') elif item_type == NewsItemType.open_booking: event = get_next_event() item = NewsItem(text='Booking now open for {} {}'.format(event.venue.name, encode_date(event.date)), link='/wagsuser/events/{}/book'.format(event.id), title='book now') elif item_type == NewsItemType.publish_minutes: latest = Minutes.latest_minutes() message = latest.full_type() + ' ' + fmt_date(latest.date) + ' minutes published' item = NewsItem(text=message, link=latest.file_link(), title='show minutes') else: return free = [ind for ind, item in enumerate(self.items.data) if item['text'] == ''] if len(free) == 0: free = [len(self.items)] self.items.append_entry(NewsItemForm()) self.items[free[0]].text.data = item.text self.items[free[0]].link.data = item.link self.items[free[0]].title.data = item.title if self.is_new.data == 'True': self.save.label.text = 'Publish'
def populate_event_bookings(self, event_id): event = get_event(event_id) self.event_name.data = event.full_name() self.sub_title.data = 'to date' if datetime.date.today( ) <= event.booking_end else '' cd = event.course.course_data_as_of(event.date.year) self.slope.data = cd.slope total = 0 for booking in event.bookings: item_form = BookingItemForm() item_form.date = fmt_date(booking.date) item_form.member_name = booking.member.player.full_name() if booking.playing: item_form.hcap = booking.member.player.state_as_of( event.date).playing_handicap(event) number = 1 + len(booking.guests) item_form.number = number total += number item_form.guests = ', '.join([ g.name + ' ({})'.format(cd.apply_slope_factor(g.handicap, cd.slope)) for g in booking.guests ]) item_form.comment = booking.comment or '' self.booking_list.append_entry(item_form) self.total.data = total
def populate_event_handicaps(self, event_id): self.event_id.data = event_id event = get_event(event_id) self.event_name.data = event.full_name() scratch = competition_scratch_score(event) self.new_date.data = fmt_date(event.date + datetime.timedelta(days=1)) self.editable.data = True # is_latest_event(event) if self.editable.data: next_event_date = datetime.date.today() else: next_event = get_next_event(event.date) if next_event: next_event_date = next_event.date else: next_event_date = datetime.date.today() num = 0 for player in sorted_players_for_event(event): num += 1 item_form = EventHandicapItemForm() item_form.num = str(num) orig_state = player.state_as_of(event.date) new_state = player.state_as_of(next_event_date) item_form.player = player.full_name() + orig_state.status.qualify() item_form.handicap = new_state.handicap item_form.old_handicap = orig_state.handicap score = player.score_for(event.id) item_form.suggested = suggested_handicap_change( scratch, orig_state.handicap, score.points) item_form.points = score.points item_form.strokes = score.shots item_form.position = score.position item_form.player_id = player.id item_form.status_return = orig_state.status.value item_form.old_handicap_return = orig_state.handicap self.scores.append_entry(item_form)
def get_attr(obj, spec): # extract data for attr spec from populated database object # e.g. get_attr(member, 'address.line_1') # or get_attr(member, 'address.country_for_mail()') - invoke a method if not spec: return '' if '=' == first_or_default(spec, ' '): return eval(spec[1:]) attr, tail = pop_next(spec, '.') if '()' in attr: # function call res = getattr(obj, attr.replace('()', ''))() elif tail and '()' in tail: # function call res = getattr(obj, attr) elif '[]' in attr: # list - get first res = first_or_default(getattr(obj, attr.replace('[]', '')), None) elif 'actions[' in attr: # list - get specific (name, type) = attr.split('[') res = first_or_default([a for a in getattr(obj, name) if a.action.name == type[:-1]], None) elif 'payments[' in attr: # list - get specific (name, type) = attr.split('[') res = first_or_default([a for a in getattr(obj, name) if a.type.name == type[:-1]], None) elif '{' in attr: # literal - return as value res = attr.replace('{', '').replace('}', '') else: # property res = getattr(obj, attr) if res and tail: res = get_attr(res, tail) if res and 'date' in spec and isinstance(res, datetime.date): res = fmt_date(res) return res if res is not None else ''
def from_html(html): # Creates a news item from html in the format: # <hr/> # <p><b>8th September 2013</b> # <ul> # <li>Line</li> # <li><a href="../2013/fixtures.htm" title="book now">Booking now open for Wimbledon Common Wednesday 25th September</a></li> # <li><a href="../minutes/min 2013 09 04.htm">Minutes of email committee meeting held on 4th September</a> from Anthony Shutes</li> # </ul> html_lines = html.split('\n') day = NewsDay() day.date = fmt_date(decode_date_formal(html_lines[1][6:-4])) list_start = lookup(html_lines, '<ul>') day.message = [] day.items = [] if list_start == -1: list_start = len(html_lines) + 1 day.message = ' '.join(html_lines[2:list_start]) day.message = day.message.replace('<p>', '\n').replace('<br>', '\n') if day.message.startswith('\n'): day.message = day.message[1:] for html_line in html_lines[list_start + 1:-2]: item = NewsItem.from_html(html_line) day.items.append(item) return day
def populate_event(self, event_id, member_id): event = get_event(event_id) self.bookable.data = event.is_bookable() self.at_capacity.data = event.at_capacity() if self.bookable.data: self.title.data = 'Book Event' else: self.title.data = 'Event Details' self.show_bookings.data = len(event.bookings) > 0 self.event_id.data = event_id self.event_type.data = event.type self.date.data = encode_date(event.date) if event.organiser: self.organiser_id.data = event.organiser.id self.organiser.data = event.organiser.player.full_name() else: self.organiser_id.data = 0 self.event.data = event.trophy.name if event.trophy else event.venue.name self.venue.data = event.venue.name contact = event.venue.contact or Contact() post_code = contact.post_code or '' self.venue_address.data = line_break( (contact.address or '') + ',' + post_code, [',', '\r', '\n']) self.venue_phone.data = contact.phone or '' self.map_url.data = 'http://maps.google.co.uk/maps?q={}&title={}&z=12 target="googlemap"' \ .format(post_code.replace(' ', '+'), event.venue.name) self.venue_directions.data = line_break(event.venue.directions or '', '\n') self.schedule.data = line_break([(s.time.strftime('%H:%M ') + s.text) for s in event.schedule]) self.member_price.data = event.member_price self.guest_price.data = event.guest_price self.booking_deadline.data = encode_date(event.booking_end) self.notes.data = event.note or '' if member_id == 0: self.message.data = '' return booking = get_booking(event_id, member_id) if not booking.id: booking.member = get_member(member_id) booking.playing = True self.message.data = self.booking_message(event, booking) if event.is_bookable() or booking.id: self.attend.data = booking.playing self.comment.data = booking.comment self.booking_date.data = fmt_date(booking.date) self.member_name.data = booking.member.player.full_name() count = 1 for guest in booking.guests + (3 - len(booking.guests)) * [Guest()]: item_form = GuestForm() item_form.item_pos = count item_form.guest_name = guest.name item_form.handicap = guest.handicap self.guests.append_entry(item_form) count += 1
def populate_history(self, player_id, event_id): player = get_player(player_id) event = get_event(event_id) self.player.data = player.full_name() for item in player.states_up_to(event.date): item_form = HandicapItemForm() item_form.date = fmt_date(item.date) item_form.handicap = item.handicap item_form.status = item.status.name self.history.append_entry(item_form)
def to_dict(self): data = {} for field in self.dict_fields: value = getattr(self, field) if 'date' in field: value = fmt_date(value) elif isinstance(value, Enum): value = value.to_dict() elif field == 'address': value = value.to_dict() data[field] = value return data
def lapse_expired(): query_clauses = [ ('Member', 'status', [s.value for s in MemberStatus.all_active()], 'in', None), ('Member', 'end_date', fmt_date(previous_year_end()), '=', None) ] members = get_members_for_query(query_clauses) count = 0 for member in members: member.status = MemberStatus.lapsed save_member(member) count += 1 return '{} records processed'.format(count)
def extract_renewals(): # for renewal notices at membership year end end_date = fmt_date(current_year_end()) query_clauses = [('Member', 'end_date', end_date, '=', None), ('Member', 'status', [s.value for s in MemberStatus.all_active()], 'in', None)] display_fields = \ ['number', 'id number', 'full name', 'address (line 1)', 'address (line 2)', 'address (line 3)', 'city', 'county', 'state', 'post code', 'country for post', 'fan id', 'status', 'member type', 'type at renewal', 'email', 'comms', 'payment method', 'renewal notes', 'home phone', 'mobile phone', 'birth date', 'junior email', 'AFCW access', '3rd pty access', 'recent new', 'recent resume'] return Query.show_found_do(query_clauses, display_fields)
def populate_history(self, player_id, year=None): player = get_player(player_id) self.player.data = player.full_name() self.year.data = year or '' events = self.get_player_history(player_id, year) for item in events.data: item_form = PlayerEventForm() item_form.date = fmt_date(item[events.column_index('date')]) item_form.course = item[events.column_index('course')] item_form.position = item[events.column_index('position')] item_form.points = item[events.column_index('points')] item_form.strokes = item[events.column_index('shots')] item_form.handicap = item[events.column_index('handicap')] item_form.status = player.state_as_of(item[events.column_index('date')]).status.name self.history.append_entry(item_form)
def extract_debits(): end_date = fmt_date(current_year_end()) query_clauses = [ ('Member', 'end_date', end_date, '=', None), ('Member', 'last_payment_method', [PaymentMethod.dd.value, PaymentMethod.dd_pending.value], 'in', None), ('Member', 'status', [s.value for s in MemberStatus.all_active()], 'in', None) ] display_fields = \ ['number', 'type at renewal', 'full name', 'dues pending', 'email', 'phone', 'address (line 1)', 'address (line 2)', 'address (line 3)', 'city', 'county', 'state', 'post code', 'country for post', 'title', 'first name', 'last name'] return Query.show_found_do(query_clauses, display_fields)
def set_region(): query_clauses = [ ('Member', 'status', [s.value for s in MemberStatus.all_active()], 'in', None), ('Member', 'end_date', fmt_date(current_year_end()), '=', None) ] members = get_members_for_query(query_clauses) count = 0 for member in members: region = get_region(member.address.country, member.address.post_code) if region: member.address.region = region save_member(member) count += 1 return '{} records processed'.format(count)
def limit_status_and_lapsed_date_by_access(query_clauses): if not current_user.role.has_lapsed_access('all'): # limit inclusion of lapsed members according to current user's access rights sel_status = [ c for c in query_clauses if c[0] == 'Member' and c[1] == 'status' ] if not sel_status: limit = current_user.access_limit() query_clauses.append( ('Member', 'status', limit, '<=', None, 'sel_status')) if not current_user.role.has_lapsed_access('1yr+'): last_lapse_date = get_1yr_lapsed_date() query_clauses.append( ('Member', 'end_date', fmt_date(last_lapse_date), '>=', None, 'sel_end_date')) return query_clauses
def populate_swing(self, year): self.year.data = str(year) as_of = datetime.date(year, datetime.date.today().month, datetime.date.today().day) year_range, swings = get_big_swing(year, as_of) for item in swings.data: item_form = SwingItemForm() item_form.position = item[swings.column_index('position')] item_form.player = item[swings.column_index('player')] item_form.course = item[swings.column_index('course')] item_form.date = fmt_date(item[swings.column_index('date')]) item_form.points_out = item[swings.column_index('points_out')] item_form.points_in = item[swings.column_index('points_in')] item_form.swing = item[swings.column_index('swing')] self.swing.append_entry(item_form) self.year_span.data = str(year_range[0]) + '/' + str(year_range[1]) self.image_url.data = url_for_html('pictures', 'trophies', 'swing.jpg')
def upload_minutes(self, member_id): minutes = Minutes(self.meeting_type.data, self.meeting_date.data) link = self.save_file(self, minutes, draft=True) # notify committee subject = '{} {} - draft minutes for review'.format( minutes.full_type(), fmt_date(minutes.date)) sender = get_member(member_id).contact.email message = [ 'The draft minutes are available here:', link, self.message.data ] to = [m.member.contact.email for m in get_committee()] send_mail(to=to, sender=sender, cc=[], subject='WAGS: ' + subject, message=message) return True
def populate_event_list(self, year): self.editable.data = is_event_editable(year) override = config.get('override') for event in get_events_for_year(year): event_type = event.type item_form = EventItemForm() item_form.event_id = event.id item_form.date = fmt_date(event.date) item_form.event = event.trophy.name if event.trophy else '' item_form.venue = event.venue.name item_form.event_type = event_type item_form.result = override or ( event.date <= datetime.date.today() and event.type in [ EventType.wags_vl_event, EventType.non_vl_event, EventType.wags_tour ]) self.event_list.append_entry(item_form)
def populate(self): type = self.minutes_type.data year = self.minutes_year.data if year == 'None': year = None if type: type = None if type.name == 'all' else type if year: year = None if year == 'all' else int(year) minutes = Minutes.get_all_minutes(type, year) if len(minutes) == 0: flash('None found', 'warning') for m in minutes: item_form = MinutesShowItemForm() item_form.mtype = m.full_type() item_form.mdate = fmt_date(m.date) item_form.mlink = m.file_link() self.choices.append_entry(item_form)
def populate_account(self, member_id, year): member = get_member(member_id) self.title.data = '{} - Account information {}'.format( member.player.full_name(), year) balance = 0 account = get_member_account(member.player.full_name(), year) for item in account.rows(): item_form = AccountItemForm() item_form.date = fmt_date(parse_date(item['date'], reverse=True)) item_form.item = item['item'] debit = parse_float(item['debit']) item_form.debit = fmt_curr(debit) credit = parse_float(item['credit']) item_form.credit = fmt_curr(credit) self.items.append_entry(item_form) balance += (credit or 0) - (debit or 0) self.balance.data = fmt_curr(balance) self.negative_balance.data = balance < 0
def booking_message(event, booking): if event.type == EventType.cancelled: return 'This event has been cancelled' if event.bookable( ) == -1 or event.tour_event_id and event.tour_event.type == EventType.wags_tour: return 'Booking is not available for this event' today = datetime.date.today() booking_start = event.booking_start or event.date booking_end = event.booking_end or event.date if today > booking_end: return 'Booking is now closed for this event' if booking_start > today: return 'Booking is not yet open for this event' if booking.id: return 'You responded on {} - see below for details'.format( fmt_date(booking.date)) if event.at_capacity(): return 'Event is at capacity' \ + (': Please contact the organiser to go on the reserve list.' if event.has_reserve_list() else '.') return ''
def get_all_scores(): current_members = get_all_members(current=True) current_players = [m.player_id for m in current_members] scores = db_session.query(Score.player_id, Event.date) \ .join(Event) \ .filter(Score.player_id.in_(current_players)) \ .filter(Score.points > 0) \ .order_by(Score.player_id, Event.date) \ .all() head = ['player_id', 'player', 'status', 'count', 'first_game'] data = [] for player_scores in [list(group) for key, group in itertools.groupby(scores, lambda x: x[0])]: player_id, first = player_scores[0] status = [m.status for m in current_members if m.player_id == player_id] count = len(player_scores) player = get_player(player_id) data.append((player_id, player.full_name(), status[0].name, count, fmt_date(first))) res = Table(head, data) res.sort('count', reverse=True) return res
def extract_debits_for_ptx(): end_date = fmt_date(current_year_end()) query_clauses = [ ('Member', 'end_date', end_date, '=', None), ('Member', 'last_payment_method', [PaymentMethod.dd.value, PaymentMethod.dd_pending.value], 'in', None), ('Member', 'status', [s.value for s in MemberStatus.all_active()], 'in', None) ] display_fields = [(None, 'Contact Reference'), ('fmt id number', 'Mandate Reference'), (None, 'Mandate Status'), ('title for ptx', 'Title'), ('first name', 'First Name'), ('last name', 'Last Name'), (None, 'Company'), ('address (line 1)', 'Street1'), ('address (line 2)', 'Street2'), ('address (line 3)', 'Street3'), ('city', 'City'), ('post code', 'Post Code'), ('county', 'County'), ('country for post', 'Country'), ('phone', 'Telephone'), ('email', 'Email'), ('number at renewal', 'Alternative Reference'), (None, 'Account Name'), (None, 'Sort Code'), (None, 'Account Number'), (None, 'Plan Index'), (None, 'Frequency Type', '{YEARLY}'), (None, 'Start Date', '{2021-08-11}'), (None, 'End Date'), (None, 'Number of Occurrences'), (None, 'Recurrence'), (None, 'Frequency Details1', '{DAY11}'), (None, 'Frequency Details2', '{AUGUST}'), ('fmt dues pending', 'Regular Amount'), (None, 'First Amount'), (None, 'Last Amount'), (None, 'Total Amount'), ('extended type at renewal', 'Comments'), (None, 'Profile Name'), ('comms for ptx', 'Communication Preference')] return Query.show_found_do(query_clauses, display_fields)
def populate_member(self, member_number, return_url, copy=False): self.return_url.data = return_url new_member = member_number == 0 if new_member or copy: member = get_new_member() else: member = get_member(member_number) if copy: base_member = get_member(member_number) new_member = True member.last_name = base_member.last_name member.address = base_member.address member.home_phone = base_member.home_phone member.mobile_phone = base_member.mobile_phone member.email = base_member.email member.comms = base_member.comms address = member.address self.member_number.data = str(member.number) self.dt_number.data = member.dt_number() self.status.data = member.status.value self.type.data = member.member_type.value self.start_date.data = member.start_date self.end_date.data = member.end_date self.birth_date.data = member.birth_date self.age.data = str(member.age()) if member.age() is not None else None self.last_updated.data = fmt_date(member.last_updated) self.access.data = member.user.role.value if member.user else 0 self.fan_id.data = member.season_ticket_id if member.season_ticket_id else '' self.external_access.data = (member.external_access or ExternalAccess.none).value self.payment_method.data = member.last_payment_method.value if member.last_payment_method else '' self.full_name.data = member.full_name() self.title.data = member.title.value if member.title else '' self.first_name.data = member.first_name self.last_name.data = member.last_name self.sex.data = member.sex.value if member.sex else '' self.line1.data = address.line_1 self.line2.data = address.line_2 self.line3.data = address.line_3 self.city.data = address.city self.state.data = address.state.id if address.state else 0 self.post_code.data = address.post_code self.county.data = address.county.id if address.county else 0 self.country.data = address.country.id self.home_phone.data = member.home_phone self.mobile_phone.data = member.mobile_phone self.email.data = member.email self.comms.data = member.comms.value self.comms_status.data = member.comms_status.value if member.comms_status else CommsStatus.all_ok for payment in [get_new_payment()] + member.payments: item_form = PaymentItemForm() item_form.date = payment.date item_form.pay_type = payment.type.value ## nb: don't set the data attribute for select fields in a fieldlist! item_form.amount = payment.amount item_form.method = payment.method.value if payment.method else None item_form.comment = payment.comment or '' self.payment_list.append_entry(item_form) for action in [get_new_action(new_member)] + member.actions: item_form = ActionItemForm() if action.action: item_form.action = action.action.value if action.status: item_form.status = action.status.value item_form.date = action.date item_form.comment = action.comment or '' self.action_list.append_entry(item_form) for comment in [get_new_comment()] + member.comments: item_form = CommentItemForm() item_form.date = comment.date item_form.comment = comment.comment or '' self.comment_list.append_entry(item_form) if new_member or member.member_type == MembershipType.junior: if not member.junior: member.junior = get_junior() self.jd_email.data = member.junior.email or '' self.jd_gift.data = member.junior.gift.value if member.junior.gift else '' else: self.jd_email = self.jd_gift = None
def file_name(self): meeting_date = fmt_date(self.date).replace('/', ' ') meeting_type = Minutes.map_type_to_file(self.type) return meeting_type + ' ' + meeting_date + '.' + self.file_type
def full_name(self): name = '' if self.trophy: name += self.trophy.name + ' ' name += self.venue.name + ' ' + fmt_date(self.date) return name