---
# System prepended metadata

title: Project documentation template
tags: [Documentation]

---

---
title: 'Project documentation template'
---

# Samsoe omni channel & K3 Integration
 
</br>

## Table of Contents

[TOC]

</br>

## Introduction

</br>Switching from Samsøe's current DdD solution to the new K3 | Imagine POS requires a shared "agreement" and an interface between Alpha's and K3's systems. The current Samsøe omni channel integration with DdD uses a standard API integration. The new Imagine POS integration will possibly use an event driven approach, meaning that there is no or very little documentation on how to inertact with that system. The purpose for this document is to establish a Documentation or "agreement" across both teams. Everything contained in this document is considered important for the pilot (phase 1).

```sequence
Storefront->K3 | DataSwitch: Create (OiS) Web Order

K3 | DataSwitch->Storefront: Web Order Payment Token

Inventory Balancer (IB)->K3 | DataSwitch: Sale

Inventory Balancer (IB)->K3 | DataSwitch: Return

Inventory Balancer (IB)->K3 | DataSwitch: Stock Adjustment

K3 | DataSwitch->Inventory Balancer (IB): Stock Movement Event

K3 | DataSwitch->Inventory Balancer (IB): Sale Callback Notification

K3 | DataSwitch->Inventory Balancer (IB): Return Callback Notification

K3 | DataSwitch->Inventory Balancer (IB): Stock Adjustment Callback Notification

```

Each arrow from above will be explained briefly here:

* *Sale - Expected behavior:* A sale is sent from IB to K3 DS. A sale is a financial transaction of goods. A sale has 2 main purposes. 1) It serves as a financial transaction that samsøe will use to create financial reports etc. 2) It also serves as a tool for adjusting stock for a specific shop. A sale will implicitly descrease stock in the shop. (Unless it is a return or negative sale, then stock should increase).

* *Return - Expected behavior:* A return is sent from IB to K3 DS. A return is simply a reverse sale. It is important to keep balance in the financials. If we bookeep sales we of course need to book keep returns. A return will increase stock for a given shop.

* *Stock Adjustment - Expected behavior:* A stock adjustment is sent from IB to K3 DS. Serves the purpose of increasing and/or decreasing stock levels. If a stock adjustment is executed with amount of negative 1 (-1) then stock for that particular item will decrease by 1. This endpoint will both handle initiating the adjustment as well as approving it. In other words, stock will be affected imidiately after the request has been accepted.

* *Stock Movement - Expected behavior:* Whenever a stock has been adjusted in store for any reason what so ever, an event should be triggered and pushed to IB. K3 DS sends a request to IB based on the event.

* *Sale Callback Notification - Expected behavior:* A callback notification is sent from K3 DS to IB with information about the original Sale request. The callback should have information such as a 'success' attribute to tell if the transaction was successful or not. It should also have a relevant error code or error message in case something went wrong. Errors recived from K3 DSW should contain information such as Client vs. Server error and a descriptive error message.

* *Return Callback Notification - Expected behavior:* Same as 'Sale Callback Notification'.

* *Stock Adjustment Callback Notification - Expected behavior:* Same as 'Sale Callback Notification'.

* *Create (OiS) Web Order - Expected behavior:* A Web Order Create request is sent from alpha (Storefront) to K3 DS.

* *Web Order Payment Token - Expected behavior:* When a Web Order is payed in-store DSW must sent back any relevant Adyen payment information such as pspReference, orderNumber, authCode etc.

K3 DataSwitch new Endpoints:
- Receive Sale
- Receive Retun
- Receive Stock Adjustment
- Receive Web Order

K3 DataSwitch events:
- Send Stock Movement Event
- Send Sale Callback Notification Event
- Send Return Callback Notification Event
- Send Stock Callback Notification Adjustment Event
- Send Web Order Payment Event

Inventory Balancer New Endpoints:
- Receive Stock Movement
- Receive Sale Callback Notification
- Receive Return Callback Notification
- Receive Stock Adjustment Callback Notification

Salesforce New Endpoint(s):
- Receive Web Order Payment

</br>
Data flow example of an online sale:
```sequence
Storefront->OMS: send order
OMS->Storefront: order received (sync)
IB->OMS: request closed orders
OMS->IB: closed orders (sync)
IB->K3 DS: request sale
K3 DS->IB: sale request received (sync)
K3 DS->IB: callback notification (async)
```

