feat: add config option to show/hide Store ID; default value
This commit is contained in:
parent
3ef84ff706
commit
89e3445ace
6
docs/api/sideshow.app.rst
Normal file
6
docs/api/sideshow.app.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``sideshow.app``
|
||||||
|
================
|
||||||
|
|
||||||
|
.. automodule:: sideshow.app
|
||||||
|
:members:
|
|
@ -30,6 +30,7 @@ For an online demo see https://demo.wuttaproject.org/
|
||||||
:caption: Package API:
|
:caption: Package API:
|
||||||
|
|
||||||
api/sideshow
|
api/sideshow
|
||||||
|
api/sideshow.app
|
||||||
api/sideshow.batch
|
api/sideshow.batch
|
||||||
api/sideshow.batch.neworder
|
api/sideshow.batch.neworder
|
||||||
api/sideshow.cli
|
api/sideshow.cli
|
||||||
|
|
|
@ -51,6 +51,9 @@ sideshow_libcache = "sideshow.web.static:libcache"
|
||||||
[project.entry-points."paste.app_factory"]
|
[project.entry-points."paste.app_factory"]
|
||||||
"main" = "sideshow.web.app:main"
|
"main" = "sideshow.web.app:main"
|
||||||
|
|
||||||
|
[project.entry-points."wutta.app.providers"]
|
||||||
|
sideshow = "sideshow.app:SideshowAppProvider"
|
||||||
|
|
||||||
[project.entry-points."wutta.batch.neworder"]
|
[project.entry-points."wutta.batch.neworder"]
|
||||||
"sideshow" = "sideshow.batch.neworder:NewOrderBatchHandler"
|
"sideshow" = "sideshow.batch.neworder:NewOrderBatchHandler"
|
||||||
|
|
||||||
|
|
56
src/sideshow/app.py
Normal file
56
src/sideshow/app.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Sideshow -- Case/Special Order Tracker
|
||||||
|
# Copyright © 2024 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/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Sideshow app provider
|
||||||
|
"""
|
||||||
|
|
||||||
|
from wuttjamaican import app as base
|
||||||
|
|
||||||
|
|
||||||
|
class SideshowAppProvider(base.AppProvider):
|
||||||
|
"""
|
||||||
|
The :term:`app provider` for Sideshow.
|
||||||
|
|
||||||
|
This adds the :meth:`get_order_handler()` method to the :term:`app
|
||||||
|
handler`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_order_handler(self, **kwargs):
|
||||||
|
"""
|
||||||
|
Get the configured :term:`order handler` for the app.
|
||||||
|
|
||||||
|
You can specify a custom handler in your :term:`config file`
|
||||||
|
like:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[sideshow]
|
||||||
|
orders.handler_spec = poser.orders:PoserOrderHandler
|
||||||
|
|
||||||
|
:returns: Instance of :class:`~sideshow.orders.OrderHandler`.
|
||||||
|
"""
|
||||||
|
if 'order_handler' not in self.__dict__:
|
||||||
|
spec = self.config.get('sideshow.orders.handler_spec',
|
||||||
|
default='sideshow.orders:OrderHandler')
|
||||||
|
self.order_handler = self.app.load_object(spec)(self.config)
|
||||||
|
return self.order_handler
|
|
@ -50,6 +50,14 @@ class NewOrderBatchHandler(BatchHandler):
|
||||||
"""
|
"""
|
||||||
model_class = NewOrderBatch
|
model_class = NewOrderBatch
|
||||||
|
|
||||||
|
def get_default_store_id(self):
|
||||||
|
"""
|
||||||
|
Returns the configured default value for
|
||||||
|
:attr:`~sideshow.db.model.batch.neworder.NewOrderBatch.store_id`,
|
||||||
|
or ``None``.
|
||||||
|
"""
|
||||||
|
return self.config.get('sideshow.orders.default_store_id')
|
||||||
|
|
||||||
def use_local_customers(self):
|
def use_local_customers(self):
|
||||||
"""
|
"""
|
||||||
Returns boolean indicating whether :term:`local customer`
|
Returns boolean indicating whether :term:`local customer`
|
||||||
|
@ -165,6 +173,18 @@ class NewOrderBatchHandler(BatchHandler):
|
||||||
'label': customer.full_name}
|
'label': customer.full_name}
|
||||||
return [result(c) for c in customers]
|
return [result(c) for c in customers]
|
||||||
|
|
||||||
|
def init_batch(self, batch, session=None, progress=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Initialize a new batch.
|
||||||
|
|
||||||
|
This sets the
|
||||||
|
:attr:`~sideshow.db.model.batch.neworder.NewOrderBatch.store_id`,
|
||||||
|
if the batch does not yet have one and a default is
|
||||||
|
configured.
|
||||||
|
"""
|
||||||
|
if not batch.store_id:
|
||||||
|
batch.store_id = self.get_default_store_id()
|
||||||
|
|
||||||
def set_customer(self, batch, customer_info, user=None):
|
def set_customer(self, batch, customer_info, user=None):
|
||||||
"""
|
"""
|
||||||
Set/update customer info for the batch.
|
Set/update customer info for the batch.
|
||||||
|
|
|
@ -62,6 +62,15 @@ class Order(model.Base):
|
||||||
ID of the store to which the order pertains, if applicable.
|
ID of the store to which the order pertains, if applicable.
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
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, doc="""
|
customer_id = sa.Column(sa.String(length=20), nullable=True, doc="""
|
||||||
Proper account ID for the :term:`external customer` to which the
|
Proper account ID for the :term:`external customer` to which the
|
||||||
order pertains, if applicable.
|
order pertains, if applicable.
|
||||||
|
|
|
@ -51,4 +51,12 @@ class Store(model.Base):
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name or ""
|
return self.get_display()
|
||||||
|
|
||||||
|
def get_display(self):
|
||||||
|
"""
|
||||||
|
Returns the display string for the store, e.g. "001 Acme Goods".
|
||||||
|
"""
|
||||||
|
return ' '.join([(self.store_id or '').strip(),
|
||||||
|
(self.name or '').strip()])\
|
||||||
|
.strip()
|
||||||
|
|
|
@ -37,6 +37,14 @@ class OrderHandler(GenericHandler):
|
||||||
handler is responsible for creation logic.)
|
handler is responsible for creation logic.)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def expose_store_id(self):
|
||||||
|
"""
|
||||||
|
Returns boolean indicating whether the ``store_id`` field
|
||||||
|
should be exposed at all. This is false by default.
|
||||||
|
"""
|
||||||
|
return self.config.get_bool('sideshow.orders.expose_store_id',
|
||||||
|
default=False)
|
||||||
|
|
||||||
def get_order_qty_uom_text(self, order_qty, order_uom, case_size=None, html=False):
|
def get_order_qty_uom_text(self, order_qty, order_uom, case_size=None, html=False):
|
||||||
"""
|
"""
|
||||||
Return the display text for a given order quantity.
|
Return the display text for a given order quantity.
|
||||||
|
|
|
@ -29,6 +29,17 @@
|
||||||
<b-field horizontal label="ID">
|
<b-field horizontal label="ID">
|
||||||
<span>${h.link_to(f"Order ID {order.order_id}", url('orders.view', uuid=order.uuid))} — Item #${item.sequence}</span>
|
<span>${h.link_to(f"Order ID {order.order_id}", url('orders.view', uuid=order.uuid))} — Item #${item.sequence}</span>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
% if expose_store_id:
|
||||||
|
<b-field horizontal label="Store">
|
||||||
|
<span>
|
||||||
|
% if order.store:
|
||||||
|
${h.link_to(order.store.get_display(), url('stores.view', uuid=order.store.uuid))}
|
||||||
|
% elif order.store_id:
|
||||||
|
${order.store_id}
|
||||||
|
% endif
|
||||||
|
</span>
|
||||||
|
</b-field>
|
||||||
|
% endif
|
||||||
<b-field horizontal label="Order Qty">
|
<b-field horizontal label="Order Qty">
|
||||||
<span>${order_qty_uom_text|n}</span>
|
<span>${order_qty_uom_text|n}</span>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
|
@ -3,6 +3,28 @@
|
||||||
|
|
||||||
<%def name="form_content()">
|
<%def name="form_content()">
|
||||||
|
|
||||||
|
<h3 class="block is-size-3">Stores</h3>
|
||||||
|
<div class="block" style="padding-left: 2rem;">
|
||||||
|
|
||||||
|
<b-field>
|
||||||
|
<b-checkbox name="sideshow.orders.expose_store_id"
|
||||||
|
v-model="simpleSettings['sideshow.orders.expose_store_id']"
|
||||||
|
native-value="true"
|
||||||
|
@input="settingsNeedSaved = true">
|
||||||
|
Show/choose the Store ID for each order
|
||||||
|
</b-checkbox>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field v-show="simpleSettings['sideshow.orders.expose_store_id']"
|
||||||
|
label="Default Store ID">
|
||||||
|
<b-input name="sideshow.orders.default_store_id"
|
||||||
|
v-model="simpleSettings['sideshow.orders.default_store_id']"
|
||||||
|
@input="settingsNeedSaved = true"
|
||||||
|
style="width: 25rem;" />
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<h3 class="block is-size-3">Customers</h3>
|
<h3 class="block is-size-3">Customers</h3>
|
||||||
<div class="block" style="padding-left: 2rem;">
|
<div class="block" style="padding-left: 2rem;">
|
||||||
|
|
||||||
|
@ -14,6 +36,7 @@
|
||||||
<option value="false">External Customers (e.g. in POS)</option>
|
<option value="false">External Customers (e.g. in POS)</option>
|
||||||
</b-select>
|
</b-select>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 class="block is-size-3">Products</h3>
|
<h3 class="block is-size-3">Products</h3>
|
||||||
|
|
|
@ -42,7 +42,25 @@
|
||||||
<script type="text/x-template" id="order-creator-template">
|
<script type="text/x-template" id="order-creator-template">
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
${self.order_form_buttons()}
|
<div style="display: flex; justify-content: space-between; margin-bottom: 1.5rem;">
|
||||||
|
<div>
|
||||||
|
% if expose_store_id:
|
||||||
|
<b-loading v-model="storeLoading" is-full-page />
|
||||||
|
<b-field label="Store" horizontal
|
||||||
|
:type="storeID ? null : 'is-danger'">
|
||||||
|
<b-select v-model="storeID"
|
||||||
|
@input="storeChanged">
|
||||||
|
<option v-for="store in stores"
|
||||||
|
:key="store.store_id"
|
||||||
|
:value="store.store_id">
|
||||||
|
{{ store.display }}
|
||||||
|
</option>
|
||||||
|
</b-select>
|
||||||
|
</b-field>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
${self.order_form_buttons()}
|
||||||
|
</div>
|
||||||
|
|
||||||
<${b}-collapse class="panel"
|
<${b}-collapse class="panel"
|
||||||
:class="customerPanelType"
|
:class="customerPanelType"
|
||||||
|
@ -837,6 +855,12 @@
|
||||||
|
|
||||||
batchTotalPriceDisplay: ${json.dumps(normalized_batch['total_price_display'])|n},
|
batchTotalPriceDisplay: ${json.dumps(normalized_batch['total_price_display'])|n},
|
||||||
|
|
||||||
|
% if expose_store_id:
|
||||||
|
stores: ${json.dumps(stores)|n},
|
||||||
|
storeID: ${json.dumps(batch.store_id)|n},
|
||||||
|
storeLoading: false,
|
||||||
|
% endif
|
||||||
|
|
||||||
customerPanelOpen: false,
|
customerPanelOpen: false,
|
||||||
customerLoading: false,
|
customerLoading: false,
|
||||||
customerIsKnown: ${json.dumps(customer_is_known)|n},
|
customerIsKnown: ${json.dumps(customer_is_known)|n},
|
||||||
|
@ -1160,6 +1184,28 @@
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
% if expose_store_id:
|
||||||
|
|
||||||
|
storeChanged(storeID) {
|
||||||
|
this.storeLoading = true
|
||||||
|
const params = {
|
||||||
|
action: 'set_store',
|
||||||
|
store_id: storeID,
|
||||||
|
}
|
||||||
|
this.submitBatchData(params, ({data}) => {
|
||||||
|
this.storeLoading = false
|
||||||
|
}, response => {
|
||||||
|
this.$buefy.toast.open({
|
||||||
|
message: "Update failed: " + (response.data.error || "(unknown error)"),
|
||||||
|
type: 'is-danger',
|
||||||
|
duration: 2000, // 2 seconds
|
||||||
|
})
|
||||||
|
this.storeLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
% endif
|
||||||
|
|
||||||
customerChanged(customerID, callback) {
|
customerChanged(customerID, callback) {
|
||||||
this.customerLoading = true
|
this.customerLoading = true
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,10 @@ class NewOrderBatchView(BatchMasterView):
|
||||||
'status_code',
|
'status_code',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def __init__(self, request, context=None):
|
||||||
|
super().__init__(request, context=context)
|
||||||
|
self.order_handler = self.app.get_order_handler()
|
||||||
|
|
||||||
def get_batch_handler(self):
|
def get_batch_handler(self):
|
||||||
""" """
|
""" """
|
||||||
# TODO: call self.app.get_batch_handler()
|
# TODO: call self.app.get_batch_handler()
|
||||||
|
@ -135,6 +139,10 @@ class NewOrderBatchView(BatchMasterView):
|
||||||
""" """
|
""" """
|
||||||
super().configure_grid(g)
|
super().configure_grid(g)
|
||||||
|
|
||||||
|
# store_id
|
||||||
|
if not self.order_handler.expose_store_id():
|
||||||
|
g.remove('store_id')
|
||||||
|
|
||||||
# total_price
|
# total_price
|
||||||
g.set_renderer('total_price', 'currency')
|
g.set_renderer('total_price', 'currency')
|
||||||
|
|
||||||
|
@ -142,6 +150,10 @@ class NewOrderBatchView(BatchMasterView):
|
||||||
""" """
|
""" """
|
||||||
super().configure_form(f)
|
super().configure_form(f)
|
||||||
|
|
||||||
|
# store_id
|
||||||
|
if not self.order_handler.expose_store_id():
|
||||||
|
f.remove('store_id')
|
||||||
|
|
||||||
# local_customer
|
# local_customer
|
||||||
f.set_node('local_customer', LocalCustomerRef(self.request))
|
f.set_node('local_customer', LocalCustomerRef(self.request))
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ from wuttaweb.views import MasterView
|
||||||
from wuttaweb.forms.schema import UserRef, WuttaMoney, WuttaQuantity, WuttaEnum, WuttaDictEnum
|
from wuttaweb.forms.schema import UserRef, WuttaMoney, WuttaQuantity, WuttaEnum, WuttaDictEnum
|
||||||
|
|
||||||
from sideshow.db.model import Order, OrderItem
|
from sideshow.db.model import Order, OrderItem
|
||||||
from sideshow.orders import OrderHandler
|
|
||||||
from sideshow.batch.neworder import NewOrderBatchHandler
|
from sideshow.batch.neworder import NewOrderBatchHandler
|
||||||
from sideshow.web.forms.schema import (OrderRef,
|
from sideshow.web.forms.schema import (OrderRef,
|
||||||
LocalCustomerRef, LocalProductRef,
|
LocalCustomerRef, LocalProductRef,
|
||||||
|
@ -155,20 +154,7 @@ class OrderView(MasterView):
|
||||||
|
|
||||||
def __init__(self, request, context=None):
|
def __init__(self, request, context=None):
|
||||||
super().__init__(request, context=context)
|
super().__init__(request, context=context)
|
||||||
self.order_handler = self.get_order_handler()
|
self.order_handler = self.app.get_order_handler()
|
||||||
|
|
||||||
def get_order_handler(self):
|
|
||||||
"""
|
|
||||||
Returns the configured :term:`order handler`.
|
|
||||||
|
|
||||||
You normally would not need to call this, and can use
|
|
||||||
:attr:`order_handler` instead.
|
|
||||||
|
|
||||||
:rtype: :class:`~sideshow.orders.OrderHandler`
|
|
||||||
"""
|
|
||||||
if hasattr(self, 'order_handler'):
|
|
||||||
return self.order_handler
|
|
||||||
return OrderHandler(self.config)
|
|
||||||
|
|
||||||
def get_batch_handler(self):
|
def get_batch_handler(self):
|
||||||
"""
|
"""
|
||||||
|
@ -190,6 +176,10 @@ class OrderView(MasterView):
|
||||||
""" """
|
""" """
|
||||||
super().configure_grid(g)
|
super().configure_grid(g)
|
||||||
|
|
||||||
|
# store_id
|
||||||
|
if not self.order_handler.expose_store_id():
|
||||||
|
g.remove('store_id')
|
||||||
|
|
||||||
# order_id
|
# order_id
|
||||||
g.set_link('order_id')
|
g.set_link('order_id')
|
||||||
|
|
||||||
|
@ -223,6 +213,7 @@ class OrderView(MasterView):
|
||||||
|
|
||||||
* :meth:`start_over()`
|
* :meth:`start_over()`
|
||||||
* :meth:`cancel_order()`
|
* :meth:`cancel_order()`
|
||||||
|
* :meth:`set_store()`
|
||||||
* :meth:`assign_customer()`
|
* :meth:`assign_customer()`
|
||||||
* :meth:`unassign_customer()`
|
* :meth:`unassign_customer()`
|
||||||
* :meth:`set_pending_customer()`
|
* :meth:`set_pending_customer()`
|
||||||
|
@ -232,10 +223,12 @@ class OrderView(MasterView):
|
||||||
* :meth:`delete_item()`
|
* :meth:`delete_item()`
|
||||||
* :meth:`submit_order()`
|
* :meth:`submit_order()`
|
||||||
"""
|
"""
|
||||||
|
model = self.app.model
|
||||||
enum = self.app.enum
|
enum = self.app.enum
|
||||||
self.creating = True
|
session = self.Session()
|
||||||
self.batch_handler = self.get_batch_handler()
|
self.batch_handler = self.get_batch_handler()
|
||||||
batch = self.get_current_batch()
|
batch = self.get_current_batch()
|
||||||
|
self.creating = True
|
||||||
|
|
||||||
context = self.get_context_customer(batch)
|
context = self.get_context_customer(batch)
|
||||||
|
|
||||||
|
@ -254,6 +247,7 @@ class OrderView(MasterView):
|
||||||
data = dict(self.request.json_body)
|
data = dict(self.request.json_body)
|
||||||
action = data.pop('action')
|
action = data.pop('action')
|
||||||
json_actions = [
|
json_actions = [
|
||||||
|
'set_store',
|
||||||
'assign_customer',
|
'assign_customer',
|
||||||
'unassign_customer',
|
'unassign_customer',
|
||||||
# 'update_phone_number',
|
# 'update_phone_number',
|
||||||
|
@ -285,12 +279,25 @@ class OrderView(MasterView):
|
||||||
for row in batch.rows],
|
for row in batch.rows],
|
||||||
'default_uom_choices': self.get_default_uom_choices(),
|
'default_uom_choices': self.get_default_uom_choices(),
|
||||||
'default_uom': None, # TODO?
|
'default_uom': None, # TODO?
|
||||||
|
'expose_store_id': self.order_handler.expose_store_id(),
|
||||||
'allow_item_discounts': self.batch_handler.allow_item_discounts(),
|
'allow_item_discounts': self.batch_handler.allow_item_discounts(),
|
||||||
'allow_unknown_products': (self.batch_handler.allow_unknown_products()
|
'allow_unknown_products': (self.batch_handler.allow_unknown_products()
|
||||||
and self.has_perm('create_unknown_product')),
|
and self.has_perm('create_unknown_product')),
|
||||||
'pending_product_required_fields': self.get_pending_product_required_fields(),
|
'pending_product_required_fields': self.get_pending_product_required_fields(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if context['expose_store_id']:
|
||||||
|
stores = session.query(model.Store)\
|
||||||
|
.filter(model.Store.archived == False)\
|
||||||
|
.order_by(model.Store.store_id)\
|
||||||
|
.all()
|
||||||
|
context['stores'] = [{'store_id': store.store_id, 'display': store.get_display()}
|
||||||
|
for store in stores]
|
||||||
|
|
||||||
|
# set default so things just work
|
||||||
|
if not batch.store_id:
|
||||||
|
batch.store_id = self.batch_handler.get_default_store_id()
|
||||||
|
|
||||||
if context['allow_item_discounts']:
|
if context['allow_item_discounts']:
|
||||||
context['allow_item_discounts_if_on_sale'] = self.batch_handler\
|
context['allow_item_discounts_if_on_sale'] = self.batch_handler\
|
||||||
.allow_item_discounts_if_on_sale()
|
.allow_item_discounts_if_on_sale()
|
||||||
|
@ -436,9 +443,26 @@ class OrderView(MasterView):
|
||||||
url = self.get_index_url()
|
url = self.get_index_url()
|
||||||
return self.redirect(url)
|
return self.redirect(url)
|
||||||
|
|
||||||
|
def set_store(self, batch, data):
|
||||||
|
"""
|
||||||
|
Assign the
|
||||||
|
:attr:`~sideshow.db.model.batch.neworder.NewOrderBatch.store_id`
|
||||||
|
for a batch.
|
||||||
|
|
||||||
|
This is a "batch action" method which may be called from
|
||||||
|
:meth:`create()`.
|
||||||
|
"""
|
||||||
|
store_id = data.get('store_id')
|
||||||
|
if not store_id:
|
||||||
|
return {'error': "Must provide store_id"}
|
||||||
|
|
||||||
|
batch.store_id = store_id
|
||||||
|
return self.get_context_customer(batch)
|
||||||
|
|
||||||
def get_context_customer(self, batch):
|
def get_context_customer(self, batch):
|
||||||
""" """
|
""" """
|
||||||
context = {
|
context = {
|
||||||
|
'store_id': batch.store_id,
|
||||||
'customer_is_known': True,
|
'customer_is_known': True,
|
||||||
'customer_id': None,
|
'customer_id': None,
|
||||||
'customer_name': batch.customer_name,
|
'customer_name': batch.customer_name,
|
||||||
|
@ -810,6 +834,10 @@ class OrderView(MasterView):
|
||||||
super().configure_form(f)
|
super().configure_form(f)
|
||||||
order = f.model_instance
|
order = f.model_instance
|
||||||
|
|
||||||
|
# store_id
|
||||||
|
if not self.order_handler.expose_store_id():
|
||||||
|
f.remove('store_id')
|
||||||
|
|
||||||
# local_customer
|
# local_customer
|
||||||
if order.customer_id and not order.local_customer:
|
if order.customer_id and not order.local_customer:
|
||||||
f.remove('local_customer')
|
f.remove('local_customer')
|
||||||
|
@ -910,8 +938,10 @@ class OrderView(MasterView):
|
||||||
""" """
|
""" """
|
||||||
settings = [
|
settings = [
|
||||||
|
|
||||||
# batches
|
# stores
|
||||||
{'name': 'wutta.batch.neworder.handler.spec'},
|
{'name': 'sideshow.orders.expose_store_id',
|
||||||
|
'type': bool},
|
||||||
|
{'name': 'sideshow.orders.default_store_id'},
|
||||||
|
|
||||||
# customers
|
# customers
|
||||||
{'name': 'sideshow.orders.use_local_customers',
|
{'name': 'sideshow.orders.use_local_customers',
|
||||||
|
@ -933,6 +963,9 @@ class OrderView(MasterView):
|
||||||
{'name': 'sideshow.orders.allow_unknown_products',
|
{'name': 'sideshow.orders.allow_unknown_products',
|
||||||
'type': bool,
|
'type': bool,
|
||||||
'default': True},
|
'default': True},
|
||||||
|
|
||||||
|
# batches
|
||||||
|
{'name': 'wutta.batch.neworder.handler.spec'},
|
||||||
]
|
]
|
||||||
|
|
||||||
# required fields for new product entry
|
# required fields for new product entry
|
||||||
|
@ -1037,6 +1070,7 @@ class OrderItemView(MasterView):
|
||||||
|
|
||||||
labels = {
|
labels = {
|
||||||
'order_id': "Order ID",
|
'order_id': "Order ID",
|
||||||
|
'store_id': "Store ID",
|
||||||
'product_id': "Product ID",
|
'product_id': "Product ID",
|
||||||
'product_scancode': "Scancode",
|
'product_scancode': "Scancode",
|
||||||
'product_brand': "Brand",
|
'product_brand': "Brand",
|
||||||
|
@ -1050,6 +1084,7 @@ class OrderItemView(MasterView):
|
||||||
|
|
||||||
grid_columns = [
|
grid_columns = [
|
||||||
'order_id',
|
'order_id',
|
||||||
|
'store_id',
|
||||||
'customer_name',
|
'customer_name',
|
||||||
# 'sequence',
|
# 'sequence',
|
||||||
'product_scancode',
|
'product_scancode',
|
||||||
|
@ -1099,20 +1134,7 @@ class OrderItemView(MasterView):
|
||||||
|
|
||||||
def __init__(self, request, context=None):
|
def __init__(self, request, context=None):
|
||||||
super().__init__(request, context=context)
|
super().__init__(request, context=context)
|
||||||
self.order_handler = self.get_order_handler()
|
self.order_handler = self.app.get_order_handler()
|
||||||
|
|
||||||
def get_order_handler(self):
|
|
||||||
"""
|
|
||||||
Returns the configured :term:`order handler`.
|
|
||||||
|
|
||||||
You normally would not need to call this, and can use
|
|
||||||
:attr:`order_handler` instead.
|
|
||||||
|
|
||||||
:rtype: :class:`~sideshow.orders.OrderHandler`
|
|
||||||
"""
|
|
||||||
if hasattr(self, 'order_handler'):
|
|
||||||
return self.order_handler
|
|
||||||
return OrderHandler(self.config)
|
|
||||||
|
|
||||||
def get_fallback_templates(self, template):
|
def get_fallback_templates(self, template):
|
||||||
""" """
|
""" """
|
||||||
|
@ -1132,11 +1154,19 @@ class OrderItemView(MasterView):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
# enum = self.app.enum
|
# enum = self.app.enum
|
||||||
|
|
||||||
|
# store_id
|
||||||
|
if not self.order_handler.expose_store_id():
|
||||||
|
g.remove('store_id')
|
||||||
|
|
||||||
# order_id
|
# order_id
|
||||||
g.set_sorter('order_id', model.Order.order_id)
|
g.set_sorter('order_id', model.Order.order_id)
|
||||||
g.set_renderer('order_id', self.render_order_id)
|
g.set_renderer('order_id', self.render_order_attr)
|
||||||
g.set_link('order_id')
|
g.set_link('order_id')
|
||||||
|
|
||||||
|
# store_id
|
||||||
|
g.set_sorter('store_id', model.Order.store_id)
|
||||||
|
g.set_renderer('store_id', self.render_order_attr)
|
||||||
|
|
||||||
# customer_name
|
# customer_name
|
||||||
g.set_label('customer_name', "Customer", column_only=True)
|
g.set_label('customer_name', "Customer", column_only=True)
|
||||||
|
|
||||||
|
@ -1165,9 +1195,10 @@ class OrderItemView(MasterView):
|
||||||
# status_code
|
# status_code
|
||||||
g.set_renderer('status_code', self.render_status_code)
|
g.set_renderer('status_code', self.render_status_code)
|
||||||
|
|
||||||
def render_order_id(self, item, key, value):
|
def render_order_attr(self, item, key, value):
|
||||||
""" """
|
""" """
|
||||||
return item.order.order_id
|
order = item.order
|
||||||
|
return getattr(order, key)
|
||||||
|
|
||||||
def render_status_code(self, item, key, value):
|
def render_status_code(self, item, key, value):
|
||||||
""" """
|
""" """
|
||||||
|
@ -1237,6 +1268,8 @@ class OrderItemView(MasterView):
|
||||||
item = context['instance']
|
item = context['instance']
|
||||||
form = context['form']
|
form = context['form']
|
||||||
|
|
||||||
|
context['expose_store_id'] = self.order_handler.expose_store_id()
|
||||||
|
|
||||||
context['item'] = item
|
context['item'] = item
|
||||||
context['order'] = item.order
|
context['order'] = item.order
|
||||||
context['order_qty_uom_text'] = self.order_handler.get_order_qty_uom_text(
|
context['order_qty_uom_text'] = self.order_handler.get_order_qty_uom_text(
|
||||||
|
|
|
@ -20,6 +20,16 @@ class TestNewOrderBatchHandler(DataTestCase):
|
||||||
def make_handler(self):
|
def make_handler(self):
|
||||||
return mod.NewOrderBatchHandler(self.config)
|
return mod.NewOrderBatchHandler(self.config)
|
||||||
|
|
||||||
|
def test_get_default_store_id(self):
|
||||||
|
handler = self.make_handler()
|
||||||
|
|
||||||
|
# null by default
|
||||||
|
self.assertIsNone(handler.get_default_store_id())
|
||||||
|
|
||||||
|
# whatever is configured
|
||||||
|
self.config.setdefault('sideshow.orders.default_store_id', '042')
|
||||||
|
self.assertEqual(handler.get_default_store_id(), '042')
|
||||||
|
|
||||||
def test_use_local_customers(self):
|
def test_use_local_customers(self):
|
||||||
handler = self.make_handler()
|
handler = self.make_handler()
|
||||||
|
|
||||||
|
@ -108,6 +118,23 @@ class TestNewOrderBatchHandler(DataTestCase):
|
||||||
# search for sally finds nothing
|
# search for sally finds nothing
|
||||||
self.assertEqual(handler.autocomplete_customers_local(self.session, 'sally'), [])
|
self.assertEqual(handler.autocomplete_customers_local(self.session, 'sally'), [])
|
||||||
|
|
||||||
|
def test_init_batch(self):
|
||||||
|
model = self.app.model
|
||||||
|
handler = self.make_handler()
|
||||||
|
|
||||||
|
# store_id is null by default
|
||||||
|
batch = handler.model_class()
|
||||||
|
self.assertIsNone(batch.store_id)
|
||||||
|
handler.init_batch(batch)
|
||||||
|
self.assertIsNone(batch.store_id)
|
||||||
|
|
||||||
|
# but default can be configured
|
||||||
|
self.config.setdefault('sideshow.orders.default_store_id', '042')
|
||||||
|
batch = handler.model_class()
|
||||||
|
self.assertIsNone(batch.store_id)
|
||||||
|
handler.init_batch(batch)
|
||||||
|
self.assertEqual(batch.store_id, '042')
|
||||||
|
|
||||||
def test_set_customer(self):
|
def test_set_customer(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
handler = self.make_handler()
|
handler = self.make_handler()
|
||||||
|
|
|
@ -13,3 +13,16 @@ class TestPendingCustomer(DataTestCase):
|
||||||
|
|
||||||
store.name = "Acme Goods"
|
store.name = "Acme Goods"
|
||||||
self.assertEqual(str(store), "Acme Goods")
|
self.assertEqual(str(store), "Acme Goods")
|
||||||
|
|
||||||
|
store.store_id = "001"
|
||||||
|
self.assertEqual(str(store), "001 Acme Goods")
|
||||||
|
|
||||||
|
def test_get_display(self):
|
||||||
|
store = mod.Store()
|
||||||
|
self.assertEqual(store.get_display(), "")
|
||||||
|
|
||||||
|
store.name = "Acme Goods"
|
||||||
|
self.assertEqual(store.get_display(), "Acme Goods")
|
||||||
|
|
||||||
|
store.store_id = "001"
|
||||||
|
self.assertEqual(store.get_display(), "001 Acme Goods")
|
||||||
|
|
17
tests/test_app.py
Normal file
17
tests/test_app.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
|
||||||
|
from wuttjamaican.testing import ConfigTestCase
|
||||||
|
|
||||||
|
from sideshow import app as mod
|
||||||
|
from sideshow.orders import OrderHandler
|
||||||
|
|
||||||
|
|
||||||
|
class TestSideshowAppProvider(ConfigTestCase):
|
||||||
|
|
||||||
|
def make_provider(self):
|
||||||
|
return mod.SideshowAppProvider(self.config)
|
||||||
|
|
||||||
|
def test_get_order_handler(self):
|
||||||
|
provider = self.make_provider()
|
||||||
|
handler = provider.get_order_handler()
|
||||||
|
self.assertIsInstance(handler, OrderHandler)
|
|
@ -16,6 +16,16 @@ class TestOrderHandler(DataTestCase):
|
||||||
def make_handler(self):
|
def make_handler(self):
|
||||||
return mod.OrderHandler(self.config)
|
return mod.OrderHandler(self.config)
|
||||||
|
|
||||||
|
def test_expose_store_id(self):
|
||||||
|
handler = self.make_handler()
|
||||||
|
|
||||||
|
# false by default
|
||||||
|
self.assertFalse(handler.expose_store_id())
|
||||||
|
|
||||||
|
# config can enable
|
||||||
|
self.config.setdefault('sideshow.orders.expose_store_id', 'true')
|
||||||
|
self.assertTrue(handler.expose_store_id())
|
||||||
|
|
||||||
def test_get_order_qty_uom_text(self):
|
def test_get_order_qty_uom_text(self):
|
||||||
enum = self.app.enum
|
enum = self.app.enum
|
||||||
handler = self.make_handler()
|
handler = self.make_handler()
|
||||||
|
|
|
@ -30,10 +30,19 @@ class TestNewOrderBatchView(WebTestCase):
|
||||||
def test_configure_grid(self):
|
def test_configure_grid(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
|
|
||||||
|
# store_id not exposed by default
|
||||||
grid = view.make_grid(model_class=model.NewOrderBatch)
|
grid = view.make_grid(model_class=model.NewOrderBatch)
|
||||||
self.assertNotIn('total_price', grid.renderers)
|
self.assertIn('store_id', grid.columns)
|
||||||
view.configure_grid(grid)
|
view.configure_grid(grid)
|
||||||
self.assertIn('total_price', grid.renderers)
|
self.assertNotIn('store_id', grid.columns)
|
||||||
|
|
||||||
|
# store_id is exposed if configured
|
||||||
|
self.config.setdefault('sideshow.orders.expose_store_id', 'true')
|
||||||
|
grid = view.make_grid(model_class=model.NewOrderBatch)
|
||||||
|
self.assertIn('store_id', grid.columns)
|
||||||
|
view.configure_grid(grid)
|
||||||
|
self.assertIn('store_id', grid.columns)
|
||||||
|
|
||||||
def test_configure_form(self):
|
def test_configure_form(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
|
@ -58,6 +67,19 @@ class TestNewOrderBatchView(WebTestCase):
|
||||||
self.assertIsInstance(schema['pending_customer'].typ, PendingCustomerRef)
|
self.assertIsInstance(schema['pending_customer'].typ, PendingCustomerRef)
|
||||||
self.assertIsInstance(schema['total_price'].typ, WuttaMoney)
|
self.assertIsInstance(schema['total_price'].typ, WuttaMoney)
|
||||||
|
|
||||||
|
# store_id not exposed by default
|
||||||
|
form = view.make_form(model_instance=batch)
|
||||||
|
self.assertIn('store_id', form)
|
||||||
|
view.configure_form(form)
|
||||||
|
self.assertNotIn('store_id', form)
|
||||||
|
|
||||||
|
# store_id is exposed if configured
|
||||||
|
self.config.setdefault('sideshow.orders.expose_store_id', 'true')
|
||||||
|
form = view.make_form(model_instance=batch)
|
||||||
|
self.assertIn('store_id', form)
|
||||||
|
view.configure_form(form)
|
||||||
|
self.assertIn('store_id', form)
|
||||||
|
|
||||||
def test_configure_row_grid(self):
|
def test_configure_row_grid(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
|
|
|
@ -31,27 +31,28 @@ class TestOrderView(WebTestCase):
|
||||||
def make_handler(self):
|
def make_handler(self):
|
||||||
return NewOrderBatchHandler(self.config)
|
return NewOrderBatchHandler(self.config)
|
||||||
|
|
||||||
def test_order_handler(self):
|
|
||||||
view = self.make_view()
|
|
||||||
handler = view.order_handler
|
|
||||||
self.assertIsInstance(handler, OrderHandler)
|
|
||||||
handler2 = view.get_order_handler()
|
|
||||||
self.assertIs(handler2, handler)
|
|
||||||
|
|
||||||
def test_configure_grid(self):
|
def test_configure_grid(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
grid = view.make_grid(model_class=model.PendingProduct)
|
|
||||||
self.assertNotIn('order_id', grid.linked_columns)
|
# store_id hidden by default
|
||||||
self.assertNotIn('total_price', grid.renderers)
|
grid = view.make_grid(model_class=model.Order, columns=['store_id', 'order_id'])
|
||||||
|
self.assertIn('store_id', grid.columns)
|
||||||
view.configure_grid(grid)
|
view.configure_grid(grid)
|
||||||
self.assertIn('order_id', grid.linked_columns)
|
self.assertNotIn('store_id', grid.columns)
|
||||||
self.assertIn('total_price', grid.renderers)
|
|
||||||
|
# store_id is shown if configured
|
||||||
|
self.config.setdefault('sideshow.orders.expose_store_id', 'true')
|
||||||
|
grid = view.make_grid(model_class=model.Order, columns=['store_id', 'order_id'])
|
||||||
|
self.assertIn('store_id', grid.columns)
|
||||||
|
view.configure_grid(grid)
|
||||||
|
self.assertIn('store_id', grid.columns)
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
self.pyramid_config.include('sideshow.web.views')
|
self.pyramid_config.include('sideshow.web.views')
|
||||||
self.config.setdefault('wutta.batch.neworder.handler.spec',
|
self.config.setdefault('wutta.batch.neworder.handler.spec',
|
||||||
'sideshow.batch.neworder:NewOrderBatchHandler')
|
'sideshow.batch.neworder:NewOrderBatchHandler')
|
||||||
|
self.config.setdefault('sideshow.orders.expose_store_id', 'true')
|
||||||
self.config.setdefault('sideshow.orders.allow_item_discounts', 'true')
|
self.config.setdefault('sideshow.orders.allow_item_discounts', 'true')
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
enum = self.app.enum
|
enum = self.app.enum
|
||||||
|
@ -59,6 +60,10 @@ class TestOrderView(WebTestCase):
|
||||||
|
|
||||||
user = model.User(username='barney')
|
user = model.User(username='barney')
|
||||||
self.session.add(user)
|
self.session.add(user)
|
||||||
|
store = model.Store(store_id='001', name='Acme Goods')
|
||||||
|
self.session.add(store)
|
||||||
|
store = model.Store(store_id='002', name='Acme Services')
|
||||||
|
self.session.add(store)
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
|
|
||||||
with patch.object(view, 'Session', return_value=self.session):
|
with patch.object(view, 'Session', return_value=self.session):
|
||||||
|
@ -101,6 +106,7 @@ class TestOrderView(WebTestCase):
|
||||||
self.assertIsInstance(response, Response)
|
self.assertIsInstance(response, Response)
|
||||||
self.assertEqual(response.content_type, 'application/json')
|
self.assertEqual(response.content_type, 'application/json')
|
||||||
self.assertEqual(response.json_body, {
|
self.assertEqual(response.json_body, {
|
||||||
|
'store_id': None,
|
||||||
'customer_is_known': False,
|
'customer_is_known': False,
|
||||||
'customer_id': None,
|
'customer_id': None,
|
||||||
'customer_name': 'Fred Flintstone',
|
'customer_name': 'Fred Flintstone',
|
||||||
|
@ -304,6 +310,7 @@ class TestOrderView(WebTestCase):
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
context = view.get_context_customer(batch)
|
context = view.get_context_customer(batch)
|
||||||
self.assertEqual(context, {
|
self.assertEqual(context, {
|
||||||
|
'store_id': None,
|
||||||
'customer_is_known': True,
|
'customer_is_known': True,
|
||||||
'customer_id': 42,
|
'customer_id': 42,
|
||||||
'customer_name': 'Fred Flintstone',
|
'customer_name': 'Fred Flintstone',
|
||||||
|
@ -321,6 +328,7 @@ class TestOrderView(WebTestCase):
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
context = view.get_context_customer(batch)
|
context = view.get_context_customer(batch)
|
||||||
self.assertEqual(context, {
|
self.assertEqual(context, {
|
||||||
|
'store_id': None,
|
||||||
'customer_is_known': True,
|
'customer_is_known': True,
|
||||||
'customer_id': local.uuid.hex,
|
'customer_id': local.uuid.hex,
|
||||||
'customer_name': 'Betty Boop',
|
'customer_name': 'Betty Boop',
|
||||||
|
@ -339,6 +347,7 @@ class TestOrderView(WebTestCase):
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
context = view.get_context_customer(batch)
|
context = view.get_context_customer(batch)
|
||||||
self.assertEqual(context, {
|
self.assertEqual(context, {
|
||||||
|
'store_id': None,
|
||||||
'customer_is_known': False,
|
'customer_is_known': False,
|
||||||
'customer_id': None,
|
'customer_id': None,
|
||||||
'customer_name': 'Fred Flintstone',
|
'customer_name': 'Fred Flintstone',
|
||||||
|
@ -357,6 +366,7 @@ class TestOrderView(WebTestCase):
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
context = view.get_context_customer(batch)
|
context = view.get_context_customer(batch)
|
||||||
self.assertEqual(context, {
|
self.assertEqual(context, {
|
||||||
|
'store_id': None,
|
||||||
'customer_is_known': True, # nb. this is for UI default
|
'customer_is_known': True, # nb. this is for UI default
|
||||||
'customer_id': None,
|
'customer_id': None,
|
||||||
'customer_name': None,
|
'customer_name': None,
|
||||||
|
@ -408,6 +418,34 @@ class TestOrderView(WebTestCase):
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
self.assertEqual(self.session.query(model.NewOrderBatch).count(), 0)
|
self.assertEqual(self.session.query(model.NewOrderBatch).count(), 0)
|
||||||
|
|
||||||
|
def test_set_store(self):
|
||||||
|
model = self.app.model
|
||||||
|
view = self.make_view()
|
||||||
|
handler = NewOrderBatchHandler(self.config)
|
||||||
|
|
||||||
|
user = model.User(username='barney')
|
||||||
|
self.session.add(user)
|
||||||
|
self.session.flush()
|
||||||
|
|
||||||
|
with patch.object(view, 'batch_handler', create=True, new=handler):
|
||||||
|
with patch.object(view, 'Session', return_value=self.session):
|
||||||
|
with patch.object(self.request, 'user', new=user):
|
||||||
|
|
||||||
|
batch = view.get_current_batch()
|
||||||
|
self.assertIsNone(batch.store_id)
|
||||||
|
|
||||||
|
# store_id is required
|
||||||
|
result = view.set_store(batch, {})
|
||||||
|
self.assertEqual(result, {'error': "Must provide store_id"})
|
||||||
|
result = view.set_store(batch, {'store_id': ''})
|
||||||
|
self.assertEqual(result, {'error': "Must provide store_id"})
|
||||||
|
|
||||||
|
# store_id is set on batch
|
||||||
|
result = view.set_store(batch, {'store_id': '042'})
|
||||||
|
self.assertEqual(batch.store_id, '042')
|
||||||
|
self.assertIn('store_id', result)
|
||||||
|
self.assertEqual(result['store_id'], '042')
|
||||||
|
|
||||||
def test_assign_customer(self):
|
def test_assign_customer(self):
|
||||||
self.pyramid_config.add_route('orders.create', '/orders/new')
|
self.pyramid_config.add_route('orders.create', '/orders/new')
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
|
@ -432,6 +470,7 @@ class TestOrderView(WebTestCase):
|
||||||
self.assertIsNone(batch.pending_customer)
|
self.assertIsNone(batch.pending_customer)
|
||||||
self.assertIs(batch.local_customer, weirdal)
|
self.assertIs(batch.local_customer, weirdal)
|
||||||
self.assertEqual(context, {
|
self.assertEqual(context, {
|
||||||
|
'store_id': None,
|
||||||
'customer_is_known': True,
|
'customer_is_known': True,
|
||||||
'customer_id': weirdal.uuid.hex,
|
'customer_id': weirdal.uuid.hex,
|
||||||
'customer_name': 'Weird Al',
|
'customer_name': 'Weird Al',
|
||||||
|
@ -470,6 +509,7 @@ class TestOrderView(WebTestCase):
|
||||||
self.assertIsNone(batch.customer_name)
|
self.assertIsNone(batch.customer_name)
|
||||||
self.assertIsNone(batch.local_customer)
|
self.assertIsNone(batch.local_customer)
|
||||||
self.assertEqual(context, {
|
self.assertEqual(context, {
|
||||||
|
'store_id': None,
|
||||||
'customer_is_known': True,
|
'customer_is_known': True,
|
||||||
'customer_id': None,
|
'customer_id': None,
|
||||||
'customer_name': None,
|
'customer_name': None,
|
||||||
|
@ -510,6 +550,7 @@ class TestOrderView(WebTestCase):
|
||||||
context = view.set_pending_customer(batch, data)
|
context = view.set_pending_customer(batch, data)
|
||||||
self.assertIsInstance(batch.pending_customer, model.PendingCustomer)
|
self.assertIsInstance(batch.pending_customer, model.PendingCustomer)
|
||||||
self.assertEqual(context, {
|
self.assertEqual(context, {
|
||||||
|
'store_id': None,
|
||||||
'customer_is_known': False,
|
'customer_is_known': False,
|
||||||
'customer_id': None,
|
'customer_id': None,
|
||||||
'customer_name': 'Fred Flintstone',
|
'customer_name': 'Fred Flintstone',
|
||||||
|
@ -1078,7 +1119,11 @@ class TestOrderView(WebTestCase):
|
||||||
form = view.make_form(model_instance=order)
|
form = view.make_form(model_instance=order)
|
||||||
# nb. this is to avoid include/exclude ambiguity
|
# nb. this is to avoid include/exclude ambiguity
|
||||||
form.remove('items')
|
form.remove('items')
|
||||||
|
# nb. store_id gets hidden by default
|
||||||
|
form.append('store_id')
|
||||||
|
self.assertIn('store_id', form)
|
||||||
view.configure_form(form)
|
view.configure_form(form)
|
||||||
|
self.assertNotIn('store_id', form)
|
||||||
schema = form.get_schema()
|
schema = form.get_schema()
|
||||||
self.assertIn('pending_customer', form)
|
self.assertIn('pending_customer', form)
|
||||||
self.assertIsInstance(schema['total_price'].typ, WuttaMoney)
|
self.assertIsInstance(schema['total_price'].typ, WuttaMoney)
|
||||||
|
@ -1089,13 +1134,20 @@ class TestOrderView(WebTestCase):
|
||||||
self.session.add(local)
|
self.session.add(local)
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
|
|
||||||
|
# nb. from now on we include store_id
|
||||||
|
self.config.setdefault('sideshow.orders.expose_store_id', 'true')
|
||||||
|
|
||||||
# viewing (local customer)
|
# viewing (local customer)
|
||||||
with patch.object(view, 'viewing', new=True):
|
with patch.object(view, 'viewing', new=True):
|
||||||
with patch.object(order, 'local_customer', new=local):
|
with patch.object(order, 'local_customer', new=local):
|
||||||
form = view.make_form(model_instance=order)
|
form = view.make_form(model_instance=order)
|
||||||
# nb. this is to avoid include/exclude ambiguity
|
# nb. this is to avoid include/exclude ambiguity
|
||||||
form.remove('items')
|
form.remove('items')
|
||||||
|
# nb. store_id will now remain
|
||||||
|
form.append('store_id')
|
||||||
|
self.assertIn('store_id', form)
|
||||||
view.configure_form(form)
|
view.configure_form(form)
|
||||||
|
self.assertIn('store_id', form)
|
||||||
self.assertNotIn('pending_customer', form)
|
self.assertNotIn('pending_customer', form)
|
||||||
schema = form.get_schema()
|
schema = form.get_schema()
|
||||||
self.assertIsInstance(schema['total_price'].typ, WuttaMoney)
|
self.assertIsInstance(schema['total_price'].typ, WuttaMoney)
|
||||||
|
@ -1272,13 +1324,6 @@ class TestOrderView(WebTestCase):
|
||||||
|
|
||||||
class OrderItemViewTestMixin:
|
class OrderItemViewTestMixin:
|
||||||
|
|
||||||
def test_common_order_handler(self):
|
|
||||||
view = self.make_view()
|
|
||||||
handler = view.order_handler
|
|
||||||
self.assertIsInstance(handler, OrderHandler)
|
|
||||||
handler2 = view.get_order_handler()
|
|
||||||
self.assertIs(handler2, handler)
|
|
||||||
|
|
||||||
def test_common_get_fallback_templates(self):
|
def test_common_get_fallback_templates(self):
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
|
|
||||||
|
@ -1294,18 +1339,29 @@ class OrderItemViewTestMixin:
|
||||||
def test_common_configure_grid(self):
|
def test_common_configure_grid(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
grid = view.make_grid(model_class=model.OrderItem)
|
|
||||||
self.assertNotIn('order_id', grid.linked_columns)
|
|
||||||
view.configure_grid(grid)
|
|
||||||
self.assertIn('order_id', grid.linked_columns)
|
|
||||||
|
|
||||||
def test_common_render_order_id(self):
|
# store_id is removed by default
|
||||||
|
grid = view.make_grid(model_class=model.OrderItem)
|
||||||
|
grid.append('store_id')
|
||||||
|
self.assertIn('store_id', grid.columns)
|
||||||
|
view.configure_grid(grid)
|
||||||
|
self.assertNotIn('store_id', grid.columns)
|
||||||
|
|
||||||
|
# store_id is shown if configured
|
||||||
|
self.config.setdefault('sideshow.orders.expose_store_id', 'true')
|
||||||
|
grid = view.make_grid(model_class=model.OrderItem)
|
||||||
|
grid.append('store_id')
|
||||||
|
self.assertIn('store_id', grid.columns)
|
||||||
|
view.configure_grid(grid)
|
||||||
|
self.assertIn('store_id', grid.columns)
|
||||||
|
|
||||||
|
def test_common_render_order_attr(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
order = model.Order(order_id=42)
|
order = model.Order(order_id=42)
|
||||||
item = model.OrderItem()
|
item = model.OrderItem()
|
||||||
order.items.append(item)
|
order.items.append(item)
|
||||||
self.assertEqual(view.render_order_id(item, None, None), 42)
|
self.assertEqual(view.render_order_attr(item, 'order_id', None), 42)
|
||||||
|
|
||||||
def test_common_render_status_code(self):
|
def test_common_render_status_code(self):
|
||||||
enum = self.app.enum
|
enum = self.app.enum
|
||||||
|
|
Loading…
Reference in a new issue