From fc89558472e4fd96aeb278b06e380b1af669941f Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 18 Jan 2023 15:21:06 -0600 Subject: [PATCH] Add support for new-style `theo install` command also use upstream menus where possible --- dev/web.conf | 1 + setup.py | 12 +- theo/commands.py | 65 +++++++++ theo/config.py | 4 +- theo/web/menus.py | 328 +++++----------------------------------------- 5 files changed, 110 insertions(+), 300 deletions(-) create mode 100644 theo/commands.py diff --git a/dev/web.conf b/dev/web.conf index f95690a..b3d105f 100644 --- a/dev/web.conf +++ b/dev/web.conf @@ -43,6 +43,7 @@ use = egg:waitress#main # to bind to all interfaces, set host to 0.0.0.0 host = 127.0.0.1 port = 9080 +trusted_proxy = 127.0.0.1 ############################## diff --git a/setup.py b/setup.py index f9bc985..aece41b 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2022 Lance Edgar +# Copyright © 2010-2023 Lance Edgar # # This file is part of Rattail. # @@ -78,7 +78,7 @@ extras = { 'invoke', # 1.4.1 'mysql-connector-python', 'psycopg2', # 2.8.5 - 'rattail[db,auth,bouncer]', # 0.9.130 + 'rattail[db,bouncer]', # 0.9.130 'Tailbone', # 0.8.97 ], @@ -151,6 +151,10 @@ setup( entry_points = { + 'console_scripts': [ + 'theo = theo.commands:main', + ], + 'rattail.config.extensions': [ 'theo = theo.config:TheoConfig', ], @@ -168,5 +172,9 @@ setup( 'main = theo.web.app:main', 'webapi = theo.web.webapi:main', ], + + 'theo.commands': [ + 'install = theo.commands:Install', + ], }, ) diff --git a/theo/commands.py b/theo/commands.py new file mode 100644 index 0000000..4d6e879 --- /dev/null +++ b/theo/commands.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Theo commands +""" + +import sys + +from rattail import commands + +from theo import __version__ + + +def main(*args): + """ + Main entry point for Theo command system + """ + args = list(args or sys.argv[1:]) + cmd = Command() + cmd.run(*args) + + +class Command(commands.Command): + """ + Main command for Theo + """ + name = 'theo' + version = __version__ + description = "Theo, the order system" + long_description = '' + + +class Install(commands.InstallSubcommand): + """ + Install the Theo app + """ + name = 'install' + description = __doc__.strip() + + # nb. these must be explicitly set b/c config is not available + # when running normally, e.g. `theo -n install` + app_title = "Theo" + app_package = 'theo' + app_eggname = 'tailbone_theo' + app_pypiname = 'tailbone-theo' diff --git a/theo/config.py b/theo/config.py index 527b2dc..ceb7161 100644 --- a/theo/config.py +++ b/theo/config.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2021 Lance Edgar +# Copyright © 2010-2023 Lance Edgar # # This file is part of Rattail. # @@ -39,7 +39,7 @@ class TheoConfig(ConfigExtension): config.setdefault('rattail', 'app_title', "Theo") # Theo comes with its own menu for web app - config.setdefault('tailbone', 'menus', 'theo.web.menus') + config.setdefault('tailbone.menus', 'handler', 'theo.web.menus:TheoMenuHandler') # Trainwreck model is same regardless of POS config.setdefault('rattail.trainwreck', 'model', 'rattail.trainwreck.db.model.defaults') diff --git a/theo/web/menus.py b/theo/web/menus.py index 8bff5c7..780c439 100644 --- a/theo/web/menus.py +++ b/theo/web/menus.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2022 Lance Edgar +# Copyright © 2010-2023 Lance Edgar # # This file is part of Rattail. # @@ -24,310 +24,46 @@ Web Menus """ +from tailbone import menus as base + from theo.config import integrate_catapult, integrate_corepos, integrate_locsms -def simple_menus(request): - url = request.route_url - rattail_config = request.rattail_config +class TheoMenuHandler(base.MenuHandler): + """ + Theo menu handler + """ - include_catapult = integrate_catapult(rattail_config) - include_corepos = integrate_corepos(rattail_config) - include_locsms = integrate_locsms(rattail_config) + def make_menus(self, request, **kwargs): - orders_menu = { - 'title': "Orders", - 'type': 'menu', - 'items': [ - { - 'title': "New Customer Order", - 'route': 'custorders.create', - 'perm': 'custorders.create', - }, - { - 'title': "All New Orders", - 'route': 'new_custorders', - 'perm': 'new_custorders.list', - }, - {'type': 'sep'}, - { - 'title': "All Customer Orders", - 'route': 'custorders', - 'perm': 'custorders.list', - }, - { - 'title': "All Order Items", - 'route': 'custorders.items', - 'perm': 'custorders.items.list', - }, - ], - } + menus = [ + self.make_custorders_menu(request), + self.make_people_menu(request), + self.make_products_menu(request), + self.make_vendors_menu(request), + ] - people_menu = { - 'title': "People", - 'type': 'menu', - 'items': [ - { - 'title': "Members", - 'route': 'members', - 'perm': 'members.list', - }, - { - 'title': "Customers", - 'route': 'customers', - 'perm': 'customers.list', - }, - { - 'title': "Employees", - 'route': 'employees', - 'perm': 'employees.list', - }, - { - 'title': "All People", - 'route': 'people', - 'perm': 'people.list', - }, - {'type': 'sep'}, - { - 'title': "Pending Customers", - 'route': 'pending_customers', - 'perm': 'pending_customers.list', - }, - ], - } + # TODO: pretty sure this should handle things? + # TODO: ..if so then 100% upstream menu should work here? + # integration_menus = self.make_integration_menus(request) + # if integration_menus: + # menus.extend(integration_menus) - products_menu = { - 'title': "Products", - 'type': 'menu', - 'items': [ - { - 'title': "Products", - 'route': 'products', - 'perm': 'products.list', - }, - { - 'title': "Departments", - 'route': 'departments', - 'perm': 'departments.list', - }, - { - 'title': "Subdepartments", - 'route': 'subdepartments', - 'perm': 'subdepartments.list', - }, - { - 'title': "Brands", - 'route': 'brands', - 'perm': 'brands.list', - }, - { - 'title': "Taxes", - 'route': 'taxes', - 'perm': 'taxes.list', - }, - { - 'title': "Units of Measure", - 'route': 'uoms', - 'perm': 'uoms.list', - }, - {'type': 'sep'}, - { - 'title': "Pending Products", - 'route': 'pending_products', - 'perm': 'pending_products.list', - }, - ], - } + if integrate_catapult(self.config): + from tailbone_onager.menus import make_catapult_menu + menus.append(make_catapult_menu(request)) - vendors_menu = { - 'title': "Vendors", - 'type': 'menu', - 'items': [ - { - 'title': "Vendors", - 'route': 'vendors', - 'perm': 'vendors.list', - }, - {'type': 'sep'}, - { - 'title': "Ordering", - 'route': 'ordering', - 'perm': 'ordering.list', - }, - { - 'title': "Receiving", - 'route': 'receiving', - 'perm': 'receiving.list', - }, - {'type': 'sep'}, - { - 'title': "Purchases", - 'route': 'purchases', - 'perm': 'purchases.list', - }, - { - 'title': "Credits", - 'route': 'purchases.credits', - 'perm': 'purchases.credits.list', - }, - {'type': 'sep'}, - { - 'title': "Catalog Batches", - 'route': 'vendorcatalogs', - 'perm': 'vendorcatalogs.list', - }, - ], - } - - if include_catapult: - from tailbone_onager.menus import make_catapult_menu - catapult_menu = make_catapult_menu(request) - - if include_corepos: - corepos_menu = None - from tailbone.util import should_use_buefy - if should_use_buefy(request): + if integrate_corepos(self.config): from tailbone_corepos.menus import make_corepos_menu - corepos_menu = make_corepos_menu(request) + menus.append(make_corepos_menu(request)) - if include_locsms: - from tailbone_locsms.menus import make_locsms_menu - locsms_menu = make_locsms_menu(request) + if integrate_locsms(self.config): + from tailbone_locsms.menus import make_locsms_menu + menus.append(make_locsms_menu(request)) - ############################## - # Reporting - ############################## + menus.extend([ + self.make_reports_menu(request, include_trainwreck=True), + self.make_admin_menu(request, include_stores=True), + ]) - reporting_menu = { - 'title': "Reporting", - 'type': 'menu', - 'items': [ - { - 'title': "New Report", - 'route': 'report_output.create', - 'perm': 'report_output.create', - }, - { - 'title': "Generated Reports", - 'route': 'report_output', - 'perm': 'report_output.list', - }, - {'type': 'sep'}, - { - 'title': "Trainwreck", - 'route': 'trainwreck.transactions', - 'perm': 'trainwreck.transactions.list', - }, - {'type': 'sep'}, - { - 'title': "Problem Reports", - 'route': 'problem_reports', - 'perm': 'problem_reports.list', - }, - ], - } - - admin_menu = { - 'title': "Admin", - 'type': 'menu', - 'items': [ - { - 'title': "Stores", - 'route': 'stores', - 'perm': 'stores.list', - }, - { - 'title': "Users", - 'route': 'users', - 'perm': 'users.list', - }, - { - 'title': "User Events", - 'route': 'userevents', - 'perm': 'userevents.list', - }, - { - 'title': "Roles", - 'route': 'roles', - 'perm': 'roles.list', - }, - { - 'title': "Raw Permissions", - 'route': 'permissions', - 'perm': 'permissions.list', - }, - {'type': 'sep'}, - { - 'title': "App Settings", - 'route': 'appsettings', - 'perm': 'settings.list', - }, - { - 'title': "Email Settings", - 'route': 'emailprofiles', - 'perm': 'emailprofiles.list', - }, - { - 'title': "Email Attempts", - 'route': 'email_attempts', - 'perm': 'email_attempts.list', - }, - { - 'title': "Raw Settings", - 'route': 'settings', - 'perm': 'settings.list', - }, - {'type': 'sep'}, - { - 'title': "DataSync Changes", - 'route': 'datasyncchanges', - 'perm': 'datasync_changes.list', - }, - { - 'title': "DataSync Status", - 'route': 'datasync.status', - 'perm': 'datasync.status', - }, - { - 'title': "Importing / Exporting", - 'route': 'importing', - 'perm': 'importing.list', - }, - { - 'title': "Luigi Tasks", - 'route': 'luigi', - 'perm': 'luigi.list', - }, - { - 'title': "Tables", - 'route': 'tables', - 'perm': 'tables.list', - }, - { - 'title': "Upgrades", - 'route': 'upgrades', - 'perm': 'upgrades.list', - }, - ], - } - - menus = [ - orders_menu, - people_menu, - products_menu, - vendors_menu, - ] - - if include_catapult: - menus.append(catapult_menu) - if include_corepos and corepos_menu: - menus.append(corepos_menu) - if include_locsms: - menus.append(locsms_menu) - - menus.extend([ - reporting_menu, - admin_menu, - ]) - - return menus + return menus