Problem/Motivation

Single search field like the product search in POS

Searches, if available:

email
username
phone number
name
address

Shows results in ajax style like the Product widget.

If no user is found, you should be able to quickly create a new customer, with a minimum of an email or phone number ONLY, although if possible allow for other details, although that might make sense in a followup issue.

Proposed resolution

Create customer lookup widget

Remaining tasks

User interface changes

API changes

Data model changes

Comments

Hubbs created an issue. See original summary.

smccabe’s picture

Status: Needs work » Postponed (maintainer needs more info)

This gif is of the order edit screen, not the POS screen, which should already have the default ability to search and pick users if i recall.

shabana.navas’s picture

Status: Postponed (maintainer needs more info) » Active
StatusFileSize
new1021.14 KB

Nope, we still don't have a customer lookup for POS.

sorabh.v6’s picture

Assigned: Unassigned » sorabh.v6
sorabh.v6’s picture

Issue summary: View changes

Whenever I remove user from the POS form using remove button, it not only remove the user from the form but from drupal too. Therefore, I suggest we remove this block from the POS form.

Only local images are allowed.

sorabh.v6’s picture

StatusFileSize
new20.24 KB
sorabh.v6’s picture

Assigned: sorabh.v6 » Unassigned
Status: Active » Needs work
StatusFileSize
new2.85 MB
new378 bytes

Hi,

I have removed the customer block and left the customer email textfield as it is. After removing the customer field from form I checked to see the POS order are created successfully and have no problem. I tried to use CustomerFormTrait to create the customer lookup field same ways as used in OrderAddForm. But it is not changing the field by clicking the new user radio button as can be seen in attached gif -

Please review the patch and suggest the next step.

Thanks

heddn’s picture

The IS and what is being discussed lower down don't match up. It would help to improve the IS.

smccabe’s picture

Issue summary: View changes

Updated Issue summary to reflect what we should build here, vs tweaking some existing stuff.

rakesh.gectcr’s picture

Issue summary: View changes
rakesh.gectcr’s picture

Issue summary: View changes
rakesh.gectcr’s picture

Title: Add ability to look up existing registered user accounts » POS customer search widget [Add ability to look up existing registered user accounts]
rakesh.gectcr’s picture

Assigned: Unassigned » rakesh.gectcr
jcandan’s picture

@sorabh.v6, your patch in #7 is incomplete. It doesn't contain the changes that would provide the functionality that your gif demonstrates. Could you please recreate the patch and upload it.

sorabh.v6’s picture

@jcandan Ah! What I wanted to show in that gif is a problem. The customer autocomplete field on the order form works perfectly but when I imported that customer field on POS form, it wasn't working for the new customers. As you can see in the gif, the field doesn't change when I click on the new customer radio button.

Again, sorry for the incomplete information.

rakesh.gectcr’s picture

@here, Shall we use the search API for making the search possible? While installing drupal commerce using composer, however search api module getting downloaded at the beginning itself, So shall we make use of that ?

smccabe’s picture

@rakesh what we normally do is a simple db query as a default and then search api if available. Lets it have fewer mandatory requirements if people don't want to get complex. Do whichever one you feel like first though, your call.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new1.32 KB

@smccabe and @rakesh.gectcr asked me to provide some direction here.

At the moment the customer field is an inline entity form - complex widget. It's not quite configured the way we'd like and it doesn't work for creating users. These feel at bit like bugs in inline_entity_form. I'm going to have a look at that module and see what's going on. It'd be great if we could get most of the functionality required here without having to do a custom widget like we did with products (that needed to be special because of the order -> product -> product_variation relationship). The patch attached configures the field it a way that's a bit more likely. And we also need to not attach the user creating the order because that's not the expected behaviour for Commerce POS.

rakesh.gectcr’s picture

StatusFileSize
new162.84 KB

@alexpott

Yes, there is an an issue reported in IEF module https://www.drupal.org/project/inline_entity_form/issues/2702401#comment-11898337

after applying the above patch I am able to get the form to create new user.

rakesh.gectcr’s picture

rakesh.gectcr’s picture

deepakaryan1988’s picture

StatusFileSize
new1.32 KB

I am also able to open the form and changed few things in the code.

Please let me know if this needs further enhancement.

