From 2bb75bfd4f4afbf09f6c0f061a001330925856a5 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 2 Sep 2022 17:18:03 -0500 Subject: [PATCH] Initial commit basic views for Wave cache tables: Customers, Invoices --- .gitignore | 1 + CHANGELOG.md | 10 +++ MANIFEST.in | 3 + README.rst | 14 ++++ setup.py | 96 +++++++++++++++++++++++++++ tailbone_wave/__init__.py | 27 ++++++++ tailbone_wave/_version.py | 3 + tailbone_wave/menus.py | 61 +++++++++++++++++ tailbone_wave/views/__init__.py | 0 tailbone_wave/views/wave/__init__.py | 32 +++++++++ tailbone_wave/views/wave/customers.py | 76 +++++++++++++++++++++ tailbone_wave/views/wave/invoices.py | 75 +++++++++++++++++++++ tailbone_wave/views/wave/master.py | 39 +++++++++++ tasks.py | 49 ++++++++++++++ 14 files changed, 486 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 MANIFEST.in create mode 100644 README.rst create mode 100644 setup.py create mode 100644 tailbone_wave/__init__.py create mode 100644 tailbone_wave/_version.py create mode 100644 tailbone_wave/menus.py create mode 100644 tailbone_wave/views/__init__.py create mode 100644 tailbone_wave/views/wave/__init__.py create mode 100644 tailbone_wave/views/wave/customers.py create mode 100644 tailbone_wave/views/wave/invoices.py create mode 100644 tailbone_wave/views/wave/master.py create mode 100644 tasks.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2df4548 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +tailbone_wave.egg-info/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..26ee2f7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ + +# Changelog +All notable changes to tailbone-wave will be documented in this file. + +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). + +## [0.1.0] - ?? +### Added +- Initial version. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..2397a56 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +include *.md +include *.rst +recursive-include tailbone_wave/templates *.mako diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..d712bf1 --- /dev/null +++ b/README.rst @@ -0,0 +1,14 @@ + +tailbone-wave +============= + +Rattail is a retail software framework, released under the GNU General +Public License. + +This package contains software interfaces for `Wave`_. + +.. _`Wave`: https://www.waveapps.com/ + +Please see the `Rattail Project`_ for more information. + +.. _`Rattail Project`: https://rattailproject.org/ diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..c776844 --- /dev/null +++ b/setup.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2022 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +tailbone-wave setup script +""" + +import os +from setuptools import setup, find_packages + + +here = os.path.abspath(os.path.dirname(__file__)) +exec(open(os.path.join(here, 'tailbone_wave', '_version.py')).read()) +README = open(os.path.join(here, 'README.rst')).read() + + +requires = [ + # + # Version numbers within comments below have specific meanings. + # Basically the 'low' value is a "soft low," and 'high' a "soft high." + # In other words: + # + # If either a 'low' or 'high' value exists, the primary point to be + # made about the value is that it represents the most current (stable) + # version available for the package (assuming typical public access + # methods) whenever this project was started and/or documented. + # Therefore: + # + # If a 'low' version is present, you should know that attempts to use + # versions of the package significantly older than the 'low' version + # may not yield happy results. (A "hard" high limit may or may not be + # indicated by a true version requirement.) + # + # Similarly, if a 'high' version is present, and especially if this + # project has laid dormant for a while, you may need to refactor a bit + # when attempting to support a more recent version of the package. (A + # "hard" low limit should be indicated by a true version requirement + # when a 'high' version is present.) + # + # In any case, developers and other users are encouraged to play + # outside the lines with regard to these soft limits. If bugs are + # encountered then they should be filed as such. + # + # package # low high + + 'invoke', # 1.5.0 + 'rattail-wave', # 0.1.0 + 'Tailbone', # 0.8.199 +] + + +setup( + name = "tailbone-wave", + version = __version__, + author = "Lance Edgar", + author_email = "lance@edbob.org", + url = "https://rattailproject.org/", + description = "Tailbone integration package for Wave", + long_description = README, + + classifiers = [ + 'Development Status :: 3 - Alpha', + 'Environment :: Web Environment', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Topic :: Office/Business', + 'Topic :: Software Development :: Libraries :: Python Modules', + ], + + install_requires = requires, + packages = find_packages(), + include_package_data = True, +) diff --git a/tailbone_wave/__init__.py b/tailbone_wave/__init__.py new file mode 100644 index 0000000..4ef1eba --- /dev/null +++ b/tailbone_wave/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2022 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +tailbone-wave package root +""" + +from ._version import __version__ diff --git a/tailbone_wave/_version.py b/tailbone_wave/_version.py new file mode 100644 index 0000000..e41b669 --- /dev/null +++ b/tailbone_wave/_version.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8; -*- + +__version__ = '0.1.0' diff --git a/tailbone_wave/menus.py b/tailbone_wave/menus.py new file mode 100644 index 0000000..dd7ab40 --- /dev/null +++ b/tailbone_wave/menus.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2022 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Common menus for Wave +""" + +from rattail_wave.config import get_wave_url + + +def make_wave_menu(request): + url = request.route_url + + wave_menu = { + 'title': "Wave", + 'type': 'menu', + 'items': [ + { + 'title': "Customers", + 'route': 'wave.customers', + 'perm': 'wave.customers.list', + }, + { + 'title': "Invoices", + 'route': 'wave.invoices', + 'perm': 'wave.invoices.list', + }, + ], + } + + wave_url = get_wave_url(request.rattail_config) + if wave_url: + wave_menu['items'].insert( + 0, { + 'title': "Go to Wave", + 'url': '{}/dashboard/'.format(wave_url), + 'target': '_blank', + }) + wave_menu['items'].insert( + 1, {'type': 'sep'}) + + return wave_menu diff --git a/tailbone_wave/views/__init__.py b/tailbone_wave/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tailbone_wave/views/wave/__init__.py b/tailbone_wave/views/wave/__init__.py new file mode 100644 index 0000000..2cdd483 --- /dev/null +++ b/tailbone_wave/views/wave/__init__.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2022 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Wave Views +""" + +from .master import WaveMasterView + + +def includeme(config): + config.include('tailbone_wave.views.wave.customers') + config.include('tailbone_wave.views.wave.invoices') diff --git a/tailbone_wave/views/wave/customers.py b/tailbone_wave/views/wave/customers.py new file mode 100644 index 0000000..19d2670 --- /dev/null +++ b/tailbone_wave/views/wave/customers.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2022 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Wave Client views +""" + +from rattail_wave.db.model import WaveCacheCustomer + +from .master import WaveMasterView + + +class WaveCustomerView(WaveMasterView): + """ + Master view for Wave Customers + """ + model_class = WaveCacheCustomer + url_prefix = '/wave/customers' + route_prefix = 'wave.customers' + + labels = { + 'internal_id': "Internal ID", + } + + grid_columns = [ + 'name', + 'email', + 'is_archived', + 'modified_at', + ] + + def configure_grid(self, g): + super(WaveCustomerView, self).configure_grid(g) + + g.filters['name'].default_active = True + g.filters['name'].default_verb = 'contains' + + g.set_sort_defaults('name') + + g.set_link('name') + g.set_link('email') + + def configure_form(self, f): + super(WaveCustomerView, self).configure_form(f) + + f.remove_field('invoices') + + +def defaults(config, **kwargs): + base = globals() + + WaveCustomerView = kwargs.get('WaveCustomerView', base['WaveCustomerView']) + WaveCustomerView.defaults(config) + + +def includeme(config): + defaults(config) diff --git a/tailbone_wave/views/wave/invoices.py b/tailbone_wave/views/wave/invoices.py new file mode 100644 index 0000000..30fbd57 --- /dev/null +++ b/tailbone_wave/views/wave/invoices.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2022 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Wave Client views +""" + +from rattail_wave.db.model import WaveCacheInvoice + +from .master import WaveMasterView + + +class WaveInvoiceView(WaveMasterView): + """ + Master view for Wave Invoices + """ + model_class = WaveCacheInvoice + url_prefix = '/wave/invoices' + route_prefix = 'wave.invoices' + + grid_columns = [ + 'title', + 'customer', + 'invoice_date', + 'total', + 'status', + 'modified_at', + ] + + def configure_grid(self, g): + super(WaveInvoiceView, self).configure_grid(g) + model = self.model + + g.set_joiner('customer', lambda q: q.join(model.WaveCacheCustomer)) + g.set_sorter('customer', model.WaveCacheCustomer.name) + g.set_filter('customer', model.WaveCacheCustomer.name, + label="Customer Name", + default_active=True, default_verb='contains') + + g.set_type('total', 'currency') + + g.set_sort_defaults('modified_at', 'desc') + + g.set_link('customer') + g.set_link('invoice_date') + + +def defaults(config, **kwargs): + base = globals() + + WaveInvoiceView = kwargs.get('WaveInvoiceView', base['WaveInvoiceView']) + WaveInvoiceView.defaults(config) + + +def includeme(config): + defaults(config) diff --git a/tailbone_wave/views/wave/master.py b/tailbone_wave/views/wave/master.py new file mode 100644 index 0000000..a1fc3c3 --- /dev/null +++ b/tailbone_wave/views/wave/master.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2022 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Wave master view +""" + +from tailbone.views import MasterView + + +class WaveMasterView(MasterView): + """ + Base class for Wave cache tables + """ + has_versions = True + + labels = { + 'id': "ID", + 'internal_id': "Internal ID", + } diff --git a/tasks.py b/tasks.py new file mode 100644 index 0000000..8503016 --- /dev/null +++ b/tasks.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2022 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Tasks for tailbone-wave +""" + +import os +import shutil + +from invoke import task + + +here = os.path.abspath(os.path.dirname(__file__)) +exec(open(os.path.join(here, 'tailbone_wave', '_version.py')).read()) + + +@task +def release(c): + """ + Release a new version of tailbone-wave + """ + # rebuild local tar.gz file for distribution + if os.path.exists('tailbone_wave.egg-info'): + shutil.rmtree('tailbone_wave.egg-info') + c.run('python -m build --sdist') + + # upload to public PyPI + filename = 'tailbone-wave-{}.tar.gz'.format(__version__) + c.run('twine upload dist/{}'.format(filename))