feat: add basic readonly web views for CORE members, products
also adds canonical web app db sessions for CORE also adds some methods to corepos handler, to get model / make session
This commit is contained in:
parent
b134e340ff
commit
05f428586b
6
docs/api/wutta_corepos.web.db.rst
Normal file
6
docs/api/wutta_corepos.web.db.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wutta_corepos.web.db``
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. automodule:: wutta_corepos.web.db
|
||||||
|
:members:
|
6
docs/api/wutta_corepos.web.rst
Normal file
6
docs/api/wutta_corepos.web.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wutta_corepos.web``
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. automodule:: wutta_corepos.web
|
||||||
|
:members:
|
6
docs/api/wutta_corepos.web.views.corepos.master.rst
Normal file
6
docs/api/wutta_corepos.web.views.corepos.master.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wutta_corepos.web.views.corepos.master``
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. automodule:: wutta_corepos.web.views.corepos.master
|
||||||
|
:members:
|
6
docs/api/wutta_corepos.web.views.corepos.members.rst
Normal file
6
docs/api/wutta_corepos.web.views.corepos.members.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wutta_corepos.web.views.corepos.members``
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
.. automodule:: wutta_corepos.web.views.corepos.members
|
||||||
|
:members:
|
6
docs/api/wutta_corepos.web.views.corepos.products.rst
Normal file
6
docs/api/wutta_corepos.web.views.corepos.products.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wutta_corepos.web.views.corepos.products``
|
||||||
|
============================================
|
||||||
|
|
||||||
|
.. automodule:: wutta_corepos.web.views.corepos.products
|
||||||
|
:members:
|
6
docs/api/wutta_corepos.web.views.corepos.rst
Normal file
6
docs/api/wutta_corepos.web.views.corepos.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wutta_corepos.web.views.corepos``
|
||||||
|
===================================
|
||||||
|
|
||||||
|
.. automodule:: wutta_corepos.web.views.corepos
|
||||||
|
:members:
|
6
docs/api/wutta_corepos.web.views.rst
Normal file
6
docs/api/wutta_corepos.web.views.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wutta_corepos.web.views``
|
||||||
|
===========================
|
||||||
|
|
||||||
|
.. automodule:: wutta_corepos.web.views
|
||||||
|
:members:
|
|
@ -27,6 +27,7 @@ templates_path = ['_templates']
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
intersphinx_mapping = {
|
intersphinx_mapping = {
|
||||||
|
'wuttaweb': ('https://rattailproject.org/docs/wuttaweb/', None),
|
||||||
'wuttjamaican': ('https://rattailproject.org/docs/wuttjamaican/', None),
|
'wuttjamaican': ('https://rattailproject.org/docs/wuttjamaican/', None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ Wutta-COREPOS
|
||||||
This package adds basic integration with `CORE-POS`_, using
|
This package adds basic integration with `CORE-POS`_, using
|
||||||
`pyCOREPOS`_.
|
`pyCOREPOS`_.
|
||||||
|
|
||||||
Its main purpose is to setup DB connections for CORE Office.
|
Its main purpose is to setup DB connections for CORE Office, but it
|
||||||
|
also contains basic readonly web views for some CORE tables.
|
||||||
|
|
||||||
.. _CORE-POS: https://www.core-pos.com/
|
.. _CORE-POS: https://www.core-pos.com/
|
||||||
|
|
||||||
|
@ -26,3 +27,10 @@ Its main purpose is to setup DB connections for CORE Office.
|
||||||
api/wutta_corepos.app
|
api/wutta_corepos.app
|
||||||
api/wutta_corepos.conf
|
api/wutta_corepos.conf
|
||||||
api/wutta_corepos.handler
|
api/wutta_corepos.handler
|
||||||
|
api/wutta_corepos.web
|
||||||
|
api/wutta_corepos.web.db
|
||||||
|
api/wutta_corepos.web.views
|
||||||
|
api/wutta_corepos.web.views.corepos
|
||||||
|
api/wutta_corepos.web.views.corepos.master
|
||||||
|
api/wutta_corepos.web.views.corepos.members
|
||||||
|
api/wutta_corepos.web.views.corepos.products
|
||||||
|
|
|
@ -34,6 +34,7 @@ dependencies = [
|
||||||
|
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
web = ["WuttaWeb"]
|
||||||
docs = ["Sphinx", "furo"]
|
docs = ["Sphinx", "furo"]
|
||||||
tests = ["pytest-cov", "tox"]
|
tests = ["pytest-cov", "tox"]
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
"""
|
"""
|
||||||
CORE-POS Handler
|
CORE-POS Integration Handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from wuttjamaican.app import GenericHandler
|
from wuttjamaican.app import GenericHandler
|
||||||
|
@ -33,6 +33,72 @@ class CoreposHandler(GenericHandler):
|
||||||
:term:`handler`.
|
:term:`handler`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def get_model_office_op(self):
|
||||||
|
"""
|
||||||
|
Returns the :term:`data model` module for CORE Office 'op' DB,
|
||||||
|
i.e. :mod:`pycorepos:corepos.db.office_op.model`.
|
||||||
|
"""
|
||||||
|
from corepos.db.office_op import model
|
||||||
|
|
||||||
|
return model
|
||||||
|
|
||||||
|
def get_model_office_trans(self):
|
||||||
|
"""
|
||||||
|
Returns the :term:`data model` module for CORE Office 'trans'
|
||||||
|
DB, i.e. :mod:`pycorepos:corepos.db.office_trans.model`.
|
||||||
|
"""
|
||||||
|
from corepos.db.office_trans import model
|
||||||
|
|
||||||
|
return model
|
||||||
|
|
||||||
|
def get_model_office_arch(self):
|
||||||
|
"""
|
||||||
|
Returns the :term:`data model` module for CORE Office 'arch'
|
||||||
|
DB, i.e. :mod:`pycorepos:corepos.db.office_arch.model`.
|
||||||
|
"""
|
||||||
|
from corepos.db.office_arch import model
|
||||||
|
|
||||||
|
return model
|
||||||
|
|
||||||
|
def make_session_office_op(self, dbkey='default', **kwargs):
|
||||||
|
"""
|
||||||
|
Make a new :term:`db session` for the CORE Office 'op' DB.
|
||||||
|
|
||||||
|
:returns: Instance of
|
||||||
|
:class:`pycorepos:corepos.db.office_op.Session`.
|
||||||
|
"""
|
||||||
|
from corepos.db.office_op import Session
|
||||||
|
|
||||||
|
if 'bind' not in kwargs:
|
||||||
|
kwargs['bind'] = self.config.core_office_op_engines[dbkey]
|
||||||
|
return Session(**kwargs)
|
||||||
|
|
||||||
|
def make_session_office_trans(self, dbkey='default', **kwargs):
|
||||||
|
"""
|
||||||
|
Make a new :term:`db session` for the CORE Office 'trans' DB.
|
||||||
|
|
||||||
|
:returns: Instance of
|
||||||
|
:class:`pycorepos:corepos.db.office_trans.Session`.
|
||||||
|
"""
|
||||||
|
from corepos.db.office_trans import Session
|
||||||
|
|
||||||
|
if 'bind' not in kwargs:
|
||||||
|
kwargs['bind'] = self.config.core_office_trans_engines[dbkey]
|
||||||
|
return Session(**kwargs)
|
||||||
|
|
||||||
|
def make_session_office_arch(self, dbkey='default', **kwargs):
|
||||||
|
"""
|
||||||
|
Make a new :term:`db session` for the CORE Office 'arch' DB.
|
||||||
|
|
||||||
|
:returns: Instance of
|
||||||
|
:class:`pycorepos:corepos.db.office_arch.Session`.
|
||||||
|
"""
|
||||||
|
from corepos.db.office_arch import Session
|
||||||
|
|
||||||
|
if 'bind' not in kwargs:
|
||||||
|
kwargs['bind'] = self.config.core_office_arch_engines[dbkey]
|
||||||
|
return Session(**kwargs)
|
||||||
|
|
||||||
def get_office_url(self, require=False):
|
def get_office_url(self, require=False):
|
||||||
"""
|
"""
|
||||||
Returns the base URL for the CORE Office web app.
|
Returns the base URL for the CORE Office web app.
|
||||||
|
|
29
src/wutta_corepos/web/__init__.py
Normal file
29
src/wutta_corepos/web/__init__.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
|
# Copyright © 2025 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Wutta-COREPOS -- wuttaweb features
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
config.include('wutta_corepos.web.views')
|
70
src/wutta_corepos/web/db.py
Normal file
70
src/wutta_corepos/web/db.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
|
# Copyright © 2025 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Wutta-COREPOS -- wuttaweb DB sessions
|
||||||
|
|
||||||
|
See :mod:`wuttaweb:wuttaweb.db.sess` for more info on web app sessions
|
||||||
|
in general.
|
||||||
|
|
||||||
|
.. class:: CoreOpSession
|
||||||
|
|
||||||
|
Primary web app :term:`db session` for CORE Office 'op' DB.
|
||||||
|
|
||||||
|
.. class:: CoreTransSession
|
||||||
|
|
||||||
|
Primary web app :term:`db session` for CORE Office 'trans' DB.
|
||||||
|
|
||||||
|
.. class:: CoreArchSession
|
||||||
|
|
||||||
|
Primary web app :term:`db session` for CORE Office 'arch' DB.
|
||||||
|
|
||||||
|
.. class:: ExtraCoreOpSessions
|
||||||
|
|
||||||
|
Dict of secondary CORE Office 'op' DB sessions, if applicable.
|
||||||
|
|
||||||
|
.. class:: ExtraCoreTransSessions
|
||||||
|
|
||||||
|
Dict of secondary CORE Office 'trans' DB sessions, if applicable.
|
||||||
|
|
||||||
|
.. class:: ExtraCoreArchSessions
|
||||||
|
|
||||||
|
Dict of secondary CORE Office 'arch' DB sessions, if applicable.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from sqlalchemy.orm import sessionmaker, scoped_session
|
||||||
|
from zope.sqlalchemy import register
|
||||||
|
|
||||||
|
|
||||||
|
CoreOpSession = scoped_session(sessionmaker())
|
||||||
|
register(CoreOpSession)
|
||||||
|
|
||||||
|
CoreTransSession = scoped_session(sessionmaker())
|
||||||
|
register(CoreTransSession)
|
||||||
|
|
||||||
|
CoreArchSession = scoped_session(sessionmaker())
|
||||||
|
register(CoreArchSession)
|
||||||
|
|
||||||
|
# nb. these start out empty but may be populated on app startup
|
||||||
|
ExtraCoreOpSessions = {}
|
||||||
|
ExtraCoreTransSessions = {}
|
||||||
|
ExtraCoreArchSessions = {}
|
29
src/wutta_corepos/web/views/__init__.py
Normal file
29
src/wutta_corepos/web/views/__init__.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
|
# Copyright © 2025 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Wutta-COREPOS -- wuttaweb views
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
config.include('wutta_corepos.web.views.corepos')
|
32
src/wutta_corepos/web/views/corepos/__init__.py
Normal file
32
src/wutta_corepos/web/views/corepos/__init__.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
|
# Copyright © 2025 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Views for CORE-POS
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .master import CoreOpMasterView
|
||||||
|
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
config.include('wutta_corepos.web.views.corepos.members')
|
||||||
|
config.include('wutta_corepos.web.views.corepos.products')
|
40
src/wutta_corepos/web/views/corepos/master.py
Normal file
40
src/wutta_corepos/web/views/corepos/master.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
|
# Copyright © 2025 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
CORE-POS master view base class
|
||||||
|
"""
|
||||||
|
|
||||||
|
from wuttaweb.views import MasterView
|
||||||
|
|
||||||
|
from wutta_corepos.web.db import CoreOpSession
|
||||||
|
|
||||||
|
|
||||||
|
class CoreOpMasterView(MasterView):
|
||||||
|
"""
|
||||||
|
Base class for master views which use the CORE Office 'op' DB.
|
||||||
|
"""
|
||||||
|
Session = CoreOpSession
|
||||||
|
|
||||||
|
def __init__(self, request, context=None):
|
||||||
|
super().__init__(request, context=context)
|
||||||
|
self.corepos_handler = self.app.get_corepos_handler()
|
117
src/wutta_corepos/web/views/corepos/members.py
Normal file
117
src/wutta_corepos/web/views/corepos/members.py
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
|
# Copyright © 2025 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Views for CORE-POS Members
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy import orm
|
||||||
|
|
||||||
|
from corepos.db.office_op.model import MemberInfo
|
||||||
|
|
||||||
|
from wutta_corepos.web.views.corepos import CoreOpMasterView
|
||||||
|
|
||||||
|
|
||||||
|
class MemberView(CoreOpMasterView):
|
||||||
|
"""
|
||||||
|
Master view for
|
||||||
|
:class:`~pycorepos:corepos.db.office_op.model.MemberInfo`; route
|
||||||
|
prefix is ``corepos_members``.
|
||||||
|
|
||||||
|
Notable URLs provided by this class:
|
||||||
|
|
||||||
|
* ``/corepos/members/``
|
||||||
|
* ``/corepos/members/XXX``
|
||||||
|
"""
|
||||||
|
model_class = MemberInfo
|
||||||
|
model_title = "CORE-POS Member"
|
||||||
|
route_prefix = 'corepos_members'
|
||||||
|
url_prefix = '/corepos/members'
|
||||||
|
|
||||||
|
# nb. this is just for readonly lookup
|
||||||
|
creatable = False
|
||||||
|
editable = False
|
||||||
|
deletable = False
|
||||||
|
|
||||||
|
grid_columns = [
|
||||||
|
'card_number',
|
||||||
|
'first_name',
|
||||||
|
'last_name',
|
||||||
|
'street',
|
||||||
|
'city',
|
||||||
|
'state',
|
||||||
|
'zip',
|
||||||
|
'phone',
|
||||||
|
'email',
|
||||||
|
]
|
||||||
|
|
||||||
|
filter_defaults = {
|
||||||
|
'card_number': {'active': True, 'verb': 'equal'},
|
||||||
|
'first_name': {'active': True, 'verb': 'contains'},
|
||||||
|
'last_name': {'active': True, 'verb': 'contains'},
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_defaults = 'card_number'
|
||||||
|
|
||||||
|
def get_query(self, session=None):
|
||||||
|
""" """
|
||||||
|
query = super().get_query(session=session)
|
||||||
|
|
||||||
|
op_model = self.corepos_handler.get_model_office_op()
|
||||||
|
query = query.outerjoin(op_model.CustomerClassic,
|
||||||
|
sa.and_(
|
||||||
|
op_model.CustomerClassic.card_number == op_model.MemberInfo.card_number,
|
||||||
|
op_model.CustomerClassic.person_number == 1,
|
||||||
|
))\
|
||||||
|
.options(orm.joinedload(op_model.MemberInfo.customers))
|
||||||
|
|
||||||
|
return query
|
||||||
|
|
||||||
|
def configure_grid(self, g):
|
||||||
|
""" """
|
||||||
|
super().configure_grid(g)
|
||||||
|
op_model = self.corepos_handler.get_model_office_op()
|
||||||
|
|
||||||
|
# first_name
|
||||||
|
g.set_renderer('first_name', self.render_customer_attr)
|
||||||
|
g.set_sorter('first_name', op_model.CustomerClassic.first_name)
|
||||||
|
|
||||||
|
# last_name
|
||||||
|
g.set_renderer('last_name', self.render_customer_attr)
|
||||||
|
g.set_sorter('last_name', op_model.CustomerClassic.last_name)
|
||||||
|
|
||||||
|
def render_customer_attr(self, member, key, value):
|
||||||
|
""" """
|
||||||
|
customer = member.customers[0]
|
||||||
|
return getattr(customer, key)
|
||||||
|
|
||||||
|
|
||||||
|
def defaults(config, **kwargs):
|
||||||
|
base = globals()
|
||||||
|
|
||||||
|
MemberView = kwargs.get('MemberView', base['MemberView'])
|
||||||
|
MemberView.defaults(config)
|
||||||
|
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
defaults(config)
|
97
src/wutta_corepos/web/views/corepos/products.py
Normal file
97
src/wutta_corepos/web/views/corepos/products.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
|
# Copyright © 2025 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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.
|
||||||
|
#
|
||||||
|
# Wutta Framework 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
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Views for CORE-POS Products
|
||||||
|
"""
|
||||||
|
|
||||||
|
from corepos.db.office_op.model import Product
|
||||||
|
|
||||||
|
from wutta_corepos.web.views.corepos import CoreOpMasterView
|
||||||
|
|
||||||
|
|
||||||
|
class ProductView(CoreOpMasterView):
|
||||||
|
"""
|
||||||
|
Master view for
|
||||||
|
:class:`~pycorepos:corepos.db.office_op.model.Product`; route
|
||||||
|
prefix is ``corepos_products``.
|
||||||
|
|
||||||
|
Notable URLs provided by this class:
|
||||||
|
|
||||||
|
* ``/corepos/products/``
|
||||||
|
* ``/corepos/products/XXX``
|
||||||
|
"""
|
||||||
|
model_class = Product
|
||||||
|
model_title = "CORE-POS Product"
|
||||||
|
route_prefix = 'corepos_products'
|
||||||
|
url_prefix = '/corepos/products'
|
||||||
|
|
||||||
|
# nb. this is just for readonly lookup
|
||||||
|
creatable = False
|
||||||
|
editable = False
|
||||||
|
deletable = False
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
'upc': "UPC",
|
||||||
|
}
|
||||||
|
|
||||||
|
grid_columns = [
|
||||||
|
'upc',
|
||||||
|
'brand',
|
||||||
|
'description',
|
||||||
|
'size',
|
||||||
|
'department',
|
||||||
|
'vendor',
|
||||||
|
'normal_price',
|
||||||
|
]
|
||||||
|
|
||||||
|
filter_defaults = {
|
||||||
|
'upc': {'active': True, 'verb': 'contains'},
|
||||||
|
'brand': {'active': True, 'verb': 'contains'},
|
||||||
|
'description': {'active': True, 'verb': 'contains'},
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_defaults = 'upc'
|
||||||
|
|
||||||
|
def configure_grid(self, g):
|
||||||
|
""" """
|
||||||
|
super().configure_grid(g)
|
||||||
|
|
||||||
|
# normal_price
|
||||||
|
g.set_renderer('normal_price', 'currency')
|
||||||
|
|
||||||
|
# links
|
||||||
|
g.set_link('upc')
|
||||||
|
g.set_link('brand')
|
||||||
|
g.set_link('description')
|
||||||
|
g.set_link('size')
|
||||||
|
|
||||||
|
|
||||||
|
def defaults(config, **kwargs):
|
||||||
|
base = globals()
|
||||||
|
|
||||||
|
ProductView = kwargs.get('ProductView', base['ProductView'])
|
||||||
|
ProductView.defaults(config)
|
||||||
|
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
defaults(config)
|
|
@ -1,5 +1,10 @@
|
||||||
# -*- coding: utf-8; -*-
|
# -*- coding: utf-8; -*-
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy import orm
|
||||||
|
|
||||||
from wuttjamaican.testing import ConfigTestCase
|
from wuttjamaican.testing import ConfigTestCase
|
||||||
from wuttjamaican.exc import ConfigurationError
|
from wuttjamaican.exc import ConfigurationError
|
||||||
|
|
||||||
|
@ -11,6 +16,51 @@ class TestCoreposHandler(ConfigTestCase):
|
||||||
def make_handler(self):
|
def make_handler(self):
|
||||||
return mod.CoreposHandler(self.config)
|
return mod.CoreposHandler(self.config)
|
||||||
|
|
||||||
|
def test_get_model_office_op(self):
|
||||||
|
from corepos.db.office_op import model
|
||||||
|
handler = self.make_handler()
|
||||||
|
op_model = handler.get_model_office_op()
|
||||||
|
self.assertIs(op_model, model)
|
||||||
|
|
||||||
|
def test_get_model_office_trans(self):
|
||||||
|
from corepos.db.office_trans import model
|
||||||
|
handler = self.make_handler()
|
||||||
|
trans_model = handler.get_model_office_trans()
|
||||||
|
self.assertIs(trans_model, model)
|
||||||
|
|
||||||
|
def test_get_model_office_arch(self):
|
||||||
|
from corepos.db.office_arch import model
|
||||||
|
handler = self.make_handler()
|
||||||
|
arch_model = handler.get_model_office_arch()
|
||||||
|
self.assertIs(arch_model, model)
|
||||||
|
|
||||||
|
def test_make_session_office_op(self):
|
||||||
|
handler = self.make_handler()
|
||||||
|
engine = sa.create_engine('sqlite://')
|
||||||
|
with patch.object(self.config, 'core_office_op_engines', create=True,
|
||||||
|
new={'default': engine}):
|
||||||
|
op_session = handler.make_session_office_op()
|
||||||
|
self.assertIsInstance(op_session, orm.Session)
|
||||||
|
self.assertIs(op_session.bind, engine)
|
||||||
|
|
||||||
|
def test_make_session_office_trans(self):
|
||||||
|
handler = self.make_handler()
|
||||||
|
engine = sa.create_engine('sqlite://')
|
||||||
|
with patch.object(self.config, 'core_office_trans_engines', create=True,
|
||||||
|
new={'default': engine}):
|
||||||
|
trans_session = handler.make_session_office_trans()
|
||||||
|
self.assertIsInstance(trans_session, orm.Session)
|
||||||
|
self.assertIs(trans_session.bind, engine)
|
||||||
|
|
||||||
|
def test_make_session_office_arch(self):
|
||||||
|
handler = self.make_handler()
|
||||||
|
engine = sa.create_engine('sqlite://')
|
||||||
|
with patch.object(self.config, 'core_office_arch_engines', create=True,
|
||||||
|
new={'default': engine}):
|
||||||
|
arch_session = handler.make_session_office_arch()
|
||||||
|
self.assertIsInstance(arch_session, orm.Session)
|
||||||
|
self.assertIs(arch_session.bind, engine)
|
||||||
|
|
||||||
def test_get_office_url(self):
|
def test_get_office_url(self):
|
||||||
handler = self.make_handler()
|
handler = self.make_handler()
|
||||||
|
|
||||||
|
|
11
tests/web/test_init.py
Normal file
11
tests/web/test_init.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
|
||||||
|
from wuttaweb.testing import WebTestCase
|
||||||
|
|
||||||
|
from wutta_corepos import web as mod
|
||||||
|
|
||||||
|
|
||||||
|
class TestIncludeme(WebTestCase):
|
||||||
|
|
||||||
|
def test_coverage(self):
|
||||||
|
return mod.includeme(self.pyramid_config)
|
39
tests/web/views/corepos/test_members.py
Normal file
39
tests/web/views/corepos/test_members.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
|
||||||
|
from sqlalchemy import orm
|
||||||
|
|
||||||
|
from corepos.db.office_op import model as op_model
|
||||||
|
|
||||||
|
from wuttaweb.testing import WebTestCase
|
||||||
|
|
||||||
|
from wutta_corepos.web.views.corepos import members as mod
|
||||||
|
|
||||||
|
|
||||||
|
class TestProductView(WebTestCase):
|
||||||
|
|
||||||
|
def make_view(self):
|
||||||
|
return mod.MemberView(self.request)
|
||||||
|
|
||||||
|
def test_includeme(self):
|
||||||
|
return mod.includeme(self.pyramid_config)
|
||||||
|
|
||||||
|
def test_get_query(self):
|
||||||
|
view = self.make_view()
|
||||||
|
query = view.get_query()
|
||||||
|
# TODO: not sure how to test the join other than doing data
|
||||||
|
# setup and full runn-thru...and i'm feeling lazy
|
||||||
|
self.assertIsInstance(query, orm.Query)
|
||||||
|
|
||||||
|
def test_configure_grid(self):
|
||||||
|
view = self.make_view()
|
||||||
|
grid = view.make_grid(model_class=view.model_class)
|
||||||
|
self.assertNotIn('first_name', grid.renderers)
|
||||||
|
view.configure_grid(grid)
|
||||||
|
self.assertIn('first_name', grid.renderers)
|
||||||
|
|
||||||
|
def test_render_customer_attr(self):
|
||||||
|
view = self.make_view()
|
||||||
|
member = op_model.MemberInfo()
|
||||||
|
customer = op_model.CustomerClassic(first_name="Fred")
|
||||||
|
member.customers.append(customer)
|
||||||
|
self.assertEqual(view.render_customer_attr(member, 'first_name', 'nope'), "Fred")
|
21
tests/web/views/corepos/test_products.py
Normal file
21
tests/web/views/corepos/test_products.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
|
||||||
|
from wuttaweb.testing import WebTestCase
|
||||||
|
|
||||||
|
from wutta_corepos.web.views.corepos import products as mod
|
||||||
|
|
||||||
|
|
||||||
|
class TestProductView(WebTestCase):
|
||||||
|
|
||||||
|
def make_view(self):
|
||||||
|
return mod.ProductView(self.request)
|
||||||
|
|
||||||
|
def test_includeme(self):
|
||||||
|
return mod.includeme(self.pyramid_config)
|
||||||
|
|
||||||
|
def test_configure_grid(self):
|
||||||
|
view = self.make_view()
|
||||||
|
grid = view.make_grid(model_class=view.model_class)
|
||||||
|
self.assertNotIn('upc', grid.linked_columns)
|
||||||
|
view.configure_grid(grid)
|
||||||
|
self.assertIn('upc', grid.linked_columns)
|
Loading…
Reference in a new issue