From 17d009942928e3c0340ae9d4edc3cd6a54ad4fbe Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 3 Jan 2026 16:05:59 -0600 Subject: [PATCH] add button to install sample data, for root user only sample data is very minimal but probably we need to ship that separate to give a more complete sample. this is better than nothing for now. --- src/wuttapos/sample-data/Customer.csv | 4 + src/wuttapos/sample-data/Department.csv | 3 + src/wuttapos/sample-data/Employee.csv | 2 + .../sample-data/InventoryAdjustmentType.csv | 4 + src/wuttapos/sample-data/Person.csv | 4 + src/wuttapos/sample-data/Product.csv | 3 + src/wuttapos/sample-data/Store.csv | 2 + src/wuttapos/sample-data/Tax.csv | 3 + src/wuttapos/sample-data/Tender.csv | 4 + src/wuttapos/sample-data/Terminal.csv | 2 + .../server/templates/appinfo/index.mako | 38 ++++++ src/wuttapos/server/views/__init__.py | 6 +- src/wuttapos/server/views/settings.py | 120 ++++++++++++++++++ 13 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 src/wuttapos/sample-data/Customer.csv create mode 100644 src/wuttapos/sample-data/Department.csv create mode 100644 src/wuttapos/sample-data/Employee.csv create mode 100644 src/wuttapos/sample-data/InventoryAdjustmentType.csv create mode 100644 src/wuttapos/sample-data/Person.csv create mode 100644 src/wuttapos/sample-data/Product.csv create mode 100644 src/wuttapos/sample-data/Store.csv create mode 100644 src/wuttapos/sample-data/Tax.csv create mode 100644 src/wuttapos/sample-data/Tender.csv create mode 100644 src/wuttapos/sample-data/Terminal.csv create mode 100644 src/wuttapos/server/templates/appinfo/index.mako create mode 100644 src/wuttapos/server/views/settings.py diff --git a/src/wuttapos/sample-data/Customer.csv b/src/wuttapos/sample-data/Customer.csv new file mode 100644 index 0000000..d5a2e17 --- /dev/null +++ b/src/wuttapos/sample-data/Customer.csv @@ -0,0 +1,4 @@ +uuid,customer_id,name,account_holder_uuid,phone_number,email_address +06958b42-e542-7914-8000-841155e871ba,001,Fred Flintstone,06958b40-8610-7caa-8000-28c14769a3f5,, +06958b43-5daf-7af5-8000-7fe6c8e19b73,002,Barney Rubble,06958b40-23ee-7eba-8000-7a6081601e4c,, +06958b43-d443-7fb0-8000-5585fb86c3ce,003,Betty Boop,06958b40-f601-7a3c-8000-638088595cea,, diff --git a/src/wuttapos/sample-data/Department.csv b/src/wuttapos/sample-data/Department.csv new file mode 100644 index 0000000..ee03530 --- /dev/null +++ b/src/wuttapos/sample-data/Department.csv @@ -0,0 +1,3 @@ +uuid,department_id,name,for_products,for_personnel,exempt_from_gross_sales +06958b44-cc3c-7b56-8000-997dd91c0d51,01,Grocery,True,False,False +06958b45-8bb4-79ed-8000-e61ebf1d545d,02,Books,True,False,False diff --git a/src/wuttapos/sample-data/Employee.csv b/src/wuttapos/sample-data/Employee.csv new file mode 100644 index 0000000..39b0123 --- /dev/null +++ b/src/wuttapos/sample-data/Employee.csv @@ -0,0 +1,2 @@ +uuid,person_uuid,name,public_name,active +06958b42-17ae-78bd-8000-56322ad38684,06958b40-8610-7caa-8000-28c14769a3f5,Fred Flintstone,,True diff --git a/src/wuttapos/sample-data/InventoryAdjustmentType.csv b/src/wuttapos/sample-data/InventoryAdjustmentType.csv new file mode 100644 index 0000000..aca45d8 --- /dev/null +++ b/src/wuttapos/sample-data/InventoryAdjustmentType.csv @@ -0,0 +1,4 @@ +uuid,type_code,name +06958b49-eee0-7a8e-8000-8fa8d1648d55,1,Manual +06958b4a-7e73-7443-8000-c9a826760dbd,2,Receiving +06958b4a-c9b8-736d-8000-ee9974208f34,3,Sales diff --git a/src/wuttapos/sample-data/Person.csv b/src/wuttapos/sample-data/Person.csv new file mode 100644 index 0000000..2a6444c --- /dev/null +++ b/src/wuttapos/sample-data/Person.csv @@ -0,0 +1,4 @@ +uuid,full_name,first_name,middle_name,last_name +06958b40-23ee-7eba-8000-7a6081601e4c,Barney Rubble,Barney,,Rubble +06958b40-8610-7caa-8000-28c14769a3f5,Fred Flintstone,Fred,,Flintstone +06958b40-f601-7a3c-8000-638088595cea,Betty Boop,Betty,,Boop diff --git a/src/wuttapos/sample-data/Product.csv b/src/wuttapos/sample-data/Product.csv new file mode 100644 index 0000000..1e66aca --- /dev/null +++ b/src/wuttapos/sample-data/Product.csv @@ -0,0 +1,3 @@ +uuid,product_id,brand_name,description,size,sold_by_weight,department_uuid,special_order,case_size,unit_cost,unit_price_reg,notes +06958b47-6c11-7bf9-8000-d47cf9ecabbd,07430500132,Bragg's,Apple Cider Vinegar,32oz,False,06958b44-cc3c-7b56-8000-997dd91c0d51,False,12.0000,3.99000,5.990,This is what notes look like for a product. +06958b49-46ce-7ded-8000-f5e2504ccb81,07430500116,Bragg's,Apple Cider Vinegar,16oz,False,06958b44-cc3c-7b56-8000-997dd91c0d51,False,12.0000,2.79000,4.490, diff --git a/src/wuttapos/sample-data/Store.csv b/src/wuttapos/sample-data/Store.csv new file mode 100644 index 0000000..b09d874 --- /dev/null +++ b/src/wuttapos/sample-data/Store.csv @@ -0,0 +1,2 @@ +uuid,store_id,name,active +06958b38-22d3-79c4-8000-5ac6198dee37,001,Main Store,True diff --git a/src/wuttapos/sample-data/Tax.csv b/src/wuttapos/sample-data/Tax.csv new file mode 100644 index 0000000..2b3329f --- /dev/null +++ b/src/wuttapos/sample-data/Tax.csv @@ -0,0 +1,3 @@ +uuid,tax_id,name,rate +06958b3c-c350-7820-8000-0650492afa09,1,Food,3.00000 +06958b3d-3d8a-7ae4-8000-461c96456694,2,Non-Food,5.00000 diff --git a/src/wuttapos/sample-data/Tender.csv b/src/wuttapos/sample-data/Tender.csv new file mode 100644 index 0000000..73dba8e --- /dev/null +++ b/src/wuttapos/sample-data/Tender.csv @@ -0,0 +1,4 @@ +uuid,tender_id,name,notes,is_cash,is_foodstamp,allow_cashback,kick_drawer,active +06958b39-d29b-7f62-8000-914f55432288,CASH,Cash,,True,False,True,True,True +06958b3a-906d-7d16-8000-369bde264e74,CHECK,Check,,False,False,False,True,True +06958b3b-bd36-765e-8000-b68a1d64a8de,FS,Food Stamps,,False,True,False,False,True diff --git a/src/wuttapos/sample-data/Terminal.csv b/src/wuttapos/sample-data/Terminal.csv new file mode 100644 index 0000000..4f498ff --- /dev/null +++ b/src/wuttapos/sample-data/Terminal.csv @@ -0,0 +1,2 @@ +uuid,terminal_id,name +06958b39-0ef2-72f1-8000-24b87acb7c6d,099,Test Terminal diff --git a/src/wuttapos/server/templates/appinfo/index.mako b/src/wuttapos/server/templates/appinfo/index.mako new file mode 100644 index 0000000..f674138 --- /dev/null +++ b/src/wuttapos/server/templates/appinfo/index.mako @@ -0,0 +1,38 @@ +## -*- coding: utf-8; -*- +<%inherit file="wuttaweb:templates/appinfo/index.mako" /> + +<%def name="middle_buttons()"> + ${parent.middle_buttons()} + + % if request.is_root: + + {{ installingSampleData ? "Working, please wait..." : "Install Sample Data" }} + + ${h.form(request.route_url(f"{route_prefix}.install_sample_data"), ref="installSampleDataForm")} + ${h.csrf_token(request)} + ${h.end_form()} + % endif + + +<%def name="modify_vue_vars()"> + ${parent.modify_vue_vars()} + + % if request.is_root: + + % endif + diff --git a/src/wuttapos/server/views/__init__.py b/src/wuttapos/server/views/__init__.py index f25671c..60cf2b9 100644 --- a/src/wuttapos/server/views/__init__.py +++ b/src/wuttapos/server/views/__init__.py @@ -31,7 +31,11 @@ def includeme(config): # wuttaweb essential.defaults( - config, **{"wuttaweb.views.common": "wuttapos.server.views.common"} + config, + **{ + "wuttaweb.views.common": "wuttapos.server.views.common", + "wuttaweb.views.settings": "wuttapos.server.views.settings", + } ) # wuttapos diff --git a/src/wuttapos/server/views/settings.py b/src/wuttapos/server/views/settings.py new file mode 100644 index 0000000..c33b335 --- /dev/null +++ b/src/wuttapos/server/views/settings.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# WuttaPOS -- Point of Sale system based on Wutta Framework +# Copyright © 2026 Lance Edgar +# +# This file is part of WuttaPOS. +# +# WuttaPOS 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. +# +# WuttaPOS 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 +# WuttaPOS. If not, see . +# +################################################################################ +""" +Views for app settings +""" + +import glob +import os +import logging + +from wuttaweb.views import settings as base + + +log = logging.getLogger(__name__) + + +class AppInfoView(base.AppInfoView): + """ + We override this view to add the :meth:`install_sample_data()` route. + + See also parent docs, :class:`~wuttaweb:wuttaweb.views.settings.AppInfoView` + """ + + def install_sample_data(self): + """ + Special view to install sample data. Probably just temporary until + something better can be worked out... + + Requires root access; imports (create only) from small CSV + files within the WuttaPOS code base. + """ + + # only root gets to do this + if not self.request.is_root: + raise self.forbidden() + + # we can't (yet?) tell the importer to import "everything" + # because it will think that means "all models" as opposed to + # "all files" found, and that raises error for missing files. + # so we first inspect the folder to see what's there. + models = [] + samples = self.app.resource_path("wuttapos:sample-data") + # nb. should use root_dir param for glob() but requires python 3.10 + for path in glob.glob(os.path.join(samples, "*.csv")): + name, ext = os.path.splitext(os.path.basename(path)) + models.append(name) + + # import all CSV files found in wuttapos/sample-data, but only + # allow new records to be created, never update/delete + try: + handler = self.app.get_import_handler("import.to_wutta.from_csv") + models = [name for name in models if name in handler.importers] + kw = dict(input_file_path=samples, allow_update=False, allow_delete=False) + handler.process_data(*models, **kw) + except Exception as err: + log.warning("failed to install sample data", exc_info=True) + self.request.session.flash( + f"Install failed: {self.app.render_error(err)}", "error" + ) + else: + self.request.session.flash("Sample data has been installed.") + + return self.redirect(self.get_index_url()) + + @classmethod + def defaults(cls, config): # pylint: disable=empty-docstring + """ """ + cls._defaults(config) + cls._appinfo_defaults(config) + cls._wuttapos_defaults(config) + + @classmethod + def _wuttapos_defaults(cls, config): + route_prefix = cls.get_route_prefix() + permission_prefix = cls.get_permission_prefix() + url_prefix = cls.get_url_prefix() + + # install sample data + config.add_route( + f"{route_prefix}.install_sample_data", + f"{url_prefix}/install-sample-data", + request_method="POST", + ) + config.add_view( + cls, + attr="install_sample_data", + route_name=f"{route_prefix}.install_sample_data", + ) + + +def defaults(config, **kwargs): # pylint: disable=missing-function-docstring + local = globals() + + AppInfoView = kwargs.get("AppInfoView", local["AppInfoView"]) + + base.defaults(config, **{"AppInfoView": AppInfoView}) + + +def includeme(config): # pylint: disable=missing-function-docstring + defaults(config)