SKILL: Uporządkowanie skills domenowych - podział na mniejsze pliki i wspólna numeracja
This commit is contained in:
@@ -0,0 +1,321 @@
|
||||
# KADRY06 — RCP — rejestracja czasu pracy
|
||||
|
||||
> Wspólne fakty o typie, podstawowe typy i szablon wzorca: [../kadry.md](../kadry.md).
|
||||
|
||||
> **Dwie tabele.** Zarejestrowany (surowy) czas pracy z czytników RCP leży w
|
||||
> `pracownik.DniRCP : DateSubTable<Soneta.Kalend.DzienRCP>` (tabela `DniRCP`). Pojedyncze zdarzenia
|
||||
> wejścia/wyjścia (`Soneta.Kalend.WejscieWyjscie`, tabela `WejsciaWyjscia`) są **childem `DzienPracy`**
|
||||
> (pole `WejscieWyjscie.Dzien : DzienPracy`, kolekcja `dzienPracy.WeWy`), a `DzienPracy` to
|
||||
> ewidencja w `pracownik.DniPracy`. `DzienRCP` jest stanem zweryfikowanym RCP (z polem
|
||||
> `StanRCP : StanWeryfikacjiRCP`), powstaje z importu/przeliczenia.
|
||||
|
||||
### KADRY-F1 — Rejestracja czasu pracy pracownika (★)
|
||||
|
||||
**Cel:** odczytać zarejestrowany/zewidencjonowany czas pracy pracownika za dzień oraz (gdy trzeba)
|
||||
utworzyć dzień ewidencji.
|
||||
|
||||
**Pola i typy:**
|
||||
|
||||
| Element | Lokalizacja | Typ | Uwaga |
|
||||
|---|---|---|---|
|
||||
| Ewidencja (kolekcja) | `pracownik.DniPracy` | `DateSubTable<Soneta.Kalend.DzienPracy>` | indeksator `[Date]` (get); element ctorem |
|
||||
| Dzień ewidencji | `pracownik.DniPracy[data]` | `Soneta.Kalend.DzienPracy` | `null` przy braku |
|
||||
| RCP zweryfikowane (kolekcja) | `pracownik.DniRCP` | `DateSubTable<Soneta.Kalend.DzienRCP>` | analogicznie |
|
||||
| Dzień RCP | `pracownik.DniRCP[data]` | `Soneta.Kalend.DzienRCP` | `null` przy braku |
|
||||
| Przepracowany czas (subrow) | `DzienPracy.Praca` / `DzienRCP.Praca` | `Soneta.Kalend.CzasPracy` | `Praca.OdGodziny`, `Praca.DoGodziny`, `Praca.Czas : Time` |
|
||||
| Czas/Od (odczyt) | `Dzien*.Czas`, `Dzien*.OdGodziny` | `Soneta.Types.Time` | kalkulowane |
|
||||
| Stan weryfikacji RCP | `DzienRCP.StanRCP` | `Soneta.Kalend.StanWeryfikacjiRCP` | zapisywalne |
|
||||
| Flaga importu RCP | `Dzien*.RcpOK` | `bool` | zapisywalne; stan rekordu po imporcie |
|
||||
| Zdarzenia we/wy dnia | `DzienPracy.WeWy` | `LpSubTable<Soneta.Kalend.WejscieWyjscie>` | patrz KADRY-F2 |
|
||||
| Uwagi / błędy (RCP) | `DzienRCP.Uwagi`, `DzienRCP.Bledy` | `Soneta.Business.MemoText` | zapisywalne |
|
||||
|
||||
**Snippet:**
|
||||
|
||||
```csharp
|
||||
var kalend = session.GetKadry().Session.GetKalend();
|
||||
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
|
||||
var data = new Date(2026, 6, 1);
|
||||
|
||||
// --- Odczyt zaewidencjonowanego czasu (ewidencja) ---
|
||||
var dzienPracy = pracownik.DniPracy[data]; // typowane: DzienPracy lub null
|
||||
if (dzienPracy is not null)
|
||||
{
|
||||
Time przepracowano = dzienPracy.Praca.Czas; // suma czasu pracy dnia
|
||||
Time od = dzienPracy.Praca.OdGodziny;
|
||||
Time @do = dzienPracy.Praca.DoGodziny;
|
||||
}
|
||||
|
||||
// --- Odczyt stanu RCP (zweryfikowany rejestr) ---
|
||||
var dzienRcp = pracownik.DniRCP[data]; // DzienRCP lub null
|
||||
if (dzienRcp is not null)
|
||||
{
|
||||
Time czasRcp = dzienRcp.Praca.Czas;
|
||||
StanWeryfikacjiRCP stan = dzienRcp.StanRCP;
|
||||
}
|
||||
|
||||
// --- Utworzenie dnia ewidencji (gdy potrzebny ręczny wpis) ---
|
||||
using (var t = session.Logout(editMode: true))
|
||||
{
|
||||
var dp = pracownik.DniPracy[data];
|
||||
if (dp is null)
|
||||
{
|
||||
dp = session.AddRow(new DzienPracy(pracownik, data)); // ctor (Pracownik, Date)
|
||||
kalend.DniPracy.AddRow(dp); // alternatywnie przez Module.DniPracy
|
||||
}
|
||||
dp.Praca.OdGodziny = new Time(8, 0);
|
||||
dp.Praca.DoGodziny = new Time(16, 0);
|
||||
t.Commit();
|
||||
}
|
||||
session.Save();
|
||||
```
|
||||
|
||||
**Pułapki:**
|
||||
- `DniPracy`/`DniRCP` są **typowane** (`DateSubTable<DzienPracy>` / `<DzienRCP>`) — indeksator
|
||||
`[Date]` zwraca od razu właściwy typ lub `null`. Nie iteruj całej kolekcji, by „znaleźć" dzień —
|
||||
użyj indeksatora po dacie albo `[FromTo]` dla zakresu.
|
||||
- Czas pracy ustawiaj na subrowie `Praca` (od–do); `Dzien*.Czas`/`Dzien*.OdGodziny` na rootcie dnia są
|
||||
kalkulowane (read-only).
|
||||
- `DzienRCP` to **wynik weryfikacji** importu RCP (z czytników) — w normalnym przepływie nie tworzysz
|
||||
go ręcznie, lecz odczytujesz po imporcie/przeliczeniu. `DzienPracy` (ewidencja) to właściwe miejsce
|
||||
na ręczny wpis.
|
||||
- Świeży `DzienPracy` z `new DzienPracy(pracownik, data)` trzeba dodać do tabeli
|
||||
(`Module.DniPracy.AddRow(...)` lub `session.AddRow(...)`) — sam ctor go nie rejestruje.
|
||||
|
||||
### KADRY-F2 — Rejestracja wejścia/wyjścia (RCP) (★)
|
||||
|
||||
**Cel:** dodać zdarzenie wejścia/wyjścia do dnia oraz odczytać listę zdarzeń RCP danego dnia.
|
||||
|
||||
**Pola i typy (`Soneta.Kalend.WejscieWyjscie`, tabela `WejsciaWyjscia`):**
|
||||
|
||||
| Pole | Typ | Uwaga |
|
||||
|---|---|---|
|
||||
| `Dzien` | `Soneta.Kalend.DzienPracy` | właściciel (guided-parent); ustawiany przez ctor `(DzienPracy)` |
|
||||
| `Godzina` | `Soneta.Types.Time` | godzina zdarzenia (zapisywalne) |
|
||||
| `Typ` | `Soneta.Kalend.TypWejsciaWyjscia` | enum: `Niezdefiniowany`, `Wejscie`, `Wyjscie`, `WejscieSluzbowe`, `WyjscieSluzbowe`, `WejsciePrywatne`, `WyjsciePrywatne` |
|
||||
| `Operacja` | `int` | kod operacji urządzenia (zapisywalne) |
|
||||
| `Lp` | `int` | liczba porządkowa zdarzeń w dniu (bazodanowe) |
|
||||
| `DefinicjaZdarzenia` | `Soneta.Kalend.DefinicjaZdarzeniaRCP` | opcjonalna definicja zdarzenia ze słownika `DefZdarzenRCP` |
|
||||
| Kolekcja zdarzeń dnia | `DzienPracy.WeWy : LpSubTable<WejscieWyjscie>` | uporządkowana po `Lp` |
|
||||
|
||||
**Snippet:**
|
||||
|
||||
```csharp
|
||||
var kalend = session.GetKadry().Session.GetKalend();
|
||||
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
|
||||
var data = new Date(2026, 6, 1);
|
||||
|
||||
using (var t = session.Logout(editMode: true))
|
||||
{
|
||||
// Upewnij się, że istnieje dzień ewidencji (właściciel zdarzeń):
|
||||
var dp = pracownik.DniPracy[data];
|
||||
if (dp is null)
|
||||
{
|
||||
dp = session.AddRow(new DzienPracy(pracownik, data));
|
||||
kalend.DniPracy.AddRow(dp);
|
||||
}
|
||||
|
||||
// Wejście 8:00
|
||||
var we = new WejscieWyjscie(dp); // ctor wiąże zdarzenie z dniem
|
||||
kalend.WejsciaWyjscia.AddRow(we);
|
||||
we.Godzina = new Time(8, 0);
|
||||
we.Typ = TypWejsciaWyjscia.Wejscie;
|
||||
|
||||
// Wyjście 16:00
|
||||
var wy = new WejscieWyjscie(dp);
|
||||
kalend.WejsciaWyjscia.AddRow(wy);
|
||||
wy.Godzina = new Time(16, 0);
|
||||
wy.Typ = TypWejsciaWyjscia.Wyjscie;
|
||||
|
||||
t.Commit();
|
||||
}
|
||||
session.Save();
|
||||
|
||||
// --- Odczyt zdarzeń dnia ---
|
||||
var dzien = pracownik.DniPracy[data];
|
||||
if (dzien is not null)
|
||||
{
|
||||
foreach (WejscieWyjscie wewy in dzien.WeWy) // posortowane po Lp
|
||||
{
|
||||
// wewy.Godzina, wewy.Typ, wewy.Operacja
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Pułapki:**
|
||||
- `WejscieWyjscie` jest childem **`DzienPracy`**, nie `DzienRCP` — najpierw potrzebujesz dnia
|
||||
ewidencji (`pracownik.DniPracy[data]`); zdarzenia wiążesz ctorem `new WejscieWyjscie(dzienPracy)`
|
||||
i dodajesz do tabeli `kalend.WejsciaWyjscia.AddRow(...)`.
|
||||
- `Typ` to enum `TypWejsciaWyjscia` (`Wejscie`/`Wyjscie`/…), nie string ani `int`. Para
|
||||
wejście+wyjście jest podstawą wyliczenia czasu dnia z surowych zdarzeń.
|
||||
- `DefinicjaZdarzenia` jest **opcjonalna** — przy ręcznym wpisie wystarczą `Godzina` + `Typ`. Jeśli
|
||||
używasz definicji, pobierz wpis ze słownika konfiguracyjnego `kalend.DefZdarzenRCP` (nie twórz w locie).
|
||||
- `WeWy` to `LpSubTable` — kolejność zdarzeń wynika z `Lp` (nadawane automatycznie); nie ustawiaj `Lp`
|
||||
ręcznie. Do usunięcia wszystkich zdarzeń dnia (przy ponownym imporcie) służy kasowanie elementów kolekcji.
|
||||
- Surowe zdarzenia są przeliczane na czas pracy/RCP przez kalkulator i import — samo dodanie
|
||||
wejść/wyjść nie aktualizuje automatycznie `DzienRCP` (to robi przeliczenie/import RCP).
|
||||
|
||||
### KADRY-F3 — Import danych z RCP (bezpośredni i przez tabelę pośrednią)
|
||||
|
||||
**Cel:** wczytać surowe odbicia z czytników RCP i przeliczyć je na ewidencję/zweryfikowany RCP.
|
||||
**UWAGA: operacja plikowa/sieciowa — opis modelu; samego importu z pliku/urządzenia NIE testujemy.**
|
||||
|
||||
**Model danych:**
|
||||
|
||||
| Element | Lokalizacja | Typ | Uwaga |
|
||||
|---|---|---|---|
|
||||
| Tabela pośrednia (surowe odbicia) | `DzienPracy.WeWy` | `LpSubTable<Soneta.Kalend.WejscieWyjscie>` | zdarzenia we/wy (godzina, typ) — patrz KADRY-F2 |
|
||||
| Zarejestrowany RCP (zweryfikowany) | `pracownik.DniRCP[data]` | `Soneta.Kalend.DzienRCP` | wynik importu/przeliczenia |
|
||||
| Ewidencja | `pracownik.DniPracy[data]` | `Soneta.Kalend.DzienPracy` | docelowa realizacja |
|
||||
| Flaga importu | `DzienPracy.RcpOK` / `DzienRCP.RcpOK` | `bool` | „stan rekordu po imporcie z RCP" |
|
||||
| Stan weryfikacji | `DzienRCP.StanRCP` | `StanWeryfikacjiRCP` | patrz KADRY-F4 |
|
||||
|
||||
**Workery przeliczające (po wczytaniu odbić — operują na obiektach sesji):**
|
||||
|
||||
| Worker | Sygnatura | Rola |
|
||||
|---|---|---|
|
||||
| `Soneta.Kalend.ImportDniaWorker` | ctor `()`, `DzienPracy DzienPracy {get;set;}`, `void Przelicz()` | przelicza pojedynczy dzień z we/wy na czas pracy |
|
||||
| `Soneta.Kalend.RCPWeryfikatorWorker` | `Dopasuj()`, `DopasujDlaZaznaczonych()`, `Dodaj()`, `Usun()` (+ `IsVisible*`), props `rw : RCPWeryfikator`, `Strefy`, `Wybrana` | dopasowanie odbić do plan/strefy (UI) |
|
||||
|
||||
**Snippet (przeliczenie dnia z już wczytanych we/wy — bez pliku):**
|
||||
|
||||
```csharp
|
||||
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
|
||||
var dzien = pracownik.DniPracy[new Date(2026, 6, 1)]; // dzień z wpisanymi WeWy (KADRY-F2)
|
||||
if (dzien is not null)
|
||||
{
|
||||
using (var t = session.Logout(editMode: true))
|
||||
{
|
||||
new ImportDniaWorker { DzienPracy = dzien }.Przelicz(); // we/wy -> czas pracy
|
||||
t.Commit();
|
||||
}
|
||||
session.Save();
|
||||
}
|
||||
```
|
||||
|
||||
**Pułapki / wykonalność:**
|
||||
- **Sam import z pliku/urządzenia (czytnik, sieć, format) jest poza zakresem testu** — wymaga
|
||||
zewnętrznego źródła (plik/serwis), brak czystego API w tym kontrakcie.
|
||||
- **Testowalny fragment**: przygotowanie tabeli pośredniej `DzienPracy.WeWy` (ctor `WejscieWyjscie(dp)`,
|
||||
patrz KADRY-F2) + `ImportDniaWorker.Przelicz()` — to przelicza już-wczytane odbicia bez I/O.
|
||||
- `RCPWeryfikatorWorker` jest mocno UI (metody `IsVisible*`, `Strefy`/`Wybrana`) — to dopasowanie
|
||||
ręczne; nie wywoływać z kodu biznesowego.
|
||||
- `DzienRCP` powstaje z importu/przeliczenia — w teście nie twórz go „z palca"; odczytuj po `Przelicz()`.
|
||||
|
||||
---
|
||||
|
||||
### KADRY-F4 — Weryfikacja i korekta danych RCP (★ testowalne)
|
||||
|
||||
**Cel:** odczytać i skorygować zweryfikowany rekord RCP — zmienić stan weryfikacji oraz poprawić
|
||||
godziny pracy / opisać błędy i uwagi.
|
||||
|
||||
**Pola `Soneta.Kalend.DzienRCP` (tabela `DniRCP`, child `Pracownik`):**
|
||||
|
||||
| Pole | Typ | Rodzaj | Uwaga |
|
||||
|---|---|---|---|
|
||||
| `Data` | `Soneta.Types.Date` | bazodanowe | data dnia (ctor) |
|
||||
| `Pracownik` | `Soneta.Kadry.Pracownik` | bazodanowe, guided-parent | właściciel |
|
||||
| `Praca` | `Soneta.Kalend.CzasPracy` | bazodanowe | `Praca.OdGodziny`/`Praca.DoGodziny`/`Praca.Czas : Time` (zapisywalne) |
|
||||
| `Czas`, `OdGodziny` | `Soneta.Types.Time` | kalkulowane | read-only (z `Praca`) |
|
||||
| `StanRCP` | `Soneta.Kalend.StanWeryfikacjiRCP` | bazodanowe | stan weryfikacji (zapisywalne) |
|
||||
| `RcpOK` | `bool` | bazodanowe | stan rekordu po imporcie (zapisywalne) |
|
||||
| `Uwagi` | `Soneta.Business.MemoText` | bazodanowe | uwagi do weryfikacji |
|
||||
| `Bledy` | `Soneta.Business.MemoText` | bazodanowe | opis błędów |
|
||||
| `Strefy` | `SubTable<Soneta.Kalend.StrefaRCP>` | | strefy zarejestrowane |
|
||||
| `StrefyOrg` | `Soneta.Business.MemoText` | bazodanowe | strefy źródłowe (org.) |
|
||||
|
||||
**`Soneta.Kalend.StanWeryfikacjiRCP` (enum):** `DoWeryfikacji`, `WymagaWeryfikacji`,
|
||||
`PrzekazanyDoWyjaśnienia`, `DoZatwierdzenia`, `Modyfikowany`, `Naniesiony`, `Poprawny`, `Błędny`,
|
||||
`Wszystkie`.
|
||||
|
||||
**Snippet (korekta godzin + zmiana stanu):**
|
||||
|
||||
```csharp
|
||||
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
|
||||
var dzienRcp = pracownik.DniRCP[new Date(2026, 6, 1)]; // DzienRCP lub null
|
||||
if (dzienRcp is not null)
|
||||
{
|
||||
using (var t = session.Logout(editMode: true))
|
||||
{
|
||||
dzienRcp.Praca.OdGodziny = new Time(8, 0); // korekta na subrowie Praca
|
||||
dzienRcp.Praca.DoGodziny = new Time(16, 0);
|
||||
dzienRcp.StanRCP = StanWeryfikacjiRCP.Poprawny; // zatwierdzenie weryfikacji
|
||||
dzienRcp.Uwagi = (MemoText)"Skorygowano wyjście";
|
||||
t.Commit();
|
||||
}
|
||||
session.Save();
|
||||
}
|
||||
```
|
||||
|
||||
**Pułapki:**
|
||||
- `DniRCP` jest **typowane** (`DateSubTable<DzienRCP>`) — indeksator `[Date]` zwraca `DzienRCP`/`null`;
|
||||
do zakresu użyj `[FromTo]`. Nie iteruj kolekcji w poszukiwaniu dnia.
|
||||
- Godziny koryguj na **subrowie `Praca`** (`Praca.OdGodziny`/`DoGodziny`); `DzienRCP.Czas`/`OdGodziny`
|
||||
na rootcie są kalkulowane (read-only).
|
||||
- `StanRCP` to enum `StanWeryfikacjiRCP` — nie string. Zmiana stanu może podlegać weryfikatorom.
|
||||
- W Demo `DzienRCP` istnieje tylko gdy był import/przeliczenie — test korekty zakłada istniejący dzień
|
||||
(sprawdzaj `is not null`), nie twórz `DzienRCP` ręcznie.
|
||||
|
||||
---
|
||||
|
||||
### KADRY-F5 — Rozliczenie pracy hybrydowej / aktualizacja podzielników na podstawie pracy hybrydowej
|
||||
|
||||
**Cel:** rozliczyć czas pracy hybrydowej (podział na strefy: stacjonarna / praca zdalna / zdalna
|
||||
okazjonalna) i zaktualizować podzielniki (elementy rozliczenia czasu pracy / strefy dnia), na
|
||||
podstawie których naliczane są składniki płacowe i koszty.
|
||||
|
||||
**Model danych (publiczny kontrakt):**
|
||||
|
||||
| Element | Lokalizacja | Typ | Uwaga |
|
||||
|---|---|---|---|
|
||||
| Strefy pracy dnia | `DzienPracy.Strefy` | `SubTable<Soneta.Kalend.StrefaPracy>` | podział dnia na strefy |
|
||||
| Strefa pracy | `Soneta.Kalend.StrefaPracy` (ctor `(DzienPracy dzien)`) | — | `Definicja : DefinicjaStrefy`, `CzasRozliczany : Time`, `OdGodziny`/`Czas` (kalk.) |
|
||||
| Definicja strefy | `Soneta.Kalend.DefinicjaStrefy` | konfiguracja | `Typ : TypStrefy`, `Wchodzi`, `Rozliczana`; stałe `Praca_Zdalna`, `PracaZdalnaOkazjonalna : Guid` |
|
||||
| Dokumenty rozliczenia | `pracownik.RozliczeniaCzasuPracy` | `SubTable<Soneta.Kalend.RozliczenieCzasuPracy>` | dokumenty rozliczenia czasu (podzielniki) |
|
||||
| Elementy rozliczenia | `pracownik.ElementyRozliczeniaCzasuPracy` | `SubTable<Soneta.Kalend.ElementRozliczeniaCzasuPracy>` | pozycje podzielnika |
|
||||
| Dokument rozliczenia | `Soneta.Kalend.RozliczenieCzasuPracy` (ctor `(Pracownik, DefinicjaRozliczeniaCzasuPracy)`) | root | `Data`, `Seria`, `Stan : StanyRozliczeniaCzasuPracy` |
|
||||
| Pozycja rozliczenia | `Soneta.Kalend.ElementRozliczeniaCzasuPracy` (ctor `(RozliczenieCzasuPracy dokument)`) | child | `Definicja : DefinicjaStrefy`, `Data`, `OdGodziny`, `Czas`, `CzasPozostały`/`CzasDostępny`/`Zrealizowane` (kalk.) |
|
||||
|
||||
**`Soneta.Kalend.TypStrefy` (enum):** `NieWplywa`, `Zwieksza`, `Zmniejsza`.
|
||||
|
||||
**Workery (UI/extendery — praca zdalna/hybrydowa):**
|
||||
- `Soneta.Kalend.StrefaPracy.PracaZdalnaWorker` (`Strefa : StrefaPracy`) — oznaczenie strefy jako
|
||||
praca zdalna.
|
||||
- `Soneta.Kadry.PracaZdalna.DzienStrefaExtWorker`, `ElementRozliczeniaCzasuPracyExtWorker`,
|
||||
`DzienZestawienieExtender` — extendery zestawień/dni dla pracy zdalnej.
|
||||
|
||||
**Snippet (odczyt rozkładu na strefy + dokument rozliczenia):**
|
||||
|
||||
```csharp
|
||||
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
|
||||
|
||||
// Odczyt podziału dnia na strefy (stacjonarna / zdalna):
|
||||
var dzien = pracownik.DniPracy[new Date(2026, 6, 1)];
|
||||
if (dzien is not null)
|
||||
{
|
||||
foreach (StrefaPracy s in dzien.Strefy)
|
||||
{
|
||||
DefinicjaStrefy def = s.Definicja; // strefa (np. praca zdalna)
|
||||
Time rozliczany = s.CzasRozliczany; // czas rozliczany w strefie
|
||||
}
|
||||
}
|
||||
|
||||
// Pozycje podzielnika (elementy rozliczenia czasu pracy):
|
||||
foreach (ElementRozliczeniaCzasuPracy el in pracownik.ElementyRozliczeniaCzasuPracy)
|
||||
{
|
||||
DefinicjaStrefy def = el.Definicja;
|
||||
Time czas = el.Czas;
|
||||
}
|
||||
```
|
||||
|
||||
**Pułapki / wykonalność:**
|
||||
- Rozkład pracy hybrydowej to **strefy** (`DzienPracy.Strefy` / `DefinicjaStrefy` z flagą zdalna) +
|
||||
dokument `RozliczenieCzasuPracy` z pozycjami `ElementRozliczeniaCzasuPracy` (podzielniki).
|
||||
- `RozliczenieCzasuPracy` to **root** (ctor `(Pracownik, DefinicjaRozliczeniaCzasuPracy)`) — utworzenie
|
||||
wymaga istniejącej `DefinicjaRozliczeniaCzasuPracy` z konfiguracji; pozycje ctorem
|
||||
`new ElementRozliczeniaCzasuPracy(dokument)`. Czysty odczyt jest bezpieczny i bez transakcji.
|
||||
- Aktualizacja podzielników na podstawie pracy hybrydowej przebiega **głównie przez extendery/UI**
|
||||
(`DzienStrefaExtWorker`, `ElementRozliczeniaCzasuPracyExtWorker`, `PracaZdalnaWorker`) zależne od
|
||||
`Context`/wniosków e-pracownika — brak prostego, czystego API operacyjnego.
|
||||
- Wymaga skonfigurowanych `DefinicjaStrefy` (Praca_Zdalna / PracaZdalnaOkazjonalna) — w Demo strefy
|
||||
mogą nie być włączone, co czyni budowę rozliczenia kruchą do testu (raczej odczyt niż zapis).
|
||||
|
||||
Reference in New Issue
Block a user