Sub-task EP-04-T02-S02 Kritik 03_warehouse erpbom-backend

Kirim (`postIn`) — yangi partiya + `stock` upsert + arxiv bloklash

Bajarildi
Status:

Tavsif

`postIn(warehouseId, variantId, condition, qty, totalCost, sourceType, sourceRefId, groupId, userId)` → yaratilgan partiya. Mantiq: 1. 🔴 **Qoida 32 (arxiv):** variant `active = false` bo'lsa **yangi kirim bloklanadi** (`purchase_in`/`return_in`/ `production_in`/`transfer_in`/`assembly_in` — hammasi). Chiqim esa ruxsat (bu tekshiruv `postOut` da YO'Q). 2. Yangi `stock_batches` qatori: `qty_in = qty_remaining = qty`, `total_cost = remaining_cost = totalCost`, `unit_cost = totalCost / qty` (hosila ko'rsatkich, `numeric(18,4)`), `received_at = now()`. 3. `stock` qatorini `FOR UPDATE` bilan qulflaydi; qator yo'q bo'lsa avval `INSERT` (race'ga chidamli — unique violation da qayta o'qish). `qty_on_hand += qty`. 4. `stock_movements` ga `direction = in` qatori: `total_cost = totalCost`, `unit_cost` = partiya ko'rsatkichi. ⚠️ `unit_cost` — **hosila**; qiymat manbai chaqiruvchidan `totalCost` sifatida keladi (kirim summasi / ishlab chiqarish tannarxi / yig'ish qiymati / ko'chirilgan qatlam qiymati).

Qabul mezonlari (DoD)

4 / 4 bajarildi

  • Kirimda yangi partiya `qty_in = qty_remaining`, `total_cost = remaining_cost` bilan yaratiladi va `stock.qty_on_hand` aniq `+qty` oshadi

    qa-ep-04-t02-s02 · 1 о аввал

  • `stock` qatori mavjud bo'lmaganda avtomatik yaratiladi; ikki parallel kirim bitta (warehouse, variant, condition) uchun ikkita qator yaratmaydi

    qa-ep-04-t02-s02 · 1 о аввал

  • Arxivlangan (`active=false`) variantga kirim `postIn` da bloklanadi, ammo o'sha variantdan chiqim (`postOut`) muammosiz o'tadi (qoida 32)

    qa-ep-04-t02-s02 · 1 о аввал

  • Partiya bo'yicha `Σ movements.total_cost` (in) partiya `total_cost` ga teng

    qa-ep-04-t02-s02 · 1 о аввал

O'zgargan fayllar

6 ta

  • modified src/test/java/uz/erpbom/warehouse/service/StockInPosterTest.java
  • modified src/main/java/uz/erpbom/products/service/ProductVariantService.java
  • modified src/main/java/uz/erpbom/warehouse/repository/StockRepository.java
  • modified src/main/java/uz/erpbom/warehouse/service/StockPostingService.java
  • modified src/main/java/uz/erpbom/warehouse/service/StockInPoster.java
  • modified src/main/java/uz/erpbom/warehouse/service/PostInCommand.java

Izoh qoldirish

Tarix

18 yozuv

  • ✎

    finalize-ep-04 yangiladi

    Yangilandi: commit_sha, pr_url

  • ⇄

    qa-ep-04-t02-s02 statusni o'zgartirdi Review → Bajarildi

    QA: 4/4 mezon mustaqil tasdiqlandi, 5 mutatsiya qizil, StockInPosterTest+StockPostingServiceTest 10/10 yashil (regressiya yo'q).

  • 💬

    qa-ep-04-t02-s02 izoh qoldirdi

    QA (mustaqil tekshiruv, coder isbotiga tayanilmadi) — ✅ done. Spec: 03_warehouse §5 qoida 4/5/9/30/32/42, CROSS_CUTTING B/Q. MUTATSIYA TEKSHIRUVI (har biri QA tomonidan kiritildi, test yurgizildi, so'ng `git checkout -- <fayl>` bilan tiklandi) — 5/5 QIZIL: (a1) qty_remaining = qty-1 → RED: StockInPosterTest:145 + invariant:301 (2 ta test) (a2) remaining_cost = totalCost-0.01 → RED: :148 (b) qty_on_hand = qty (add() o'rniga) → RED: :151 (13 kutilgan) + :201 (16 kutilgan) (c) arxiv gvardi olib tashlandi → RED: :212 (AC2433) (d) movement.total_cost = unitCost×qty → RED: :262 (100.00 vs 99.99, AC2434) (e) qo'shimcha — insertIfAbsent'dan ON CONFLICT olib tashlandi → RED: duplicate key uq_stock_warehouse_id_product_variant_id_condition (AC2432 testining tishi bor) Testlar (flock ostida, tor doira): mvn -Dtest='StockInPosterTest,StockPostingServiceTest' test → Tests run: 10, Failures: 0, Errors: 0 — BUILD SUCCESS. EP-04-T02-S01 (StockPostingServiceTest, 6 test) yashil qoldi — regressiya yo'q. Mezon bo'yicha: • AC2431 — qty_in=qty_remaining=10, total_cost=remaining_cost=250000.00, unit_cost=25000.0000 (divide(qty,4,HALF_UP) → numeric(18,4), qoida 30 istisnosi), received_at=now() to'ldirilgan; stock 3→13 (nol EMAS qoldiqdan seed qilingan — 'qty_on_hand = qty' mutatsiyasi tasodifan yashil qolmaydi). • AC2432 — HAQIQIY konkurentlik: 8 thread × ExecutorService.invokeAll, ketma-ket chaqiruv EMAS. stock qatori 1 ta, qty_on_hand 16.0000, 8 ta alohida partiya. ON CONFLICT nishoni V16 dagi uq_stock_warehouse_id_product_variant_id_condition (partial EMAS → arbiter inference to'g'ri ishlaydi) — mutatsiya (e) buni DB xatosi bilan tasdiqladi. • AC2433 — 409 VARIANT_ARCHIVED (openapi/v1/warehouse.yaml:111, 1402, 2662, 2715 bilan mos), to'liq rollback (stock/batch/movement — 0 qator). postOut'da arxiv tekshiruvi YO'Q (StockOutPoster'da isActive chaqiruvi yo'qligi grep bilan tasdiqlandi; test o'sha arxiv variantdan write_off chiqimini muvaffaqiyatli o'tkazadi) — qoida 32 asimmetriyasi saqlangan. • AC2434 — Σ movements.total_cost (direction=in) = partiya total_cost (100.00), bitta 'in' qatori; movement_type=purchase_in, direction=in, source_type=purchase — V16 chk_stock_movements_consistency bilan izchil. Invariantlar: qoida 4 — postIn faqat qo'shadi + DB chk_stock_qty_on_hand>=0; qoida 5 — qty_on_hand ≡ Σ stock_batches.qty_remaining bitta @Transactional ichida, ikkita testda alohida assert qilingan. Cross-cutting: @Transactional (StockInPoster.post), isActive — readOnly=true; tenant_id yo'q (AR-1); migratsiya/FK o'zgarmagan; outbox/broker/kesh tegilmagan (AR-3/AR-4); precision qty 18,4 · pul 18,2 · batch.unit_cost 18,4 (qoida 30); soft-delete — isActive findByIdAndDeletedAtIsNull ishlatadi; log'ga sir yozilmagan. Qulf tartibi: setLockTimeoutForCurrentTransaction() (SET LOCAL lock_timeout=3s) insertIfAbsent'dan OLDIN qo'yilgan — INSERT kutishi ham 3s bilan chegaralangan → 55P03 → executeWithRetry (max 2) → STOCK_BUSY (CROSS_CUTTING Q p.3/4/5). postIn bitta stock qatorini qulflaydi, tartib masalasi tug'ilmaydi. Cross-module: ProductVariantService.isActive(id) — warehouse products entity/repository'siga tegmaydi, faqat boolean qaytaradi; ADR-001 §5 (AR-1…AR-12) ga zid emas. ℹ️ Eslatma (defekt EMAS, S01 da qabul qilingan naqsh): stock_movements.unit_cost — numeric(18,2), partiya ko'rsatkichi (0.3333) DB'da 0.33 ga yaxlitlanadi. Qiymat manbai total_cost (18,2) bo'lgani uchun tiyin yo'qolmaydi (qoida 42); test buni ochiq hujjatlashtirgan. Working tree: `git status --short` faqat `M openapi/v1/warehouse.yaml` (staged, tegilmagan) — src/ da HEAD bilan farq yo'q.

  • ✓

    qa-ep-04-t02-s02 qabul mezonini belgiladi

    ✓ Partiya bo'yicha `Σ movements.total_cost` (in) partiya `total_cost` ga teng

  • ✓

    qa-ep-04-t02-s02 qabul mezonini belgiladi

    ✓ Arxivlangan (`active=false`) variantga kirim `postIn` da bloklanadi, ammo o'sha variantdan chiqim (`postOut`) muammosiz o'tadi (qoida 32)

  • ✓

    qa-ep-04-t02-s02 qabul mezonini belgiladi

    ✓ `stock` qatori mavjud bo'lmaganda avtomatik yaratiladi; ikki parallel kirim bitta (warehouse, variant, condition) uchun ikkita qator yaratmaydi

  • ✓

    qa-ep-04-t02-s02 qabul mezonini belgiladi

    ✓ Kirimda yangi partiya `qty_in = qty_remaining`, `total_cost = remaining_cost` bilan yaratiladi va `stock.qty_on_hand` aniq `+qty` oshadi

  • ⇄

    coder-ep-04-t02-s02 statusni o'zgartirdi Ishlanyapti → Review

  • ✎

    coder-ep-04-t02-s02 yangiladi

    Yangilandi: branch, commit_sha

  • ✓

    coder-ep-04-t02-s02 qabul mezonini belgiladi

    ✓ Partiya bo'yicha `Σ movements.total_cost` (in) partiya `total_cost` ga teng

  • ✓

    coder-ep-04-t02-s02 qabul mezonini belgiladi

    ✓ Arxivlangan (`active=false`) variantga kirim `postIn` da bloklanadi, ammo o'sha variantdan chiqim (`postOut`) muammosiz o'tadi (qoida 32)

  • ✓

    coder-ep-04-t02-s02 qabul mezonini belgiladi

    ✓ `stock` qatori mavjud bo'lmaganda avtomatik yaratiladi; ikki parallel kirim bitta (warehouse, variant, condition) uchun ikkita qator yaratmaydi

  • ✓

    coder-ep-04-t02-s02 qabul mezonini belgiladi

    ✓ Kirimda yangi partiya `qty_in = qty_remaining`, `total_cost = remaining_cost` bilan yaratiladi va `stock.qty_on_hand` aniq `+qty` oshadi

  • 📄

    coder-ep-04-t02-s02 fayllarni qayd etdi

    6 ta fayl qayd etildi

  • ⇄

    coder-ep-04-t02-s02 statusni o'zgartirdi Backlog → Ishlanyapti

    Agent ishni boshladi

  • ⚑

    coder-ep-04-t02-s02 ishga oldi

  • 🔗

    pm-agent bog'liqlik qo'shdi

    → EP-04-T02-S01

  • ✦

    pm-agent yaratdi

    Kirim (`postIn`) — yangi partiya + `stock` upsert + arxiv bloklash

Ma'lumot

Agent
coder-ep-04-t02-s02
Olingan
1 о аввал
Boshlandi
20.08.2026 13:20
Tugadi
20.08.2026 14:08
Baho
4 soat
Spec
erp/docs/modules/03_warehouse.md#5
Branch
feat/EP-04-erpbom-backend
Commit
b6685d9b9b72

Bog'liqliklar

Agent uchun

Bu ishni AI agent quyidagicha oladi:

curl -s -X POST https://pmboard.ferp.uz/api/items/EP-04-T02-S02/claim \
  -H "X-Agent: backend-dev-1"

Tugatgach:

curl -s -X POST https://pmboard.ferp.uz/api/items/EP-04-T02-S02/status \
  -H "X-Agent: backend-dev-1" \
  -H "Content-Type: application/json" \
  -d '{"status":"review","note":"..."}'