Pick Service Request
********************

This type of service request is used for picking inventory out of the butler
system.

Pick Request Lifecycle
======================

.. mermaid::

   graph TD
       A[created] --> |Inventory available and blocked| B[fulfillable]
       B --> |First rack reached| C[cancellation_locked]
       C --> |First pick transaction done| D[pick_started]
       D --> |Pick transactions| D
       D --> |All picks done| E[complete]
       A --> |Inventory not available| F[not_fulfillable]
       A --> |Cancel API call| G[cancelled]
       B --> |Cancel API call| G
       D --> |Partially complete due to<br/>inventory missing| H[abandoned]

       class E node-success
       class F node-failure
       class G node-failure
       class H node-failure

Pick Service Request Object
===========================

A pick service request object is derived from the generic :ref:`Service Request
Object`.

.. gm:data:: pickServiceRequest

   .. gm:data:: type

      The type of a pick service request object is ``PICK``.

   .. gm:data:: serviceRequests

      This is a list of child service requests of this object. The list elements
      are of the type :gm:data:`pickLineServiceRequest`, and at least one child
      pick line is required.

   .. gm:data:: attributes

      This is an *optional* dictionary containing key-value pairs that affect how
      this service request is processed.

      Supported attributes:

      .. gm:data:: pick_before_time

         This is a string in ISO 8601 datetime format. The system will set this
         as the **deadline before which** this order has to be picked.

      .. gm:data:: pick_after_time

         This is a string in ISO 8601 datetime format. The system will set this
         as the **time after which** this order can be picked.

      .. gm:data:: simple_priority

      .. versionadded:: 4.0

         This is a string representing the priority of this service request. It
         can have the following values:

         #. ``normal``: This is the default value of the priority.
         #. ``high``: High priority orders have a higher chance of being
            completed before normal orders.
         #. ``low``: Low priority orders have a lower chance of being completed
            before normal orders.
         #. ``critical``: Critical orders have the highest probability of being
            picked early, and critical orders can even jump pick_before_time /
            pick_after_time boundaries.

      .. gm:data:: order_options

         This is a dictionary representing key-value pairs that further affect
         how this service request will be processed. The possible values here
         can be different depending on different downstream fulfillment engines
         configured in the system.

.. gm:data:: pickLineServiceRequest

   This service request describes a single pick line in a pick service request.

   .. gm:data:: type

      The type of a pick line service request object is ``PICK_LINE``.

   .. gm:data:: expectations

      The expectations object in a pick line service request defines the
      product(s) to be picked.

      This object is of the form: ``{ "containers": [``
      :gm:data:`pickLineExpectationContainer` ``]}``.

.. gm:data:: pickLineExpectationContainer

   .. gm:data:: products[]

      This is a list with one object containing the product details.

      .. gm:data:: productQuantity

         An integer representing the quantity of eaches to be picked.

      .. gm:data:: productAttributes

         This is an object which specifies which product has to be picked for
         this pick line.

         .. gm:data:: filter_parameters

            This is a list of strings with a special SQL-like syntax which
            represents filtering criteria to match the product to be picked.

            If multiple filter strings are given, products matching all the
            filters are selected.

            Each filter string is of the format::

              unique_key operator value

            * ``unique_key`` is one of the uniquely defining attributes of the
              product
            * ``operator`` is one of ``=``, ``in``.
            * ``value`` is either a string with single quotes, or a list of
              strings.

            Examples:

            .. sourcecode:: json

               {
                   "filter_parameters": [
                       "product_sku = 'SKU12345'"
                   ]
               }

            .. sourcecode:: json

               {
                   "filter_parameters": [
                       "lot_id in ['e82b3734-8dee-48a8-af72-e6c0abcc6eec',
                                   '6f6dd87f-d0f5-49de-bd4e-94dd58e8d682',
                                   'd3cbd2e8-c5a2-43ac-8467-87de272496b5']"
                   ]
               }

            .. sourcecode:: json

               {
                   "filter_parameters": [
                       "product_sku = 'SKU12345'",
                       "client_id = 'C1'"
                   ]
               }


Create a Pick Request
=====================

