Compare commits
	
		
			No commits in common. "614189531f3ce279d812da2a9b1347a0e72c0afc" and "04de98a7870234be6f143c1f6158c6094c1f5e1d" have entirely different histories.
		
	
	
		
			614189531f
			...
			04de98a787
		
	
		
					 27 changed files with 295 additions and 423 deletions
				
			
		
							
								
								
									
										32
									
								
								.pylintrc
									
										
									
									
									
								
							
							
						
						
									
										32
									
								
								.pylintrc
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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`.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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).
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 = "×" 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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"]
 | 
			
		||||
                for d in self.get_dept_item_discounts()
 | 
			
		||||
            }
 | 
			
		||||
            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,9 +381,10 @@ class OrderView(MasterView):  # pylint: disable=too-many-public-methods
 | 
			
		|||
            return handler.autocomplete_customers_local(
 | 
			
		||||
                session, term, user=self.request.user
 | 
			
		||||
            )
 | 
			
		||||
        return handler.autocomplete_customers_external(
 | 
			
		||||
            session, term, user=self.request.user
 | 
			
		||||
        )
 | 
			
		||||
        else:
 | 
			
		||||
            return handler.autocomplete_customers_external(
 | 
			
		||||
                session, term, user=self.request.user
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    def product_autocomplete(self):
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -405,11 +409,12 @@ class OrderView(MasterView):  # pylint: disable=too-many-public-methods
 | 
			
		|||
            return handler.autocomplete_products_local(
 | 
			
		||||
                session, term, user=self.request.user
 | 
			
		||||
            )
 | 
			
		||||
        return handler.autocomplete_products_external(
 | 
			
		||||
            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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue