Fluent Commerce Logo
Sign In

Validate Customer ID at Pickup

How-to Guide
Extend

Authors:

Amine Sadallah, Siarhei Vaitsiakhovich, Randy Chan

Changed on:

4 July 2024

Key Points

  • This article gives System Integrator (SI) Partners and Businesses a high-level idea of where new features can be built on top of the OMS reference solution to support the customer's requirement within Fluent OMS.
  • This idea/solution will provide an extended new feature where the Store User can validate the Customer ID during the Customer Collection Process.
  • New custom UI components and rules are needed to capture the user input and confirm the selected articles in the UI user Action screen.  Then, the store/business can track and trace the proof of the shopper's collection.
  • Due to security reasons, the shopper's sensitive personal information should not be stored within Fluent OMS. Therefore, the proof of collection should be stored at a third-party storage.

Steps

Step arrow right iconSolution Approach

The customer collection process must include a step to validate customer identification. Some key aspects of this screen change:

  • Card 1: Customer card stays in the Customer Collection Screen.
No alt provided
  • Card 2: Validate Identification (new component) in the user action drawers:
    • This contains a drop-down of various identification types (presumably housed in a new setting)
      • Driver’s License
      • Passport
      • Student ID
      • Other
No alt providedNo alt provided
  • Card 3: Capture Signature (new component) in the user action drawers:
    • This needs to allow the capture of a signature. This requires a dialogue pop-up to enter (and re-enter if needed). This is similar to the return image capture component experience that was created.
    • This signature image should be saved as a file with a name that includes the article ID.
    • This signature image should be saved as a file in an external repo (like product images and return capture images)
    • This signature image should be visible against the article in Fluent OMS (like the return image is visible against the return order) Note: this idea is not part of this article.
No alt provided
  • Card 4: Article Selector (new component) in the user action drawers:
    • After the user has provided Identification, validated by the Store Staff, and captured the Shopper's signature, a list of articles will be displayed so that the Store Staff can pick which article is ready for collection:
No alt provided
  • By clicking the Submit button, all customer-provided information is stored in a third-party storage.

Step arrow right iconTechnical Design Overview

To support the business solution design, the following technical areas need to be enhanced:

  • A new custom UI component (by using Component SDK) -
    `articlesSelector`
  • Two custom rules (by using Rule SDK):
    • `UpdateArticleAttributesAccordingEventAttribute`
       
    • `SendEventForAllArticlesFromAttribute`
       
  • A new Setting to list out Identification Types:
    `IDENTIFICATION_TYPE`
  • Update of the Language Setting. E.g.
    `LANGUAGE_EN-AU`
  • Update Rulesets in CC Order workflow (
    `ARTICLE_COLLECTED`
    ,
    `ArticlesCollected`
    )

Each of these tasks will be described below in steps.

Step arrow right iconUI Component: articlesSelector

For training purposes, the signature canvas package can be downloaded here: https://www.npmjs.com/package/react-signature-canvas

After installing the React signature canvas, open up your Component SDK, and create a new file:

`IdentificationTypes.tsx`

1 return (
2    <Card
3      title={translate(
4        'fc.sf.ui.collections.articleSelector.identificationTypes.selector',
5      )}
6    >
7      <CardContent>
8        <FormControl className={classes.cardSelect} variant="outlined">
9          <InputLabel id="identification-label">
10            {translate(
11              'fc.sf.ui.collections.articleSelector.identificationTypes.title',
12            )}
13          </InputLabel>
14          <Select
15            onChange={(_event, identification: any) => {
16              setValidate(false);
17              setIdentificationType(identification.props.value);
18            }}
19            value={identificationType}
20            labelId="identification-label"
21            label={translate(
22              'fc.sf.ui.collections.articleSelector.identificationTypes.title',
23            )}
24          >
25            {identificationSetting &&
26              identificationSetting.map((item, idx) => {
27                const identificationItemText = translate(item);
28                return (
29                  <MenuItem key={idx} value={identificationItemText}>
30                    {identificationItemText}
31                  </MenuItem>
32                );
33              })}
34          </Select>
35        </FormControl>
36        <FormControlLabel
37          className={classes.cardCheckbox}
38          value="end"
39          control={
40            <Checkbox
41              color="primary"
42              checked={validate}
43              onChange={(_event, checked) => {
44                setValidate(checked);
45              }}
46            />
47          }
48          label={translate(
49            'fc.sf.ui.collections.articleSelector.identificationTypes.validate',
50          )}
51        />
52      </CardContent>
53    </Card>
54  );

