Overhaul new custorder so contact may be either Person or Customer

also make the handler responsible for (un)assigning contact
This commit is contained in:
Lance Edgar 2021-09-27 09:22:06 -04:00
parent 12310da09e
commit a52b5ec380
2 changed files with 202 additions and 91 deletions

View file

@ -101,50 +101,63 @@
<br />
<div class="field">
<b-radio v-model="customerIsKnown"
<b-radio v-model="contactIsKnown"
:native-value="true">
Customer is already in the system.
</b-radio>
</div>
<div v-show="customerIsKnown">
<div v-show="contactIsKnown">
<b-field label="Customer" horizontal>
<tailbone-autocomplete ref="customerAutocomplete"
v-model="customerUUID"
<tailbone-autocomplete ref="contactAutocomplete"
v-model="contactUUID"
placeholder="Enter name or phone number"
:initial-label="customerDisplay"
:initial-label="contactDisplay"
% if new_order_requires_customer:
serviceUrl="${url('{}.customer_autocomplete'.format(route_prefix))}"
@input="customerChanged">
% else:
serviceUrl="${url('{}.person_autocomplete'.format(route_prefix))}"
% endif
@input="contactChanged">
</tailbone-autocomplete>
<b-button v-if="contactUUID && contactProfileURL"
type="is-primary"
tag="a" target="_blank"
:href="contactProfileURL"
icon-pack="fas"
icon-left="external-link-alt">
View Profile
</b-button>
</b-field>
<b-field label="Phone Number" horizontal
v-show="customerUUID">
<b-input v-model="phoneNumberEntry"
@input="phoneNumberChanged"
@keydown.native="phoneNumberKeyDown">
</b-input>
<b-button v-if="!phoneNumberSaved"
type="is-primary"
icon-pack="fas"
icon-left="fas fa-save"
@click="setCustomerData()">
Please save when finished editing
</b-button>
<!-- <tailbone-autocomplete -->
<!-- serviceUrl="${url('customers.autocomplete.phone')}"> -->
<!-- </tailbone-autocomplete> -->
v-show="contactUUID">
{{ phoneNumberEntry }}
## <b-input v-model="phoneNumberEntry"
## @input="phoneNumberChanged"
## @keydown.native="phoneNumberKeyDown">
## </b-input>
## <b-button v-if="!phoneNumberSaved"
## type="is-primary"
## icon-pack="fas"
## icon-left="fas fa-save"
## @click="setContactData()">
## Please save when finished editing
## </b-button>
## <!-- <tailbone-autocomplete -->
## <!-- serviceUrl="${url('customers.autocomplete.phone')}"> -->
## <!-- </tailbone-autocomplete> -->
</b-field>
</div>
<br />
<div class="field">
<b-radio v-model="customerIsKnown" disabled
<b-radio v-model="contactIsKnown" disabled
:native-value="false">
Customer is not yet in the system.
</b-radio>
</div>
<div v-if="!customerIsKnown">
<div v-if="!contactIsKnown">
<b-field label="Customer Name" horizontal>
<b-input v-model="customerName"></b-input>
</b-field>
@ -382,10 +395,11 @@
batchTotalPriceDisplay: ${json.dumps(normalized_batch['total_price_display'])|n},
customerPanelOpen: false,
customerIsKnown: true,
customerUUID: ${json.dumps(batch.customer_uuid)|n},
customerDisplay: ${json.dumps(six.text_type(batch.customer or ''))|n},
contactIsKnown: true,
contactUUID: ${json.dumps(batch.customer_uuid)|n},
contactDisplay: ${json.dumps(six.text_type(batch.customer or ''))|n},
customerEntry: null,
contactProfileURL: ${json.dumps(contact_profile_url)|n},
phoneNumberEntry: ${json.dumps(batch.phone_number)|n},
phoneNumberSaved: true,
customerName: null,
@ -415,12 +429,12 @@
customerPanelHeader() {
let text = "Customer"
if (this.customerIsKnown) {
if (this.customerUUID) {
if (this.$refs.customerAutocomplete) {
text = "Customer: " + this.$refs.customerAutocomplete.getDisplayText()
if (this.contactIsKnown) {
if (this.contactUUID) {
if (this.$refs.contactAutocomplete) {
text = "Customer: " + this.$refs.contactAutocomplete.getDisplayText()
} else {
text = "Customer: " + this.customerDisplay
text = "Customer: " + this.contactDisplay
}
}
} else {
@ -457,8 +471,8 @@
},
customerStatusTypeAndText() {
let phoneNumber = null
if (this.customerIsKnown) {
if (!this.customerUUID) {
if (this.contactIsKnown) {
if (!this.contactUUID) {
return {
type: 'is-danger',
text: "Please identify the customer.",
@ -495,7 +509,7 @@
}
}
if (!this.customerIsKnown) {
if (!this.contactIsKnown) {
return {
type: 'is-warning',
text: "Will create a new customer record.",
@ -555,8 +569,8 @@
// return
// }
// }
// this.customerIsKnown = true
// this.customerUUID = null
// this.contactIsKnown = true
// this.contactUUID = null
// // this.customerEntry = null
// this.phoneNumberEntry = null
// this.customerName = null
@ -607,17 +621,17 @@
})
},
setCustomerData() {
let params = {
action: 'set_customer_data',
customer_uuid: this.customerUUID,
phone_number: this.phoneNumberEntry,
}
let that = this
this.submitBatchData(params, function(response) {
that.phoneNumberSaved = true
})
},
// setContactData() {
// let params = {
// action: 'set_customer_data',
// customer_uuid: this.contactUUID,
// phone_number: this.phoneNumberEntry,
// }
// let that = this
// this.submitBatchData(params, function(response) {
// that.phoneNumberSaved = true
// })
// },
submitOrder() {
this.submittingOrder = true
@ -644,32 +658,40 @@
})
},
customerChanged(uuid) {
contactChanged(uuid) {
let params
if (!uuid) {
this.phoneNumberEntry = null
this.setCustomerData()
} else {
let params = {
action: 'get_customer_info',
uuid: this.customerUUID,
params = {
action: 'unassign_contact',
}
} else {
params = {
action: 'assign_contact',
uuid: this.contactUUID,
}
let that = this
this.submitBatchData(params, function(response) {
that.phoneNumberEntry = response.data.phone_number
that.setCustomerData()
})
}
let that = this
this.submitBatchData(params, function(response) {
console.log(response.data)
% if new_order_requires_customer:
that.contactUUID = response.data.customer_uuid
% else:
that.contactUUID = response.data.person_uuid
% endif
that.phoneNumberEntry = response.data.phone_number
that.contactProfileURL = response.data.contact_profile_url
})
},
phoneNumberChanged(value) {
this.phoneNumberSaved = false
},
// phoneNumberChanged(value) {
// this.phoneNumberSaved = false
// },
phoneNumberKeyDown(event) {
if (event.which == 13) { // Enter
this.setCustomerData()
}
},
// phoneNumberKeyDown(event) {
// if (event.which == 13) { // Enter
// this.setContactData()
// }
// },
showAddItemDialog() {
this.editingItem = null

View file

@ -227,8 +227,10 @@ class CustomerOrderView(MasterView):
data = dict(self.request.json_body)
action = data.get('action')
json_actions = [
'assign_contact',
'unassign_contact',
'get_customer_info',
'set_customer_data',
# 'set_customer_data',
'find_product_by_upc',
'get_product_info',
'add_item',
@ -251,8 +253,17 @@ class CustomerOrderView(MasterView):
context = {'batch': batch,
'normalized_batch': self.normalize_batch(batch),
'new_order_requires_customer': self.handler.new_order_requires_customer(),
'contact_profile_url': None,
'order_items': items,
'product_autocomplete_url': self.request.route_url(product_autocomplete)}
# maybe add profile URL
if batch.person_uuid:
if self.request.has_perm('people.view_profile'):
context['contact_profile_url'] = self.request.route_url(
'people.view_profile', uuid=batch.person_uuid)
return self.render_to_response(template, context)
def get_current_batch(self):
@ -307,13 +318,22 @@ class CustomerOrderView(MasterView):
def customer_autocomplete(self):
"""
Custom customer autocomplete logic, which invokes the handler.
Customer autocomplete logic, which invokes the handler.
"""
self.handler = self.get_batch_handler()
term = self.request.GET['term']
return self.handler.customer_autocomplete(self.Session(), term,
user=self.request.user)
def person_autocomplete(self):
"""
Person autocomplete logic, which invokes the handler.
"""
self.handler = self.get_batch_handler()
term = self.request.GET['term']
return self.handler.person_autocomplete(self.Session(), term,
user=self.request.user)
def get_customer_info(self, batch, data):
uuid = data.get('uuid')
if not uuid:
@ -326,30 +346,90 @@ class CustomerOrderView(MasterView):
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,
# most info comes from handler
info = self.handler.get_customer_info(batch)
# maybe add profile URL
if info['person_uuid']:
if self.request.has_perm('people.view_profile'):
info['contact_profile_url'] = self.request.route_url(
'people.view_profile', uuid=info['person_uuid']),
return info
def assign_contact(self, batch, data):
kwargs = {}
# this will either be a Person or Customer UUID
uuid = data['uuid']
if self.handler.new_order_requires_customer():
customer = self.Session.query(model.Customer).get(uuid)
if not customer:
return {'error': "Customer not found"}
kwargs['customer'] = customer
else:
person = self.Session.query(model.Person).get(uuid)
if not person:
return {'error': "Person not found"}
kwargs['person'] = person
# invoke handler to assign contact
try:
self.handler.assign_contact(batch, **kwargs)
except ValueError as error:
return {'error': six.text_type(error)}
context = {
'success': True,
'customer_uuid': batch.customer_uuid,
'person_uuid': batch.person_uuid,
'phone_number': batch.phone_number,
'email_address': batch.email_address,
}
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}
# maybe add profile URL
if batch.person_uuid:
if self.request.has_perm('people.view_profile'):
context['contact_profile_url'] = self.request.route_url(
'people.view_profile', uuid=batch.person_uuid)
return context
def unassign_contact(self, batch, data):
self.handler.unassign_contact(batch)
context = {
'success': True,
'customer_uuid': batch.customer_uuid,
'person_uuid': batch.person_uuid,
'phone_number': batch.phone_number,
'email_address': batch.email_address,
'contact_profile_url': None,
}
return context
# 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 product_autocomplete(self):
"""
@ -601,6 +681,15 @@ class CustomerOrderView(MasterView):
route_prefix = cls.get_route_prefix()
url_prefix = cls.get_url_prefix()
# person autocomplete
config.add_route('{}.person_autocomplete'.format(route_prefix),
'{}/person-autocomplete'.format(url_prefix),
request_method='GET')
config.add_view(cls, attr='person_autocomplete',
route_name='{}.person_autocomplete'.format(route_prefix),
renderer='json',
permission='people.list')
# customer autocomplete
config.add_route('{}.customer_autocomplete'.format(route_prefix),
'{}/customer-autocomplete'.format(url_prefix),