Epic EP-06 Kritik 04_employees erpbom-backend backend

04_employees — Hodimlar (kasb, normativ, maosh, ishbay accrual + bonus)

Bajarildi
100% 33/33
Status:

Tavsif

Korxona hodimlari va ularning kasblari: kasb lug'ati (`professions` — **tenant-umumiy**), hodim kartasi (`employees` — **node-lokal**, akkaunt ixtiyoriy), hodim ↔ kasb N-to-N, **normativ** (`profession_norms` — operatsiya × org-node) va uning audit tarixi, **oylik maosh** (`employee_salaries` + logs) va **ishbay accrual** (`wage_entries` — bosqichli/marginal bonus, snapshot bilan). 🔴 Modulning o'zagi — "**struktura ≠ iqtisod**" ikkiligi: *struktura* (kim qanday kasb) butun korxona bo'ylab bir xil → `professions` da `organization_id` YO'Q; *iqtisod* (qancha va qanchada) joyga bog'liq → `employees`, `profession_norms`, `wage_entries` da `organization_id` BOR. Bu epic uchta uzilgan uchni ham ulaydi: 1. `variant_operations.profession_id` FK — EP-02 da ATAYLAB qoldirilgan (`professions` yo'q edi); 2. 02_products qoida 26d (`wage_type = piece_rate` validatsiyasi) va `professionName` javob maydoni — EP-02 da bo'sh qolgan; 3. `AudienceOwnershipPort` ning `employee`/`driver` qismi — hozir `false` qaytaradi, ya'ni mobil ilovada *Hodim* va *Haydovchi* rollari UMUMAN LOGIN QILA OLMAYDI (09_auth R53). Backend'da to'liq data-model + REST API + accrual dvigateli; web'da kadrlar/normativ/maosh/payroll ekranlari; mobil ilovada *Hodim* rolining "mening ish haqim" oynasi.

Texnik ko'rsatma

Agent uchun