.. http:post:: /api-gateway/sr-service/platform-srms/service-request

   To create a new pick service request, a :ref:`Pick Service Request Object`
   should be sent in a HTTP POST request to the above endpoint. The newly
   created or modified object will be returned in the response if the request is
   successful.

   :reqheader Content-Type: the request's content-type has to be passed in this
                            header
   :reqheader Accept: the response content type depends on
                      :mailheader:`Accept` header
   :reqheader Authorization: OAuth token to authenticate
   :statuscode 200: No error
   :statuscode 400: Bad data

   .. container:: toggle

      .. container:: header

         **Example request**:

      .. sourcecode:: http

         POST /api-gateway/sr-service/platform-srms/service-request HTTP/1.1
         Host: example.com
         Content-Type: application/json
         Accept: application/json, text/javascript

      .. literalinclude:: pick/create_pick_request.json
         :language: JSON

   .. container:: toggle

      .. container:: header

         **Example Response**:
      
      .. sourcecode:: http

         HTTP/1.1 200 OK
         Content-Type: application/json;charset=UTF-8

      .. literalinclude:: pick/create_pick_response.json
         :language: JSON


Cancel a Pick Request
=====================

.. http:post:: /api-gateway/sr-service/platform-srms/service-request/cancel

   A Pick request can only be modified or cancelled before the
   ``cancellation_locked`` state. Please consult the :ref:`Pick Request
   Lifecycle` for details.

   Pick cancellation works asynchronously. So, this API accepts the request, and
   generates a success or failure notification according to the result.

   .. seealso:: :ref:`Cancelled and Modified Notification`

   .. todo:: Write about full vs partial cancellation

   :reqheader Content-Type: the request's content-type has to be passed in this
                            header
   :reqheader Accept: the response content type depends on
                      :mailheader:`Accept` header
   :reqheader Authorization: OAuth token to authenticate

   :<json string externalServiceRequestId: :gm:data:`serviceRequest.externalServiceRequestId`
                                           to be cancelled
   :<json string type: Should be equal to ``PICK``

   :>json int id: A unique transaction id for this request. The result
                  notification will have this transaction id for reference.
   :>json string externalServiceRequestId: :gm:data:`serviceRequest.externalServiceRequestId`
   :>json string type: ``PICK``

   :statuscode 202: The request has been accepted for processing
   :statuscode 400: Bad data

   .. container:: toggle

      .. container:: header

         **Example request**:

      .. sourcecode:: http

         POST /api-gateway/sr-service/platform-srms/service-request/cancel HTTP/1.1
         Host: example.com
         Content-Type: application/json
         Accept: application/json, text/javascript

      .. literalinclude:: pick/cancel_pick_request.json
         :language: JSON

   .. container:: toggle

      .. container:: header

         **Example Response**:
      
      .. sourcecode:: http

         HTTP/1.1 200 OK
         Content-Type: application/json;charset=UTF-8

      .. literalinclude:: pick/cancel_pick_response.json
         :language: JSON


Modify a Pick Request
=====================

.. http:post:: /api-gateway/sr-service/platform-srms/service-request/modify

   A Pick request can only be modified or cancelled before the
   ``cancellation_locked`` state. Please consult the :ref:`Pick Request
   Lifecycle` for details.

   Pick modification works asynchronously. So, this API accepts the request, and
   generates a success or failure notification according to the result.

   .. seealso:: :ref:`Cancelled and Modified Notification`

   :reqheader Content-Type: the request's content-type has to be passed in this
                            header
   :reqheader Accept: the response content type depends on
                      :mailheader:`Accept` header
   :reqheader Authorization: OAuth token to authenticate

   :<json string externalServiceRequestId: :gm:data:`serviceRequest.externalServiceRequestId`
                                           to be modified
   :<json string type: Should be equal to ``PICK``
   :<json expectations: (Optional) Can be passed if expectation(s) of this
                        service request have to be modified.
   :<json serviceRequests: (Optional) Can be passed if child service request(s)
                           of this service request have to be modified.
   :<json attributes: (Optional) Can be passed if attributes of this service
                      request have to be modified.

   :>json int id: A unique transaction id for this request. The result
                  notification will have this transaction id for reference.
   :>json string externalServiceRequestId: :gm:data:`serviceRequest.externalServiceRequestId`
   :>json string type: ``PICK``

   :statuscode 202: The request has been accepted for processing
   :statuscode 400: Bad data

   .. container:: toggle

      .. container:: header

         **Example request**:

      .. sourcecode:: http

         POST /api-gateway/sr-service/platform-srms/service-request/modify HTTP/1.1
         Host: example.com
         Content-Type: application/json
         Accept: application/json, text/javascript

      .. literalinclude:: pick/modify_pick_request.json
         :language: JSON

   .. container:: toggle

      .. container:: header

         **Example Response**:
      
      .. sourcecode:: http

         HTTP/1.1 200 OK
         Content-Type: application/json;charset=UTF-8

      .. literalinclude:: pick/modify_pick_response.json
         :language: JSON