Data flow example of an in-store sale:
```sequence
K3 Imagine POS->K3 DS: new sale
K3 DS->K3 Imagine POS: received

K3 DS->IB: new stock movement
IB->K3 DS: received

IB->OMS: new inventory file
OMS->IB: received
```

Data flow example of Order in Store (OiS):
```sequence
Storefront->K3 DSW: create web order

K3 DSW->Storefront: request received (sync)

K3 DSW->K3 Imagine POS: web order

K3 Imagine POS->K3 DSW: payment details

K3 DSW->Storefront: payment details (async callback)

Storefront->OMS: release order

```

</br>

## Inventory Balancer (IB) - Endpoints

:::info
**Stock Movement Notification** - [POST]
:::

*Test uri: https://samsoe-envii-oms-dev-inventory-sync.azurewebsites.net/api/notification/stockmovement*

K3 will create a subscription within their DataSwitch and from that subscription push events of Stock Movements to Samsøe's Inventory Balancer API. Alpha will provide K3 with access to this endpoint.

IMPORTANT: K3 must provide a product's available stock. Example: Shop A has a Product B with current stock of 5 pcs available. A customer buys 2 pcs. of product B. This will trigger an event from K3 sending IB the total remaining quantity of (5 - 2) = 3 pcs available.

> Request (from DSW to IB)

```json=
{
    "notificationId": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "skuNo": "MXD122243434104",
    "shopId": 92010,
    "stockInShop": 9 
}
```

OBS: stockInShop - should be the number available to sell. In-transit or reserved items should already be deducted from this number.

> Response JSON (from IB to DSW) - Success (Status code 2xx)

```json=
{
    "message": "received"
}
```

> Response JSON (from IB to DSW) - Error (Status code 4xx or 5xx)

```json=
{
    "message": "<error message>"
}
```

</br>

:::info
**Sale Callback Notification** - [POST]
:::

*Test uri: https://samsoe-envii-oms-dev-inventory-sync.azurewebsites.net/api/notification/sale*

In case of asynchronous responses sent from K3 to Inventory Balancer, this endpoint will be made available. This is especially important if we send requests to K3 | DataSwitch that for some reason fails within K3 system. Then Alpha MUST be notified so we can flag this fault in our system.


> Callback Notification Request (from DSW to IB) with Successful Result

```json=
{
    "notificationId": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "receiptId": "123456xyz",
    "success": true 
}
```

> Callback Notification (from DSW to IB) with Faulted Result

```json=
{
    "notificationId": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "receiptId": "123456xyz",
    "success": false,
    "errorMessage": "Error message here.."    
}
```

> Sync response JSON (from IB to DSW) - Success (Status code 2xx)

```json=
{
    "message": "received"
}
```

> Sync response JSON (from IB to DSW) - Error (Status code 4xx or 5xx)

```json=
{
    "message": "<error message>"
}
```

:::info
**Return Callback Notification** - [POST]
:::

*Test uri: https://samsoe-envii-oms-dev-inventory-sync.azurewebsites.net/api/notification/return*

In case of asynchronous responses sent from K3 to Inventory Balancer, this endpoint will be made available. This is especially important if we send requests to K3 | DataSwitch that for some reason fails within K3 system. Then Alpha MUST be notified so we can flag this fault in our system.


> Callback Notification Request (from DSW to IB) with Successful Result

```json=
{
    "notificationId": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "receiptId": "123456xyz",
    "success": true 
}
```

> Callback Notification (from DSW to IB) with Faulted Result

```json=
{
    "notificationId": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "receiptId": "123456xyz",
    "success": false,
    "errorMessage": "Error message here.."    
}
```

> Sync response JSON (from IB to DSW) - Success (Status code 2xx)

```json=
{
    "message": "received"
}
```

> Sync response JSON (from IB to DSW) - Error (Status code 4xx or 5xx)

```json=
{
    "message": "<error message>"
}
```

:::info
**Stock Adjustment Callback Notification** - [POST]
:::

*Test uri: https://samsoe-envii-oms-dev-inventory-sync.azurewebsites.net/api/notification/stockadjustment*

In case of asynchronous responses sent from K3 to Inventory Balancer, this endpoint will be made available. This is especially important if we send requests to K3 | DataSwitch that for some reason fails within K3 system. Then Alpha MUST be notified so we can flag this fault in our system.


> Callback Notification Request (from DSW to IB) with Successful Result

```json=
{
    "notificationId": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "receiptId": "123456xyz",
    "success": true 
}
```

> Callback Notification (from DSW to IB) with Faulted Result

```json=
{
    "notificationId": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "receiptId": "123456xyz",
    "success": false,
    "errorMessage": "Error message here.."    
}
```

> Sync response JSON (from IB to DSW) - Success (Status code 2xx)

```json=
{
    "message": "received"
}
```

> Sync response JSON (from IB to DSW) - Error (Status code 4xx or 5xx)

```json=
{
    "message": "<error message>"
}
```

</br>

## Salesforce - Endpoints

:::info
**Web Order Payment Details** - [POST]
:::

*Test uri: https://dev05-store-samsoesamsoe.demandware.net/on/demandware.store/Sites-samsoe-Site/en/Imagine-NotifyOrderInStore*

Whenever a Web Order is payed in-store DSW will push an event containing payment details in the payload to Salesforce.

> Request (from DSW to Salesforce)

```json=
{
    "orderNumber": "DEV0500006728",
    "additionalData": {
        "recurring.recurringDetailReference": "7219687191761347",
        "recurring.shopperReference": "YOUR_UNIQUE_SHOPPER_ID_IOfW3k9G2PvXFu2j"
    },
    "pspReference": "8814689190961342",
    "resultCode": "Authorised"
}
```

> Sync response (from Salesforce to DSW) - Success (Status code 200)

```json=
{
    "message": "recieved"
}
```

> Sync response (from Salesforce to DSW) - Error

```json=
{
    "message": "<error message>"
}
```

</br>

## K3 | DataSwitch - Endpoints

:::info
**Sale** - [POST]
:::

