Exemple #1
0
 def concession_type(self):
     if self.member_type in MembershipType.concessions(all=True):
         long = [
             c for c in MembershipType.renewal_choices()
             if c[0] == self.member_type.value
         ][0][1]
     else:
         long = ''
     return long
Exemple #2
0
def membership_type_choices():
    # set choices for membership type according to current user's access rights
    junior = current_user.is_access(UserRole.jd_admin)
    choices = MembershipType.choices(extra=[(99, 'adult (!=junior)')],
                                     blank=True)
    if junior:
        choices = [c for c in choices if c[1] == 'junior']
    return choices
Exemple #3
0
 def renewal_payment(self, member, upgrade):
     member_type = member.member_type_at_renewal()
     if member.status == MemberStatus.life:
         return None
     new_member = member.is_recent_new() or member.is_recent_resume()
     if new_member:
         if member_type == MembershipType.junior:
             return None
         elif member_type in MembershipType.concessions(all=True):
             return RenewalPayment.Dons_Trust_Plus_Concession_upgrade if upgrade else None
         elif member_type == MembershipType.standard:
             return RenewalPayment.Dons_Trust_Plus_Adult_upgrade if upgrade else None
     else:
         plus = upgrade or member.status == MemberStatus.plus
         if member_type == MembershipType.junior:
             return RenewalPayment.Junior_Dons_renewal
         elif member_type in MembershipType.concessions(all=True):
             return RenewalPayment.Dons_Trust_Plus_Concession if plus else RenewalPayment.Concession
         elif member_type == MembershipType.standard:
             return RenewalPayment.Dons_Trust_Plus_Adult if plus else RenewalPayment.Adult
Exemple #4
0
 def extract_email_senior():
     query_clauses = [
         ('Member', 'status', [s.value for s in MemberStatus.all_active()],
          'in', None),
         ('Member', 'member_type',
          [s.value for s in MembershipType.adult()], 'in', None),
         ('Member', 'comms', CommsType.email.value, '=', None),
         ('Member', 'comms_status', CommsStatus.all_ok.value, '=', None)
     ]
     display_fields = ['number', 'first name', 'email']
     return Query.show_found_do(query_clauses, display_fields)
Exemple #5
0
 def long_membership_type(self, upgrade=False):
     long_type = [
         c for c in MembershipType.renewal_choices()
         if c[0] == self.member_type.value
     ][0][1]
     if self.status == MemberStatus.life:
         status = '(Life)'
     elif upgrade or self.status == MemberStatus.plus:
         status = '(Plus)'
     else:
         status = ''
     return long_type + status
Exemple #6
0
 def upgrade_dues(self, as_of=None):
     if self.status == [MemberStatus.life]:
         return 0
     if not as_of:
         as_of = current_year_end()
     type = self.member_type_at_renewal(as_of)
     if type in MembershipType.concessions():
         return PlusUpgradeDues.concession.value
     if type == MembershipType.intermediate:
         return PlusUpgradeDues.intermediate.value
     if type == MembershipType.senior:
         return PlusUpgradeDues.senior.value
     return PlusUpgradeDues.standard.value
Exemple #7
0
 def member_type_at_renewal(self, as_of=None):
     if self.member_type in MembershipType.concessions():
         return self.member_type
     if not as_of:
         as_of = current_year_end()
     age = self.age(as_of, True)
     if age <= AgeBand.junior.upper:
         return MembershipType.junior
     if age <= AgeBand.intermediate.upper:
         return MembershipType.intermediate
     if age < AgeBand.senior.lower:
         return MembershipType.standard
     if age >= AgeBand.senior.lower:
         return MembershipType.senior
     return MembershipType.standard
Exemple #8
0
 def base_dues(self, as_of=None):
     if not as_of:
         as_of = current_year_end()
     if self.status == MemberStatus.life or self.is_recent_resume(
     ) or self.is_recent_new():
         return 0
     type = self.member_type_at_renewal(as_of)
     if type in MembershipType.concessions():
         return Dues.concession.value
     if type == MembershipType.junior:
         return Dues.junior.value
     if type == MembershipType.intermediate:
         return Dues.intermediate.value
     if type == MembershipType.senior:
         return Dues.senior.value
     return Dues.standard.value
