Misc. improvements for Customer Orders view

This commit is contained in:
Lance Edgar 2023-09-10 17:06:14 -05:00
parent e255c35e86
commit e49e0edc57
3 changed files with 113 additions and 15 deletions

View file

@ -0,0 +1,3 @@
## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" />
${parent.body()}

View file

@ -85,8 +85,10 @@ class CustomerOrderItemView(MasterView):
form_fields = [ form_fields = [
'order', 'order',
'sequence', 'customer',
'person', 'person',
'sequence',
'_product_key_',
'product', 'product',
'pending_product', 'pending_product',
'product_brand', 'product_brand',
@ -97,9 +99,11 @@ class CustomerOrderItemView(MasterView):
'case_quantity', 'case_quantity',
'unit_price', 'unit_price',
'total_price', 'total_price',
'special_order',
'price_needs_confirmation', 'price_needs_confirmation',
'paid_amount', 'paid_amount',
'status_code', 'status_code',
'flagged',
'notes', 'notes',
] ]
@ -167,13 +171,30 @@ class CustomerOrderItemView(MasterView):
return HTML.tag('span', title=item.status_text, c=[text]) return HTML.tag('span', title=item.status_text, c=[text])
return text return text
def get_batch_handler(self):
app = self.get_rattail_app()
return app.get_batch_handler(
'custorder',
default='rattail.batch.custorder:CustomerOrderBatchHandler')
def configure_form(self, f): def configure_form(self, f):
super(CustomerOrderItemView, self).configure_form(f) super().configure_form(f)
item = f.model_instance item = f.model_instance
# order # order
f.set_renderer('order', self.render_order) f.set_renderer('order', self.render_order)
# contact
batch_handler = self.get_batch_handler()
if batch_handler.new_order_requires_customer():
f.remove('person')
else:
f.remove('customer')
# product key
key = self.get_product_key_field()
f.set_renderer(key, lambda item, field: getattr(item, f'product_{key}'))
# (pending) product # (pending) product
f.set_renderer('product', self.render_product) f.set_renderer('product', self.render_product)
f.set_renderer('pending_product', self.render_pending_product) f.set_renderer('pending_product', self.render_pending_product)
@ -192,13 +213,6 @@ class CustomerOrderItemView(MasterView):
f.set_renderer('product_size', self.highlight_pending_field) f.set_renderer('product_size', self.highlight_pending_field)
f.set_renderer('case_quantity', self.highlight_pending_field_quantity) f.set_renderer('case_quantity', self.highlight_pending_field_quantity)
'unit_price',
'total_price',
'price_needs_confirmation',
'paid_amount',
'status_code',
'notes',
# quantity fields # quantity fields
f.set_type('cases_ordered', 'quantity') f.set_type('cases_ordered', 'quantity')
f.set_type('units_ordered', 'quantity') f.set_type('units_ordered', 'quantity')

View file

