Może ktoś implementował rozliczanie urlopów i byłby skłonny się podzielić doświadczeniem?
Nie pytam o zasady rozliczania urlopu (te znam) a spósób implementacji w bazie danych.
Może na przykładzie, pracownik zatrudnił się 5 lat temu, niech będzie że w lipcu a więc za pierwszy rok nalezała mu się połowa jego wymiaru urlopu, w którymś kolejnym roku zmienił mu się wymiar urlopu z 20 na 26 dni. Pytanie - ile urlopu ma do wykorzystania pracownik w tym roku? Jak to policzyć? Od której strony do tego podejść?
przecież algorytm już masz.. o o co chodzi? gotowy kod?
Nie, na gotowca nie liczę :)
Zastanawiam się jak robią to inni bo raczej zwykłym zapytaniem tego nie policzę, na razie mam dwie koncepcje:
- Przy zatrudnieniu zapisać pulę przysługującego urlopu i dopisując każdy wykorzystany urlop odejmować z puli, kłopotem będzie to że co roku trzeba będzie przeliczać pulę urlopu.
- Pętla od daty zatrudnienia która dla każdego roku policzy ilość przysługującego urlopu (chodzi o wychwycenie momentu zmiany wymiaru) i zwróci sumę, później już tylko wyliczenie różnicy między tą sumą a sumą wykorzystanego urlopu.
Pewnie jest kilka rzeczy o których nie pomyślałem a które rozwalą moje koncepcje dlatego pytanie jak to robią inni.
Add 1. Tak. I co z tego? To nawet lepiej, będziesz miał historyczne dane ile, kto, kiedy miał urlopu. Jeśli ustawodawca zmieni wymiar urlopu, to jak dobrze będziesz miał napisane wyliczanie urlopu na rok, wystarczy zmienić parametryzację i wszystko śmiga.
Add 2. Wymiar zmienia też np. ukończenie studiów, które jakby wliczają się do stażu pracy. Poza tym czemu pętlę. Sql został wymyślony do filtrowania, agregowania danych i to co chcesz zrobić da się zrobić bez użycia pętli, tzn. zależy jeszcze jak i jakie dane będziesz trzymał, ale jak to dobrze obmyślisz, to powinno dać radę jakimś średnio złożonym zapytaniem to pobrać.
Sumę za wszystkie lata? nie bardzo rozumiem?
Jakie dane powinieneś mieć:
- data zatrudnienia
- dotychczasowy okres zatrudnienia (u poprzednich pracodawców, zero rozwiąże nam sprawę pierwszej w życiu pracy i umożliwi naliczanie 1/12 urlopu/mies.)
- ukończona szkoła (stopień, tzn. średnia, wyższa)
- koniec zatrudnienia
- wykorzystany urlop wypoczynkowy (daty dni, kiedy pracownik miał urlop)
- wymiar etatu
jeśli jest to typowa praca, tzn. dziennie 8h przez pięć dni w tyg. to tyle powinno wystarczyć. Jeśli chcesz to zrobić dla zakładu gdzie jest zmianowość, albo dziennie nie pracuje się 8h, albo pon-pt. nie musi być tygodniem pracy pracownika, to trochę więcej parametryzacji to wymaga, ale się da :)
dzieki za cenne uwagi :)
Nie zakładam nowego wątku bo problem dotyczy pośrednio tego co powyżej.
Temat - karta pracy, czyli tabela z polami odpowiadającymi dniom miesiąca w której miały by być przechowywane ilość godzin pracy w danym dniu oraz ewentualne absencje.
Napisałem procedurę składowaną która coś takiego robi, kopiuje z kalendarza danej osoby nominalną ilość godzin pracy w danym dniu a następnie nadpisuje skopiowane godziny ewentualnymi absencjami. Niby fajnie... ale.
Problem będzie kiedy już po wygenerowaniu karty pracy trzeba będzie dokonać jakiejkolwiek zmiany w absencjach. Niby najprościej było by wygenerowć kartę ponownie ale nie można tego zrobić ponieważ mogły być już robione jakieś zmiany w godzinach (zapisane nadgodziny) i utracę te informacje.
Rozwiązaniem mogło by być - zapisywanie w karcie tylko godzin i w dynamiczny sposób "przesłanianie" godzin absencjami, fajnie by się tu sprawdził widok ale nie mam pojęcia czy coś takiego jest możliwe w tym konkretnym przypadku?
Na razie wymysliłem że oprę to o tabelę tymczasową:
-w karcie pracy przechowywane tylko godziny
-w momencie żądania wyświetlenia karty pracy generowana tabela tymczasowa
-przepisanie godzin z karty pracy
-nadpisanie absencjami
-podanie takiej tabeli urzyszkodnikowi
Pewnie da się to zrobić lepiej, prościej dlatego wszelkie pomysły i sugestie oraz wytknięcie braków mojej koncepcji mile widziane.
@pytek może inaczej - jakie masz dane wejściowe i co byś chciał mieć na wyjściu bo nie bardzo z Twojego tłumaczenia można się zorientować co po drodze jest tam jeszcze robione. Zazwyczaj kartę pracy generuje się wtedy kiedy jest potrzebna (do wydruku np) z danych, które się przecież cały czas zmieniają
Karta pracy rozumiem że to jakiś szablon zmian pracownika. Szblon powinien mieć zapisane w jakim dniu, od której godziny i ile godzin ma przepracować dany pracownik. Teraz lista obecności i nieobecności to inna bajka (inna tabela :]), ewentualnie tylko nieobecności, tak czy siak masz tam kto, kiedy, nie był lub był i w jakich godzinach lub ile godzin.
Później wystarczy złączyć te tabele i po wszystkim, nie widzę potrzeby tworzenia jakiejś tabeli tymczasowej. Po prostu na wyjściu dostaniesz listę dat i informacje był (ile h), nie był (dlaczego, ile h się odlicza), a na poziomie gui ewentualnie wyświetlasz to w jakiejś bardziej znośnej formie.
Powoli wymiękam z tym gów..m :/
Co mam:
tabela z absencjami
id_pracownika
dataOd
dataDo
typ_absencji
ilosc_dni
każdy pracownik ma przypisany kalendarz
id_kalendarza
data
ilosc_godzin //ilość godzin do przepracowania w danym dniu, jak wolne to 0
Musze mieć możliwość edytowania ile godzin faktycznie przepracował człowiek każdego dnia, stąd pomysł tabeli z polami na każdy dzień miesiąca i przepisywaniem do niej z kalendarza nominalnych godzin pracy, dalej urzyszkodnik mógłby to sobie edytować (jakieś nadgodziny czy inne c****-muje).
Co muszę mieć na końcu:
prezentację na każdy dzień miesiąca (najlepiej w formie edytowalnej tabeli aby móc wpisywać nadgodziny) czyli
pierwszego dnia miesiąca gość przepracowł 8h
drugiego 8,5h
trzeciego był na urlopie (bo zachlał)
w kolejnych dniach chorobowe (bo zachlał i poprawił) //stąd pomysł "przesłaniania" nominalnych godzin absencjami
itd.
A żeby tego było mało to muszę posumować wszystko co się da, dni/godziny faktycznie przepracowane, nadgodziny, każdy typ absencji.
Myślisz o tej strukturze jak o tabelkach w Excelu. Bazy danych wymagają innego podejścia. Do tych dwóch tabel, które zaproponowałeś dołożyłbym jeszcze jedną, w której odkładały by się informacje o faktycznie przepracowanym czasie dla pracownika. Czyli nie edytujesz tylko dokładasz rekordy: w razie absencji insert do tabelki z absencjami, w razie pracy insert do tabelki z pracą, a potem tylko porównujesz te informacje z kalendarzem (zakładam, że kalendarz to zbiór jakiś szablonowych godzin) i gotowe.
OK, przyjmuję krytyke z pokorą.
Poproszę o sugestię jak miałaby wyglądać strukura bazy.
żeby Ci cokolwiek zaproponować musisz napisać co się tam ma znaleźć :) - przypuszczam, że
- poszczególne godziny rozpoczęcia, zakończenia i trwania normalnej 'dniówki',
- godziny nadliczbowe,
- jak to jest z godzinami szkodliwymi - czy są wyliczane z automatu - jakiś % przepracowanych godzin czy podawane 'ręcznie'
- nieobecności - urlop płatny, niepłatny, bumelki, inne
- inne, o których nie mam pojęcia a zapewne istnieją
Potem musisz napisać co chcesz z tego uzyskać - inaczej jak ma wyglądać przykładowa karta iksińskiego
Misiekd napisał(a)
- poszczególne godziny rozpoczęcia, zakończenia i trwania normalnej 'dniówki',
- godziny nadliczbowe,
- jak to jest z godzinami szkodliwymi - czy są wyliczane z automatu - jakiś % przepracowanych godzin czy podawane 'ręcznie'
- nieobecności - urlop płatny, niepłatny, bumelki, inne
- inne, o których nie mam pojęcia a zapewne istnieją
- nie ma potrzeby godzina rozpoczęcia i zakończenia, wystarczy ilość godzin w dniu
- tak
- na tym etapie nie przewiduje się
- dokałdanie tak
- zapewne tak ;)
poniżej obrazek z tym co chciałbym osiągnąć na końcu (coś podobnego)
<image> http://img806.imageshack.us/i/absij.jpg/</image>
znaczenia obrazków:
słonko - urlop
krzyżyk - chorobowe
a co było 9? i co oznaczają dodatkowe cyfry 25?
Ja się średnio (prawie wcale) orientuję w systemach rozliczania czasu pracy, ale - zakładając, że input do systemu robi np. pracownik kadr:
Tablica z szablonami godzin do przepracowania: Kalendarz (KalendarzId, Data, IloscGodzin, + ew. klucze dodatkowe dla innych informacji)
Tablica z ewidencją czasu: Ewidencja (EwidencjaId, RodzajId, PracownikId, Data, IloscGodzin)
Oczywiście tablica: Pracownicy (PracownikId, KalendarzId, itp)
Tablica słownikowa: SL_Rodzaj (RodzajId, RodzajNazwa : 1-Praca, 2-Nadliczbowe50, 3-Nadliczbowe100, 4-nocne, 5-dyżur, 6-urlop, 7-chorobowe, itp.) + ewentualnie pole flagi: 1/0 dla łatwiejszego budowania widoków: 1 = praca, 0 = wolne
Tak, albo rozbijasz tablicę Ewidencja na dwie tablice: EwidencjaPracy, EwidencjaAbsencji. Równocześnie tablicę słownikową też trzeba by rozbić. Są plusy i minusy obu rozwiązań - sam zdecyduj.
Widok mniej więcej (pisane z palca - chodzi o ideę):
select K.Data, K.IloscGodzin as GodzinyNominalne, X.IloscGodzin as GodzinyPracy, Y.IloscGodzin as GodzinyWolne from Kalendarz K
inner join Pracownicy P on K.KalendarzId=P.KalendarzId
left join (select PracownikId, Data, IloscGodzin from Ewidencja where Flaga=1) X on P.PracownikId=X.PracownikId and P.Data=X.Data -- praca
left join (select PracownikId, Data, IloscGodzin from Ewidencja where Flaga=0) Y on P.PracownikId=Y.PracownikId and P.Data=Y.Data -- wolne
No właśnie ten program też nie radzi sobie najlepiej z korektami absencji, najpierw wpisałem urlop do 9-tego a później skróciłem go do 8-mego i efekt jest taki że wyszło nie wiadomo co.
Dodadkowe cyferki 25 to nadgodziny, konkretnie pół godziny nadgodzin (1/2).
@marcinsvr czy ja dobrze rozumiem, proponujesz aby w tabeli Ewidencja każdemu pracownikowi na każdy dzień roku zapisywać co mu się przydażyło (ilość godzin pracy lub rodzaj absencji)?
Nie na każdy dzień w roku, tylko na te dni w które wg Kalendarza powinien być w pracy (stąd "LEFT JOIJN'y" w proponowanym widoku)
Nie brałem w ogóle pod uwagę zapisu "wzdłuż" (każdy dzień to osobny rekord) ze względu na ilość rekordów ale po zastanowieniu wydaje się to mieć sens :)
Muszę to sobie przemyśleć.
w roku masz 365 (366 co 4 lata) dni. przy 1000 pracownikach rocznie przybędzie Ci około 400 000 rekordów. To jest 'pikuś'. Rozwiązanie 'wzdłuż' to jedyne sensowne rozwiązanie.
Moja propozycja jest taka:
typy dni - L4, UW, normalny dzień pracy, inne
PK | FK | Typ |
---|---|---|
* | typ_id | |
ikonka :) | ||
inne |
PK | FK | Pracownicy |
---|---|---|
* | pracownik_id | |
imie | ||
nazwisko | ||
inne |
PK | FK | Dni |
---|---|---|
* | data | |
* | typ_id | |
* | pracownik_id | |
ilosc_godzin | ||
ilosc_godzin_50 | ||
ilosc_godzin_100 | ||
ilosc_godzin_noc | ||
ilosc_godzin_szkodliwe | ||
dyzur_50 | ||
dyzur_100 | ||
inne |
z tego wyciągnięcie danych dla np usera 1 i miesiąca styczeń to banał
SELECT d.*, t.* FROM dni d, typ t WHERE d.typ_id = t.typ_id AND d.pracownik_id = 1 AND d.data BETWEEN '01-01-2011' AND '31-01-2011 ORDER BY d.data'
Stosunek dni przepracowanych do urlopu + chorobowego dla przeciętnego kowalskiego w roku to jakieś 26 (urlop) + 10 (2 razy L4 po tygodniu) 36 do ok 215 dni pracujących (przy założeniu, że sobota i niedziela jest niepracująca ale dla nich wpisów nie potrzeba) (średnio w roku jest ok 250 dni pracujących). W związku z tym nie widzę sensu rozbijać tabeli Dni na więcej - osobno na urlopy, L4 i pracujące czy też komplikować sobie życie przenoszęc kolumny odnośnie ilości godzin do osobnej tabeli
Dzięki chłopaki za pomoc, robię wzdłuż, w razie problemów pozwolę sobie jeszcze się odezwać :)