Status: Needs review » Needs work

The last submitted patch, 22: 2921655-22.patch, failed testing. View results

deepakaryan1988’s picture

StatusFileSize
new1.64 KB

Re uploading the patch after changing in the code.

deepakaryan1988’s picture

Status: Needs work » Needs review
alexpott’s picture

Assigned: rakesh.gectcr » Unassigned
+++ b/config/install/core.entity_form_display.commerce_order.pos.default.yml
@@ -46,20 +46,20 @@ content:
+  billing_profile: TRUE
+  created: TRUE
+  field_cashier: TRUE
+  field_register: TRUE
+  ip_address: TRUE
+  order_number: TRUE
+  state: TRUE
+  store_id: TRUE

The use of CAPITALS here is not correct. The capitals standard is for PHP. For yaml files we use the format written by Symfony's Yaml component as our standard - which is the patch in #18.

So @smccabe we have a choice here. Do we create our own widget for user registration or do we push on #2702401: Add integration for the user entity type and try and get that done for IEF.

alexpott’s picture

StatusFileSize
new1.32 KB

Re-uploading the patch from #18 to make the most recent patch the correct patch.

smccabe’s picture

Status: Needs review » Needs work

Bojan is trying to decrease Commerce cores dependency on IEF, since it is a maintenance nightmare. Making it work for all entity types is a constant pain.

We should probably follow suit and do the same, so a custom widget similar to what we did for order items makes the most sense.

shabana.navas’s picture

Assigned: Unassigned » shabana.navas
Status: Needs work » Needs review
StatusFileSize
new13.97 KB
new1.21 MB

A WIP of the new customer widget.

Status: Needs review » Needs work

The last submitted patch, 29: pos_new_customer_widget-2921655-29.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

shabana.navas’s picture

StatusFileSize
new18.18 KB

More changes. Still need to implement look up by customer order billing name, address and phone. And of course TESTS!

shabana.navas’s picture

Version: 8.x-2.0-alpha1 » 8.x-2.x-dev
Status: Needs work » Needs review
StatusFileSize
new29.44 KB

Ready for review. Tests also included.

Status: Needs review » Needs work

The last submitted patch, 32: pos_new_customer_widget-2921655-32.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

shabana.navas’s picture

Status: Needs work » Needs review
StatusFileSize
new29.28 KB

Phpcs fixes.

shabana.navas’s picture

Assigned: shabana.navas » Unassigned

Status: Needs review » Needs work

The last submitted patch, 34: pos_new_customer_widget-2921655-34.patch, failed testing. View results

shabana.navas’s picture

Status: Needs work » Needs review
StatusFileSize
new30.08 KB

Fixed code for tests.

alexpott’s picture

