Add basic/unfinished "new customer order" page/feature
so far creates the order batch, and can set some customer info
This commit is contained in:
parent
c32f47ba95
commit
808e737202
4 changed files with 639 additions and 2 deletions
|
@ -26,8 +26,13 @@ Base class for customer order batch views
|
|||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import six
|
||||
|
||||
from rattail.db import model
|
||||
|
||||
import colander
|
||||
|
||||
from tailbone import forms
|
||||
from tailbone.views.batch import BatchMasterView
|
||||
|
||||
|
||||
|
@ -39,3 +44,79 @@ class CustomerOrderBatchView(BatchMasterView):
|
|||
model_class = model.CustomerOrderBatch
|
||||
model_row_class = model.CustomerOrderBatchRow
|
||||
default_handler_spec = 'rattail.batch.custorder:CustomerOrderBatchHandler'
|
||||
|
||||
grid_columns = [
|
||||
'id',
|
||||
'customer',
|
||||
'rows',
|
||||
'created',
|
||||
'created_by',
|
||||
]
|
||||
|
||||
form_fields = [
|
||||
'id',
|
||||
'customer',
|
||||
'person',
|
||||
'phone_number',
|
||||
'email_address',
|
||||
'created',
|
||||
'created_by',
|
||||
'rows',
|
||||
'status_code',
|
||||
]
|
||||
|
||||
def configure_grid(self, g):
|
||||
super(CustomerOrderBatchView, self).configure_grid(g)
|
||||
|
||||
g.set_link('customer')
|
||||
g.set_link('created')
|
||||
g.set_link('created_by')
|
||||
|
||||
def configure_form(self, f):
|
||||
super(CustomerOrderBatchView, self).configure_form(f)
|
||||
order = f.model_instance
|
||||
model = self.rattail_config.get_model()
|
||||
|
||||
# readonly fields
|
||||
f.set_readonly('rows')
|
||||
f.set_readonly('status_code')
|
||||
|
||||
# customer
|
||||
if 'customer' in f.fields and self.editing:
|
||||
f.replace('customer', 'customer_uuid')
|
||||
f.set_node('customer_uuid', colander.String(), missing=colander.null)
|
||||
customer_display = ""
|
||||
if self.request.method == 'POST':
|
||||
if self.request.POST.get('customer_uuid'):
|
||||
customer = self.Session.query(model.Customer)\
|
||||
.get(self.request.POST['customer_uuid'])
|
||||
if customer:
|
||||
customer_display = six.text_type(customer)
|
||||
elif self.editing:
|
||||
customer_display = six.text_type(order.customer or "")
|
||||
customers_url = self.request.route_url('customers.autocomplete')
|
||||
f.set_widget('customer_uuid', forms.widgets.JQueryAutocompleteWidget(
|
||||
field_display=customer_display, service_url=customers_url))
|
||||
f.set_label('customer_uuid', "Customer")
|
||||
else:
|
||||
f.set_renderer('customer', self.render_customer)
|
||||
|
||||
# person
|
||||
if 'person' in f.fields and self.editing:
|
||||
f.replace('person', 'person_uuid')
|
||||
f.set_node('person_uuid', colander.String(), missing=colander.null)
|
||||
person_display = ""
|
||||
if self.request.method == 'POST':
|
||||
if self.request.POST.get('person_uuid'):
|
||||
person = self.Session.query(model.Person)\
|
||||
.get(self.request.POST['person_uuid'])
|
||||
if person:
|
||||
person_display = six.text_type(person)
|
||||
elif self.editing:
|
||||
person_display = six.text_type(order.person or "")
|
||||
people_url = self.request.route_url('people.autocomplete')
|
||||
f.set_widget('person_uuid', forms.widgets.JQueryAutocompleteWidget(
|
||||
field_display=person_display, service_url=people_url))
|
||||
f.set_label('person_uuid', "Person")
|
||||
else:
|
||||
f.set_renderer('person', self.render_person)
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
################################################################################
|
||||
"""
|
||||
Views for 'creating' customer order batches
|
||||
|
||||
Note that this provides only the "direct" or "raw" table views for these
|
||||
batches. This does *not* provide a way to create a new batch; you should see
|
||||
:meth:`tailbone.views.custorders.orders.CustomerOrdersView.create()` for that
|
||||
logic.
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2018 Lance Edgar
|
||||
# Copyright © 2010-2020 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -43,7 +43,6 @@ class CustomerOrdersView(MasterView):
|
|||
"""
|
||||
model_class = model.CustomerOrder
|
||||
route_prefix = 'custorders'
|
||||
creatable = False
|
||||
editable = False
|
||||
deletable = False
|
||||
|
||||
|
@ -59,6 +58,8 @@ class CustomerOrdersView(MasterView):
|
|||
'id',
|
||||
'customer',
|
||||
'person',
|
||||
'phone_number',
|
||||
'email_address',
|
||||
'created',
|
||||
'status_code',
|
||||
]
|
||||
|
@ -115,6 +116,130 @@ class CustomerOrdersView(MasterView):
|
|||
url = self.request.route_url('people.view', uuid=person.uuid)
|
||||
return tags.link_to(text, url)
|
||||
|
||||
def create(self, form=None, template='create'):
|
||||
"""
|
||||
View for creating a new customer order. Note that it does so by way of
|
||||
maintaining a "new customer order" batch, until the user finally
|
||||
submits the order, at which point the batch is converted to a proper
|
||||
order.
|
||||
"""
|
||||
batch = self.get_current_batch()
|
||||
|
||||
if self.request.method == 'POST':
|
||||
|
||||
# first we check for traditional form post
|
||||
action = self.request.POST.get('action')
|
||||
post_actions = [
|
||||
'start_over_entirely',
|
||||
'delete_batch',
|
||||
]
|
||||
if action in post_actions:
|
||||
return getattr(self, action)(batch)
|
||||
|
||||
# okay then, we'll assume newer JSON-style post params
|
||||
data = dict(self.request.json_body)
|
||||
action = data.get('action')
|
||||
json_actions = [
|
||||
'get_customer_info',
|
||||
'set_customer_data',
|
||||
'submit_new_order',
|
||||
]
|
||||
if action in json_actions:
|
||||
result = getattr(self, action)(batch, data)
|
||||
return self.json_response(result)
|
||||
|
||||
context = {'batch': batch}
|
||||
return self.render_to_response(template, context)
|
||||
|
||||
def get_current_batch(self):
|
||||
user = self.request.user
|
||||
if not user:
|
||||
raise RuntimeError("this feature requires a user to be logged in")
|
||||
|
||||
try:
|
||||
# there should be at most *one* new batch per user
|
||||
batch = self.Session.query(model.CustomerOrderBatch)\
|
||||
.filter(model.CustomerOrderBatch.mode == self.enum.CUSTORDER_BATCH_MODE_CREATING)\
|
||||
.filter(model.CustomerOrderBatch.created_by == user)\
|
||||
.one()
|
||||
|
||||
except orm.exc.NoResultFound:
|
||||
# no batch yet for this user, so make one
|
||||
batch = model.CustomerOrderBatch()
|
||||
batch.mode = self.enum.CUSTORDER_BATCH_MODE_CREATING
|
||||
batch.created_by = user
|
||||
self.Session.add(batch)
|
||||
self.Session.flush()
|
||||
|
||||
return batch
|
||||
|
||||
def start_over_entirely(self, batch):
|
||||
# just delete current batch outright
|
||||
# TODO: should use self.handler.do_delete() instead?
|
||||
self.Session.delete(batch)
|
||||
self.Session.flush()
|
||||
|
||||
# send user back to normal "create" page; a new batch will be generated
|
||||
# for them automatically
|
||||
route_prefix = self.get_route_prefix()
|
||||
url = self.request.route_url('{}.create'.format(route_prefix))
|
||||
return self.redirect(url)
|
||||
|
||||
def delete_batch(self, batch):
|
||||
# just delete current batch outright
|
||||
# TODO: should use self.handler.do_delete() instead?
|
||||
self.Session.delete(batch)
|
||||
self.Session.flush()
|
||||
|
||||
# set flash msg just to be more obvious
|
||||
self.request.session.flash("New customer order has been deleted.")
|
||||
|
||||
# send user back to customer orders page, w/ no new batch generated
|
||||
route_prefix = self.get_route_prefix()
|
||||
url = self.request.route_url(route_prefix)
|
||||
return self.redirect(url)
|
||||
|
||||
def get_customer_info(self, batch, data):
|
||||
uuid = data.get('uuid')
|
||||
if not uuid:
|
||||
return {'error': "Must specify a customer UUID"}
|
||||
|
||||
customer = self.Session.query(model.Customer).get(uuid)
|
||||
if not customer:
|
||||
return {'error': "Customer not found"}
|
||||
|
||||
return self.info_for_customer(batch, data, customer)
|
||||
|
||||
def info_for_customer(self, batch, data, customer):
|
||||
phone = customer.first_phone()
|
||||
email = customer.first_email()
|
||||
return {
|
||||
'uuid': customer.uuid,
|
||||
'phone_number': phone.number if phone else None,
|
||||
'email_address': email.address if email else None,
|
||||
}
|
||||
|
||||
def set_customer_data(self, batch, data):
|
||||
if 'customer_uuid' in data:
|
||||
batch.customer_uuid = data['customer_uuid']
|
||||
if 'person_uuid' in data:
|
||||
batch.person_uuid = data['person_uuid']
|
||||
elif batch.customer_uuid:
|
||||
self.Session.flush()
|
||||
batch.person = batch.customer.first_person()
|
||||
else: # no customer set
|
||||
batch.person_uuid = None
|
||||
if 'phone_number' in data:
|
||||
batch.phone_number = data['phone_number']
|
||||
if 'email_address' in data:
|
||||
batch.email_address = data['email_address']
|
||||
self.Session.flush()
|
||||
return {'success': True}
|
||||
|
||||
def submit_new_order(self, batch, data):
|
||||
# TODO
|
||||
return {'success': True}
|
||||
|
||||
|
||||
def includeme(config):
|
||||
CustomerOrdersView.defaults(config)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue