diff --git a/tailbone/menus.py b/tailbone/menus.py
index 9a0ba066..8aebf043 100644
--- a/tailbone/menus.py
+++ b/tailbone/menus.py
@@ -332,6 +332,12 @@ class MenuHandler(GenericHandler):
'route': 'members',
'perm': 'members.list',
},
+ {
+ 'title': "Membership Types",
+ 'route': 'membership_types',
+ 'perm': 'membership_types.list',
+ },
+ {'type': 'sep'},
{
'title': "Customers",
'route': 'customers',
@@ -342,22 +348,23 @@ class MenuHandler(GenericHandler):
'route': 'customergroups',
'perm': 'customergroups.list',
},
+ {
+ 'title': "Pending Customers",
+ 'route': 'pending_customers',
+ 'perm': 'pending_customers.list',
+ },
+ {'type': 'sep'},
{
'title': "Employees",
'route': 'employees',
'perm': 'employees.list',
},
+ {'type': 'sep'},
{
'title': "All People",
'route': 'people',
'perm': 'people.list',
},
- {'type': 'sep'},
- {
- 'title': "Pending Customers",
- 'route': 'pending_customers',
- 'perm': 'pending_customers.list',
- },
],
}
diff --git a/tailbone/templates/people/view_profile_buefy.mako b/tailbone/templates/people/view_profile_buefy.mako
index 075735cc..f21c021e 100644
--- a/tailbone/templates/people/view_profile_buefy.mako
+++ b/tailbone/templates/people/view_profile_buefy.mako
@@ -551,6 +551,16 @@
{{ member._key }}
+
+
+ {{ member.membership_type_name }}
+
+
+ {{ member.membership_type_name }}
+
+
+
{{ member.active }}
diff --git a/tailbone/views/members.py b/tailbone/views/members.py
index 955a217f..9f96e667 100644
--- a/tailbone/views/members.py
+++ b/tailbone/views/members.py
@@ -27,13 +27,70 @@ Member Views
import sqlalchemy as sa
from rattail.db import model
+from rattail.db.model import MembershipType, Member
from deform import widget as dfwidget
+from webhelpers2.html import tags
from tailbone import grids
from tailbone.views import MasterView
+class MembershipTypeView(MasterView):
+ """
+ Master view for Membership Types
+ """
+ model_class = MembershipType
+ route_prefix = 'membership_types'
+ url_prefix = '/membership-types'
+ has_versions = True
+
+ labels = {
+ 'id': "ID",
+ }
+
+ grid_columns = [
+ 'number',
+ 'name',
+ ]
+
+ has_rows = True
+ model_row_class = Member
+ rows_title = "Members"
+
+ row_grid_columns = [
+ '_member_key_',
+ 'person',
+ 'active',
+ 'equity_current',
+ 'equity_total',
+ 'joined',
+ 'withdrew',
+ ]
+
+ def configure_grid(self, g):
+ super().configure_grid(g)
+
+ g.set_sort_defaults('number')
+
+ g.set_link('number')
+ g.set_link('name')
+
+ def get_row_data(self, memtype):
+ model = self.model
+ return self.Session.query(model.Member)\
+ .filter(model.Member.membership_type == memtype)
+
+ def get_parent(self, member):
+ return member.membership_type
+
+ def configure_row_grid(self, g):
+ super().configure_row_grid(g)
+
+ g.filters['active'].default_active = True
+ g.filters['active'].default_verb = 'is_true'
+
+
class MemberView(MasterView):
"""
Master view for the Member class.
@@ -51,9 +108,7 @@ class MemberView(MasterView):
grid_columns = [
'_member_key_',
'person',
- 'customer',
- 'email',
- 'phone',
+ 'membership_type',
'active',
'equity_current',
'joined',
@@ -66,6 +121,7 @@ class MemberView(MasterView):
'customer',
'default_email',
'default_phone',
+ 'membership_type',
'active',
'equity_current',
'equity_payment_due',
@@ -75,6 +131,7 @@ class MemberView(MasterView):
def configure_grid(self, g):
super(MemberView, self).configure_grid(g)
+ model = self.model
# member key
field = self.get_member_key_field()
@@ -111,6 +168,12 @@ class MemberView(MasterView):
g.set_filter('email', model.MemberEmailAddress.address)
g.set_label('email', "Email Address")
+ # membership_type
+ g.set_joiner('membership_type', lambda q: q.outerjoin(model.MembershipType))
+ g.set_sorter('membership_type', model.MembershipType.name)
+ g.set_filter('membership_type', model.MembershipType.name,
+ label="Membership Type Name")
+
g.set_link('person')
g.set_link('customer')
@@ -174,6 +237,9 @@ class MemberView(MasterView):
if not self.creating and member.phones:
f.set_default('default_phone', member.phones[0].number)
+ # membership_type
+ f.set_renderer('membership_type', self.render_membership_type)
+
if self.creating:
f.remove_fields(
'equity_total',
@@ -190,6 +256,14 @@ class MemberView(MasterView):
if member.phones:
return member.phones[0].number
+ def render_membership_type(self, member, field):
+ memtype = getattr(member, field)
+ if not memtype:
+ return
+ text = str(memtype)
+ url = self.request.route_url('membership_types.view', uuid=memtype.uuid)
+ return tags.link_to(text, url)
+
def configure_get_simple_settings(self):
return [
@@ -204,6 +278,9 @@ class MemberView(MasterView):
def defaults(config, **kwargs):
base = globals()
+ MembershipTypeView = kwargs.get('MembershipTypeView', base['MembershipTypeView'])
+ MembershipTypeView.defaults(config)
+
MemberView = kwargs.get('MemberView', base['MemberView'])
MemberView.defaults(config)
diff --git a/tailbone/views/people.py b/tailbone/views/people.py
index dc75b8aa..89b857f1 100644
--- a/tailbone/views/people.py
+++ b/tailbone/views/people.py
@@ -585,7 +585,7 @@ class PersonView(MasterView):
uuid=member.person_uuid)
key = self.get_member_key_field()
- return {
+ data = {
'uuid': member.uuid,
'_key': getattr(member, key),
'number': member.number,
@@ -602,6 +602,18 @@ class PersonView(MasterView):
'view_profile_url': profile_url,
}
+ membership_type = member.membership_type
+ if membership_type:
+ data.update({
+ 'membership_type_uuid': membership_type.uuid,
+ 'membership_type_number': membership_type.number,
+ 'membership_type_name': membership_type.name,
+ 'view_membership_type_url': self.request.route_url(
+ 'membership_types.view', uuid=membership_type.uuid),
+ })
+
+ return data
+
def get_context_employee(self, employee):
"""
Return a dict of context data for the given employee.