diff --git a/tailbone_corepos/menus.py b/tailbone_corepos/menus.py index b55931e..8c0b11f 100644 --- a/tailbone_corepos/menus.py +++ b/tailbone_corepos/menus.py @@ -167,6 +167,11 @@ def make_corepos_menu(request): 'title': "Transactions", 'type': 'menu', 'items': [ + { + 'title': "Stock Purchases", + 'route': 'corepos.stock_purchases', + 'perm': 'corepos.stock_purchases.list', + }, { 'title': "Tax Rates", 'route': 'corepos.taxrates', diff --git a/tailbone_corepos/views/corepos/__init__.py b/tailbone_corepos/views/corepos/__init__.py index 7cbf0d9..37d9bae 100644 --- a/tailbone_corepos/views/corepos/__init__.py +++ b/tailbone_corepos/views/corepos/__init__.py @@ -48,6 +48,7 @@ def defaults(config, **kwargs): config.include(mod('tailbone_corepos.views.corepos.customers')) config.include(mod('tailbone_corepos.views.corepos.employees')) config.include(mod('tailbone_corepos.views.corepos.coupons')) + config.include(mod('tailbone_corepos.views.corepos.stockpurchases')) config.include(mod('tailbone_corepos.views.corepos.taxrates')) config.include(mod('tailbone_corepos.views.corepos.transactions')) config.include(mod('tailbone_corepos.views.corepos.batches')) diff --git a/tailbone_corepos/views/corepos/master.py b/tailbone_corepos/views/corepos/master.py index 1e7aaa5..a524fec 100644 --- a/tailbone_corepos/views/corepos/master.py +++ b/tailbone_corepos/views/corepos/master.py @@ -32,7 +32,8 @@ from rattail_corepos.config import core_office_url from webhelpers2.html import tags from tailbone.views import MasterView -from tailbone_corepos.db import CoreOfficeSession, ExtraCoreOfficeSessions +from tailbone_corepos.db import (CoreOfficeSession, ExtraCoreOfficeSessions, + CoreTransSession) class CoreMasterView(MasterView): @@ -55,6 +56,16 @@ class CoreMasterView(MasterView): value = app.localtime(value) return str(value.date()) + def render_linked_corepos_card_number(self, obj, field): + card_number = getattr(obj, field) + if not card_number: + return + + text = str(card_number) + url = self.request.route_url('corepos.members.view', + card_number=card_number) + return tags.link_to(text, url) + def render_corepos_store(self, obj, field): store = getattr(obj, field) if not store: @@ -71,6 +82,16 @@ class CoreMasterView(MasterView): url = self.request.route_url('corepos.departments.view', number=department.number) return tags.link_to(text, url) + def render_linked_corepos_department_number(self, obj, field): + department_number = getattr(obj, field) + if not department_number: + return + + text = str(department_number) + url = self.request.route_url('corepos.departments.view', + number=department_number) + return tags.link_to(text, url) + def render_corepos_vendor(self, obj, field): vendor = getattr(obj, field) if not vendor: @@ -151,3 +172,13 @@ class CoreOfficeMasterView(CoreMasterView): return CoreSession(bind=self.rattail_config.corepos_engines[dbkey]) return CoreSession() + + +class CoreTransMasterView(CoreMasterView): + """ + Master base class for CORE Office "trans" DB views + """ + + @property + def Session(self): + return CoreTransSession diff --git a/tailbone_corepos/views/corepos/members.py b/tailbone_corepos/views/corepos/members.py index 9abe263..3de2684 100644 --- a/tailbone_corepos/views/corepos/members.py +++ b/tailbone_corepos/views/corepos/members.py @@ -24,12 +24,16 @@ CORE-POS member views """ +from sqlalchemy import orm + from corepos.db.office_op import model as corepos +from corepos.db.office_trans import model as coretrans from rattail_corepos.config import core_office_url, core_office_customer_account_url from webhelpers2.html import HTML, tags +from tailbone_corepos.db import CoreTransSession from .master import CoreOfficeMasterView @@ -100,6 +104,23 @@ class MemberView(CoreOfficeMasterView): 'dates', 'barcodes', 'suspension', + 'equity_live_balance', + ] + + has_rows = True + model_row_class = coretrans.StockPurchase + rows_title = "Stock Purchases" + + row_labels = { + 'transaction_id': "Transaction ID", + } + + row_grid_columns = [ + 'datetime', + 'amount', + 'transaction_number', + 'transaction_id', + 'department_number', ] def configure_grid(self, g): @@ -126,6 +147,8 @@ class MemberView(CoreOfficeMasterView): f.set_renderer('suspension', self.render_suspension) + f.set_renderer('equity_live_balance', self.render_equity_live_balance) + def render_member_dates(self, member, field): if not member.dates: return "" @@ -175,6 +198,17 @@ class MemberView(CoreOfficeMasterView): card_number=suspension.card_number) return tags.link_to(text, url) + def render_equity_live_balance(self, member, field): + try: + balance = CoreTransSession.query(coretrans.EquityLiveBalance)\ + .filter(coretrans.EquityLiveBalance.member_number == member.card_number)\ + .one() + except orm.exc.NoResultFound: + return + + app = self.get_rattail_app() + return app.render_currency(balance.payments) + def get_xref_buttons(self, member): url = core_office_url(self.rattail_config) if url: @@ -184,6 +218,26 @@ class MemberView(CoreOfficeMasterView): return [self.make_xref_button(url=url, text="View in CORE Office")] + def get_row_data(self, member): + return CoreTransSession.query(coretrans.StockPurchase)\ + .filter(coretrans.StockPurchase.card_number == member.card_number) + + def get_parent(self, stock_purchase): + return self.Session.get(corepos.MemberInfo, stock_purchase.card_number) + + def configure_row_grid(self, g): + super().configure_row_grid(g) + + g.set_type('amount', 'currency') + + g.set_sort_defaults('datetime', 'desc') + + def row_view_action_url(self, stock_purchase, i): + return self.request.route_url('corepos.stock_purchases.view', + card_number=stock_purchase.card_number, + datetime=stock_purchase.datetime, + transaction_number=stock_purchase.transaction_number) + def defaults(config, **kwargs): base = globals() diff --git a/tailbone_corepos/views/corepos/stockpurchases.py b/tailbone_corepos/views/corepos/stockpurchases.py new file mode 100644 index 0000000..6108196 --- /dev/null +++ b/tailbone_corepos/views/corepos/stockpurchases.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 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 . +# +################################################################################ +""" +Views for CORE-POS Stock Purchases +""" + +from corepos.db.office_trans import model as corepos + +from .master import CoreTransMasterView + + +class StockPurchaseView(CoreTransMasterView): + """ + Master view for tax rates + """ + model_class = corepos.StockPurchase + model_title = "CORE-POS Stock Purchase" + url_prefix = '/core-pos/stock-purchases' + route_prefix = 'corepos.stock_purchases' + + labels = { + 'transaction_id': "Transaction ID", + } + + def configure_grid(self, g): + super().configure_grid(g) + + g.set_type('amount', 'currency') + + g.set_sort_defaults('datetime', 'desc') + + g.set_link('card_number') + g.set_link('transaction_number') + g.set_link('datetime') + + def configure_form(self, f): + super().configure_form(f) + + f.set_renderer('card_number', self.render_linked_corepos_card_number) + + f.set_type('amount', 'currency') + + f.set_renderer('department_number', + self.render_linked_corepos_department_number) + + +def defaults(config, **kwargs): + base = globals() + + StockPurchaseView = kwargs.get('StockPurchaseView', base['StockPurchaseView']) + StockPurchaseView.defaults(config) + + +def includeme(config): + defaults(config)