From 1ebeac923fa04eee6a77f4bd821b631abb7745eb 2021-09-24 17:27:00 From: Lance Edgar Date: 2021-09-24 17:27:00 Subject: [PATCH] Add "custom" customer autocomplete for new custorder handler can search by name or phone number --- diff --git a/rattail/batch/custorder.py b/rattail/batch/custorder.py index 947508ad5f64a57688d623136e52014a7757eb39..e54b2e64033c8ce87c9d6ccca43c55485d26a189 100644 --- a/rattail/batch/custorder.py +++ b/rattail/batch/custorder.py @@ -26,7 +26,10 @@ Handler for "customer order" batches from __future__ import unicode_literals, absolute_import, division +import re + import six +import sqlalchemy as sa from sqlalchemy import orm from rattail.db import model @@ -48,6 +51,7 @@ class CustomerOrderBatchHandler(BatchHandler): """ batch_model_class = model.CustomerOrderBatch has_custom_product_autocomplete = False + nondigits_pattern = re.compile(r'\D') def get_case_size_for_product(self, product): if product.case_size: @@ -57,6 +61,61 @@ class CustomerOrderBatchHandler(BatchHandler): if cost: return cost.case_size + def get_phone_search_term(self, term): + """ + Try to figure out if the given search term represents a whole + or partial phone number, and if so return just the digits. + """ + digits = self.nondigits_pattern.sub('', term) + if digits and len(digits) >= 4: + return digits + + def customer_autocomplete(self, session, term, **kwargs): + """ + Override the customer autocomplete, to search by phone number + as well as customer name. + """ + model = self.model + + # define the base query + query = session.query(model.Customer)\ + .options(orm.joinedload(model.Customer.phones)) + + # does search term look like a phone number? + phone_term = self.get_phone_search_term(term) + if phone_term: + + # yep, so just search for the phone number + query = query.join(model.CustomerPhoneNumber, + model.CustomerPhoneNumber.parent_uuid == model.Customer.uuid) + query = query.filter(sa.func.regexp_replace(model.CustomerPhoneNumber.number, + r'\D', '', 'g')\ + .like('%{}%'.format(phone_term))) + + else: # term does not look like a phone number + + # so just search by customer name + criteria = [model.Customer.name.ilike('%{}%'.format(word)) + for word in term.split()] + query = query.filter(sa.and_(*criteria)) + + # oh, and sort by something useful + query = query.order_by(model.Customer.name) + + # generate result list from query + results = [] + for customer in query: + phone = customer.first_phone() + if phone: + label = "{} {}".format(customer.name, phone.number) + else: + label = customer.name + results.append({'value': customer.uuid, + 'label': label, + 'display': customer.name}) + + return results + def custom_product_autocomplete(self, session, term, **kwargs): """ For the given term, this should return a (possibly empty) list