Compare commits
No commits in common. "master" and "v0.1.0" have entirely different histories.
31
CHANGELOG.md
31
CHANGELOG.md
|
@ -5,37 +5,6 @@ All notable changes to Wutta-COREPOS will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## v0.3.0 (2025-02-20)
|
|
||||||
|
|
||||||
### Feat
|
|
||||||
|
|
||||||
- add app db schema extension, for CoreUser
|
|
||||||
- add support for `lane_op` and `lane_trans` DB sessions, models
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
- bump min version for wuttjamaican
|
|
||||||
- bump version requirement for pyCOREPOS
|
|
||||||
- add `get_office_employee_url()` method for corepos handler
|
|
||||||
- add grid links for Members
|
|
||||||
- bump min version for pycorepos dependency
|
|
||||||
|
|
||||||
## v0.2.1 (2025-01-15)
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
- add latest schema columns on app startup, unless not supported
|
|
||||||
|
|
||||||
## v0.2.0 (2025-01-13)
|
|
||||||
|
|
||||||
### Feat
|
|
||||||
|
|
||||||
- add basic readonly web views for CORE members, products
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
- add docs, tests; tweak some handler method signatures
|
|
||||||
|
|
||||||
## v0.1.0 (2025-01-12)
|
## v0.1.0 (2025-01-12)
|
||||||
|
|
||||||
### Feat
|
### Feat
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Minimal makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line, and also
|
|
||||||
# from the environment for the first two.
|
|
||||||
SPHINXOPTS ?=
|
|
||||||
SPHINXBUILD ?= sphinx-build
|
|
||||||
SOURCEDIR = .
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Put it first so that "make" without argument is like "make help".
|
|
||||||
help:
|
|
||||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
||||||
|
|
||||||
.PHONY: help Makefile
|
|
||||||
|
|
||||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
||||||
%: Makefile
|
|
||||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
0
docs/_static/.keepme
vendored
0
docs/_static/.keepme
vendored
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.app``
|
|
||||||
=====================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.app
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.conf``
|
|
||||||
======================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.conf
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.db.model``
|
|
||||||
==========================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.db.model
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.db``
|
|
||||||
====================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.db
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.handler``
|
|
||||||
=========================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.handler
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos``
|
|
||||||
=================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.web.db``
|
|
||||||
========================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.web.db
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.web``
|
|
||||||
=====================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.web
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.web.views.corepos.master``
|
|
||||||
==========================================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.web.views.corepos.master
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.web.views.corepos.members``
|
|
||||||
===========================================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.web.views.corepos.members
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.web.views.corepos.products``
|
|
||||||
============================================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.web.views.corepos.products
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.web.views.corepos``
|
|
||||||
===================================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.web.views.corepos
|
|
||||||
:members:
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
``wutta_corepos.web.views``
|
|
||||||
===========================
|
|
||||||
|
|
||||||
.. automodule:: wutta_corepos.web.views
|
|
||||||
:members:
|
|
39
docs/conf.py
39
docs/conf.py
|
@ -1,39 +0,0 @@
|
||||||
# Configuration file for the Sphinx documentation builder.
|
|
||||||
#
|
|
||||||
# For the full list of built-in configuration values, see the documentation:
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
|
||||||
|
|
||||||
from importlib.metadata import version as get_version
|
|
||||||
|
|
||||||
project = 'Wutta-COREPOS'
|
|
||||||
copyright = '2025, Lance Edgar'
|
|
||||||
author = 'Lance Edgar'
|
|
||||||
release = get_version('Wutta-COREPOS')
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
||||||
|
|
||||||
extensions = [
|
|
||||||
'sphinx.ext.autodoc',
|
|
||||||
'sphinx.ext.intersphinx',
|
|
||||||
'sphinx.ext.viewcode',
|
|
||||||
'sphinx.ext.todo',
|
|
||||||
]
|
|
||||||
|
|
||||||
templates_path = ['_templates']
|
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
|
||||||
|
|
||||||
intersphinx_mapping = {
|
|
||||||
'wuttaweb': ('https://docs.wuttaproject.org/wuttaweb/', None),
|
|
||||||
'wuttjamaican': ('https://docs.wuttaproject.org/wuttjamaican/', None),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
|
||||||
|
|
||||||
html_theme = 'furo'
|
|
||||||
html_static_path = ['_static']
|
|
|
@ -1,45 +0,0 @@
|
||||||
|
|
||||||
Wutta-COREPOS
|
|
||||||
=============
|
|
||||||
|
|
||||||
This package adds basic integration with `CORE-POS`_, using
|
|
||||||
`pyCOREPOS`_.
|
|
||||||
|
|
||||||
It provides the following:
|
|
||||||
|
|
||||||
* standard configuration for CORE Office + Lane databases
|
|
||||||
* special :term:`handler` for CORE integration
|
|
||||||
(:class:`~wutta_corepos.handler.CoreposHandler`)
|
|
||||||
* readonly web views for primary CORE Office DB tables
|
|
||||||
* :term:`data model` extension to map
|
|
||||||
:class:`~wuttjamaican:wuttjamaican.db.model.auth.User` to CORE
|
|
||||||
Employee
|
|
||||||
|
|
||||||
.. _CORE-POS: https://www.core-pos.com/
|
|
||||||
|
|
||||||
.. _pyCOREPOS: https://pypi.org/project/pyCOREPOS/
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
:caption: Documentation
|
|
||||||
|
|
||||||
narr/install
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 1
|
|
||||||
:caption: API
|
|
||||||
|
|
||||||
api/wutta_corepos
|
|
||||||
api/wutta_corepos.app
|
|
||||||
api/wutta_corepos.conf
|
|
||||||
api/wutta_corepos.db
|
|
||||||
api/wutta_corepos.db.model
|
|
||||||
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
|
|
|
@ -1,35 +0,0 @@
|
||||||
@ECHO OFF
|
|
||||||
|
|
||||||
pushd %~dp0
|
|
||||||
|
|
||||||
REM Command file for Sphinx documentation
|
|
||||||
|
|
||||||
if "%SPHINXBUILD%" == "" (
|
|
||||||
set SPHINXBUILD=sphinx-build
|
|
||||||
)
|
|
||||||
set SOURCEDIR=.
|
|
||||||
set BUILDDIR=_build
|
|
||||||
|
|
||||||
%SPHINXBUILD% >NUL 2>NUL
|
|
||||||
if errorlevel 9009 (
|
|
||||||
echo.
|
|
||||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
|
||||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
|
||||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
|
||||||
echo.may add the Sphinx directory to PATH.
|
|
||||||
echo.
|
|
||||||
echo.If you don't have Sphinx installed, grab it from
|
|
||||||
echo.https://www.sphinx-doc.org/
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "" goto help
|
|
||||||
|
|
||||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
||||||
goto end
|
|
||||||
|
|
||||||
:help
|
|
||||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
||||||
|
|
||||||
:end
|
|
||||||
popd
|
|
|
@ -1,85 +0,0 @@
|
||||||
|
|
||||||
Installation
|
|
||||||
============
|
|
||||||
|
|
||||||
This assumes you already have a :doc:`WuttJamaican app
|
|
||||||
<wuttjamaican:narr/install/index>` setup and working.
|
|
||||||
|
|
||||||
Install the Wutta-COREPOS package to your virtual environment:
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
pip install Wutta-COREPOS
|
|
||||||
|
|
||||||
Edit your :term:`config file` to add CORE-POS DB connection info, and
|
|
||||||
related settings.
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
[corepos]
|
|
||||||
office.url = http://localhost/fannie/
|
|
||||||
|
|
||||||
[corepos.db.office_op]
|
|
||||||
default.url = mysql+mysqlconnector://localhost/core_op
|
|
||||||
|
|
||||||
[corepos.db.office_trans]
|
|
||||||
default.url = mysql+mysqlconnector://localhost/core_trans
|
|
||||||
|
|
||||||
[corepos.db.office_arch]
|
|
||||||
default.url = mysql+mysqlconnector://localhost/trans_archive
|
|
||||||
|
|
||||||
[corepos.db.lane_op]
|
|
||||||
keys = 01, 02
|
|
||||||
01.url = mysql+mysqlconnector://lane01/opdata
|
|
||||||
02.url = mysql+mysqlconnector://lane02/opdata
|
|
||||||
|
|
||||||
[corepos.db.lane_trans]
|
|
||||||
keys = 01, 02
|
|
||||||
01.url = mysql+mysqlconnector://lane01/translog
|
|
||||||
02.url = mysql+mysqlconnector://lane02/translog
|
|
||||||
|
|
||||||
And that's it, the CORE-POS integration is configured.
|
|
||||||
|
|
||||||
|
|
||||||
Schema Extension
|
|
||||||
----------------
|
|
||||||
|
|
||||||
As of writing the only reason to add the schema extension is if you
|
|
||||||
need to map Wutta Users to CORE Employees, for auth (login) purposes.
|
|
||||||
So this section can be skipped if you do not need that.
|
|
||||||
|
|
||||||
This will effectively add the
|
|
||||||
:attr:`~wutta_corepos.db.model.CoreUser.corepos_employee_number`
|
|
||||||
attribute on the
|
|
||||||
:class:`~wuttjamaican:wuttjamaican.db.model.auth.User` model.
|
|
||||||
|
|
||||||
First you must override the :term:`app model` with your own. To do
|
|
||||||
this, create your own module (e.g. ``poser.db.model``) to contain::
|
|
||||||
|
|
||||||
from wuttjamaican.db.model import *
|
|
||||||
from wutta_corepos.db.model import *
|
|
||||||
|
|
||||||
Then configure your app model to override the default:
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
[wutta]
|
|
||||||
model_spec = poser.db.model
|
|
||||||
|
|
||||||
Then configure the Alembic section for schema migrations:
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
[alembic]
|
|
||||||
script_location = wuttjamaican.db:alembic
|
|
||||||
version_locations = wutta_corepos.db:alembic/versions wuttjamaican.db:alembic/versions
|
|
||||||
|
|
||||||
And finally run the Alembic command to migrate:
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
cd /path/to/env
|
|
||||||
bin/alembic -c app/wutta.conf upgrade heads
|
|
||||||
|
|
||||||
That should do it, from then on any changes will be migrated
|
|
||||||
automatically during upgrade.
|
|
|
@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "Wutta-COREPOS"
|
name = "Wutta-COREPOS"
|
||||||
version = "0.3.0"
|
version = "0.1.0"
|
||||||
description = "Wutta Framework integration for CORE-POS"
|
description = "Wutta Framework integration for CORE-POS"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
|
authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
|
||||||
|
@ -28,13 +28,12 @@ classifiers = [
|
||||||
]
|
]
|
||||||
requires-python = ">= 3.8"
|
requires-python = ">= 3.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pyCOREPOS>=0.5.1",
|
"pyCOREPOS>=0.3.2",
|
||||||
"WuttJamaican>=0.20.3",
|
"WuttJamaican>=0.20.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
web = ["WuttaWeb"]
|
|
||||||
docs = ["Sphinx", "furo"]
|
docs = ["Sphinx", "furo"]
|
||||||
tests = ["pytest-cov", "tox"]
|
tests = ["pytest-cov", "tox"]
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
# Copyright © 2025 Lance Edgar
|
# Copyright © 2024 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Wutta Framework.
|
# This file is part of Wutta Framework.
|
||||||
#
|
#
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
# Copyright © 2025 Lance Edgar
|
# Copyright © 2024 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Wutta Framework.
|
# This file is part of Wutta Framework.
|
||||||
#
|
#
|
||||||
|
@ -36,11 +36,6 @@ class WuttaCoreposAppProvider(AppProvider):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_corepos_handler(self, **kwargs):
|
def get_corepos_handler(self, **kwargs):
|
||||||
"""
|
|
||||||
Get the configured CORE-POS integration handler.
|
|
||||||
|
|
||||||
:rtype: :class:`~wutta_corepos.handler.CoreposHandler`
|
|
||||||
"""
|
|
||||||
if not hasattr(self, 'corepos_handler'):
|
if not hasattr(self, 'corepos_handler'):
|
||||||
spec = self.config.get(f'{self.appname}.corepos_handler',
|
spec = self.config.get(f'{self.appname}.corepos_handler',
|
||||||
default='wutta_corepos.handler:CoreposHandler')
|
default='wutta_corepos.handler:CoreposHandler')
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
# Copyright © 2025 Lance Edgar
|
# Copyright © 2024 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Wutta Framework.
|
# This file is part of Wutta Framework.
|
||||||
#
|
#
|
||||||
|
@ -40,7 +40,7 @@ class WuttaCoreposConfigExtension(WuttaConfigExtension):
|
||||||
* ``office_trans`` (default name ``core_trans``)
|
* ``office_trans`` (default name ``core_trans``)
|
||||||
* ``office_arch`` (default name ``trans_archive``)
|
* ``office_arch`` (default name ``trans_archive``)
|
||||||
|
|
||||||
The :term:`config object` will be given the following attributes:
|
The config object will be given the following attributes:
|
||||||
|
|
||||||
.. data:: core_office_op_engine
|
.. data:: core_office_op_engine
|
||||||
|
|
||||||
|
@ -74,34 +74,6 @@ class WuttaCoreposConfigExtension(WuttaConfigExtension):
|
||||||
Dict of ``office_arch`` DB engines. May be empty if no config
|
Dict of ``office_arch`` DB engines. May be empty if no config
|
||||||
is found; otherwise there should at least be a ``default`` key
|
is found; otherwise there should at least be a ``default`` key
|
||||||
defined, corresonding to :data:`core_office_arch_engine`.
|
defined, corresonding to :data:`core_office_arch_engine`.
|
||||||
|
|
||||||
.. data:: core_lane_op_engine
|
|
||||||
|
|
||||||
Primary engine for the ``lane_op`` DB. May be null if no
|
|
||||||
"default" engine is configured - which is *typical* for a
|
|
||||||
multi-lane environment. See :data:`core_lane_op_engines` for
|
|
||||||
the full set.
|
|
||||||
|
|
||||||
.. data:: core_lane_op_engines
|
|
||||||
|
|
||||||
Dict of ``lane_op`` DB engines. May be empty if no config is
|
|
||||||
found; otherwise keys are typically like ``01`` and ``02`` etc.
|
|
||||||
If present, the ``default`` key will correspond to
|
|
||||||
:data:`core_lane_op_engine`.
|
|
||||||
|
|
||||||
.. data:: core_lane_trans_engine
|
|
||||||
|
|
||||||
Primary engine for the ``lane_trans`` DB. May be null if no
|
|
||||||
"default" engine is configured - which is *typical* for a
|
|
||||||
multi-lane environment. See :data:`core_lane_trans_engines`
|
|
||||||
for the full set.
|
|
||||||
|
|
||||||
.. data:: core_lane_trans_engines
|
|
||||||
|
|
||||||
Dict of ``lane_trans`` DB engines. May be empty if no config
|
|
||||||
is found; otherwise keys are typically like ``01`` and ``02``
|
|
||||||
etc. If present, the ``default`` key will correspond to
|
|
||||||
:data:`core_lane_trans_engine`.
|
|
||||||
"""
|
"""
|
||||||
key = 'wutta_corepos'
|
key = 'wutta_corepos'
|
||||||
|
|
||||||
|
@ -128,23 +100,3 @@ class WuttaCoreposConfigExtension(WuttaConfigExtension):
|
||||||
config.core_office_arch_engines = engines
|
config.core_office_arch_engines = engines
|
||||||
config.core_office_arch_engine = engines.get('default')
|
config.core_office_arch_engine = engines.get('default')
|
||||||
Session.configure(bind=config.core_office_arch_engine)
|
Session.configure(bind=config.core_office_arch_engine)
|
||||||
|
|
||||||
# lane_op
|
|
||||||
from corepos.db.lane_op import Session
|
|
||||||
engines = get_engines(config, 'corepos.db.lane_op')
|
|
||||||
config.core_lane_op_engines = engines
|
|
||||||
config.core_lane_op_engine = engines.get('default')
|
|
||||||
Session.configure(bind=config.core_lane_op_engine)
|
|
||||||
|
|
||||||
# lane_trans
|
|
||||||
from corepos.db.lane_trans import Session
|
|
||||||
engines = get_engines(config, 'corepos.db.lane_trans')
|
|
||||||
config.core_lane_trans_engines = engines
|
|
||||||
config.core_lane_trans_engine = engines.get('default')
|
|
||||||
Session.configure(bind=config.core_lane_trans_engine)
|
|
||||||
|
|
||||||
# define some schema columns "late" unless not supported
|
|
||||||
if config.get_bool('corepos.db.office_op.use_latest_columns',
|
|
||||||
default=True, usedb=False):
|
|
||||||
from corepos.db.office_op.model import use_latest_columns
|
|
||||||
use_latest_columns()
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
"""initial user extension
|
|
||||||
|
|
||||||
Revision ID: 0f94089f1af1
|
|
||||||
Revises:
|
|
||||||
Create Date: 2025-01-24 21:13:14.359200
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
import wuttjamaican.db.util
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '0f94089f1af1'
|
|
||||||
down_revision: Union[str, None] = None
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = ('wutta_corepos',)
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
|
|
||||||
# corepos_user
|
|
||||||
op.create_table('corepos_user',
|
|
||||||
sa.Column('uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
|
||||||
sa.Column('corepos_employee_number', sa.Integer(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['uuid'], ['user.uuid'], name=op.f('fk_corepos_user_uuid_user')),
|
|
||||||
sa.PrimaryKeyConstraint('uuid', name=op.f('pk_corepos_user')),
|
|
||||||
sa.UniqueConstraint('corepos_employee_number', name=op.f('uq_corepos_user_corepos_employee_number'))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
|
|
||||||
# corepos_user
|
|
||||||
op.drop_table('corepos_user')
|
|
|
@ -1,67 +0,0 @@
|
||||||
# -*- 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/>.
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
"""
|
|
||||||
Data models for CORE-POS integration
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sqlalchemy as sa
|
|
||||||
from sqlalchemy import orm
|
|
||||||
|
|
||||||
from wuttjamaican.db import model
|
|
||||||
|
|
||||||
|
|
||||||
class CoreUser(model.Base):
|
|
||||||
"""
|
|
||||||
CORE-POS extension for
|
|
||||||
:class:`~wuttjamaican:wuttjamaican.db.model.auth.User`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__tablename__ = 'corepos_user'
|
|
||||||
|
|
||||||
uuid = model.uuid_column(sa.ForeignKey('user.uuid'), default=None)
|
|
||||||
user = orm.relationship(
|
|
||||||
model.User,
|
|
||||||
cascade_backrefs=False,
|
|
||||||
doc="""
|
|
||||||
Reference to the
|
|
||||||
:class:`~wuttjamaican:wuttjamaican.db.model.auth.User` which
|
|
||||||
this record extends.
|
|
||||||
""",
|
|
||||||
backref=orm.backref(
|
|
||||||
'_corepos',
|
|
||||||
uselist=False,
|
|
||||||
cascade='all, delete-orphan',
|
|
||||||
cascade_backrefs=False,
|
|
||||||
doc="""
|
|
||||||
Reference to the CORE-POS extension record for the user.
|
|
||||||
""")
|
|
||||||
)
|
|
||||||
|
|
||||||
corepos_employee_number = sa.Column(sa.Integer(), nullable=False, unique=True, doc="""
|
|
||||||
``employees.emp_no`` value for the user within CORE-POS.
|
|
||||||
""")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self.user)
|
|
||||||
|
|
||||||
CoreUser.make_proxy(model.User, '_corepos', 'corepos_employee_number')
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
# Wutta-COREPOS -- Wutta Framework integration for CORE-POS
|
||||||
# Copyright © 2025 Lance Edgar
|
# Copyright © 2024 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Wutta Framework.
|
# This file is part of Wutta Framework.
|
||||||
#
|
#
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
"""
|
"""
|
||||||
CORE-POS Integration Handler
|
CORE-POS Handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from wuttjamaican.app import GenericHandler
|
from wuttjamaican.app import GenericHandler
|
||||||
|
@ -33,126 +33,11 @@ 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 get_model_lane_op(self):
|
|
||||||
"""
|
|
||||||
Returns the :term:`data model` module for CORE Lane 'op' DB,
|
|
||||||
i.e. :mod:`pycorepos:corepos.db.lane_op.model`.
|
|
||||||
"""
|
|
||||||
from corepos.db.lane_op import model
|
|
||||||
|
|
||||||
return model
|
|
||||||
|
|
||||||
def get_model_lane_trans(self):
|
|
||||||
"""
|
|
||||||
Returns the :term:`data model` module for CORE Lane 'trans'
|
|
||||||
DB, i.e. :mod:`pycorepos:corepos.db.lane_trans.model`.
|
|
||||||
"""
|
|
||||||
from corepos.db.lane_trans 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 make_session_lane_op(self, dbkey='default', **kwargs):
|
|
||||||
"""
|
|
||||||
Make a new :term:`db session` for the CORE Lane 'op' DB.
|
|
||||||
|
|
||||||
:returns: Instance of
|
|
||||||
:class:`pycorepos:corepos.db.lane_op.Session`.
|
|
||||||
"""
|
|
||||||
from corepos.db.lane_op import Session
|
|
||||||
|
|
||||||
if 'bind' not in kwargs:
|
|
||||||
kwargs['bind'] = self.config.core_lane_op_engines[dbkey]
|
|
||||||
return Session(**kwargs)
|
|
||||||
|
|
||||||
def make_session_lane_trans(self, dbkey='default', **kwargs):
|
|
||||||
"""
|
|
||||||
Make a new :term:`db session` for the CORE Lane 'trans' DB.
|
|
||||||
|
|
||||||
:returns: Instance of
|
|
||||||
:class:`pycorepos:corepos.db.lane_trans.Session`.
|
|
||||||
"""
|
|
||||||
from corepos.db.lane_trans import Session
|
|
||||||
|
|
||||||
if 'bind' not in kwargs:
|
|
||||||
kwargs['bind'] = self.config.core_lane_trans_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.
|
||||||
|
|
||||||
Note that the return value is stripped of final slash.
|
Note that the return value is stripped of final slash.
|
||||||
|
|
||||||
:param require: If true, an error is raised when URL cannot be
|
|
||||||
determined.
|
|
||||||
|
|
||||||
:returns: URL as string.
|
|
||||||
"""
|
"""
|
||||||
url = self.config.get('corepos.office.url', require=require)
|
url = self.config.get('corepos.office.url', require=require)
|
||||||
if url:
|
if url:
|
||||||
|
@ -160,86 +45,40 @@ class CoreposHandler(GenericHandler):
|
||||||
|
|
||||||
def get_office_department_url(
|
def get_office_department_url(
|
||||||
self,
|
self,
|
||||||
dept_id,
|
number,
|
||||||
office_url=None,
|
office_url=None,
|
||||||
require=False):
|
require=False,
|
||||||
|
**kwargs):
|
||||||
"""
|
"""
|
||||||
Returns the CORE Office URL for a Department.
|
Returns the CORE Office URL for a Department.
|
||||||
|
|
||||||
:param dept_id: Department ID for the URL.
|
|
||||||
|
|
||||||
:param office_url: Root URL from :meth:`get_office_url()`.
|
|
||||||
|
|
||||||
:param require: If true, an error is raised when URL cannot be
|
|
||||||
determined.
|
|
||||||
|
|
||||||
:returns: URL as string.
|
|
||||||
"""
|
"""
|
||||||
if not office_url:
|
if not office_url:
|
||||||
office_url = self.get_office_url(require=require)
|
office_url = self.get_office_url(require=require)
|
||||||
if office_url:
|
if office_url:
|
||||||
return f'{office_url}/item/departments/DepartmentEditor.php?did={dept_id}'
|
return f'{office_url}/item/departments/DepartmentEditor.php?did={number}'
|
||||||
|
|
||||||
def get_office_employee_url(
|
|
||||||
self,
|
|
||||||
employee_id,
|
|
||||||
office_url=None,
|
|
||||||
require=False):
|
|
||||||
"""
|
|
||||||
Returns the CORE Office URL for an Employee.
|
|
||||||
|
|
||||||
:param employee_id: Employee ID for the URL.
|
|
||||||
|
|
||||||
:param office_url: Root URL from :meth:`get_office_url()`.
|
|
||||||
|
|
||||||
:param require: If true, an error is raised when URL cannot be
|
|
||||||
determined.
|
|
||||||
|
|
||||||
:returns: URL as string.
|
|
||||||
"""
|
|
||||||
if not office_url:
|
|
||||||
office_url = self.get_office_url(require=require)
|
|
||||||
if office_url:
|
|
||||||
return f'{office_url}/admin/Cashiers/CashierEditor.php?emp_no={employee_id}'
|
|
||||||
|
|
||||||
def get_office_likecode_url(
|
def get_office_likecode_url(
|
||||||
self,
|
self,
|
||||||
likecode_id,
|
id,
|
||||||
office_url=None,
|
office_url=None,
|
||||||
require=False):
|
require=False,
|
||||||
|
**kwargs):
|
||||||
"""
|
"""
|
||||||
Returns the CORE Office URL for a Like Code.
|
Returns the CORE Office URL for a Like Code.
|
||||||
|
|
||||||
:param likecode_id: Like Code ID for the URL.
|
|
||||||
|
|
||||||
:param office_url: Root URL from :meth:`get_office_url()`.
|
|
||||||
|
|
||||||
:param require: If true, an error is raised when URL cannot be
|
|
||||||
determined.
|
|
||||||
|
|
||||||
:returns: URL as string.
|
|
||||||
"""
|
"""
|
||||||
if not office_url:
|
if not office_url:
|
||||||
office_url = self.get_office_url(require=require)
|
office_url = self.get_office_url(require=require)
|
||||||
if office_url:
|
if office_url:
|
||||||
return f'{office_url}/item/likecodes/LikeCodeEditor.php?start={likecode_id}'
|
return f'{office_url}/item/likecodes/LikeCodeEditor.php?start={id}'
|
||||||
|
|
||||||
def get_office_product_url(
|
def get_office_product_url(
|
||||||
self,
|
self,
|
||||||
upc,
|
upc,
|
||||||
office_url=None,
|
office_url=None,
|
||||||
require=False):
|
require=False,
|
||||||
|
**kwargs):
|
||||||
"""
|
"""
|
||||||
Returns the CORE Office URL for a Product.
|
Returns the CORE Office URL for a Product.
|
||||||
|
|
||||||
:param upc: UPC for the URL.
|
|
||||||
|
|
||||||
:param office_url: Root URL from :meth:`get_office_url()`.
|
|
||||||
|
|
||||||
:param require: If true, an error is raised when URL cannot be
|
|
||||||
determined.
|
|
||||||
|
|
||||||
:returns: URL as string.
|
|
||||||
"""
|
"""
|
||||||
if not office_url:
|
if not office_url:
|
||||||
office_url = self.get_office_url(require=require)
|
office_url = self.get_office_url(require=require)
|
||||||
|
@ -248,22 +87,14 @@ class CoreposHandler(GenericHandler):
|
||||||
|
|
||||||
def get_office_vendor_url(
|
def get_office_vendor_url(
|
||||||
self,
|
self,
|
||||||
vend_id,
|
id,
|
||||||
office_url=None,
|
office_url=None,
|
||||||
require=False):
|
require=False,
|
||||||
|
**kwargs):
|
||||||
"""
|
"""
|
||||||
Returns the CORE Office URL for a Vendor.
|
Returns the CORE Office URL for a Vendor.
|
||||||
|
|
||||||
:param vend_id: Vendor ID for the URL.
|
|
||||||
|
|
||||||
:param office_url: Root URL from :meth:`get_office_url()`.
|
|
||||||
|
|
||||||
:param require: If true, an error is raised when URL cannot be
|
|
||||||
determined.
|
|
||||||
|
|
||||||
:returns: URL as string.
|
|
||||||
"""
|
"""
|
||||||
if not office_url:
|
if not office_url:
|
||||||
office_url = self.get_office_url(require=require)
|
office_url = self.get_office_url(require=require)
|
||||||
if office_url:
|
if office_url:
|
||||||
return f'{office_url}/item/vendors/VendorIndexPage.php?vid={vend_id}'
|
return f'{office_url}/item/vendors/VendorIndexPage.php?vid={id}'
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
# -*- 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')
|
|
|
@ -1,94 +0,0 @@
|
||||||
# -*- 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.
|
|
||||||
|
|
||||||
.. class:: CoreLaneOpSession
|
|
||||||
|
|
||||||
Primary web app :term:`db session` for CORE Lane 'op' DB.
|
|
||||||
|
|
||||||
.. class:: CoreLaneTransSession
|
|
||||||
|
|
||||||
Primary web app :term:`db session` for CORE Lane 'trans' DB.
|
|
||||||
|
|
||||||
.. class:: ExtraCoreLaneOpSessions
|
|
||||||
|
|
||||||
Dict of secondary CORE Lane 'op' DB sessions, if applicable.
|
|
||||||
|
|
||||||
.. class:: ExtraCoreLaneTransSessions
|
|
||||||
|
|
||||||
Dict of secondary CORE Lane 'trans' 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)
|
|
||||||
|
|
||||||
CoreLaneOpSession = scoped_session(sessionmaker())
|
|
||||||
register(CoreLaneOpSession)
|
|
||||||
|
|
||||||
CoreLaneTransSession = scoped_session(sessionmaker())
|
|
||||||
register(CoreLaneTransSession)
|
|
||||||
|
|
||||||
# nb. these start out empty but may be populated on app startup
|
|
||||||
ExtraCoreOpSessions = {}
|
|
||||||
ExtraCoreTransSessions = {}
|
|
||||||
ExtraCoreArchSessions = {}
|
|
||||||
ExtraCoreLaneOpSessions = {}
|
|
||||||
ExtraCoreLaneTransSessions = {}
|
|
|
@ -1,29 +0,0 @@
|
||||||
# -*- 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')
|
|
|
@ -1,32 +0,0 @@
|
||||||
# -*- 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')
|
|
|
@ -1,40 +0,0 @@
|
||||||
# -*- 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()
|
|
|
@ -1,123 +0,0 @@
|
||||||
# -*- 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)
|
|
||||||
|
|
||||||
# links
|
|
||||||
if self.has_perm('view'):
|
|
||||||
g.set_link('card_number')
|
|
||||||
g.set_link('first_name')
|
|
||||||
g.set_link('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)
|
|
|
@ -1,97 +0,0 @@
|
||||||
# -*- 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,16 +0,0 @@
|
||||||
# -*- coding: utf-8; -*-
|
|
||||||
|
|
||||||
from wuttjamaican.testing import ConfigTestCase
|
|
||||||
from wuttjamaican.db.model import User
|
|
||||||
|
|
||||||
from wutta_corepos.db import model as mod
|
|
||||||
|
|
||||||
|
|
||||||
class TestCoreUser(ConfigTestCase):
|
|
||||||
|
|
||||||
def test_str(self):
|
|
||||||
user = User(username='barney')
|
|
||||||
self.assertEqual(str(user), 'barney')
|
|
||||||
|
|
||||||
ext = mod.CoreUser(user=user, corepos_employee_number=42)
|
|
||||||
self.assertEqual(str(ext), 'barney')
|
|
|
@ -1,16 +0,0 @@
|
||||||
# -*- coding: utf-8; -*-
|
|
||||||
|
|
||||||
from wuttjamaican.testing import ConfigTestCase
|
|
||||||
|
|
||||||
from wutta_corepos import app as mod
|
|
||||||
from wutta_corepos.handler import CoreposHandler
|
|
||||||
|
|
||||||
|
|
||||||
class TestWuttaCoreposAppProvider(ConfigTestCase):
|
|
||||||
|
|
||||||
def make_provider(self):
|
|
||||||
return mod.WuttaCoreposAppProvider(self.config)
|
|
||||||
|
|
||||||
def test_get_report_handler(self):
|
|
||||||
handler = self.app.get_corepos_handler()
|
|
||||||
self.assertIsInstance(handler, CoreposHandler)
|
|
|
@ -1,36 +0,0 @@
|
||||||
# -*- coding: utf-8; -*-
|
|
||||||
|
|
||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
from wuttjamaican.conf import WuttaConfig
|
|
||||||
|
|
||||||
from wutta_corepos import conf as mod
|
|
||||||
|
|
||||||
|
|
||||||
class TestWuttaCoreposConfigExtension(TestCase):
|
|
||||||
|
|
||||||
def test_configure(self):
|
|
||||||
config = WuttaConfig()
|
|
||||||
|
|
||||||
# no engines by default
|
|
||||||
self.assertFalse(hasattr(config, 'core_office_op_engine'))
|
|
||||||
self.assertFalse(hasattr(config, 'core_office_trans_engine'))
|
|
||||||
self.assertFalse(hasattr(config, 'core_office_arch_engine'))
|
|
||||||
self.assertFalse(hasattr(config, 'core_lane_op_engine'))
|
|
||||||
self.assertFalse(hasattr(config, 'core_lane_trans_engine'))
|
|
||||||
ext = mod.WuttaCoreposConfigExtension()
|
|
||||||
ext.configure(config)
|
|
||||||
self.assertIsNone(config.core_office_op_engine)
|
|
||||||
self.assertIsNone(config.core_office_trans_engine)
|
|
||||||
self.assertIsNone(config.core_office_arch_engine)
|
|
||||||
self.assertIsNone(config.core_lane_op_engine)
|
|
||||||
self.assertIsNone(config.core_lane_trans_engine)
|
|
||||||
|
|
||||||
# but config can change that
|
|
||||||
config.setdefault('corepos.db.office_op.default.url', 'sqlite://')
|
|
||||||
config.setdefault('corepos.db.lane_trans.default.url', 'sqlite://')
|
|
||||||
ext.configure(config)
|
|
||||||
self.assertIsNotNone(config.core_office_op_engine)
|
|
||||||
self.assertEqual(str(config.core_office_op_engine.url), 'sqlite://')
|
|
||||||
self.assertIsNotNone(config.core_lane_trans_engine)
|
|
||||||
self.assertEqual(str(config.core_lane_trans_engine.url), 'sqlite://')
|
|
|
@ -1,156 +0,0 @@
|
||||||
# -*- 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
|
|
||||||
|
|
||||||
from wutta_corepos import handler as mod
|
|
||||||
|
|
||||||
|
|
||||||
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_get_model_lane_op(self):
|
|
||||||
from corepos.db.lane_op import model
|
|
||||||
handler = self.make_handler()
|
|
||||||
op_model = handler.get_model_lane_op()
|
|
||||||
self.assertIs(op_model, model)
|
|
||||||
|
|
||||||
def test_get_model_lane_trans(self):
|
|
||||||
from corepos.db.lane_trans import model
|
|
||||||
handler = self.make_handler()
|
|
||||||
trans_model = handler.get_model_lane_trans()
|
|
||||||
self.assertIs(trans_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_make_session_lane_op(self):
|
|
||||||
handler = self.make_handler()
|
|
||||||
engine = sa.create_engine('sqlite://')
|
|
||||||
with patch.object(self.config, 'core_lane_op_engines', create=True,
|
|
||||||
new={'default': engine}):
|
|
||||||
op_session = handler.make_session_lane_op()
|
|
||||||
self.assertIsInstance(op_session, orm.Session)
|
|
||||||
self.assertIs(op_session.bind, engine)
|
|
||||||
|
|
||||||
def test_make_session_lane_trans(self):
|
|
||||||
handler = self.make_handler()
|
|
||||||
engine = sa.create_engine('sqlite://')
|
|
||||||
with patch.object(self.config, 'core_lane_trans_engines', create=True,
|
|
||||||
new={'default': engine}):
|
|
||||||
trans_session = handler.make_session_lane_trans()
|
|
||||||
self.assertIsInstance(trans_session, orm.Session)
|
|
||||||
self.assertIs(trans_session.bind, engine)
|
|
||||||
|
|
||||||
def test_get_office_url(self):
|
|
||||||
handler = self.make_handler()
|
|
||||||
|
|
||||||
# null by default
|
|
||||||
self.assertIsNone(handler.get_office_url())
|
|
||||||
|
|
||||||
# error if required
|
|
||||||
self.assertRaises(ConfigurationError, handler.get_office_url, require=True)
|
|
||||||
|
|
||||||
# config can specify (traliing slash is stripped)
|
|
||||||
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
|
|
||||||
self.assertEqual(handler.get_office_url(), 'http://localhost/fannie')
|
|
||||||
self.assertEqual(handler.get_office_url(require=True), 'http://localhost/fannie')
|
|
||||||
|
|
||||||
def test_get_office_department_url(self):
|
|
||||||
handler = self.make_handler()
|
|
||||||
|
|
||||||
# null
|
|
||||||
self.assertIsNone(handler.get_office_department_url(7))
|
|
||||||
|
|
||||||
# typical
|
|
||||||
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
|
|
||||||
self.assertEqual(handler.get_office_department_url(7), 'http://localhost/fannie/item/departments/DepartmentEditor.php?did=7')
|
|
||||||
|
|
||||||
def test_get_office_employee_url(self):
|
|
||||||
handler = self.make_handler()
|
|
||||||
|
|
||||||
# null
|
|
||||||
self.assertIsNone(handler.get_office_employee_url(7))
|
|
||||||
|
|
||||||
# typical
|
|
||||||
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
|
|
||||||
self.assertEqual(handler.get_office_employee_url(7), 'http://localhost/fannie/admin/Cashiers/CashierEditor.php?emp_no=7')
|
|
||||||
|
|
||||||
def test_get_office_likecode_url(self):
|
|
||||||
handler = self.make_handler()
|
|
||||||
|
|
||||||
# null
|
|
||||||
self.assertIsNone(handler.get_office_likecode_url(7))
|
|
||||||
|
|
||||||
# typical
|
|
||||||
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
|
|
||||||
self.assertEqual(handler.get_office_likecode_url(7), 'http://localhost/fannie/item/likecodes/LikeCodeEditor.php?start=7')
|
|
||||||
|
|
||||||
def test_get_office_product_url(self):
|
|
||||||
handler = self.make_handler()
|
|
||||||
|
|
||||||
# null
|
|
||||||
self.assertIsNone(handler.get_office_product_url('07430500132'))
|
|
||||||
|
|
||||||
# typical
|
|
||||||
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
|
|
||||||
self.assertEqual(handler.get_office_product_url('07430500132'), 'http://localhost/fannie/item/ItemEditorPage.php?searchupc=07430500132')
|
|
||||||
|
|
||||||
def test_get_office_vendor_url(self):
|
|
||||||
handler = self.make_handler()
|
|
||||||
|
|
||||||
# null
|
|
||||||
self.assertIsNone(handler.get_office_vendor_url(7))
|
|
||||||
|
|
||||||
# typical
|
|
||||||
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
|
|
||||||
self.assertEqual(handler.get_office_vendor_url(7), 'http://localhost/fannie/item/vendors/VendorIndexPage.php?vid=7')
|
|
|
@ -1,11 +0,0 @@
|
||||||
# -*- 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)
|
|
|
@ -1,44 +0,0 @@
|
||||||
# -*- coding: utf-8; -*-
|
|
||||||
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
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 TestMemberView(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)
|
|
||||||
self.assertNotIn('first_name', grid.linked_columns)
|
|
||||||
with patch.object(self.request, 'is_root', new=True):
|
|
||||||
view.configure_grid(grid)
|
|
||||||
self.assertIn('first_name', grid.renderers)
|
|
||||||
self.assertIn('first_name', grid.linked_columns)
|
|
||||||
|
|
||||||
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")
|
|
|
@ -1,21 +0,0 @@
|
||||||
# -*- 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)
|
|
4
tox.ini
4
tox.ini
|
@ -3,7 +3,7 @@
|
||||||
envlist = py38, py39, py310, py311
|
envlist = py38, py39, py310, py311
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
extras = web,tests
|
extras = tests
|
||||||
commands = pytest {posargs}
|
commands = pytest {posargs}
|
||||||
|
|
||||||
[testenv:coverage]
|
[testenv:coverage]
|
||||||
|
@ -12,6 +12,6 @@ commands = pytest --cov=wutta_corepos --cov-report=html --cov-fail-under=100
|
||||||
|
|
||||||
[testenv:docs]
|
[testenv:docs]
|
||||||
basepython = python3.11
|
basepython = python3.11
|
||||||
extras = web,docs
|
extras = docs
|
||||||
changedir = docs
|
changedir = docs
|
||||||
commands = sphinx-build -b html -d {envtmpdir}/doctrees -W -T . {envtmpdir}/docs
|
commands = sphinx-build -b html -d {envtmpdir}/doctrees -W -T . {envtmpdir}/docs
|
||||||
|
|
Loading…
Reference in a new issue