Language: tsx

Name: IdentificationTypes sample output:

Description:

This will display a dropdown list of the type of identification accepted by the Store.  The list is derived from a setting.  It also displays a checkbox where the store user has confirmed the ID validation.


Then create a new file: 

`CanvasSignature.tsx`

1    <Card
2      title={translate('fc.sf.ui.collections.articleSelector.signature.title')}
3    >
4      <CardContent>
5        <div className={classes.sigCanvas}>
6          <SignatureCanvas
7            ref={(ref) => {
8              sigCanvas.current = ref;
9            }}
10            penColor="black"
11            backgroundColor="#eee"
12            canvasProps={{ width: 450, height: 150 }}
13          />
14        </div>
15        <div className={classes.sigBlockButton}>
16          <Button variant="contained" color="primary" onClick={clearSignature}>
17            {translate(
18              'fc.sf.ui.collections.articleSelector.signature.button.clear',
19            )}
20          </Button>
21          <Button variant="contained" color="primary" onClick={getDataUrl}>
22            {translate(
23              'fc.sf.ui.collections.articleSelector.signature.button.capture',
24            )}
25          </Button>
26        </div>
27      </CardContent>
28    </Card>

Language: tsx

Name: The CanvasSignature sample output:

Description:

This will display the Signature Canvas card with a clear button and a capture button.


Next, create a new file: 

`ArticleSelector.tsx`

 

1  return (
2    <div className={classes.articleColumn}>
3      <IdentificationTypes onChange={getIdentificationType} />
4      <CanvasSignature onChange={getSignature} />
5      {signature && identificationType && (
6        <TableContainer component={Paper}>
7          <Table className={classes.table}>
8            <TableHead>
9              <TableRow>
10                {articles?.length ? (
11                  <TableCell padding="checkbox">
12                    <Checkbox
13                      onChange={handleSelectAllClick}
14                      color="secondary"
15                      indeterminate={
16                        selectedRows.length > 0 &&
17                        selectedRows.length < articles.length
18                      }
19                      checked={
20                        articles.length > 0 &&
21                        selectedRows.length === articles.length
22                      }
23                      inputProps={{
24                        'aria-label': 'select all',
25                      }}
26                    />
27                  </TableCell>
28                ) : (
29                  ''
30                )}
31                <TableCell>
32                  <span>
33                    {translate(
34                      'fc.sf.ui.collections.articleSelector.details.list.column.storageArea.heading',
35                    )}
36                  </span>
37                </TableCell>
38                <TableCell>
39                  <span>
40                    {translate(
41                      'fc.sf.ui.collections.articleSelector.details.list.column.status.heading',
42                    )}
43                  </span>
44                </TableCell>
45                <TableCell>
46                  <span>
47                    {translate(
48                      'fc.sf.ui.collections.articleSelector.details.list.column.article.heading',
49                    )}
50                  </span>
51                </TableCell>
52              </TableRow>
53            </TableHead>
54            <TableBody>
55              {articles?.length ? (
56                articles.map((articleNode) => {
57                  const isItemSelected = isSelected(articleNode);
58                  return (
59                    <TableRow
60                      hover
61                      role="checkbox"
62                      tabIndex={-1}
63                      key={articleNode.ref}
64                      selected={isItemSelected}
65                    >
66                      <TableCell
67                        padding="checkbox"
68                        onClick={(e) => {
69                          selectRow(e, articleNode);
70                        }}
71                      >
72                        <Checkbox
73                          checked={
74                            !!selectedRows.find(
75                              (sel) => sel.key === articleNode.ref,
76                            )
77                          }
78                          inputProps={{
79                            'aria-labelledby': '' + articleNode.ref,
80                          }}
81                        />
82                      </TableCell>
83                      <TableCell>
84                        <span title={articleNode.storageArea?.name}>
85                          {articleNode.storageArea?.name}
86                        </span>
87                      </TableCell>
88                      <TableCell>
89                        <span title={articleNode.status}>
90                          <ContentColumn
91                            data={articleNode}
92                            value={'{{status}}'}
93                            contentColumnSetting={
94                              (contentColumnSetting.setting.status === 'ok' &&
95                                contentColumnSetting.setting.result?.value) ||
96                              'fc.list.status.column'
97                            }
98                          />
99                        </span>
100                      </TableCell>
101                      <TableCell>
102                        <span title={articleNode.ref}>
103                          <CollapsibleText
104                            text={articleNode.ref}
105                            charCutoff={8}
106                          />
107                        </span>
108                      </TableCell>
109                    </TableRow>
110                  );
111                })
112              ) : (
113                <TableRow className={classes.tableEmpty}>
114                  <TableCell colSpan={3} align="center">
115                    {translate(
116                      'fc.sf.ui.collections.articleSelector.details.list.noRecords',
117                    )}
118                  </TableCell>
119                </TableRow>
120              )}
121            </TableBody>
122          </Table>
123        </TableContainer>
124      )}
125    </div>
126  );

