Compare commits
	
		
			4 commits
		
	
	
		
			4bb4272341
			...
			edd1f17184
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| edd1f17184 | |||
| d8b37969c5 | |||
| 7ea83b2715 | |||
| f3cca2e370 | 
					 8 changed files with 135 additions and 2 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue