# Tashqi tizimdan onlayn buyurtma

> To'liq ssenariy: mijozni topish, kerakli do'konda sotuvni shakllantirish, chegirmani qo'llash va to'lovni o'tkazish — faqat integratsiya kaliti uchun mavjud bo'lgan metodlar orqali.

Vazifa: onlayn do’kon yoki marketpleys buyurtmani o’zida rasmiylashtiradi va uni BILLZ’da aniq bir do’konning sotuvi sifatida — xaridor, chegirma va to’lov bilan o’tkazishi lozim.

## Atamalardagi farqlar

BILLZ’da «buyurtma» so’zi band.

| Vazifa ta’rifi                                      | Bu BILLZ’da qanday ataladi                         | Metodlar                                              |
| --------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------- |
| Xaridor saytda mahsulotga buyurtma berdi            | **Sotuv** (`Order`, sotuv cheki)                   | `/v2/order`, `/v2/order-product`, `/v2/order-payment` |
| Mahsulot **yetkazib beruvchidan** buyurtma qilingan | **Yetkazib beruvchiga buyurtma** (`SupplierOrder`) | `/v2/supplier-order`, `/v2/supplier-order/add-item`   |

Onlayn buyurtma uchun **birinchi qator** kerak.

> **API’da hali alohida «onlayn buyurtma» obyekti yo’q**
>
> Saytdan buyurtma oddiy sotuv sifatida o’tkaziladi. Agar rasmiylashtirish va topshirish o’rtasida oraliq holat kerak bo’lsa, u tashqi tizim tomonida saqlanadi, BILLZ’da sotuv esa amalda topshirish yoki to’lov paytida yaratiladi.

## Ssenariy sxemasi

```plaintext
GET  /v1/shop, /v1/company-payment-type      ma'lumotnomalar, bir marta
     │
GET  /v1/client?phone_number=…               mijozni topish
POST /v1/client                              topilmasa, yaratish
     │
POST /v2/order   {shop_id, cashbox_id}       sotuv yaratish ──> order_id
POST /v2/order-product/:order_id             tovar qo'shish (birma-bir)
PUT  /v2/order-customer-new/:order_id        mijozni biriktirish
POST /v2/order-manual-discount/:order_id     chegirma
POST /v1/recalculate-order-bill/:order_id    summani solishtirish
POST /v2/order-payment/:order_id             sotuvni yakunlash
     │
GET  /v2/order/:id                           o'tkazilgan sotuv tafsilotlari
```

Sotuvni yaratish va chek tarkibini o’zgartiruvchi metodlar — **asinxron**: `Billz-Response-Channel: HTTP` sarlavhasi talab etiladi, aks holda natija o’rniga hodisa identifikatori keladi. Qayta hisoblash va to’lov — sinxron, ularga sarlavha kerak emas.

## 1. Mijoz

### Qidiruv

```bash
curl -X GET 'https://api-admin.billz.ai/v1/client?phone_number=%2B998900000000&limit=10&page=1' \
  -H 'Authorization: Bearer TOKEN'
```

Parametrlar: `phone_number`, `search`, `chat_id`, `limit`, `page`. Javob — `{count, clients[]}`. Topilgan ID bo’yicha batafsil kartochka — `GET /v1/customer/:id` (unda `clients[]` elementiga qaraganda boshqa, kengroq maydonlar to’plami mavjud).

`search` ism, familiya, otasining ismi, telefon raqamlari, `external_id`, `chat_id`, tug’ilgan sana, sodiqlik kartasi kodi va nomi bo’yicha ostsatrni qidiradi. Bo’sh joy orqali ajratilgan bir necha so’z — «VA». Maxsus belgilar olib tashlanadi: `+998901234567` va `998901234567` teng qiymatli. `phone_number` ostsatr bo’yicha, `chat_id` esa aniq moslik bo’yicha qidiradi.

