diff --git a/tailbone_corepos/menus.py b/tailbone_corepos/menus.py index 960c077..09e3b11 100644 --- a/tailbone_corepos/menus.py +++ b/tailbone_corepos/menus.py @@ -48,6 +48,11 @@ def make_corepos_menu(request): 'url': url('corepos.members'), 'perm': 'corepos.members.list', }, + { + 'title': "Suspensions", + 'url': url('corepos.suspensions'), + 'perm': 'corepos.suspensions.list', + }, { 'title': "Member Types", 'url': url('corepos.member_types'), @@ -58,6 +63,11 @@ def make_corepos_menu(request): 'url': url('corepos.employees'), 'perm': 'corepos.employees.list', }, + { + 'title': "Users", + 'url': url('corepos.users'), + 'perm': 'corepos.users.list', + }, ], }, { diff --git a/tailbone_corepos/views/corepos/__init__.py b/tailbone_corepos/views/corepos/__init__.py index a145371..4856bfa 100644 --- a/tailbone_corepos/views/corepos/__init__.py +++ b/tailbone_corepos/views/corepos/__init__.py @@ -30,6 +30,7 @@ from .master import CoreOfficeMasterView def includeme(config): config.include('tailbone_corepos.views.corepos.parameters') config.include('tailbone_corepos.views.corepos.tablesyncrules') + config.include('tailbone_corepos.views.corepos.users') config.include('tailbone_corepos.views.corepos.stores') config.include('tailbone_corepos.views.corepos.departments') config.include('tailbone_corepos.views.corepos.subdepartments') diff --git a/tailbone_corepos/views/corepos/customers.py b/tailbone_corepos/views/corepos/customers.py index 297b3b2..fc787f8 100644 --- a/tailbone_corepos/views/corepos/customers.py +++ b/tailbone_corepos/views/corepos/customers.py @@ -33,6 +33,16 @@ from webhelpers2.html import tags from .master import CoreOfficeMasterView +def render_member_info(request, custdata, field): + meminfo = custdata.member_info + if not meminfo: + return + text = str(meminfo) + url = request.route_url('corepos.members.view', + card_number=meminfo.card_number) + return tags.link_to(text, url) + + class CustomerView(CoreOfficeMasterView): """ Base class for customer views. @@ -127,13 +137,7 @@ class CustomerView(CoreOfficeMasterView): return tags.link_to(text, url) def render_member_info(self, custdata, field): - meminfo = custdata.member_info - if not meminfo: - return - text = str(meminfo) - url = self.request.route_url('corepos.members.view', - card_number=meminfo.card_number) - return tags.link_to(text, url) + return render_member_info(self.request, custdata, field) def core_office_object_url(self, office_url, customer): return core_office_customer_account_url(self.rattail_config, @@ -162,5 +166,70 @@ class CustomerView(CoreOfficeMasterView): return data +class SuspensionView(CoreOfficeMasterView): + """ + Master view for legacy customer suspensions. + """ + model_class = corepos.Suspension + model_title = "CORE-POS Suspension" + model_title_plural = "CORE-POS Suspensions" + url_prefix = '/core-pos/suspensions' + route_prefix = 'corepos.suspensions' + + labels = { + 'reason_object': "Reason Code", + } + + grid_columns = [ + 'card_number', + 'type', + 'memtype1', + 'memtype2', + 'suspension_date', + 'reason', + 'mail_flag', + 'discount', + 'charge_limit', + 'reason_object', + ] + + form_fields = [ + 'card_number', + 'member_info', + 'type', + 'memtype1', + 'memtype2', + 'suspension_date', + 'reason', + 'mail_flag', + 'discount', + 'charge_limit', + 'reason_object', + ] + + def configure_grid(self, g): + super(SuspensionView, self).configure_grid(g) + + g.filters['card_number'].default_active = True + g.filters['card_number'].default_verb = 'equal' + + g.set_type('charge_limit', 'currency') + + g.set_sort_defaults('card_number') + + g.set_link('card_number') + + def configure_form(self, f): + super(SuspensionView, self).configure_form(f) + + f.set_renderer('member_info', self.render_member_info) + + f.set_type('charge_limit', 'currency') + + def render_member_info(self, custdata, field): + return render_member_info(self.request, custdata, field) + + def includeme(config): CustomerView.defaults(config) + SuspensionView.defaults(config) diff --git a/tailbone_corepos/views/corepos/members.py b/tailbone_corepos/views/corepos/members.py index aecd529..947e6c9 100644 --- a/tailbone_corepos/views/corepos/members.py +++ b/tailbone_corepos/views/corepos/members.py @@ -88,6 +88,7 @@ class MemberView(CoreOfficeMasterView): 'last_name', 'other_first_name', 'other_last_name', + 'customers', 'street', 'city', 'state', @@ -98,6 +99,7 @@ class MemberView(CoreOfficeMasterView): 'ads_ok', 'dates', 'barcodes', + 'suspension', ] def configure_grid(self, g): @@ -119,10 +121,11 @@ class MemberView(CoreOfficeMasterView): f.set_renderer('barcodes', self.render_barcodes) - f.append('customers') f.set_readonly('customers') f.set_renderer('customers', self.render_customers) + f.set_renderer('suspension', self.render_suspension) + def render_member_dates(self, member, field): if not member.dates: return "" @@ -161,6 +164,16 @@ class MemberView(CoreOfficeMasterView): items.append(HTML.tag('li', c=[link])) return HTML.tag('ul', c=items) + def render_suspension(self, member, field): + suspension = member.suspension + if not suspension: + return + + text = str(suspension) + url = self.request.route_url('corepos.suspensions.view', + card_number=suspension.card_number) + return tags.link_to(text, url) + def core_office_object_url(self, office_url, member): return core_office_customer_account_url(self.rattail_config, member.card_number, diff --git a/tailbone_corepos/views/corepos/users.py b/tailbone_corepos/views/corepos/users.py new file mode 100644 index 0000000..3558d7d --- /dev/null +++ b/tailbone_corepos/views/corepos/users.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2021 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +CORE-POS user views +""" + +from corepos.db.office_op import model as corepos + +from .master import CoreOfficeMasterView + + +class UserView(CoreOfficeMasterView): + """ + Master view for CORE Office Users + """ + model_class = corepos.User + model_key = 'name' + model_title = "CORE-POS User" + url_prefix = '/core-pos/users' + route_prefix = 'corepos.users' + + labels = { + 'uid': "UID", + 'name': "Username", + 'session_id': "Session ID", + 'totp_url': "TOTP URL", + } + + grid_columns = [ + 'uid', + 'name', + 'real_name', + 'email', + ] + + form_fields = [ + 'uid', + 'name', + 'real_name', + 'email', + 'session_id', + 'totp_url', + ] + + def configure_grid(self, g): + super(UserView, self).configure_grid(g) + + if not hasattr(corepos.User, 'email'): + g.remove('email') + + g.set_sort_defaults('name') + + g.set_link('uid') + g.set_link('name') + g.set_link('real_name') + g.set_link('email') + + def configure_form(self, f): + super(UserView, self).configure_form(f) + + if not hasattr(corepos.User, 'email'): + f.remove('email') + + +def includeme(config): + UserView.defaults(config)