Pick Request Notifications
==========================

All Pick Request notifications follow the generic notification format (see
:ref:`Event Notifications`), and contain the relevant payload in the
:gm:data:`notification.notification_data` attribute.

Fulfillable Notification
------------------------

.. container:: toggle

   .. container:: header

      Show/Hide
   
   .. literalinclude:: pick/fulfillable_notification.json
      :language: JSON

Cancellation Locked Notification
--------------------------------

.. container:: toggle

   .. container:: header

      Show/Hide
   
   .. literalinclude:: pick/cancellation_locked_notification.json
      :language: JSON

Pick Started Notification
-------------------------

.. container:: toggle

   .. container:: header

      Show/Hide
   
   .. literalinclude:: pick/pick_started_notification.json
      :language: JSON

Unfulfillable Notification
--------------------------

.. container:: toggle

   .. container:: header

      Show/Hide
   
   .. literalinclude:: pick/unfulfillable_notification.json
      :language: JSON

Abandoned Notification
----------------------

.. container:: toggle

   .. container:: header

      Show/Hide
   
   .. literalinclude:: pick/abandoned_notification.json
      :language: JSON

Cancelled and Modified Notification
-----------------------------------

This notification is sent when a cancellation or modification request has been
processed.

Attributes in :gm:data:`notification.notification_data`:

* **id**: Transaction id of the cancellation/modification request for which this
  is a response.
* **state**: Status. Either ``success`` or ``failure``.

Sample Notification:

   .. container:: toggle

      .. container:: header

         Show/Hide

      .. literalinclude:: pick/cancelled_modified_notification.json
         :language: JSON


In case the cancellation or modification is successful, an additional
``order_information`` notification is generated:

   .. container:: toggle

      .. container:: header

         Order Information after cancellation

      .. literalinclude:: pick/cancelled_order_information_notification.json
         :language: JSON


Order Complete Notification
---------------------------

.. container:: toggle

   .. container:: header

      Show/Hide
   
   .. literalinclude:: pick/order_complete_notification.json
      :language: JSON

Bin Complete Notification
-------------------------

.. container:: toggle

   .. container:: header

      Show/Hide
   
   .. literalinclude:: pick/bin_complete_notification.json
      :language: JSON

Item Picked Notifications
-------------------------

This notification is sent whenever a pick transaction is done. The payload
contains the complete current state of the service request.

Some examples of different cases are shown below:

   .. container:: toggle

      .. container:: header
   
         Item Picked (K-Deep Containers)
      
      .. literalinclude:: pick/item_picked_kdeep_notification.json
         :language: JSON
   
   .. container:: toggle
   
      .. container:: header
   
         Item Picked (Eaches)
      
      .. literalinclude:: pick/item_picked_eaches_notification.json
         :language: JSON

   .. container:: toggle
   
      .. container:: header
   
         Item Picked (Tote Flow)
      
      .. literalinclude:: pick/item_picked_tote_flow_notification.json
         :language: JSON

   .. container:: toggle
   
      .. container:: header
   
         Item Picked (with Item Missing exception)
      
      .. literalinclude:: pick/item_picked_missing_notification.json
         :language: JSON