Sub-task EP-06-T04-S01 Yuqori 04_employees erpbom-backend

`ProfessionNormService` — belgilash/o'zgartirish + `profession_norm_logs`

Bajarildi
Status:

Tavsif

Belgilash: (operatsiya × org-node) uchun faol normativ yaratish. O'zgartirish (§8.2, Q17 + CROSS_CUTTING G): 1. eski qiymat `profession_norm_logs` ga (`effective_to` = yangi `effective_from` dan bir kun oldin); 2. `profession_norms` **joyida yangilanadi** (`norm_per_day`, `effective_from`, `set_by_user_id`). 🔴 Active jadval hech qachon log sifatida ishlatilmaydi (`employee_salaries` bilan bir xil naqsh). Retire: `active=false` (variant ishlab chiqarilmaydi).

Qabul mezonlari (DoD)

4 / 4 bajarildi

  • Normativ o'zgartirilganda `profession_norm_logs` ga aynan bitta qator qo'shiladi va `effective_to` = yangi `effective_from` − 1 kun

    qa-ep-06-t04-s01 · 1 о аввал

  • `profession_norms` da qator soni o'zgarmaydi (joyida UPDATE, yangi qator emas)

    qa-ep-06-t04-s01 · 1 о аввал

  • Bir (operatsiya × org-node) uchun ikkinchi faol normativ yaratishga urinish 409

    qa-ep-06-t04-s01 · 1 о аввал

  • Retire qilingan normativdan keyin o'sha kalit uchun yangi normativ yaratish mumkin

    qa-ep-06-t04-s01 · 1 о аввал

O'zgargan fayllar

10 ta

  • modified src/test/java/uz/erpbom/employees/service/ProfessionNormServiceTest.java
  • modified src/main/java/uz/erpbom/employees/service/ProfessionNormService.java
  • modified src/main/java/uz/erpbom/employees/repository/ProfessionNormRepository.java
  • modified src/main/java/uz/erpbom/employees/repository/ProfessionNormLogRepository.java
  • modified src/main/java/uz/erpbom/employees/mapper/ProfessionNormMapper.java
  • modified src/main/java/uz/erpbom/employees/entity/ProfessionNormLog.java
  • modified src/main/java/uz/erpbom/employees/entity/ProfessionNorm.java
  • modified src/main/java/uz/erpbom/employees/dto/ProfessionNormUpdateRequest.java
  • modified src/main/java/uz/erpbom/employees/dto/ProfessionNormResponse.java
  • modified src/main/java/uz/erpbom/employees/dto/ProfessionNormCreateRequest.java

Izoh qoldirish

Tarix

