Compare commits

..

No commits in common. "614189531f3ce279d812da2a9b1347a0e72c0afc" and "04de98a7870234be6f143c1f6158c6094c1f5e1d" have entirely different histories.

27 changed files with 295 additions and 423 deletions

View file

@ -3,3 +3,35 @@
[MESSAGES CONTROL]
disable=fixme,
duplicate-code,
abstract-method,
arguments-differ,
arguments-renamed,
attribute-defined-outside-init,
broad-exception-caught,
consider-using-dict-comprehension,
consider-using-f-string,
consider-using-set-comprehension,
empty-docstring,
implicit-str-concat,
inconsistent-return-statements,
invalid-name,
missing-class-docstring,
missing-function-docstring,
no-else-return,
no-member,
no-self-argument,
redefined-outer-name,
singleton-comparison,
too-few-public-methods,
too-many-arguments,
too-many-branches,
too-many-lines,
too-many-locals,
too-many-positional-arguments,
too-many-public-methods,
unnecessary-lambda-assignment,
unused-argument,
unused-import,
unused-variable,
unused-wildcard-import,
wildcard-import,

View file

@ -10,9 +10,6 @@ project.
.. _test coverage: https://buildbot.rattailproject.org/coverage/sideshow/
.. image:: https://img.shields.io/badge/linting-pylint-yellowgreen
:target: https://github.com/pylint-dev/pylint
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -35,7 +35,7 @@ class SideshowAppProvider(base.AppProvider):
handler`.
"""
def get_order_handler(self):
def get_order_handler(self, **kwargs):
"""
Get the configured :term:`order handler` for the app.
@ -49,9 +49,9 @@ class SideshowAppProvider(base.AppProvider):
:returns: Instance of :class:`~sideshow.orders.OrderHandler`.
"""
if "orders" not in self.app.handlers:
if "order_handler" not in self.__dict__:
spec = self.config.get(
"sideshow.orders.handler_spec", default="sideshow.orders:OrderHandler"
)
self.app.handlers["orders"] = self.app.load_object(spec)(self.config)
return self.app.handlers["orders"]
self.order_handler = self.app.load_object(spec)(self.config)
return self.order_handler

View file

@ -23,7 +23,6 @@
"""
New Order Batch Handler
"""
# pylint: disable=too-many-lines
import datetime
import decimal
@ -36,7 +35,7 @@ from wuttjamaican.batch import BatchHandler
from sideshow.db.model import NewOrderBatch
class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-methods
class NewOrderBatchHandler(BatchHandler):
"""
The :term:`batch handler` for :term:`new order batches <new order
batch>`.
@ -117,7 +116,6 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
discount = self.config.get("sideshow.orders.default_item_discount")
if discount:
return decimal.Decimal(discount)
return None
def autocomplete_customers_external(self, session, term, user=None):
"""
@ -139,9 +137,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
"""
raise NotImplementedError
def autocomplete_customers_local( # pylint: disable=unused-argument
self, session, term, user=None
):
def autocomplete_customers_local(self, session, term, user=None):
"""
Return autocomplete search results for
:class:`~sideshow.db.model.customers.LocalCustomer` records.
@ -347,9 +343,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
"""
raise NotImplementedError
def autocomplete_products_local( # pylint: disable=unused-argument
self, session, term, user=None
):
def autocomplete_products_local(self, session, term, user=None):
"""
Return autocomplete search results for
:class:`~sideshow.db.model.products.LocalProduct` records.
@ -474,9 +468,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
"""
raise NotImplementedError
def get_product_info_local( # pylint: disable=unused-argument
self, session, uuid, user=None
):
def get_product_info_local(self, session, uuid, user=None):
"""
Returns basic info for a :term:`local product` as pertains to
ordering.
@ -605,6 +597,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
:returns: List of product info dicts.
"""
model = self.app.model
session = self.app.get_session(batch)
use_local = self.use_local_products()
user = user or batch.created_by
@ -657,7 +650,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
return products
def add_item( # pylint: disable=too-many-arguments,too-many-positional-arguments,too-many-locals
def add_item(
self,
batch,
product_info,
@ -768,7 +761,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
session.flush()
return row
def update_item( # pylint: disable=too-many-arguments,too-many-positional-arguments
def update_item(
self, row, product_info, order_qty, order_uom, discount_percent=None, user=None
):
"""
@ -872,7 +865,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
# refresh per new info
self.refresh_row(row)
def refresh_row(self, row): # pylint: disable=too-many-branches
def refresh_row(self, row):
"""
Refresh data for the row. This is called when adding a new
row to the batch, or anytime the row is updated (e.g. when
@ -1030,7 +1023,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
super().remove_row(row)
def do_delete(self, batch, user, **kwargs): # pylint: disable=arguments-differ
def do_delete(self, batch, user, **kwargs):
"""
Delete a batch completely.
@ -1054,7 +1047,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
# continue with normal deletion
super().do_delete(batch, user, **kwargs)
def why_not_execute(self, batch, **kwargs): # pylint: disable=arguments-differ
def why_not_execute(self, batch, **kwargs):
"""
By default this checks to ensure the batch has a customer with
phone number, and at least one item. It also may check to
@ -1075,8 +1068,6 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
if not rows:
return "Must add at least one valid item"
return None
def get_effective_rows(self, batch):
"""
Only rows with
@ -1197,7 +1188,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
session.flush()
def make_new_order(self, batch, rows, user=None, progress=None):
def make_new_order(self, batch, rows, user=None, progress=None, **kwargs):
"""
Create a new :term:`order` from the batch data.
@ -1214,6 +1205,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
:returns: :class:`~sideshow.db.model.orders.Order` instance.
"""
model = self.app.model
enum = self.app.enum
session = self.app.get_session(batch)
batch_fields = [
@ -1255,17 +1247,17 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
]
# make order
kw = {field: getattr(batch, field) for field in batch_fields}
kw = dict([(field, getattr(batch, field)) for field in batch_fields])
kw["order_id"] = batch.id
kw["created_by"] = user
order = model.Order(**kw)
session.add(order)
session.flush()
def convert(row, i): # pylint: disable=unused-argument
def convert(row, i):
# make order item
kw = {field: getattr(row, field) for field in row_fields}
kw = dict([(field, getattr(row, field)) for field in row_fields])
item = model.OrderItem(**kw)
order.items.append(item)
@ -1278,7 +1270,7 @@ class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-met
session.flush()
return order
def set_initial_item_status(self, item, user):
def set_initial_item_status(self, item, user, **kwargs):
"""
Set the initial status and attach event(s) for the given item.

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -38,10 +38,10 @@ def install(
"""
config = ctx.parent.wutta_config
app = config.get_app()
handler = app.get_install_handler(
install = app.get_install_handler(
pkg_name="sideshow",
app_title="Sideshow",
pypi_name="Sideshow",
egg_name="Sideshow",
)
handler.run()
install.run()

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -36,7 +36,7 @@ class SideshowConfig(WuttaConfigExtension):
key = "sideshow"
def configure(self, config): # pylint: disable=empty-docstring
def configure(self, config):
""" """
# app info

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -57,7 +57,7 @@ class NewOrderBatch(model.BatchMixin, model.Base):
"""
@declared_attr
def __table_args__(cls): # pylint: disable=no-self-argument
def __table_args__(cls):
return cls.__default_table_args__() + (
sa.ForeignKeyConstraint(
["local_customer_uuid"], ["sideshow_customer_local.uuid"]
@ -95,9 +95,7 @@ class NewOrderBatch(model.BatchMixin, model.Base):
local_customer_uuid = sa.Column(model.UUID(), nullable=True)
@declared_attr
def local_customer( # pylint: disable=no-self-argument,missing-function-docstring
cls,
):
def local_customer(cls):
return orm.relationship(
"LocalCustomer",
back_populates="new_order_batches",
@ -113,9 +111,7 @@ class NewOrderBatch(model.BatchMixin, model.Base):
pending_customer_uuid = sa.Column(model.UUID(), nullable=True)
@declared_attr
def pending_customer( # pylint: disable=no-self-argument,missing-function-docstring
cls,
):
def pending_customer(cls):
return orm.relationship(
"PendingCustomer",
back_populates="new_order_batches",
@ -174,7 +170,7 @@ class NewOrderBatchRow(model.BatchRowMixin, model.Base):
__batch_class__ = NewOrderBatch
@declared_attr
def __table_args__(cls): # pylint: disable=no-self-argument
def __table_args__(cls):
return cls.__default_table_args__() + (
sa.ForeignKeyConstraint(
["local_product_uuid"], ["sideshow_product_local.uuid"]
@ -226,9 +222,7 @@ class NewOrderBatchRow(model.BatchRowMixin, model.Base):
local_product_uuid = sa.Column(model.UUID(), nullable=True)
@declared_attr
def local_product( # pylint: disable=no-self-argument,missing-function-docstring
cls,
):
def local_product(cls):
return orm.relationship(
"LocalProduct",
back_populates="new_order_batch_rows",
@ -244,9 +238,7 @@ class NewOrderBatchRow(model.BatchRowMixin, model.Base):
pending_product_uuid = sa.Column(model.UUID(), nullable=True)
@declared_attr
def pending_product( # pylint: disable=no-self-argument,missing-function-docstring
cls,
):
def pending_product(cls):
return orm.relationship(
"PendingProduct",
back_populates="new_order_batch_rows",

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -34,7 +34,7 @@ from wuttjamaican.db import model
from sideshow.enum import PendingCustomerStatus
class CustomerMixin: # pylint: disable=too-few-public-methods
class CustomerMixin:
"""
Base class for customer tables. This has shared columns, used by e.g.:
@ -86,9 +86,7 @@ class CustomerMixin: # pylint: disable=too-few-public-methods
return self.full_name or ""
class LocalCustomer( # pylint: disable=too-few-public-methods
CustomerMixin, model.Base
):
class LocalCustomer(CustomerMixin, model.Base):
"""
This table contains the :term:`local customer` records.
@ -138,9 +136,7 @@ class LocalCustomer( # pylint: disable=too-few-public-methods
)
class PendingCustomer( # pylint: disable=too-few-public-methods
CustomerMixin, model.Base
):
class PendingCustomer(CustomerMixin, model.Base):
"""
This table contains the :term:`pending customer` records, used
when creating an :term:`order` for new/unknown customer.

View file

@ -33,7 +33,7 @@ from sqlalchemy.ext.orderinglist import ordering_list
from wuttjamaican.db import model
class Order(model.Base): # pylint: disable=too-few-public-methods
class Order(model.Base):
"""
Represents an :term:`order` for a customer. Each order has one or
more :attr:`items`.
@ -519,7 +519,7 @@ class OrderItem(model.Base):
)
@property
def full_description(self): # pylint: disable=empty-docstring
def full_description(self):
""" """
fields = [
self.product_brand or "",
@ -542,7 +542,7 @@ class OrderItem(model.Base):
self.events.append(OrderItemEvent(**kwargs))
class OrderItemEvent(model.Base): # pylint: disable=too-few-public-methods
class OrderItemEvent(model.Base):
"""
An event in the life of an :term:`order item`.
"""

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -169,7 +169,7 @@ class ProductMixin:
)
@property
def full_description(self): # pylint: disable=empty-docstring
def full_description(self):
""" """
fields = [self.brand_name or "", self.description or "", self.size or ""]
fields = [f.strip() for f in fields if f.strip()]
@ -179,7 +179,7 @@ class ProductMixin:
return self.full_description
class LocalProduct(ProductMixin, model.Base): # pylint: disable=too-few-public-methods
class LocalProduct(ProductMixin, model.Base):
"""
This table contains the :term:`local product` records.
@ -228,9 +228,7 @@ class LocalProduct(ProductMixin, model.Base): # pylint: disable=too-few-public-
)
class PendingProduct( # pylint: disable=too-few-public-methods
ProductMixin, model.Base
):
class PendingProduct(ProductMixin, model.Base):
"""
This table contains the :term:`pending product` records, used when
creating an :term:`order` for new/unknown product(s).

View file

@ -27,7 +27,7 @@ Enum Values
from enum import Enum
from collections import OrderedDict
from wuttjamaican.enum import * # pylint: disable=wildcard-import,unused-wildcard-import
from wuttjamaican.enum import *
ORDER_UOM_CASE = "CS"

View file

@ -72,15 +72,15 @@ class OrderHandler(GenericHandler):
else:
case_qty = self.app.render_quantity(case_size)
unit_qty = self.app.render_quantity(order_qty * case_size)
CS = enum.ORDER_UOM[enum.ORDER_UOM_CASE] # pylint: disable=invalid-name
EA = enum.ORDER_UOM[enum.ORDER_UOM_UNIT] # pylint: disable=invalid-name
CS = enum.ORDER_UOM[enum.ORDER_UOM_CASE]
EA = enum.ORDER_UOM[enum.ORDER_UOM_UNIT]
order_qty = self.app.render_quantity(order_qty)
times = "&times;" if html else "x"
return f"{order_qty} {CS} ({times} {case_qty} = {unit_qty} {EA})"
# units
unit_qty = self.app.render_quantity(order_qty)
EA = enum.ORDER_UOM[enum.ORDER_UOM_UNIT] # pylint: disable=invalid-name
EA = enum.ORDER_UOM[enum.ORDER_UOM_UNIT]
return f"{unit_qty} {EA}"
def item_status_to_variant(self, status_code):
@ -105,7 +105,6 @@ class OrderHandler(GenericHandler):
enum.ORDER_ITEM_STATUS_INACTIVE,
):
return "warning"
return None
def resolve_pending_product(self, pending_product, product_info, user, note=None):
"""
@ -160,10 +159,7 @@ class OrderHandler(GenericHandler):
items = (
session.query(model.OrderItem)
.filter(model.OrderItem.pending_product == pending_product)
.filter(
model.OrderItem.product_id # pylint: disable=singleton-comparison
== None
)
.filter(model.OrderItem.product_id == None)
.all()
)
@ -187,7 +183,7 @@ class OrderHandler(GenericHandler):
if note:
item.add_event(enum.ORDER_ITEM_EVENT_NOTE_ADDED, user, note=note)
def process_placement( # pylint: disable=too-many-arguments,too-many-positional-arguments
def process_placement(
self, items, user, vendor_name=None, po_number=None, note=None
):
"""
@ -230,7 +226,7 @@ class OrderHandler(GenericHandler):
item.add_event(enum.ORDER_ITEM_EVENT_NOTE_ADDED, user, note=note)
item.status_code = enum.ORDER_ITEM_STATUS_PLACED
def process_receiving( # pylint: disable=too-many-arguments,too-many-positional-arguments
def process_receiving(
self,
items,
user,

View file

@ -28,10 +28,6 @@ from wuttaweb import testing as base
class WebTestCase(base.WebTestCase):
"""
Custom class for web tests; it configures defaults specific to
Sideshow.
"""
def make_config(self, **kwargs):
config = super().make_config(**kwargs)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -25,7 +25,7 @@ Sideshow web app
"""
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
config.include("sideshow.web.static")
config.include("wuttaweb.subscribers")
config.include("sideshow.web.views")

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -27,7 +27,7 @@ Sideshow web app
from wuttaweb import app as base
def main(global_config, **settings): # pylint: disable=unused-argument
def main(global_config, **settings):
"""
Make and return the WSGI app (Paste entry point).
"""
@ -41,7 +41,7 @@ def main(global_config, **settings): # pylint: disable=unused-argument
)
# make config objects
wutta_config = base.make_wutta_config(settings) # pylint: disable=unused-variable
wutta_config = base.make_wutta_config(settings)
pyramid_config = base.make_pyramid_config(settings)
# bring in the rest of Sideshow

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -37,18 +37,17 @@ class OrderRef(ObjectRef):
"""
@property
def model_class(self): # pylint: disable=empty-docstring
def model_class(self):
""" """
model = self.app.model
return model.Order
def sort_query(self, query): # pylint: disable=empty-docstring
def sort_query(self, query):
""" """
return query.order_by(self.model_class.order_id)
def get_object_url(self, obj): # pylint: disable=empty-docstring
def get_object_url(self, order):
""" """
order = obj
return self.request.route_url("orders.view", uuid=order.uuid)
@ -63,18 +62,17 @@ class LocalCustomerRef(ObjectRef):
"""
@property
def model_class(self): # pylint: disable=empty-docstring
def model_class(self):
""" """
model = self.app.model
return model.LocalCustomer
def sort_query(self, query): # pylint: disable=empty-docstring
def sort_query(self, query):
""" """
return query.order_by(self.model_class.full_name)
def get_object_url(self, obj): # pylint: disable=empty-docstring
def get_object_url(self, customer):
""" """
customer = obj
return self.request.route_url("local_customers.view", uuid=customer.uuid)
@ -89,18 +87,17 @@ class PendingCustomerRef(ObjectRef):
"""
@property
def model_class(self): # pylint: disable=empty-docstring
def model_class(self):
""" """
model = self.app.model
return model.PendingCustomer
def sort_query(self, query): # pylint: disable=empty-docstring
def sort_query(self, query):
""" """
return query.order_by(self.model_class.full_name)
def get_object_url(self, obj): # pylint: disable=empty-docstring
def get_object_url(self, customer):
""" """
customer = obj
return self.request.route_url("pending_customers.view", uuid=customer.uuid)
@ -114,18 +111,17 @@ class LocalProductRef(ObjectRef):
"""
@property
def model_class(self): # pylint: disable=empty-docstring
def model_class(self):
""" """
model = self.app.model
return model.LocalProduct
def sort_query(self, query): # pylint: disable=empty-docstring
def sort_query(self, query):
""" """
return query.order_by(self.model_class.scancode)
def get_object_url(self, obj): # pylint: disable=empty-docstring
def get_object_url(self, product):
""" """
product = obj
return self.request.route_url("local_products.view", uuid=product.uuid)
@ -140,16 +136,15 @@ class PendingProductRef(ObjectRef):
"""
@property
def model_class(self): # pylint: disable=empty-docstring
def model_class(self):
""" """
model = self.app.model
return model.PendingProduct
def sort_query(self, query): # pylint: disable=empty-docstring
def sort_query(self, query):
""" """
return query.order_by(self.model_class.scancode)
def get_object_url(self, obj): # pylint: disable=empty-docstring
def get_object_url(self, product):
""" """
product = obj
return self.request.route_url("pending_products.view", uuid=product.uuid)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -32,7 +32,7 @@ class SideshowMenuHandler(base.MenuHandler):
Sideshow menu handler
"""
def make_menus(self, request): # pylint: disable=empty-docstring
def make_menus(self, request, **kwargs):
""" """
return [
self.make_orders_menu(request),
@ -43,7 +43,7 @@ class SideshowMenuHandler(base.MenuHandler):
self.make_admin_menu(request),
]
def make_orders_menu(self, request): # pylint: disable=unused-argument
def make_orders_menu(self, request, **kwargs):
"""
Generate the Orders menu.
"""
@ -91,7 +91,7 @@ class SideshowMenuHandler(base.MenuHandler):
],
}
def make_customers_menu(self, request): # pylint: disable=unused-argument
def make_customers_menu(self, request, **kwargs):
"""
Generate the Customers menu.
"""
@ -112,7 +112,7 @@ class SideshowMenuHandler(base.MenuHandler):
],
}
def make_products_menu(self, request): # pylint: disable=unused-argument
def make_products_menu(self, request, **kwargs):
"""
Generate the Products menu.
"""
@ -133,7 +133,7 @@ class SideshowMenuHandler(base.MenuHandler):
],
}
def make_batch_menu(self, request): # pylint: disable=unused-argument
def make_batch_menu(self, request, **kwargs):
"""
Generate the Batch menu.
"""
@ -149,7 +149,7 @@ class SideshowMenuHandler(base.MenuHandler):
],
}
def make_other_menu(self, request): # pylint: disable=unused-argument
def make_other_menu(self, request, **kwargs):
"""
Generate the "Other" menu.
"""
@ -159,7 +159,7 @@ class SideshowMenuHandler(base.MenuHandler):
"items": [],
}
def make_admin_menu(self, request, **kwargs): # pylint: disable=empty-docstring
def make_admin_menu(self, request, **kwargs):
""" """
kwargs["include_people"] = True
menu = super().make_admin_menu(request, **kwargs)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -43,6 +43,6 @@ fontawesome_js = Resource(libcache, "fontawesome-5.3.1-all.min.js")
# bb_vue_fontawesome_js = Resource(libcache, 'vue-fontawesome-3.0.6.index.es.js')
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
config.include("wuttaweb.static")
config.add_static_view("sideshow", "sideshow.web:static", cache_max_age=3600)

View file

@ -27,7 +27,7 @@ Sideshow Views
from wuttaweb.views import essential
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
# core views for wuttaweb
essential.defaults(

View file

@ -32,7 +32,7 @@ from sideshow.batch.neworder import NewOrderBatchHandler
from sideshow.web.forms.schema import LocalCustomerRef, PendingCustomerRef
class NewOrderBatchView(BatchMasterView): # pylint: disable=abstract-method
class NewOrderBatchView(BatchMasterView):
"""
Master view for :class:`~sideshow.db.model.batch.neworder.NewOrderBatch`.
@ -131,14 +131,13 @@ class NewOrderBatchView(BatchMasterView): # pylint: disable=abstract-method
super().__init__(request, context=context)
self.order_handler = self.app.get_order_handler()
def get_batch_handler(self): # pylint: disable=empty-docstring
def get_batch_handler(self):
""" """
# TODO: call self.app.get_batch_handler()
return NewOrderBatchHandler(self.config)
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# store_id
@ -148,9 +147,8 @@ class NewOrderBatchView(BatchMasterView): # pylint: disable=abstract-method
# total_price
g.set_renderer("total_price", "currency")
def configure_form(self, form): # pylint: disable=empty-docstring
def configure_form(self, f):
""" """
f = form
super().configure_form(f)
# store_id
@ -166,10 +164,10 @@ class NewOrderBatchView(BatchMasterView): # pylint: disable=abstract-method
# total_price
f.set_node("total_price", WuttaMoney(self.request))
def configure_row_grid(self, grid): # pylint: disable=empty-docstring
def configure_row_grid(self, g):
""" """
g = grid
super().configure_row_grid(g)
enum = self.app.enum
# TODO
# order_uom
@ -190,13 +188,12 @@ class NewOrderBatchView(BatchMasterView): # pylint: disable=abstract-method
# total_price
g.set_renderer("total_price", "currency")
def get_xref_buttons(self, obj):
def get_xref_buttons(self, batch):
"""
Adds "View this Order" button, if batch has been executed and
a corresponding :class:`~sideshow.db.model.orders.Order` can
be located.
"""
batch = obj
buttons = super().get_xref_buttons(batch)
model = self.app.model
session = self.Session()
@ -218,14 +215,12 @@ class NewOrderBatchView(BatchMasterView): # pylint: disable=abstract-method
return buttons
def defaults(config, **kwargs): # pylint: disable=missing-function-docstring
def defaults(config, **kwargs):
base = globals()
NewOrderBatchView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"NewOrderBatchView", base["NewOrderBatchView"]
)
NewOrderBatchView = kwargs.get("NewOrderBatchView", base["NewOrderBatchView"])
NewOrderBatchView.defaults(config)
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
defaults(config)

View file

@ -47,7 +47,7 @@ class CommonView(base.CommonView):
admin = model.Role(name="Order Admin")
admin.notes = (
"this role was auto-created; you can change or remove it as needed."
"this role was auto-created; " "you can change or remove it as needed."
)
session.add(admin)
@ -101,5 +101,5 @@ class CommonView(base.CommonView):
auth.grant_permission(admin, perm)
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
base.defaults(config, **{"CommonView": CommonView})

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024-2025 Lance Edgar
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
@ -30,7 +30,7 @@ from wuttaweb.forms.schema import UserRef, WuttaEnum
from sideshow.db.model import LocalCustomer, PendingCustomer
class LocalCustomerView(MasterView): # pylint: disable=abstract-method
class LocalCustomerView(MasterView):
"""
Master view for
:class:`~sideshow.db.model.customers.LocalCustomer`; route prefix
@ -76,9 +76,8 @@ class LocalCustomerView(MasterView): # pylint: disable=abstract-method
"new_order_batches",
]
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# links
@ -88,9 +87,8 @@ class LocalCustomerView(MasterView): # pylint: disable=abstract-method
g.set_link("phone_number")
g.set_link("email_address")
def configure_form(self, form): # pylint: disable=empty-docstring
def configure_form(self, f):
""" """
f = form
super().configure_form(f)
customer = f.model_instance
@ -140,11 +138,10 @@ class LocalCustomerView(MasterView): # pylint: disable=abstract-method
grid.set_renderer("total_price", grid.render_currency)
if self.request.has_perm("orders.view"):
def view_url(order, i): # pylint: disable=unused-argument
return self.request.route_url("orders.view", uuid=order.uuid)
grid.add_action("view", icon="eye", url=view_url)
url = lambda order, i: self.request.route_url(
"orders.view", uuid=order.uuid
)
grid.add_action("view", icon="eye", url=url)
grid.set_link("order_id")
return grid
@ -177,17 +174,17 @@ class LocalCustomerView(MasterView): # pylint: disable=abstract-method
)
if self.request.has_perm("neworder_batches.view"):
def view_url(batch, i): # pylint: disable=unused-argument
return self.request.route_url("neworder_batches.view", uuid=batch.uuid)
grid.add_action("view", icon="eye", url=view_url)
url = lambda batch, i: self.request.route_url(
"neworder_batches.view", uuid=batch.uuid
)
grid.add_action("view", icon="eye", url=url)
grid.set_link("id")
return grid
def objectify(self, form): # pylint: disable=empty-docstring
def objectify(self, form):
""" """
enum = self.app.enum
customer = super().objectify(form)
customer.full_name = self.app.make_full_name(
@ -197,7 +194,7 @@ class LocalCustomerView(MasterView): # pylint: disable=abstract-method
return customer
class PendingCustomerView(MasterView): # pylint: disable=abstract-method
class PendingCustomerView(MasterView):
"""
Master view for
:class:`~sideshow.db.model.customers.PendingCustomer`; route
@ -249,9 +246,8 @@ class PendingCustomerView(MasterView): # pylint: disable=abstract-method
"new_order_batches",
]
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
enum = self.app.enum
@ -265,9 +261,8 @@ class PendingCustomerView(MasterView): # pylint: disable=abstract-method
g.set_link("phone_number")
g.set_link("email_address")
def configure_form(self, form): # pylint: disable=empty-docstring
def configure_form(self, f):
""" """
f = form
super().configure_form(f)
enum = self.app.enum
customer = f.model_instance
@ -334,11 +329,10 @@ class PendingCustomerView(MasterView): # pylint: disable=abstract-method
grid.set_renderer("total_price", grid.render_currency)
if self.request.has_perm("orders.view"):
def view_url(order, i): # pylint: disable=unused-argument
return self.request.route_url("orders.view", uuid=order.uuid)
grid.add_action("view", icon="eye", url=view_url)
url = lambda order, i: self.request.route_url(
"orders.view", uuid=order.uuid
)
grid.add_action("view", icon="eye", url=url)
grid.set_link("order_id")
return grid
@ -371,16 +365,15 @@ class PendingCustomerView(MasterView): # pylint: disable=abstract-method
)
if self.request.has_perm("neworder_batches.view"):
def view_url(batch, i): # pylint: disable=unused-argument
return self.request.route_url("neworder_batches.view", uuid=batch.uuid)
grid.add_action("view", icon="eye", url=view_url)
url = lambda batch, i: self.request.route_url(
"neworder_batches.view", uuid=batch.uuid
)
grid.add_action("view", icon="eye", url=url)
grid.set_link("id")
return grid
def objectify(self, form): # pylint: disable=empty-docstring
def objectify(self, form):
""" """
enum = self.app.enum
customer = super().objectify(form)
@ -391,15 +384,14 @@ class PendingCustomerView(MasterView): # pylint: disable=abstract-method
return customer
def delete_instance(self, obj): # pylint: disable=empty-docstring
def delete_instance(self, customer):
""" """
customer = obj
model_title = self.get_model_title()
# avoid deleting if still referenced by order(s)
if list(customer.orders):
for order in customer.orders:
self.request.session.flash(
f"Cannot delete {model_title} still attached to Order(s)", "warning"
f"Cannot delete {model_title} still attached " "to Order(s)", "warning"
)
raise self.redirect(self.get_action_url("view", customer))
@ -417,19 +409,15 @@ class PendingCustomerView(MasterView): # pylint: disable=abstract-method
super().delete_instance(customer)
def defaults(config, **kwargs): # pylint: disable=missing-function-docstring
def defaults(config, **kwargs):
base = globals()
LocalCustomerView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"LocalCustomerView", base["LocalCustomerView"]
)
LocalCustomerView = kwargs.get("LocalCustomerView", base["LocalCustomerView"])
LocalCustomerView.defaults(config)
PendingCustomerView = ( # pylint: disable=redefined-outer-name,invalid-name
kwargs.get("PendingCustomerView", base["PendingCustomerView"])
)
PendingCustomerView = kwargs.get("PendingCustomerView", base["PendingCustomerView"])
PendingCustomerView.defaults(config)
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
defaults(config)

View file

@ -23,23 +23,30 @@
"""
Views for Orders
"""
# pylint: disable=too-many-lines
import decimal
import json
import logging
import re
import colander
import sqlalchemy as sa
from sqlalchemy import orm
from webhelpers2.html import tags, HTML
from wuttaweb.views import MasterView
from wuttaweb.forms.schema import UserRef, WuttaMoney, WuttaQuantity, WuttaDictEnum
from wuttaweb.forms.schema import (
UserRef,
WuttaMoney,
WuttaQuantity,
WuttaEnum,
WuttaDictEnum,
)
from wuttaweb.util import make_json_safe
from sideshow.db.model import Order, OrderItem
from sideshow.batch.neworder import NewOrderBatchHandler
from sideshow.web.forms.schema import (
OrderRef,
LocalCustomerRef,
@ -52,7 +59,7 @@ from sideshow.web.forms.schema import (
log = logging.getLogger(__name__)
class OrderView(MasterView): # pylint: disable=too-many-public-methods
class OrderView(MasterView):
"""
Master view for :class:`~sideshow.db.model.orders.Order`; route
prefix is ``orders``.
@ -165,9 +172,8 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
self.order_handler = self.app.get_order_handler()
self.batch_handler = self.app.get_batch_handler("neworder")
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# store_id
@ -218,6 +224,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
* :meth:`submit_order()`
"""
model = self.app.model
enum = self.app.enum
session = self.Session()
batch = self.get_current_batch()
self.creating = True
@ -257,7 +264,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
if action in json_actions:
try:
result = getattr(self, action)(batch, data)
except Exception as error: # pylint: disable=broad-exception-caught
except Exception as error:
log.warning("error calling json action for order", exc_info=True)
result = {"error": self.app.render_error(error)}
return self.json_response(result)
@ -285,10 +292,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
if context["expose_store_id"]:
stores = (
session.query(model.Store)
.filter(
model.Store.archived # pylint: disable=singleton-comparison
== False
)
.filter(model.Store.archived == False)
.order_by(model.Store.store_id)
.all()
)
@ -309,10 +313,12 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
context["default_item_discount"] = self.app.render_quantity(
self.batch_handler.get_default_item_discount()
)
context["dept_item_discounts"] = {
d["department_id"]: d["default_item_discount"]
context["dept_item_discounts"] = dict(
[
(d["department_id"], d["default_item_discount"])
for d in self.get_dept_item_discounts()
}
]
)
return self.render_to_response("create", context)
@ -340,10 +346,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
batch = (
session.query(model.NewOrderBatch)
.filter(model.NewOrderBatch.created_by == user)
.filter(
model.NewOrderBatch.executed # pylint: disable=singleton-comparison
== None
)
.filter(model.NewOrderBatch.executed == None)
.one()
)
@ -378,6 +381,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
return handler.autocomplete_customers_local(
session, term, user=self.request.user
)
else:
return handler.autocomplete_customers_external(
session, term, user=self.request.user
)
@ -405,11 +409,12 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
return handler.autocomplete_products_local(
session, term, user=self.request.user
)
else:
return handler.autocomplete_products_external(
session, term, user=self.request.user
)
def get_pending_product_required_fields(self): # pylint: disable=empty-docstring
def get_pending_product_required_fields(self):
""" """
required = []
for field in self.PENDING_PRODUCT_ENTRY_FIELDS:
@ -483,11 +488,9 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
* :meth:`cancel_order()`
* :meth:`submit_order()`
"""
session = self.Session()
# drop current batch
self.batch_handler.do_delete(batch, self.request.user)
session.flush()
self.Session.flush()
# send back to "create order" which makes new batch
route_prefix = self.get_route_prefix()
@ -505,10 +508,8 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
* :meth:`start_over()`
* :meth:`submit_order()`
"""
session = self.Session()
self.batch_handler.do_delete(batch, self.request.user)
session.flush()
self.Session.flush()
# set flash msg just to be more obvious
self.request.session.flash("New order has been deleted.")
@ -533,7 +534,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
batch.store_id = store_id
return self.get_context_customer(batch)
def get_context_customer(self, batch): # pylint: disable=empty-docstring
def get_context_customer(self, batch):
""" """
context = {
"store_id": batch.store_id,
@ -598,7 +599,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
self.batch_handler.set_customer(batch, customer_id)
return self.get_context_customer(batch)
def unassign_customer(self, batch, data): # pylint: disable=unused-argument
def unassign_customer(self, batch, data):
"""
Clear the customer info for a batch.
@ -632,9 +633,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
self.batch_handler.set_customer(batch, data, user=self.request.user)
return self.get_context_customer(batch)
def get_product_info( # pylint: disable=unused-argument,too-many-branches
self, batch, data
):
def get_product_info(self, batch, data):
"""
Fetch data for a specific product.
@ -708,7 +707,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
return data
def get_past_products(self, batch, data): # pylint: disable=unused-argument
def get_past_products(self, batch, data):
"""
Fetch past products for convenient re-ordering.
@ -803,7 +802,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
self.batch_handler.do_remove_row(row)
return {"batch": self.normalize_batch(batch)}
def submit_order(self, batch, data): # pylint: disable=unused-argument
def submit_order(self, batch, data):
"""
This submits the user's current new order batch, hence
executing the batch and creating the true order.
@ -821,7 +820,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
try:
order = self.batch_handler.do_execute(batch, user)
except Exception as error: # pylint: disable=broad-exception-caught
except Exception as error:
log.warning("failed to execute new order batch: %s", batch, exc_info=True)
return {"error": self.app.render_error(error)}
@ -829,7 +828,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
"next_url": self.get_action_url("view", order),
}
def normalize_batch(self, batch): # pylint: disable=empty-docstring
def normalize_batch(self, batch):
""" """
return {
"uuid": batch.uuid.hex,
@ -839,7 +838,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
"status_text": batch.status_text,
}
def normalize_row(self, row): # pylint: disable=empty-docstring
def normalize_row(self, row):
""" """
data = {
"uuid": row.uuid.hex,
@ -916,6 +915,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
row.unit_price_sale
)
if row.sale_ends:
sale_ends = row.sale_ends
data["sale_ends"] = str(row.sale_ends)
data["sale_ends_display"] = self.app.render_date(row.sale_ends)
@ -953,14 +953,12 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
return data
def get_instance_title(self, instance): # pylint: disable=empty-docstring
def get_instance_title(self, order):
""" """
order = instance
return f"#{order.order_id} for {order.customer_name}"
def configure_form(self, form): # pylint: disable=empty-docstring
def configure_form(self, f):
""" """
f = form
super().configure_form(f)
order = f.model_instance
@ -987,9 +985,8 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
f.set_node("created_by", UserRef(self.request))
f.set_readonly("created_by")
def get_xref_buttons(self, obj): # pylint: disable=empty-docstring
def get_xref_buttons(self, order):
""" """
order = obj
buttons = super().get_xref_buttons(order)
model = self.app.model
session = self.Session()
@ -1010,16 +1007,14 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
return buttons
def get_row_grid_data(self, obj): # pylint: disable=empty-docstring
def get_row_grid_data(self, order):
""" """
order = obj
model = self.app.model
session = self.Session()
return session.query(model.OrderItem).filter(model.OrderItem.order == order)
def configure_row_grid(self, grid): # pylint: disable=empty-docstring
def configure_row_grid(self, g):
""" """
g = grid
super().configure_row_grid(g)
# enum = self.app.enum
@ -1056,28 +1051,22 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
# TODO: upstream should set this automatically
g.row_class = self.row_grid_row_class
def row_grid_row_class( # pylint: disable=unused-argument,empty-docstring
self, item, data, i
):
def row_grid_row_class(self, item, data, i):
""" """
variant = self.order_handler.item_status_to_variant(item.status_code)
if variant:
return f"has-background-{variant}"
return None
def render_status_code( # pylint: disable=unused-argument,empty-docstring
self, item, key, value
):
def render_status_code(self, item, key, value):
""" """
enum = self.app.enum
return enum.ORDER_ITEM_STATUS[value]
def get_row_action_url_view(self, row, i): # pylint: disable=empty-docstring
def get_row_action_url_view(self, item, i):
""" """
item = row
return self.request.route_url("order_items.view", uuid=item.uuid)
def configure_get_simple_settings(self): # pylint: disable=empty-docstring
def configure_get_simple_settings(self):
""" """
settings = [
# stores
@ -1122,9 +1111,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
return settings
def configure_get_context( # pylint: disable=empty-docstring,arguments-differ
self, **kwargs
):
def configure_get_context(self, **kwargs):
""" """
context = super().configure_get_context(**kwargs)
@ -1138,9 +1125,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
return context
def configure_gather_settings(
self, data, simple_settings=None
): # pylint: disable=empty-docstring
def configure_gather_settings(self, data, simple_settings=None):
""" """
settings = super().configure_gather_settings(
data, simple_settings=simple_settings
@ -1163,9 +1148,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
return settings
def configure_remove_settings( # pylint: disable=empty-docstring,arguments-differ
self, **kwargs
):
def configure_remove_settings(self, **kwargs):
""" """
model = self.app.model
session = self.Session()
@ -1241,7 +1224,7 @@ class OrderView(MasterView): # pylint: disable=too-many-public-methods
)
class OrderItemView(MasterView): # pylint: disable=abstract-method
class OrderItemView(MasterView):
"""
Master view for :class:`~sideshow.db.model.orders.OrderItem`;
route prefix is ``order_items``.
@ -1346,21 +1329,20 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
super().__init__(request, context=context)
self.order_handler = self.app.get_order_handler()
def get_fallback_templates(self, template): # pylint: disable=empty-docstring
def get_fallback_templates(self, template):
""" """
templates = super().get_fallback_templates(template)
templates.insert(0, f"/order-items/{template}.mako")
return templates
def get_query(self, session=None): # pylint: disable=empty-docstring
def get_query(self, session=None):
""" """
query = super().get_query(session=session)
model = self.app.model
return query.join(model.Order)
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
model = self.app.model
# enum = self.app.enum
@ -1409,32 +1391,24 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
# status_code
g.set_renderer("status_code", self.render_status_code)
def render_order_attr( # pylint: disable=unused-argument,empty-docstring
self, item, key, value
):
def render_order_attr(self, item, key, value):
""" """
order = item.order
return getattr(order, key)
def render_status_code( # pylint: disable=unused-argument,empty-docstring
self, item, key, value
):
def render_status_code(self, item, key, value):
""" """
enum = self.app.enum
return enum.ORDER_ITEM_STATUS[value]
def grid_row_class( # pylint: disable=unused-argument,empty-docstring
self, item, data, i
):
def grid_row_class(self, item, data, i):
""" """
variant = self.order_handler.item_status_to_variant(item.status_code)
if variant:
return f"has-background-{variant}"
return None
def configure_form(self, form): # pylint: disable=empty-docstring
def configure_form(self, f):
""" """
f = form
super().configure_form(f)
enum = self.app.enum
item = f.model_instance
@ -1481,7 +1455,7 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
# paid_amount
f.set_node("paid_amount", WuttaMoney(self.request))
def get_template_context(self, context): # pylint: disable=empty-docstring
def get_template_context(self, context):
""" """
if self.viewing:
model = self.app.model
@ -1531,9 +1505,7 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
return context
def render_event_note( # pylint: disable=unused-argument,empty-docstring
self, event, key, value
):
def render_event_note(self, event, key, value):
""" """
enum = self.app.enum
if event.type_code == enum.ORDER_ITEM_EVENT_NOTE_ADDED:
@ -1545,9 +1517,8 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
)
return value
def get_xref_buttons(self, obj): # pylint: disable=empty-docstring
def get_xref_buttons(self, item):
""" """
item = obj
buttons = super().get_xref_buttons(item)
if self.request.has_perm("orders.view"):
@ -1581,8 +1552,10 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
View which changes status for an order item. This is
POST-only; will redirect back to the item view.
"""
model = self.app.model
enum = self.app.enum
main_item = self.get_instance()
session = self.Session()
redirect = self.redirect(self.get_action_url("view", main_item))
extra_note = self.request.POST.get("note")
@ -1608,9 +1581,8 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
if item.status_code != new_status_code:
# event: change status
note = (
f'status changed from "{enum.ORDER_ITEM_STATUS[item.status_code]}" '
f'to "{new_status_text}"'
note = 'status changed from "{}" to "{}"'.format(
enum.ORDER_ITEM_STATUS[item.status_code], new_status_text
)
item.add_event(
enum.ORDER_ITEM_EVENT_STATUS_CHANGE, self.request.user, note=note
@ -1672,7 +1644,7 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
return items
@classmethod
def defaults(cls, config): # pylint: disable=empty-docstring
def defaults(cls, config):
""" """
cls._order_item_defaults(config)
cls._defaults(config)
@ -1730,7 +1702,7 @@ class OrderItemView(MasterView): # pylint: disable=abstract-method
)
class PlacementView(OrderItemView): # pylint: disable=abstract-method
class PlacementView(OrderItemView):
"""
Master view for the "placement" phase of
:class:`~sideshow.db.model.orders.OrderItem`; route prefix is
@ -1772,16 +1744,15 @@ class PlacementView(OrderItemView): # pylint: disable=abstract-method
"vendor_name": {"active": True},
}
def get_query(self, session=None): # pylint: disable=empty-docstring
def get_query(self, session=None):
""" """
query = super().get_query(session=session)
model = self.app.model
enum = self.app.enum
return query.filter(model.OrderItem.status_code == enum.ORDER_ITEM_STATUS_READY)
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# checkable
@ -1869,7 +1840,7 @@ class PlacementView(OrderItemView): # pylint: disable=abstract-method
)
class ReceivingView(OrderItemView): # pylint: disable=abstract-method
class ReceivingView(OrderItemView):
"""
Master view for the "receiving" phase of
:class:`~sideshow.db.model.orders.OrderItem`; route prefix is
@ -1911,7 +1882,7 @@ class ReceivingView(OrderItemView): # pylint: disable=abstract-method
"vendor_name": {"active": True},
}
def get_query(self, session=None): # pylint: disable=empty-docstring
def get_query(self, session=None):
""" """
query = super().get_query(session=session)
model = self.app.model
@ -1920,9 +1891,8 @@ class ReceivingView(OrderItemView): # pylint: disable=abstract-method
model.OrderItem.status_code == enum.ORDER_ITEM_STATUS_PLACED
)
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# checkable
@ -2070,7 +2040,7 @@ class ReceivingView(OrderItemView): # pylint: disable=abstract-method
)
class ContactView(OrderItemView): # pylint: disable=abstract-method
class ContactView(OrderItemView):
"""
Master view for the "contact" phase of
:class:`~sideshow.db.model.orders.OrderItem`; route prefix is
@ -2093,7 +2063,7 @@ class ContactView(OrderItemView): # pylint: disable=abstract-method
route_prefix = "order_items_contact"
url_prefix = "/contact"
def get_query(self, session=None): # pylint: disable=empty-docstring
def get_query(self, session=None):
""" """
query = super().get_query(session=session)
model = self.app.model
@ -2104,9 +2074,8 @@ class ContactView(OrderItemView): # pylint: disable=abstract-method
)
)
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# checkable
@ -2238,7 +2207,7 @@ class ContactView(OrderItemView): # pylint: disable=abstract-method
)
class DeliveryView(OrderItemView): # pylint: disable=abstract-method
class DeliveryView(OrderItemView):
"""
Master view for the "delivery" phase of
:class:`~sideshow.db.model.orders.OrderItem`; route prefix is
@ -2261,7 +2230,7 @@ class DeliveryView(OrderItemView): # pylint: disable=abstract-method
route_prefix = "order_items_delivery"
url_prefix = "/delivery"
def get_query(self, session=None): # pylint: disable=empty-docstring
def get_query(self, session=None):
""" """
query = super().get_query(session=session)
model = self.app.model
@ -2272,9 +2241,8 @@ class DeliveryView(OrderItemView): # pylint: disable=abstract-method
)
)
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# checkable
@ -2404,39 +2372,27 @@ class DeliveryView(OrderItemView): # pylint: disable=abstract-method
)
def defaults(config, **kwargs): # pylint: disable=missing-function-docstring
def defaults(config, **kwargs):
base = globals()
OrderView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"OrderView", base["OrderView"]
)
OrderView = kwargs.get("OrderView", base["OrderView"])
OrderView.defaults(config)
OrderItemView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"OrderItemView", base["OrderItemView"]
)
OrderItemView = kwargs.get("OrderItemView", base["OrderItemView"])
OrderItemView.defaults(config)
PlacementView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"PlacementView", base["PlacementView"]
)
PlacementView = kwargs.get("PlacementView", base["PlacementView"])
PlacementView.defaults(config)
ReceivingView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"ReceivingView", base["ReceivingView"]
)
ReceivingView = kwargs.get("ReceivingView", base["ReceivingView"])
ReceivingView.defaults(config)
ContactView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"ContactView", base["ContactView"]
)
ContactView = kwargs.get("ContactView", base["ContactView"])
ContactView.defaults(config)
DeliveryView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"DeliveryView", base["DeliveryView"]
)
DeliveryView = kwargs.get("DeliveryView", base["DeliveryView"])
DeliveryView.defaults(config)
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
defaults(config)

View file

@ -25,13 +25,13 @@ Views for Products
"""
from wuttaweb.views import MasterView
from wuttaweb.forms.schema import UserRef, WuttaMoney, WuttaQuantity
from wuttaweb.forms.schema import UserRef, WuttaEnum, WuttaMoney, WuttaQuantity
from sideshow.enum import PendingProductStatus
from sideshow.db.model import LocalProduct, PendingProduct
class LocalProductView(MasterView): # pylint: disable=abstract-method
class LocalProductView(MasterView):
"""
Master view for :class:`~sideshow.db.model.products.LocalProduct`;
route prefix is ``local_products``.
@ -88,9 +88,8 @@ class LocalProductView(MasterView): # pylint: disable=abstract-method
"new_order_batches",
]
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# unit_cost
@ -106,10 +105,10 @@ class LocalProductView(MasterView): # pylint: disable=abstract-method
g.set_link("description")
g.set_link("size")
def configure_form(self, form): # pylint: disable=empty-docstring
def configure_form(self, f):
""" """
f = form
super().configure_form(f)
enum = self.app.enum
product = f.model_instance
# external_id
@ -156,7 +155,7 @@ class LocalProductView(MasterView): # pylint: disable=abstract-method
model = self.app.model
route_prefix = self.get_route_prefix()
orders = {item.order for item in product.order_items}
orders = set([item.order for item in product.order_items])
orders = sorted(orders, key=lambda order: order.order_id)
grid = self.make_grid(
@ -178,11 +177,10 @@ class LocalProductView(MasterView): # pylint: disable=abstract-method
)
if self.request.has_perm("orders.view"):
def view_url(order, i): # pylint: disable=unused-argument
return self.request.route_url("orders.view", uuid=order.uuid)
grid.add_action("view", icon="eye", url=view_url)
url = lambda order, i: self.request.route_url(
"orders.view", uuid=order.uuid
)
grid.add_action("view", icon="eye", url=url)
grid.set_link("order_id")
return grid
@ -194,7 +192,7 @@ class LocalProductView(MasterView): # pylint: disable=abstract-method
model = self.app.model
route_prefix = self.get_route_prefix()
batches = {row.batch for row in product.new_order_batch_rows}
batches = set([row.batch for row in product.new_order_batch_rows])
batches = sorted(batches, key=lambda batch: batch.id)
grid = self.make_grid(
@ -218,17 +216,16 @@ class LocalProductView(MasterView): # pylint: disable=abstract-method
)
if self.request.has_perm("neworder_batches.view"):
def view_url(batch, i): # pylint: disable=unused-argument
return self.request.route_url("neworder_batches.view", uuid=batch.uuid)
grid.add_action("view", icon="eye", url=view_url)
url = lambda batch, i: self.request.route_url(
"neworder_batches.view", uuid=batch.uuid
)
grid.add_action("view", icon="eye", url=url)
grid.set_link("id")
return grid
class PendingProductView(MasterView): # pylint: disable=abstract-method
class PendingProductView(MasterView):
"""
Master view for
:class:`~sideshow.db.model.products.PendingProduct`; route
@ -295,9 +292,8 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
"new_order_batches",
]
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
enum = self.app.enum
@ -317,19 +313,16 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
g.set_link("description")
g.set_link("size")
def grid_row_class( # pylint: disable=unused-argument,empty-docstring
self, product, data, i
):
def grid_row_class(self, product, data, i):
""" """
enum = self.app.enum
if product.status == enum.PendingProductStatus.IGNORED:
return "has-background-warning"
return None
def configure_form(self, form): # pylint: disable=empty-docstring
def configure_form(self, f):
""" """
f = form
super().configure_form(f)
enum = self.app.enum
product = f.model_instance
# product_id
@ -376,7 +369,7 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
model = self.app.model
route_prefix = self.get_route_prefix()
orders = {item.order for item in product.order_items}
orders = set([item.order for item in product.order_items])
orders = sorted(orders, key=lambda order: order.order_id)
grid = self.make_grid(
@ -398,11 +391,10 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
)
if self.request.has_perm("orders.view"):
def view_url(order, i): # pylint: disable=unused-argument
return self.request.route_url("orders.view", uuid=order.uuid)
grid.add_action("view", icon="eye", url=view_url)
url = lambda order, i: self.request.route_url(
"orders.view", uuid=order.uuid
)
grid.add_action("view", icon="eye", url=url)
grid.set_link("order_id")
return grid
@ -414,7 +406,7 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
model = self.app.model
route_prefix = self.get_route_prefix()
batches = {row.batch for row in product.new_order_batch_rows}
batches = set([row.batch for row in product.new_order_batch_rows])
batches = sorted(batches, key=lambda batch: batch.id)
grid = self.make_grid(
@ -438,16 +430,15 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
)
if self.request.has_perm("neworder_batches.view"):
def view_url(batch, i): # pylint: disable=unused-argument
return self.request.route_url("neworder_batches.view", uuid=batch.uuid)
grid.add_action("view", icon="eye", url=view_url)
url = lambda batch, i: self.request.route_url(
"neworder_batches.view", uuid=batch.uuid
)
grid.add_action("view", icon="eye", url=url)
grid.set_link("id")
return grid
def get_template_context(self, context): # pylint: disable=empty-docstring
def get_template_context(self, context):
""" """
enum = self.app.enum
@ -461,9 +452,8 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
return context
def delete_instance(self, obj): # pylint: disable=empty-docstring
def delete_instance(self, product):
""" """
product = obj
# avoid deleting if still referenced by new order batch(es)
for row in product.new_order_batch_rows:
@ -541,7 +531,7 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
return self.redirect(self.get_action_url("view", product))
@classmethod
def defaults(cls, config): # pylint: disable=empty-docstring
def defaults(cls, config):
""" """
cls._defaults(config)
cls._pending_product_defaults(config)
@ -586,19 +576,15 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
)
def defaults(config, **kwargs): # pylint: disable=missing-function-docstring
def defaults(config, **kwargs):
base = globals()
LocalProductView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"LocalProductView", base["LocalProductView"]
)
LocalProductView = kwargs.get("LocalProductView", base["LocalProductView"])
LocalProductView.defaults(config)
PendingProductView = ( # pylint: disable=redefined-outer-name,invalid-name
kwargs.get("PendingProductView", base["PendingProductView"])
)
PendingProductView = kwargs.get("PendingProductView", base["PendingProductView"])
PendingProductView.defaults(config)
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
defaults(config)

View file

@ -29,7 +29,7 @@ from wuttaweb.views import MasterView
from sideshow.db.model import Store
class StoreView(MasterView): # pylint: disable=abstract-method
class StoreView(MasterView):
"""
Master view for
:class:`~sideshow.db.model.stores.Store`; route prefix
@ -56,26 +56,21 @@ class StoreView(MasterView): # pylint: disable=abstract-method
sort_defaults = "store_id"
def configure_grid(self, grid): # pylint: disable=empty-docstring
def configure_grid(self, g):
""" """
g = grid
super().configure_grid(g)
# links
g.set_link("store_id")
g.set_link("name")
def grid_row_class( # pylint: disable=unused-argument,empty-docstring
self, store, data, i
):
def grid_row_class(self, store, data, i):
""" """
if store.archived:
return "has-background-warning"
return None
def configure_form(self, form): # pylint: disable=empty-docstring
def configure_form(self, f):
""" """
f = form
super().configure_form(f)
# store_id
@ -84,7 +79,7 @@ class StoreView(MasterView): # pylint: disable=abstract-method
# name
f.set_validator("name", self.unique_name)
def unique_store_id(self, node, value): # pylint: disable=empty-docstring
def unique_store_id(self, node, value):
""" """
model = self.app.model
session = self.Session()
@ -98,7 +93,7 @@ class StoreView(MasterView): # pylint: disable=abstract-method
if query.count():
node.raise_invalid("Store ID must be unique")
def unique_name(self, node, value): # pylint: disable=empty-docstring
def unique_name(self, node, value):
""" """
model = self.app.model
session = self.Session()
@ -113,14 +108,12 @@ class StoreView(MasterView): # pylint: disable=abstract-method
node.raise_invalid("Name must be unique")
def defaults(config, **kwargs): # pylint: disable=missing-function-docstring
def defaults(config, **kwargs):
base = globals()
StoreView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"StoreView", base["StoreView"]
)
StoreView = kwargs.get("StoreView", base["StoreView"])
StoreView.defaults(config)
def includeme(config): # pylint: disable=missing-function-docstring
def includeme(config):
defaults(config)

View file

@ -58,7 +58,6 @@ class TestLocalCustomerView(WebTestCase):
self.assertIn("new_order_batches", form)
def test_make_orders_grid(self):
self.pyramid_config.add_route("orders.view", "/orders/{uuid}/view")
model = self.app.model
view = self.make_view()
@ -80,13 +79,7 @@ class TestLocalCustomerView(WebTestCase):
self.assertEqual(len(grid.actions), 1)
self.assertEqual(grid.actions[0].key, "view")
# render grid for coverage generating url
grid.render_vue_template()
def test_make_new_order_batches_grid(self):
self.pyramid_config.add_route(
"neworder_batches.view", "/batch/neworder/{uuid}/view"
)
model = self.app.model
handler = NewOrderBatchHandler(self.config)
view = self.make_view()
@ -111,9 +104,6 @@ class TestLocalCustomerView(WebTestCase):
self.assertEqual(len(grid.actions), 1)
self.assertEqual(grid.actions[0].key, "view")
# render grid for coverage generating url
grid.render_vue_template()
def test_objectify(self):
model = self.app.model
view = self.make_view()
@ -188,7 +178,6 @@ class TestPendingCustomerView(WebTestCase):
self.assertIn("new_order_batches", form)
def test_make_orders_grid(self):
self.pyramid_config.add_route("orders.view", "/orders/{uuid}/view")
model = self.app.model
enum = self.app.enum
view = self.make_view()
@ -213,13 +202,7 @@ class TestPendingCustomerView(WebTestCase):
self.assertEqual(len(grid.actions), 1)
self.assertEqual(grid.actions[0].key, "view")
# render grid for coverage generating url
grid.render_vue_template()
def test_make_new_order_batches_grid(self):
self.pyramid_config.add_route(
"neworder_batches.view", "/batch/neworder/{uuid}/view"
)
model = self.app.model
enum = self.app.enum
handler = NewOrderBatchHandler(self.config)
@ -247,9 +230,6 @@ class TestPendingCustomerView(WebTestCase):
self.assertEqual(len(grid.actions), 1)
self.assertEqual(grid.actions[0].key, "view")
# render grid for coverage generating url
grid.render_vue_template()
def test_objectify(self):
model = self.app.model
enum = self.app.enum

View file

@ -60,7 +60,6 @@ class TestLocalProductView(WebTestCase):
self.assertIn("local_products.view.orders", form.grid_vue_context)
def test_make_orders_grid(self):
self.pyramid_config.add_route("orders.view", "/orders/{uuid}/view")
model = self.app.model
enum = self.app.enum
view = self.make_view()
@ -90,13 +89,7 @@ class TestLocalProductView(WebTestCase):
self.assertEqual(len(grid.actions), 1)
self.assertEqual(grid.actions[0].key, "view")
# render grid for coverage generating url
grid.render_vue_template()
def test_make_new_order_batches_grid(self):
self.pyramid_config.add_route(
"neworder_batches.view", "/batch/neworder/{uuid}/view"
)
model = self.app.model
enum = self.app.enum
handler = NewOrderBatchHandler(self.config)
@ -124,9 +117,6 @@ class TestLocalProductView(WebTestCase):
self.assertEqual(len(grid.actions), 1)
self.assertEqual(grid.actions[0].key, "view")
# render grid for coverage generating url
grid.render_vue_template()
class TestPendingProductView(WebTestCase):
@ -188,7 +178,6 @@ class TestPendingProductView(WebTestCase):
self.assertIn("created_by", form)
def test_make_orders_grid(self):
self.pyramid_config.add_route("orders.view", "/orders/{uuid}/view")
model = self.app.model
enum = self.app.enum
view = self.make_view()
@ -220,13 +209,7 @@ class TestPendingProductView(WebTestCase):
self.assertEqual(len(grid.actions), 1)
self.assertEqual(grid.actions[0].key, "view")
# render grid for coverage generating url
grid.render_vue_template()
def test_make_new_order_batches_grid(self):
self.pyramid_config.add_route(
"neworder_batches.view", "/batch/neworder/{uuid}/view"
)
model = self.app.model
enum = self.app.enum
handler = NewOrderBatchHandler(self.config)
@ -256,9 +239,6 @@ class TestPendingProductView(WebTestCase):
self.assertEqual(len(grid.actions), 1)
self.assertEqual(grid.actions[0].key, "view")
# render grid for coverage generating url
grid.render_vue_template()
def test_get_template_context(self):
enum = self.app.enum
model = self.app.model