# 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 %}
```