Exemple #9
0
 def add_member(member, member_totals):
     member_type = member.member_type
     member_totals[member_type] += 1
     if member.status == MemberStatus.life:
         if member_type == MembershipType.junior:
             member_totals[101] += 1
         else:
             member_totals[100] += 1
     if member.status == MemberStatus.plus:
         if member_type in (MembershipType.concessions() + [MembershipType.senior]):
             member_totals[103] += 1
         elif member_type == MembershipType.intermediate:
             member_totals[104] += 1
         else:
             member_totals[102] += 1
     if member.voter():
         member_totals[105] += 1
     return
Exemple #10
0
 def get_dd_payment_plan(payment_method, member, upgrade):
     if payment_method == PaymentMethod.dd:
         plus = upgrade or member.status == MemberStatus.plus
         member_type = member.member_type_at_renewal()
         if member.status == MemberStatus.life:
             return None
         new_member = member.is_recent_new() or member.is_recent_resume()
         if member_type == MembershipType.junior:
             if new_member:
                 return EmandatePaymentPlan.Junior_Dons_new
             else:
                 return EmandatePaymentPlan.Junior_Dons_renewal
         elif member_type in MembershipType.concessions(all=True):
             return EmandatePaymentPlan.Dons_Trust_Plus_Concession if plus else EmandatePaymentPlan.Concession
         elif member_type == MembershipType.standard:
             return EmandatePaymentPlan.Dons_Trust_Plus_Adult if plus else EmandatePaymentPlan.Adult
     else:
         return None
Exemple #11
0
def update_member_details(member, details):
    member.title = Title(details['title']) if details['title'] > 0 else None
    member.first_name = details['first_name']
    member.last_name = details['last_name']
    member.sex = Sex(details['sex']) if details['sex'] > 0 else None
    member.birth_date = details['birth_date']
    member.home_phone = details['home_phone']
    member.mobile_phone = details['mobile_phone']
    member.email = details['email']
    member.comms = CommsType(details['comms'])
    if 'comms_status' in details:
        member.comms_status = CommsStatus(details['comms_status'])
    member.external_access = ExternalAccess(details['external_access'])
    member.address.line_1 = details['line_1']
    member.address.line_2 = details['line_2']
    member.address.line_3 = details['line_3']
    member.address.city = details['city']
    member.address.state = details['state']
    member.address.post_code = details['post_code']
    member.address.county = details['county']
    member.address.country = details['country']
    member.address.region = get_region(details['country'], details['post_code'])

    if 'fan_id' in details and len(details['fan_id']) > 0:
        member.season_ticket_id = to_int(details['fan_id'])
    if 'member_type' in details and details['member_type']:
        member.member_type = MembershipType(details['member_type'])

    role = UserRole.from_value(details['access'])
    if member.user:
        member.user.role = role
    elif role != UserRole.none:
        member.user = get_new_user(role)

    if member.member_type == MembershipType.junior:
        if not member.junior:
            member.junior = get_junior()
        member.junior.email = details['jd_mail']
        member.junior.gift = JuniorGift(details['jd_gift']) if details['jd_gift'] and details['jd_gift'] > 0 else None
        if 'parental_consent' in details:
            member.junior.parental_consent = details['parental_consent']
Exemple #12
0
 def volatile_concession(self):
     return self.member_type in MembershipType.volatile_concessions()
