28 KiB
KADRY02 — Etat — zatrudnienie etatowe
Wspólne fakty o typie, podstawowe typy i szablon wzorca: ../kadry.md.
KADRY-B1 — Definiowanie etatu (umowa o pracę) (★)
Cel: ustalić warunki zatrudnienia etatowego pracownika — rodzaj umowy o pracę, okres, daty
zawarcia/rozpoczęcia pracy, stanowisko, jednostkę organizacyjną oraz stawkę zaszeregowania
(wymiar etatu, rodzaj/typ stawki, kwota). Warunki etatu są historyczne: siedzą w polu
Etat konkretnego zapisu PracHistoria. Etat ustawiamy albo na świeżo utworzonym pracowniku
(pracownik.Last.Etat, patrz KADRY-A1), albo na nowym zapisie historii „od daty" (patrz KADRY-A14).
Gdzie leżą pola — PracHistoria.Etat: Soneta.Kadry.Etat (subrow zapisu historii):
| Dana | Pole / typ | Uwaga |
|---|---|---|
| Rodzaj umowy o pracę | Etat.TypUmowy: Soneta.Kadry.TypUmowyOPrace |
enum: NaCzasNieokreślony, NaOkresPróbny, NaCzasOkreślony, NaOkresZastępstwa, DoDniaPorodu, NaCzasWykonywniaPracy, … (Brak = 0 = nie dotyczy) |
| Okres etatu (od–do) | Etat.Okres: Soneta.Types.FromTo |
okres obowiązywania warunków zatrudnienia |
| Data zawarcia umowy | Etat.DataZawarcia: Soneta.Types.Date |
data podpisania umowy |
| Data rozpoczęcia pracy | Etat.DataRozpPracy: Soneta.Types.Date |
data faktycznego rozpoczęcia |
| Stanowisko (opis tekstowy) | Etat.Stanowisko: string |
wymagane dla etatu (weryfikator przy Save()) |
| Jednostka organizacyjna (wydział) | Etat.Wydzial: Soneta.Kadry.Wydzial |
wymagane dla etatu; pobierz istniejący wydział, korzeń struktury: session.GetKadry().Wydzialy.Firma |
| Oddział firmy | Etat.Oddzial: Soneta.Core.OddzialFirmy |
opcjonalny oddział |
| Miejsce wykonywania pracy | Etat.MiejscePracy: string |
tekst |
| Podstawa stosunku pracy | Etat.Podstawa: Soneta.Kadry.StosPracyNaPodstawie |
enum |
Stawka — subrow Etat.Zaszeregowanie: Soneta.Kadry.Zaszeregowanie:
| Dana | Pole / typ | Uwaga |
|---|---|---|
| Rodzaj stawki | Zaszeregowanie.RodzajStawki: Soneta.Kadry.RodzajStawkiZaszeregowania |
enum: Godzinowa = 0, Miesieczna = 1, DochodDeklarowany = 2 |
| Typ stawki | Zaszeregowanie.TypStawki: Soneta.Kadry.TypStawkiZaszeregowania |
enum: Dowolna = 0, Minimalna = 1, ZZakresu = 2, WgWskaźnika = 3, Nieokreślona = 10 |
| Wymiar etatu (ułamek) | Zaszeregowanie.Wymiar: Soneta.Types.Fraction |
Fraction.One = pełny etat; new Fraction(1, 2) = ½ etatu |
| Kwota stawki | Zaszeregowanie.Stawka: Soneta.Types.Currency |
kwota brutto (miesięczna lub godzinowa wg RodzajStawki) |
| Grupa zaszeregowania | Zaszeregowanie.Grupa: Soneta.Kadry.GrupaZaszeregowania |
rekord słownika (opcjonalny) |
| Definicja elementu wynagrodzenia | Zaszeregowanie.Element: Soneta.Place.DefinicjaElementu |
element płacowy wiązany ze stawką (opcjonalny) |
Pułapki:
- Kolejność ma znaczenie —
Etat.Okresustaw jako PIERWSZE. Na świeżo utworzonym pracowniku (lub świeżym zapisie historii) cały subrowEtatjest w trybie tylko-do-odczytu, dopóki nie ustawiszEtat.Okres(zakres zatrudnienia). Próba ustawieniaEtat.TypUmowy,Etat.PodstawaczyZaszeregowanie.RodzajStawki/WymiarprzedEtat.OkresrzucaSoneta.Business.ColReadOnlyException(np. „'Etat.Typ umowy' — pole w trybie 'tylko do odczytu'"). Po ustawieniuEtat.Okrespozostałe pola (w tymZaszeregowanie.Wymiar) są zapisywalne — kolejność wśród nich nie ma już znaczenia. - Pola wymagane dla etatu: po ustawieniu
Etat.Okres(pracownik staje się etatowy)Save()wymagaEtat.WydzialorazEtat.Stanowisko— bez nich zapis rzuca wyjątek weryfikatora. Etatto subrow zapisuPracHistoria— modyfikujesz jego pola (Last.Etat.Okres = …), nie przypisujesz całego obiektuEtat.Zaszeregowanieto z kolei subrowEtat— analogicznie modyfikujesz pola (Last.Etat.Zaszeregowanie.Stawka = …).Etat.WymiariEtat.TypStawkiistnieją także na poziomieEtat(delegaty/odczyt) — kanonicznie ustawiamy je naEtat.Zaszeregowanie(Zaszeregowanie.Wymiar,Zaszeregowanie.RodzajStawki,Zaszeregowanie.TypStawki), bo to one są polami bazodanowymi tej struktury.Etat.WydzialiEtat.Oddzialto referencje do istniejących rekordów — nie twórz „w locie"; korzeń struktury organizacyjnej pobierzesz przezsession.GetKadry().Wydzialy.Firma.- Zmiana warunków etatu od konkretnego dnia to nowy zapis historii (
Historia.Update(date)+PracHistorie.AddRow, patrz KADRY-A14), a nie nadpisanie bieżącego zapisu (to byłaby korekta całego okresu). TypUmowyOPraceto enum, nie string;Okres/DataZawarcia/DataRozpPracyto typy biznesoweFromTo/Date, nieDateTime(safe-code §10.1).
Snippet:
var kadry = session.GetKadry();
using (var t = session.Logout(editMode: true))
{
// Nowy pracownik (KADRY-A1) — AddRow tworzy pierwszy zapis historii (Last) + kalendarz.
var pracownik = session.AddRow(new PracownikFirmy());
pracownik.Kod = "555";
pracownik.Last.Nazwisko = "Kowalska";
pracownik.Last.Imie = "Gabriela";
// Warunki etatu — na Etat bieżącego (pierwszego) zapisu historii.
// KLUCZOWE: Etat.Okres MUSI być pierwszy — odblokowuje (z trybu read-only) resztę pól Etat.
var etat = pracownik.Last.Etat;
etat.Okres = new FromTo(new Date(2026, 1, 1), Date.MaxValue); // 1) NAJPIERW okres
etat.TypUmowy = TypUmowyOPrace.NaCzasNieokreślony;
etat.DataZawarcia = new Date(2025, 12, 20);
etat.DataRozpPracy = new Date(2026, 1, 1);
etat.Stanowisko = "Specjalista"; // wymagane dla etatu
etat.Wydzial = kadry.Wydzialy.Firma; // wymagane dla etatu (korzeń struktury)
// Stawka zaszeregowania (po ustawieniu Etat.Okres pola są zapisywalne):
var z = etat.Zaszeregowanie;
z.RodzajStawki = RodzajStawkiZaszeregowania.Miesieczna;
z.TypStawki = TypStawkiZaszeregowania.Dowolna;
z.Wymiar = Fraction.One; // pełny etat
z.Stawka = (Currency)6000m; // kwota brutto miesięcznie
t.Commit();
}
session.Save();
Zmiany warunków zatrudnienia (KADRY-B2–KADRY-B7). Warunki zatrudnienia etatowego siedzą w polu
PracHistoria.Etat: Soneta.Kadry.Etat(subrow zapisu historii).Etatjest historyczny wraz z całymPracHistoria— okres obowiązywania warunków trzymaEtat.Okres: FromTo, a okres zapisu historiiPracHistoria.Aktualnosc. Zmiana warunków „od dnia" to nowy zapis historii (Historia.Update(date)+PracHistorie.AddRow, wzorzec z KADRY-A14) — modyfikacja bieżącego zapisu byłaby korektą całego jego okresu.Bramka edycji etatu (KADRY-B1). Na świeżym zapisie cały subrow
Etatjest tylko-do-odczytu, dopóki nie ustawiszEtat.Okres— ustaw go PIERWSZY, inaczej dotknięcieTypUmowy/Zaszeregowanie.*rzucaSoneta.Business.ColReadOnlyException. Pola wymagane przy zapisie etatu:Etat.WydzialorazEtat.Stanowisko. PoUpdate(date)klon ma już ustawionyEtat.Okres(sklonowany ze starego zapisu) — zwykle nie trzeba go ustawiać ponownie, ale jeśli zmieniasz okres etatu, rób to jako pierwsze.
KADRY-B2 — Zmiana warunków zatrudnienia (aneks)
Cel: zarejestrować aneks do umowy o pracę — zmianę warunków obowiązującą od wskazanego dnia (np. zmiana stanowiska, miejsca pracy, wymiaru, jednostki organizacyjnej). Realizuje się przez nowy zapis historyczny etatu „od daty", nie przez nadpisanie bieżącego.
Pola Etat (subrow PracHistoria.Etat: Soneta.Kadry.Etat):
| Dana | Pole / typ | Uwaga |
|---|---|---|
| Okres etatu (od–do) | Etat.Okres: Soneta.Types.FromTo |
okres obowiązywania warunków; po Update zwykle już ustawiony |
| Rodzaj umowy o pracę | Etat.TypUmowy: Soneta.Kadry.TypUmowyOPrace |
enum |
| Data zawarcia aneksu | Etat.DataZawarcia: Soneta.Types.Date |
data podpisania |
| Stanowisko (opis) | Etat.Stanowisko: string |
wymagane dla etatu |
| Jednostka organizacyjna | Etat.Wydzial: Soneta.Kadry.Wydzial |
wymagane dla etatu; referencja (session.GetKadry().Wydzialy.Firma) |
| Oddział firmy | Etat.Oddzial: Soneta.Core.OddzialFirmy |
opcjonalny |
| Miejsce wykonywania pracy | Etat.MiejscePracy: string |
tekst |
| Podstawa stosunku pracy | Etat.Podstawa: Soneta.Kadry.StosPracyNaPodstawie |
enum |
| Forma organizacji pracy | Etat.FormaOrganizacjiPracy: Soneta.Kadry.FormaOrganizacjiPracy |
enum |
Wymiar / stawka (na Zaszeregowanie) |
Etat.Zaszeregowanie.Wymiar: Fraction, Etat.Zaszeregowanie.Stawka: Currency |
patrz KADRY-B3 |
Snippet:
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
var odDnia = new Date(2026, 7, 1);
using (var t = session.Logout(editMode: true))
{
// Nowy zapis historii „od daty" — klonuje zapis aktualny na `odDnia`, skraca stary do dnia
// poprzedniego i zwraca nowy klon (okres od `odDnia`). Klon MUSI trafić do tabeli zapisów.
var nowy = (PracHistoria)pracownik.Historia.Update(odDnia);
pracownik.Module.PracHistorie.AddRow(nowy);
// Etat na klonie ma już Okres (sklonowany) — pola Etat są zapisywalne. Aneksowane warunki:
var etat = nowy.Etat;
etat.Stanowisko = "Starszy specjalista";
etat.MiejscePracy = "Oddział Kraków";
etat.DataZawarcia = new Date(2026, 6, 20);
etat.Wydzial = session.GetKadry().Wydzialy.Firma; // wymagane (referencja)
t.Commit();
}
session.Save();
Pułapki:
Update(date)+PracHistorie.AddRow(nowy)to nierozłączna para — samUpdatezwraca odpięty klon; bezAddRowzmiana nie zostanie zapisana.Update(date)rzucaHistorySubTable.DateDuplicateException, gdy nadatejuż zaczyna się zapis (Aktualnosc.From == date) — wtedy modyfikuj istniejący zapis (pracownik[date]).- Nie ustawiaj
PracHistoria.Aktualnoscani (zwykle)Etat.Okresręcznie — zarządza nimi historia. Jeśli aneks zmienia długość okresu etatu, ustawEtat.Okresprzed pozostałymi polami (bramka KADRY-B1). Etatto subrow — modyfikuj jego pola, nie przypisuj całego obiektu.
KADRY-B3 — Przeszeregowanie (zmiana stawki / grupy zaszeregowania)
Cel: zmienić wynagrodzenie zasadnicze — stawkę i/lub grupę zaszeregowania, od wskazanego dnia.
Pola Etat.Zaszeregowanie: Soneta.Kadry.Zaszeregowanie (subrow Etat):
| Dana | Pole / typ | Uwaga |
|---|---|---|
| Rodzaj stawki | Zaszeregowanie.RodzajStawki: Soneta.Kadry.RodzajStawkiZaszeregowania |
enum: Godzinowa = 0, Miesieczna = 1, DochodDeklarowany = 2 |
| Typ stawki | Zaszeregowanie.TypStawki: Soneta.Kadry.TypStawkiZaszeregowania |
enum: Dowolna, Minimalna, ZZakresu, WgWskaźnika, Nieokreślona |
| Kwota stawki | Zaszeregowanie.Stawka: Soneta.Types.Currency |
brutto (miesięczna/godzinowa wg RodzajStawki) |
| Wymiar etatu | Zaszeregowanie.Wymiar: Soneta.Types.Fraction |
Fraction.One = pełny etat |
| Grupa zaszeregowania | Etat.Grupa: Soneta.Kadry.GrupaZaszeregowania |
leży na Etat, nie na Zaszeregowanie; referencja do słownika session.GetKadry().GrupyZaszer (opcjonalna) |
| Element wynagrodzenia | Zaszeregowanie.Element: Soneta.Place.DefinicjaElementu |
element płacowy wiązany ze stawką (opcjonalny) |
| Wskaźnik (wg wskaźnika) | Zaszeregowanie.WskaznikNazwa: string, Zaszeregowanie.WskaznikKrotnosc: double |
gdy TypStawki = WgWskaźnika |
Snippet (bezpośrednia zmiana, „od daty"):
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
var odDnia = new Date(2026, 7, 1);
using (var t = session.Logout(editMode: true))
{
var nowy = (PracHistoria)pracownik.Historia.Update(odDnia);
pracownik.Module.PracHistorie.AddRow(nowy);
var etat = nowy.Etat; // subrow zapisu; Okres ustawiony przez Update
etat.Zaszeregowanie.Stawka = (Currency)7200m; // podwyżka stawki zasadniczej
// etat.Grupa = session.GetKadry().GrupyZaszer... // ewentualna zmiana grupy (leży na Etat, nie na Zaszeregowanie)
t.Commit();
}
session.Save();
Worker platformy (alternatywa seryjna): przeszeregowania realizuje moduł
Soneta.Przeszeregowania — dokument Soneta.Kadry.Przeszeregowanie z elementami
ElementPrzeszeregowania (m.in. Soneta.Kadry.ZmianaStawki), wykonywany czynnością
ZmianaStawkiWorker (zmiana kwoty / procentowa / grupa) dla zaznaczonej grupy pracowników. Element
ZmianaStawki ma pola Grupa: GrupaZaszeregowania, Kwota: Currency i zapisuje wynik do
Etat.Zaszeregowanie właściwego zapisu historii.
Pułapki:
Wymiar/Stawka/RodzajStawkina świeżym zapisie są zapisywalne dopiero poEtat.Okres(bramka KADRY-B1); poUpdateokres jest już sklonowany, więc pola są zapisywalne.StawkatoCurrency(niedecimal),WymiartoFraction(niedouble) — safe-code §10.1.Etat.Grupa/Zaszeregowanie.Elementto referencje do istniejących rekordów — nie twórz „w locie". Uwaga:Grupajest polemEtat(pobierasz ze słownikasession.GetKadry().GrupyZaszer), a nie polemZaszeregowanie—Zaszeregowanienie ma propertyGrupa.- Kanonicznie ustawiasz pola stawki na
Etat.Zaszeregowanie(pola bazodanowe), nie na delegatachEtat.Wymiar/Etat.TypStawki.
KADRY-B4 — Rozwiązanie / wygaśnięcie umowy o pracę
Cel: zakończyć stosunek pracy z dniem rozwiązania — ustawić datę końca okresu etatu, dane wypowiedzenia oraz przyczynę/kod rozwiązania (na potrzeby świadectwa pracy i deklaracji ZUS).
Wzorzec (zgodny z czynnością „Zwolnij zaznaczonych pracowników"):
- skróć
Etat.Okres.Todo dnia rozwiązania (na bieżącym zapisie albo na nowym zapisie „od daty"), - ustaw dane wypowiedzenia (
Etat.OkresWypowiedzenia.*) i przyczynę (Etat.RozwiazanieUmowy.*), - opcjonalnie oznacz
Etat.PracownikZwolniony = truei wyrejestruj z ubezpieczeń.
Pola — Etat.OkresWypowiedzenia: Soneta.Kadry.OkresWypowiedzenia (subrow):
| Dana | Pole / typ | Uwaga |
|---|---|---|
| Data złożenia wypowiedzenia | OkresWypowiedzenia.DataZlozenia: Soneta.Types.Date |
data wręczenia wypowiedzenia |
| Długość — dni / tygodnie / miesiące | OkresWypowiedzenia.Dni: int, .Tygodnie: int, .Miesiace: int |
okres wypowiedzenia |
| Data upływu | OkresWypowiedzenia.Uplywa: Soneta.Types.Date |
data upływu okresu wypowiedzenia |
| Skrócony | OkresWypowiedzenia.Skrocony: bool |
skrócony okres wypowiedzenia |
| Zwolnienie z obowiązku pracy od | OkresWypowiedzenia.ZwolnionyZObowiazkuPracyOd: Date |
|
| Data rozwiązania umowy (odczyt) | OkresWypowiedzenia.DataRozwiązaniaUmowy: Date |
kalkulowane |
Pola — Etat.RozwiazanieUmowy: Soneta.Kadry.RozwiazanieUmowy (subrow):
| Dana | Pole / typ | Uwaga |
|---|---|---|
| Przyczyna rozwiązania | RozwiazanieUmowy.PrzyczynaRozwUmowy: Soneta.Kadry.PrzyczynaRozwUmowy |
referencja do słownika session.GetKadry().PrzyczRozwUmow (indeks WgNazwy lub iteracja; brak indeksera WgKodu); rekord ma Typ: TypPrzyczynyRozwUmowy |
| Opis przyczyny | RozwiazanieUmowy.PrzyczynaRozwUmowyOpis: string |
tekst |
| Podstawa prawna | RozwiazanieUmowy.PodstawaPrawna: Soneta.Kadry.KodPodstawyPrawnejZwolnienia |
enum (tryb rozwiązania: za wypowiedzeniem, porozumienie, wygaśnięcie itd.) |
| Kod zwolnienia (ZUS) | RozwiazanieUmowy.KodZwolnienia: Soneta.Kadry.KodZwolnienia |
enum (kod do ZUS RA/świadectwa) |
| Inicjatywa | RozwiazanieUmowy.Inicjatywa: Soneta.Kadry.KodInicjatywyZwolnienia |
enum (pracodawca/pracownik) |
| Za odszkodowaniem | RozwiazanieUmowy.ZaOdszkodowaniem: bool |
|
| Pracownik zwolniony (flaga) | Etat.PracownikZwolniony: bool |
znacznik zakończenia |
Snippet:
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
var dataRozwiazania = new Date(2026, 9, 30);
using (var t = session.Logout(editMode: true))
{
var ph = pracownik.Last;
var etat = ph.Etat;
// 1) skrócenie okresu etatu do dnia rozwiązania
etat.Okres = new FromTo(etat.Okres.From, dataRozwiazania);
// 2) dane wypowiedzenia
etat.OkresWypowiedzenia.DataZlozenia = new Date(2026, 8, 31);
etat.OkresWypowiedzenia.Miesiace = 1;
// 3) przyczyna / tryb rozwiązania
// PrzyczynaRozwUmowy to rekord słownika — pobierz po nazwie (WgNazwy) albo iteracją (brak WgKodu):
etat.RozwiazanieUmowy.PrzyczynaRozwUmowy = session.GetKadry().PrzyczRozwUmow.WgNazwy["Wypowiedzenie przez pracownika"]; // referencja
// PodstawaPrawna to enum kodów: NieDotyczy, _400.._463, _550 (kody GUS/ZUS) — wybierz właściwy kod:
etat.RozwiazanieUmowy.PodstawaPrawna = KodPodstawyPrawnejZwolnienia._400;
etat.RozwiazanieUmowy.Inicjatywa = KodInicjatywyZwolnienia.Pracownik;
etat.PracownikZwolniony = true; // znacznik zakończenia zatrudnienia
t.Commit();
}
session.Save();
Pułapki:
- Wygaśnięcie vs rozwiązanie rozróżnia
PodstawaPrawna(enum trybu) orazKodZwolnienia— to one trafiają do świadectwa pracy i deklaracji ZUS. PrzyczynaRozwUmowyto rekord słownika (referencja), nie enum — pobierz istniejący wpis zsession.GetKadry().PrzyczRozwUmow(indeksWgNazwylub iteracja — słownik nie ma indekseraWgKodu). Pomyłka:RozwiazanieUmowy.PrzyczynaRozwUmowy(referencja) ≠PrzyczynaRozwUmowy.Typ(enumTypPrzyczynyRozwUmowyna rekordzie słownika).KodPodstawyPrawnejZwolnieniato enum kodów GUS/ZUS o wartościachNieDotyczy,_400.._463,_550(nazwy z prefiksem_) — nie ma wartości opisowych typuRozwiazanieZaWypowiedzeniemPrzezPracownika.KodInicjatywyZwolnienia:NieDotyczy,Pracownik,Pracodawca.- Skrócenie
Etat.Okres.Tozmienia warunki w całym bieżącym okresie zapisu. Jeśli rozwiązanie ma obowiązywać od konkretnego dnia z zachowaniem poprzedniego okresu, użyj nowego zapisu (Historia.Update(data)+PracHistorie.AddRow), a zmiany rób na klonie. - Wyrejestrowanie z ubezpieczeń (
IUbezpieczenie.Wyrejestrowany/datyDo) to osobny krok — patrz KADRY-A7. Okres/DataZlozenia/UplywatoFromTo/Date, nieDateTime.
KADRY-B5 — Obniżenie / przywrócenie wymiaru etatu
Cel: czasowo obniżyć wymiar etatu i stawkę (operacje typu COVID / seryjne), a następnie
przywrócić warunki. Stan obniżenia jest odczytowo widoczny w subrowie
Etat.ObnizenieEtatu: Soneta.Kadry.ObniżenieWymiaruEtatu (delegat do zapisu historii etatu).
Ważne (zweryfikowane na DLL): subrow
ObniżenieWymiaruEtatujest w całości tylko-do-odczytu — wszystkie jego property (Wymiar,Stawka,RodzajStawki,TypStawki,Element,Kalendarz,Info) mająCanWrite == false, a klasa nie udostępnia publicznej metodySave(...). Z poziomu kodu biznesowego nie da się ustawić tych pól ani „utrwalić" obniżenia przez ten subrow. Pełny zapis stanu obniżenia (z metadanymiObniżenieWymiaruEtatuInfo) realizują workery platformy. W zwykłym kodzie obniżenie sprowadzasz do ustawienia docelowegoEtat.Zaszeregowanie.Wymiar(i ewentualnieStawka) na nowym zapisie „od daty".
Pola odczytowe — Etat.ObnizenieEtatu: Soneta.Kadry.ObniżenieWymiaruEtatu (subrow, read-only):
| Dana | Pole / typ | Uwaga |
|---|---|---|
| Obniżony wymiar etatu | ObnizenieEtatu.Wymiar: Soneta.Types.Fraction |
read-only |
| Obniżona stawka | ObnizenieEtatu.Stawka: Soneta.Types.Currency |
read-only |
| Rodzaj / typ stawki | ObnizenieEtatu.RodzajStawki, .TypStawki |
enumy, read-only |
| Kalendarz | ObnizenieEtatu.Kalendarz: Soneta.Kalend.KalendarzBase |
referencja, read-only |
| Element wynagrodzenia | ObnizenieEtatu.Element: Soneta.Place.DefinicjaElementu |
referencja, read-only |
| Zakres obniżenia (przełącznik) | ObnizenieEtatu.Info: Soneta.Kadry.ObniżenieWymiaruEtatuInfo |
enum (Brak/Wymiar/Stawka/Zaszeregowanie/Kalendarz/…), read-only |
Snippet (obniżenie wymiaru „od daty" w kodzie biznesowym):
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
var odDnia = new Date(2026, 7, 1);
using (var t = session.Logout(editMode: true))
{
var ph = (PracHistoria)pracownik.Historia.Update(odDnia);
pracownik.Module.PracHistorie.AddRow(ph);
// Subrow ObnizenieEtatu jest read-only — NIE ustawiamy go bezpośrednio.
// Docelowy wymiar po obniżeniu utrwalamy na Etat.Zaszeregowanie.Wymiar (pole zapisywalne):
ph.Etat.Zaszeregowanie.Wymiar = new Fraction(4, 5); // np. obniżenie do 4/5 etatu
t.Commit();
}
session.Save();
Workery platformy (seryjne, na zaznaczonych pracownikach, tabela Pracownicy):
ObniżWymiarEtatuWorker (obniżenie: proporcjonalnie / do / o), ZmianaStawkiZaszeregowaniaWorker,
ZmianaKalendarzaWorker, PrzywróćWarunkiZatrudnieniaWorker (przywrócenie warunków sprzed
obniżenia). To one zakładają nowy zapis historii „od daty" i zapisują pełny stan obniżenia
(ObniżenieWymiaruEtatuInfo), którego nie da się ustawić przez publiczny kontrakt subrowa.
Pułapki:
Etat.ObnizenieEtatuto odczytowy delegat do zapisu historii etatu — wszystkie property są read-only i klasa nie ma metodySave(...). W kodzie biznesowym obniżenie wymiaru realizujesz ustawiającEtat.Zaszeregowanie.Wymiar(iStawka) na nowym zapisie; pełny zapis stanu obniżenia zObniżenieWymiaruEtatuInfozostaw workerom platformy.- Operacja jest „od daty" — zawsze przez nowy zapis (
Update+AddRow); inaczej zmienisz wymiar wstecz w całym bieżącym okresie. - Przywrócenie warunków to osobna operacja (
PrzywróćWarunkiZatrudnieniaWorker) — nie polega na usuwaniu obniżenia, lecz na nowym zapisie z przywróconym wymiarem.
KADRY-B6 — Podzielniki kosztów (rozdział kosztów wynagrodzenia)
Cel: rozdzielić koszty wynagrodzenia pracownika na wydziały/projekty/centra kosztów wg
współczynników. Struktura: Pracownik jako źródło podzielnika →
pracownik.Podzielniki: SubTable<Soneta.Core.PodzielnikKosztow> → każdy podzielnik ma historię
PodzielnikKosztow.Historia: HistorySubTable<HistoriaPodzielnika> → a zapis historii ma kolekcję
HistoriaPodzielnika.Elementy: SubTable<Soneta.Core.ElementPodzielnika> (poszczególne udziały).
Uwaga:
Pracownik.ElementyPodzielnika: SubTable<ElementPodzielnika>to widok zbiorczy elementów ze wszystkich podzielników pracownika (do odczytu). Tworzysz elementy na konkretnym zapisieHistoriaPodzielnika, nie przez tę kolekcję.
Tworzenie obiektów (konstruktory + AddRow):
| Obiekt | Konstruktor | Tabela / AddRow |
|---|---|---|
| Podzielnik | new PodzielnikKosztow(pracownik) (pracownik jako IZrodloPodzielnikaKosztow) |
session.GetCore().PodzielKosztow.AddRow(p) |
| Zapis historii | podzielnik.Historia.Update(odDnia) |
session.GetCore().HistPodzielnikow.AddRow(h) |
| Element udziału | new ElementPodzielnika(historia) |
session.GetCore().ElemPodzielnikow.AddRow(e) |
Pola — PodzielnikKosztow: Nazwa: string, Definicja: Soneta.Core.DefinicjaPodzielnikaKosztow,
Zrodlo: IZrodloPodzielnikaKosztow (pracownik, ustawiany ctorem), Last/Historia.
Pola — HistoriaPodzielnika: Aktualnosc: FromTo (okres zapisu, zarządzany), Podstawa: decimal,
Elementy: SubTable<ElementPodzielnika>.
Pola — ElementPodzielnika: ElementPodzialowy: Soneta.Core.IElementSlownika (cel rozdziału —
m.in. Wydzial, Projekt, CentrumKosztow, OddzialFirmy — iface-ref), Wspolczynnik: double,
Procent: Percent (kalkulowany z współczynników).
Snippet:
var core = session.GetCore();
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
var odDnia = new Date(2026, 1, 1);
var wydzialA = session.GetKadry().Wydzialy.Firma; // referencja do celu rozdziału (IElementSlownika)
using (var t = session.Logout(editMode: true))
{
var podzielnik = new PodzielnikKosztow(pracownik); // ctor wiąże ze źródłem (pracownik)
core.PodzielKosztow.AddRow(podzielnik);
podzielnik.Nazwa = "Rozdział kosztów";
// podzielnik.Definicja = ... // referencja do definicji (opcjonalnie)
// zapis historii „od daty" (klon + AddRow)
var historia = podzielnik.Historia.Update(odDnia);
core.HistPodzielnikow.AddRow(historia);
// udział: cel rozdziału + współczynnik
var element = new ElementPodzielnika(historia);
core.ElemPodzielnikow.AddRow(element);
element.ElementPodzialowy = wydzialA;
element.Wspolczynnik = 100d; // Procent wyliczany z współczynników
t.Commit();
}
session.Save();
// Odczyt zbiorczy elementów podzielnika pracownika:
foreach (ElementPodzielnika e in pracownik.ElementyPodzielnika)
{
IElementSlownika cel = e.ElementPodzialowy; // np. Wydzial / Projekt
double wsp = e.Wspolczynnik;
}
Pułapki:
- Trójpoziomowa struktura —
PodzielnikKosztow(root, źródło = pracownik) →HistoriaPodzielnika(historia „od daty") →ElementPodzielnika(udziały). Każdy poziom: konstruktor +AddRowdo właściwej tabeliCore. Sam konstruktor nie wystarczy. Historia.Update(odDnia)+HistPodzielnikow.AddRow— para jak w KADRY-A14; zmiana udziałów „od dnia" to nowy zapis historii (a wcześniej zwykle usunięcie/Delete()elementów starego zapisu przy aktualizacji tego samego okresu — patrz worker pracy zdalnej).ElementPodzialowyto referencja interfejsowa (IElementSlownika) — przypisz istniejący rekord (Wydzial,Projekt,CentrumKosztow, …), nie twórz „w locie".Procentjest kalkulowany zWspolczynnikposzczególnych elementów — ustawiasz współczynniki, nie procenty.
KADRY-B7 — Aktualizacja danych wg definicji stanowiska (matrycy)
Cel: powiązać etat z definicją stanowiska i przejąć z niej parametry (stawka/grupa/wymiar, kalendarz, kod zawodu). Definicja stanowiska to matryca — wzorzec wartości dla etatu.
Pole na etacie: Etat.Definicja: Soneta.HR.DefinicjaStanowiska (referencja do słownika
konfiguracyjnego session.GetHR().DefStanowisk). Pokrewne: Etat.DefinicjaFunkcji: DefinicjaFunkcji.
Pola DefinicjaStanowiska (matryca, do skopiowania na etat):
| Dana | Pole / typ |
|---|---|
| Nazwa / stanowisko | Nazwa: string, Stanowisko: string, StanowiskoPelne: string |
| Funkcja | Funkcja: string, DefinicjaFunkcji: Soneta.HR.DefinicjaFunkcji |
| Zaszeregowanie (wzorzec) | Zaszeregowanie: Soneta.Kadry.Zaszeregowanie (Stawka, Wymiar, RodzajStawki, Element, WskaznikNazwa/Krotnosc) |
| Typ stawki / grupa | TypStawki: TypStawkiZaszeregowania, Grupa: Soneta.Kadry.GrupaZaszeregowania |
| Kalendarz | Kalendarz: Soneta.Kalend.Kalendarz, NieNadpisujKalendarza: bool |
| Kod zawodu / praca w szcz. warunkach | KodWykonywanegoZawodu, KodPracyWSzczWarunkach, InterpretacjaKalendarza |
Snippet:
var pracownik = session.GetKadry().Pracownicy.WgKodu["006"];
var def = session.GetHR().DefStanowisk.WgNazwa["Specjalista ds. kadr"]; // matryca (referencja; klucz WgNazwa)
var odDnia = new Date(2026, 7, 1);
using (var t = session.Logout(editMode: true))
{
var nowy = (PracHistoria)pracownik.Historia.Update(odDnia);
pracownik.Module.PracHistorie.AddRow(nowy);
var etat = nowy.Etat;
etat.Definicja = def; // powiązanie z definicją stanowiska
etat.Stanowisko = def.Stanowisko; // przeniesienie wartości z matrycy
etat.Zaszeregowanie.Wymiar = def.Zaszeregowanie.Wymiar;
etat.Zaszeregowanie.Stawka = def.Zaszeregowanie.Stawka;
t.Commit();
}
session.Save();
Pułapki:
Etat.Definicjato referencja do rekordu konfiguracyjnegoDefStanowisk— pobierz istniejącą (session.GetHR().DefStanowisk), nie twórz „w locie". Indeks po nazwie toWgNazwa(nieWgNazwy); w bazie Demo słownik bywa pusty — zabezpiecz się na brak definicji.- Definicja jest matrycą — przeniesienie wartości (stawka/wymiar/kalendarz) na etat zrób jawnie;
samo wskazanie
Etat.Definicjanie nadpisuje automatycznie wszystkich pól etatu w kodzie biznesowym. - Dostępność definicji potrafi zależeć od konfiguracji (
DefinicjeStanowiskDlaWydziałów) — definicja może być filtrowana po wydziale. - Zmiana stanowiska „od dnia" to nowy zapis historii (KADRY-A14), nie nadpisanie bieżącego.