Language: tsx

Name: The CanvasSignature sample output:

Description:

After user has provided an Identification, validated by the Store Staff and capture the Shopper's signature, a list of articles will be displayed so that the Store Staff can pick which article is ready for collection


Step arrow right iconCustom Rules

Two custom Rules need to be added: 

SendEventForAllArticlesFromAttribute

Property

Value

Plugin name

<yourPluginName>

Rule API Client

GraphQL

Rule Info Description

Send an event

`{eventName}`
for articles from the event attribute
`ARTICLES`

Supported Entities

ORDER, FULFILMENT, ARTICLE

Input Parameters

Parameter

Description

eventName

The name of the event to be triggered

Event Attributes

Attribute Name

Description

ARTICLES

Object with information about articles in JSON format.

Example:

{

  "signature": "data:image/png;base64,iVBORw0KGgoAAAN...",

  "identificationType": "Passport",

  "articles": [

    "fd7c188b-d9cf-42da-9a71-14bd11e336183d443e333-1"

  ]

}

Where

`signature`
is a signature image in base64 format,
`identificationType`
is the type of identification document,
`articles`
are lists of article refs for processing.


UpdateArticleAttributesAccordingEventAttribute

Property

Value

Plugin name

<yourPluginName>

Rule API Client

GraphQL

Rule Info Description

Update Article attributes according to Event Attribute

`ARTICLES`
. Save given fields (
`IDENTIFICATION_TYPE`
and
`SIGNATURE`
) to entity Attributes.

Supported Entities

ARTICLE

Event Attributes

Attribute Name

Description

ARTICLES

Object with information about articles in JSON format.

Example:

{

  "signature": "data:image/png;base64,iVBORw0KGgoAAAN...",

  "identificationType": "Passport",

  "articles": [

    "fd7c188b-d9cf-42da-9a71-14bd11e336183d443e333-1"

  ]

}

Where

`signature`
is the signature image in base64 format,
`identificationType`
is the type of identification document,
`articles`
are lists of article refs for processing.

Step arrow right iconUpdate Language Setting

Include the following in your language Setting. For example: Setting name: LANGUAGE_EN-AU:

