add customers table, view

plus some other random fixes
This commit is contained in:
Lance Edgar 2026-01-01 20:11:41 -06:00
parent 89238722b3
commit 67c97d0847
8 changed files with 261 additions and 2 deletions

View file

@ -59,7 +59,7 @@ wuttapos = "wuttapos.app:WuttaPosAppProvider"
# TODO: (why) is this needed again?
[project.entry-points."wutta.web.menus"]
"wuttapos" = "wuttapos.server.menus:serverMenuHandler"
"wuttapos" = "wuttapos.server.menus:WuttaPosMenuHandler"
[project.urls]

View file

@ -51,7 +51,7 @@ class WuttaPosConfigExtension(WuttaConfigExtension):
# server menu handler
config.setdefault(
f"{config.appname}.web.menus.handler.spec",
"wuttapos.server.menus:serverMenuHandler",
"wuttapos.server.menus:WuttaPosMenuHandler",
)
# # web app libcache

View file

@ -0,0 +1,104 @@
"""add Customers
Revision ID: 32e965f42f0f
Revises: 6f02663c2220
Create Date: 2026-01-01 19:51:21.769137
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "32e965f42f0f"
down_revision: Union[str, None] = "6f02663c2220"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# customer
op.create_table(
"customer",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("customer_id", sa.String(length=20), nullable=False),
sa.Column("name", sa.String(length=100), nullable=False),
sa.Column("account_holder_uuid", wuttjamaican.db.util.UUID(), nullable=True),
sa.Column("phone_number", sa.String(length=20), nullable=True),
sa.Column("email_address", sa.String(length=255), nullable=True),
sa.ForeignKeyConstraint(
["account_holder_uuid"],
["person.uuid"],
name=op.f("fk_customer_account_holder_uuid_person"),
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_customer")),
)
op.create_table(
"customer_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"customer_id", sa.String(length=20), autoincrement=False, nullable=True
),
sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
sa.Column(
"account_holder_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column(
"phone_number", sa.String(length=20), autoincrement=False, nullable=True
),
sa.Column(
"email_address", sa.String(length=255), autoincrement=False, nullable=True
),
sa.Column(
"transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
),
sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
sa.Column("operation_type", sa.SmallInteger(), nullable=False),
sa.PrimaryKeyConstraint(
"uuid", "transaction_id", name=op.f("pk_customer_version")
),
)
op.create_index(
op.f("ix_customer_version_end_transaction_id"),
"customer_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_customer_version_operation_type"),
"customer_version",
["operation_type"],
unique=False,
)
op.create_index(
op.f("ix_customer_version_transaction_id"),
"customer_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# customer
op.drop_index(
op.f("ix_customer_version_transaction_id"), table_name="customer_version"
)
op.drop_index(
op.f("ix_customer_version_operation_type"), table_name="customer_version"
)
op.drop_index(
op.f("ix_customer_version_end_transaction_id"), table_name="customer_version"
)
op.drop_table("customer_version")
op.drop_table("customer")

View file

@ -26,6 +26,7 @@ WuttaPOS - data model
from wuttjamaican.db.model import *
from .customers import Customer
from .departments import Department
from .products import (
Product,

View file

@ -0,0 +1,67 @@
# -*- coding: utf-8; -*-
"""
Model definition for Customers
"""
import sqlalchemy as sa
from sqlalchemy import orm
from wuttjamaican.db import model
class Customer(model.Base):
"""
Technically a customer account, but relates to a person (account holder).
"""
__tablename__ = "customer"
__versioned__ = {}
__wutta_hint__ = {
"model_title": "Customer",
"model_title_plural": "Customers",
}
uuid = model.uuid_column()
customer_id = sa.Column(
sa.String(length=20),
nullable=False,
doc="""
Unique identifier for the customer account.
""",
)
name = sa.Column(
sa.String(length=100),
nullable=False,
doc="""
Name for the customer account.
""",
)
account_holder_uuid = model.uuid_fk_column("person.uuid", nullable=True)
account_holder = orm.relationship(
"Person",
doc="""
Reference to the account holder, if applicable.
""",
)
phone_number = sa.Column(
sa.String(length=20),
nullable=True,
doc="""
Phone number for the customer.
""",
)
email_address = sa.Column(
sa.String(length=255),
nullable=True,
doc="""
Email address for the customer.
""",
)
def __str__(self):
return self.name or ""

View file

@ -38,10 +38,24 @@ class WuttaPosMenuHandler(base.MenuHandler):
# replace it and add more as needed
return [
self.make_customers_menu(request),
self.make_products_menu(request),
self.make_admin_menu(request, include_people=True),
]
def make_customers_menu(self, request):
return {
"title": "Customers",
"type": "menu",
"items": [
{
"title": "Customers",
"route": "customers",
"perm": "customers.list",
},
],
}
def make_products_menu(self, request):
return {
"title": "Products",

View file

@ -34,3 +34,4 @@ def includeme(config):
config.include("wuttapos.server.views.departments")
config.include("wuttapos.server.views.products")
config.include("wuttapos.server.views.inventory_adjustments")
config.include("wuttapos.server.views.customers")

View file

@ -0,0 +1,72 @@
# -*- coding: utf-8; -*-
"""
Master view for Customers
"""
from wuttaweb.views import MasterView
from wuttaweb.forms.schema import PersonRef
from wuttapos.db.model.customers import Customer
class CustomerView(MasterView):
"""
Master view for Customers
"""
model_class = Customer
model_title = "Customer"
model_title_plural = "Customers"
route_prefix = "customers"
url_prefix = "/customers"
creatable = True
editable = True
deletable = True
labels = {
"customer_id": "Customer ID",
}
grid_columns = [
"customer_id",
"name",
"phone_number",
"email_address",
]
form_fields = [
"customer_id",
"name",
"account_holder",
"phone_number",
"email_address",
]
def configure_grid(self, grid):
g = grid
super().configure_grid(g)
# links
g.set_link("customer_id")
g.set_link("name")
def configure_form(self, form):
f = form
super().configure_form(f)
# account_holder
f.set_node("account_holder", PersonRef(self.request))
f.set_required("account_holder", False)
def defaults(config, **kwargs):
base = globals()
CustomerView = kwargs.get("CustomerView", base["CustomerView"])
CustomerView.defaults(config)
def includeme(config):
defaults(config)