Status: Needs review » Needs work
  1. +++ b/src/Controller/PosCustomerAutoComplete.php
    @@ -0,0 +1,134 @@
    +  /**
    +   * The tempstore object.
    +   *
    +   * @var \Drupal\user\SharedTempStore
    +   */
    +  protected $tempStore;
    ...
    +    $this->tempStore = $temp_store_factory->get('commerce_pos');
    

    Not used.

  2. +++ b/src/Controller/PosCustomerAutoComplete.php
    @@ -0,0 +1,134 @@
    +  public function searchQueryString($string, $count) {
    +    $query = \Drupal::database();
    +    $query = $query->select('users_field_data', 'u')
    +      ->fields('u', ['uid', 'name'])
    +      ->orderBy('uid', 'DESC')
    +      ->range(0, $count);
    +    $query->leftJoin('user__field_commerce_pos_phone_number', 'p', 'u.uid = p.entity_id');
    +    $query->leftJoin('commerce_order', 'o', 'u.uid = o.uid');
    +    $query->leftJoin('profile__address', 'a', 'o.billing_profile__target_id = a.entity_id');
    +    $query->condition('u.uid', 0, '!=');
    +    $query->condition($query->orConditionGroup()
    +      ->condition('u.name', '%' . $string . '%', 'LIKE')
    +      ->condition('u.mail', '%' . $string . '%', 'LIKE')
    +      ->condition('p.field_commerce_pos_phone_number_value', '%' . $string . '%', 'LIKE')
    +      ->condition('a.address_address_line1', '%' . $string . '%', 'LIKE')
    +      // Search for just a matching first name.
    +      ->condition('a.address_given_name', '%' . $string . '%', 'LIKE')
    +      // Search for just a matching last name.
    +      ->condition('a.address_family_name', '%' . $string . '%', 'LIKE')
    +      // Search for a matching full name.
    +      ->where("CONCAT(a.address_given_name, ' ', a.address_family_name) LIKE :q", [':q' => $string])
    +    );
    +
    +    // Execute the query.
    +    $result = $query->execute()->fetchAllKeyed(0, 1);
    +
    +    return $result;
    

    Can we convert this into two entity queries - one against users and one against profiles?

  3. +++ b/src/Plugin/Field/FieldWidget/PosOrderItemWidget.php
    @@ -187,6 +187,7 @@ class PosOrderItemWidget extends WidgetBase implements WidgetInterface, Containe
    +    $form_state->set('form_wrapper_id', $wrapper_id);
    

    I'm not sure that we should link the two widgets like this. Maybe we should make the widgets use something set by PosForm if it is set or add there own if not. This will make the widgets a bit more independent.

sorabh.v6’s picture

Assigned: Unassigned » sorabh.v6
sorabh.v6’s picture

@alexpott

I tried to convert the query into two entity queries as suggested in point 2, but I need some direction. I can get the user query and profile query using -

$userQuery = $this->entityTypeManager->getStorage('users')->getQuery();

$profileQuery = $this->entityTypeManager->getStorage('profile')->getQuery();

But how to apply join on them and how to do the other joins also -

$query->leftJoin('user__field_commerce_pos_phone_number', 'p', 'u.uid = p.entity_id');
    $query->leftJoin('commerce_order', 'o', 'u.uid = o.uid');
    $query->leftJoin('profile__address', 'a', 'o.billing_profile__target_id = a.entity_id');

I also need some more information about point 3.

shabana.navas’s picture

Saurabh, I believe what Alex is recommending is (correct me if I'm wrong Alex) we first do an entity query on the users table, and if we haven't got a user, we then, do an entity query on the profile table. So, you'd do something like this:

// Do query on user entity.
$query = $this->entity_query->get('user')
    ->condition('status', 1)
    ->condition('changed', REQUEST_TIME, '<');
  
$group = $query->orConditionGroup()
    ->condition('title', 'ipsum lorem', 'CONTAINS')
    ->condition('field_tags.entity.name', 'test');
  
$uids = $query->condition($group)->execute();

// Do similar query on profile entity.
if (empty($uids)) {
...
}

As for the comment on

$form_state->set('form_wrapper_id', $wrapper_id);

remove that line. I think we should just set a form wrapper in POSForm.php and then, in OrderItemWidget and CustomerWidget, we just make sure that $form has a prefix and suffix and then, use that as the ajax wrapper ID. If it doesn't exist (which it will as we're setting it in POSForm.php, but just to be safe), then, we do our own, $form['#prefix'] = ....

alexpott’s picture

@shabana.navas++ yep exactly.

shabana.navas’s picture

Great, thanks for the confirmation Alex!

sorabh.v6’s picture

Thanks guys, will post the updated patch soon.

smccabe’s picture

Flipped the entity_query work to a separate issue, it isn't quite as simple as it seems.

  • How to handle first name + last name searching, you need to concat the fields, so you can't use regular entity query for that, at least not without making it pretty gross.
  • Splitting into 2 queries makes your results weird, if you get 1 result on users, then as you add more detail, you drop your 1 user but gain 10 matches from profile, it's misleading to the user, who expects an ever narrowing filter.

I think the real change here is we should just build in some search_api support for both customers and order_items, as that would allow much better searching that either of these methods.

#2938569: Add Search API Support

smccabe’s picture

Status: Needs work » Needs review
StatusFileSize
new31.5 KB

Fixed up the form stuff as per Shabana and Alex's recommendations

  • smccabe committed 8e599ba on 8.x-2.x
    Issue #2921655 by shabana.navas, sorabh.v6, alexpott, smccabe, Hubbs:...
smccabe’s picture

Status: Needs review » Fixed
sorabh.v6’s picture

Assigned: sorabh.v6 » Unassigned

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.