Majburiy o'qish: erp/docs/modules/04_employees.md (to'liq), erp/docs/00_CROSS_CUTTING.md (A valyuta, B precision, G versiyalash, H soft-delete, J node-lokal, K nomlash, L RBAC, M xavfsizlik, P scoping, Q qulflash), .claude/skills/coding/java-spring-coder/SKILL.md (backend), .claude/skills/coding/vuejs-coder/SKILL.md (web), .claude/skills/coding/flutter-coder/SKILL.md (mobil), .claude/skills/coding/postgresql/SKILL.md, .claude/skills/coding/swagger/SKILL.md (T00 uchun). 🔴 SCOPING (§3 "Tenant doirasi" p.1, CROSS_CUTTING P): * `professions` — **tenant-umumiy**: `organization_id` ustuni YO'Q va QO'SHILMAYDI. Unique kalit ham org segmentisiz. * `employees`, `profession_norms`, `wage_entries` — **node-lokal**: `organization_id` FK BOR (mehnat iqtisodi joyga bog'liq). 🔴 FLYWAY: keyingi versiya **V19** (V18 — EP-04 oxirgisi). Bitta migratsiya fayli emas, T01 subtasklari ketma-ket V19…V23 raqamlarini oladi (S01→V19, S02→V20, S03→V21, S04→V22, S05→V23) — parallel worker'lar bir raqamga urishmasin. 🔴 ENUM naqshi: native ENUM EMAS — `varchar(N) NOT NULL DEFAULT ...` + `CHECK (col IN (...))` (V12/V17 bilan bir xil, postgresql skill §6). 🔴 PRECISION (CROSS_CUTTING B, §6.3): pul — `numeric(18,2)`; miqdor va normativ — `numeric(18,4)`. Wire formatda pul/miqdor — **string decimal** (mavjud kontrakt qoidasi). 🔴 RBAC o'qish yo'llari: katalogda `profession.view` RULE YO'Q. Mavjud naqsh (`SectorController`, EP-02): lug'at GET yo'llari `@RequirePermission` SIZ — faqat autentifikatsiya talab qilinadi; yozish `profession.manage`. Yangi rule O'YLAB TOPILMAYDI. 🔴 HISOBLASH nuqtalari: * §6.1 marginal bonus — accrual paytida, kunlik agregat kaliti (`employee_id`, `variant_operation_id`, `work_date`); * agregat bo'yicha `pg_advisory_xact_lock` (CROSS_CUTTING Q) — `UNIQUE(work_id)` bu race'ni YOPMAYDI, faqat takrorni to'sadi; * `rate`/`bonus_rate`/`norm_per_day` — accrual paytida SNAPSHOT.

Qabul mezonlari (DoD)

0 / 12 bajarildi

  • Migratsiyalar V19..V23 toza bazada va V18 gacha to'ldirilgan bazada xatosiz o'tadi

  • `professions` jadvalida `organization_id` ustuni yo'q; `employees`/`profession_norms`/`wage_entries` da bor (information_schema testi)

  • Kasb lug'ati takrori: faol "Payvandchi" bor ekan `"payvandchi"`/`" Payvandchi "` rad etiladi; `active=false` qilingach yangi "Payvandchi" o'tadi (§12 AC1)

  • Akkauntsiz hodim (`user_id IS NULL`) darhol `active` holatda yaratiladi; keyin akkaunt biriktirilganda `employees.status` `active` da qoladi (§12 AC2, qoida 21e)

  • §6.1 ishlangan misol kodda takrorlanadi: norm=10, rate=10000, bonus_rate=13000; Task A(8) → 80 000, Task B(10) → 124 000, kunlik jami 204 000

  • Hodim bir kunda ikki turli operatsiya bajarsa normativlar ALOHIDA hisoblanadi (bir operatsiyadagi oshish ikkinchisining bonusiga ta'sir qilmaydi)

  • `fired` hodim: `users.status='blocked'` + barcha sessiya `revoked_at` + `token_valid_after=now()` — BIR tranzaksiyada; sinxron yiqilsa butun amal rollback

  • Oxirgi faol `owner` akkauntli hodimni bo'shatishga urinish `409 last_owner_required` beradi va `employees.status` HAM o'zgarmaydi

  • Mobil ilovada *Hodim* roli bilan login ishlaydi (`audience='employee'`), *Haydovchi* roli faqat faol `professions.is_driver=true` kasbi bo'lganda o'tadi, aks holda `403 audience_mismatch`

  • `employee_salary.view` huquqi yo'q foydalanuvchi javobida maosh maydoni UMUMAN yo'q (null emas, maydonning o'zi yo'q)

  • Bu epicda qo'shilgan har qanday YANGI egalik (ownership) rad etishi `OwnershipDeniedException` orqali o'tadi — ya'ni EP-04-T12 markaziy handleri uni `auth_logs` ga `deny` qilib yozadi (R30(1)); qo'lda `auditService.log(...)` yozilmaydi

  • Kontrakt↔kod drift toza (EP-05 gate): `openapi/v1/employees.yaml` dagi har operatsiya kodda bor

Ichki ishlar

10 ta

Izoh qoldirish

Tarix

15 yozuv

  • ⇄

    system statusni o'zgartirdi Ishlanyapti → Bajarildi

    Bolalardan avtomatik hisoblandi

  • ⇄

    system statusni o'zgartirdi Bajarildi → Ishlanyapti

    Bolalardan avtomatik hisoblandi

  • ⇄

    system statusni o'zgartirdi Ishlanyapti → Bajarildi

    Bolalardan avtomatik hisoblandi

  • 💬

    team-lead-pm izoh qoldirdi

    T06: 3/4 barg done. S03 — texnik bogliqlik (EP-06-T05-S02 maskalashi), blok emas; T05-S02 yopilgach yangi worker bilan ochiladi. 🔴 07_tasks EPICI UCHUN MUHIM: WageAccrualPort javadocidagi "xato tashlanmaydi" shartsiz kafolati NOTOGRI — catch-fallback bitta tranzaksiya ichida ishlamaydi (Hibernate sessiyasi buziladi), u faqat ketma-ket retry uchun tori. 07_tasks tasdiq tranzaksiyasini shu asosda loyihalang, aks holda accrual xatosi butun tasdiqni jimgina yiqitadi.

  • 💬

    team-lead-pm izoh qoldirdi

    T04 yopildi (3/3). Uch qoldiq: (1) PUT /product-variants/{id}/profession-norms/{normId} yoldagi {id} ni etiborga olmasdi (A yoli orqali B normativi yangilanardi) — alohida coder 404 bilan tuzatmoqda, kontrakt ozgarmaydi (404 allaqachon elon qilingan). (2) FINAL PASS / 09_auth: oqishda scope_for qollanmaydi — node A ga scoped user B ning normativini oqiydi; bu repo-keng mavjud naqsh (PieceRateController ham shunday), 09_auth §6.1 cross-cutting masalasi, bir joyda hal qilinsin. (3) §5 SIKLIGA: 02 qoida 27 kochirishni auditlashni talab qiladi, lekin 04 §2.4a sxemasi effective_to ni majburiy qilgani uchun kochirish loglanmaydi; EP-02 ning piece_rates yarmi ham shunday va done — umumiy qaror kerak. Mayda: normativ update() active ekanini tekshirmaydi (retired normativ tahrirlanadi), §2.4 buni tariflamaydi.

  • 💬

    team-lead-pm izoh qoldirdi

    T08 yopildi (3/3). Kuzatuv FINAL PASS uchun: muzlatilgan kontrakt (employees.yaml:48-56) normativni OQISH uchun ham profession_norm.set huquqini talab qiladi — 09_auth katalogida profession_norm.view rule YOQ. AC2926 matni (huquqsizda read-only) shu sababli sozma-soz bajarilmadi; mezon komponent darajasida mudofaa qatlami bilan yopildi (useCan, 7/7 mutatsiya oldi). Agar biznes normativni faqat KORISH huquqini istasa — .view rule 09_auth ga qoshilib kontrakt yangilanishi kerak. Ayrim vaqt bombasi (EmployeePayrollView.spec sentabrda qizil boladi) va employee-detail route guard testi alohida coder bilan tuzatilmoqda.

  • 💬

    team-lead-pm izoh qoldirdi

    T02 dan IKKI YANGI BIZNES SAVOLI (kod defekti emas, 04_employees §5 sikliga tegishli, epicni bloklamaydi): (1) kasb wage_type piece_rate -> monthly ga ozgartirilsa, oshа kasbga boglangan MAVJUD ishbay stavkalar bilan nima boladi? Hozir saqlanib qoladi va tahrirlanishi mumkin; spec 26d faqat operatsiya yaratish/tahrir paytini qamraydi. PUT bilan wage_type almashtirish endi ochiq yol. (2) Nofaol (active=false) piece_rate kasbni yangi marshrut operatsiyasiga biriktirish hozir mumkin — spec faqat wage_type ni talab qiladi, active haqida jim.

  • 💬

    team-lead-pm izoh qoldirdi

    Qizil branch YOPILDI: ddf403f — EP-02 ning 4 sinfida 32 qizil test (V19 FK toqnashuvi) fixture orqali tuzatildi, 147/147 yashil. FAZA D UCHUN QOLDIQ: (1) toliq backend suite (127 sinf, ~3 soat) hech qachon oxirigacha yurgizilmadi — epic yakunida bir marta toliq yurgizilsin; (2) main da ikkita eskirgan izoh qoldi: VariantOperation.java:45 (FK yoq deydi) va RecipeVersionService.java:680 (professions jadvali yoq deydi) — kichik tozalash kerak.

  • 💬

    team-lead-pm izoh qoldirdi

    T01 natijasi: V19 dagi variant_operations.profession_id FK EP-02 ning RecipesAndRoutesMigrationTest fixture-larini yiqitadi (profession_id 1L/999999999L qotirilgan). Board taski emas — team lead to gridan-to gri backend coder bilan tuzattirmoqda; branch yashil bolmaguncha Faza D (PR) boshlanmaydi. Kontrakt employees.yaml commit qilindi: 37bd084.

  • 💬

    team-lead-pm izoh qoldirdi

    T09 qoldigi (epic yakunida korilsin): (1) mobil payroll ekrani router/home ga ulanmagan; (2) haydovchi AUDIENCE_MISMATCH ikki sababni farqlamaydi. Ochiq spec boshligi: /me/payroll/summary kutilayotgan ish haqi (04_employees 6.1 formulasi yoq + works jadvali yoq).

  • ⇄

    system statusni o'zgartirdi Backlog → Ishlanyapti

    Bolalardan avtomatik hisoblandi

  • 🔗

    pm-agent bog'liqlik qo'shdi

    → EP-02

  • 🔗

    pm-agent bog'liqlik qo'shdi

    → EP-09

  • 🔗

    pm-agent bog'liqlik qo'shdi

    → EP-01

  • ✦

    pm-agent yaratdi

    04_employees — Hodimlar (kasb, normativ, maosh, ishbay accrual + bonus)

Ma'lumot

Agent
—
Olingan
—
Boshlandi
24.08.2026 08:38
Tugadi
25.08.2026 06:11
Baho
118 soat
Spec
erp/docs/modules/04_employees.md
Branch
—
Commit
—

Bog'liqliklar

Agent uchun

Bu ishni AI agent quyidagicha oladi:

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

Tugatgach:

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