DEPO Firebird: проверка на реальной базе Fancy — генераторы, диалект 1, дата без времени
Обезличенная база Fancy (Firebird 2.5.9, диалект 1, кодировка NONE) с UDF ib_Fansy и штатными триггерами: установка, HANDBOOK, поручения IN/OUT, события до BJ_EXECUTED, операции и проводки, ошибки. - генераторы OD_DOCS_ID_GEN / OD_DOLS_ID_GEN (как в Fancy); - COMMENT без кавычек: в диалекте 1 "..." — строка; - FTV_M2M_DAY: дата без времени (в диалекте 1 CAST AS DATE время не отрезает); - README: установка в WIN1251, что подтвердилось, что проверить у клиента (UDF, кодировщик M2M, оператор). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/* Bridge&Join — процедуры обработки M2M для Fancy DEPO на Firebird 2.5.
|
||||
Перенос процедур MSSQL-версии (Фонтвьель, тексты от 22.10.2026, OPERATION — от 24.10.2026) на PSQL. Логика та же; отличия:
|
||||
- raiserror → FTV_M2M_FAIL: текст причины кладётся в контекст транзакции и поднимается исключение FTV_M2M_ERROR;
|
||||
- raiserror — FTV_M2M_FAIL: текст причины кладётся в контекст транзакции и поднимается исключение FTV_M2M_ERROR;
|
||||
FTV_M2M_JOB пишет этот текст в COMMENT (в Firebird 2.5 текст исключения в WHEN не доступен; контекст
|
||||
возвращает строку без кодировки — приводится к WIN1251, кодировке базы Fancy);
|
||||
- ошибка записи откатывает только её изменения (WHEN ANY = точка сохранения), в MSSQL-версии изменения
|
||||
@@ -11,7 +11,10 @@
|
||||
- SELECT … INTO, который в MSSQL молча брал последнюю из нескольких строк, — SELECT FIRST 1;
|
||||
- в цикле по строкам поручения бумага/счета сбрасываются перед поиском (в MSSQL ненайденное значение
|
||||
оставалось от предыдущей строки).
|
||||
Порядок создания: вспомогательные → WIRING → OPERATION → UPDATE_HANDBOOK → EVENTS → CREATE → JOB. */
|
||||
Тексты работают в обоих диалектах: база Fancy — диалект 1 (DATE хранит и время, "…" — строка, а не имя),
|
||||
поэтому COMMENT без кавычек, а дата без времени — через FTV_M2M_DAY. Проверено 27.10.2026 на обезличенной
|
||||
базе Fancy (Firebird 2.5, диалект 1, кодировка NONE) с UDF ib_Fansy и штатными триггерами.
|
||||
Порядок создания: вспомогательные, WIRING, OPERATION, UPDATE_HANDBOOK, EVENTS, CREATE, JOB. */
|
||||
|
||||
SET TERM ^ ;
|
||||
|
||||
@@ -42,6 +45,14 @@ BEGIN
|
||||
LPAD(CAST(FLOOR(EXTRACT(SECOND FROM T)) AS INTEGER), 2, '0');
|
||||
END^
|
||||
|
||||
/* Дата без времени (CONVERT(DATE, …) MSSQL-версии). В диалекте 1 CAST(… AS DATE) время не отрезает. */
|
||||
CREATE OR ALTER PROCEDURE FTV_M2M_DAY (T TIMESTAMP) RETURNS (D TIMESTAMP) AS
|
||||
BEGIN
|
||||
D = NULL;
|
||||
IF (T IS NOT NULL) THEN
|
||||
D = CAST(EXTRACT(YEAR FROM T) || '-' || EXTRACT(MONTH FROM T) || '-' || EXTRACT(DAY FROM T) AS TIMESTAMP);
|
||||
END^
|
||||
|
||||
|
||||
/* Директива «Обработать» для документа «Зачисление» или «Списание». Значения берутся только из самого
|
||||
документа; M2M-поручение и трансферные таблицы не используются. */
|
||||
@@ -151,7 +162,7 @@ DECLARE VARIABLE CLISER_ID INTEGER;
|
||||
DECLARE VARIABLE CLISER_NUM VARCHAR(64);
|
||||
DECLARE VARIABLE CLISER_DATE TIMESTAMP;
|
||||
DECLARE VARIABLE DIRECTION VARCHAR(64);
|
||||
DECLARE VARIABLE DD_DATE DATE;
|
||||
DECLARE VARIABLE DD_DATE TIMESTAMP;
|
||||
DECLARE VARIABLE DD_NUM VARCHAR(64);
|
||||
DECLARE VARIABLE SHARE INTEGER;
|
||||
DECLARE VARIABLE AMOUNT NUMERIC(18,7);
|
||||
@@ -167,7 +178,7 @@ DECLARE VARIABLE FILER_DATE TIMESTAMP;
|
||||
DECLARE VARIABLE STEP_ID INTEGER;
|
||||
DECLARE VARIABLE P VARCHAR(4000);
|
||||
DECLARE VARIABLE REP_NUM VARCHAR(255);
|
||||
DECLARE VARIABLE REP_DATE DATE;
|
||||
DECLARE VARIABLE REP_DATE TIMESTAMP;
|
||||
DECLARE VARIABLE CMT VARCHAR(4000);
|
||||
BEGIN
|
||||
EXECUTE PROCEDURE FTV_M2M_GET('WHOS') RETURNING_VALUES :WHOS;
|
||||
@@ -181,7 +192,7 @@ BEGIN
|
||||
|
||||
SELECT FIRST 1 H.DOC, D.NUM, D.D_DATE,
|
||||
CASE WHEN DC.SYS_NAME = 'I_CLISER_M2M_ZACH' THEN 'IN' WHEN DC.SYS_NAME = 'I_CLISER_M2M_SPIS' THEN 'OUT' END,
|
||||
CAST(D.D_DATE AS DATE), D.NUM, F.SHARE, F.AMOUNT, F.CLIENT, H.DEPONENT, F.PLACE
|
||||
D.D_DATE, D.NUM, F.SHARE, F.AMOUNT, F.CLIENT, H.DEPONENT, F.PLACE
|
||||
FROM D_CLISER_M2M_DOL F
|
||||
LEFT JOIN OD_DOLS L ON L.ID = F.DOL
|
||||
LEFT JOIN OD_DOCS D ON D.ID = L.DOC
|
||||
@@ -192,6 +203,7 @@ BEGIN
|
||||
|
||||
IF (CLISER_ID IS NULL) THEN
|
||||
EXECUTE PROCEDURE FTV_M2M_FAIL('Не найдено M2M-поручение по GUID + REFERENCE');
|
||||
EXECUTE PROCEDURE FTV_M2M_DAY(:DD_DATE) RETURNING_VALUES :DD_DATE;
|
||||
|
||||
/* Направление */
|
||||
SELECT FIRST 1 DC.ID FROM OD_DOC_CATS DC
|
||||
@@ -199,7 +211,7 @@ BEGIN
|
||||
INTO :D_CAT;
|
||||
|
||||
/* ID и номер операции */
|
||||
OPER_ID = GEN_ID(OD_DOC_ID_GEN, 1);
|
||||
OPER_ID = GEN_ID(OD_DOCS_ID_GEN, 1);
|
||||
EXECUTE PROCEDURE FU_NEXT_DOC_NUM (:D_CAT, :OPER_DATE, NULL, :OPER_ID) RETURNING_VALUES :NUM, :NEW_DATE;
|
||||
NUM = NUM || '_' || REFERENCE;
|
||||
|
||||
@@ -212,14 +224,14 @@ BEGIN
|
||||
(MSSQL-версия, правка программиста 24.10.2026). */
|
||||
P = TRIM(PARAMETERS);
|
||||
REP_NUM = LEFT(P, POSITION(' ' IN P || ' ') - 1);
|
||||
REP_DATE = CAST(RIGHT(P, POSITION(' ' IN REVERSE(P)) - 1) AS DATE);
|
||||
REP_DATE = CAST(RIGHT(P, POSITION(' ' IN REVERSE(P)) - 1) AS TIMESTAMP);
|
||||
|
||||
IF (DIRECTION = 'IN') THEN
|
||||
BEGIN
|
||||
CMT = 'Перевод M2M (без поручения), GUID ' || GUID || ', референс ' || REFERENCE;
|
||||
INSERT INTO U_OP_INV_ZACH
|
||||
(DOC, DD_TYPE, DD_DATE, DD_NUM, SHARE, AMOUNT, BLANKS, PLACE, D_NUM, DEPO, K_NUM, MARKET,
|
||||
CONDITION, IS_REG, TAX_R, B_TYPE, B_DATE, B_NUM, WIR_DATE, NOTIFY_DATE, REG_DATE, IS_BLOCK, FROM_FACE, REJECT_REASON, "COMMENT")
|
||||
CONDITION, IS_REG, TAX_R, B_TYPE, B_DATE, B_NUM, WIR_DATE, NOTIFY_DATE, REG_DATE, IS_BLOCK, FROM_FACE, REJECT_REASON, COMMENT)
|
||||
VALUES
|
||||
(:OPER_ID, 1 /* клиентское */, :DD_DATE, :DD_NUM, :SHARE, :AMOUNT, NULL, :PLACE, :ACC_D, :CLIENT, :ACC_K, :MARKET,
|
||||
NULL, NULL, NULL, :B_TYPE, :REP_DATE, :REP_NUM, :OPER_DATE, :OPER_DATE, :OPER_DATE, 0, :FACE, NULL, :CMT);
|
||||
@@ -229,20 +241,20 @@ BEGIN
|
||||
CMT = 'Перевод M2M, GUID ' || GUID || ', референс ' || REFERENCE;
|
||||
INSERT INTO U_OP_INV_SPIS
|
||||
(DOC, DD_TYPE, DD_DATE, DD_NUM, SHARE, AMOUNT, BLANKS, PLACE, D_NUM, DEPO, K_NUM, MARKET,
|
||||
OLD_CONDITIONS, IS_REG, TAX_R, B_TYPE, B_DATE, B_NUM, WIR_DATE, NOTIFY_DATE, REG_DATE, IS_BLOCK, FROM_FACE, REJECT_REASON, "COMMENT")
|
||||
OLD_CONDITIONS, IS_REG, TAX_R, B_TYPE, B_DATE, B_NUM, WIR_DATE, NOTIFY_DATE, REG_DATE, IS_BLOCK, FROM_FACE, REJECT_REASON, COMMENT)
|
||||
VALUES
|
||||
(:OPER_ID, 1 /* клиентское */, :DD_DATE, :DD_NUM, :SHARE, :AMOUNT, NULL, :PLACE, :ACC_D, :CLIENT, :ACC_K, :MARKET,
|
||||
NULL, NULL, NULL, :B_TYPE, :REP_DATE, :REP_NUM, :OPER_DATE, :OPER_DATE, :OPER_DATE, 0, :FACE, NULL, :CMT);
|
||||
END
|
||||
|
||||
/* Входящая запись (отчёт НРД) */
|
||||
FILER_ID = GEN_ID(OD_DOC_ID_GEN, 1);
|
||||
FILER_ID = GEN_ID(OD_DOCS_ID_GEN, 1);
|
||||
FILER_DATE = CURRENT_TIMESTAMP;
|
||||
EXECUTE PROCEDURE FU_NEXT_DOC_NUM ('D_FILER', :FILER_DATE, 1, :FILER_ID) RETURNING_VALUES :FILER_NUM, :NEW_DATE;
|
||||
INSERT INTO OD_DOCS (ID, NUM, D_CAT, D_DATE, STATE, DIRECTION, WHOS)
|
||||
VALUES (:FILER_ID, :FILER_NUM, :FILER_CAT, :FILER_DATE, 2, 1, :WHOS);
|
||||
|
||||
INSERT INTO D_FILER (DOC, PASS_KIND, RUBRICA, "COMMENT", DOC_NUM, DOC_DATE, CORR_FACE, FUND, ACCOUNT, PLACE, ORI_DATE, CHILD_CAT, MESS)
|
||||
INSERT INTO D_FILER (DOC, PASS_KIND, RUBRICA, COMMENT, DOC_NUM, DOC_DATE, CORR_FACE, FUND, ACCOUNT, PLACE, ORI_DATE, CHILD_CAT, MESS)
|
||||
VALUES (:FILER_ID, 8, :RUBRICA, 'Отчет (перевод через MOEX-МОСТ)', :REP_NUM, :REP_DATE, :CORR_FACE,
|
||||
:FACE, :CLIENT, :PLACE, :FILER_DATE, NULL, 'MS010 / ' || :GUID || ' / ' || :REFERENCE);
|
||||
|
||||
@@ -362,7 +374,7 @@ DECLARE VARIABLE CLIENT INTEGER;
|
||||
DECLARE VARIABLE FACE INTEGER;
|
||||
DECLARE VARIABLE CLISER_ID INTEGER;
|
||||
DECLARE VARIABLE DOL_ID INTEGER;
|
||||
DECLARE VARIABLE DD_DATE DATE;
|
||||
DECLARE VARIABLE DD_DATE TIMESTAMP;
|
||||
DECLARE VARIABLE DD_NUM VARCHAR(64);
|
||||
DECLARE VARIABLE OPER_ID INTEGER;
|
||||
DECLARE VARIABLE ST INTEGER;
|
||||
@@ -370,7 +382,7 @@ DECLARE VARIABLE EV_S VARCHAR(19);
|
||||
DECLARE VARIABLE NOW_S VARCHAR(19);
|
||||
BEGIN
|
||||
SELECT FIRST 1 ME.GUID, ME.REFERENCE, ME.EVENT_TYPE, ME.EVENT_DATE, ME.M2M_REJECT_CODE, ME.PARAMETERS, M.DIRECTION,
|
||||
H.DOC, F.DOL, CAST(D.D_DATE AS DATE), D.NUM, F.SHARE, F.AMOUNT, F.PLACE, F.CLIENT, H.DEPONENT
|
||||
H.DOC, F.DOL, D.D_DATE, D.NUM, F.SHARE, F.AMOUNT, F.PLACE, F.CLIENT, H.DEPONENT
|
||||
FROM FTV_M2M_EVENTS ME
|
||||
LEFT JOIN FTV_M2M M ON M.GUID = ME.GUID
|
||||
LEFT JOIN D_CLISER_M2M_DOL F ON F.DOL_REF = ME.REFERENCE
|
||||
@@ -384,7 +396,7 @@ BEGIN
|
||||
IF (EVENT_TYPE = 'HANDBOOK') THEN
|
||||
BEGIN
|
||||
EXECUTE PROCEDURE FTV_M2M_UPDATE_HANDBOOK RETURNING_VALUES :CMT;
|
||||
UPDATE FTV_M2M_EVENTS SET "COMMENT" = :CMT WHERE ID = :ID;
|
||||
UPDATE FTV_M2M_EVENTS SET COMMENT = :CMT WHERE ID = :ID;
|
||||
EXIT;
|
||||
END
|
||||
|
||||
@@ -399,7 +411,7 @@ BEGIN
|
||||
/* 3. Признак документа */
|
||||
EXECUTE PROCEDURE FTV_M2M_DT(:EVENT_DATE) RETURNING_VALUES :EV_S;
|
||||
EXECUTE PROCEDURE FTV_M2M_DT(CURRENT_TIMESTAMP) RETURNING_VALUES :NOW_S;
|
||||
INSERT INTO OD_INVALIDS (DOC, STATUS, "COMMENT", DO_ING)
|
||||
INSERT INTO OD_INVALIDS (DOC, STATUS, COMMENT, DO_ING)
|
||||
VALUES (:CLISER_ID, 0,
|
||||
:EV_S || ' - ' || :EVENT_TYPE || COALESCE(' (референс - ' || :REFERENCE || ')', '') || COALESCE(' (параметры - ' || :PARAMETERS || ')', ''),
|
||||
'Время начала обработки: ' || :NOW_S);
|
||||
@@ -474,6 +486,7 @@ DECLARE VARIABLE FILER_ID INTEGER;
|
||||
DECLARE VARIABLE FILER_NUM VARCHAR(255);
|
||||
DECLARE VARIABLE FILER_DATE TIMESTAMP;
|
||||
DECLARE VARIABLE DOL_ID INTEGER;
|
||||
DECLARE VARIABLE D_DAY TIMESTAMP;
|
||||
BEGIN
|
||||
EXECUTE PROCEDURE FTV_M2M_GET('WHOS') RETURNING_VALUES :WHOS;
|
||||
|
||||
@@ -508,7 +521,7 @@ BEGIN
|
||||
INTO :DEPONENT;
|
||||
|
||||
/* 1.5. Шапка документа */
|
||||
CLISER_ID = GEN_ID(OD_DOC_ID_GEN, 1);
|
||||
CLISER_ID = GEN_ID(OD_DOCS_ID_GEN, 1);
|
||||
D_DATE = CURRENT_TIMESTAMP;
|
||||
EXECUTE PROCEDURE FU_NEXT_DOC_NUM (:D_CAT, :D_DATE, NULL, :CLISER_ID) RETURNING_VALUES :NUM, :NEW_DATE;
|
||||
|
||||
@@ -549,7 +562,7 @@ BEGIN
|
||||
/* Счёт клиента */
|
||||
SELECT FIRST 1 C.ID FROM OD_CLIENTS C WHERE C.NUMBER = :DEPO_NUMBER INTO :DEPO;
|
||||
|
||||
DOL_ID = GEN_ID(OD_DOL_ID_GEN, 1);
|
||||
DOL_ID = GEN_ID(OD_DOLS_ID_GEN, 1);
|
||||
INSERT INTO OD_DOLS (ID, DOC) VALUES (:DOL_ID, :CLISER_ID);
|
||||
INSERT INTO D_CLISER_M2M_DOL (DOL, SHARE, AMOUNT, DOL_REF, PLACE, CLIENT) VALUES (:DOL_ID, :SHARE, :AMOUNT, :REFERENCE, :PLACE, :DEPO);
|
||||
|
||||
@@ -561,13 +574,14 @@ BEGIN
|
||||
IF (DIRECTION = 'OUT') THEN
|
||||
BEGIN
|
||||
EXECUTE PROCEDURE FTV_M2M_GET('FILER_CAT') RETURNING_VALUES :FILER_CAT;
|
||||
FILER_ID = GEN_ID(OD_DOC_ID_GEN, 1);
|
||||
FILER_ID = GEN_ID(OD_DOCS_ID_GEN, 1);
|
||||
FILER_DATE = CURRENT_TIMESTAMP;
|
||||
EXECUTE PROCEDURE FU_NEXT_DOC_NUM ('D_FILER', :FILER_DATE, 1, :FILER_ID) RETURNING_VALUES :FILER_NUM, :NEW_DATE;
|
||||
EXECUTE PROCEDURE FTV_M2M_DAY(:D_DATE) RETURNING_VALUES :D_DAY;
|
||||
INSERT INTO OD_DOCS (ID, NUM, D_CAT, D_DATE, STATE, DIRECTION, WHOS)
|
||||
VALUES (:FILER_ID, :FILER_NUM, :FILER_CAT, :FILER_DATE, 2, 1, :WHOS);
|
||||
INSERT INTO D_FILER (DOC, PASS_KIND, RUBRICA, "COMMENT", DOC_NUM, DOC_DATE, CORR_FACE, FUND, ACCOUNT, PLACE, ORI_DATE, CHILD_CAT, MESS)
|
||||
VALUES (:FILER_ID, 7, 8, 'M2M поручение на списание через MOEX-МОСТ', :NUM, CAST(:D_DATE AS DATE), :DEPONENT, :DEPONENT,
|
||||
INSERT INTO D_FILER (DOC, PASS_KIND, RUBRICA, COMMENT, DOC_NUM, DOC_DATE, CORR_FACE, FUND, ACCOUNT, PLACE, ORI_DATE, CHILD_CAT, MESS)
|
||||
VALUES (:FILER_ID, 7, 8, 'M2M поручение на списание через MOEX-МОСТ', :NUM, :D_DAY, :DEPONENT, :DEPONENT,
|
||||
:DEPO, :PLACE, :FILER_DATE, :D_CAT, :GUID);
|
||||
/* Связываем с M2M-поручением */
|
||||
UPDATE OD_DOCS SET ID = 0, KVIT = :FILER_ID WHERE ID = :CLISER_ID;
|
||||
@@ -597,7 +611,7 @@ BEGIN
|
||||
CMT = COALESCE(CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'FTV_M2M_ERR') AS VARCHAR(255) CHARACTER SET WIN1251), 'ошибка Fancy') || ' // FTV_M2M_PROCESS_CREATE // SQLCODE ' || SQLCODE || ', GDSCODE ' || GDSCODE;
|
||||
END
|
||||
END
|
||||
UPDATE FTV_M2M SET STATE = :ST, TIMEEND = CURRENT_TIMESTAMP, "COMMENT" = :CMT WHERE ID = :ID;
|
||||
UPDATE FTV_M2M SET STATE = :ST, TIMEEND = CURRENT_TIMESTAMP, COMMENT = :CMT WHERE ID = :ID;
|
||||
END
|
||||
|
||||
/* НОВЫЕ СОБЫТИЯ */
|
||||
@@ -616,7 +630,7 @@ BEGIN
|
||||
END
|
||||
/* без ошибки COMMENT не трогаем: в нём отчёт справочника (HANDBOOK) */
|
||||
IF (CMT IS NOT NULL) THEN
|
||||
UPDATE FTV_M2M_EVENTS SET STATE = :ST, TIMEEND = CURRENT_TIMESTAMP, "COMMENT" = :CMT WHERE ID = :ID;
|
||||
UPDATE FTV_M2M_EVENTS SET STATE = :ST, TIMEEND = CURRENT_TIMESTAMP, COMMENT = :CMT WHERE ID = :ID;
|
||||
ELSE
|
||||
UPDATE FTV_M2M_EVENTS SET STATE = :ST, TIMEEND = CURRENT_TIMESTAMP WHERE ID = :ID;
|
||||
END
|
||||
|
||||
Reference in New Issue
Block a user