Exemple #13
0
class MemberDetailsForm(FlaskForm):
    full_name = StringField(label='Full Name')
    return_url = HiddenField(label='Return URL')
    member_number = HiddenField(label='Member Number')
    dt_number = StringField(label='Id')
    status = MySelectField(label='Status',
                           choices=MemberStatus.choices(),
                           coerce=MemberStatus.coerce)
    type = MySelectField(label='Type',
                         choices=MembershipType.choices(),
                         coerce=MembershipType.coerce)
    start_date = DateField(label='Start')
    end_date = DateField(label='End')
    birth_date = DateField(label='DoB', validators=[Optional()])
    age = HiddenField(label='Age')
    last_updated = StringField(label='Updated')
    access = MySelectField(label='Access',
                           choices=UserRole.choices(blank=False, ),
                           coerce=UserRole.coerce)
    fan_id = StringField(label='AFCW Fan ID')
    external_access = MySelectField(label='External access',
                                    choices=ExternalAccess.choices(),
                                    coerce=ExternalAccess.coerce)
    payment_method = MySelectField(label='Pay method',
                                   choices=PaymentMethod.choices(blank=True),
                                   coerce=PaymentMethod.coerce)
    title = MySelectField(label='Title',
                          choices=Title.choices(blank=True),
                          coerce=Title.coerce)
    first_name = StringField(label='First', validators=[InputRequired()])
    last_name = StringField(label='Last', validators=[InputRequired()])
    sex = MySelectField(label='Sex',
                        choices=Sex.choices(blank=True),
                        coerce=int)

    line1 = StringField(label='Address line 1')
    line2 = StringField(label='Address line 2')
    line3 = StringField(label='Address line 3')
    city = StringField(label='City')
    state = MySelectField(label='State',
                          choices=state_choices(blank=True),
                          coerce=int)
    post_code = StringField(label='Post Code')
    county = MySelectField(label='County',
                           choices=county_choices(blank=True),
                           coerce=int)
    country = MySelectField(label='Country',
                            choices=country_choices(),
                            coerce=int)

    home_phone = StringField(label='Home Phone')
    mobile_phone = StringField(label='Mobile')
    email = StringField(
        label='Email ',
        validators=[Optional(), Email("Invalid email address")])
    comms = MySelectField(label='Comms ',
                          choices=CommsType.choices(),
                          coerce=CommsType.coerce)
    comms_status = MySelectField(label='Status ',
                                 choices=CommsStatus.choices(),
                                 coerce=CommsStatus.coerce)

    submit = SubmitField(label='Save')

    payment_list = FieldList(FormField(PaymentItemForm))
    action_list = FieldList(FormField(ActionItemForm))
    comment_list = FieldList(FormField(CommentItemForm))

    jd_email = StringField(
        label='JD Email ',
        validators=[Optional(), Email("Invalid email address")])
    jd_gift = MySelectField(label='JD Gift',
                            choices=JuniorGift.choices(blank=True),
                            coerce=JuniorGift.coerce)

    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 validate(self):
        result = True
        new_member = int(self.member_number.data) == 0
        if not super(MemberDetailsForm, self).validate():
            return False
        if new_member:
            name = self.first_name.data + ' ' + self.last_name.data
            existing = get_members_by_name(name)
            if len(existing) > 0:
                self.first_name.errors.append('{} is already member {}'.format(
                    name, existing[0].dt_number()))
                result = False
        return result

    def save_member(self, member_number):
        member_details = {
            'title': self.title.data,
            'first_name': self.first_name.data.strip(),
            'last_name': self.last_name.data.strip(),
            'sex': self.sex.data,
            'member_type': self.type.data,
            'status': self.status.data,
            'start_date': self.start_date.data,
            'end_date': self.end_date.data,
            'birth_date': self.birth_date.data,
            'access': self.access.data,
            'external_access': self.external_access.data,
            'fan_id': self.fan_id.data,
            'payment_method': self.payment_method.data,
            'home_phone': self.home_phone.data.strip(),
            'mobile_phone': self.mobile_phone.data.strip(),
            'email': self.email.data.strip(),
            'comms': self.comms.data,
            'comms_status': self.comms_status.data,
            'line_1': self.line1.data.strip(),
            'line_2': self.line2.data.strip(),
            'line_3': self.line3.data.strip(),
            'city': self.city.data.strip(),
            'state': get_state(self.state.data),
            'post_code': self.post_code.data.strip(),
            'county': get_county(self.county.data),
            'country': get_country(self.country.data),
            'payments': [],
            'actions': [],
            'comments': []
        }
        if self.type.data == MembershipType.junior.value:
            member_details['jd_mail'] = self.jd_email.data.strip()
            member_details['jd_gift'] = self.jd_gift.data

        for payment in self.payment_list.data:
            if payment['amount']:
                member_details['payments'].append(payment)

        for action in self.action_list.data:
            if action['action'] > 0:
                member_details['actions'].append(action)

        for comment in self.comment_list.data:
            if comment['comment']:
                member_details['comments'].append(comment)

        return save_member_details(member_number, member_details)
