Compare commits

..

29 commits

Author SHA1 Message Date
614189531f docs: add badge for pylint 2025-09-01 15:37:38 -05:00
45e20926ef fix: fix 'abstract-method' for pylint 2025-09-01 15:29:51 -05:00
e0a58dc524 fix: fix 'arguments-differ' for pylint 2025-09-01 15:27:27 -05:00
8008b0edad fix: fix 'attribute-defined-outside-init' for pylint 2025-09-01 15:17:18 -05:00
a56f6e9b91 fix: fix 'broad-exception-caught' for pylint 2025-09-01 15:15:22 -05:00
c3e262804c fix: fix 'consider-using-dict-comprehension' for pylint 2025-09-01 15:13:59 -05:00
3ba57e3640 fix: fix 'consider-using-f-string' for pylint 2025-09-01 15:12:05 -05:00
efa13362e1 fix: fix 'consider-using-set-comprehension' for pylint 2025-09-01 15:10:28 -05:00
8d8f276793 fix: fix 'empty-docstring' for pylint 2025-09-01 15:08:09 -05:00
54602f605d fix: fix 'implicit-str-concat' for pylint 2025-09-01 14:57:23 -05:00
c01f9395f0 fix: fix 'inconsistent-return-statements' for pylint 2025-09-01 14:56:35 -05:00
281d654e32 fix: fix 'invalid-name' for pylint 2025-09-01 14:54:59 -05:00
b2beeb4df3 fix: fix 'missing-class-docstring' and 'missing-function-docstring' for pylint 2025-09-01 14:51:13 -05:00
1374910d65 fix: fix 'no-else-return' for pylint 2025-09-01 14:46:06 -05:00
258a1ed287 fix: fix 'no-member' for pylint 2025-09-01 14:45:16 -05:00
c439bacf4f fix: fix 'no-self-argument' for pylint 2025-09-01 14:43:56 -05:00
5a0d59ee36 fix: fix 'redefined-outer-name' for pylint 2025-09-01 14:35:58 -05:00
d2b5dce8e3 fix: fix 'singleton-comparison' for pylint 2025-09-01 14:32:22 -05:00
e884263779 fix: fix 'too-few-public-methods' for pylint 2025-09-01 14:29:13 -05:00
a4c9e3070c fix: fix 'too-many-branches' for pylint 2025-09-01 14:29:13 -05:00
becf4fa822 fix: fix 'too-many-lines' for pylint 2025-09-01 14:29:13 -05:00
e5dbc4a98c fix: fix 'too-many-locals' for pylint 2025-09-01 14:29:13 -05:00
93855e79d1 fix: fix 'too-many-arguments' for pylint 2025-09-01 14:29:13 -05:00
fee44b455a fix: fix 'too-many-public-methods' for pylint 2025-09-01 14:29:13 -05:00
625a22c83b fix: fix 'unnecessary-lambda-assignment' for pylint 2025-09-01 14:29:10 -05:00
2e248adb82 fix: fix 'unused-argument' for pylint 2025-09-01 14:07:38 -05:00
4194d20988 fix: fix 'unused-import' for pylint 2025-09-01 13:59:49 -05:00
2d61d6aecf fix: fix 'unused-variable' for pylint 2025-09-01 13:58:12 -05:00
7833ad502a fix: fix 'wildcard-import' and 'unused-wildcard-import' for pylint 2025-09-01 13:52:21 -05:00
27 changed files with 423 additions and 295 deletions

View file