> **Hozirgina yaratilgan mijoz darhol topilmasligi mumkin**
>
> UUID `POST /v1/client` javobidan darhol saqlanadi.

### Yaratish

```bash
curl -X POST 'https://api-admin.billz.ai/v1/client' \
  -H 'Authorization: Bearer TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "first_name": "Ivan",
    "last_name": "Petrov",
    "phone_number": "+998900000000",
    "gender": 1,
    "date_of_birth": "1990-05-14"
  }'
```

Javob — `{ "id": "..." }`: tashqi tizimda saqlanadigan mijoz UUID’si. `gender`: `1` — erkak, `2` — ayol, boshqa qiymatlar bo’sh qilib yoziladi.

> **Metod telefon bo’yicha dubllarni tekshirmaydi**
>
> Xuddi shu raqam bilan qayta so’rov ikkinchi UUID va ikkinchi sodiqlik kartasini yaratadi. Yaratishdan oldin `GET /v1/client?phone_number=…` bajariladi, yaratish — faqat `count == 0` holatida.

## 2. Kerakli do’konda sotuv yaratish

Sotuv `POST /v2/order` asinxron metodi bilan yaratiladi. Javob kanali `Billz-Response-Channel: HTTP` sarlavhasi yoki xuddi shu nomdagi query-parametr orqali belgilanadi — quyidagi misoldagidek.

```bash
curl -X POST 'https://api-admin.billz.ai/v2/order?Billz-Response-Channel=HTTP' \
  -H 'Authorization: Bearer TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "shop_id": "c1056fcc-539b-47ea-8bc4-d9e337c433f0",
    "cashbox_id": "9b4a7f8c-a8ef-4870-8a1b-89869fdd4141"
  }'
```

```json
{
  "session_id": "fd8d352a-6299-4489-8a6e-a5c037f3f65b",
  "status_code": 200,
  "id": "38c3920a-ffdd-4233-a823-8af3266f5f4f",
  "error": { "code": "", "message": "" },
  "data": {
    "id": "38c3920a-ffdd-4233-a823-8af3266f5f4f",
    "order_number": "5632631379",
    "order_type": "SALE"
  },
  "correlation_id": "3674f28e-7b96-4683-87c3-80892698f421"
}
```

Sotuv UUID’si — `id` maydoni (`data.id` dagi qiymat bilan bir xil), u barcha keyingi qadamlarga qo’yiladi. `order_number` — kassir interfeysda ko’radigan qisqa sotuv raqami.

**Do’kon `shop_id` maydoni, kassa esa `cashbox_id` maydoni orqali tanlanadi.** Do’konlar ro’yxati — `GET /v1/shop`.

> **Javob kanalisiz sotuv ID’si kelmaydi**
>
> `Billz-Response-Channel` bo’lmasa, metod `200` tanasi bilan `{"message": "<correlation_id>"}` deb javob qaytaradi.

## 3. Mahsulotlarni qo’shish

Har bir so’rovga bitta tovar nomi.

```bash
curl -X POST 'https://api-admin.billz.ai/v2/order-product/SOTUV_ID' \
  -H 'Authorization: Bearer TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Billz-Response-Channel: HTTP' \
  -d '{
    "product_id": "2ce40c63-4527-4898-a975-7c30c255fd50",
    "sold_measurement_value": 2,
    "used_wholesale_price": false
  }'
```

> **Pozitsiyalarni faqat ushbu metod qo’shadi**
>
> To’lov tekshiradigan «savat hisoblangan» belgisini faqat `POST /v2/order-product/:order_id` orqali ishga tushiriladigan qayta hisoblash o’rnatadi.

Bu **mutlaq miqdorli upsert**: xuddi shu `product_id` bilan takroriy chaqiruv miqdorni almashtiradi. `sold_measurement_value: 0` chekdan pozitsiyani olib tashlaydi.

## 4. Mijozni biriktirish