Exemple #14
0
 def renewal_notes(self):
     age = self.age_at_renewal(default=True)
     new_member = self.is_recent_new()
     recent_resume = self.is_recent_resume()
     renewal_dues = '£' + str(self.dues())
     renewal_cost = "The renewal cost is {}. ".format(renewal_dues) if not (
         new_member or recent_resume) else ''
     upgrade_dues = '£' + str(self.upgrade_dues() if (
         new_member or recent_resume) else self.dues() +
                              self.upgrade_dues())
     if not self.is_pending_upgrade():
         upgrade_para = "You may upgrade to Dons Trust Plus membership at a total cost of {}.".format(
             upgrade_dues) if self.status != MemberStatus.plus else ''
     else:
         upgrade_para = 'You have chosen to upgrade to Dons Trust Plus membership'
     member_type = self.member_type_at_renewal()
     life_member = self.status == MemberStatus.life
     member_type_switch = member_type != self.member_type and not life_member
     junior = member_type == MembershipType.junior
     notes = []
     if life_member:
         notes = [
             "As you are a life member, there is no payment required. " \
             "We will send your new membership card in due course.", ]
     else:
         if member_type == MembershipType.intermediate:
             if member_type_switch:
                 notes = [
                     "As you have passed your 18th birthday, your membership will change to Young Adult (18-21)", \
                     "{}{}".format(renewal_cost, upgrade_para)]
             else:
                 notes = ["{}{}".format(renewal_cost, upgrade_para)]
         elif junior:
             notes = [
                 "{}".format(renewal_cost),
             ]
         if member_type == MembershipType.senior:
             if member_type_switch:
                 notes = [
                     "As you have passed your 65th birthday, your membership will change to Senior (65+)", \
                     "{}{}".format(renewal_cost, upgrade_para)]
             else:
                 notes = [
                     "{}{}".format(renewal_cost, upgrade_para),
                 ]
         elif member_type in MembershipType.concessions():
             notes = [
                 "According to our records, you currently have a concessionary membership ({})."
                 .format(member_type.name),
                 "{}{}".format(renewal_cost, upgrade_para),
                 "**If your circumstances have changed please choose the appropriate membership type."
             ]
         else:
             if member_type == MembershipType.standard:
                 if member_type_switch:
                     notes = [
                         "As you have passed your 21st birthday, you membership will change to Adult (22+)", \
                         "{}{}".format(renewal_cost, upgrade_para)]
                 else:
                     notes = [
                         "{}{}".format(renewal_cost, upgrade_para),
                     ]
     if self.last_payment_method == PaymentMethod.dd and not (
             new_member or recent_resume):
         up = "Unless you wish to upgrade to Dons Trust Plus, you need take no action about payment." \
             if not junior and self.status != MemberStatus.plus else ''
         notes = [
             "According to our records you currently pay by direct debit. "
             + up,
             "Provided the payment is taken successfully, your membership will be automatically updated.",
         ] + notes
     if new_member and not life_member:
         notes = [
                     "As you joined relatively late during the membership year we will automatically extend " \
                     "your membership until August 2022.", ] + notes
     if recent_resume and not life_member:
         notes = [
                     "As you resumed a lapsed membership recently we will automatically extend " \
                     "your membership until August 2022.", ] + notes
     return notes
Exemple #15
0
 def is_adult(self):
     return self.member_type in MembershipType.adult()