1{
2    "translation": {
3        "fc.sf.ui.collections.articleSelector.signature.success.capture": "Successful",
4        "fc.sf.ui.collections.articleSelector.signature.title": "CUSTOMER SIGNATURE",
5        "fc.sf.ui.collections.articleSelector.signature.button.clear": "Clear",
6        "fc.sf.ui.collections.articleSelector.signature.button.capture": "Capture",
7        "fc.sf.ui.collections.articleSelector.details.list.column.storageArea.heading": "Storage Area",
8        "fc.sf.ui.collections.articleSelector.details.list.column.status.heading": "Status",
9        "fc.sf.ui.collections.articleSelector.details.list.column.article.heading": "Article",
10        "fc.sf.ui.collections.articleSelector.identificationTypes.selector": "IDENTIFICATION TYPE",
11        "fc.sf.ui.collections.articleSelector.identificationTypes.title": "Validate Identification",
12        "fc.sf.ui.collections.articleSelector.identificationTypes.validate": "Validated",
13        "fc.sf.ui.collections.articleSelector.identificationTypes.driversLicense": "Driver License",
14        "fc.sf.ui.collections.articleSelector.identificationTypes.passport": "Passport",
15        "fc.sf.ui.collections.articleSelector.identificationTypes.studentId": "Student ID",
16        "fc.sf.ui.collections.articleSelector.identificationTypes.other": "Other",
17        
18        ...
19    }
20}

Language: json

Name: Language setting snippets

Description:

Language setting snippets

Step arrow right iconSetting: IDENTIFICATION_TYPE

Create a new Setting with the following:

Name

IDENTIFICATION_TYPE

Value Type

JSON

Context

ACCOUNT

Context ID

0

JSON Value

[

    "fc.sf.ui.collections.articleSelector.identificationTypes.driversLicense",

    "fc.sf.ui.collections.articleSelector.identificationTypes.passport",

    "fc.sf.ui.collections.articleSelector.identificationTypes.studentId",

    "fc.sf.ui.collections.articleSelector.identificationTypes.other"

]

Step arrow right iconCC Order Manifest Change

Update the Ruleset ARTICLE_COLLECTED with the following:

1{
2            "name": "ARTICLE_COLLECTED",
3            "description": "Customer collection",
4            "type": "ARTICLE",
5            "subtype": "DEFAULT",
6            "eventType": "NORMAL",
7            "rules": [
8                {
9                    "name": "{{fluent.account.id}}.core.SetState",
10                    "props": {
11                        "status": "COLLECTED"
12                    }
13                },
14                {
15                    "name": "{{fluent.account.id}}.{packageName}.UpdateArticleAttributesAccordingEventAttribute",
16                    "props": {}
17                },
18                {
19                    "name": "{{fluent.account.id}}.{packageName}.SendEventForAllArticlesFromAttribute",
20                    "props": {
21                        "eventName": "ArticleCollected"
22                    }
23                }
24            ],
25            "triggers": [
26                {
27                    "status": "AWAITING_COLLECTION"
28                }
29            ],
30            "userActions": [
31                {
32                    "context": [
33                        {
34                            "label": "CUSTOMER COLLECTION",
35                            "type": "PRIMARY",
36                            "modules": [
37                                "servicepoint"
38                            ],
39                            "confirm": false
40                        }
41                    ],
42                    "attributes": [
43                        {
44                            "name": "ARTICLES",
45                            "label": "Articles",
46                            "type": "articlesSelector",
47                            "source": "",
48                            "defaultValue": "",
49                            "mandatory": true
50                        }
51                    ]
52                }
53            ]
54        },

Language: json

Name: ARTICLE_COLLECTED ruleset in Click and Collect (CC) order workflow

Description:

ARTICLE_COLLECTED ruleset in CC order workflow

Step arrow right iconResult

The user should able to see the article selector UI in the User Action section:

No alt providedNo alt provided


The output of the above can be seen in the  third-party storage:

1"articles": {
2"edges": [
3    {
4        "node": {
5            "ref": "35e6ea8f-ee85-464c-dsdsdsds-2dsdsdsds-199_MEL-1",
6            "id": "1231",
7            "status": "COLLECTED",
8            "attributes": [
9                {
10                    "name": "IDENTIFICATION_TYPE",
11                    "type": "STRING",
12                    "value": "fc.sf.ui.collections.articleSelector.identificationTypes.driversLicense"
13                },
14                {
15                    "name": "SIGNATURE",
16                    "type": "STRING",
17                    "value": "data:image/png;base64,i...Jggg=="
18                }
19            ]
20        }
21    }
22]

Language: json

Name: sample output

Description:

Example of attributes

Amine Sadallah

Amine Sadallah

Contributors:
Siarhei Vaitsiakhovich
Randy Chan