Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
UCC
uccportal
Commits
81cc295d
Commit
81cc295d
authored
Feb 26, 2019
by
frekk
Browse files
renewals: update existing member details without creating multiple membership records per year
parent
9e9387fb
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/memberdb/approve.py
View file @
81cc295d
...
@@ -8,110 +8,102 @@ from django.urls import reverse
...
@@ -8,110 +8,102 @@ from django.urls import reverse
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django
import
forms
from
django
import
forms
from
memberdb.models
import
Member
,
Membership
,
get_membership_
type
from
memberdb.models
import
Member
,
Membership
,
get_membership_
choices
from
memberdb.forms
import
MyModelForm
from
memberdb.forms
import
MyModelForm
from
memberdb.views
import
MyUpdateView
from
memberdb.views
import
MyUpdateView
"""
inline admin change list action buttons
see https://medium.com/@hakibenita/how-to-add-custom-action-buttons-to-django-admin-8d266f5b0d41
and have a look at .admin.MembershipAdmin
"""
class
MembershipApprovalForm
(
MyModelForm
):
class
MembershipApprovalForm
(
MyModelForm
):
payment_confirm
=
forms
.
BooleanField
(
label
=
'Confirm payment'
,
required
=
False
)
payment_confirm
=
forms
.
BooleanField
(
label
=
'Confirm payment'
,
class
Meta
:
required
=
False
model
=
Membership
)
fields
=
[
'membership_type'
,
'payment_method'
]
widgets
=
{
class
Meta
:
'membership_type'
:
forms
.
RadioSelect
(),
model
=
Membership
'payment_method'
:
forms
.
RadioSelect
(),
fields
=
[
'membership_type'
,
'payment_method'
]
}
widgets
=
{
'membership_type'
:
forms
.
RadioSelect
(),
"""
'payment_method'
:
forms
.
RadioSelect
(),
Called to validate the data on the form.
}
here we fill out some fields automatically (ie. approver, date paid / approved, etc.)
TODO: deal with account activation/creation, etc.
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""
super
().
__init__
(
*
args
,
**
kwargs
)
def
clean
(
self
):
# get the cleaned data from the form API and do something with it
# override the model membership_type field so we display all the options with prices
data
=
super
().
clean
()
self
.
fields
[
'membership_type'
].
choices
=
get_membership_choices
()
now
=
timezone
.
now
()
#breakpoint()
def
clean
(
self
):
# find a Member matching our current username
"""
approver
=
Member
.
objects
.
filter
(
username__exact
=
self
.
request
.
user
.
username
).
first
()
Called to validate the data on the form.
if
(
approver
==
None
):
here we fill out some fields automatically (ie. approver, date paid / approved, etc.)
self
.
add_error
(
None
,
'Cannot set approver: no Member record with username %s'
%
self
.
request
.
user
.
username
)
TODO: deal with account activation/creation, etc.
data
[
'approver'
]
=
approver
"""
data
[
'approved'
]
=
True
data
=
super
().
clean
()
data
[
'date_approved'
]
=
now
now
=
timezone
.
now
()
approver
=
self
.
request
.
member
if
(
data
[
'payment_confirm'
]
==
True
):
if
(
approver
==
None
):
if
(
data
[
'payment_method'
]
==
''
):
self
.
add_error
(
None
,
'Cannot set approver: no Member record associated with current session. (username %s)'
%
self
.
request
.
user
.
username
)
self
.
add_error
(
'payment_method'
,
'Please select a payment method'
)
data
[
'date_paid'
]
=
now
data
[
'approver'
]
=
approver
else
:
data
[
'approved'
]
=
True
data
[
'date_paid'
]
=
None
data
[
'date_approved'
]
=
now
# make sure "no payment" is recorded for Life Members.
if
(
data
[
'payment_confirm'
]
==
True
):
# XXX this might not actually be the case, since some life members may want to also be financial members (ie. for constitutional voting rights)
if
(
data
[
'payment_method'
]
==
''
):
# and so this is probably more annoying than helpful
self
.
add_error
(
'payment_method'
,
'Please select a payment method'
)
if
(
data
[
'membership_type'
]
==
''
):
data
[
'date_paid'
]
=
now
if
(
data
[
'payment_method'
]
!=
''
):
else
:
self
.
add_error
(
'payment_method'
,
'Life members shall not pay membership fees!'
)
data
[
'date_paid'
]
=
None
data
[
'payment_method'
]
=
''
return
data
return
data
def
save
(
self
,
commit
=
True
):
"""
""" save the data into a Membership object """
do the stuff, approve the things
ms
=
super
().
save
(
commit
=
False
)
"""
def
save
(
self
,
commit
=
True
):
# copy attributes not specified in editable form fields
ms
=
super
().
save
(
commit
=
False
)
ms
.
approver
=
self
.
cleaned_data
[
'approver'
]
ms
.
approved
=
self
.
cleaned_data
[
'approved'
]
# copy attributes not specified in fields
ms
.
date_approved
=
self
.
cleaned_data
[
'date_approved'
]
ms
.
approver
=
self
.
cleaned_data
[
'approver'
]
ms
.
date_paid
=
self
.
cleaned_data
[
'date_paid'
]
ms
.
approved
=
self
.
cleaned_data
[
'approved'
]
ms
.
date_approved
=
self
.
cleaned_data
[
'date_approved'
]
if
(
commit
):
ms
.
date_paid
=
self
.
cleaned_data
[
'date_paid'
]
ms
.
save
()
return
ms
# do something
if
(
commit
):
ms
.
save
()
return
ms
class
MembershipApprovalAdminView
(
MyUpdateView
):
class
MembershipApprovalAdminView
(
MyUpdateView
):
template_name
=
'admin/memberdb/membership_approve.html'
template_name
=
'admin/memberdb/membership_approve.html'
form_class
=
MembershipApprovalForm
form_class
=
MembershipApprovalForm
model
=
Membership
model
=
Membership
pk_url_kwarg
=
'object_id'
pk_url_kwarg
=
'object_id'
# override with the instance of ModelAdmin
# override with the instance of ModelAdmin
admin
=
None
admin
=
None
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
ms
=
self
.
get_object
()
ms
=
self
.
get_object
()
context
=
super
().
get_context_data
(
**
kwargs
)
context
=
super
().
get_context_data
(
**
kwargs
)
context
.
update
(
self
.
admin
.
admin_site
.
each_context
(
self
.
request
))
context
.
update
(
self
.
admin
.
admin_site
.
each_context
(
self
.
request
))
context
.
update
({
context
.
update
({
'opts'
:
self
.
admin
.
model
.
_meta
,
'opts'
:
self
.
admin
.
model
.
_meta
,
'ms'
:
ms
,
'ms'
:
ms
,
'member'
:
ms
.
member
,
'member'
:
ms
.
member
,
'show_member_summary'
:
True
,
'show_member_summary'
:
True
,
})
})
return
context
return
context
"""
"""
called when the approval form is submitted and valid data (according to the form's field types and defined validators) is given
called when the approval form is submitted and valid data (according to the form's field types and defined validators) is given
"""
"""
def
form_valid
(
self
,
form
):
def
form_valid
(
self
,
form
):
ms
=
form
.
save
()
ms
=
form
.
save
()
self
.
admin
.
message_user
(
self
.
request
,
'Approve success'
)
self
.
admin
.
message_user
(
self
.
request
,
'Approve success'
)
url
=
reverse
(
url
=
reverse
(
'admin:memberdb_membership_changelist'
,
'admin:memberdb_membership_changelist'
,
args
=
[],
args
=
[],
current_app
=
self
.
admin
.
admin_site
.
name
,
current_app
=
self
.
admin
.
admin_site
.
name
,
)
)
return
HttpResponseRedirect
(
url
)
return
HttpResponseRedirect
(
url
)
src/memberdb/models.py
View file @
81cc295d
...
@@ -100,13 +100,18 @@ def get_membership_type(member):
...
@@ -100,13 +100,18 @@ def get_membership_type(member):
return
best
return
best
def
make_pending_membership
(
member
):
def
make_pending_membership
(
member
):
# check if this member already has a pending membership
""" creates or updates and returns a pending membership for the given member """
ms
=
Membership
.
objects
.
filter
(
member
=
member
,
approved__exact
=
False
).
first
()
latest
=
member
.
get_last_renewal
()
if
(
ms
is
None
):
if
latest
is
None
or
latest
.
date_submitted
.
year
!=
timezone
.
now
().
year
:
ms
=
Membership
(
member
=
member
,
approved
=
False
)
# create a Membership if none exists already for this year
ms
.
date_submitted
=
timezone
.
now
()
latest
=
Membership
(
member
=
member
)
ms
.
membership_type
=
get_membership_type
(
member
)
latest
.
membership_type
=
get_membership_type
(
member
)
return
ms
# otherwise update the existing membership and mark as pending
latest
.
approved
=
False
latest
.
date_submitted
=
timezone
.
now
()
return
latest
def
make_token
():
def
make_token
():
return
get_random_string
(
128
)
return
get_random_string
(
128
)
...
@@ -162,8 +167,6 @@ class Member (IncAssocMember):
...
@@ -162,8 +167,6 @@ class Member (IncAssocMember):
Note: Privacy laws are a thing, unless people allow it then we cannot provide this info to members.
Note: Privacy laws are a thing, unless people allow it then we cannot provide this info to members.
"""
"""
# data to be entered by user and validated (mostly) manually
# data to be entered by user and validated (mostly) manually
display_name
=
models
.
CharField
(
'Display name'
,
max_length
=
200
)
display_name
=
models
.
CharField
(
'Display name'
,
max_length
=
200
)
username
=
models
.
SlugField
(
'Username'
,
max_length
=
32
,
null
=
True
,
blank
=
True
,
unique
=
False
,
validators
=
[
RegexValidator
(
regex
=
'^[a-z0-9._-]*$'
)])
username
=
models
.
SlugField
(
'Username'
,
max_length
=
32
,
null
=
True
,
blank
=
True
,
unique
=
False
,
validators
=
[
RegexValidator
(
regex
=
'^[a-z0-9._-]*$'
)])
...
@@ -182,6 +185,10 @@ class Member (IncAssocMember):
...
@@ -182,6 +185,10 @@ class Member (IncAssocMember):
has_account
=
models
.
BooleanField
(
'Has AD account'
,
null
=
False
,
editable
=
False
,
default
=
False
)
has_account
=
models
.
BooleanField
(
'Has AD account'
,
null
=
False
,
editable
=
False
,
default
=
False
)
def
get_last_renewal
(
self
):
""" returns the most recently submitted Membership object """
return
self
.
memberships
.
order_by
(
'-date_submitted'
).
first
()
# account info
# account info
def
get_uid
(
self
):
def
get_uid
(
self
):
result
,
uid
=
subprocess
.
getstatusoutput
([
"id"
,
"-u"
,
self
.
username
])
result
,
uid
=
subprocess
.
getstatusoutput
([
"id"
,
"-u"
,
self
.
username
])
...
@@ -210,7 +217,7 @@ class Membership (models.Model):
...
@@ -210,7 +217,7 @@ class Membership (models.Model):
payment_method
=
models
.
CharField
(
'Payment method'
,
max_length
=
10
,
blank
=
True
,
null
=
True
,
choices
=
PAYMENT_METHODS
,
default
=
None
)
payment_method
=
models
.
CharField
(
'Payment method'
,
max_length
=
10
,
blank
=
True
,
null
=
True
,
choices
=
PAYMENT_METHODS
,
default
=
None
)
approved
=
models
.
BooleanField
(
'Membership approved'
,
default
=
False
)
approved
=
models
.
BooleanField
(
'Membership approved'
,
default
=
False
)
approver
=
models
.
ForeignKey
(
Member
,
on_delete
=
models
.
SET_NULL
,
null
=
True
,
blank
=
True
,
related_name
=
'approved_memberships'
)
approver
=
models
.
ForeignKey
(
Member
,
on_delete
=
models
.
SET_NULL
,
null
=
True
,
blank
=
True
,
related_name
=
'approved_memberships'
)
date_submitted
=
models
.
DateTimeField
(
'Date signed up'
)
date_submitted
=
models
.
DateTimeField
(
'Date signed up'
,
default
=
timezone
.
now
)
date_paid
=
models
.
DateTimeField
(
'Date of payment'
,
blank
=
True
,
null
=
True
)
date_paid
=
models
.
DateTimeField
(
'Date of payment'
,
blank
=
True
,
null
=
True
)
date_approved
=
models
.
DateTimeField
(
'Date approved'
,
blank
=
True
,
null
=
True
)
date_approved
=
models
.
DateTimeField
(
'Date approved'
,
blank
=
True
,
null
=
True
)
...
@@ -220,6 +227,9 @@ class Membership (models.Model):
...
@@ -220,6 +227,9 @@ class Membership (models.Model):
def
get_dispense_item
(
self
):
def
get_dispense_item
(
self
):
return
MEMBERSHIP_TYPES
[
self
.
membership_type
][
'dispense'
]
return
MEMBERSHIP_TYPES
[
self
.
membership_type
][
'dispense'
]
def
get_pretty_type
(
self
):
return
MEMBERSHIP_TYPES
[
self
.
membership_type
][
'desc'
]
class
Meta
:
class
Meta
:
verbose_name
=
"Membership renewal record"
verbose_name
=
"Membership renewal record"
ordering
=
[
'approved'
,
'-date_submitted'
]
ordering
=
[
'approved'
,
'-date_submitted'
]
...
...
src/memberdb/register.py
View file @
81cc295d
...
@@ -7,6 +7,7 @@ from django.shortcuts import render
...
@@ -7,6 +7,7 @@ from django.shortcuts import render
from
django.urls
import
reverse
from
django.urls
import
reverse
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.utils.safestring
import
mark_safe
from
django.utils.safestring
import
mark_safe
from
django.utils
import
timezone
from
django.contrib
import
messages
from
django.contrib
import
messages
from
django
import
forms
from
django
import
forms
...
@@ -44,7 +45,7 @@ class RegisterRenewForm(MyModelForm):
...
@@ -44,7 +45,7 @@ class RegisterRenewForm(MyModelForm):
if
(
self
[
'email_address'
].
value
()
!=
self
[
'confirm_email'
].
value
()):
if
(
self
[
'email_address'
].
value
()
!=
self
[
'confirm_email'
].
value
()):
self
.
add_error
(
'email_address'
,
'Email addresses must match.'
)
self
.
add_error
(
'email_address'
,
'Email addresses must match.'
)
if
(
self
[
'email_address'
].
value
().
lower
().
split
(
'@'
)[
1
]
in
[
"ucc.asn.au"
,
"ucc.gu.uwa.edu.au"
]):
if
(
self
[
'email_address'
].
value
().
lower
().
split
(
'@'
)[
1
]
in
[
"ucc.asn.au"
,
"ucc.gu.uwa.edu.au"
]):
self
.
add_error
(
'email_address'
,
'Contact address cannot be an UCC address.'
)
self
.
add_error
(
'email_address'
,
'Contact address cannot be an UCC address.'
)
except
:
except
:
pass
pass
super
().
clean
();
super
().
clean
();
...
@@ -57,8 +58,8 @@ class RegisterRenewForm(MyModelForm):
...
@@ -57,8 +58,8 @@ class RegisterRenewForm(MyModelForm):
# must save otherwise membership creation will fail
# must save otherwise membership creation will fail
m
.
save
()
m
.
save
()
# now create a corresponding Membership (marked as pending / not accepted, mostly default values)
ms
=
make_pending_membership
(
m
)
ms
=
make_pending_membership
(
m
)
ms
.
membership_type
=
self
.
cleaned_data
[
'membership_type'
]
if
(
commit
):
if
(
commit
):
ms
.
save
();
ms
.
save
();
...
@@ -112,13 +113,18 @@ class RegisterView(MyUpdateView):
...
@@ -112,13 +113,18 @@ class RegisterView(MyUpdateView):
template_name
=
'register.html'
template_name
=
'register.html'
form_class
=
RegisterForm
form_class
=
RegisterForm
model
=
Member
model
=
Member
can_create
=
False
"""
def
get_context_data
(
self
,
**
kwargs
):
called when valid form data has been POSTed
""" update view context with current renewal year """
invalid form data simply redisplays the form with validation errors
context
=
super
().
get_context_data
(
**
kwargs
)
"""
context
[
'year'
]
=
timezone
.
now
().
year
return
context
def
form_valid
(
self
,
form
):
def
form_valid
(
self
,
form
):
"""
called when valid form data has been POSTed
invalid form data simply redisplays the form with validation errors
"""
# save the member data and get the Member instance
# save the member data and get the Member instance
m
,
ms
=
form
.
save
()
m
,
ms
=
form
.
save
()
messages
.
success
(
self
.
request
,
'Your registration has been submitted.'
)
messages
.
success
(
self
.
request
,
'Your registration has been submitted.'
)
...
@@ -139,29 +145,37 @@ def thanks_view(request, member, ms):
...
@@ -139,29 +145,37 @@ def thanks_view(request, member, ms):
}
}
return
render
(
request
,
'thanks.html'
,
context
)
return
render
(
request
,
'thanks.html'
,
context
)
class
RenewView
(
LoginRequiredMixin
,
MyUpda
teView
):
class
RenewView
(
LoginRequiredMixin
,
Regis
te
r
View
):
template_name
=
'renew.html'
template_name
=
'renew.html'
form_class
=
RenewForm
form_class
=
RenewForm
model
=
Member
model
=
Member
def
get_object
(
self
):
def
get_object
(
self
):
""" try to get a pending renewal for this year (to edit & resubmit) otherwise create a new one """
u
=
self
.
request
.
user
u
=
self
.
request
.
user
m
=
self
.
request
.
member
obj
=
Member
.
objects
.
filter
(
username__exact
=
u
.
username
).
first
()
if
m
is
None
:
if
(
obj
is
None
):
# this member is not in the DB yet - make a new Member object and prefill some data
# make a new Member object and prefill some data
m
=
Member
(
username
=
u
.
username
)
obj
=
Member
(
username
=
u
.
username
)
m
.
first_name
=
u
.
first_name
obj
.
first_name
=
u
.
first_name
m
.
last_name
=
u
.
last_name
obj
.
last_name
=
u
.
last_name
m
.
email_address
=
u
.
email
obj
.
email_address
=
u
.
email
m
.
login_token
=
None
# renewing members won't need this, make sure it is null for security
obj
.
login_token
=
None
# renewing members won't need this
return
m
return
obj
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
(
**
kwargs
)
context
=
super
().
get_context_data
(
**
kwargs
)
context
.
update
({
last_renewal
=
self
.
object
.
get_last_renewal
()
'is_new'
:
Member
.
objects
.
filter
(
username__exact
=
self
.
request
.
user
.
username
).
count
()
==
0
,
})
# renew.html says whether a record exists in the DB or not
context
[
'is_new'
]
=
self
.
request
.
member
is
None
# let the template check if user has already renewed this year so it displays a warning
if
last_renewal
is
not
None
:
context
[
'last_renewal'
]
=
last_renewal
.
date_submitted
.
year
context
[
'memberships'
]
=
[
last_renewal
]
return
context
return
context
def
form_valid
(
self
,
form
):
def
form_valid
(
self
,
form
):
...
...
src/memberdb/views.py
View file @
81cc295d
...
@@ -108,24 +108,13 @@ class MemberHomeView(MemberAccessMixin, MyUpdateView):
...
@@ -108,24 +108,13 @@ class MemberHomeView(MemberAccessMixin, MyUpdateView):
def
get_object
(
self
):
def
get_object
(
self
):
return
self
.
request
.
member
return
self
.
request
.
member
def
get_membership_context
(
self
,
ms
):
""" gets the per-membership-record context data """
return
{
'id'
:
ms
.
id
,
'type'
:
MEMBERSHIP_TYPES
[
ms
.
membership_type
][
'desc'
],
'submitted'
:
ms
.
date_submitted
.
strftime
(
'%Y-%m-%d %H:%M'
),
'paid'
:
ms
.
date_paid
.
strftime
(
'%Y-%m-%d %H:%M'
)
if
ms
.
date_paid
is
not
None
else
None
,
'approved'
:
ms
.
date_approved
.
strftime
(
'%Y-%m-%d %H:%M'
)
if
ms
.
approved
else
None
,
'is_approved'
:
ms
.
approved
,
}
def
get_context_data
(
self
):
def
get_context_data
(
self
):
d
=
super
().
get_context_data
()
d
=
super
().
get_context_data
()
m
=
self
.
get_object
()
m
=
self
.
get_object
()
if
m
is
not
None
:
if
m
is
not
None
:
# get a list of all the membership records associated with this member
# get a list of all the membership records associated with this member
ms_list
=
[
self
.
get_membership_context
(
ms
)
for
ms
in
m
.
memberships
.
all
()
]
ms_list
=
m
.
memberships
.
all
()
d
.
update
({
d
.
update
({
'memberships'
:
ms_list
,
'memberships'
:
ms_list
,
})
})
...
...
src/squarepay/dispense.py.orig
deleted
100644 → 0
View file @
9e9387fb
"""
this file contains utilities for wrapping the opendispense2 CLI utility `dispense`
It is essentially a hack to avoid having to write an actual dispense client here.
"""
import subprocess
from subprocess import CalledProcessError, TimeoutExpired
from django.conf import settings
from .payments import log
DISPENSE_BIN = getattr(settings, 'DISPENSE_BIN', None)
if DISPENSE_BIN is None:
log.warning("DISPENSE_BIN is not defined! Lookups for prices will fallback to weird numbers (for testing)!")
def run_dispense(*args):
<<<<<<< HEAD
if DISPENSE_BIN is None:
return None
cmd = [DISPENSE_BIN] + args
log.info("run_dispense: " + cmd)
try:
# get a string containing the output of the program
res = subprocess.check_output(cmd, timeout=4, universal_newlines=True)
except CalledProcessError as e:
log.warning("dispense returned error code %d, output: '%s'" % (e.returncode, e.output))
return None
except TimeoutExpired as e:
log.error(e)
return None
return res
def get_item_price(itemid):
""" gets the price of the given dispense item in cents """
if (itemid is None or itemid == ""):
return None
if DISPENSE_BIN is None:
return 2223
out = run_dispense('iteminfo', itemid)
if out is None:
return None
s = out.split() # get something like ['pseudo:7', '25.00', 'membership', '(non-student', 'and', 'non-guild)']
if (s[0] != itemid):
log.warning("get_item_price: got result for incorrect item: %s" + s)
return None
else:
# return the price as a number of cents
return int(float(s[0]) * 100)
def set_dispense_flag(user, flag, reason):
if DISPENSE_BIN is None:
log.warning("DISPENSE_BIN is not defined, user will not be disabled")
return False
cmd = [DISPENSE_BIN] + args
out = run_dispense('user', 'type', user, flag, reason)
s = out.split()
if s[2] != "updated":
# user was not updated
log.warning("set_dispense_flag: user was not updated with error: " + out)
return False;
return True;
=======
if DISPENSE_BIN is None:
return None
cmd = (DISPENSE_BIN, ) + args
log.info("run_dispense: " + str(cmd))
try:
# get a string containing the output of the program
res = subprocess.check_output(cmd, timeout=4, universal_newlines=True)
except CalledProcessError as e:
log.warning("dispense returned error code %d, output: '%s'" % (e.returncode, e.output))
return None
except TimeoutExpired as e:
log.error(e)
return None
return res
def get_item_price(itemid):
""" gets the price of the given dispense item in cents """
if (itemid is None or itemid == ""):
return None
if DISPENSE_BIN is None:
return 2223
out = run_dispense('iteminfo', itemid)
if out is None:
return None
s = out.split() # get something like ['pseudo:7', '25.00', 'membership', '(non-student', 'and', 'non-guild)']
if (s[0] != itemid):
log.warning("get_item_price: got result for incorrect item: %s" + s)
return None
else:
# return the price as a number of cents
return int(float(s[1]) * 100)
>>>>>>> origin/frekk-testing
src/templates/home.html
View file @
81cc295d
...
@@ -31,45 +31,7 @@
...
@@ -31,45 +31,7 @@
<h4>
Membership renewals on record
</h4>
<h4>
Membership renewals on record
</h4>
<!-- stuff from the membership record itself -->
<!-- stuff from the membership record itself -->
{% if memberships %}
{% if memberships %}
<table
class=
"membership-details"
>
{% include 'membership_list.html' %}
<tr
class=
"{% cycle 'row1' 'row2' as rcl %}"
>
<th>
Membership type
</th>
<th>
Submitted
</th>
<th>
Paid
</th>
<th>
Approved
</th>
<th>
Actions
</th>
</tr>
{% for ms in memberships %}
<tr
class=
"{% cycle rcl %}"
>
<td>
{{ ms.type }}
</td>
<td>
{{ ms.submitted }}
</td>
<td>
{% if ms.paid %}
<img
src=
"{% static 'admin/img/icon-yes.svg' %}"
alt=
"yes"
>
{{ ms.paid }}
{% else %}
<img
src=
"{% static 'admin/img/icon-no.svg' %}"
alt=
"no"
>
Not paid yet
{% endif %}
</td>
<td>
{% if ms.approved and ms.is_approved %}
<img
src=
"{% static 'admin/img/icon-yes.svg' %}"
alt=
"yes"
>
{{ ms.approved }}
{% elif ms.approved and not ms.is_approved %}
<img
src=
"{% static 'admin/img/icon-no.svg' %}"
alt=
"no"
>
Rejected: {{ ms.approved }}
{% else %}
<img
src=
"{% static 'admin/img/icon-unknown.svg' %}"
alt=
"?"
>
Not approved yet
{% endif %}
</td>
<td>
<!-- membership actions -->
{% if not ms.paid %}
<a
class=
"button"
href=
"{% url 'squarepay:pay_membership' ms.id %}"
>
Pay now
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% else %}
{% else %}
No membership renewal records for your account exist yet. Please
<a
href=
"{% url 'memberdb:renew' %}"
>
renew your membership
</a>
to get started.
No membership renewal records for your account exist yet. Please
<a
href=
"{% url 'memberdb:renew' %}"
>
renew your membership
</a>
to get started.
{% endif %}
{% endif %}
...
...
src/templates/membership_list.html
0 → 100644
View file @
81cc295d
{% load static %}
<table
class=
"membership-details"
>
<tr
class=
"{% cycle 'row1' 'row2' as rcl %}"
>
<th>
Membership type
</th>
<th>
Submitted / Updated
</th>
<th>
Paid
</th>
<th>
Approved
</th>
<th>
Actions
</th>
</tr>
{% for ms in memberships %}
<tr
class=
"{% cycle rcl %}"
>
<td>
{{ ms.get_pretty_type }}