@ -3,35 +3,3 @@
[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,6 +10,9 @@ 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 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Sideshow.
#
@ -35,7 +35,7 @@ class SideshowAppProvider(base.AppProvider):
handler`.
"""
def get_order_handler(self, **kwargs):
def get_order_handler(self):
"""
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 "order_handler" not in self.__dict__:
if "orders" not in self.app.handlers:
spec = self.config.get(
"sideshow.orders.handler_spec", default="sideshow.orders:OrderHandler"
)
self.order_handler = self.app.load_object(spec)(self.config)
return self.order_handler
self.app.handlers["orders"] = self.app.load_object(spec)(self.config)
return self.app.handlers["orders"]

View file

@ -23,6 +23,7 @@
"""
New Order Batch Handler
"""
# pylint: disable=too-many-lines
import datetime
import decimal
@ -35,7 +36,7 @@ from wuttjamaican.batch import BatchHandler
from sideshow.db.model import NewOrderBatch
class NewOrderBatchHandler(BatchHandler):
class NewOrderBatchHandler(BatchHandler): # pylint: disable=too-many-public-methods
"""
The :term:`batch handler` for :term:`new order batches <new order
batch>`.
@ -116,6 +117,7 @@ class NewOrderBatchHandler(BatchHandler):
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):
"""
@ -137,7 +139,9 @@ class NewOrderBatchHandler(BatchHandler):
"""
raise NotImplementedError
def autocomplete_customers_local(self, session, term, user=None):
def autocomplete_customers_local( # pylint: disable=unused-argument
self, session, term, user=None
):
"""
Return autocomplete search results for
:class:`~sideshow.db.model.customers.LocalCustomer` records.
@ -343,7 +347,9 @@ class NewOrderBatchHandler(BatchHandler):
"""
raise NotImplementedError
def autocomplete_products_local(self, session, term, user=None):
def autocomplete_products_local( # pylint: disable=unused-argument
self, session, term, user=None
):
"""
Return autocomplete search results for
:class:`~sideshow.db.model.products.LocalProduct` records.
@ -468,7 +474,9 @@ class NewOrderBatchHandler(BatchHandler):
"""
raise NotImplementedError
def get_product_info_local(self, session, uuid, user=None):
def get_product_info_local( # pylint: disable=unused-argument
self, session, uuid, user=None
):
"""
Returns basic info for a :term:`local product` as pertains to
ordering.
@ -597,7 +605,6 @@ class NewOrderBatchHandler(BatchHandler):
: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
@ -650,7 +657,7 @@ class NewOrderBatchHandler(BatchHandler):
return products
def add_item(
def add_item( # pylint: disable=too-many-arguments,too-many-positional-arguments,too-many-locals
self,
batch,
product_info,
@ -761,7 +768,7 @@ class NewOrderBatchHandler(BatchHandler):
session.flush()
return row
def update_item(
def update_item( # pylint: disable=too-many-arguments,too-many-positional-arguments
self, row, product_info, order_qty, order_uom, discount_percent=None, user=None
):
"""
@ -865,7 +872,7 @@ class NewOrderBatchHandler(BatchHandler):
# refresh per new info
self.refresh_row(row)
def refresh_row(self, row):
def refresh_row(self, row): # pylint: disable=too-many-branches
"""
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
@ -1023,7 +1030,7 @@ class NewOrderBatchHandler(BatchHandler):
super().remove_row(row)
def do_delete(self, batch, user, **kwargs):
def do_delete(self, batch, user, **kwargs): # pylint: disable=arguments-differ
"""
Delete a batch completely.
@ -1047,7 +1054,7 @@ class NewOrderBatchHandler(BatchHandler):
# continue with normal deletion
super().do_delete(batch, user, **kwargs)
def why_not_execute(self, batch, **kwargs):
def why_not_execute(self, batch, **kwargs): # pylint: disable=arguments-differ
"""
By default this checks to ensure the batch has a customer with
phone number, and at least one item. It also may check to
@ -1068,6 +1075,8 @@ class NewOrderBatchHandler(BatchHandler):
if not rows:
return "Must add at least one valid item"
return None
def get_effective_rows(self, batch):
"""
Only rows with
@ -1188,7 +1197,7 @@ class NewOrderBatchHandler(BatchHandler):
session.flush()
def make_new_order(self, batch, rows, user=None, progress=None, **kwargs):
def make_new_order(self, batch, rows, user=None, progress=None):
"""
Create a new :term:`order` from the batch data.
@ -1205,7 +1214,6 @@ class NewOrderBatchHandler(BatchHandler):
:returns: :class:`~sideshow.db.model.orders.Order` instance.
"""
model = self.app.model
enum = self.app.enum
session = self.app.get_session(batch)
batch_fields = [
@ -1247,17 +1255,17 @@ class NewOrderBatchHandler(BatchHandler):
]
# make order
kw = dict([(field, getattr(batch, field)) for field in batch_fields])
kw = {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):
def convert(row, i): # pylint: disable=unused-argument
# make order item
kw = dict([(field, getattr(row, field)) for field in row_fields])
kw = {field: getattr(row, field) for field in row_fields}
item = model.OrderItem(**kw)
order.items.append(item)
@ -1270,7 +1278,7 @@ class NewOrderBatchHandler(BatchHandler):
session.flush()
return order
def set_initial_item_status(self, item, user, **kwargs):
def set_initial_item_status(self, item, user):
"""
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 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Sideshow.
#
@ -38,10 +38,10 @@ def install(
"""
config = ctx.parent.wutta_config
app = config.get_app()
install = app.get_install_handler(
handler = app.get_install_handler(
pkg_name="sideshow",
app_title="Sideshow",
pypi_name="Sideshow",
egg_name="Sideshow",
)
install.run()
handler.run()

View file

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

View file

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

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Sideshow.
#
@ -34,7 +34,7 @@ from wuttjamaican.db import model
from sideshow.enum import PendingCustomerStatus
class CustomerMixin:
class CustomerMixin: # pylint: disable=too-few-public-methods
"""
Base class for customer tables. This has shared columns, used by e.g.:
@ -86,7 +86,9 @@ class CustomerMixin:
return self.full_name or ""
class LocalCustomer(CustomerMixin, model.Base):
class LocalCustomer( # pylint: disable=too-few-public-methods
CustomerMixin, model.Base
):
"""
This table contains the :term:`local customer` records.
@ -136,7 +138,9 @@ class LocalCustomer(CustomerMixin, model.Base):
)
class PendingCustomer(CustomerMixin, model.Base):
class PendingCustomer( # pylint: disable=too-few-public-methods
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):
class Order(model.Base): # pylint: disable=too-few-public-methods
"""
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):
def full_description(self): # pylint: disable=empty-docstring
""" """
fields = [
self.product_brand or "",
@ -542,7 +542,7 @@ class OrderItem(model.Base):
self.events.append(OrderItemEvent(**kwargs))
class OrderItemEvent(model.Base):
class OrderItemEvent(model.Base): # pylint: disable=too-few-public-methods
"""
An event in the life of an :term:`order item`.
"""

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Sideshow.
#
@ -169,7 +169,7 @@ class ProductMixin:
)
@property
def full_description(self):
def full_description(self): # pylint: disable=empty-docstring
""" """
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):
class LocalProduct(ProductMixin, model.Base): # pylint: disable=too-few-public-methods
"""
This table contains the :term:`local product` records.
@ -228,7 +228,9 @@ class LocalProduct(ProductMixin, model.Base):
)
class PendingProduct(ProductMixin, model.Base):
class PendingProduct( # pylint: disable=too-few-public-methods
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 *
from wuttjamaican.enum import * # pylint: disable=wildcard-import,unused-wildcard-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]
EA = enum.ORDER_UOM[enum.ORDER_UOM_UNIT]
CS = enum.ORDER_UOM[enum.ORDER_UOM_CASE] # pylint: disable=invalid-name
EA = enum.ORDER_UOM[enum.ORDER_UOM_UNIT] # pylint: disable=invalid-name
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]
EA = enum.ORDER_UOM[enum.ORDER_UOM_UNIT] # pylint: disable=invalid-name
return f"{unit_qty} {EA}"
def item_status_to_variant(self, status_code):
@ -105,6 +105,7 @@ class OrderHandler(GenericHandler):
enum.ORDER_ITEM_STATUS_INACTIVE,
):
return "warning"
return None
def resolve_pending_product(self, pending_product, product_info, user, note=None):
"""
@ -159,7 +160,10 @@ class OrderHandler(GenericHandler):
items = (
session.query(model.OrderItem)
.filter(model.OrderItem.pending_product == pending_product)
.filter(model.OrderItem.product_id == None)
.filter(
model.OrderItem.product_id # pylint: disable=singleton-comparison
== None
)
.all()
)
@ -183,7 +187,7 @@ class OrderHandler(GenericHandler):
if note:
item.add_event(enum.ORDER_ITEM_EVENT_NOTE_ADDED, user, note=note)
def process_placement(
def process_placement( # pylint: disable=too-many-arguments,too-many-positional-arguments
self, items, user, vendor_name=None, po_number=None, note=None
):
"""
@ -226,7 +230,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(
def process_receiving( # pylint: disable=too-many-arguments,too-many-positional-arguments
self,
items,
user,

View file

@ -28,6 +28,10 @@ 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 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Sideshow.
#
@ -25,7 +25,7 @@ Sideshow web app
"""
def includeme(config):
def includeme(config): # pylint: disable=missing-function-docstring
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 Lance Edgar
# Copyright © 2024-2025 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):
def main(global_config, **settings): # pylint: disable=unused-argument
"""
Make and return the WSGI app (Paste entry point).
"""
@ -41,7 +41,7 @@ def main(global_config, **settings):
)
# make config objects
wutta_config = base.make_wutta_config(settings)
wutta_config = base.make_wutta_config(settings) # pylint: disable=unused-variable
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 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Sideshow.
#
@ -37,17 +37,18 @@ class OrderRef(ObjectRef):
"""
@property
def model_class(self):
def model_class(self): # pylint: disable=empty-docstring
""" """
model = self.app.model
return model.Order
def sort_query(self, query):
def sort_query(self, query): # pylint: disable=empty-docstring
""" """
return query.order_by(self.model_class.order_id)
def get_object_url(self, order):
def get_object_url(self, obj): # pylint: disable=empty-docstring
""" """
order = obj
return self.request.route_url("orders.view", uuid=order.uuid)
@ -62,17 +63,18 @@ class LocalCustomerRef(ObjectRef):
"""
@property
def model_class(self):
def model_class(self): # pylint: disable=empty-docstring
""" """
model = self.app.model
return model.LocalCustomer
def sort_query(self, query):
def sort_query(self, query): # pylint: disable=empty-docstring
""" """
return query.order_by(self.model_class.full_name)
def get_object_url(self, customer):
def get_object_url(self, obj): # pylint: disable=empty-docstring
""" """
customer = obj
return self.request.route_url("local_customers.view", uuid=customer.uuid)
@ -87,17 +89,18 @@ class PendingCustomerRef(ObjectRef):
"""
@property
def model_class(self):
def model_class(self): # pylint: disable=empty-docstring
""" """
model = self.app.model
return model.PendingCustomer
def sort_query(self, query):
def sort_query(self, query): # pylint: disable=empty-docstring
""" """
return query.order_by(self.model_class.full_name)
def get_object_url(self, customer):
def get_object_url(self, obj): # pylint: disable=empty-docstring
""" """
customer = obj
return self.request.route_url("pending_customers.view", uuid=customer.uuid)
@ -111,17 +114,18 @@ class LocalProductRef(ObjectRef):
"""
@property
def model_class(self):
def model_class(self): # pylint: disable=empty-docstring
""" """
model = self.app.model
return model.LocalProduct
def sort_query(self, query):
def sort_query(self, query): # pylint: disable=empty-docstring
""" """
return query.order_by(self.model_class.scancode)
def get_object_url(self, product):
def get_object_url(self, obj): # pylint: disable=empty-docstring
""" """
product = obj
return self.request.route_url("local_products.view", uuid=product.uuid)
@ -136,15 +140,16 @@ class PendingProductRef(ObjectRef):
"""
@property
def model_class(self):
def model_class(self): # pylint: disable=empty-docstring
""" """
model = self.app.model
return model.PendingProduct
def sort_query(self, query):
def sort_query(self, query): # pylint: disable=empty-docstring
""" """
return query.order_by(self.model_class.scancode)
def get_object_url(self, product):
def get_object_url(self, obj): # pylint: disable=empty-docstring
""" """
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 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Sideshow.
#
@ -32,7 +32,7 @@ class SideshowMenuHandler(base.MenuHandler):
Sideshow menu handler
"""
def make_menus(self, request, **kwargs):
def make_menus(self, request): # pylint: disable=empty-docstring
""" """
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, **kwargs):
def make_orders_menu(self, request): # pylint: disable=unused-argument
"""
Generate the Orders menu.
"""
@ -91,7 +91,7 @@ class SideshowMenuHandler(base.MenuHandler):
],
}
def make_customers_menu(self, request, **kwargs):
def make_customers_menu(self, request): # pylint: disable=unused-argument
"""
Generate the Customers menu.
"""
@ -112,7 +112,7 @@ class SideshowMenuHandler(base.MenuHandler):
],
}
def make_products_menu(self, request, **kwargs):
def make_products_menu(self, request): # pylint: disable=unused-argument
"""
Generate the Products menu.
"""
@ -133,7 +133,7 @@ class SideshowMenuHandler(base.MenuHandler):
],
}
def make_batch_menu(self, request, **kwargs):
def make_batch_menu(self, request): # pylint: disable=unused-argument
"""
Generate the Batch menu.
"""
@ -149,7 +149,7 @@ class SideshowMenuHandler(base.MenuHandler):
],
}
def make_other_menu(self, request, **kwargs):
def make_other_menu(self, request): # pylint: disable=unused-argument
"""
Generate the "Other" menu.
"""
@ -159,7 +159,7 @@ class SideshowMenuHandler(base.MenuHandler):
"items": [],
}
def make_admin_menu(self, request, **kwargs):
def make_admin_menu(self, request, **kwargs): # pylint: disable=empty-docstring
""" """
kwargs["include_people"] = True
menu = super().make_admin_menu(request, **kwargs)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024 Lance Edgar
# Copyright © 2024-2025 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):
def includeme(config): # pylint: disable=missing-function-docstring
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):
def includeme(config): # pylint: disable=missing-function-docstring
# 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):
class NewOrderBatchView(BatchMasterView): # pylint: disable=abstract-method
"""
Master view for :class:`~sideshow.db.model.batch.neworder.NewOrderBatch`.
@ -131,13 +131,14 @@ class NewOrderBatchView(BatchMasterView):
super().__init__(request, context=context)
self.order_handler = self.app.get_order_handler()
def get_batch_handler(self):
def get_batch_handler(self): # pylint: disable=empty-docstring
""" """
# TODO: call self.app.get_batch_handler()
return NewOrderBatchHandler(self.config)
def configure_grid(self, g):
def configure_grid(self, grid): # pylint: disable=empty-docstring
""" """
g = grid
super().configure_grid(g)
# store_id
@ -147,8 +148,9 @@ class NewOrderBatchView(BatchMasterView):
# total_price
g.set_renderer("total_price", "currency")
def configure_form(self, f):
def configure_form(self, form): # pylint: disable=empty-docstring
""" """
f = form
super().configure_form(f)
# store_id
@ -164,10 +166,10 @@ class NewOrderBatchView(BatchMasterView):
# total_price
f.set_node("total_price", WuttaMoney(self.request))
def configure_row_grid(self, g):
def configure_row_grid(self, grid): # pylint: disable=empty-docstring
""" """
g = grid
super().configure_row_grid(g)
enum = self.app.enum
# TODO
# order_uom
@ -188,12 +190,13 @@ class NewOrderBatchView(BatchMasterView):
# total_price
g.set_renderer("total_price", "currency")
def get_xref_buttons(self, batch):
def get_xref_buttons(self, obj):
"""
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()
@ -215,12 +218,14 @@ class NewOrderBatchView(BatchMasterView):
return buttons
def defaults(config, **kwargs):
def defaults(config, **kwargs): # pylint: disable=missing-function-docstring
base = globals()
NewOrderBatchView = kwargs.get("NewOrderBatchView", base["NewOrderBatchView"])
NewOrderBatchView = kwargs.get( # pylint: disable=redefined-outer-name,invalid-name
"NewOrderBatchView", base["NewOrderBatchView"]
)
NewOrderBatchView.defaults(config)
def includeme(config):
def includeme(config): # pylint: disable=missing-function-docstring
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):
def includeme(config): # pylint: disable=missing-function-docstring
base.defaults(config, **{"CommonView": CommonView})

View file

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

View file

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

View file

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

View file

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

View file

@ -58,6 +58,7 @@ 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()
@ -79,7 +80,13 @@ 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()
@ -104,6 +111,9 @@ 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()
@ -178,6 +188,7 @@ 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()
@ -202,7 +213,13 @@ 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)
@ -230,6 +247,9 @@ 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,6 +60,7 @@ 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()
@ -89,7 +90,13 @@ 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)
@ -117,6 +124,9 @@ 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):
@ -178,6 +188,7 @@ 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()
@ -209,7 +220,13 @@ 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)
@ -239,6 +256,9 @@ 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