Compare commits
No commits in common. "960dbfdee6835d16b67396c13ecaa34ae6ab007a" and "d6c1e688b165307facdb48145df1fa1b147ffdbd" have entirely different histories.
960dbfdee6
...
d6c1e688b1
7 changed files with 21 additions and 214 deletions
|
|
@ -5,12 +5,6 @@ All notable changes to WuttaPOS 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.4.1 (2026-01-03)
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
- add basic support for install/setup of terminal
|
|
||||||
|
|
||||||
## v0.4.0 (2026-01-03)
|
## v0.4.0 (2026-01-03)
|
||||||
|
|
||||||
First release under the new project.
|
First release under the new project.
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ For now this only describes a *development* setup, which assumes the following:
|
||||||
* Python 3.11 or newer
|
* Python 3.11 or newer
|
||||||
* database in PostgreSQL or MySQL
|
* database in PostgreSQL or MySQL
|
||||||
|
|
||||||
These steps will setup both the Server and Terminal in a shared
|
These steps will setup both the server and terminal in a shared
|
||||||
virtual environment.
|
virtual environment.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -40,13 +40,13 @@ Install Server
|
||||||
|
|
||||||
**Please note, you must create your database before running the installer.**
|
**Please note, you must create your database before running the installer.**
|
||||||
|
|
||||||
Run the WuttaPOS installer to setup the Server app:
|
Run the WuttaPOS installer to setup the server app:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
bin/wuttapos install
|
bin/wuttapos install
|
||||||
|
|
||||||
Now you can run the Server app via command line:
|
Now you can run the server app via command line:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
|
|
@ -86,48 +86,4 @@ should be improved - but that will come later.
|
||||||
Install Terminal
|
Install Terminal
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
**Please note, this assumes you already installed the Server as described above.**
|
TODO: this is not yet documented
|
||||||
|
|
||||||
For now, we'll just install the Terminal alongside the Server. They
|
|
||||||
will share the same virtual environment, installed code, app database,
|
|
||||||
and "most of" the config files.
|
|
||||||
|
|
||||||
So within your virtual environment, run the same installer again:
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
bin/wuttapos install
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
You will be asked for store and terminal IDs - these should be
|
|
||||||
valid and refer to actual records for those types, within the
|
|
||||||
database. See the Admin menu of the Server web app to manage those
|
|
||||||
records.
|
|
||||||
|
|
||||||
At this point the Terminal app should be ready to go. To run the
|
|
||||||
standalone GUI:
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
bin/wuttapos -c app/terminal.conf run
|
|
||||||
|
|
||||||
You will need to login; the POS uses a special set of permissions but
|
|
||||||
the first admin user should already have all that are needed. So just
|
|
||||||
login using same credentials as for the Server app.
|
|
||||||
|
|
||||||
It's also possible (due to the magic of Flet/Flutter) to *serve* the
|
|
||||||
Terminal as a web app:
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
bin/wuttapos -c app/terminal.conf serve
|
|
||||||
|
|
||||||
In that case (by default) you can browse it at http://localhost:8332
|
|
||||||
|
|
||||||
That might be useful for online demo purposes etc. but definitely the
|
|
||||||
intention is to run as standalone GUI for production. (However the
|
|
||||||
story around tablets is TBD.)
|
|
||||||
|
|
||||||
For now, running as a web service like that is not a supported
|
|
||||||
feature.
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ build-backend = "hatchling.build"
|
||||||
name = "WuttaPOS"
|
name = "WuttaPOS"
|
||||||
# nb. 0.3.0 was the last release of the previous rattail WuttaPOS app.
|
# nb. 0.3.0 was the last release of the previous rattail WuttaPOS app.
|
||||||
# pretty sure this will bump to 0.4.0 and then i can remove this note.
|
# pretty sure this will bump to 0.4.0 and then i can remove this note.
|
||||||
version = "0.4.1"
|
version = "0.4.0"
|
||||||
description = "Point of Sale system based on Wutta Framework"
|
description = "Point of Sale system based on Wutta Framework"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
|
authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
|
||||||
|
|
@ -32,7 +32,7 @@ classifiers = [
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"psycopg2",
|
"psycopg2",
|
||||||
"WuttJamaican[db]>=0.28.4",
|
"WuttJamaican[db]>=0.28.2",
|
||||||
"WuttaSync",
|
"WuttaSync",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@
|
||||||
See also: :ref:`wuttapos-run`
|
See also: :ref:`wuttapos-run`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import typer
|
import typer
|
||||||
|
|
||||||
from wuttapos.cli import wuttapos_typer
|
from wuttapos.cli import wuttapos_typer
|
||||||
|
|
@ -39,11 +37,4 @@ def run(ctx: typer.Context):
|
||||||
from wuttapos.terminal.app import run_app
|
from wuttapos.terminal.app import run_app
|
||||||
|
|
||||||
config = ctx.parent.wutta_config
|
config = ctx.parent.wutta_config
|
||||||
|
run_app(config)
|
||||||
# nb. it does not seem possible (?) to inject our config when
|
|
||||||
# launching the Flet app, which means it will create a *separate*
|
|
||||||
# config for itself..this should ensure it has the right settings.
|
|
||||||
# see also notes in wuttapos.terminal.app module, for run_app()
|
|
||||||
os.environ["WUTTA_CONFIG_FILES"] = os.pathsep.join(config.get_prioritized_files())
|
|
||||||
|
|
||||||
run_app()
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
Install handler for WuttaPOS
|
Install handler for WuttaPOS
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -38,62 +37,14 @@ class InstallHandler(base.InstallHandler):
|
||||||
|
|
||||||
template_paths = ["wuttapos:installer-templates"]
|
template_paths = ["wuttapos:installer-templates"]
|
||||||
|
|
||||||
store_id = None
|
|
||||||
terminal_id = None
|
|
||||||
alongside = False
|
|
||||||
|
|
||||||
def do_install_steps(self):
|
def do_install_steps(self):
|
||||||
|
|
||||||
# prompt for install type first
|
# prompt for install type first
|
||||||
self.get_install_type()
|
self.get_install_type()
|
||||||
|
|
||||||
# install server/terminal dependencies
|
|
||||||
self.install_app_deps()
|
|
||||||
|
|
||||||
# then everything else
|
# then everything else
|
||||||
super().do_install_steps()
|
super().do_install_steps()
|
||||||
|
|
||||||
def sanity_check(self):
|
|
||||||
"""
|
|
||||||
We override this because the normal up-front sanity check
|
|
||||||
includes a check for the app dir. But we need to delay that
|
|
||||||
one a bit, so behavior depends on which "install type" we're
|
|
||||||
doing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def check_appdir(self):
|
|
||||||
"""
|
|
||||||
We bypass the normal check here, if the current install is for
|
|
||||||
terminal alongside server.
|
|
||||||
"""
|
|
||||||
if self.install_type == "terminal":
|
|
||||||
|
|
||||||
# does appdir exist yet?
|
|
||||||
appdir = os.path.join(sys.prefix, "app")
|
|
||||||
if os.path.exists(appdir):
|
|
||||||
|
|
||||||
# install alongside server?
|
|
||||||
self.alongside = self.prompt_bool(
|
|
||||||
"install alongside server?", default=False
|
|
||||||
)
|
|
||||||
if self.alongside:
|
|
||||||
# this mode expects the appdir to exist, so continue
|
|
||||||
return
|
|
||||||
|
|
||||||
else:
|
|
||||||
# no appdir - means we should install "everything" for
|
|
||||||
# the terminal, but we don't support that yet
|
|
||||||
self.rprint(
|
|
||||||
f"\n\t[bold red]sorry, full terminal install not yet supported[/bold red]\n"
|
|
||||||
)
|
|
||||||
self.rprint(
|
|
||||||
f"\n\tPlease install the server, then terminal alongside that.\n"
|
|
||||||
)
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
# do normal check
|
|
||||||
super().check_appdir()
|
|
||||||
|
|
||||||
def get_install_type(self):
|
def get_install_type(self):
|
||||||
|
|
||||||
# prompt user
|
# prompt user
|
||||||
|
|
@ -104,88 +55,22 @@ class InstallHandler(base.InstallHandler):
|
||||||
# remember the answer
|
# remember the answer
|
||||||
self.install_type = install_type
|
self.install_type = install_type
|
||||||
|
|
||||||
# now we can check the app dir; do this before further questions
|
if self.install_type != "server":
|
||||||
self.check_appdir()
|
|
||||||
|
|
||||||
# stop here for server, but we have more questions for terminal
|
|
||||||
if self.install_type == "server":
|
|
||||||
return
|
|
||||||
|
|
||||||
self.rprint(
|
self.rprint(
|
||||||
"\n\n\t[blue]Next you must specify the Store and Terminal IDs.[/blue]"
|
"[bold red]sorry, terminal install is not yet implemented[/bold red]\n"
|
||||||
)
|
|
||||||
self.rprint(
|
|
||||||
"\n\tThese should match records in your DB; see the Server app for info.\n"
|
|
||||||
)
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# store_id
|
# install dependencies
|
||||||
while not self.store_id:
|
|
||||||
self.store_id = self.prompt_generic("Store ID")
|
|
||||||
|
|
||||||
# terminal_id
|
|
||||||
while not self.terminal_id:
|
|
||||||
self.terminal_id = self.prompt_generic("Terminal ID")
|
|
||||||
|
|
||||||
def install_app_deps(self):
|
|
||||||
|
|
||||||
if self.install_type == "server":
|
if self.install_type == "server":
|
||||||
|
self.install_server_deps()
|
||||||
|
|
||||||
|
def install_server_deps(self):
|
||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
[sys.executable, "-m", "pip", "install", "WuttaPOS[server]"]
|
[sys.executable, "-m", "pip", "install", "WuttaPOS[server]"]
|
||||||
)
|
)
|
||||||
|
|
||||||
elif self.install_type == "terminal":
|
|
||||||
subprocess.check_call(
|
|
||||||
[sys.executable, "-m", "pip", "install", "WuttaPOS[terminal]"]
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_dbinfo(self):
|
|
||||||
if self.alongside:
|
|
||||||
return {"dburl": self.config.appdb_engine.url}
|
|
||||||
|
|
||||||
return super().get_dbinfo()
|
|
||||||
|
|
||||||
def make_template_context(self, dbinfo, **kwargs):
|
def make_template_context(self, dbinfo, **kwargs):
|
||||||
context = super().make_template_context(dbinfo, **kwargs)
|
context = super().make_template_context(dbinfo, **kwargs)
|
||||||
|
|
||||||
context["install_type"] = self.install_type
|
context["install_type"] = self.install_type
|
||||||
context["store_id"] = self.store_id
|
|
||||||
context["terminal_id"] = self.terminal_id
|
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def write_all_config_files(self, appdir, context):
|
|
||||||
if self.alongside:
|
|
||||||
# just want to add terminal.conf for this mode
|
|
||||||
self.write_terminal_conf(appdir, context)
|
|
||||||
return
|
|
||||||
|
|
||||||
# new app, so write normal files
|
|
||||||
super().write_all_config_files(appdir, context)
|
|
||||||
|
|
||||||
def write_terminal_conf(self, appdir, context):
|
|
||||||
term_context = dict(context)
|
|
||||||
self.make_config_file(
|
|
||||||
"terminal.conf.mako", os.path.join(appdir, "terminal.conf"), **term_context
|
|
||||||
)
|
|
||||||
|
|
||||||
def install_db_schema(self, db_url, appdir=None):
|
|
||||||
if self.alongside:
|
|
||||||
# no need to install schema here
|
|
||||||
return False
|
|
||||||
|
|
||||||
return super().install_db_schema(db_url, appdir=appdir)
|
|
||||||
|
|
||||||
def show_goodbye(self):
|
|
||||||
"""
|
|
||||||
Show the final message; this assumes setup completed okay.
|
|
||||||
|
|
||||||
This is normally called by :meth:`run()`.
|
|
||||||
"""
|
|
||||||
if self.alongside:
|
|
||||||
self.rprint("\n\t[bold green]initial setup is complete![/bold green]")
|
|
||||||
self.rprint("\n\tyou can run the terminal GUI app with:")
|
|
||||||
self.rprint(f"\n\t[blue]cd {sys.prefix}[/blue]")
|
|
||||||
self.rprint("\t[blue]bin/wuttapos -c app/terminal.conf run[/blue]\n")
|
|
||||||
return
|
|
||||||
|
|
||||||
super().show_goodbye()
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
## -*- mode: conf; -*-
|
|
||||||
|
|
||||||
<%text>############################################################</%text>
|
|
||||||
#
|
|
||||||
# ${app_title} - terminal installed alongside the server
|
|
||||||
#
|
|
||||||
<%text>############################################################</%text>
|
|
||||||
|
|
||||||
[wutta.config]
|
|
||||||
require = %(here)s/wutta.conf
|
|
||||||
|
|
||||||
[wuttapos]
|
|
||||||
store_id = ${store_id}
|
|
||||||
terminal_id = ${terminal_id}
|
|
||||||
|
|
||||||
[wutta_continuum]
|
|
||||||
enable_versioning = false
|
|
||||||
|
|
@ -282,11 +282,9 @@ def main(page: ft.Page):
|
||||||
page.go("/login")
|
page.go("/login")
|
||||||
|
|
||||||
|
|
||||||
# TODO: is there any way to inject a config object into the new Flet
|
# TODO: can we inject config to the main() via ft.app() kwargs somehow?
|
||||||
# app? if so this would be the place to do it. currently in main()
|
# pretty sure the `wuttapos open` command is trying to anyway..
|
||||||
# it always makes a new config for itself, as workaround. but also
|
def run_app(config=None):
|
||||||
# see notes in the wuttapos.cli.run module
|
|
||||||
def run_app():
|
|
||||||
ft.app(target=main, assets_dir=resource_path("wuttapos.terminal:assets"))
|
ft.app(target=main, assets_dir=resource_path("wuttapos.terminal:assets"))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue