# AMPER API

**AMPER API** to otwarty interfejs **RestAPI** służący do wymiany danych z innymi systemami, takimi jak systemy ERP, porównywarki, sklepy internetowe.

# External services integration

This page contains infromations and instructions on how to get data from AMPER for use in external services (like e-commerce site).

# Example external e-commerce shop integration

[Example project - generating CENEO.PL XML file](https://bitbucket.org/amplifierspzoo/amper-ceneo-generator/)

***Prerequisites***

1. AMPER API KEY 
2. AMPER web serivce URL

To get those, please, contact with IT support of company you want to integrate with.

## Example request

***C#***

``` csharp 
var client = new RestClient("https://{amper_ws_url}/external/v1/products/?api_key={amper_api_key}");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
```

***NodeJS***

```ts
var request = require('request');
var options = {
  'method': 'GET',
  'url': 'http://{amper_ws_url}/external/v1/products/?api_key={amper_api_key}',
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

```

***PHP CURL***

```php
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'http://{amper_ws_url}/external/v1/products/?api_key={amper_api_key}',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'GET',
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

```

***Python***

```python
import requests

url = "http://{amper_ws_url}/external/v1/products/?api_key={amper_api_key}"

payload={}
headers = {}

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)
```

> replace `"amper_ws_url"` and `"amper_api_key"` with your data

### Response

As a response you will get JSON. Example response with list of products

```json
[
    {
        "id": 1037,
        "name": "BAHAMA zapach samochodowy NASZYJNIK Wild Hibiskus /1szt",
        "short_code": "850267",
        "description": "Zapachy inspirowane wakacjami oraz trendami konsumenckimi. Bahama & Co. to nie tylko akcesoria do samochodu, ale również atrakcyjne gadżety, stanowiące element dekoracyjny.",
        "ean": "978020137962",
        "sku": "850267",
        "vat": 23,
        "default_unit_of_measure": "szt.",
        "weight": "0.20",
        "default_price": "25.43"
    },
    {
        "id": 1034,
        "name": "VORTEX TKANINA wielofunkcyjna z mikrofibry /1szt",
        "short_code": "623765",
        "description": "Uniwersalne zastosowanie",
        "ean": "978020137962",
        "sku": "623765",
        "vat": 23,
        "default_unit_of_measure": "op.",
        "weight": "0.38",
        "default_price": "31.52"
    },
    {
        "id": 951,
        "name": "CALIFORNIA zapach samochodowy SCENT CONTROL Ice /1szt",
        "short_code": "851233",
        "description": "Papierowe zawieszki zapachowe: \nInnowacyjna technologia dostosowania intensywności zapachu – wystarczy odpowiednio ustawić zawieszkę. \nPapier pokryty zapachowymi olejkami.\nW zestawie sznurek umożliwiający wygodne zawieszanie zapachu. \nDostępne zapachy: Coronado cherry; Ice; New Car; Sea Breeze",
        "ean": "978020137962",
        "sku": "851233",
        "vat": 23,
        "default_unit_of_measure": "szt.",
        "weight": "0.33",
        "default_price": "18.38"
    },
 ]
```

## Available methods

Here is a list of available methods. 
**HTTP** method that is allowed: **GET**

<br/>

### Products

With this method you can get list of products.

**Methods**

URL | HTTP allowed method | Description |
---- | ---- | ----------- |
| **/external/v1/products/** | *GET* | get list of products |
| **/external/v1/products/{id}/** | *GET* | get product by ID |

<br/>

### Categories

With this method you can get list of categories.

**Methods**

URL | HTTP allowed method | Description |
---- | ---- | ----------- |
| **/external/v1/categories/** | *GET* | get list of categories |
| **/external/v1/categories/{id}/** | *GET* | get category by ID |

<br/>

### Relation between Product and Categories

This method returns all bindings of product to categories

**Methods**

URL | HTTP allowed method | Description |
---- | ---- | ----------- |
| **/external/v1/product-categories/** | *GET* | list of relations beteen product and category |

<br/>

### Product files

This method returns all files attached to product

URL | HTTP allowed method | Description |
---- | ---- | ----------- |
| **/external/v1/product-files/** | *GET* |  list of files |

<br/>

### Stocks

This method returns prodct's stocks

URL | HTTP allowed method | Description |
---- | ---- | ----------- |
| **/external/v1/stocks/** | *GET* |  list of stocks |

### Promotions

This method returns list of promotions

URL | HTTP allowed method | Description |
---- | ---- | ----------- |
| **/external/v1/promotions/** | *GET* |  list of promotions |

# Translator

# Introduction

**AmplifierApiClient** .NET package provides ways to authenticate and communicate with Amplifier API. This includes access to B2B WS.

[Nuget](https://www.nuget.org/packages/AmperApiClient.NET/)

You can add this package to your .NET project by using:

- **Package Manager Console in Visual Studio**
    
    `Install-Package AmperApiClient.NET`
- **.NET CLI**
    
    `dotnet add package AmperApiClient.NET`
- **add reference directly to your .csproj file**
    
    ```xml
        <ItemGroup>
              <PackageReference Include="AmperApiClient.NET" Version="1.x.x" />
          </ItemGroup> 
    
    ```

[Example project](https://bitbucket.org/amplifierspzoo/amper-translator-example)

Import

```
  using Amplifier;

```

# AmplifierJWTAuth

### Constructors

<table id="bkmrk-name-description-con"><thead><tr><th>Name</th><th>Description</th></tr></thead><tbody><tr><td>**Constructor(username, password, authUrl)**</td><td>Creates an **AmplifierJWTAuth** with specified credentials</td></tr></tbody></table>

### Methods

<table id="bkmrk-return-type-name-des"><thead><tr><th>Return Type</th><th>Name</th><th>Description</th></tr></thead><tbody><tr><td>*Task&lt;string&gt;*</td><td>**[GetToken](#gettoken)**</td><td>Fetches your JSON Web Token required for communication with backend of Amplifier</td></tr></tbody></table>

### Constructor(username, password, authUrl)

```cs
  using Amplifier;

```

```csharp
  string AUTH_URL = "your_ws_endpoint";
  string USERNAME = "your_user_name";
  string PASSWORD = "your_password";

  AmplifierJWTAuth amplifierJWTAuth = new AmplifierJWTAuth(USERNAME, PASSWORD, AUTH_URL);

```

> replace `"your_ws_endpoint"`, `"your_user_name"` and `"your_password"` with your credentials

<table id="bkmrk-name-type-descriptio"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**your\_ws\_endpoint**</td><td>*String*</td><td>Your dedicated AMPER WS endpoint</td></tr><tr><td>**username**</td><td>*String*</td><td></td></tr><tr><td>**password**</td><td>*String*</td><td></td></tr></tbody></table>

### GetToken()

```cs
  using Amplifier;

```

```csharp
  AmplifierJWTAuth amplifierJWTAuth = new AmplifierJWTAuth(USERNAME, PASSWORD, AUTH_URL);

  string token = await amplifierJWTAuth.getToken();

```

**Returns**

Personal JSON Web Token

# B2BWSConfig

### Properties

<table id="bkmrk-name-type-descriptio-1"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**B2BWSUrl**</td><td>*string*</td><td>target AMPER Web Service URL</td></tr><tr><td>**ERPConnectionString**</td><td>*string*</td><td></td></tr><tr><td>**JWTToken**</td><td>*string*</td><td>JSON Web Token fetched by AmplifierJWTAuth</td></tr></tbody></table>

# B2BWSBackend

### Constructors

<table id="bkmrk-name-description-con-1"><thead><tr><th>Name</th><th>Description</th></tr></thead><tbody><tr><td>**Constructor(b2BWSConfig)**</td><td>Creates an B2BWSBackend using config containing JWT and WS URL</td></tr></tbody></table>

### Methods

<table id="bkmrk-return-type-name-des-1"><thead><tr><th>Return Type</th><th>Name</th><th>Description</th></tr></thead><tbody><tr><td>*Task&lt;string&gt;*</td><td>**[ChangeOrderStatus(status, token)](#changeorderstatus-status-token)**</td><td>Asynchronously changes the status of an order</td></tr><tr><td>*Task&lt;string&gt;*</td><td>**[GetListOfComplaints](#getlistofcomplaints)**</td><td>Asynchronously fetches the list of complaints</td></tr><tr><td>*Task&lt;string&gt;*</td><td>**[GetListOfOrders(status)](#getlistoforders-status)**</td><td>Asynchronously fetches list of orders with a specified status</td></tr><tr><td>*Task&lt;string&gt;*</td><td>**[GetOrder(token)](#getorder-token)**</td><td>Asynchronously fetches an order by it's token</td></tr><tr><td>*Task*</td><td>**[SendAccountsAsync(accounts)](#sendaccountsasync-accounts)**</td><td>Asynchronously sends the list of accounts</td></tr><tr><td>*Task*</td><td>**[SendAddresses(addresses)](#sendaddresses-addresses)**</td><td>Asynchronously Sends the list of addresses</td></tr><tr><td>*Task*</td><td>**[SendCategoryDiscountAsync(category\_discounts)](#sendcategorydiscountasync-category_discounts)**</td><td>Asynchronously sends the list of category discounts</td></tr><tr><td>*Task*</td><td>**[SendCustomerProductLogisticMinimumAsync(relations)](#sendcustomerproductlogisticminimumasync-relations)**</td><td>Asynchronously sends the list of logistic minimums for customers and products</td></tr><tr><td>*Task*</td><td>**[SendCustomerProductsRelationAsyncsAsync(relations)](#sendcustomerproductsrelationasyncsasync-relations)**</td><td>Asynchronously sends the list of customer product relations</td></tr><tr><td>Task\*</td><td>**[SendDocumentsAsync(documents)](#senddocumentsasync-documents)**</td><td>Asynchronously sends the list of documents</td></tr><tr><td>*Task*</td><td>**[SendFile(path, fileName, product\_external\_id, order)](#sendfile-path-filename-product_external_id-order)**</td><td>Asynchronously sends a file</td></tr><tr><td>*Task*</td><td>**[SendPriceLevelsAsync(priceLevels)](#sendpricelevelsasync-pricelevels)**</td><td>Asynchronously sends the list of price levels</td></tr><tr><td>*Task*</td><td>**[SendPricesAsync(priceLevels)](#sendpricesasync-pricelevels)**</td><td>Asynchronously sends the list of prices</td></tr><tr><td>*Task*</td><td>**[SendProductCategoriesAsync(categories)](#sendproductcategoriesasync-categories)**</td><td>Asynchronously sends the list of product categories</td></tr><tr><td>*Task*</td><td>**[SendProductCategoriesRelationAsyncsAsync(relations)](#sendproductcategoriesrelationasyncsasync-relations)**</td><td>Asynchronously sends the list of product category relations</td></tr><tr><td>*Task*</td><td>**[SendProductsAsync(products)](#sendproductsasync-products)**</td><td>Asynchronously sends the list of products</td></tr><tr><td>*Task*</td><td>**[SendRelatedProductsAsync(related\_products)](#sendrelatedproductsasync-related_products)**</td><td>Asynchronously sends the list of related products</td></tr><tr><td>*Task*</td><td>**[SendSettlementsAsync(settlements)](#sendsettlementsasync-settlements)**</td><td>Asynchronously sends the list of settlements</td></tr><tr><td>*Task*</td><td>**[SendStockLocationsAsync(stockLocations)](#sendstocklocationsasync-stocklocations)**</td><td>Asynchronously sends the list of location of the product stock</td></tr><tr><td>*Task*</td><td>**[SendStocksAsync(stocks)](#sendstocksasync-stocks)**</td><td>Asynchronously sends the list of product stock</td></tr></tbody></table>

### Constructor(b2BWSConfig)

**Parameters**

<table id="bkmrk-name-type-descriptio-2"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**b2BWSConfig**</td><td>*[B2BWSConfig](#b2bwsconfig)*</td><td></td></tr></tbody></table>

### ChangeOrderStatus(status, token)

<table id="bkmrk-name-type-descriptio-3"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**status**</td><td>*String*</td><td>New status</td></tr><tr><td>**token**</td><td>*String*</td><td>Order's token</td></tr></tbody></table>

**Returns**

Task object containing result of the operation

### GetListOfComplaints()

**Returns**

Task object containing list of complaints in JSON format as a string

### GetListOfOrders(status)

**Parameters**

<table id="bkmrk-name-type-descriptio-4"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**status**</td><td>*String*</td><td>Status of orders</td></tr></tbody></table>

**Returns**

Task object containing list of orders in JSON format as a string

### GetOrder(token)

**Parameters**

<table id="bkmrk-name-type-descriptio-5"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**token**</td><td>*String*</td><td>Order's token</td></tr></tbody></table>

**Returns**

Task object containing order in JSON format as a string

### SendAccountsAsync(accounts)

**Parameters**

<table id="bkmrk-name-type-descriptio-6"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**accounts**</td><td>*List&lt;[Account](#account)&gt;*</td><td>List of accounts</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendAddresses(addresses)

**Parameters**

<table id="bkmrk-name-type-descriptio-7"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**addresses**</td><td>*List&lt;[Address](#address)&gt;*</td><td>List of addresses</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendCategoryDiscountAsync(category\_discounts)

**Parameters**

<table id="bkmrk-name-type-descriptio-8"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**category\_discounts**</td><td>*List&lt;[CategoryDiscount](#categorydiscount)&gt;*</td><td>List of category discounts</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendCustomerProductLogisticMinimumAsync(relations)

**Parameters**

<table id="bkmrk-name-type-descriptio-9"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**relations**</td><td>*List&lt;[CustomerProductLogisticMinimum](#customerproductlogisticminimum)&gt;*</td><td>List of logistic minimums for customers and products</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendCustomerProductsRelationAsyncsAsync(relations)

**Parameters**

<table id="bkmrk-name-type-descriptio-10"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**relations**</td><td>*List&lt;[CustomerProductRelation](#customerproductrelation)&gt;*</td><td>List of customer product relations</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendDocumentsAsync(documents)

**Parameters**

<table id="bkmrk-name-type-descriptio-11"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**documents**</td><td>*List&lt;[Document](#document)&gt;*</td><td>List of documents</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendFile(path, fileName, product\_external\_id, order)

**Parameters**

<table id="bkmrk-name-type-descriptio-12"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**path**</td><td>*String*</td><td>Path to a file</td></tr><tr><td>**fileName**</td><td>*String*</td><td>Name of a file after it's sent</td></tr><tr><td>**product\_external\_id**</td><td>*String*</td><td>Product's Id in client's database</td></tr><tr><td>**order**</td><td>*String*</td><td></td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendPriceLevelsAsync(priceLevels)

**Parameters**

<table id="bkmrk-name-type-descriptio-13"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**priceLevels**</td><td>*List&lt;[PriceLevel](#pricelevel)&gt;*</td><td>List of price levels</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendPricesAsync(priceLevels)

**Parameters**

<table id="bkmrk-name-type-descriptio-14"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**priceLevels**</td><td>*List&lt;[Price](#price)&gt;*</td><td>List of prices</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendProductCategoriesAsync(categories)

**Parameters**

<table id="bkmrk-name-type-descriptio-15"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**categories**</td><td>*List&lt;[ProductCategory](#productcategory)&gt;*</td><td>List of product categories</td></tr></tbody></table>

**Returns**Task object representing the result of the operation

### SendProductCategoriesRelationAsyncsAsync(relations)

**Parameters**

<table id="bkmrk-name-type-descriptio-16"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**relations**</td><td>*List&lt;[ProductCategoryRelation](#productcategoryrelation)&gt;*</td><td>List of product category relations</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendProductsAsync(products)

**Parameters**

<table id="bkmrk-name-type-descriptio-17"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**products**</td><td>*List&lt;[Product](#product)&gt;*</td><td>List of products</td></tr></tbody></table>

**Returns**

Task object representing the result of asynchrous operation

### SendRelatedProductsAsync(related\_products)

**Parameters**

<table id="bkmrk-name-type-descriptio-18"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**related\_products**</td><td>*List&lt;[RelatedProducts](#relatedproducts)&gt;*</td><td>List of related products</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendSettlementsAsync(settlements)

**Parameters**

<table id="bkmrk-name-type-descriptio-19"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**settlements**</td><td>*List&lt;[Settlement](#settlement)&gt;*</td><td>List of settlements</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendStockLocationsAsync(stockLocations)

**Parameters**

<table id="bkmrk-name-type-descriptio-20"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**stockLocations**</td><td>*List&lt;[StockLocation](#stocklocation)&gt;*</td><td>List of location of the product stock</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

### SendStocksAsync(stocks)

**Parameters**

<table id="bkmrk-name-type-descriptio-21"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**stocks**</td><td>*List&lt;[Stock](#stock)&gt;*</td><td>List of product stock</td></tr></tbody></table>

**Returns**

Task object representing the result of the operation

# Models

## Account

### Properties

<table id="bkmrk-name-type-descriptio-22"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**customers**</td><td>*List&lt;[Customer](#customer)&gt;*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Account's Id in client's database</td></tr><tr><td>**name**</td><td>*string*</td><td></td></tr><tr><td>**short\_name**</td><td>*string*</td><td></td></tr></tbody></table>

## Address

### Properties

<table id="bkmrk-name-type-descriptio-23"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**city**</td><td>*string*</td><td></td></tr><tr><td>**customer\_external\_id**</td><td>*string*</td><td>Customer's Id in client's database</td></tr><tr><td>**email**</td><td>*string*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Addres's Id in client's database</td></tr><tr><td>**name**</td><td>*string*</td><td></td></tr><tr><td>**phone**</td><td>*string*</td><td></td></tr><tr><td>**postal\_code**</td><td>*string*</td><td></td></tr><tr><td>**street**</td><td>*string*</td><td></td></tr><tr><td>**street\_continuation**</td><td>*string*</td><td></td></tr><tr><td>**voivodeship**</td><td>*string*</td><td></td></tr></tbody></table>

## CategoryDiscount

### Properties

<table id="bkmrk-name-type-descriptio-24"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**category\_external\_id**</td><td>*string*</td><td>Category's Id in client's database</td></tr><tr><td>**discount**</td><td>*decimal*</td><td></td></tr><tr><td>**end\_date**</td><td>*string*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Category discount's Id in client's database</td></tr><tr><td>**order**</td><td>*int*</td><td></td></tr><tr><td>**price\_level\_external\_id**</td><td>*string*</td><td>Price level's Id in client's database</td></tr><tr><td>**start\_date**</td><td>*string*</td><td></td></tr></tbody></table>

## Complaint

### Properties

<table id="bkmrk-name-type-descriptio-25"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**attachments**</td><td>*List&lt;object&gt;*</td><td></td></tr><tr><td>**created\_at**</td><td>*DateTime*</td><td></td></tr><tr><td>**created\_by**</td><td>*DateTime*</td><td></td></tr><tr><td>**customer\_external\_id**</td><td>*string*</td><td>Customer's Id in client's database</td></tr><tr><td>**id**</td><td>*int*</td><td></td></tr><tr><td>**lines**</td><td>*List&lt;[ComplaintLine](#complaintline)&gt;*</td><td></td></tr><tr><td>**note**</td><td>*string*</td><td></td></tr><tr><td>**notes**</td><td>*List&lt;object&gt;*</td><td></td></tr><tr><td>**nr**</td><td>*string*</td><td></td></tr><tr><td>**status**</td><td>*string*</td><td></td></tr><tr><td>**updated\_at**</td><td>*int?*</td><td></td></tr><tr><td>**updated\_by**</td><td>*int?*</td><td></td></tr></tbody></table>

## ComplaintLine

### Properties

<table id="bkmrk-name-type-descriptio-26"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**complaint**</td><td>*id*</td><td></td></tr><tr><td>**description**</td><td>*string*</td><td></td></tr><tr><td>**id**</td><td>*id*</td><td></td></tr><tr><td>**name**</td><td>*string*</td><td></td></tr><tr><td>**order**</td><td>*string*</td><td></td></tr><tr><td>**product\_external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr><tr><td>**product\_id**</td><td>*int*</td><td></td></tr><tr><td>**purchase\_date**</td><td>*string*</td><td></td></tr></tbody></table>

## Customer

### Properties

<table id="bkmrk-name-type-descriptio-27"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**city**</td><td>*string*</td><td></td></tr><tr><td>**comments**</td><td>*string*</td><td></td></tr><tr><td>**discount**</td><td>*decimal*</td><td></td></tr><tr><td>**doc\_export**</td><td>*bool*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Customer's Id in client's database</td></tr><tr><td>**ftp\_export**</td><td>*bool*</td><td></td></tr><tr><td>**login**</td><td>*string*</td><td></td></tr><tr><td>**mail\_export**</td><td>*bool*</td><td></td></tr><tr><td>**name**</td><td>*string*</td><td></td></tr><tr><td>**offer\_export**</td><td>*bool*</td><td></td></tr><tr><td>**overdue\_limit**</td><td>*decimal*</td><td></td></tr><tr><td>**password**</td><td>*string*</td><td></td></tr><tr><td>**phone**</td><td>*string*</td><td></td></tr><tr><td>**postal\_code**</td><td>*string*</td><td></td></tr><tr><td>**price\_level\_external\_id**</td><td>*string*</td><td>Price level's Id in client's database</td></tr><tr><td>**primary\_email**</td><td>*string*</td><td></td></tr><tr><td>**short\_name**</td><td>*string*</td><td></td></tr><tr><td>**street**</td><td>*string*</td><td></td></tr><tr><td>**tax\_id**</td><td>*string*</td><td></td></tr><tr><td>**template**</td><td>*string*</td><td></td></tr><tr><td>**trade\_credit\_limit**</td><td>*decimal*</td><td></td></tr></tbody></table>

## CustomerProductLogisticMinimum

### Properties

<table id="bkmrk-name-type-descriptio-28"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**customer\_external\_id**</td><td>*string*</td><td>Customer's Id in client's database</td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Id of logistic minimum for customer and product in client's database</td></tr><tr><td>**logistic\_minimum**</td><td>*decimal*</td><td></td></tr><tr><td>**product\_external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr></tbody></table>

## CustomerProductRelation

### Properties

<table id="bkmrk-name-type-descriptio-29"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**customer\_external\_id**</td><td>*string*</td><td>Customer's Id in client's database</td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Customer product relation's Id in client's database</td></tr><tr><td>**product\_external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr></tbody></table>

## Document

### Properties

<table id="bkmrk-name-type-descriptio-30"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**customer**</td><td>*string*</td><td></td></tr><tr><td>**date**</td><td>*string*</td><td></td></tr><tr><td>**description**</td><td>*string*</td><td></td></tr><tr><td>**document\_lines**</td><td>*List&lt;[DocumentLine](#documentline)&gt;*</td><td></td></tr><tr><td>**due\_date**</td><td>*string*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Document's Id in client's database</td></tr><tr><td>**number**</td><td>*string*</td><td></td></tr><tr><td>**value\_gross**</td><td>*decimal*</td><td></td></tr><tr><td>**value\_net**</td><td>*decimal*</td><td></td></tr></tbody></table>

## DocumentLine

### Properties

<table id="bkmrk-name-type-descriptio-31"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**document**</td><td>*string*</td><td></td></tr><tr><td>**group**</td><td>*string*</td><td></td></tr><tr><td>**make**</td><td>*string*</td><td></td></tr><tr><td>**manufacturer**</td><td>*string*</td><td></td></tr><tr><td>**price\_gross**</td><td>*decimal*</td><td></td></tr><tr><td>**price\_net**</td><td>*decimal*</td><td></td></tr><tr><td>**product**</td><td>*decimal*</td><td></td></tr><tr><td>**product\_ean**</td><td>*decimal*</td><td></td></tr><tr><td>**product\_name**</td><td>*string*</td><td></td></tr><tr><td>**product\_symbol**</td><td>*string*</td><td></td></tr><tr><td>**quantity**</td><td>*decimal*</td><td></td></tr><tr><td>**quantity\_aggregate**</td><td>*decimal*</td><td></td></tr><tr><td>**unit**</td><td>*string*</td><td></td></tr><tr><td>**unit\_aggregate**</td><td>*string*</td><td></td></tr><tr><td>**value\_gross**</td><td>*decimal*</td><td></td></tr><tr><td>**value\_net**</td><td>*decimal*</td><td></td></tr><tr><td>**vat**</td><td>*int*</td><td></td></tr></tbody></table>

## Order

### Properties

<table id="bkmrk-name-type-descriptio-32"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**billing\_address**</td><td>*string*</td><td></td></tr><tr><td>**created**</td><td>*DateTime*</td><td></td></tr><tr><td>**customer\_external\_id**</td><td>*string*</td><td>Customer's Id in client's database</td></tr><tr><td>**customer\_note**</td><td>*string*</td><td></td></tr><tr><td>**discount\_amount**</td><td>*object*</td><td></td></tr><tr><td>**lines**</td><td>*List&lt;[OrderLine](#orderline)&gt;*</td><td></td></tr><tr><td>**paid**</td><td>*object*</td><td></td></tr><tr><td>**products\_total\_gross**</td><td>*string*</td><td></td></tr><tr><td>**products\_total\_net**</td><td>*string*</td><td></td></tr><tr><td>**shipment**</td><td>*int*</td><td></td></tr><tr><td>**shipment\_type**</td><td>*int*</td><td></td></tr><tr><td>**shipping\_address**</td><td>*int*</td><td></td></tr><tr><td>**shipping\_price\_gross**</td><td>*string*</td><td></td></tr><tr><td>**shipping\_price\_net**</td><td>*string*</td><td></td></tr><tr><td>**status**</td><td>*string*</td><td></td></tr><tr><td>**token**</td><td>*string*</td><td></td></tr><tr><td>**total\_gross**</td><td>*decimal*</td><td></td></tr><tr><td>**total\_net**</td><td>*decimal*</td><td></td></tr><tr><td>**updated**</td><td>*DateTime*</td><td></td></tr><tr><td>**user\_email**</td><td>*string*</td><td></td></tr></tbody></table>

## OrderLine

### Properties

<table id="bkmrk-name-type-descriptio-33"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**attributes**</td><td>*List&lt;object&gt;*</td><td></td></tr><tr><td>**id**</td><td>*int*</td><td></td></tr><tr><td>**product**</td><td>*int*</td><td></td></tr><tr><td>**product\_external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr><tr><td>**product\_name**</td><td>*string*</td><td></td></tr><tr><td>**product\_sku**</td><td>*string*</td><td></td></tr><tr><td>**quantity**</td><td>*int*</td><td></td></tr><tr><td>**tax\_rate**</td><td>*string*</td><td></td></tr><tr><td>**unit\_price\_gross**</td><td>*string*</td><td></td></tr><tr><td>**unit\_price\_net**</td><td>*string*</td><td></td></tr></tbody></table>

## Price

### Properties

<table id="bkmrk-name-type-descriptio-34"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**discount**</td><td>*decimal*</td><td></td></tr><tr><td>**end\_date**</td><td>*string*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Price's Id in client's database</td></tr><tr><td>**order**</td><td>*int*</td><td></td></tr><tr><td>**price**</td><td>*decimal*</td><td></td></tr><tr><td>**price\_level\_external\_id**</td><td>*string*</td><td>Price level's Id in client's database</td></tr><tr><td>**product\_external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr><tr><td>**start\_date**</td><td>*string*</td><td></td></tr></tbody></table>

## PriceLevel

### Properties

<table id="bkmrk-name-type-descriptio-35"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**external\_id**</td><td>*string*</td><td>Price level's Id in client's database</td></tr><tr><td>**name**</td><td>*string*</td><td></td></tr><tr><td>**order**</td><td>*int*</td><td></td></tr></tbody></table>

## Product

### Properties

<table id="bkmrk-name-type-descriptio-36"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**attributes**</td><td>*List&lt;[ProductAttributes](#productattributes)&gt;*</td><td></td></tr><tr><td>**available\_on**</td><td>*string*</td><td></td></tr><tr><td>**can\_be\_split**</td><td>*bool*</td><td></td></tr><tr><td>**cumulative\_converter**</td><td>*decimal*</td><td></td></tr><tr><td>**cumulative\_unit\_of\_measure**</td><td>*string*</td><td></td></tr><tr><td>**cumulative\_unit\_ratio\_splitter**</td><td>*decimal*</td><td></td></tr><tr><td>**default\_price**</td><td>*decimal*</td><td></td></tr><tr><td>**default\_unit\_of\_measure**</td><td>*string*</td><td></td></tr><tr><td>**description**</td><td>*string*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr><tr><td>**friendly\_name**</td><td>*string*</td><td></td></tr><tr><td>**is\_featured**</td><td>*bool*</td><td></td></tr><tr><td>**is\_published**</td><td>*bool*</td><td></td></tr><tr><td>**name**</td><td>*string*</td><td></td></tr><tr><td>**short\_code**</td><td>*string*</td><td></td></tr><tr><td>**short\_description**</td><td>*string*</td><td></td></tr><tr><td>**sku**</td><td>*string*</td><td></td></tr><tr><td>**unit\_roundup**</td><td>*bool*</td><td></td></tr><tr><td>**vat**</td><td>*int*</td><td></td></tr><tr><td>**weight**</td><td>*decimal*</td><td></td></tr></tbody></table>

## ProductAttributes

### Properties

<table id="bkmrk-name-type-descriptio-37"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**atr\_name**</td><td>*string*</td><td></td></tr><tr><td>**atr\_val**</td><td>*string*</td><td></td></tr><tr><td>**key**</td><td>*string*</td><td></td></tr></tbody></table>

### Constructors

<table id="bkmrk-name-description-con-2"><thead><tr><th>Name</th><th>Description</th></tr></thead><tbody><tr><td>**Constructor(String, String, String)**</td><td></td></tr></tbody></table>

### Constructor(String, String, String)

## ProductCategory

### Properties

<table id="bkmrk-name-type-descriptio-38"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**description**</td><td>*string*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Product category's Id in client's database</td></tr><tr><td>**name**</td><td>*string*</td><td></td></tr><tr><td>**order**</td><td>*int*</td><td></td></tr><tr><td>**parent\_external\_id**</td><td>*string*</td><td>Category's parent category Id in client's database</td></tr><tr><td>**seo\_tags**</td><td>*string*</td><td></td></tr></tbody></table>

## ProductCategoryRelation

### Properties

<table id="bkmrk-name-type-descriptio-39"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**category\_external\_id**</td><td>*string*</td><td>Category's Id in client's database</td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Product and category relation's Id in client's database</td></tr><tr><td>**product\_external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr></tbody></table>

## ProductImage

<table id="bkmrk-name-type-descriptio-40"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**alt**</td><td>*string*</td><td></td></tr><tr><td>**product\_id**</td><td>*int*</td><td></td></tr><tr><td>**image**</td><td>*string*</td><td></td></tr><tr><td>**order**</td><td>*int*</td><td></td></tr><tr><td>**thumbnail\_width**</td><td>*int*</td><td></td></tr></tbody></table>

## RelatedProduct

### Properties

<table id="bkmrk-name-type-descriptio-41"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**external\_id**</td><td>*string*</td><td>Related product's Id in client's database</td></tr></tbody></table>

## RelatedProducts

### Properties

<table id="bkmrk-name-type-descriptio-42"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr><tr><td>**related\_products**</td><td>*List&lt;[RelatedProduct](#relatedproducts)&gt;*</td><td>List of related products</td></tr></tbody></table>

## Settlement

### Properties

<table id="bkmrk-name-type-descriptio-43"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**customer**</td><td>*string*</td><td></td></tr><tr><td>**date**</td><td>*string*</td><td></td></tr><tr><td>**due\_date**</td><td>*string*</td><td></td></tr><tr><td>**external\_id**</td><td>*string*</td><td>Settlement's Id in client's database</td></tr><tr><td>**number**</td><td>*string*</td><td></td></tr><tr><td>**value**</td><td>*decimal*</td><td></td></tr><tr><td>**value\_to\_pay**</td><td>*decimal*</td><td></td></tr></tbody></table>

## Stock

### Properties

<table id="bkmrk-name-type-descriptio-44"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**external\_id**</td><td>*string*</td><td></td></tr><tr><td>**product\_external\_id**</td><td>*string*</td><td>Product's Id in client's database</td></tr><tr><td>**quantity**</td><td>*decimal*</td><td></td></tr><tr><td>**quantity\_allocated**</td><td>*decimal*</td><td></td></tr><tr><td>**stock\_level\_external\_id**</td><td>*string*</td><td>Stock location's Id in client's database</td></tr></tbody></table>

## StockLocation

### Properties

<table id="bkmrk-name-type-descriptio-45"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>**external\_id**</td><td>*string*</td><td></td></tr><tr><td>**name**</td><td>*string*</td><td></td></tr></tbody></table>

# AMPER Channels

# How to use amper-channels microservice (websockets)

Short instruction how to implement communication with microservice.

## Frontend

Each of the front service (admin, b2b, msf, etc.) should firstly request a websocket authorization token through.

GET https://channels.ampli-solutions.com/authorize

```cs
Authorization Header: Bearer TOKEN

```

replace TOKEN with WS token

Code implementation - package [socket.io](www.socket.io)

```cs
<script src="/socket.io/socket.io.js"></script>

```

For all the other methods of including socket.io package to your project, please refer to documentation: [client-api](https://socket.io/docs/v4/client-api/)

After receiving a token, use it to get your websocket connection

```cs
const url = 'https://channels.ampli-solutions.com/'
const token = token received from "authorize" API
const keycloakID = 'your keycloak'
const channel = 'msf' (channel used by your project) (b2b, admin, msf, etc)
const socket = io(url, {
	auth: {
		token:token,
		keycloakID:keycloakID,
		channel:channel
	}
})

```

Add a **notification** type event listener to your socket:

```cs
socket.on('notification', function(msg) {
	//here goes your action code that runs after notification is received
	(msg) - notification message object (string lub json)
})

```

## Backend

You have 3 variants of notifications:

1. notifying every user of given channel (msg, b2b, admin, etc.),
2. notifiyng every channel that a given keycloak user is using,
3. notifying a single channel of given keycloak user

API Endpoint: POST https://channels.ampli-solutions.com/notify

BODY:

```cs
{
	"API_KEY": "5b28dc2f-...-7fbb705907c5", //current api key//Required
	"msg" : string/json, //Required
	"keycloak": "26259ede-....-9c58927efaae",//keycloak of the target user for notification(variant 2 and 3)
	"channel": "msf"//(b2b, admin, etc)//when you want to use variant 1 or 2 notification
}

```

Summary: Variant 1 requires only the **channel** variable in the body, Variant 2: only **keycloak**Variant 3: both **channel** and **keycloak**

# Wymiana ofert i dokumentów w systemie AMPER

Dokument opisuje dostępne możliwości konfigurowania ofert i formatów dokumentów na potrzeby wymiany danych z systemami obcymi.

## Użytkownik

Użytkownik ma możliwość eksportowania swoich dokumentów do dowolnego z dostępnych formatów.  
Dostępne są 3 formy eksportu:

- w przeglądarce
- na serwer FTP
- na maila
- cyklicznie raz na dobę (dotyczy wysłki mailem i FTP)

### Eksport w przeglądarce

W zakładce "moje dokumenty" użytkownik ma opcję pobrania dokumentu w wybranym formacie.

Opis techniczny:  
Aby pobrać wybrany dokument w wybranym formacie należy użyć następującej metody z serwera ampli-ws:

```
GET /documents/:id_dokumentu/export/:id_szablonu
```

  
Jeżeli dokument oraz szablon istnieją, plik w wybranym formacie zostanie pobrany.

### Eksport na serwer FTP

Użytkownik w zakładce Moje Konto -&gt; Ustawienia ustawia dane dostępowe do serwera FTP takie jak:  
adres serwera, port, nazwa użytkownika, hasło, katalog do którego mają być wrzucane pliki oraz czy transmisja ma być szyfrowana.  
Dodatkowo konieczne jest wybranie do jakiego formatu mają być eksportowane dokumenty.  
Od tego momentu co określony okres czasu wszystkie dokumenty niewyeksportowane poprawnie będą  
wrzucane na serwer FTP klienta.

Domyślnie dla każdego użytkownika jest zakładane konto FTP na serwerze: [**ftp://ftp.amplifier.pl**](ftp://ftp.amplifier.pl/). Należy pamiętać, że dokumenty na tym serwerze FTP są automatycznie kasowane po 90 dniach. Dane dostępowe do konta FTP są zapisywane wraz z utworzeniem konta.

Opis techniczny:  
Eksportem i wysyłaniem plików zajmuje się serwer ampli-ws.  
Serwer udostępnia zestaw standardowych operacji pod adresem: <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">/ftp-config</span>

Aby eksport był możliwy <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">Customer</span> musi mieć przypisany obiekt <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">FTPConfig</span>.

```
{
  "id": 1,
  "address": "localhost",
  "port": 2121,
  "username": "samplelogin",
  "password": "samplepass",
  "directory": "export",
  "is_secure": false,
  "customer": 3,
  "template": 2  // id szablonu do eksportu
}
```

  
Pole <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">directory</span> nie jest wymagane, pliki będą wtedy eksportowane do katalogu głównego.  
W przypadku gdy transmisja ma być szyfrowana z wykorzystaniem TLS należy ustawić <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">is\_secure</span> na <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">true</span>.  
UWAGA! Jeżeli <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">is\_secure</span> będzie ustawione niepoprawnie połączenie nie powiedzie się.

W pliku <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">documents/tasks.py</span> zdefiniowana jest funkcja <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">export\_all\_to\_ftp()</span>.  
Odpowiada ona za operację eksportu, a przebiega ona w sposób następujący:  
Dla każdego użytkownika posiadającego konfigurację FTP wykonywany jest eksport dokumentów.  
Eksportowane są tylko te dokumenty, dla których nie istnieje wpis w historii FTP, bądź wpis zawiera informację o błędzie.

### Eksport na maila

Użytkownik w zakładce Moje Konto -&gt; Ustawienia ustawia adres email na który mają  
być wysyłane dokumenty oraz format do którego mają być eksportowane.  
Od tego momentu co określony okres czasu wszystkie dokumenty niewyeksportowane poprawnie będą wysyłane na ten adres.

Opis techniczny:  
Eksportem i wysyłaniem plików zajmuje się serwer ampli-ws.  
Serwer udostępnia zestaw standardowych operacji pod adresem: <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">/mail-config</span>

Aby eksport był możliwy <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">Customer</span> musi mieć przypisany obiekt <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">MailConfig</span>.

```
{
  "id": 1,
  "address": "customer@example.com",
  "customer": 3,
  "template": 2  // id szablonu do eksportu
}
```

W pliku <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">documents/tasks.py</span> zdefiniowana jest funkcja <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">export\_all\_to\_mail()</span>.  
Odpowiada ona za operację eksportu, a przebiega ona w sposób następujący:  
Dla każdego użytkownika posiadającego konfigurację email wykonywany jest eksport dokumentów.  
Eksportowane są tylko te dokumenty, dla których nie istnieje wpis w historii Mail, bądź wpis zawiera informację o błędzie.  
Każdy plik wysyłany jest w oddzielnej wiadomości jako załącznik.

### Historia eksportów

Każde zdarzenie eksportu jest zapisywane w bazie danych.  
Zapisywane jest id dokumentu, data i godzina, cel eksportu (przeglądarka, FTP, mail) oraz informacja o błędzie.  
W przypadku eksportów automatycznych (FTP, mail) dokumenty, dla których poprzedni eksport się nie powiódł  
zostaną wyeksportowane ponownie.

## Administrator

Administrator systemu (nie sklepu) ma możliwość podglądu, definiowania, edycji oraz usuwania szablonów.

Opis techniczny:  
Serwer ampli-ws udostępnia zestaw standardowych operacji pod adresem: <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">/document-templates</span>

Aby jakikolwiek dokument mógł zostać wyeksportowany wymagane jest dodanie przynajmniej jednego szablonu.  
Przykładowy obiekt <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">DocumentTemplate</span> wygląda następująco:

```
{
  "id": 2,
  "name": "Testowy Format",
  "extension": ".txt",  // konieczne jest umieszczenie kropki razem z roszerzeniem
  "content": "Numer dokumentu: {{ document.number }}, data: {{ document.date }}" 
} 
```

  
Pole <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">content</span> zawiera w sobie standardowy szablon Django.  
Mogą być używane wszystkie standardowe dla tego typu szablonów elementy.  
Jako kontekst przekazywany jest obiekt typu <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">Document</span> pod nazwą <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">document</span>.

### Dostępne pola dla nagłówka dokumentu

Dostęp: **document.nazwa\_pola**

**number** - Numer dokumentu  
**date** - Data dokumentu  
**due\_date** - Termin dokumentu  
**description** - Opis  
**value\_net** - Wartość netto  
**value\_gross** - Wartość brutto

Tagi własne

- **get\_vat\_value\_net**
- **get\_vat\_value\_gross**
- **get\_vat\_value\_vat**

Sposób użycia:

```
{% get_vat_value_net document 23 %}
```

  
zwraca wartość netto dla stawki VAT 23%

### Dostępne pola dla pozycji dokumentu

Dostęp: **line.nazwa\_pola**

**product\_name** - Nazwa  
**product\_symbol** - Symbol  
**product\_vat** - Stawka VAT produktu  
**product\_ean** - Kod EAN produktu  
**unit** - Jednostka miary  
**quantity** - Ilość  
**unit\_aggregate** - Jednostka miary zbiorcza"  
**quantity\_aggregate** - Ilość zbiorcza  
**price\_net** - Cena netto  
**price\_gross** - Cena brutto  
**value\_net** - Wartość netto  
**value\_gross** - Wartość brutto  
**manufacturer** - Producent  
**make** - Marka  
**group** - Grupa  
**value\_vat** - Wartość VAT pozycji

### Dostępne pola dla kontrahenta

Dostęp: **customer.nazwa\_pola**

**name** - Nazwa kontrahenta  
**short\_name** - Kod/nazwa skrócona  
**tax\_id** - Numer NIP

### Dostępne pola dla produktu

Dostęp: **line.product.nazwa\_pola**

**name** - Nazwa produktu  
**friendly\_name** - Nazwa skrócona/nazwa zrozumiała dla użytkownika  
**short\_description** - Krótki opis produktu  
**description** - Opis  
**short\_code** - Kod produktu  
**sku** - SKU  
**vat** - VAT  
**available\_on** - Dostępny od  
**is\_published** - Czy opulikowany  
**is\_featured** - Czy promowany  
**default\_unit\_of\_measure** - Domyślna jednostka miary  
**cumulative\_unit\_of\_measure** - Zbiorcza jednostka miary  
**cumulative\_converter** - Przelicznika na jednostkę zbiorczą  
**can\_be\_split** - Czy jednostka miary zbiorcza podzielna  
**cumulative\_unit\_ratio\_splitter** - Współczynnik podzielności (uzupełniany tylko kiedy can\_be\_split==True)  
**unit\_roundup** - Zaokrąglenie jednostki miary  
**weight** - Waga  
**default\_price** - Cena 100  
**default\_image.image.url** - url do domyślnego obrazka produktu  
**product\_b2b\_url** - url do produktu w systemie AMPER B2B  
**available\_on\_stock** - czy produkt dostępny na stanie, zwraca True/False  
**stocks\_available** - podaje rzyczywisty stan produktu na magazynie  
**stocks\_available\_in\_words** - podaje stan magazynu w formie słownej <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">none/low/medium/high</span>  
**stock\_availability\_customer** - podaje stan produktu na magazynie do którego jest przypisany kontrahent z uwzględnieniem flagi <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">Zwracaj rzeczywistą wartość stanów w API i ofertach</span>  
**cn\_code** - kod CN  
**category\_path** - ścieżka kategorii głównej do jakiej jest przypisany produkt  
**main\_category** - nazwa kategorii głównej

Tagi własne

- **attribute\_value**
- **unit\_of\_measure\_converter**

Sposób użycia:

```
{% attribute_value product [id atrybutu] %}
{% unit_of_measure_converter product [nazwa jednostki miary] %}
```

W szablonie należy zadeklarować tagi produktu: <span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false">{% load product\_extras %}</span>

Kolumny dostępne tylko do typu szablonu **Oferty**

**offer\_best\_promotion.price** - najlepsza cena promocyjna  
**offer\_best\_promotion.promotion\_name** - nazwa promocji z jakiej pochodzi cena promocyjna  
**offer\_best\_promotion.promotion\_id** - id promocji  
**offer\_best\_promotion.promotion\_url** - link URL do promocji w B2B  
**offer\_best\_promotion.promotion\_min\_order\_quantity** - minimalna ilość zamówienia w promocji  
**offer\_promotion\_prices\_list** - lista cen promocyjnych z programi zwracana w formie<span class="code" data-prosemirror-content-type="mark" data-prosemirror-mark-name="code" spellcheck="false"> 2880.00;1.39;1440.00;1.43;720.00;1.50;</span> . Czyli produkt występuje w trzech progach promocyjnych: 1.39 PLN za zakup 2880, 1.43 PLN za zakup 1440, 1.50 PLN za zakup 720  
**top\_offer\_starting\_from\_a\_single\_piece** - najlepsza cena promocyjna dla minimum jednej sztuki

## Operacje na liczbach

W definicji szablonu na samym początku należy dodać deklarcję:  
`{% load mathfilters %}`

W szablonie można wtedy używać następujących operacji matematycznych:

- **sub** – odejmowanie
- **mul** – mnożenie
- **div** – dzielenie
- **intdiv** – dzielenie całkowite (podłoga)
- **abs** – wartość bezwzględna
- **mod** – modulo
- **addition** – zamiennik filtra add ze wsparciem dla typów float/decimal

Przykład:

```html
{% load mathfilters %}
{% with answer=42 %}
42 * 0.5 = {{ answer|mul:0.5 }}
{% endwith %}
{% with numerator=12 denominator=3 %}
12 / 3 = {{ numerator|div:denominator }}
{% endwith %}
```

## Dokumentacja składni używanej przy tworzeniu szablonów

<span class="inlineCardView-content-wrap inlineNodeView" data-prosemirror-content-type="node" data-prosemirror-node-inline="true" data-prosemirror-node-name="inlineCard"><span class="card">[https://docs.djangoproject.com/en/3.2/topics/templates/](https://docs.djangoproject.com/en/3.2/topics/templates/)</span></span>

## Przykład

```
{% for line in document.document_lines.all %}{{line.product_name}};{{line.product_symbol}};{{line.quantity}};{{line.price_net}};{{line.value_net}}
{% endfor %}
```

# Promocje - integracja z systemami zewnętrznymi

#### **📘 Dokumentacja techniczna struktura i logika promocji**

##### **🧩 1. Struktura pojedynczej promocji**

Każdy element tablicy to *jedna promocja* w systemie AMPER B2B.

```
{
  "id": 22960679,
  "name": "promocja na palete",
  "description": "",
  "start": "2025-10-23T00:00:00+02:00",
  "end": "2028-10-20T23:59:00+02:00",
  "short_code": "promocja-na-palete",
  "default_image": { "image": "...", "alt": "..." },
  "keep_bundle_multiplayer_same": false,
  "use_promotion_price_for_threshold": false,
  "calculate_using_cumulative_units": true,
  "multiply_reward": 0,
  "color_in_cart": null,
  "start_using_default_price": false,
  "is_active": true,
  "conditions": [ ... ]
}
```

##### **🔍 Kluczowe pola**

<table id="bkmrk-pole-typ-opis-id-int"><thead><tr><th>**Pole**

</th><th>**Typ**

</th><th>**Opis**

</th></tr></thead><tbody><tr><td>id

</td><td>int

</td><td>ID promocji

</td></tr><tr><td>name

</td><td>string

</td><td>Nazwa promocji

</td></tr><tr><td>description

</td><td>string

</td><td>Opis (opcjonalny)

</td></tr><tr><td>start<span class="s1">, </span>end

</td><td>datetime

</td><td>Zakres obowiązywania promocji

</td></tr><tr><td>short\_code

</td><td>string

</td><td>Jednoznaczny kod identyfikacyjny

</td></tr><tr><td>default\_image

</td><td>object

</td><td>Domyślna grafika promocji

</td></tr><tr><td>keep\_bundle\_multiplayer\_same

</td><td>bool

</td><td>Czy utrzymać wielokrotność w zestawach

</td></tr><tr><td>use\_promotion\_price\_for\_threshold

</td><td>bool

</td><td>Czy threshold/próg liczony wg ceny promocyjnej

</td></tr><tr><td>calculate\_using\_cumulative\_units

</td><td>bool

</td><td>Czy przeliczać jednostki po konwerterach/jednostkach zbiorczych

</td></tr><tr><td>multiply\_reward

</td><td>int

</td><td>Czy nagroda mnożona przez ilość pakietów

</td></tr><tr><td>color\_in\_cart

</td><td>string/null

</td><td>Kolor w koszyku

</td></tr><tr><td>start\_using\_default\_price

</td><td>bool

</td><td>Czy liczyć od ceny domyślnej

</td></tr><tr><td>is\_active

</td><td>bool

</td><td>Czy aktywna

</td></tr><tr><td>conditions

</td><td>array

</td><td>Lista warunków aktywujących promocję

</td></tr></tbody></table>

#### **🧠 2. Warunki promocji (conditions)**

Każda promocja może zawierać <span class="s2">**jeden lub wiele warunków**</span>.

Struktura warunku:

```
{
  "threshold_min": 1.0,
  "threshold_max": 0.0,
  "measure": "quantity",
  "rewards": [ ... ]
}
```

##### **▶ Pola warunku**

<table id="bkmrk-pole-typ-opis-thresh"><thead><tr><th>**Pole**

</th><th>**Typ**

</th><th>**Opis**

</th></tr></thead><tbody><tr><td>threshold\_min

</td><td>float

</td><td>Minimalny próg osiągnięcia promocji

</td></tr><tr><td>threshold\_max

</td><td>float

</td><td>Maksymalny próg (0 = brak limitu)

</td></tr><tr><td>measure

</td><td>string

</td><td>Typ pomiaru: <span class="s1">"quantity"</span> lub <span class="s1">"value"</span>

</td></tr><tr><td>rewards

</td><td>array/null

</td><td>Lista nagród (ceny, gratisy, rabaty)

</td></tr></tbody></table>

#### **🎁 3. Nagrody (rewards)**

Każda nagroda jest powiązana do konkretnego produktu.

```
{
  "given_price": 8.0,
  "reward_value": 0.0,
  "value_type": "3",
  "quantity": 0.0,
  "product": {
    "id": 817,
    "ean": "817",
    "name": "BATERIA ENERGIZER...",
    "short_code": "426684-CC",
    "default_unit_of_measure": "bl.",
    "cumulative_unit_of_measure": "karton",
    "cumulative_converter": "24.00",
    "can_be_split": true,
    "cumulative_unit_ratio_splitter": "24.00",
    "unit_roundup": false
  }
}
```

##### **▶ Pola nagrody**

<table id="bkmrk-pole-typ-opis-given_"><thead><tr><th>**Pole**

</th><th>**Typ**

</th><th>**Opis**

</th></tr></thead><tbody><tr><td>given\_price

</td><td>float

</td><td>Cena promocyjna produktu

</td></tr><tr><td>reward\_value

</td><td>float

</td><td>Wartość rabatu (jeśli dotyczy)

</td></tr><tr><td>value\_type

</td><td>string

</td><td>Typ rabatu (np. stała cena, gratis, procent)

</td></tr><tr><td>quantity

</td><td>float

</td><td>Ilość nagrody (np. liczba gratisów)

</td></tr><tr><td>product

</td><td>object

</td><td>Opis produktu objętego promocją

</td></tr></tbody></table>

#### **📦 4. Struktura produktu w nagrodzie (product)**

<table id="bkmrk-pole-typ-opis-id-int-1"><thead><tr><th>**Pole**

</th><th>**Typ**

</th><th>**Opis**

</th></tr></thead><tbody><tr><td>id

</td><td>int

</td><td>ID produktu

</td></tr><tr><td>ean

</td><td>string

</td><td>Kod EAN

</td></tr><tr><td>name

</td><td>string

</td><td>Pełna nazwa

</td></tr><tr><td>short\_code

</td><td>string

</td><td>Kod skrócony

</td></tr><tr><td>default\_unit\_of\_measure

</td><td>string

</td><td>Jednostka bazowa

</td></tr><tr><td>cumulative\_unit\_of\_measure

</td><td>string

</td><td>Jednostka zbiorcza

</td></tr><tr><td>cumulative\_converter

</td><td>string

</td><td>Przelicznik jednostek

</td></tr><tr><td>can\_be\_split

</td><td>bool

</td><td>Czy można dzielić jednostki

</td></tr><tr><td>cumulative\_unit\_ratio\_splitter

</td><td>string

</td><td>Współczynnik dzielenia

</td></tr><tr><td>unit\_roundup

</td><td>bool

</td><td>Czy zaokrąglać w górę

</td></tr></tbody></table>

#### **🧮 5. Logika liczenia promocji**

##### **5.1. Typ progu – measure**

Dwa tryby:

##### **1) quantity**

Liczymy ilość sztuk / opakowań / jednostek.

##### **2) value**

Liczymy wartość koszyka dla produktów spełniających warunki.

##### **5.2. Przeliczanie jednostek (calculate\_using\_cumulative\_units)**

Jeśli <span class="s2">**true**</span> – ilość do thresholdu liczona jest tak:

```
ilość_w_sztukach * cumulative_converter
```

Przykład:

- <span class="s1">produkt: 6-pack → </span>cumulative\_converter = 6
- klient kupuje 2 opakowania
- do thresholdu liczymy: <span class="s1">**12 szt.**</span>

---

##### **5.3. Multiplikacja nagród (multiply\_reward)**

<span class="s2">Jeśli </span>multiply\_reward &gt; 0<span class="s2">:</span>

- osiągnięcie kolejnych progów zwiększa liczbę nagród

Przykład:

threshold = 10 szt

multiply\_reward = 1

klient kupił 30 szt → <span class="s3">**3x nagroda**</span>

#### **🎯 6. Typowe przypadki** 

##### **📌 Stała cena za produkt**

Promocje typu:

> <span class="s2">reward → </span>value\_type = 3<span class="s2">, </span>given\_price &gt; 0

Przykład: “Stała cena 5 zł przy zakupie min 10 szt”

##### **📌 Gratis**

<span class="s2">Promocja ma </span>quantity &gt; 0<span class="s2"> oraz </span>given\_price = 0<span class="s2">.</span>

##### **📌 Progi wielokrotności**

Promocje:

- Próg wielokrotności - produkt kwota
- Próg wielokrotności - kategoria kwota

Mechanika:

- measure = value
- wiele warunków z tym samym threshold
- wiele nagród równoległych

---

#### **🧱 7. Przykład – schematy strukturalne**

##### **Promocja (Promo)**

```
Promo
 ├── conditions [Condition]
 │     ├── threshold_min
 │     ├── threshold_max
 │     ├── measure (quantity/value)
 │     └── rewards [Reward]
 │            ├── given_price
 │            ├── reward_value
 │            ├── value_type
 │            ├── quantity
 │            └── product (Product)
 └── metadata...
```

---

##### **▶ 8. Użycie** 

### **Algorytm wyliczania promocji:**

1. Pobierz wszystkie aktywne promocje dla klienta
2. Dla każdej promocji:
    
    
    - sprawdź daty start/end
    - oblicz threshold dla danego measure
    - uwzględnij cumulative conversions
3. Jeśli warunki spełnione:
    
    
    - zastosuj nagrody:
        
        
        - nadpisz cenę (<span class="s1">given\_price</span>)
        - dodaj gratisy
        - nadaj rabat procentowy/kwotowy
4. Zapisz informację o zastosowanej promocji w koszyku.

---

#### **📄 9. Użycie po stronie frontend (koszyk)**

Front powinien:

- wyróżnić produkty w promocji (<span class="s1">color\_in\_cart</span>)
- pokazać cenę promocyjną <span class="s1">given\_price</span>
- pokazać opis promocji
- dodać gratisy jako osobne linie (jeśli quantity &gt; 0)
- opcjonalnie pokazać osiągnięty próg

---

#### **📗 10. Podsumowanie**

AMPER to elastyczny model promocji zawierający:

✔ wiele progów

✔ wiele typów nagród

✔ wielokrotność progów

✔ konwersje jednostek

✔ stałe ceny

✔ gratisy

✔ rabaty

✔ pakiety

# Tworzenie zamówienia "create-order"

## Przegląd

Endpoint `POST /create-order` tworzy zamówienie na podstawie podanych danych klienta i linii produktów. Przed wywołaniem należy uzyskać token JWT przez endpoint autoryzacyjny.

---

## 1. Autoryzacja - uzyskanie tokena

### 1.1 Pobranie tokena (logowanie)

```
POST /auth/
Content-Type: application/json

```

**Body żądania:**

```json
{
  "username": "login_uzytkownika",
  "password": "haslo"
}

```

**Przykład (curl):**

```bash
curl -X POST https://<host>/auth/ \
  -H "Content-Type: application/json" \
  -d '{"username": "jan.kowalski", "password": "tajnehaslo"}'

```

**Odpowiedź (200 OK):**

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cC...",
  "expires_in": 300,
  "refresh_expires_in": 1800,
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5c...",
  "token_type": "Bearer",
  "not-before-policy": 0,
  "session_state": "abc123...",
  "scope": "amper"
}

```

<table id="bkmrk-pole-opis-access_tok"><thead><tr><th>Pole</th><th>Opis</th></tr></thead><tbody><tr><td>`access_token`</td><td>Token JWT do autoryzacji żądań API</td></tr><tr><td>`expires_in`</td><td>Czas ważności tokena w sekundach (domyślnie 300 s = 5 min)</td></tr><tr><td>`refresh_token`</td><td>Token do odświeżenia sesji bez ponownego logowania</td></tr><tr><td>`refresh_expires_in`</td><td>Czas ważności refresh tokena w sekundach</td></tr></tbody></table>

---

### 1.2 Odświeżenie tokena

Gdy `access_token` wygaśnie, użyj `refresh_token` zamiast ponownie logować użytkownika.

```
POST /auth/token-refresh/
Content-Type: application/json

```

**Body żądania:**

```json
{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5c..."
}

```

**Przykład (curl):**

```bash
curl -X POST https://<host>/auth/token-refresh/ \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5c..."}'

```

**Odpowiedź:** Taki sam format jak przy logowaniu — nowy `access_token` i `refresh_token`.

---

## 2. Tworzenie zamówienia

### Endpoint

```
POST /create-order
Authorization: Bearer <access_token>
Content-Type: application/json

```

### Wymagane uprawnienia

Token musi należeć do użytkownika z zakresem `B2B` lub `TRANSLATOR`.

---

### 2.1 Parametry żądania

**Body żądania (JSON):**

<table id="bkmrk-pole-typ-wymagane-op"><thead><tr><th>Pole</th><th>Typ</th><th>Wymagane</th><th>Opis</th></tr></thead><tbody><tr><td>`customer_id`</td><td>`integer`</td><td>Tak\*</td><td>ID klienta w systemie</td></tr><tr><td>`customer_external_id`</td><td>`string`</td><td>Tak\*</td><td>Zewnętrzny ID klienta (alternatywa dla `customer_id`)</td></tr><tr><td>`lines`</td><td>`array`</td><td>Tak</td><td>Lista linii zamówienia (patrz niżej)</td></tr><tr><td>`playground`</td><td>`boolean`</td><td>Nie</td><td>`true` — symulacja bez zapisu zamówienia (domyślnie `false`)</td></tr><tr><td>`description`</td><td>`string`</td><td>Nie</td><td>Opis/notatka do zamówienia</td></tr><tr><td>`shipment_type_id`</td><td>`integer`</td><td>Nie</td><td>ID typu wysyłki</td></tr></tbody></table>

> \* Wymagane jest podanie `customer_id` **lub** `customer_external_id`.

**Pola obiektu w tablicy `lines`:**

<table id="bkmrk-pole-typ-wymagane-op-1"><thead><tr><th>Pole</th><th>Typ</th><th>Wymagane</th><th>Opis</th></tr></thead><tbody><tr><td>`product_id`</td><td>`integer`</td><td>Tak\*</td><td>ID produktu w systemie</td></tr><tr><td>`product_external_id`</td><td>`string`</td><td>Tak\*</td><td>Zewnętrzny ID produktu (alternatywa dla `product_id`)</td></tr><tr><td>`quantity`</td><td>`decimal`</td><td>Tak</td><td>Ilość (zaokrąglana do kroku jednostki produktu)</td></tr><tr><td>`suggested_price`</td><td>`decimal`</td><td>Tak</td><td>Sugerowana cena jednostkowa</td></tr><tr><td>`promotion_id`</td><td>`integer`</td><td>Nie</td><td>ID konkretnej promocji do zastosowania</td></tr><tr><td>`order_line_promotion_id`</td><td>`integer`</td><td>Nie</td><td>ID promocji linii zamówienia</td></tr></tbody></table>

> \* Wymagane jest podanie `product_id` **lub** `product_external_id`.

---

### 2.2 Przykłady żądań

**Przykład z wewnętrznymi ID:**

```bash
curl -X POST https://<host>/create-order \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cC..." \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": 42,
    "lines": [
      {
        "product_id": 101,
        "quantity": 10,
        "suggested_price": 99.99
      },
      {
        "product_id": 205,
        "quantity": 5,
        "suggested_price": 49.50,
        "promotion_id": 7
      }
    ],
    "description": "Zamówienie testowe"
  }'

```

**Przykład z zewnętrznymi ID (integracja ERP):**

```bash
curl -X POST https://<host>/create-order \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cC..." \
  -H "Content-Type: application/json" \
  -d '{
    "customer_external_id": "ERP-KLIENT-0042",
    "lines": [
      {
        "product_external_id": "SKU-ABC-001",
        "quantity": 10,
        "suggested_price": 99.99
      }
    ]
  }'

```

**Przykład trybu playground (symulacja bez zapisu):**

```bash
curl -X POST https://<host>/create-order \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cC..." \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": 42,
    "playground": true,
    "lines": [
      {
        "product_id": 101,
        "quantity": 10,
        "suggested_price": 99.99
      }
    ]
  }'

```

---

### 2.3 Odpowiedź

**Sukces — 201 Created:**

```json
{
  "order_id": 12345,
  "lines": [
    {
      "product_id": 101,
      "product_external_id": "SKU-ABC-001",
      "quantity": 10,
      "suggested_price": 99.99,
      "default_price": 100.00,
      "customer_price": 95.00,
      "given_price": 90.00,
      "promotion": {
        "price": 90.00,
        "promotion_min_order_quantity": 5,
        "promotion_condition_item_id": 123,
        "promotion_condition_id": 456,
        "relation_id": 789,
        "promotion_name": "Letnia wyprzedaż",
        "promotion_id": 999,
        "promotion_url": "https://<host>/promotions/999/"
      }
    }
  ]
}

```

<table id="bkmrk-pole-opis-order_id-i"><thead><tr><th>Pole</th><th>Opis</th></tr></thead><tbody><tr><td>`order_id`</td><td>ID utworzonego zamówienia; `0` gdy `playground=true` lub brak linii</td></tr><tr><td>`lines`</td><td>Linie zamówienia z przeliczonymi cenami i promocjami</td></tr><tr><td>`lines[].default_price`</td><td>Cena katalogowa</td></tr><tr><td>`lines[].customer_price`</td><td>Cena indywidualna klienta</td></tr><tr><td>`lines[].given_price`</td><td>Cena końcowa (po uwzględnieniu promocji; `0` gdy brak promocji)</td></tr><tr><td>`lines[].promotion`</td><td>Najlepsza dostępna promocja lub `null` gdy nie dotyczy</td></tr></tbody></table>

> **Uwaga:** W odpowiedzi zwracane są tylko linie produktów, które są dostępne dla danego klienta i mają prawidłowe dane cenowe. Linie z niedostępnymi produktami są pomijane.

---

## 3. Kody błędów

<table id="bkmrk-kod-opis-201-created"><thead><tr><th>Kod</th><th>Opis</th></tr></thead><tbody><tr><td>`201 Created`</td><td>Zamówienie zostało pomyślnie utworzone</td></tr><tr><td>`401 Unauthorized`</td><td>Brak lub nieprawidłowy token `Authorization`</td></tr><tr><td>`403 Forbidden`</td><td>Token ważny, ale brak wymaganego zakresu (`B2B` lub `TRANSLATOR`)</td></tr><tr><td>`404 Not Found`</td><td>Nieprawidłowe dane logowania przy pobieraniu tokena</td></tr></tbody></table>

---

## 4. Pełny przepływ integracji

```
1. POST /auth/               → otrzymujesz access_token + refresh_token
         │
         ▼
2. POST /create-order        → zamówienie zostaje utworzone
   Authorization: Bearer <access_token>
         │
         ▼
3. Gdy access_token wygaśnie (expires_in sekund):
   POST /auth/token-refresh/ → otrzymujesz nowy access_token
   { "refresh_token": "..." }

```

**Rekomendowane podejście w kliencie:**

- Przechowuj `access_token` i `refresh_token` w pamięci sesji.
- Przed każdym żądaniem sprawdzaj, czy token nie wygasł (`expires_in`).
- W przypadku odpowiedzi `401` automatycznie wywołaj endpoint odświeżenia tokena.
- Gdy `refresh_token` również wygaśnie, ponownie pobierz token przez `/auth/`.

---

## 5. Uwagi implementacyjne

- **Tryb playground** (`"playground": true`) pozwala przetestować logikę cenową i promocyjną bez tworzenia zamówienia w bazie danych. Zwrócone `order_id` będzie równe `0`.
- **Zewnętrzne ID** (`customer_external_id`, `product_external_id`) są tłumaczone na wewnętrzne ID systemu przez moduł translatora. Używaj ich przy integracji z zewnętrznymi systemami (ERP, WMS).
- **Ilość** (`quantity`) jest automatycznie zaokrąglana do kroku jednostki produktu (np. jeśli krok to 5, zamówienie 7 szt. zostanie zaokrąglone do 10).
- **Promocje** są wybierane automatycznie (najlepsza dostępna dla klienta), chyba że podasz `promotion_id` w linii zamówienia.