В канторе наконец запускаем электронную проходную.

Турникет уже работает, софт развернут на сервере, списки людей импортировали в систему, сейчас привязываем пропуска.

Теперь бухи могут получать отчеты об реально проведенном на рабочем месте времени каждого обладателя пропуска.

Естественно возникло желание немного улучшить систему в плане неухудшения качества своей жизни:

 

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 не очень много умеет с этой СУБД. Но все равно удалось сделать все, что нужно.

Пока разбирался, что куда был удивлен, что люди не использовали в БД форейн кеи. Много таблиц, процедур, триггеров, но целостность и связность таблиц на уровне СУБД отсутствует. Странно как-то, то ли я совсем древний :-(