```bash
curl -X PUT 'https://api-admin.billz.ai/v2/order-customer-new/SOTUV_ID' \
  -H 'Authorization: Bearer TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Billz-Response-Channel: HTTP' \
  -d '{ "customer_id": "ID_MIJOZNI", "check_auth_code": false }'
```

Javob konvertda keladi: obyekt `data` maydonida joylashgan.

> **SMS-tasdiqlash va `check_auth_code` maydoni**
>
> Mijozni biriktirishda SMS-kod talab qilinishi rol ruxsati bilan belgilanadi. `check_auth_code: false` bo’lganda tasdiqlash so’ralmaydi.

## 5. Chegirma

```bash
curl -X POST 'https://api-admin.billz.ai/v2/order-manual-discount/SOTUV_ID' \
  -H 'Authorization: Bearer TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Billz-Response-Channel: HTTP' \
  -d '{ "discount_unit": "PERCENTAGE", "discount_value": 10 }'
```

`discount_unit` — `PERCENTAGE` yoki `CURRENCY`. Ixtiyoriy `product_id` bitta pozitsiyaga chegirma qo’llaydi; usiz — butun savatga.

> **`CURRENCY` — yakuniy narx**
>
> `discount_unit: "CURRENCY"` bo’lganda, `discount_value` qiymati **yakuniy narxga** aylanadi: 900 000 lik savat uchun `50000` «hammasini 50 000 ga sotish» degan ma’noni anglatadi. Chegirmaning belgilangan summasi tashqi tizimda ayirib tashlanadi va tayyor narx uzatiladi.

> **Savatga chegirma va pozitsiyaga chegirma bir-birini bekor qiladi**
>
> Pozitsiyaga chegirmadan keyin qo’llanilgan savat chegirmasi uni bekor qiladi va aksincha. Bitta darajadan foydalaniladi.

> **Integratsiya kaliti orqali chegirmani bekor qilib bo’lmaydi**
>
> Chegirmani bekor qilish uchun unga qaytadan nol qiymati beriladi yoki chek qayta yig’iladi.

Qo’lda kiritilgan chegirma savatni qayta hisoblashni ishga tushiradi: to’lov chegirmaga asinxron javob olingandan so’ng chaqiriladi.

## 6. Summani solishtirish

```bash
curl -X POST 'https://api-admin.billz.ai/v1/recalculate-order-bill/SOTUV_ID' \
  -H 'Authorization: Bearer TOKEN'
```

Metod sinxron bo’lib, pozitsiyalar, chegirmalar va yakuniy summa ko’rsatilgan dolzarb chekni qaytaradi.

> **Metod «savat hisoblangan» belgisini o’rnatmaydi**
>
> To’lov vaqtida `20084` bo’lsa, qayta hisoblash yordam bermaydi: chekni o’zgartirgan asinxron operatsiya yakunlanishini kutish talab etiladi.

Kechiktirilgan sotuv uchun metod rad javobini beradi.

## 7. Sotuvni yakunlash

```bash
curl -X POST 'https://api-admin.billz.ai/v2/order-payment/SOTUV_ID' \
  -H 'Authorization: Bearer TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "payments": [
      { "company_payment_type_id": "c6e84d9b-...", "paid_amount": 900000, "returned_amount": 0 }
    ],
    "comment": "Saytdan №12345 buyurtma",
    "without_cashback": false
  }'
```

