diff --git a/docs/api/wutta_corepos.web.db.rst b/docs/api/wutta_corepos.web.db.rst
new file mode 100644
index 0000000..11c37ca
--- /dev/null
+++ b/docs/api/wutta_corepos.web.db.rst
@@ -0,0 +1,6 @@
+
+``wutta_corepos.web.db``
+========================
+
+.. automodule:: wutta_corepos.web.db
+ :members:
diff --git a/docs/api/wutta_corepos.web.rst b/docs/api/wutta_corepos.web.rst
new file mode 100644
index 0000000..56d6604
--- /dev/null
+++ b/docs/api/wutta_corepos.web.rst
@@ -0,0 +1,6 @@
+
+``wutta_corepos.web``
+=====================
+
+.. automodule:: wutta_corepos.web
+ :members:
diff --git a/docs/api/wutta_corepos.web.views.corepos.master.rst b/docs/api/wutta_corepos.web.views.corepos.master.rst
new file mode 100644
index 0000000..f9ebea7
--- /dev/null
+++ b/docs/api/wutta_corepos.web.views.corepos.master.rst
@@ -0,0 +1,6 @@
+
+``wutta_corepos.web.views.corepos.master``
+==========================================
+
+.. automodule:: wutta_corepos.web.views.corepos.master
+ :members:
diff --git a/docs/api/wutta_corepos.web.views.corepos.members.rst b/docs/api/wutta_corepos.web.views.corepos.members.rst
new file mode 100644
index 0000000..d5012c1
--- /dev/null
+++ b/docs/api/wutta_corepos.web.views.corepos.members.rst
@@ -0,0 +1,6 @@
+
+``wutta_corepos.web.views.corepos.members``
+===========================================
+
+.. automodule:: wutta_corepos.web.views.corepos.members
+ :members:
diff --git a/docs/api/wutta_corepos.web.views.corepos.products.rst b/docs/api/wutta_corepos.web.views.corepos.products.rst
new file mode 100644
index 0000000..00db4c4
--- /dev/null
+++ b/docs/api/wutta_corepos.web.views.corepos.products.rst
@@ -0,0 +1,6 @@
+
+``wutta_corepos.web.views.corepos.products``
+============================================
+
+.. automodule:: wutta_corepos.web.views.corepos.products
+ :members:
diff --git a/docs/api/wutta_corepos.web.views.corepos.rst b/docs/api/wutta_corepos.web.views.corepos.rst
new file mode 100644
index 0000000..d2703d5
--- /dev/null
+++ b/docs/api/wutta_corepos.web.views.corepos.rst
@@ -0,0 +1,6 @@
+
+``wutta_corepos.web.views.corepos``
+===================================
+
+.. automodule:: wutta_corepos.web.views.corepos
+ :members:
diff --git a/docs/api/wutta_corepos.web.views.rst b/docs/api/wutta_corepos.web.views.rst
new file mode 100644
index 0000000..aecedcb
--- /dev/null
+++ b/docs/api/wutta_corepos.web.views.rst
@@ -0,0 +1,6 @@
+
+``wutta_corepos.web.views``
+===========================
+
+.. automodule:: wutta_corepos.web.views
+ :members:
diff --git a/docs/conf.py b/docs/conf.py
index 301c604..4759410 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -27,6 +27,7 @@ templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
intersphinx_mapping = {
+ 'wuttaweb': ('https://rattailproject.org/docs/wuttaweb/', None),
'wuttjamaican': ('https://rattailproject.org/docs/wuttjamaican/', None),
}
diff --git a/docs/index.rst b/docs/index.rst
index 44e43b7..4f5d57b 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -5,7 +5,8 @@ Wutta-COREPOS
This package adds basic integration with `CORE-POS`_, using
`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/
@@ -26,3 +27,10 @@ Its main purpose is to setup DB connections for CORE Office.
api/wutta_corepos.app
api/wutta_corepos.conf
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
diff --git a/pyproject.toml b/pyproject.toml
index a088123..a12611b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -34,6 +34,7 @@ dependencies = [
[project.optional-dependencies]
+web = ["WuttaWeb"]
docs = ["Sphinx", "furo"]
tests = ["pytest-cov", "tox"]
diff --git a/src/wutta_corepos/handler.py b/src/wutta_corepos/handler.py
index 9a66367..8b39795 100644
--- a/src/wutta_corepos/handler.py
+++ b/src/wutta_corepos/handler.py
@@ -21,7 +21,7 @@
#
################################################################################
"""
-CORE-POS Handler
+CORE-POS Integration Handler
"""
from wuttjamaican.app import GenericHandler
@@ -33,6 +33,72 @@ class CoreposHandler(GenericHandler):
: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):
"""
Returns the base URL for the CORE Office web app.
diff --git a/src/wutta_corepos/web/__init__.py b/src/wutta_corepos/web/__init__.py
new file mode 100644
index 0000000..71a9477
--- /dev/null
+++ b/src/wutta_corepos/web/__init__.py
@@ -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 .
+#
+################################################################################
+"""
+Wutta-COREPOS -- wuttaweb features
+"""
+
+
+def includeme(config):
+ config.include('wutta_corepos.web.views')
diff --git a/src/wutta_corepos/web/db.py b/src/wutta_corepos/web/db.py
new file mode 100644
index 0000000..7faeff2
--- /dev/null
+++ b/src/wutta_corepos/web/db.py
@@ -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 .
+#
+################################################################################
+"""
+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 = {}
diff --git a/src/wutta_corepos/web/views/__init__.py b/src/wutta_corepos/web/views/__init__.py
new file mode 100644
index 0000000..d4112a2
--- /dev/null
+++ b/src/wutta_corepos/web/views/__init__.py
@@ -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 .
+#
+################################################################################
+"""
+Wutta-COREPOS -- wuttaweb views
+"""
+
+
+def includeme(config):
+ config.include('wutta_corepos.web.views.corepos')
diff --git a/src/wutta_corepos/web/views/corepos/__init__.py b/src/wutta_corepos/web/views/corepos/__init__.py
new file mode 100644
index 0000000..a78e4ef
--- /dev/null
+++ b/src/wutta_corepos/web/views/corepos/__init__.py
@@ -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 .
+#
+################################################################################
+"""
+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')
diff --git a/src/wutta_corepos/web/views/corepos/master.py b/src/wutta_corepos/web/views/corepos/master.py
new file mode 100644
index 0000000..817a443
--- /dev/null
+++ b/src/wutta_corepos/web/views/corepos/master.py
@@ -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 .
+#
+################################################################################
+"""
+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()
diff --git a/src/wutta_corepos/web/views/corepos/members.py b/src/wutta_corepos/web/views/corepos/members.py
new file mode 100644
index 0000000..66c967e
--- /dev/null
+++ b/src/wutta_corepos/web/views/corepos/members.py
@@ -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 .
+#
+################################################################################
+"""
+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)
diff --git a/src/wutta_corepos/web/views/corepos/products.py b/src/wutta_corepos/web/views/corepos/products.py
new file mode 100644
index 0000000..e8f33c4
--- /dev/null
+++ b/src/wutta_corepos/web/views/corepos/products.py
@@ -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 .
+#
+################################################################################
+"""
+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)
diff --git a/tests/test_handler.py b/tests/test_handler.py
index e29835b..6dc5077 100644
--- a/tests/test_handler.py
+++ b/tests/test_handler.py
@@ -1,5 +1,10 @@
# -*- coding: utf-8; -*-
+from unittest.mock import patch
+
+import sqlalchemy as sa
+from sqlalchemy import orm
+
from wuttjamaican.testing import ConfigTestCase
from wuttjamaican.exc import ConfigurationError
@@ -11,6 +16,51 @@ class TestCoreposHandler(ConfigTestCase):
def make_handler(self):
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):
handler = self.make_handler()
diff --git a/tests/web/test_init.py b/tests/web/test_init.py
new file mode 100644
index 0000000..6c9d367
--- /dev/null
+++ b/tests/web/test_init.py
@@ -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)
diff --git a/tests/web/views/corepos/test_members.py b/tests/web/views/corepos/test_members.py
new file mode 100644
index 0000000..6055ef9
--- /dev/null
+++ b/tests/web/views/corepos/test_members.py
@@ -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")
diff --git a/tests/web/views/corepos/test_products.py b/tests/web/views/corepos/test_products.py
new file mode 100644
index 0000000..8870208
--- /dev/null
+++ b/tests/web/views/corepos/test_products.py
@@ -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)