Exemple #16
0
class QueryForm(FlaskForm):
    months = [(m, calendar.month_name[m]) for m in range(1, 13)]
    number = MyStringField(label='number', db_map='Member.number')
    last_updated = MyStringField(label='last updated',
                                 db_map='Member.last_updated',
                                 validators=[validate_date_format])
    status = MySelectField(label='status',
                           choices=[],
                           coerce=MemberStatus.coerce,
                           db_map='Member.status')
    member_type = MySelectField(label='member type',
                                choices=MembershipType.choices(extra=[
                                    (99, 'adult (!=junior)')
                                ],
                                                               blank=True),
                                coerce=MembershipType.coerce,
                                db_map='Member.member_type')
    start_date = MyStringField(label='start date',
                               db_map='Member.start_date',
                               validators=[validate_date_format])
    end_date = MyStringField('end date',
                             db_map='Member.end_date',
                             validators=[validate_date_format])
    birth_date = MyStringField('birth date',
                               db_map='Member.birth_date',
                               validators=[validate_date_format])
    post_code = MyStringField(label='post code', db_map='Address.post_code')
    country = MySelectField(label='country',
                            choices=country_choices(
                                blank=True,
                                extra=[(9999, 'overseas (!=United Kingdom)')]),
                            coerce=int,
                            db_map='Address.Country.id')
    payment_type = MySelectField(label='payment type',
                                 choices=PaymentType.choices(blank=True),
                                 coerce=PaymentMethod.coerce,
                                 db_map='Member.Payment.type')
    payment_method = MySelectField(label='payment method',
                                   choices=PaymentMethod.choices(blank=True),
                                   coerce=PaymentMethod.coerce,
                                   db_map='Member.last_payment_method')
    payment_date = MyStringField(label='payment date',
                                 db_map='Member.Payment.date',
                                 validators=[validate_date_format])
    payment_comment = MyStringField(label='payment comment',
                                    db_map='Payment.comment')
    renewal_activated = MyStringField(label='renewal activated',
                                      db_map='Member.renewal_activated()')
    comms = MySelectField(label='comms',
                          choices=CommsType.choices(blank=True),
                          coerce=CommsType.coerce,
                          db_map='Member.comms')
    comms_status = MySelectField(label='comms status',
                                 choices=CommsStatus.choices(blank=True),
                                 coerce=CommsType.coerce,
                                 db_map='Member.comms_status')
    birth_month = MySelectField(label='birth month',
                                choices=[(0, '')] + months,
                                coerce=int,
                                db_map='Member.birth_date.birth_month()')
    age = MyStringField(label='age', db_map='Member.birth_date.age()')
    current_action = MySelectField(label='current action',
                                   choices=MemberAction.choices(blank=True),
                                   coerce=MemberAction.coerce,
                                   db_map='Action.action')
    action_status = MySelectField(label='action status',
                                  choices=ActionStatus.choices(blank=True),
                                  coerce=ActionStatus.coerce,
                                  db_map='Action.status')
    action_date = MyStringField(label='action date',
                                db_map='Action.date',
                                validators=[validate_date_format])
    action_comment = MyStringField(label='action comment',
                                   db_map='Action.comment')
    comment_date = MyStringField(label='comment date',
                                 db_map='Comment.date',
                                 validators=[validate_date_format])
    comment = MyStringField(label='comment', db_map='Comment.comment')

    first_name = MyStringField(label='first name', db_map='Member.first_name')
    last_name = MyStringField(label='last name', db_map='Member.last_name')
    email = MyStringField(label='email', db_map='Member.email')
    fan_id = MyStringField(label='fan id', db_map='Member.season_ticket_id')

    query_clauses = HiddenField(label='query')
    display_fields = MultiCheckboxField(label='fields to extract ...',
                                        choices=list(
                                            enumerate(extract_fields_map)))
    submit = SubmitField(label='Submit')

    def query_fields(self):
        return [
            self.number, self.last_updated, self.status, self.member_type,
            self.start_date, self.end_date, self.birth_date, self.comms,
            self.comms_status, self.birth_month, self.age, self.current_action,
            self.action_date, self.action_status, self.action_comment,
            self.comment_date, self.comment, self.payment_type,
            self.payment_method, self.payment_date, self.payment_comment,
            self.first_name, self.last_name, self.email, self.post_code,
            self.country, self.renewal_activated, self.fan_id
        ]

    def set_status_choices(self):
        self.status.choices = status_choices()

    def find_members(self):
        query_clauses = select_fields_to_query(self.query_fields(), 'Member')
        return query_clauses

    def get_updates(self):
        updates = select_fields_to_update(self.query_fields(), 'Member')