@ -52,7 +52,7 @@ class CustomerOrderView(MasterView):
configurable = True configurable = True
labels = { labels = {
'id': "ID", 'id': "Order ID",
'status_code': "Status", 'status_code': "Status",
} }
@ -60,8 +60,9 @@ class CustomerOrderView(MasterView):
'id', 'id',
'customer', 'customer',
'person', 'person',
'created',
'status_code', 'status_code',
'created',
'created_by',
] ]
form_fields = [ form_fields = [
@ -88,14 +89,17 @@ class CustomerOrderView(MasterView):
row_grid_columns = [ row_grid_columns = [
'sequence', 'sequence',
'_product_key_',
'product_brand', 'product_brand',
'product_description', 'product_description',
'product_size', 'product_size',
'order_quantity', 'order_quantity',
'order_uom', 'order_uom',
'case_quantity', 'case_quantity',
'department_name',
'total_price', 'total_price',
'status_code', 'status_code',
'flagged',
] ]
def __init__(self, request): def __init__(self, request):
@ -107,11 +111,19 @@ class CustomerOrderView(MasterView):
.options(orm.joinedload(model.CustomerOrder.customer)) .options(orm.joinedload(model.CustomerOrder.customer))
def configure_grid(self, g): def configure_grid(self, g):
super(CustomerOrderView, self).configure_grid(g) super().configure_grid(g)
# id
g.set_link('id')
g.filters['id'].default_active = True
g.filters['id'].default_verb = 'equal'
# import ipdb; ipdb.set_trace()
# customer or person # customer or person
if self.batch_handler.new_order_requires_customer(): if self.batch_handler.new_order_requires_customer():
g.remove('person') g.remove('person')
g.set_link('customer')
g.set_joiner('customer', lambda q: q.outerjoin(model.Customer)) g.set_joiner('customer', lambda q: q.outerjoin(model.Customer))
g.set_sorter('customer', model.Customer.name) g.set_sorter('customer', model.Customer.name)
g.filters['customer'] = g.make_filter('customer', model.Customer.name, g.filters['customer'] = g.make_filter('customer', model.Customer.name,
@ -120,6 +132,7 @@ class CustomerOrderView(MasterView):
default_verb='contains') default_verb='contains')
else: else:
g.remove('customer') g.remove('customer')
g.set_link('person')
g.set_joiner('person', lambda q: q.outerjoin(model.Person)) g.set_joiner('person', lambda q: q.outerjoin(model.Person))
g.set_sorter('person', model.Person.display_name) g.set_sorter('person', model.Person.display_name)
g.filters['person'] = g.make_filter('person', model.Person.display_name, g.filters['person'] = g.make_filter('person', model.Person.display_name,
@ -127,13 +140,14 @@ class CustomerOrderView(MasterView):
default_active=True, default_active=True,
default_verb='contains') default_verb='contains')
# status_code
g.set_enum('status_code', self.enum.CUSTORDER_STATUS) g.set_enum('status_code', self.enum.CUSTORDER_STATUS)
# created
g.set_sort_defaults('created', 'desc') g.set_sort_defaults('created', 'desc')
g.set_link('id') def get_instance_title(self, order):
g.set_link('customer') return f"#{order.id} for {order.customer or order.person}"
g.set_link('person')
def configure_form(self, f): def configure_form(self, f):
super(CustomerOrderView, self).configure_form(f) super(CustomerOrderView, self).configure_form(f)
@ -232,6 +246,10 @@ class CustomerOrderView(MasterView):
'custorder', 'custorder',
default='rattail.batch.custorder:CustomerOrderBatchHandler') default='rattail.batch.custorder:CustomerOrderBatchHandler')
# product key
key = self.get_product_key_field()
g.set_renderer(key, lambda item, field: getattr(item, f'product_{key}'))
g.set_type('case_quantity', 'quantity') g.set_type('case_quantity', 'quantity')
g.set_type('order_quantity', 'quantity') g.set_type('order_quantity', 'quantity')
g.set_type('cases_ordered', 'quantity') g.set_type('cases_ordered', 'quantity')
@ -962,6 +980,61 @@ class CustomerOrderView(MasterView):
def execute_new_order_batch(self, batch, data): def execute_new_order_batch(self, batch, data):
return self.batch_handler.do_execute(batch, self.request.user) return self.batch_handler.do_execute(batch, self.request.user)
def fetch_order_data(self):
app = self.get_rattail_app()
model = self.model
order = None
uuid = self.request.GET.get('uuid')
if uuid:
order = self.Session.get(model.CustomerOrder, uuid)
if not order:
# raise self.notfound()
return {'error': "Customer order not found"}
address = None
if self.batch_handler.new_order_requires_customer():
contact = order.customer
else:
contact = order.person
if contact and contact.address:
a = contact.address
address = {
'street_1': a.street,
'street_2': a.street2,
'city': a.city,
'state': a.state,
'zip': a.zipcode,
}
# gather all the order items
items = []
grand_total = 0
for item in order.items:
item_data = {
'uuid': item.uuid,
'special_order': False, # TODO
'product_description': item.product_description,
'order_quantity': app.render_quantity(item.order_quantity),
'department': item.department_name,
'price': app.render_currency(item.unit_price),
'total': app.render_currency(item.total_price),
}
items.append(item_data)
grand_total += item.total_price
return {
'uuid': order.uuid,
'id': order.id,
'created_display': app.render_datetime(app.localtime(order.created, from_utc=True)),
'contact_display': str(contact or ''),
'address': address,
'phone_display': str(contact.phone) if contact and contact.phone else "",
'email_display': str(contact.email) if contact and contact.email else "",
'items': items,
'grand_total_display': app.render_currency(grand_total),
}
def configure_get_simple_settings(self): def configure_get_simple_settings(self):
return [ return [
@ -1048,6 +1121,14 @@ class CustomerOrderView(MasterView):
renderer='json', renderer='json',
permission='products.list') permission='products.list')
# fetch order data
config.add_route(f'{route_prefix}.fetch_order_data',
f'{url_prefix}/fetch-order-data')
config.add_view(cls, attr='fetch_order_data',
route_name=f'{route_prefix}.fetch_order_data',
renderer='json',
permission=f'{permission_prefix}.view')
# TODO: deprecate / remove this # TODO: deprecate / remove this
CustomerOrdersView = CustomerOrderView CustomerOrdersView = CustomerOrderView