17 yozuv

  • ✎

    finalize-ep-06 yangiladi

    Yangilandi: pr_url

  • ⇄

    qa-ep-06-t04-s01 statusni o'zgartirdi Review → Bajarildi

  • 💬

    qa-ep-06-t04-s01 izoh qoldirdi

    QA (qa-EP-06-T04-S01) — commit d01cd70, branch feat/EP-06-erpbom-backend. Verdikt: DONE. Test: mvn -Dtest=ProfessionNormServiceTest test → Tests run: 10, Failures: 0, Errors: 0 (Testcontainers postgres:16, real DB). Mezonlar kod darajasida: - AC2870 — ProfessionNormService.java:137-144: log qatori AYNAN bitta save(); :141 setEffectiveTo(request.effectiveFrom().minusDays(1)). Test :150 hasSize(1), :155 effective_to = newEffectiveFrom-1. - AC2871 — :146-150 joyida UPDATE (existing entity, yangi ProfessionNorm yaratilmaydi). Test :175 count() o'zgarmaydi + :176 updated.id() == created.id(). - AC2872 — :91-94 pre-check findActiveByKey → BusinessConflictException(DUPLICATE_PROFESSION_NORM); :201-210 saveAndFlush + V21 partial unique uq_profession_norms_variant_operation_organization_active ikkinchi qatlam. GlobalExceptionHandler:96 → HTTP 409. - AC2873 — retire(): :173 active=false; partial indeks WHERE active retired qatorni qamramaydi → qayta create ishlaydi. Test :204-221. MUTATSIYA TEKSHIRUVI (har mutatsiya kiritildi, test yiqildi, git checkout bilan tiklandi — fayl md5 c67204ad… asliga qaytdi): - minusDays(1)→minusDays(2): updateWritesExactlyOneLogRow… YIQILDI (expected 2026-01-31, was 2026-01-30). - update()da qo'shimcha qator INSERT: updateKeepsRowCountUnchanged… YIQILDI (expected 1, was 2). - retire() active=true: creatingAgainAfterRetireSucceeds + retireIsIdempotent YIQILDI. - xatolik kodi DUPLICATE_NORM_MUTANT: secondActiveNormForSameKeyReturns409 YIQILDI. - log ikki marta yozildi: updateWritesExactlyOneLogRow… YIQILDI (Expected size 1 but was 2). - create() pre-check butunlay olib tashlandi: test PASS bo'ldi (SURVIVED) — javap bilan tasdiqlandi, findActiveByKey chindan bytecode'dan yo'qolgan. Bu test bo'shligi emas: DB partial unique indeksi 409 ni yolg'iz o'zi beradi (defense-in-depth ikki qatlami ham ishlaydi). Kontrakt (openapi/v1/employees.yaml): ProfessionNormResponse 9 maydon (id, variant_operation_id, organization_id, norm_per_day, effective_from, set_by_user_id, active, created_at, updated_at) — DTO bilan 1:1, global SNAKE_CASE. Create/Update request maydonlari va exclusiveMinimum>0 (@DecimalMin inclusive=false) mos. 409 DUPLICATE_PROFESSION_NORM, 400 VALIDATION_ERROR mos. Drift yo'q. Cross-cutting: @Transactional hamma DB metodida (get — readOnly=true); tenant_id yo'q (organization_id node-lokal, AR-1 buzilmaydi); FK'lar V21 da to'liq nomda (fk_profession_norms_*); snake_case + ko'plik; norm_per_day numeric(18,4); fizik DELETE yo'q (active=false soft-retire); log/parol muammosi yo'q (servisda logging umuman yo'q). QAYD (defekt emas): variant_operation_id ning yo'ldagi variant marshrutiga tegishliligi validatsiyasi ataylab EP-06-T04-S03 ga qoldirilgan (cross-modul o'qish, ADR §2.3). 2870-2873 mezonlarining hech biri marshrut a'zoligiga tayanmaydi — qabul qilindi, lekin S03 yopilmaguncha POST bo'yicha 400 tekshiruvi mavjud emas. QAYD 2 (kichik, spec bo'shligi emas): update() normativ active ekanini tekshirmaydi — retired normativni ham o'zgartirish mumkin (log yoziladi). Spec §2.4/§2.4a bu holatni ta'riflamaydi; S03 (REST) yoki S02 da ko'rib chiqilsa bo'ladi.

  • ✓

    qa-ep-06-t04-s01 qabul mezonini belgiladi

    ✓ Retire qilingan normativdan keyin o'sha kalit uchun yangi normativ yaratish mumkin

  • ✓

    qa-ep-06-t04-s01 qabul mezonini belgiladi

    ✓ Bir (operatsiya × org-node) uchun ikkinchi faol normativ yaratishga urinish 409

  • ✓

    qa-ep-06-t04-s01 qabul mezonini belgiladi

    ✓ `profession_norms` da qator soni o'zgarmaydi (joyida UPDATE, yangi qator emas)

  • ✓

    qa-ep-06-t04-s01 qabul mezonini belgiladi

    ✓ Normativ o'zgartirilganda `profession_norm_logs` ga aynan bitta qator qo'shiladi va `effective_to` = yangi `effective_from` − 1 kun

  • ⇄

    coder-ep-06-t04-s01 statusni o'zgartirdi Ishlanyapti → Review

  • ✎

    coder-ep-06-t04-s01 yangiladi

    Yangilandi: branch, commit_sha

  • ✓

    coder-ep-06-t04-s01 qabul mezonini belgiladi

    ✓ Retire qilingan normativdan keyin o'sha kalit uchun yangi normativ yaratish mumkin

  • ✓

    coder-ep-06-t04-s01 qabul mezonini belgiladi

    ✓ Bir (operatsiya × org-node) uchun ikkinchi faol normativ yaratishga urinish 409

  • ✓

    coder-ep-06-t04-s01 qabul mezonini belgiladi

    ✓ `profession_norms` da qator soni o'zgarmaydi (joyida UPDATE, yangi qator emas)

  • ✓

    coder-ep-06-t04-s01 qabul mezonini belgiladi

    ✓ Normativ o'zgartirilganda `profession_norm_logs` ga aynan bitta qator qo'shiladi va `effective_to` = yangi `effective_from` − 1 kun

  • 📄

    coder-ep-06-t04-s01 fayllarni qayd etdi

    10 ta fayl qayd etildi

  • ⇄

    coder-ep-06-t04-s01 statusni o'zgartirdi Backlog → Ishlanyapti

    Agent ishni boshladi

  • ⚑

    coder-ep-06-t04-s01 ishga oldi

  • ✦

    pm-agent yaratdi

    `ProfessionNormService` — belgilash/o'zgartirish + `profession_norm_logs`

Ma'lumot

Agent
coder-ep-06-t04-s01
Olingan
1 о аввал
Boshlandi
24.08.2026 13:51
Tugadi
24.08.2026 14:24
Baho
4 soat
Spec
erp/docs/modules/04_employees.md#2.4
Branch
feat/EP-06-erpbom-backend
Commit
d01cd70b607e

Bog'liqliklar

Agent uchun

Bu ishni AI agent quyidagicha oladi:

curl -s -X POST https://pmboard.ferp.uz/api/items/EP-06-T04-S01/claim \
  -H "X-Agent: backend-dev-1"

Tugatgach:

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