Alpha need to agree with K3 on the right way to perform sales and returns as described in the [Discussion](##Discussion) section.

From K3 Swagger API https://publicapi.k3imagine.com/swagger/index.html i see 2 options:

1. [POST] https://publicapi.k3imagine.com/api/v1.0/WebOrders
2. [POST] https://publicapi.k3imagine.com/api/v1.0/Sales/park

<br/>

:::info
**Return** - [POST]
:::

Alpha need to agree with K3 on the right way to perform sales and returns as described in the [Discussion](##Discussion) section.

From K3 Swagger API https://publicapi.k3imagine.com/swagger/index.html i see 2 options:

1. [POST] https://publicapi.k3imagine.com/api/v1.0/WebOrders
2. [POST] https://publicapi.k3imagine.com/api/v1.0/Sales/park

<br/>

:::info
**Stock Adjustment** - [POST]
:::

IMPORTANT: Must be able to handle both positive and negative (increase / decrease) adjustments.


> Request JSON (from IB to DSW)

```json=
{
    "requestReference": "eb86e57f-d2c2-411c-b980-e17d99b91305"
    "storeCode": 92099,
    "adjustmentNumber": "ADJ_001",
    "createdBy": "SAMSOE-OMNI",
    "dateCreated": "2018-07-26T09:49:03.393Z",
    "locationName": "SAMSOE SAMSOE Pilestræde",
    "adjustmentLines": [
        {
            "lineNumber": 1,
            "itemNo": "sku no.",
            "quantity": -2,
        },
        {
            "lineNumber": 2,
            "itemNo": "sku no.",
            "quantity": 2,
        }
    ]
}
```

> Sync response JSON (from DSW to IB) - Success (Status code 2xx)

```json=
{
    "requestReference": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "receiptId": "<unique update id here...>"
}
```

> Sync response JSON (from DSW to IB) - Error (Status code 4xx or 5xx)

```json=
{
    "requestReference": "eb86e57f-d2c2-411c-b980-e17d99b91305",
    "message": "<error message>"
}
```

</br>

:::info
**Web Order** - [POST] 
:::

> Request JSON (from Salesforce to DSW)

```json=
{
    "callbackUrl": "www.test.com",
    "webOrder": {
        "orderNo": "WEBORDER001",
        "orderReference": "123456",
        "orderedOn": "2019-02-11T10:37:34.737Z",
        "shopId": 1,
        "firstName": "Joe",
        "lastName": "Smith",
        "email": "joe@smiths.com",
        "phoneNo": "",
        "orderType": "OrderInStore",
        "webOrderLines": [
            {
                "sku": 5000,
                "salesPrice": 1500.0,
                "effectiveSalesPrice": 1250.0,
                "discountAmount": 250.0,
                "notes": "string"
            }
        ],
    }
}
```

> Sync response (from DSW to Salesforce) - Success (Status code 201)

```json=
{
    "message": "created"
}
```

> Sync response (from DSW to Salesforce) - Error (Status code 4xx or 5xx)

```json=
{
    "message": "<error message>"
}
```

</br>

## K3 | API - Endpoints

This section contains a list of endpoints that Alpha will possibly be using when integrating to Imagine POS. Documentation is found here: https://publicapi.k3imagine.com/swagger/index.html.

    Shops
    [GET] /api/v{version}/Shop/shops
    [GET] /api/v{version}/Shop/{id}
    
    Transfers
    [GET] /api/v{version}/Transfers/forShop/{shopId}
    
    StockLookup
    [GET] /api/v{version}/StockLookup/barcode/{barcode}
    [GET] /api/v{version}/StockLookup/paged/{after}/{recordCount}

</br>

## K3 | DataSwitch - Test POS

Alpha would like to access a test POS. This requires access to an actual Imagine POS. We would need a storeId, posId, and proper authentication like a token.

</br>

## Discussion

* *Sale & Return:*
What type of endpoint should we utilize? From K3 swagger API. You have something called a parked sale. Could this be used? And is this the equivalent to the old DdD sale? A quick back story on the current sales integration: Sales are created today primarily for accounting/financial purposes but also for regulating stock. Samsoe and Tommy must be able to pull a financial report on all online (Ship from Store) sales through Imagine POS. As a reference with the current solutions we use the following DdD endpoint: https://publicapi.dddretail.com/Swagger/ui/index#!/Sale/Sale_PostSale.

* *Stock Adjustments:*
Creating Stock Adjustments in the current DdD system requires 2 API requests. One for *intiation* and another for *approval*. Would this be the same with K3 Imagine POS? If possible a single endpoint that did both operations could be conveniant, but not mandatory. 

* *Get All Stock from All Shops:*
Looking at your documentation, i don't see an endpoint allowing us to retrieve all stock for all shops? This is something we use today because of 1) We must be able to initially populate our database with full inventory and 2) if the inventory is in an "out-of-sync" state we need the ability to clean the database and fill it up with new and fresh inventory.

* *Synchronous vs. asynchronous responses:*
During integration with K3 | DataSwitch if any responses are asynchronous Alpha will build a callback endpoint which K3 can then use to send back any relevant information like error events. Especially when something goes wrong AFTER data has left Inventory Balancer, Alpha MUST be notified.

* *Asynchronous callbacks should contain references to the original requests  :*
In relation to the previous note, if the DataSwitch uses callback notifications to send back asynchronous messages, we (alpha and K3) need to agree on a unique identifier making it possible for alpha to match any callback with the original request. I.e. when we sent a Stock Adjustment request to you and later you send back a callback notification, the callback should contain a reference (ID) making it possible for alpha to lookup th original request.

* *Sku codes:*
On previous workshops K3 mentioned that it was not a problem to use Samsøe's own SKU codes to do things like Sales, StockAdjustments, Create Web Orders etc. This is still the case i hope? So, for ALL the requests we make to your DataSwitch we can use SKU codes? This is the order on which we prefer to use item codes: 1) SKU, 2) Barcode, 3) your internal id (VariantId)

* *OiS and Adyen:*
Can your system handle delayed payments? (link: https://docs.adyen.com/point-of-sale/delayed-capture). A delayed payment is when the terminal only makes an authorization on the customers credit/debit card. The actual Capture can be done later on. By default when a payment is Approved it is processed in two steps: 1) Authorize 2) Capture.
If your system could handle delayed payments, then OMS could  finish the payment transaction like any other online order, and suddenly OiS would follow the original order flow like any other online order. This would be of great benefit to Samsøe.
*Answer: K3 will handle all authorizations and captures. There will be no part authorized and part captured payments at this point* 

</br>

## Appendix and FAQ

* https://publicapi.k3imagine.com/swagger/index.html
* https://postman.k3imagine.com/?version=latest
* https://publicapi.dddretail.com/Swagger/ui/index

###### tags: `Documentation`
