diff --git a/deploy/depo/fancy-m2m-firebird/10_FTV_M2M_PROCS.sql b/deploy/depo/fancy-m2m-firebird/10_FTV_M2M_PROCS.sql index 87790a0..19fd10d 100644 --- a/deploy/depo/fancy-m2m-firebird/10_FTV_M2M_PROCS.sql +++ b/deploy/depo/fancy-m2m-firebird/10_FTV_M2M_PROCS.sql @@ -388,6 +388,9 @@ DECLARE VARIABLE OPER_ID INTEGER; DECLARE VARIABLE ST INTEGER; DECLARE VARIABLE EV_S VARCHAR(19); DECLARE VARIABLE NOW_S VARCHAR(19); +DECLARE VARIABLE LINES INTEGER; +DECLARE VARIABLE LINES_ACCEPTED INTEGER; +DECLARE VARIABLE LINES_REJECTED INTEGER; 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, D.D_DATE, D.NUM, F.SHARE, F.AMOUNT, F.PLACE, F.CLIENT, H.DEPONENT @@ -424,6 +427,19 @@ BEGIN :EV_S || ' - ' || :EVENT_TYPE || COALESCE(' (референс - ' || :REFERENCE || ')', '') || COALESCE(' (параметры - ' || :PARAMETERS || ')', ''), 'Время начала обработки: ' || :NOW_S); + /* 3a. Исход по строкам документа: у каждой бумаги своё поручение НРД, строки могут разойтись + (одна исполнена BJ_ORDER_ACCEPTED, другая отвергнута BJ_ORDER_REJECTED) — тогда документ «Частично обработан» */ + IF (EVENT_TYPE IN ('BJ_ORDER_ACCEPTED', 'BJ_ORDER_REJECTED')) THEN + SELECT COUNT(*), COUNT(A.REFERENCE), COUNT(R.REFERENCE) + FROM D_CLISER_M2M_DOL F + JOIN OD_DOLS L ON L.ID = F.DOL + LEFT JOIN (SELECT DISTINCT E.REFERENCE FROM FTV_M2M_EVENTS E WHERE E.GUID = :GUID AND E.EVENT_TYPE = 'BJ_ORDER_ACCEPTED' + AND E.STATE <> 'ERROR') A ON A.REFERENCE = F.DOL_REF + LEFT JOIN (SELECT DISTINCT E.REFERENCE FROM FTV_M2M_EVENTS E WHERE E.GUID = :GUID AND E.EVENT_TYPE = 'BJ_ORDER_REJECTED' + AND E.STATE <> 'ERROR') R ON R.REFERENCE = F.DOL_REF + WHERE L.DOC = :CLISER_ID + INTO :LINES, :LINES_ACCEPTED, :LINES_REJECTED; + /* 4. Обработка каждого типа события. ID = 0 в UPDATE OD_DOCS — служебное изменение Fancy (триггер оставляет прежний ID и не проверяет права оператора). */ IF (EVENT_TYPE = 'BJ_RECEIVED') THEN @@ -449,7 +465,25 @@ BEGIN ELSE IF (EVENT_TYPE = 'BJ_ORDER_ACCEPTED') THEN BEGIN EXECUTE PROCEDURE FTV_M2M_PROCESS_OPERATION (:GUID, :REFERENCE, :EVENT_DATE, :PARAMETERS) RETURNING_VALUES :OPER_ID; - UPDATE OD_DOCS SET ID = 0, STATE = 2 WHERE ID = :CLISER_ID; /* FINAL — конец обработки */ + ST = NULL; + IF (LINES_REJECTED > 0) THEN /* другая строка отвергнута НРД */ + SELECT FIRST 1 S.ID FROM OD_DOC_STATES S WHERE S.SYS_NAME = 'IN_PROCESS' INTO :ST; + UPDATE OD_DOCS SET ID = 0, STATE = COALESCE(:ST, 2) WHERE ID = :CLISER_ID; /* FINAL — конец обработки или «Частично обработан» */ + END + ELSE IF (EVENT_TYPE = 'BJ_ORDER_REJECTED') THEN + BEGIN + /* НРД отверг поручение по строке (отчёт MS010). В PARAMETERS — номер и дата отчёта НРД, если номера нет — текст отказа. + Операцию не создаём; входящую запись D_FILER не трогаем — поручение было (ответ на вопрос от 16.10.2026) */ + UPDATE D_CLISER_M2M_DOL SET DEP_TEXT = SUBSTRING('Отказ НРД: ' || COALESCE(:PARAMETERS, '') FROM 1 FOR 255) WHERE DOL = :DOL_ID; + ST = NULL; + IF (LINES_ACCEPTED > 0) THEN /* другая строка исполнена */ + BEGIN + SELECT FIRST 1 S.ID FROM OD_DOC_STATES S WHERE S.SYS_NAME = 'IN_PROCESS' INTO :ST; + UPDATE OD_DOCS SET ID = 0, STATE = COALESCE(:ST, 2) WHERE ID = :CLISER_ID; /* «Частично обработан» */ + END + ELSE IF (LINES_REJECTED = LINES) THEN + UPDATE OD_DOCS SET ID = 0, STATE = 3 WHERE ID = :CLISER_ID; /* REJECT — отмена обработки: отвергнуты все строки */ + /* иначе по другим строкам ответа НРД ещё нет — состояние документа не меняем */ END ELSE IF (EVENT_TYPE = 'BJ_EXECUTED') THEN EXIT; /* уже исполнено по BJ_ORDER_ACCEPTED */ diff --git a/deploy/depo/fancy-m2m-firebird/README.md b/deploy/depo/fancy-m2m-firebird/README.md index ce0df5b..957f938 100644 --- a/deploy/depo/fancy-m2m-firebird/README.md +++ b/deploy/depo/fancy-m2m-firebird/README.md @@ -101,11 +101,11 @@ bj пишет его в MSSQL (полная перезапись `FTV_M2M_HANDBO 5. **Кодировка и диалект**: `RDB$DATABASE.RDB$CHARACTER_SET_NAME`, `MON$DATABASE.MON$SQL_DIALECT`. При NONE или WIN1251 — ставить в WIN1251 (см. выше); текст ошибки в `FTV_M2M_JOB` приводится к WIN1251. 6. **Числа состояний** в `PROCESS_EVENTS` (`STATE = 1, 2, 3, 8`) — как у Фонтвьель; в проверенной базе поручения - дошли до `STATE = 2`, сверить с `OD_DOC_STATES` клиента. + дошли до `STATE = 2`, сверить с `OD_DOC_STATES` клиента. «Частично обработан» (`BJ_ORDER_REJECTED`, строки + разошлись) ищется по `SYS_NAME = 'IN_PROCESS'`: в базе SPI это 762, в DEPO Фонтвьель — 869. ## Открытые вопросы логики (те же, что в MSSQL-версии) -- `BJ_ORDER_REJECTED` не обрабатывается — уходит в «неизвестное событие» (вопрос программисту от 16.10.2026). - `BJ_CP_CONFIRM` с направлением OUT перехватывается веткой `BJ_DECISION_CONFIRM` выше. - Депонент не найден — поручение создаётся без депонента, ошибки нет. Ищется по имени и серии+номеру документа: при пустой серии (`NULL`) не находится. diff --git a/deploy/depo/fancy-m2m-firebird/test/smoke.sql b/deploy/depo/fancy-m2m-firebird/test/smoke.sql index 772a373..5e86f99 100644 --- a/deploy/depo/fancy-m2m-firebird/test/smoke.sql +++ b/deploy/depo/fancy-m2m-firebird/test/smoke.sql @@ -1,5 +1,6 @@ /* Прогон процедур на заглушках Fancy: перевод IN (найден) и с неизвестным контрагентом; события PING, RECEIVED, - SENT, ORDER_ACCEPTED (операция, входящая запись, проводка), неизвестное, HANDBOOK. Привязки — значения Фонтвьель. */ + SENT, ORDER_ACCEPTED (операция, входящая запись, проводка), ORDER_REJECTED по второй строке (документ «Частично + обработан», отказ в DEP_TEXT), неизвестное, HANDBOOK. Привязки — значения Фонтвьель. */ UPDATE FTV_M2M_SETTINGS SET VAL = CASE NAME WHEN 'WHOS' THEN 383118 WHEN 'OPER_USER' THEN 84 WHEN 'FILER_CAT' THEN 255 WHEN 'D_NUM' THEN 313 WHEN 'K_NUM' THEN 836 WHEN 'MARKET' THEN 8106 WHEN 'B_TYPE' THEN 31 WHEN 'CORR_FACE' THEN 18174 WHEN 'FILER_RUBRICA' THEN 5 END; INSERT INTO OD_FACES (ID, SELF_ID, LAST_FLAG, MNEM, NAME, E_DATE, S_TYPE) VALUES (1, 1, 1, 'M2M', 'Кодировщик M2M', '9999-01-01', 0); @@ -12,6 +13,7 @@ INSERT INTO OD_DOC_CATS (ID, SYS_NAME) VALUES (501, 'I_CLISER_M2M_SPIS'); INSERT INTO OD_DOC_CATS (ID, SYS_NAME) VALUES (502, 'OP_INV_ZACH'); INSERT INTO OD_DOC_CATS (ID, SYS_NAME) VALUES (503, 'OP_INV_SPIS'); INSERT INTO OD_DOC_STATES (ID, SYS_NAME) VALUES (11, 'WAIT_RESP_DECIS'); +INSERT INTO OD_DOC_STATES (ID, SYS_NAME) VALUES (869, 'IN_PROCESS'); INSERT INTO OD_STEP_TYPES (ID, SYS_NAME, D_CAT, OUT_STATE) VALUES (77, 'PROCESS', 502, 2); INSERT INTO OD_SYS_TABS (CODE, NUM, NAME) VALUES ('DEPO96_DCLA', 31, 'Отчет депозитария'); INSERT INTO OD_VALUES (ID, ISIN) VALUES (300, 'RU000A0JVHH1'); @@ -23,6 +25,7 @@ INSERT INTO FTV_M2M_HANDBOOK (INN, PARTICIPANT_CODE, KIND, NAME_SHORT, NAME_FULL INSERT INTO FTV_M2M_HANDBOOK (INN, PARTICIPANT_CODE, KIND, NAME_SHORT, NAME_FULL) VALUES ('7703807489', 'MC0413600000', 'depo', 'ООО "ИК "Фонтвьель"', 'ООО Инвестиционная Компания Фонтвьель'); INSERT INTO FTV_M2M (GUID, DIRECTION, CONTRAGENT_M2M_CODE, DEPONENT_NAME, DEPONENT_DOC) VALUES ('bae1fa60-eb0a-4fee-b12c-018d1eafcbd2', 'IN', 'MC000050MOST', 'Лапшина Юлия Юрьевна', '4508 147055'); INSERT INTO FTV_M2M_LINES (GUID, REFERENCE, ISIN, SEC_CODE, AMOUNT, PLACE_NUMBER, LINK_NUMBER, DEPO_NUMBER) VALUES ('BAE1FA60-EB0A-4FEE-B12C-018D1EAFCBD2', 'M2MREF_1', 'RU000A0JVHH1', 'RU000A0JVHH1', 11, '36MC0413600000F00', 'HL171004001C', 'ВТНКЦ00000060'); +INSERT INTO FTV_M2M_LINES (GUID, REFERENCE, ISIN, SEC_CODE, AMOUNT, PLACE_NUMBER, LINK_NUMBER, DEPO_NUMBER) VALUES ('BAE1FA60-EB0A-4FEE-B12C-018D1EAFCBD2', 'M2MREF_2', 'RU000A0JVHH1', 'RU000A0JVHH1', 5, '36MC0413600000F00', 'HL171004001C', 'ВТНКЦ00000060'); INSERT INTO FTV_M2M (GUID, DIRECTION, CONTRAGENT_M2M_CODE, DEPONENT_NAME, DEPONENT_DOC) VALUES ('00000000-0000-4000-8000-000000000002', 'IN', 'MC9999999999', 'Никто', '0000 000000'); COMMIT; EXECUTE PROCEDURE FTV_M2M_JOB; @@ -31,6 +34,7 @@ INSERT INTO FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE) VALUES (NUL INSERT INTO FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE) VALUES ('BAE1FA60-EB0A-4FEE-B12C-018D1EAFCBD2', 'M2MREF_1', 'BJ_RECEIVED', CURRENT_TIMESTAMP); INSERT INTO FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE) VALUES ('BAE1FA60-EB0A-4FEE-B12C-018D1EAFCBD2', 'M2MREF_1', 'BJ_SENT', CURRENT_TIMESTAMP); INSERT INTO FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE, PARAMETERS) VALUES ('BAE1FA60-EB0A-4FEE-B12C-018D1EAFCBD2', 'M2MREF_1', 'BJ_ORDER_ACCEPTED', '2026-10-22 15:00:00', '1234567890 от 22.10.2026'); +INSERT INTO FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE, PARAMETERS) VALUES ('BAE1FA60-EB0A-4FEE-B12C-018D1EAFCBD2', 'M2MREF_2', 'BJ_ORDER_REJECTED', '2026-10-22 15:05:00', '1234567891 от 22.10.2026'); INSERT INTO FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE) VALUES ('BAE1FA60-EB0A-4FEE-B12C-018D1EAFCBD2', 'M2MREF_1', 'BJ_WHATEVER', CURRENT_TIMESTAMP); INSERT INTO FTV_M2M_EVENTS (EVENT_TYPE, EVENT_DATE) VALUES ('HANDBOOK', CURRENT_TIMESTAMP); COMMIT; @@ -41,6 +45,7 @@ SELECT ID, GUID, STATE, DOC, CONTRAGENT, DEPONENT, CAST(COMMENT AS VARCHAR(300)) SELECT ID, STATE, DOC, DOL, SHARE, PLACE, DEPO FROM FTV_M2M_LINES; SELECT ID, EVENT_TYPE, STATE, CAST(COMMENT AS VARCHAR(600)) C FROM FTV_M2M_EVENTS; SELECT ID, NUM, D_CAT, STATE, KVIT, WHOS FROM OD_DOCS ORDER BY ID; +SELECT DOL, DOL_REF, DEP_TEXT FROM D_CLISER_M2M_DOL; SELECT DOC, D_NUM, K_NUM, MARKET, B_TYPE, B_NUM, B_DATE, CAST(COMMENT AS VARCHAR(300)) C FROM U_OP_INV_ZACH; SELECT DOC, RUBRICA, DOC_NUM, DOC_DATE, CORR_FACE, MESS FROM D_FILER; SELECT DOC, CAST(COMMENT AS VARCHAR(300)) C, CAST(DO_ING AS VARCHAR(100)) D FROM OD_INVALIDS; diff --git a/deploy/depo/fancy-m2m/FTV_M2M_PROCESS_EVENTS.sql b/deploy/depo/fancy-m2m/FTV_M2M_PROCESS_EVENTS.sql index dffea3c..c2a7c7f 100644 --- a/deploy/depo/fancy-m2m/FTV_M2M_PROCESS_EVENTS.sql +++ b/deploy/depo/fancy-m2m/FTV_M2M_PROCESS_EVENTS.sql @@ -40,6 +40,9 @@ declare @DD_DATE datetime, @DD_NUM varchar(64), @STATE int, + @LINES int, + @LINES_ACCEPTED int, + @LINES_REJECTED int, @RAISERROR varchar(64) = null; select @@ -99,6 +102,20 @@ values print @EVENT_TYPE; +--3a. Исход по строкам документа: у каждой бумаги свое поручение НРД, строки могут разойтись +--(одна исполнена BJ_ORDER_ACCEPTED, другая отвергнута BJ_ORDER_REJECTED) - тогда документ «Частично обработан» +if @EVENT_TYPE in ('BJ_ORDER_ACCEPTED', 'BJ_ORDER_REJECTED') + select + @LINES = count(*), + @LINES_ACCEPTED = count(A.REFERENCE), + @LINES_REJECTED = count(R.REFERENCE) + from D_CLISER_M2M_DOL F + join OD_DOLS L on L.ID = F.DOL + left join (select distinct REFERENCE from FTV_M2M_EVENTS where GUID = @GUID and EVENT_TYPE = 'BJ_ORDER_ACCEPTED' and isnull(STATE, '') <> 'ERROR') A on A.REFERENCE = F.DOL_REF + left join (select distinct REFERENCE from FTV_M2M_EVENTS where GUID = @GUID and EVENT_TYPE = 'BJ_ORDER_REJECTED' and isnull(STATE, '') <> 'ERROR') R on R.REFERENCE = F.DOL_REF + where L.DOC = @CLISER_ID; + + --4. ОБРАБОТКА КАЖДОГО ТИПА СОБЫТИЯ -- https://lic.zetit.ru/docs/fancy-events @@ -161,11 +178,28 @@ else if @EVENT_TYPE = 'BJ_ORDER_ACCEPTED' begin --Создаем операцию и проводим ее exec FTV_M2M_PROCESS_OPERATION @GUID, @REFERENCE, @EVENT_DATE, @PARAMETERS, @OPER_ID out; - update OD_DOCS set ID = 0, STATE = 2 where ID = @CLISER_ID; -- FINAL - Конец обработки (в архиве) + if @LINES_REJECTED > 0 begin + select @STATE = ID from OD_DOC_STATES where SYS_NAME = 'IN_PROCESS'; + update OD_DOCS set ID = 0, STATE = isnull(@STATE, 2) where ID = @CLISER_ID; --IN_PROCESS = Частично обработан: другая строка отвергнута НРД + end + else + update OD_DOCS set ID = 0, STATE = 2 where ID = @CLISER_ID; -- FINAL - Конец обработки (в архиве) end ---BJ_ORDER_REJECTED ---TODO задал вопрос 16.10.2026 +else +if @EVENT_TYPE = 'BJ_ORDER_REJECTED' begin + --НРД отверг поручение по строке (отчет MS010). В PARAMETERS - номер и дата отчета НРД, если номера нет - текст отказа. + --Операцию не создаем; входящую запись D_FILER не трогаем - поручение было (ответ на вопрос от 16.10.2026) + update D_CLISER_M2M_DOL set DEP_TEXT = left('Отказ НРД: ' + isnull(@PARAMETERS, ''), 255) where DOL = @DOL_ID; + if @LINES_ACCEPTED > 0 begin + select @STATE = ID from OD_DOC_STATES where SYS_NAME = 'IN_PROCESS'; + update OD_DOCS set ID = 0, STATE = isnull(@STATE, 2) where ID = @CLISER_ID; --IN_PROCESS = Частично обработан: другая строка исполнена + end + else + if @LINES_REJECTED = @LINES + update OD_DOCS set ID = 0, STATE = 3 where ID = @CLISER_ID; --REJECT = Отмена обработки: отвергнуты все строки + --иначе по другим строкам ответа НРД еще нет - состояние документа не меняем +end --BJ_EXECUTED --Оно уже в событии BJ_ORDER_ACCEPTED в финале и с проводками, что делать-то? diff --git a/deploy/depo/fancy-m2m/README.md b/deploy/depo/fancy-m2m/README.md index ca1b4c7..5992fa3 100644 --- a/deploy/depo/fancy-m2m/README.md +++ b/deploy/depo/fancy-m2m/README.md @@ -19,6 +19,11 @@ («<номер> от <дд.мм.гггг>», событие `BJ_ORDER_ACCEPTED`), а не номер и дата M2M-поручения; комментарий операции — без «Отчет НКО АО НРД <номер> от <дата>.». Без даты в `@PARAMETERS` операция не создаётся (ошибка преобразования даты) — как и раньше во входящей записи `D_FILER`. +- 28.10.2026 (по ответу программиста): `BJ_ORDER_REJECTED` — НРД отверг поручение по строке (MS010). Операция не + создаётся, входящая запись `D_FILER` не меняется; в строке `D_CLISER_M2M_DOL.DEP_TEXT` — «Отказ НРД: » + `@PARAMETERS` + (номер и дата отчёта НРД, без номера — текст отказа). Документ: все строки отвергнуты — `STATE = 3` «Отмена + обработки»; строки разошлись (одна исполнена, другая отвергнута — в любом порядке) — «Частично обработан» + (`OD_DOC_STATES.SYS_NAME = 'IN_PROCESS'`, ID у баз разный); по другим строкам ответа ещё нет — состояние не меняется. ## От чего зависит на стороне Fancy (должно быть в DEPO клиента) Таблицы поставки Fancy с поддержкой M2M (у Фонтвьель появились 25.08.2026): `D_CLISER_M2M`, `D_CLISER_M2M_DOL`, `OD_M2M_ACCS`, diff --git a/internal/lkgateway/depoprocs/FTV_M2M_PROCESS_EVENTS.sql b/internal/lkgateway/depoprocs/FTV_M2M_PROCESS_EVENTS.sql index dffea3c..c2a7c7f 100644 --- a/internal/lkgateway/depoprocs/FTV_M2M_PROCESS_EVENTS.sql +++ b/internal/lkgateway/depoprocs/FTV_M2M_PROCESS_EVENTS.sql @@ -40,6 +40,9 @@ declare @DD_DATE datetime, @DD_NUM varchar(64), @STATE int, + @LINES int, + @LINES_ACCEPTED int, + @LINES_REJECTED int, @RAISERROR varchar(64) = null; select @@ -99,6 +102,20 @@ values print @EVENT_TYPE; +--3a. Исход по строкам документа: у каждой бумаги свое поручение НРД, строки могут разойтись +--(одна исполнена BJ_ORDER_ACCEPTED, другая отвергнута BJ_ORDER_REJECTED) - тогда документ «Частично обработан» +if @EVENT_TYPE in ('BJ_ORDER_ACCEPTED', 'BJ_ORDER_REJECTED') + select + @LINES = count(*), + @LINES_ACCEPTED = count(A.REFERENCE), + @LINES_REJECTED = count(R.REFERENCE) + from D_CLISER_M2M_DOL F + join OD_DOLS L on L.ID = F.DOL + left join (select distinct REFERENCE from FTV_M2M_EVENTS where GUID = @GUID and EVENT_TYPE = 'BJ_ORDER_ACCEPTED' and isnull(STATE, '') <> 'ERROR') A on A.REFERENCE = F.DOL_REF + left join (select distinct REFERENCE from FTV_M2M_EVENTS where GUID = @GUID and EVENT_TYPE = 'BJ_ORDER_REJECTED' and isnull(STATE, '') <> 'ERROR') R on R.REFERENCE = F.DOL_REF + where L.DOC = @CLISER_ID; + + --4. ОБРАБОТКА КАЖДОГО ТИПА СОБЫТИЯ -- https://lic.zetit.ru/docs/fancy-events @@ -161,11 +178,28 @@ else if @EVENT_TYPE = 'BJ_ORDER_ACCEPTED' begin --Создаем операцию и проводим ее exec FTV_M2M_PROCESS_OPERATION @GUID, @REFERENCE, @EVENT_DATE, @PARAMETERS, @OPER_ID out; - update OD_DOCS set ID = 0, STATE = 2 where ID = @CLISER_ID; -- FINAL - Конец обработки (в архиве) + if @LINES_REJECTED > 0 begin + select @STATE = ID from OD_DOC_STATES where SYS_NAME = 'IN_PROCESS'; + update OD_DOCS set ID = 0, STATE = isnull(@STATE, 2) where ID = @CLISER_ID; --IN_PROCESS = Частично обработан: другая строка отвергнута НРД + end + else + update OD_DOCS set ID = 0, STATE = 2 where ID = @CLISER_ID; -- FINAL - Конец обработки (в архиве) end ---BJ_ORDER_REJECTED ---TODO задал вопрос 16.10.2026 +else +if @EVENT_TYPE = 'BJ_ORDER_REJECTED' begin + --НРД отверг поручение по строке (отчет MS010). В PARAMETERS - номер и дата отчета НРД, если номера нет - текст отказа. + --Операцию не создаем; входящую запись D_FILER не трогаем - поручение было (ответ на вопрос от 16.10.2026) + update D_CLISER_M2M_DOL set DEP_TEXT = left('Отказ НРД: ' + isnull(@PARAMETERS, ''), 255) where DOL = @DOL_ID; + if @LINES_ACCEPTED > 0 begin + select @STATE = ID from OD_DOC_STATES where SYS_NAME = 'IN_PROCESS'; + update OD_DOCS set ID = 0, STATE = isnull(@STATE, 2) where ID = @CLISER_ID; --IN_PROCESS = Частично обработан: другая строка исполнена + end + else + if @LINES_REJECTED = @LINES + update OD_DOCS set ID = 0, STATE = 3 where ID = @CLISER_ID; --REJECT = Отмена обработки: отвергнуты все строки + --иначе по другим строкам ответа НРД еще нет - состояние документа не меняем +end --BJ_EXECUTED --Оно уже в событии BJ_ORDER_ACCEPTED в финале и с проводками, что делать-то? diff --git a/internal/lkgateway/depoprocs/firebird/10_FTV_M2M_PROCS.sql b/internal/lkgateway/depoprocs/firebird/10_FTV_M2M_PROCS.sql index 87790a0..19fd10d 100644 --- a/internal/lkgateway/depoprocs/firebird/10_FTV_M2M_PROCS.sql +++ b/internal/lkgateway/depoprocs/firebird/10_FTV_M2M_PROCS.sql @@ -388,6 +388,9 @@ DECLARE VARIABLE OPER_ID INTEGER; DECLARE VARIABLE ST INTEGER; DECLARE VARIABLE EV_S VARCHAR(19); DECLARE VARIABLE NOW_S VARCHAR(19); +DECLARE VARIABLE LINES INTEGER; +DECLARE VARIABLE LINES_ACCEPTED INTEGER; +DECLARE VARIABLE LINES_REJECTED INTEGER; 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, D.D_DATE, D.NUM, F.SHARE, F.AMOUNT, F.PLACE, F.CLIENT, H.DEPONENT @@ -424,6 +427,19 @@ BEGIN :EV_S || ' - ' || :EVENT_TYPE || COALESCE(' (референс - ' || :REFERENCE || ')', '') || COALESCE(' (параметры - ' || :PARAMETERS || ')', ''), 'Время начала обработки: ' || :NOW_S); + /* 3a. Исход по строкам документа: у каждой бумаги своё поручение НРД, строки могут разойтись + (одна исполнена BJ_ORDER_ACCEPTED, другая отвергнута BJ_ORDER_REJECTED) — тогда документ «Частично обработан» */ + IF (EVENT_TYPE IN ('BJ_ORDER_ACCEPTED', 'BJ_ORDER_REJECTED')) THEN + SELECT COUNT(*), COUNT(A.REFERENCE), COUNT(R.REFERENCE) + FROM D_CLISER_M2M_DOL F + JOIN OD_DOLS L ON L.ID = F.DOL + LEFT JOIN (SELECT DISTINCT E.REFERENCE FROM FTV_M2M_EVENTS E WHERE E.GUID = :GUID AND E.EVENT_TYPE = 'BJ_ORDER_ACCEPTED' + AND E.STATE <> 'ERROR') A ON A.REFERENCE = F.DOL_REF + LEFT JOIN (SELECT DISTINCT E.REFERENCE FROM FTV_M2M_EVENTS E WHERE E.GUID = :GUID AND E.EVENT_TYPE = 'BJ_ORDER_REJECTED' + AND E.STATE <> 'ERROR') R ON R.REFERENCE = F.DOL_REF + WHERE L.DOC = :CLISER_ID + INTO :LINES, :LINES_ACCEPTED, :LINES_REJECTED; + /* 4. Обработка каждого типа события. ID = 0 в UPDATE OD_DOCS — служебное изменение Fancy (триггер оставляет прежний ID и не проверяет права оператора). */ IF (EVENT_TYPE = 'BJ_RECEIVED') THEN @@ -449,7 +465,25 @@ BEGIN ELSE IF (EVENT_TYPE = 'BJ_ORDER_ACCEPTED') THEN BEGIN EXECUTE PROCEDURE FTV_M2M_PROCESS_OPERATION (:GUID, :REFERENCE, :EVENT_DATE, :PARAMETERS) RETURNING_VALUES :OPER_ID; - UPDATE OD_DOCS SET ID = 0, STATE = 2 WHERE ID = :CLISER_ID; /* FINAL — конец обработки */ + ST = NULL; + IF (LINES_REJECTED > 0) THEN /* другая строка отвергнута НРД */ + SELECT FIRST 1 S.ID FROM OD_DOC_STATES S WHERE S.SYS_NAME = 'IN_PROCESS' INTO :ST; + UPDATE OD_DOCS SET ID = 0, STATE = COALESCE(:ST, 2) WHERE ID = :CLISER_ID; /* FINAL — конец обработки или «Частично обработан» */ + END + ELSE IF (EVENT_TYPE = 'BJ_ORDER_REJECTED') THEN + BEGIN + /* НРД отверг поручение по строке (отчёт MS010). В PARAMETERS — номер и дата отчёта НРД, если номера нет — текст отказа. + Операцию не создаём; входящую запись D_FILER не трогаем — поручение было (ответ на вопрос от 16.10.2026) */ + UPDATE D_CLISER_M2M_DOL SET DEP_TEXT = SUBSTRING('Отказ НРД: ' || COALESCE(:PARAMETERS, '') FROM 1 FOR 255) WHERE DOL = :DOL_ID; + ST = NULL; + IF (LINES_ACCEPTED > 0) THEN /* другая строка исполнена */ + BEGIN + SELECT FIRST 1 S.ID FROM OD_DOC_STATES S WHERE S.SYS_NAME = 'IN_PROCESS' INTO :ST; + UPDATE OD_DOCS SET ID = 0, STATE = COALESCE(:ST, 2) WHERE ID = :CLISER_ID; /* «Частично обработан» */ + END + ELSE IF (LINES_REJECTED = LINES) THEN + UPDATE OD_DOCS SET ID = 0, STATE = 3 WHERE ID = :CLISER_ID; /* REJECT — отмена обработки: отвергнуты все строки */ + /* иначе по другим строкам ответа НРД ещё нет — состояние документа не меняем */ END ELSE IF (EVENT_TYPE = 'BJ_EXECUTED') THEN EXIT; /* уже исполнено по BJ_ORDER_ACCEPTED */