fix: consolidate some duplicated code
i feel like there was a reason i hadn't done that to begin with, but now can't recall for sure. pylint certainly thinks it is duplicated so mostly cleaning this up per its suggestion...
This commit is contained in:
parent
49261a696d
commit
4e7c8d393c
8 changed files with 402 additions and 738 deletions
6
docs/api/sideshow.web.util.rst
Normal file
6
docs/api/sideshow.web.util.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
``sideshow.web.util``
|
||||
=====================
|
||||
|
||||
.. automodule:: sideshow.web.util
|
||||
:members:
|
|
@ -59,6 +59,7 @@ For an online demo see https://demo.wuttaproject.org/
|
|||
api/sideshow.web.forms.schema
|
||||
api/sideshow.web.menus
|
||||
api/sideshow.web.static
|
||||
api/sideshow.web.util
|
||||
api/sideshow.web.views
|
||||
api/sideshow.web.views.batch
|
||||
api/sideshow.web.views.batch.neworder
|
||||
|
|
|
@ -33,8 +33,10 @@ from sqlalchemy.ext.declarative import declared_attr
|
|||
|
||||
from wuttjamaican.db import model
|
||||
|
||||
from sideshow.db.model.orders import OrderMixin, OrderItemMixin
|
||||
|
||||
class NewOrderBatch(model.BatchMixin, model.Base):
|
||||
|
||||
class NewOrderBatch(model.BatchMixin, OrderMixin, model.Base):
|
||||
"""
|
||||
:term:`Batch <batch>` used for entering new :term:`orders <order>`
|
||||
into the system. Each batch ultimately becomes an
|
||||
|
@ -73,25 +75,6 @@ class NewOrderBatch(model.BatchMixin, model.Base):
|
|||
STATUS_OK: "ok",
|
||||
}
|
||||
|
||||
store_id = sa.Column(
|
||||
sa.String(length=10),
|
||||
nullable=True,
|
||||
doc="""
|
||||
ID of the store to which the order pertains, if applicable.
|
||||
""",
|
||||
)
|
||||
|
||||
customer_id = sa.Column(
|
||||
sa.String(length=20),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Proper account ID for the :term:`external customer` to which the
|
||||
order pertains, if applicable.
|
||||
|
||||
See also :attr:`local_customer` and :attr:`pending_customer`.
|
||||
""",
|
||||
)
|
||||
|
||||
local_customer_uuid = sa.Column(model.UUID(), nullable=True)
|
||||
|
||||
@declared_attr
|
||||
|
@ -100,6 +83,7 @@ class NewOrderBatch(model.BatchMixin, model.Base):
|
|||
):
|
||||
return orm.relationship(
|
||||
"LocalCustomer",
|
||||
cascade_backrefs=False,
|
||||
back_populates="new_order_batches",
|
||||
doc="""
|
||||
Reference to the
|
||||
|
@ -118,6 +102,7 @@ class NewOrderBatch(model.BatchMixin, model.Base):
|
|||
):
|
||||
return orm.relationship(
|
||||
"PendingCustomer",
|
||||
cascade_backrefs=False,
|
||||
back_populates="new_order_batches",
|
||||
doc="""
|
||||
Reference to the
|
||||
|
@ -128,40 +113,8 @@ class NewOrderBatch(model.BatchMixin, model.Base):
|
|||
""",
|
||||
)
|
||||
|
||||
customer_name = sa.Column(
|
||||
sa.String(length=100),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Name for the customer account.
|
||||
""",
|
||||
)
|
||||
|
||||
phone_number = sa.Column(
|
||||
sa.String(length=20),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Phone number for the customer.
|
||||
""",
|
||||
)
|
||||
|
||||
email_address = sa.Column(
|
||||
sa.String(length=255),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Email address for the customer.
|
||||
""",
|
||||
)
|
||||
|
||||
total_price = sa.Column(
|
||||
sa.Numeric(precision=10, scale=3),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Full price (not including tax etc.) for all items on the order.
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
class NewOrderBatchRow(model.BatchRowMixin, model.Base):
|
||||
class NewOrderBatchRow(model.BatchRowMixin, OrderItemMixin, model.Base):
|
||||
"""
|
||||
Row of data within a :class:`NewOrderBatch`. Each row ultimately
|
||||
becomes an :class:`~sideshow.db.model.orders.OrderItem`.
|
||||
|
@ -212,17 +165,6 @@ class NewOrderBatchRow(model.BatchRowMixin, model.Base):
|
|||
Dict of possible status code -> label options.
|
||||
"""
|
||||
|
||||
product_id = sa.Column(
|
||||
sa.String(length=20),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Proper ID for the :term:`external product` which the order item
|
||||
represents, if applicable.
|
||||
|
||||
See also :attr:`local_product` and :attr:`pending_product`.
|
||||
""",
|
||||
)
|
||||
|
||||
local_product_uuid = sa.Column(model.UUID(), nullable=True)
|
||||
|
||||
@declared_attr
|
||||
|
@ -231,6 +173,7 @@ class NewOrderBatchRow(model.BatchRowMixin, model.Base):
|
|||
):
|
||||
return orm.relationship(
|
||||
"LocalProduct",
|
||||
cascade_backrefs=False,
|
||||
back_populates="new_order_batch_rows",
|
||||
doc="""
|
||||
Reference to the
|
||||
|
@ -249,6 +192,7 @@ class NewOrderBatchRow(model.BatchRowMixin, model.Base):
|
|||
):
|
||||
return orm.relationship(
|
||||
"PendingProduct",
|
||||
cascade_backrefs=False,
|
||||
back_populates="new_order_batch_rows",
|
||||
doc="""
|
||||
Reference to the
|
||||
|
@ -259,224 +203,5 @@ class NewOrderBatchRow(model.BatchRowMixin, model.Base):
|
|||
""",
|
||||
)
|
||||
|
||||
product_scancode = sa.Column(
|
||||
sa.String(length=14),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Scancode for the product, as string.
|
||||
|
||||
.. note::
|
||||
|
||||
This column allows 14 chars, so can store a full GPC with check
|
||||
digit. However as of writing the actual format used here does
|
||||
not matter to Sideshow logic; "anything" should work.
|
||||
|
||||
That may change eventually, depending on POS integration
|
||||
scenarios that come up. Maybe a config option to declare
|
||||
whether check digit should be included or not, etc.
|
||||
""",
|
||||
)
|
||||
|
||||
product_brand = sa.Column(
|
||||
sa.String(length=100),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Brand name for the product - up to 100 chars.
|
||||
""",
|
||||
)
|
||||
|
||||
product_description = sa.Column(
|
||||
sa.String(length=255),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Description for the product - up to 255 chars.
|
||||
""",
|
||||
)
|
||||
|
||||
product_size = sa.Column(
|
||||
sa.String(length=30),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Size of the product, as string - up to 30 chars.
|
||||
""",
|
||||
)
|
||||
|
||||
product_weighed = sa.Column(
|
||||
sa.Boolean(),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Flag indicating the product is sold by weight; default is null.
|
||||
""",
|
||||
)
|
||||
|
||||
department_id = sa.Column(
|
||||
sa.String(length=10),
|
||||
nullable=True,
|
||||
doc="""
|
||||
ID of the department to which the product belongs, if known.
|
||||
""",
|
||||
)
|
||||
|
||||
department_name = sa.Column(
|
||||
sa.String(length=30),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Name of the department to which the product belongs, if known.
|
||||
""",
|
||||
)
|
||||
|
||||
special_order = sa.Column(
|
||||
sa.Boolean(),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Flag indicating the item is a "special order" - e.g. something not
|
||||
normally carried by the store. Default is null.
|
||||
""",
|
||||
)
|
||||
|
||||
vendor_name = sa.Column(
|
||||
sa.String(length=50),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Name of vendor from which product may be purchased, if known. See
|
||||
also :attr:`vendor_item_code`.
|
||||
""",
|
||||
)
|
||||
|
||||
vendor_item_code = sa.Column(
|
||||
sa.String(length=20),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Item code (SKU) to use when ordering this product from the vendor
|
||||
identified by :attr:`vendor_name`, if known.
|
||||
""",
|
||||
)
|
||||
|
||||
case_size = sa.Column(
|
||||
sa.Numeric(precision=10, scale=4),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Case pack count for the product, if known.
|
||||
|
||||
If this is not set, then customer cannot order a "case" of the item.
|
||||
""",
|
||||
)
|
||||
|
||||
order_qty = sa.Column(
|
||||
sa.Numeric(precision=10, scale=4),
|
||||
nullable=False,
|
||||
doc="""
|
||||
Quantity (as decimal) of product being ordered.
|
||||
|
||||
This must be interpreted along with :attr:`order_uom` to determine
|
||||
the *complete* order quantity, e.g. "2 cases".
|
||||
""",
|
||||
)
|
||||
|
||||
order_uom = sa.Column(
|
||||
sa.String(length=10),
|
||||
nullable=False,
|
||||
doc="""
|
||||
Code indicating the unit of measure for product being ordered.
|
||||
|
||||
This should be one of the codes from
|
||||
:data:`~sideshow.enum.ORDER_UOM`.
|
||||
|
||||
Sideshow will treat :data:`~sideshow.enum.ORDER_UOM_CASE`
|
||||
differently but :data:`~sideshow.enum.ORDER_UOM_UNIT` and others
|
||||
are all treated the same (i.e. "unit" is assumed).
|
||||
""",
|
||||
)
|
||||
|
||||
unit_cost = sa.Column(
|
||||
sa.Numeric(precision=9, scale=5),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Cost of goods amount for one "unit" (not "case") of the product,
|
||||
as decimal to 4 places.
|
||||
""",
|
||||
)
|
||||
|
||||
unit_price_reg = sa.Column(
|
||||
sa.Numeric(precision=8, scale=3),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Regular price for the item unit. Unless a sale is in effect,
|
||||
:attr:`unit_price_quoted` will typically match this value.
|
||||
""",
|
||||
)
|
||||
|
||||
unit_price_sale = sa.Column(
|
||||
sa.Numeric(precision=8, scale=3),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Sale price for the item unit, if applicable. If set, then
|
||||
:attr:`unit_price_quoted` will typically match this value. See
|
||||
also :attr:`sale_ends`.
|
||||
""",
|
||||
)
|
||||
|
||||
sale_ends = sa.Column(
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=True,
|
||||
doc="""
|
||||
End date/time for the sale in effect, if any.
|
||||
|
||||
This is only relevant if :attr:`unit_price_sale` is set.
|
||||
""",
|
||||
)
|
||||
|
||||
unit_price_quoted = sa.Column(
|
||||
sa.Numeric(precision=8, scale=3),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Quoted price for the item unit. This is the "effective" unit
|
||||
price, which is used to calculate :attr:`total_price`.
|
||||
|
||||
This price does *not* reflect the :attr:`discount_percent`. It
|
||||
normally should match either :attr:`unit_price_reg` or
|
||||
:attr:`unit_price_sale`.
|
||||
|
||||
See also :attr:`case_price_quoted`, if applicable.
|
||||
""",
|
||||
)
|
||||
|
||||
case_price_quoted = sa.Column(
|
||||
sa.Numeric(precision=8, scale=3),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Quoted price for a "case" of the item, if applicable.
|
||||
|
||||
This is mostly for display purposes; :attr:`unit_price_quoted` is
|
||||
used for calculations.
|
||||
""",
|
||||
)
|
||||
|
||||
discount_percent = sa.Column(
|
||||
sa.Numeric(precision=5, scale=3),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Discount percent to apply when calculating :attr:`total_price`, if
|
||||
applicable.
|
||||
""",
|
||||
)
|
||||
|
||||
total_price = sa.Column(
|
||||
sa.Numeric(precision=8, scale=3),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Full price (not including tax etc.) which the customer is quoted
|
||||
for the order item.
|
||||
|
||||
This is calculated using values from:
|
||||
|
||||
* :attr:`unit_price_quoted`
|
||||
* :attr:`order_qty`
|
||||
* :attr:`order_uom`
|
||||
* :attr:`case_size`
|
||||
* :attr:`discount_percent`
|
||||
""",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.pending_product or self.product_description or "")
|
||||
|
|
|
@ -33,36 +33,12 @@ from sqlalchemy.ext.orderinglist import ordering_list
|
|||
from wuttjamaican.db import model
|
||||
|
||||
|
||||
class Order(model.Base): # pylint: disable=too-few-public-methods
|
||||
class OrderMixin: # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
Represents an :term:`order` for a customer. Each order has one or
|
||||
more :attr:`items`.
|
||||
|
||||
Usually, orders are created by way of a
|
||||
:class:`~sideshow.db.model.batch.neworder.NewOrderBatch`.
|
||||
Mixin class providing common columns for orders and new order
|
||||
batches.
|
||||
"""
|
||||
|
||||
__tablename__ = "sideshow_order"
|
||||
|
||||
# TODO: this feels a bit hacky yet but it does avoid problems
|
||||
# showing the Orders grid for a PendingCustomer
|
||||
__colanderalchemy_config__ = {
|
||||
"excludes": ["items"],
|
||||
}
|
||||
|
||||
uuid = model.uuid_column()
|
||||
|
||||
order_id = sa.Column(
|
||||
sa.Integer(),
|
||||
nullable=False,
|
||||
doc="""
|
||||
Unique ID for the order.
|
||||
|
||||
When the order is created from New Order Batch, this order ID will
|
||||
match the batch ID.
|
||||
""",
|
||||
)
|
||||
|
||||
store_id = sa.Column(
|
||||
sa.String(length=10),
|
||||
nullable=True,
|
||||
|
@ -71,16 +47,6 @@ class Order(model.Base): # pylint: disable=too-few-public-methods
|
|||
""",
|
||||
)
|
||||
|
||||
store = orm.relationship(
|
||||
"Store",
|
||||
primaryjoin="Store.store_id == Order.store_id",
|
||||
foreign_keys="Order.store_id",
|
||||
doc="""
|
||||
Reference to the :class:`~sideshow.db.model.stores.Store`
|
||||
record, if applicable.
|
||||
""",
|
||||
)
|
||||
|
||||
customer_id = sa.Column(
|
||||
sa.String(length=20),
|
||||
nullable=True,
|
||||
|
@ -92,38 +58,6 @@ class Order(model.Base): # pylint: disable=too-few-public-methods
|
|||
""",
|
||||
)
|
||||
|
||||
local_customer_uuid = model.uuid_fk_column(
|
||||
"sideshow_customer_local.uuid", nullable=True
|
||||
)
|
||||
local_customer = orm.relationship(
|
||||
"LocalCustomer",
|
||||
cascade_backrefs=False,
|
||||
back_populates="orders",
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~sideshow.db.model.customers.LocalCustomer` record
|
||||
for the order, if applicable.
|
||||
|
||||
See also :attr:`customer_id` and :attr:`pending_customer`.
|
||||
""",
|
||||
)
|
||||
|
||||
pending_customer_uuid = model.uuid_fk_column(
|
||||
"sideshow_customer_pending.uuid", nullable=True
|
||||
)
|
||||
pending_customer = orm.relationship(
|
||||
"PendingCustomer",
|
||||
cascade_backrefs=False,
|
||||
back_populates="orders",
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~sideshow.db.model.customers.PendingCustomer` record
|
||||
for the order, if applicable.
|
||||
|
||||
See also :attr:`customer_id` and :attr:`local_customer`.
|
||||
""",
|
||||
)
|
||||
|
||||
customer_name = sa.Column(
|
||||
sa.String(length=100),
|
||||
nullable=True,
|
||||
|
@ -156,76 +90,13 @@ class Order(model.Base): # pylint: disable=too-few-public-methods
|
|||
""",
|
||||
)
|
||||
|
||||
created = sa.Column(
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=False,
|
||||
default=datetime.datetime.now,
|
||||
doc="""
|
||||
Timestamp when the order was created.
|
||||
|
||||
If the order is created via New Order Batch, this will match the
|
||||
batch execution timestamp.
|
||||
""",
|
||||
)
|
||||
|
||||
created_by_uuid = model.uuid_fk_column("user.uuid", nullable=False)
|
||||
created_by = orm.relationship(
|
||||
model.User,
|
||||
cascade_backrefs=False,
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~wuttjamaican:wuttjamaican.db.model.auth.User` who
|
||||
created the order.
|
||||
""",
|
||||
)
|
||||
|
||||
items = orm.relationship(
|
||||
"OrderItem",
|
||||
collection_class=ordering_list("sequence", count_from=1),
|
||||
cascade="all, delete-orphan",
|
||||
cascade_backrefs=False,
|
||||
back_populates="order",
|
||||
doc="""
|
||||
List of :class:`OrderItem` records belonging to the order.
|
||||
""",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.order_id)
|
||||
|
||||
|
||||
class OrderItem(model.Base):
|
||||
class OrderItemMixin: # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
Represents an :term:`order item` within an :class:`Order`.
|
||||
|
||||
Usually these are created from
|
||||
:class:`~sideshow.db.model.batch.neworder.NewOrderBatchRow`
|
||||
records.
|
||||
Mixin class providing common columns for order items and new order
|
||||
batch rows.
|
||||
"""
|
||||
|
||||
__tablename__ = "sideshow_order_item"
|
||||
|
||||
uuid = model.uuid_column()
|
||||
|
||||
order_uuid = model.uuid_fk_column("sideshow_order.uuid", nullable=False)
|
||||
order = orm.relationship(
|
||||
Order,
|
||||
cascade_backrefs=False,
|
||||
back_populates="items",
|
||||
doc="""
|
||||
Reference to the :class:`Order` to which the item belongs.
|
||||
""",
|
||||
)
|
||||
|
||||
sequence = sa.Column(
|
||||
sa.Integer(),
|
||||
nullable=False,
|
||||
doc="""
|
||||
1-based numeric sequence for the item, i.e. its line number within
|
||||
the order.
|
||||
""",
|
||||
)
|
||||
|
||||
product_id = sa.Column(
|
||||
sa.String(length=20),
|
||||
nullable=True,
|
||||
|
@ -237,38 +108,6 @@ class OrderItem(model.Base):
|
|||
""",
|
||||
)
|
||||
|
||||
local_product_uuid = model.uuid_fk_column(
|
||||
"sideshow_product_local.uuid", nullable=True
|
||||
)
|
||||
local_product = orm.relationship(
|
||||
"LocalProduct",
|
||||
cascade_backrefs=False,
|
||||
back_populates="order_items",
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~sideshow.db.model.products.LocalProduct` record for
|
||||
the order item, if applicable.
|
||||
|
||||
See also :attr:`product_id` and :attr:`pending_product`.
|
||||
""",
|
||||
)
|
||||
|
||||
pending_product_uuid = model.uuid_fk_column(
|
||||
"sideshow_product_pending.uuid", nullable=True
|
||||
)
|
||||
pending_product = orm.relationship(
|
||||
"PendingProduct",
|
||||
cascade_backrefs=False,
|
||||
back_populates="order_items",
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~sideshow.db.model.products.PendingProduct` record for
|
||||
the order item, if applicable.
|
||||
|
||||
See also :attr:`product_id` and :attr:`local_product`.
|
||||
""",
|
||||
)
|
||||
|
||||
product_scancode = sa.Column(
|
||||
sa.String(length=14),
|
||||
nullable=True,
|
||||
|
@ -367,6 +206,8 @@ class OrderItem(model.Base):
|
|||
nullable=True,
|
||||
doc="""
|
||||
Case pack count for the product, if known.
|
||||
|
||||
If this is not set, then customer cannot order a "case" of the item.
|
||||
""",
|
||||
)
|
||||
|
||||
|
@ -389,6 +230,10 @@ class OrderItem(model.Base):
|
|||
|
||||
This should be one of the codes from
|
||||
:data:`~sideshow.enum.ORDER_UOM`.
|
||||
|
||||
Sideshow will treat :data:`~sideshow.enum.ORDER_UOM_CASE`
|
||||
differently but :data:`~sideshow.enum.ORDER_UOM_UNIT` and others
|
||||
are all treated the same (i.e. "unit" is assumed).
|
||||
""",
|
||||
)
|
||||
|
||||
|
@ -440,6 +285,8 @@ class OrderItem(model.Base):
|
|||
This price does *not* reflect the :attr:`discount_percent`. It
|
||||
normally should match either :attr:`unit_price_reg` or
|
||||
:attr:`unit_price_sale`.
|
||||
|
||||
See also :attr:`case_price_quoted`, if applicable.
|
||||
""",
|
||||
)
|
||||
|
||||
|
@ -480,6 +327,181 @@ class OrderItem(model.Base):
|
|||
""",
|
||||
)
|
||||
|
||||
|
||||
class Order(OrderMixin, model.Base): # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
Represents an :term:`order` for a customer. Each order has one or
|
||||
more :attr:`items`.
|
||||
|
||||
Usually, orders are created by way of a
|
||||
:class:`~sideshow.db.model.batch.neworder.NewOrderBatch`.
|
||||
"""
|
||||
|
||||
__tablename__ = "sideshow_order"
|
||||
|
||||
# TODO: this feels a bit hacky yet but it does avoid problems
|
||||
# showing the Orders grid for a PendingCustomer
|
||||
__colanderalchemy_config__ = {
|
||||
"excludes": ["items"],
|
||||
}
|
||||
|
||||
uuid = model.uuid_column()
|
||||
|
||||
order_id = sa.Column(
|
||||
sa.Integer(),
|
||||
nullable=False,
|
||||
doc="""
|
||||
Unique ID for the order.
|
||||
|
||||
When the order is created from New Order Batch, this order ID will
|
||||
match the batch ID.
|
||||
""",
|
||||
)
|
||||
|
||||
store = orm.relationship(
|
||||
"Store",
|
||||
primaryjoin="Store.store_id == Order.store_id",
|
||||
foreign_keys="Order.store_id",
|
||||
doc="""
|
||||
Reference to the :class:`~sideshow.db.model.stores.Store`
|
||||
record, if applicable.
|
||||
""",
|
||||
)
|
||||
|
||||
local_customer_uuid = model.uuid_fk_column(
|
||||
"sideshow_customer_local.uuid", nullable=True
|
||||
)
|
||||
local_customer = orm.relationship(
|
||||
"LocalCustomer",
|
||||
cascade_backrefs=False,
|
||||
back_populates="orders",
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~sideshow.db.model.customers.LocalCustomer` record
|
||||
for the order, if applicable.
|
||||
|
||||
See also :attr:`customer_id` and :attr:`pending_customer`.
|
||||
""",
|
||||
)
|
||||
|
||||
pending_customer_uuid = model.uuid_fk_column(
|
||||
"sideshow_customer_pending.uuid", nullable=True
|
||||
)
|
||||
pending_customer = orm.relationship(
|
||||
"PendingCustomer",
|
||||
cascade_backrefs=False,
|
||||
back_populates="orders",
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~sideshow.db.model.customers.PendingCustomer` record
|
||||
for the order, if applicable.
|
||||
|
||||
See also :attr:`customer_id` and :attr:`local_customer`.
|
||||
""",
|
||||
)
|
||||
|
||||
created = sa.Column(
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=False,
|
||||
default=datetime.datetime.now,
|
||||
doc="""
|
||||
Timestamp when the order was created.
|
||||
|
||||
If the order is created via New Order Batch, this will match the
|
||||
batch execution timestamp.
|
||||
""",
|
||||
)
|
||||
|
||||
created_by_uuid = model.uuid_fk_column("user.uuid", nullable=False)
|
||||
created_by = orm.relationship(
|
||||
model.User,
|
||||
cascade_backrefs=False,
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~wuttjamaican:wuttjamaican.db.model.auth.User` who
|
||||
created the order.
|
||||
""",
|
||||
)
|
||||
|
||||
items = orm.relationship(
|
||||
"OrderItem",
|
||||
collection_class=ordering_list("sequence", count_from=1),
|
||||
cascade="all, delete-orphan",
|
||||
cascade_backrefs=False,
|
||||
back_populates="order",
|
||||
doc="""
|
||||
List of :class:`OrderItem` records belonging to the order.
|
||||
""",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.order_id)
|
||||
|
||||
|
||||
class OrderItem(OrderItemMixin, model.Base):
|
||||
"""
|
||||
Represents an :term:`order item` within an :class:`Order`.
|
||||
|
||||
Usually these are created from
|
||||
:class:`~sideshow.db.model.batch.neworder.NewOrderBatchRow`
|
||||
records.
|
||||
"""
|
||||
|
||||
__tablename__ = "sideshow_order_item"
|
||||
|
||||
uuid = model.uuid_column()
|
||||
|
||||
order_uuid = model.uuid_fk_column("sideshow_order.uuid", nullable=False)
|
||||
order = orm.relationship(
|
||||
Order,
|
||||
cascade_backrefs=False,
|
||||
back_populates="items",
|
||||
doc="""
|
||||
Reference to the :class:`Order` to which the item belongs.
|
||||
""",
|
||||
)
|
||||
|
||||
sequence = sa.Column(
|
||||
sa.Integer(),
|
||||
nullable=False,
|
||||
doc="""
|
||||
1-based numeric sequence for the item, i.e. its line number within
|
||||
the order.
|
||||
""",
|
||||
)
|
||||
|
||||
local_product_uuid = model.uuid_fk_column(
|
||||
"sideshow_product_local.uuid", nullable=True
|
||||
)
|
||||
local_product = orm.relationship(
|
||||
"LocalProduct",
|
||||
cascade_backrefs=False,
|
||||
back_populates="order_items",
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~sideshow.db.model.products.LocalProduct` record for
|
||||
the order item, if applicable.
|
||||
|
||||
See also :attr:`product_id` and :attr:`pending_product`.
|
||||
""",
|
||||
)
|
||||
|
||||
pending_product_uuid = model.uuid_fk_column(
|
||||
"sideshow_product_pending.uuid", nullable=True
|
||||
)
|
||||
pending_product = orm.relationship(
|
||||
"PendingProduct",
|
||||
cascade_backrefs=False,
|
||||
back_populates="order_items",
|
||||
doc="""
|
||||
Reference to the
|
||||
:class:`~sideshow.db.model.products.PendingProduct` record for
|
||||
the order item, if applicable.
|
||||
|
||||
See also :attr:`product_id` and :attr:`local_product`.
|
||||
""",
|
||||
)
|
||||
|
||||
status_code = sa.Column(
|
||||
sa.Integer(),
|
||||
nullable=False,
|
||||
|
|
102
src/sideshow/web/util.py
Normal file
102
src/sideshow/web/util.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Sideshow -- Case/Special Order Tracker
|
||||
# Copyright © 2024-2025 Lance Edgar
|
||||
#
|
||||
# This file is part of Sideshow.
|
||||
#
|
||||
# Sideshow is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Sideshow is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Sideshow. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Web Utility Functions
|
||||
"""
|
||||
|
||||
|
||||
def make_new_order_batches_grid(request, **kwargs):
|
||||
"""
|
||||
Make and return the grid for the New Order Batches field.
|
||||
"""
|
||||
config = request.wutta_config
|
||||
app = config.get_app()
|
||||
model = app.model
|
||||
web = app.get_web_handler()
|
||||
|
||||
if "key" not in kwargs:
|
||||
route_prefix = kwargs.pop("route_prefix")
|
||||
kwargs["key"] = f"{route_prefix}.view.new_order_batches"
|
||||
|
||||
kwargs.setdefault("model_class", model.NewOrderBatch)
|
||||
kwargs.setdefault(
|
||||
"columns",
|
||||
[
|
||||
"id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
"executed",
|
||||
],
|
||||
)
|
||||
kwargs.setdefault("labels", {"id": "Batch ID"})
|
||||
kwargs.setdefault("renderers", {"id": "batch_id", "total_price": "currency"})
|
||||
grid = web.make_grid(request, **kwargs)
|
||||
|
||||
if request.has_perm("neworder_batches.view"):
|
||||
|
||||
def view_url(batch, i): # pylint: disable=unused-argument
|
||||
return request.route_url("neworder_batches.view", uuid=batch.uuid)
|
||||
|
||||
grid.add_action("view", icon="eye", url=view_url)
|
||||
grid.set_link("id")
|
||||
|
||||
return grid
|
||||
|
||||
|
||||
def make_orders_grid(request, **kwargs):
|
||||
"""
|
||||
Make and return the grid for the Orders field.
|
||||
"""
|
||||
config = request.wutta_config
|
||||
app = config.get_app()
|
||||
model = app.model
|
||||
web = app.get_web_handler()
|
||||
|
||||
if "key" not in kwargs:
|
||||
route_prefix = kwargs.pop("route_prefix")
|
||||
kwargs["key"] = f"{route_prefix}.view.orders"
|
||||
|
||||
kwargs.setdefault("model_class", model.Order)
|
||||
kwargs.setdefault(
|
||||
"columns",
|
||||
[
|
||||
"order_id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
],
|
||||
)
|
||||
kwargs.setdefault("labels", {"order_id": "Order ID"})
|
||||
kwargs.setdefault("renderers", {"total_price": "currency"})
|
||||
grid = web.make_grid(request, **kwargs)
|
||||
|
||||
if request.has_perm("orders.view"):
|
||||
|
||||
def view_url(order, i): # pylint: disable=unused-argument
|
||||
return request.route_url("orders.view", uuid=order.uuid)
|
||||
|
||||
grid.add_action("view", icon="eye", url=view_url)
|
||||
grid.set_link("order_id")
|
||||
|
||||
return grid
|
|
@ -25,9 +25,11 @@ Views for Customers
|
|||
"""
|
||||
|
||||
from wuttaweb.views import MasterView
|
||||
from wuttaweb.forms.schema import UserRef, WuttaEnum
|
||||
from wuttaweb.forms.schema import WuttaEnum
|
||||
|
||||
from sideshow.db.model import LocalCustomer, PendingCustomer
|
||||
from sideshow.web.views.shared import PendingMixin
|
||||
from sideshow.web.util import make_new_order_batches_grid, make_orders_grid
|
||||
|
||||
|
||||
class LocalCustomerView(MasterView): # pylint: disable=abstract-method
|
||||
|
@ -120,72 +122,20 @@ class LocalCustomerView(MasterView): # pylint: disable=abstract-method
|
|||
"""
|
||||
Make and return the grid for the Orders field.
|
||||
"""
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
grid = self.make_grid(
|
||||
key=f"{route_prefix}.view.orders",
|
||||
model_class=model.Order,
|
||||
data=customer.orders,
|
||||
columns=[
|
||||
"order_id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
],
|
||||
labels={
|
||||
"order_id": "Order ID",
|
||||
},
|
||||
return make_orders_grid(
|
||||
self.request, route_prefix=self.get_route_prefix(), data=customer.orders
|
||||
)
|
||||
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)
|
||||
grid.set_link("order_id")
|
||||
|
||||
return grid
|
||||
|
||||
def make_new_order_batches_grid(self, customer):
|
||||
"""
|
||||
Make and return the grid for the New Order Batches field.
|
||||
"""
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
grid = self.make_grid(
|
||||
key=f"{route_prefix}.view.new_order_batches",
|
||||
model_class=model.NewOrderBatch,
|
||||
return make_new_order_batches_grid(
|
||||
self.request,
|
||||
route_prefix=self.get_route_prefix(),
|
||||
data=customer.new_order_batches,
|
||||
columns=[
|
||||
"id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
"executed",
|
||||
],
|
||||
labels={
|
||||
"id": "Batch ID",
|
||||
},
|
||||
renderers={
|
||||
"id": "batch_id",
|
||||
"total_price": "currency",
|
||||
},
|
||||
)
|
||||
|
||||
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)
|
||||
grid.set_link("id")
|
||||
|
||||
return grid
|
||||
|
||||
def objectify(self, form): # pylint: disable=empty-docstring
|
||||
""" """
|
||||
customer = super().objectify(form)
|
||||
|
@ -197,7 +147,7 @@ class LocalCustomerView(MasterView): # pylint: disable=abstract-method
|
|||
return customer
|
||||
|
||||
|
||||
class PendingCustomerView(MasterView): # pylint: disable=abstract-method
|
||||
class PendingCustomerView(PendingMixin, MasterView): # pylint: disable=abstract-method
|
||||
"""
|
||||
Master view for
|
||||
:class:`~sideshow.db.model.customers.PendingCustomer`; route
|
||||
|
@ -270,7 +220,8 @@ class PendingCustomerView(MasterView): # pylint: disable=abstract-method
|
|||
f = form
|
||||
super().configure_form(f)
|
||||
enum = self.app.enum
|
||||
customer = f.model_instance
|
||||
|
||||
self.configure_form_pending(f)
|
||||
|
||||
# customer_id
|
||||
if self.creating:
|
||||
|
@ -285,101 +236,24 @@ class PendingCustomerView(MasterView): # pylint: disable=abstract-method
|
|||
f.set_node("status", WuttaEnum(self.request, enum.PendingCustomerStatus))
|
||||
f.set_readonly("status")
|
||||
|
||||
# created
|
||||
if self.creating:
|
||||
f.remove("created")
|
||||
else:
|
||||
f.set_readonly("created")
|
||||
|
||||
# created_by
|
||||
if self.creating:
|
||||
f.remove("created_by")
|
||||
else:
|
||||
f.set_node("created_by", UserRef(self.request))
|
||||
f.set_readonly("created_by")
|
||||
|
||||
# orders
|
||||
if self.creating or self.editing:
|
||||
f.remove("orders")
|
||||
else:
|
||||
f.set_grid("orders", self.make_orders_grid(customer))
|
||||
|
||||
# new_order_batches
|
||||
if self.creating or self.editing:
|
||||
f.remove("new_order_batches")
|
||||
else:
|
||||
f.set_grid("new_order_batches", self.make_new_order_batches_grid(customer))
|
||||
|
||||
def make_orders_grid(self, customer):
|
||||
"""
|
||||
Make and return the grid for the Orders field.
|
||||
"""
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
grid = self.make_grid(
|
||||
key=f"{route_prefix}.view.orders",
|
||||
model_class=model.Order,
|
||||
data=customer.orders,
|
||||
columns=[
|
||||
"order_id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
],
|
||||
labels={
|
||||
"order_id": "Order ID",
|
||||
},
|
||||
return make_orders_grid(
|
||||
self.request, route_prefix=self.get_route_prefix(), data=customer.orders
|
||||
)
|
||||
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)
|
||||
grid.set_link("order_id")
|
||||
|
||||
return grid
|
||||
|
||||
def make_new_order_batches_grid(self, customer):
|
||||
"""
|
||||
Make and return the grid for the New Order Batches field.
|
||||
"""
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
grid = self.make_grid(
|
||||
key=f"{route_prefix}.view.new_order_batches",
|
||||
model_class=model.NewOrderBatch,
|
||||
return make_new_order_batches_grid(
|
||||
self.request,
|
||||
route_prefix=self.get_route_prefix(),
|
||||
data=customer.new_order_batches,
|
||||
columns=[
|
||||
"id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
"executed",
|
||||
],
|
||||
labels={
|
||||
"id": "Batch ID",
|
||||
},
|
||||
renderers={
|
||||
"id": "batch_id",
|
||||
"total_price": "currency",
|
||||
},
|
||||
)
|
||||
|
||||
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)
|
||||
grid.set_link("id")
|
||||
|
||||
return grid
|
||||
|
||||
def objectify(self, form): # pylint: disable=empty-docstring
|
||||
""" """
|
||||
enum = self.app.enum
|
||||
|
|
|
@ -25,10 +25,12 @@ Views for Products
|
|||
"""
|
||||
|
||||
from wuttaweb.views import MasterView
|
||||
from wuttaweb.forms.schema import UserRef, WuttaMoney, WuttaQuantity
|
||||
from wuttaweb.forms.schema import WuttaMoney, WuttaQuantity
|
||||
|
||||
from sideshow.enum import PendingProductStatus
|
||||
from sideshow.db.model import LocalProduct, PendingProduct
|
||||
from sideshow.web.views.shared import PendingMixin
|
||||
from sideshow.web.util import make_new_order_batches_grid, make_orders_grid
|
||||
|
||||
|
||||
class LocalProductView(MasterView): # pylint: disable=abstract-method
|
||||
|
@ -153,82 +155,28 @@ class LocalProductView(MasterView): # pylint: disable=abstract-method
|
|||
"""
|
||||
Make and return the grid for the Orders field.
|
||||
"""
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
orders = {item.order for item in product.order_items}
|
||||
orders = sorted(orders, key=lambda order: order.order_id)
|
||||
|
||||
grid = self.make_grid(
|
||||
key=f"{route_prefix}.view.orders",
|
||||
model_class=model.Order,
|
||||
data=orders,
|
||||
columns=[
|
||||
"order_id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
],
|
||||
labels={
|
||||
"order_id": "Order ID",
|
||||
},
|
||||
renderers={
|
||||
"total_price": "currency",
|
||||
},
|
||||
return make_orders_grid(
|
||||
self.request, route_prefix=self.get_route_prefix(), data=orders
|
||||
)
|
||||
|
||||
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)
|
||||
grid.set_link("order_id")
|
||||
|
||||
return grid
|
||||
|
||||
def make_new_order_batches_grid(self, product):
|
||||
"""
|
||||
Make and return the grid for the New Order Batches field.
|
||||
"""
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
batches = {row.batch for row in product.new_order_batch_rows}
|
||||
batches = sorted(batches, key=lambda batch: batch.id)
|
||||
|
||||
grid = self.make_grid(
|
||||
key=f"{route_prefix}.view.new_order_batches",
|
||||
model_class=model.NewOrderBatch,
|
||||
return make_new_order_batches_grid(
|
||||
self.request,
|
||||
route_prefix=self.get_route_prefix(),
|
||||
data=batches,
|
||||
columns=[
|
||||
"id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
"executed",
|
||||
],
|
||||
labels={
|
||||
"id": "Batch ID",
|
||||
"status_code": "Status",
|
||||
},
|
||||
renderers={
|
||||
"id": "batch_id",
|
||||
},
|
||||
)
|
||||
|
||||
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)
|
||||
grid.set_link("id")
|
||||
|
||||
return grid
|
||||
|
||||
|
||||
class PendingProductView(MasterView): # pylint: disable=abstract-method
|
||||
class PendingProductView(PendingMixin, MasterView): # pylint: disable=abstract-method
|
||||
"""
|
||||
Master view for
|
||||
:class:`~sideshow.db.model.products.PendingProduct`; route
|
||||
|
@ -330,7 +278,8 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
|
|||
""" """
|
||||
f = form
|
||||
super().configure_form(f)
|
||||
product = f.model_instance
|
||||
|
||||
self.configure_form_pending(f)
|
||||
|
||||
# product_id
|
||||
if self.creating:
|
||||
|
@ -344,109 +293,30 @@ class PendingProductView(MasterView): # pylint: disable=abstract-method
|
|||
# notes
|
||||
f.set_widget("notes", "notes")
|
||||
|
||||
# created
|
||||
if self.creating:
|
||||
f.remove("created")
|
||||
else:
|
||||
f.set_readonly("created")
|
||||
|
||||
# created_by
|
||||
if self.creating:
|
||||
f.remove("created_by")
|
||||
else:
|
||||
f.set_node("created_by", UserRef(self.request))
|
||||
f.set_readonly("created_by")
|
||||
|
||||
# orders
|
||||
if self.creating or self.editing:
|
||||
f.remove("orders")
|
||||
else:
|
||||
f.set_grid("orders", self.make_orders_grid(product))
|
||||
|
||||
# new_order_batches
|
||||
if self.creating or self.editing:
|
||||
f.remove("new_order_batches")
|
||||
else:
|
||||
f.set_grid("new_order_batches", self.make_new_order_batches_grid(product))
|
||||
|
||||
def make_orders_grid(self, product):
|
||||
"""
|
||||
Make and return the grid for the Orders field.
|
||||
"""
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
orders = {item.order for item in product.order_items}
|
||||
orders = sorted(orders, key=lambda order: order.order_id)
|
||||
|
||||
grid = self.make_grid(
|
||||
key=f"{route_prefix}.view.orders",
|
||||
model_class=model.Order,
|
||||
data=orders,
|
||||
columns=[
|
||||
"order_id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
],
|
||||
labels={
|
||||
"order_id": "Order ID",
|
||||
},
|
||||
renderers={
|
||||
"total_price": "currency",
|
||||
},
|
||||
return make_orders_grid(
|
||||
self.request, route_prefix=self.get_route_prefix(), data=orders
|
||||
)
|
||||
|
||||
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)
|
||||
grid.set_link("order_id")
|
||||
|
||||
return grid
|
||||
|
||||
def make_new_order_batches_grid(self, product):
|
||||
"""
|
||||
Make and return the grid for the New Order Batches field.
|
||||
"""
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
batches = {row.batch for row in product.new_order_batch_rows}
|
||||
batches = sorted(batches, key=lambda batch: batch.id)
|
||||
|
||||
grid = self.make_grid(
|
||||
key=f"{route_prefix}.view.new_order_batches",
|
||||
model_class=model.NewOrderBatch,
|
||||
return make_new_order_batches_grid(
|
||||
self.request,
|
||||
route_prefix=self.get_route_prefix(),
|
||||
data=batches,
|
||||
columns=[
|
||||
"id",
|
||||
"total_price",
|
||||
"created",
|
||||
"created_by",
|
||||
"executed",
|
||||
],
|
||||
labels={
|
||||
"id": "Batch ID",
|
||||
"status_code": "Status",
|
||||
},
|
||||
renderers={
|
||||
"id": "batch_id",
|
||||
},
|
||||
)
|
||||
|
||||
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)
|
||||
grid.set_link("id")
|
||||
|
||||
return grid
|
||||
|
||||
def get_template_context(self, context): # pylint: disable=empty-docstring
|
||||
""" """
|
||||
enum = self.app.enum
|
||||
|
|
64
src/sideshow/web/views/shared.py
Normal file
64
src/sideshow/web/views/shared.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Sideshow -- Case/Special Order Tracker
|
||||
# Copyright © 2024-2025 Lance Edgar
|
||||
#
|
||||
# This file is part of Sideshow.
|
||||
#
|
||||
# Sideshow is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Sideshow is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Sideshow. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Shared View Logic
|
||||
"""
|
||||
|
||||
from wuttaweb.forms.schema import UserRef
|
||||
|
||||
|
||||
class PendingMixin: # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
Mixin class with logic shared by Pending Customer and Pending
|
||||
Product views.
|
||||
"""
|
||||
|
||||
def configure_form_pending(self, form): # pylint: disable=empty-docstring
|
||||
""" """
|
||||
f = form
|
||||
obj = f.model_instance
|
||||
|
||||
# created
|
||||
if self.creating:
|
||||
f.remove("created")
|
||||
else:
|
||||
f.set_readonly("created")
|
||||
|
||||
# created_by
|
||||
if self.creating:
|
||||
f.remove("created_by")
|
||||
else:
|
||||
f.set_node("created_by", UserRef(self.request))
|
||||
f.set_readonly("created_by")
|
||||
|
||||
# orders
|
||||
if self.creating or self.editing:
|
||||
f.remove("orders")
|
||||
else:
|
||||
f.set_grid("orders", self.make_orders_grid(obj))
|
||||
|
||||
# new_order_batches
|
||||
if self.creating or self.editing:
|
||||
f.remove("new_order_batches")
|
||||
else:
|
||||
f.set_grid("new_order_batches", self.make_new_order_batches_grid(obj))
|
Loading…
Add table
Add a link
Reference in a new issue