Exemple #17
0
class MemberEditForm(FlaskForm):
    form_type = HiddenField(label='Form Type')
    last_updated = StringField(label='Last Update')
    full_name = StringField(label='Full Name')
    return_url = HiddenField(label='Return URL')
    member_number = HiddenField(label='Member Number')
    recent_new = HiddenField(label='Recent new')
    recent_resume = HiddenField(label='Recent resume')
    payment_required = HiddenField(label='payment required')
    current_payment_method = HiddenField(label='current payment method')
    dt_number = StringField(label='Id')

    start_date = StringField(label='Joined')
    birth_date = DateField(label='Date of Birth', validators=[InputRequired()])
    age = HiddenField(label='Age')
    fan_id = StringField(label='AFCW Fan ID')
    title = MySelectField(label='Title',
                          choices=Title.choices(blank=True),
                          coerce=Title.coerce)
    first_name = StringField(label='First', validators=[InputRequired()])
    last_name = StringField(label='Last', validators=[InputRequired()])
    sex = HiddenField(label='Sex')

    line1 = StringField(label='Address line 1')
    line2 = StringField(label='Address line 2')
    line3 = StringField(label='Address line 3')
    city = StringField(label='City')
    state = MySelectField(label='State',
                          choices=state_choices(blank=True),
                          coerce=int)
    post_code = StringField(label='Post Code')
    county = MySelectField(label='County',
                           choices=county_choices(blank=True),
                           coerce=int)
    country = MySelectField(label='Country',
                            choices=country_choices(),
                            coerce=int)

    home_phone = StringField(label='Home Phone')
    mobile_phone = StringField(label='Mobile')
    email = StringField(
        label='Email ',
        validators=[Optional(), Email("Invalid email address")])
    comms = MySelectField(label='Communications preference ',
                          choices=CommsType.choices(),
                          coerce=CommsType.coerce)
    comms_status = MySelectField(label='Status ',
                                 choices=CommsStatus.choices(),
                                 coerce=CommsStatus.coerce)

    jd_email = StringField(
        label='JD Email ',
        validators=[Optional(), Email("Invalid email address")])
    jd_gift = MySelectField(label='JD Gift',
                            choices=JuniorGift.choices(blank=True),
                            coerce=JuniorGift.coerce)

    third_pty_access = BooleanField(
        label='Please indicate whether you wish to receive this information')

    upgrade = BooleanField(
        label='I wish to change my membership to Dons Trust Plus')
    payment_method = RadioField(label='Payment Method',
                                choices=PaymentMethod.renewal_choices(),
                                coerce=PaymentMethod.coerce)
    comment = TextAreaField(
        label='Please add any comments about the renewal here')
    previous_payment_method = HiddenField(label='Last Payment Method')
    notes = HiddenField(label='Notes')

    status = HiddenField(label='Member Status')
    access = HiddenField(label='User Access')
    plus = HiddenField(label='DT plus')
    type = MySelectField(label='Member Type',
                         choices=MembershipType.renewal_choices(),
                         coerce=MembershipType.coerce)

    (parental_consent, gender, gender_other, gender_identify, disability,
     disability_type, disability_type_other, impairment, marital_status,
     ethnicity, ethnicity_other, sexual_orientation, religion, religion_other,
     employment, employment_other) = diversity_fields()

    submit = SubmitField(label='Save')

    def populate_member(self, member_number, return_url, renewal):
        self.return_url.data = return_url
        self.form_type.data = 'renewal' if renewal else 'details'
        member = get_member(member_number)
        address = member.address
        self.member_number.data = str(member.number)
        self.recent_new.data = member.is_recent_new()
        self.recent_resume.data = member.is_recent_resume()
        self.payment_required.data = not (
            member.status == MemberStatus.life) and not (
                member.status == MemberStatus.plus and member.is_recent_new()
                or member.is_recent_resume())
        if member.last_payment_method:
            prev = member.last_payment_method.value
        else:
            prev = member.last_payment()
            if prev and prev.method:
                prev = prev.method.value
            else:
                prev = 0
        self.current_payment_method.data = prev
        self.dt_number.data = member.dt_number()
        self.access.data = member.user.role.value if member.user else 0
        self.status.data = member.status.name
        self.plus.data = ' (Dons Trust Plus)' if member.status == MemberStatus.plus else ''
        self.type.data = member.member_type_at_renewal().value

        self.start_date.data = fmt_date(member.start_date)
        self.birth_date.data = member.birth_date
        self.age.data = str(member.age()) if member.age() is not None else None

        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.last_updated.data = fmt_date(member.last_updated)

        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 0

        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

        if member.member_type_at_renewal() == 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 ''
            self.parental_consent.data = 1 if member.junior.parental_consent else 0
        else:
            self.jd_email = self.jd_gift = None

        self.third_pty_access.data = member.third_pty_access()

        self.payment_method.data = self.current_payment_method.data
        previous = member.previous_renewal_payment()
        self.previous_payment_method.data = previous.value if previous else 0

        self.upgrade.data = member.last_action() and member.last_action(
        ).action == MemberAction.upgrade

        self.notes.data = member.renewal_notes() + member.edit_notes()
        self.notes.data += [
            'This year we are collecting diversity information - please complete this section as well.',
        ]
        self.notes.data += [
            'We are also asking for your AFC Wimbledon Fan ID so please give this if you have one.',
        ]
        DiversityForm.populate_member(self, member_number, return_url, renewal)
        return member.renewal_activated()

    def save_member(self, member_number):
        member_details = {
            'title':
            self.title.data,
            'first_name':
            self.first_name.data.strip(),
            'last_name':
            self.last_name.data.strip(),
            'sex':
            int(self.sex.data),
            'member_type':
            self.type.data,
            'birth_date':
            self.birth_date.data,
            'access':
            int(self.access.data),
            'fan_id':
            self.fan_id.data,
            'home_phone':
            self.home_phone.data.strip(),
            'mobile_phone':
            self.mobile_phone.data.strip(),
            'email':
            self.email.data.strip(),
            'comms':
            self.comms.data,
            'line_1':
            self.line1.data.strip(),
            'line_2':
            self.line2.data.strip(),
            'line_3':
            self.line3.data.strip(),
            'city':
            self.city.data.strip(),
            'state':
            get_state(self.state.data),
            'post_code':
            self.post_code.data.strip(),
            'county':
            get_county(self.county.data),
            'country':
            get_country(self.country.data),
            'external_access':
            self.external_access(None, self.third_pty_access.data),
            'payment_method':
            self.payment_method.data,
            'comment':
            self.comment.data,
            'upgrade':
            self.upgrade.data
        }
        if self.type.data == MembershipType.junior.value:
            member_details['jd_mail'] = self.jd_email.data.strip()
            member_details['jd_gift'] = self.jd_gift.data
            member_details[
                'parental_consent'] = YesNo.yes if self.parental_consent.data else YesNo.no

        # return key info for save message
        member = get_member(member_number)
        payment_method = PaymentMethod.from_value(self.payment_method.data)
        upgrade = self.upgrade.data
        plus = upgrade or member.status == MemberStatus.plus
        member_type = member.long_membership_type(upgrade=upgrade)
        dues = member.base_dues() + (member.upgrade_dues() if plus else 0)
        if member.is_recent_resume() and not upgrade:
            dues = -1
        renewal_payment = self.get_renewal_payment(payment_method, member,
                                                   upgrade)

        member = save_member_contact_details(member_number, member_details,
                                             self.form_type.data == 'renewal',
                                             False)
        member = DiversityForm.save_member(self, member)
        return payment_method, renewal_payment, dues, member_type, member

    def get_renewal_payment(self, payment_method, member, upgrade):
        if payment_method == PaymentMethod.cc:
            return self.renewal_payment(member, upgrade)
        elif payment_method == PaymentMethod.dd and \
                member.last_payment_type() == "pending" and member.last_payment_method != PaymentMethod.dd:
            return self.renewal_payment(member, upgrade)
        else:
            return self.renewal_payment(member, upgrade)

    def renewal_payment(self, member, upgrade):
        member_type = member.member_type_at_renewal()
        if member.status == MemberStatus.life:
            return None
        new_member = member.is_recent_new() or member.is_recent_resume()
        if new_member:
            if member_type == MembershipType.junior:
                return None
            elif member_type in MembershipType.concessions(all=True):
                return RenewalPayment.Dons_Trust_Plus_Concession_upgrade if upgrade else None
            elif member_type == MembershipType.standard:
                return RenewalPayment.Dons_Trust_Plus_Adult_upgrade if upgrade else None
        else:
            plus = upgrade or member.status == MemberStatus.plus
            if member_type == MembershipType.junior:
                return RenewalPayment.Junior_Dons_renewal
            elif member_type in MembershipType.concessions(all=True):
                return RenewalPayment.Dons_Trust_Plus_Concession if plus else RenewalPayment.Concession
            elif member_type == MembershipType.standard:
                return RenewalPayment.Dons_Trust_Plus_Adult if plus else RenewalPayment.Adult

    @staticmethod
    def external_access(afcw, third_pty):
        access = ExternalAccess.none
        if afcw:
            access = ExternalAccess.AFCW
        if third_pty:
            access = ExternalAccess.all
        return access