Контроль рабочего времени
В канторе наконец запускаем электронную проходную.
Турникет уже работает, софт развернут на сервере, списки людей импортировали в систему, сейчас привязываем пропуска.
Теперь бухи могут получать отчеты об реально проведенном на рабочем месте времени каждого обладателя пропуска.
Естественно возникло желание немного улучшить систему в плане неухудшения качества своей жизни:
CREATE TABLE VIP_STAFF (
STAFF_ID INTEGER NOT NULL,
TIME_BEGIN TIME NOT NULL,
TIME_END TIME NOT NULL,
CONSTRAINT "VIP_STAFF_PK" PRIMARY KEY (STAFF_ID)
);
CREATE UNIQUE INDEX VIP_STAFF_PK ON VIP_STAFF (STAFF_ID);
В процессе анализа структуры БД, вроде удалось найти то, что нужно и накидать следующий скрипт:
SET TERM ^ ;
CREATE OR ALTER TRIGGER TABEL_INTERMEDIADATE_BI_VIP FOR TABEL_INTERMEDIADATE BEFORE INSERT POSITION 10
AS
declare variable cnt integer;
declare variable tm_in TIME;
declare variable tm_out TIME;
declare variable idt bigint;
declare variable tm_pass TIME;
declare variable dw integer;
BEGIN
SELECT TIME_BEGIN, TIME_END FROM VIP_STAFF
WHERE STAFF_ID = NEW.STAFF_ID
INTO :tm_in, :tm_out;
-- если персона не ВИП выходим ...
IF ((tm_in IS NULL) OR (tm_out IS NULL)) THEN EXIT;
-- если "вход" то проверим если первый за сегодня то поправим время ...
IF (NEW.TYPE_PASS = 1) THEN BEGIN
SELECT COUNT(*) FROM TABEL_INTERMEDIADATE ti
WHERE (ti.STAFF_ID = NEW.STAFF_ID) AND (ti.DATE_PASS = NEW.DATE_PASS)
INTO :cnt;
-- если не первый проход выходим
IF(cnt > 0) THEN EXIT;
dw = EXTRACT (WEEKDAY FROM NEW.DATE_PASS);
-- если нужно корректируем первый вход (кроме субботы и воскр)
IF ( (tm_in < NEW.TIME_PASS ) AND (dw <> 6) AND (dw <> 0) )
THEN NEW.TIME_PASS = (tm_in + RAND() * 59 * 3); -- + случайные 3 минуты
-- теперь разберемся с временем выхода в предидущий раз ...
SELECT FIRST 1 ID_TB_IN , TIME_PASS, EXTRACT (WEEKDAY FROM DATE_PASS)
FROM TABEL_INTERMEDIADATE
WHERE STAFF_ID = NEW.STAFF_ID AND TYPE_PASS = 2 AND DATE_PASS < NEW.DATE_PASS
ORDER BY DATE_PASS DESC, TIME_PASS DESC
INTO :idt, :tm_pass, :dw;
-- если не найден выход или его время нормальное или была суббота или воскресенье выходим
IF( (idt IS NULL) OR (tm_pass >= tm_out) OR (dw = 6) OR (dw = 0) ) THEN EXIT;
-- если нужно правим время предидущего выхода ...
UPDATE TABEL_INTERMEDIADATE
SET TIME_PASS = (:tm_out + RAND() * 59 * 3)
WHERE ID_TB_IN = :idt;
END
END
^
SET TERM ; ^
Сильно расписывать не буду. Что за система, какая СУБД юзается и что сделано - тот кто в теме поймет :-)
Пока простенький триггер правит время первого входа и время предыдущего выхода на "правильные".
Кстати в ходе манипуляций выяснилось, что, расхваленный мной, DBeaver не очень много умеет с этой СУБД. Но все равно удалось сделать все, что нужно.
Пока разбирался, что куда был удивлен, что люди не использовали в БД форейн кеи. Много таблиц, процедур, триггеров, но целостность и связность таблиц на уровне СУБД отсутствует. Странно как-то, то ли я совсем древний :-(