Add views etc. for member equity payments

This commit is contained in:
Lance Edgar 2023-06-18 14:08:36 -05:00
parent aa5e44efb5
commit 58354e7adf
5 changed files with 164 additions and 4 deletions

View file

@ -332,6 +332,11 @@ class MenuHandler(GenericHandler):
'route': 'members', 'route': 'members',
'perm': 'members.list', 'perm': 'members.list',
}, },
{
'title': "Member Equity Payments",
'route': 'member_equity_payments',
'perm': 'member_equity_payments.list',
},
{ {
'title': "Membership Types", 'title': "Membership Types",
'route': 'membership_types', 'route': 'membership_types',

View file

@ -634,6 +634,10 @@
{{ member.withdrew }} {{ member.withdrew }}
</b-field> </b-field>
<b-field horizontal label="Equity Total">
{{ member.equity_total_display }}
</b-field>
</div> </div>
<div class="buttons" style="align-items: start;"> <div class="buttons" style="align-items: start;">
${self.render_member_panel_buttons(member)} ${self.render_member_panel_buttons(member)}

View file

@ -973,6 +973,14 @@ class MasterView(View):
url = self.request.route_url('customers.view', uuid=customer.uuid) url = self.request.route_url('customers.view', uuid=customer.uuid)
return tags.link_to(text, url) return tags.link_to(text, url)
def render_member(self, obj, field):
member = getattr(obj, field)
if not member:
return
text = str(member)
url = self.request.route_url('members.view', uuid=member.uuid)
return tags.link_to(text, url)
def render_email_key(self, obj, field): def render_email_key(self, obj, field):
if hasattr(obj, field): if hasattr(obj, field):
email_key = getattr(obj, field) email_key = getattr(obj, field)

View file

@ -29,12 +29,12 @@ from collections import OrderedDict
import sqlalchemy as sa import sqlalchemy as sa
from rattail.db import model from rattail.db import model
from rattail.db.model import MembershipType, Member from rattail.db.model import MembershipType, Member, MemberEquityPayment
from deform import widget as dfwidget from deform import widget as dfwidget
from webhelpers2.html import tags from webhelpers2.html import tags
from tailbone import grids from tailbone import grids, forms
from tailbone.views import MasterView from tailbone.views import MasterView
@ -107,6 +107,7 @@ class MemberView(MasterView):
touchable = True touchable = True
has_versions = True has_versions = True
configurable = True configurable = True
supports_autocomplete = True
labels = { labels = {
'id': "ID", 'id': "ID",
@ -131,12 +132,40 @@ class MemberView(MasterView):
'default_phone', 'default_phone',
'membership_type', 'membership_type',
'active', 'active',
'equity_total',
'equity_current', 'equity_current',
'equity_payment_due', 'equity_payment_due',
'joined', 'joined',
'withdrew', 'withdrew',
] ]
has_rows = True
model_row_class = MemberEquityPayment
rows_title = "Equity Payments"
row_grid_columns = [
'amount',
'received',
'description',
'transaction_identifier',
]
def should_expose_quickie_search(self):
if self.expose_quickie_search:
return True
app = self.get_rattail_app()
return app.get_people_handler().should_expose_quickie_search()
def get_quickie_perm(self):
return 'people.quickie'
def get_quickie_url(self):
return self.request.route_url('people.quickie')
def get_quickie_placeholder(self):
app = self.get_rattail_app()
return app.get_people_handler().get_quickie_search_placeholder()
def configure_grid(self, g): def configure_grid(self, g):
super(MemberView, self).configure_grid(g) super(MemberView, self).configure_grid(g)
route_prefix = self.get_route_prefix() route_prefix = self.get_route_prefix()
@ -225,14 +254,17 @@ class MemberView(MasterView):
return 'notice' return 'notice'
def configure_form(self, f): def configure_form(self, f):
super(MemberView, self).configure_form(f) super().configure_form(f)
member = f.model_instance member = f.model_instance
# date fields # date fields
f.set_type('joined', 'date_jquery') f.set_type('joined', 'date_jquery')
f.set_type('withdrew', 'date_jquery')
# equity fields
f.set_renderer('equity_total', self.render_equity_total)
f.set_type('equity_payment_due', 'date_jquery') f.set_type('equity_payment_due', 'date_jquery')
f.set_type('equity_last_paid', 'date_jquery') f.set_type('equity_last_paid', 'date_jquery')
f.set_type('withdrew', 'date_jquery')
# person # person
if self.creating or self.editing: if self.creating or self.editing:
@ -289,6 +321,11 @@ class MemberView(MasterView):
'withdrew', 'withdrew',
) )
def render_equity_total(self, member, field):
app = self.get_rattail_app()
total = sum([payment.amount for payment in member.equity_payments])
return app.render_currency(total)
def template_kwargs_view(self, **kwargs): def template_kwargs_view(self, **kwargs):
kwargs = super().template_kwargs_view(**kwargs) kwargs = super().template_kwargs_view(**kwargs)
app = self.get_rattail_app() app = self.get_rattail_app()
@ -323,6 +360,25 @@ class MemberView(MasterView):
url = self.request.route_url('membership_types.view', uuid=memtype.uuid) url = self.request.route_url('membership_types.view', uuid=memtype.uuid)
return tags.link_to(text, url) return tags.link_to(text, url)
def get_row_data(self, member):
model = self.model
return self.Session.query(model.MemberEquityPayment)\
.filter(model.MemberEquityPayment.member == member)
def get_parent(self, payment):
return payment.member
def configure_row_grid(self, g):
super().configure_row_grid(g)
g.set_type('amount', 'currency')
g.set_sort_defaults('received', 'desc')
def row_view_action_url(self, payment, i):
return self.request.route_url('member_equity_payments.view',
uuid=payment.uuid)
def configure_get_simple_settings(self): def configure_get_simple_settings(self):
return [ return [
@ -337,6 +393,87 @@ class MemberView(MasterView):
] ]
class MemberEquityPaymentView(MasterView):
"""
Master view for the MemberEquityPayment class.
"""
model_class = model.MemberEquityPayment
route_prefix = 'member_equity_payments'
url_prefix = '/member-equity-payments'
has_versions = True
grid_columns = [
'member',
'amount',
'received',
'description',
'transaction_identifier',
]
form_fields = [
'member',
'amount',
'received',
'description',
'transaction_identifier',
]
def query(self, session):
query = super().query(session)
model = self.model
query = query.join(model.Member)
return query
def configure_grid(self, g):
super().configure_grid(g)
model = self.model
g.set_joiner('member', lambda q: q.outerjoin(model.Person))
g.set_sorter('member', model.Person.display_name)
g.set_link('member')
g.set_type('amount', 'currency')
g.set_sort_defaults('received', 'desc')
g.set_link('received')
def configure_form(self, f):
super().configure_form(f)
model = self.model
payment = f.model_instance
# member
if self.creating:
f.replace('member', 'member_uuid')
member_display = ""
if self.request.method == 'POST':
if self.request.POST.get('member_uuid'):
member = self.Session.get(model.Member,
self.request.POST['member_uuid'])
if member:
member_display = str(member)
elif self.editing:
member_display = str(payment.member or '')
members_url = self.request.route_url('members.autocomplete')
f.set_widget('member_uuid', forms.widgets.JQueryAutocompleteWidget(
field_display=member_display, service_url=members_url))
f.set_label('member_uuid', "Member")
else:
f.set_readonly('member')
f.set_renderer('member', self.render_member)
# amount
f.set_type('amount', 'currency')
# received
if self.creating:
f.set_type('received', 'date_jquery')
else:
f.set_readonly('received')
def defaults(config, **kwargs): def defaults(config, **kwargs):
base = globals() base = globals()
@ -346,6 +483,9 @@ def defaults(config, **kwargs):
MemberView = kwargs.get('MemberView', base['MemberView']) MemberView = kwargs.get('MemberView', base['MemberView'])
MemberView.defaults(config) MemberView.defaults(config)
MemberEquityPaymentView = kwargs.get('MemberEquityPaymentView', base['MemberEquityPaymentView'])
MemberEquityPaymentView.defaults(config)
def includeme(config): def includeme(config):
defaults(config) defaults(config)

View file

@ -715,12 +715,14 @@ class PersonView(MasterView):
return list(data.values()) return list(data.values())
def get_context_member(self, member): def get_context_member(self, member):
app = self.get_rattail_app()
profile_url = None profile_url = None
if member.person: if member.person:
profile_url = self.request.route_url('people.view_profile', profile_url = self.request.route_url('people.view_profile',
uuid=member.person_uuid) uuid=member.person_uuid)
key = self.get_member_key_field() key = self.get_member_key_field()
equity_total = sum([payment.amount for payment in member.equity_payments])
data = { data = {
'uuid': member.uuid, 'uuid': member.uuid,
'_key': getattr(member, key), '_key': getattr(member, key),
@ -736,6 +738,7 @@ class PersonView(MasterView):
'person_display_name': member.person.display_name if member.person else None, 'person_display_name': member.person.display_name if member.person else None,
'view_url': self.request.route_url('members.view', uuid=member.uuid), 'view_url': self.request.route_url('members.view', uuid=member.uuid),
'view_profile_url': profile_url, 'view_profile_url': profile_url,
'equity_total_display': app.render_currency(equity_total),
} }
membership_type = member.membership_type membership_type = member.membership_type