| Maydon                               | Mazmuni                                                                                     |
| ------------------------------------ | ------------------------------------------------------------------------------------------- |
| `payments[]`                         | to’lovlar ro’yxati; bir nechta element — turli usullar bilan to’lash                        |
| `payments[].company_payment_type_id` | `GET /v1/company-payment-type` dan to’lov turi                                              |
| `payments[].paid_amount`             | kiritilgan summa                                                                            |
| `payments[].returned_amount`         | qaytim                                                                                      |
| `payments[].gift_card_id`            | **butun son**; sovg’a kartasi bilan to’lash uchun kerak                                     |
| `with_cashback`                      | **summa** (bayroq emas), mijoz bonuslari hisobidan qoplanadi                                |
| `without_cashback`                   | `true` — ushbu sotuv uchun keshbek hisoblanmasin                                            |
| `sold_at`                            | `YYYY-MM-DD HH:MM:SS` formatidagi sotuv sanasi va vaqti — o’tgan sana bilan o’tkazish uchun |
| `comment`                            | tashqi tizimning buyurtma raqami; bo’sh qator oldingisini o’chirib yubormaydi               |
| `skip_ofd`                           | to’lovdan oldin OFD **tekshiruvlarini** olib tashlaydi, quyida qarang                       |

Metod sinxron. Javob tariqasida `{"order_type": "SALE", "should_print_cheque": true}` statusli `200` keladi.

> **`skip_ofd` fiskallashtirishni o’chirmaydi**
>
> Bayroqcha to’lovgacha chek fiskallashtirilganligini **tekshirishni o’tkazib yuboradi**. Metod OFDga hech narsa yubormaydi.

### To’lov xatolari kodlari

Xato HTTP `400` bilan keladi, sabab raqami esa **`data` ichida** joylashgan:

```json
{
  "status_code": 400,
  "error": { "code": "", "message": "status: 400 - errors: Bad request - causes: ..." },
  "data": { "error_code": 20084, "message": "payment is possible only for calculated order" }
}
```

Sababi `data.error_code` bo’yicha aniqlanadi: ushbu javobdagi `error.code` maydoni bo’sh.

| Kod     | Xabar                                           | Nimani anglatadi                                                                |
| ------- | ----------------------------------------------- | ------------------------------------------------------------------------------- |
| `20009` | cashbox shop id and order shop id are different | foydalanuvchining joriy kassasi boshqa do’konga tegishli                        |
| `20010` | user’s current cashbox id is empty              | sotuv do’konida ochiq kassa yo’q                                                |
| `20011` | cashbox has not enough money                    | kassada qaytarish uchun pul yetishmayapti                                       |
| `20015` | order does not have items                       | chekda pozitsiyalar yo’q                                                        |
| `20016` | not enough product                              | qoldiq yetishmayapti; mavjud miqdor — `data.data` da                            |
| `20017` | order is deleted                                | sotuv o’chirildi                                                                |
| `20020` | wrong payment amount                            | to’lovlar summasi mos kelmayapti; `data` da — `total_price` va `claimed_amount` |
| `20047` | not enough funds in customer balance            | `with_cashback` uchun bonuslar yetishmayapti                                    |
| `20063` | order not sent to epos                          | chek OFD ga yuborilmadi (`skip_ofd` bayrog’i bilan olib tashlanadi)             |
| `20082` | cannot make payment with closed cashbox         | kassa yopiq                                                                     |
| `20084` | payment is possible only for calculated order   | savat qayta hisoblanmadi, 3-qadamga qarang                                      |

`claimed_amount` — barcha elementlar bo’yicha `paid_amount` summasi minus `returned_amount`, plyus `with_cashback`, plyus qarz; chek yakuni bilan solishtiriladi.

## 8. Sotuv ID si va tafsilotlari

ID 2-qadamda qaytariladi. O’tkazilgan sotuvning to’liq tafsilotlari — pozitsiyalar, to’lovlar, chegirmalar, mijoz:

```bash
curl -X GET 'https://api-admin.billz.ai/v2/order/SOTUV_ID' \
  -H 'Authorization: Bearer TOKEN'
```

## Ko’p beriladigan aniqlashtiruvchi savollarga javoblar

### Do’kon qaysi maydon orqali tanlanadi

`shop_id` tanasidagi `POST /v2/order` maydoni orqali; kassa ham o’sha yerda belgilanadi — `cashbox_id`. Do’konlar ro’yxati — `GET /v1/shop`.

### Qoldiq yetishmaganda sotuvni rasmiylashtirish mumkinmi

Bu mahsulotning **«manfiy qoldiqqa ruxsat berish»** sozlamasi orqali boshqariladi. Agar u o’chirilgan bo’lsa, qoldiqdan ortiqcha mahsulot qo’shib bo’lmaydi; agar yoqilgan bo’lsa — qoldiq minusga kiradi.

Xato — HTTP `400`, `data.error_code` = **20016**, `data.message` = `not enough product`; mavjud miqdor `data.data` da keladi.

Qoldiqni dastlabki tekshirish — kerakli `GET /v2/products` bo’yicha `shop_measurement_values[].active_measurement_value` → `shop_id`. Tekshiruv va to’lov o’rtasida mahsulot oflayn sotilishi mumkin: to’lovdagi rad etish ham qayta ishlanadi.

### Yuk xati qanday ko’rinishda beriladi

**Ommaviy API sotuv bo’yicha tayyor yuk xatini yoki bosma shaklni bermaydi.**

| Nima kerak                 | Nima bilan yopiladi                                                                                                  |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| O’z bosma shakli           | `GET /v2/order/:id` — pozitsiyalar, narxlar, chegirmalar, to’lovlar, do’kon, mijoz; tashqi tizim tomonida sahifalash |
| Buxgalteriya uchun yuklash | hisobotlar `/v1/general-report-table`, `/v1/transaction-report-table`                                                |

### O’zida qaysi identifikatorni saqlash kerak

**Sotuv UUID’si** (2-qadam javob konvertidan `id`). `order_number` qo’llab-quvvatlash xizmati bilan yozishish uchun mo’ljallangan.

1. «Tashqi tizim buyurtma raqami → BILLZ sotuv UUID’si» aloqasi tashqi tizim tomonida saqlanadi; **UUID 2-qadamdan so’ng darhol yozib olinadi**, mahsulotlar qo’shilishidan oldin.
2. Sotuvni yaratishdan oldin ushbu buyurtma bo’yicha yozuv bor-yo’qligi tekshiriladi.
3. Tashqi tizimning buyurtma raqami to’lov vaqtida `comment` ga uzatiladi: dublikat BILLZ interfeysida va hisobotlarda ko’rinadi.

## Ruxsatlar

`403` tahlili — [muammolarni hal qilishda](/uz/troubleshooting/403-and-404/), kalit uchun ochiq bo’lganlarning to’liq ro’yxati esa [ma’lumotnomada](/uz/reference/permissions/) keltirilgan.

Kalitni chiqarish metodlarning asosiy to’plamini ochadi; nozik metodlar kalit ruxsatlarini sozlash orqali alohida ochiladi.

## Metodlar xulosasi

| Qadam                | Metod                                       | Tur   |
| -------------------- | ------------------------------------------- | ----- |
| Do’konlar ro’yxati   | `GET /v1/shop`                              | sync  |
| To’lov turlari       | `GET /v1/company-payment-type`              | sync  |
| Mijozni qidirish     | `GET /v1/client`                            | sync  |
| Mijoz kartasi        | `GET /v1/customer/:id`                      | sync  |
| Mijoz yaratish       | `POST /v1/client`                           | sync  |
| Mijozni o’zgartirish | `PUT /v1/client/:id`                        | sync  |
| Sotuv yaratish       | `POST /v2/order`                            | async |
| Mahsulot qo’shish    | `POST /v2/order-product/:order_id`          | async |
| Mijozni biriktirish  | `PUT /v2/order-customer-new/:order_id`      | async |
| Chegirma             | `POST /v2/order-manual-discount/:order_id`  | async |
| Summani solishtirish | `POST /v1/recalculate-order-bill/:order_id` | sync  |
| Sotuvni yakunlash    | `POST /v2/order-payment/:order_id`          | sync  |
| Sotuv tafsilotlari   | `GET /v2/order/:id`                         | sync  |