Compare commits
4 commits
4bb4272341
...
edd1f17184
Author | SHA1 | Date | |
---|---|---|---|
|
edd1f17184 | ||
|
d8b37969c5 | ||
|
7ea83b2715 | ||
|
f3cca2e370 |
|
@ -38,7 +38,8 @@ dependencies = [
|
|||
[project.optional-dependencies]
|
||||
postgres = ["psycopg2"]
|
||||
mysql = ["mysql-connector-python"]
|
||||
docs = ["Sphinx", "furo", "sphinxcontrib-programoutput", "enum-tools[sphinx]"]
|
||||
# TODO: remove sphinx version cap after new sphinx-toolbox release?
|
||||
docs = ["Sphinx<8.2", "furo", "sphinxcontrib-programoutput", "enum-tools[sphinx]"]
|
||||
tests = ["pytest-cov", "tox"]
|
||||
|
||||
|
||||
|
|
|
@ -938,6 +938,8 @@ class NewOrderBatchHandler(BatchHandler):
|
|||
row.department_id = product.department_id
|
||||
row.department_name = product.department_name
|
||||
row.special_order = product.special_order
|
||||
row.vendor_name = product.vendor_name
|
||||
row.vendor_item_code = product.vendor_item_code
|
||||
row.case_size = product.case_size
|
||||
row.unit_cost = product.unit_cost
|
||||
row.unit_price_reg = product.unit_price_reg
|
||||
|
@ -959,6 +961,8 @@ class NewOrderBatchHandler(BatchHandler):
|
|||
row.department_id = product.department_id
|
||||
row.department_name = product.department_name
|
||||
row.special_order = product.special_order
|
||||
row.vendor_name = product.vendor_name
|
||||
row.vendor_item_code = product.vendor_item_code
|
||||
row.case_size = product.case_size
|
||||
row.unit_cost = product.unit_cost
|
||||
row.unit_price_reg = product.unit_price_reg
|
||||
|
@ -1017,8 +1021,14 @@ class NewOrderBatchHandler(BatchHandler):
|
|||
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.
|
||||
phone number, and at least one item. It also may check to
|
||||
ensure the store is assigned, if applicable.
|
||||
"""
|
||||
if not batch.store_id:
|
||||
order_handler = self.app.get_order_handler()
|
||||
if order_handler.expose_store_id():
|
||||
return "Must assign the store"
|
||||
|
||||
if not batch.customer_name:
|
||||
return "Must assign the customer"
|
||||
|
||||
|
@ -1190,6 +1200,8 @@ class NewOrderBatchHandler(BatchHandler):
|
|||
'product_weighed',
|
||||
'department_id',
|
||||
'department_name',
|
||||
'vendor_name',
|
||||
'vendor_item_code',
|
||||
'case_size',
|
||||
'order_qty',
|
||||
'order_uom',
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
"""add order_item.vendor*
|
||||
|
||||
Revision ID: 13af2ffbc0e0
|
||||
Revises: a4273360d379
|
||||
Create Date: 2025-02-19 19:36:30.308840
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import wuttjamaican.db.util
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '13af2ffbc0e0'
|
||||
down_revision: Union[str, None] = 'a4273360d379'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
|
||||
# sideshow_batch_neworder_row
|
||||
op.add_column('sideshow_batch_neworder_row', sa.Column('vendor_name', sa.String(length=50), nullable=True))
|
||||
op.add_column('sideshow_batch_neworder_row', sa.Column('vendor_item_code', sa.String(length=20), nullable=True))
|
||||
|
||||
# sideshow_order_item
|
||||
op.add_column('sideshow_order_item', sa.Column('vendor_name', sa.String(length=50), nullable=True))
|
||||
op.add_column('sideshow_order_item', sa.Column('vendor_item_code', sa.String(length=20), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
|
||||
# sideshow_order_item
|
||||
op.drop_column('sideshow_order_item', 'vendor_item_code')
|
||||
op.drop_column('sideshow_order_item', 'vendor_name')
|
||||
|
||||
# sideshow_batch_neworder_row
|
||||
op.drop_column('sideshow_batch_neworder_row', 'vendor_item_code')
|
||||
op.drop_column('sideshow_batch_neworder_row', 'vendor_name')
|
|
@ -252,6 +252,16 @@ class NewOrderBatchRow(model.BatchRowMixin, model.Base):
|
|||
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.
|
||||
|
||||
|
|
|
@ -253,6 +253,16 @@ class OrderItem(model.Base):
|
|||
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.
|
||||
""")
|
||||
|
|
|
@ -243,6 +243,12 @@
|
|||
<b-field horizontal label="Special Order">
|
||||
<span>${app.render_boolean(item.special_order)}</span>
|
||||
</b-field>
|
||||
<b-field horizontal label="Vendor Name">
|
||||
<span>${item.vendor_name}</span>
|
||||
</b-field>
|
||||
<b-field horizontal label="Vendor Item Code">
|
||||
<span>${item.vendor_item_code}</span>
|
||||
</b-field>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
@ -1239,6 +1239,9 @@ class OrderItemView(MasterView):
|
|||
|
||||
# customer_name
|
||||
g.set_label('customer_name', "Customer", column_only=True)
|
||||
g.set_renderer('customer_name', self.render_order_attr)
|
||||
g.set_sorter('customer_name', model.Order.customer_name)
|
||||
g.set_filter('customer_name', model.Order.customer_name)
|
||||
|
||||
# # sequence
|
||||
# g.set_label('sequence', "Seq.", column_only=True)
|
||||
|
@ -1562,6 +1565,26 @@ class PlacementView(OrderItemView):
|
|||
route_prefix = 'order_items_placement'
|
||||
url_prefix = '/placement'
|
||||
|
||||
grid_columns = [
|
||||
'order_id',
|
||||
'store_id',
|
||||
'customer_name',
|
||||
'product_brand',
|
||||
'product_description',
|
||||
'product_size',
|
||||
'department_name',
|
||||
'special_order',
|
||||
'vendor_name',
|
||||
'vendor_item_code',
|
||||
'order_qty',
|
||||
'order_uom',
|
||||
'total_price',
|
||||
]
|
||||
|
||||
filter_defaults = {
|
||||
'vendor_name': {'active': True},
|
||||
}
|
||||
|
||||
def get_query(self, session=None):
|
||||
""" """
|
||||
query = super().get_query(session=session)
|
||||
|
@ -1664,6 +1687,26 @@ class ReceivingView(OrderItemView):
|
|||
route_prefix = 'order_items_receiving'
|
||||
url_prefix = '/receiving'
|
||||
|
||||
grid_columns = [
|
||||
'order_id',
|
||||
'store_id',
|
||||
'customer_name',
|
||||
'product_brand',
|
||||
'product_description',
|
||||
'product_size',
|
||||
'department_name',
|
||||
'special_order',
|
||||
'vendor_name',
|
||||
'vendor_item_code',
|
||||
'order_qty',
|
||||
'order_uom',
|
||||
'total_price',
|
||||
]
|
||||
|
||||
filter_defaults = {
|
||||
'vendor_name': {'active': True},
|
||||
}
|
||||
|
||||
def get_query(self, session=None):
|
||||
""" """
|
||||
query = super().get_query(session=session)
|
||||
|
|
|
@ -818,6 +818,8 @@ class TestNewOrderBatchHandler(DataTestCase):
|
|||
brand_name='Bragg',
|
||||
description='Vinegar',
|
||||
size='32oz',
|
||||
vendor_name='Acme Distributors',
|
||||
vendor_item_code='1234',
|
||||
created_by=user,
|
||||
status=enum.PendingProductStatus.PENDING)
|
||||
row = handler.make_row(pending_product=product, order_qty=1, order_uom=enum.ORDER_UOM_UNIT)
|
||||
|
@ -830,6 +832,8 @@ class TestNewOrderBatchHandler(DataTestCase):
|
|||
self.assertEqual(row.product_brand, 'Bragg')
|
||||
self.assertEqual(row.product_description, 'Vinegar')
|
||||
self.assertEqual(row.product_size, '32oz')
|
||||
self.assertEqual(row.vendor_name, 'Acme Distributors')
|
||||
self.assertEqual(row.vendor_item_code, '1234')
|
||||
self.assertIsNone(row.case_size)
|
||||
self.assertIsNone(row.unit_cost)
|
||||
self.assertIsNone(row.unit_price_reg)
|
||||
|
@ -1114,9 +1118,15 @@ class TestNewOrderBatchHandler(DataTestCase):
|
|||
self.session.add(row)
|
||||
self.session.flush()
|
||||
|
||||
# batch is okay to execute..
|
||||
reason = handler.why_not_execute(batch)
|
||||
self.assertIsNone(reason)
|
||||
|
||||
# unless we also require store
|
||||
self.config.setdefault('sideshow.orders.expose_store_id', 'true')
|
||||
reason = handler.why_not_execute(batch)
|
||||
self.assertEqual(reason, "Must assign the store")
|
||||
|
||||
def test_make_local_customer(self):
|
||||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
|
|
Loading…
Reference in a new issue