Files
Bridge-and-Join-s/deploy/depo/fancy-m2m/FTV_M2M_PROCESS_EVENTS.sql
T
fontvielle d05cba44ec DEPO: обработка BJ_ORDER_REJECTED (отказ НРД по поручению) — MSSQL и Firebird
По ответу программиста Fancy от 28.10.2026:
- операция не создаётся, входящая запись D_FILER не меняется (поручение было);
- в строке D_CLISER_M2M_DOL.DEP_TEXT — «Отказ НРД: » + PARAMETERS (номер и дата
  отчёта НРД, без номера — текст отказа);
- документ: все строки отвергнуты — «Отмена обработки» (3); строки разошлись
  (одна исполнена, другая отвергнута, в любом порядке) — «Частично обработан»
  (OD_DOC_STATES.SYS_NAME = IN_PROCESS, ID у баз разный: 869 / 762); по другим
  строкам ответа ещё нет — состояние не меняется. BJ_ORDER_ACCEPTED при уже
  отвергнутой строке ставит «Частично обработан» вместо «Конец обработки».

Проверено: MSSQL — тестовая DEPO в транзакции с откатом (A: 2→869, B: 127→869,
D: 127→3); Firebird — база SPI с триггерами Fancy (A–D, OUT с отказом без номера)
и smoke на заглушках.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
2026-10-28 14:25:27 +03:00

245 lines
9.7 KiB
Transact-SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
CREATE OR ALTER procedure [dbo].[FTV_M2M_PROCESS_EVENTS] (@ID int)
--grant execute on FTV_M2M_PROCESS_EVENTS to public;
--TODO что делать если мы проставили статус не по всем строкам документа??
as
set nocount on;
--if user = 'dbo' execute as user = 'SYSDBA';
print 'FTV_M2M_PROCESS_EVENTS';
print @ID;
declare
@WHOS int = 383118,
@GUID uniqueidentifier,
@REFERENCE varchar(255),
@EVENT_TYPE varchar(64),
@EVENT_DATE datetime,
@M2M_REJECT_CODE varchar,
@PARAMETERS nvarchar(4000),
@DIRECTION varchar(64),
@COMMENT varchar(MAX),
--
@CONTRAGENT_FACE int,
@DEPONENT_FACE int,
@SHARE int,
@AMOUNT numeric(27, 7),
@PLACE int,
@CLIENT int,
@FACE int,
@CLISER_ID int,
@DOL_ID int,
--
@D_CAT int,
@NUM varchar(64),
@D_DATE datetime,
@OPER_ID int,
@DD_DATE datetime,
@DD_NUM varchar(64),
@STATE int,
@LINES int,
@LINES_ACCEPTED int,
@LINES_REJECTED int,
@RAISERROR varchar(64) = null;
select
@GUID = ME.GUID,
@REFERENCE = ME.REFERENCE,
@EVENT_TYPE = ME.EVENT_TYPE,
@EVENT_DATE = ME.EVENT_DATE,
@M2M_REJECT_CODE = ME.M2M_REJECT_CODE,
@PARAMETERS = ME.PARAMETERS,
@DIRECTION = M.DIRECTION,
@CLISER_ID = H.DOC,
@DOL_ID = F.DOL,
@DD_DATE = cast(D.D_DATE as date),
@DD_NUM = D.NUM,
@SHARE = F.SHARE,
@AMOUNT = F.AMOUNT,
@PLACE = F.PLACE,
@CLIENT = F.CLIENT,
@FACE = H.DEPONENT
from FTV_M2M_EVENTS ME
left join FTV_M2M_LINES ML on ML.GUID = ME.GUID and ML.REFERENCE = ME.REFERENCE
left join FTV_M2M M on M.GUID = ME.GUID
left join D_CLISER_M2M_DOL F on F.DOL_REF = ME.REFERENCE
left join D_CLISER_M2M H on H.DOC_GUID = ME.GUID
left join OD_DOCS D on D.ID = H.DOC
where ME.ID = @ID;
--1. Обновление справоника участников сервмса
if @EVENT_TYPE = 'HANDBOOK' begin
exec FTV_M2M_UPDATE_HANDBOOK @COMMENT out;
update FTV_M2M_EVENTS set COMMENT = @COMMENT where ID = @ID;
return;
end;
--1a. BJ_PING — проверочное событие bj (без GUID и REFERENCE): отметить обработанным, документ не трогать
if @EVENT_TYPE = 'BJ_PING' return;
--2. Критические ошибки (TODO другте обязательные поля)
if @GUID is null raiserror ('Не указан GUID', 16, 1);
if @REFERENCE is null raiserror ('Не указан REFERENCE', 16, 1);
if @DOL_ID is null raiserror ('Не найдена строка M2M-поручение по GUID + REFERENCE', 16, 1);
--3. Пишем в признаки документа
insert into OD_INVALIDS (DOC, STATUS, COMMENT, DO_ING)
values
(
@CLISER_ID,
0,
FORMAT(@EVENT_DATE, 'dd.MM.yyyy HH:mm:ss') + ' - ' + @EVENT_TYPE + coalesce (' (референс - ' + @REFERENCE + ')', '') + coalesce (' (параметры - ' + @PARAMETERS + ')', ''),
'Время начала обработки: ' + FORMAT(GETDATE(), 'dd.MM.yyyy HH:mm:ss')
);
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
if @EVENT_TYPE = 'BJ_RECEIVED' begin
update OD_DOCS set ID = 0, STATE = 1 where ID = @CLISER_ID; --START = Начало обработки (зарегистрирован)
end
else
if @EVENT_TYPE = 'BJ_SENT' begin
select @STATE = ID from OD_DOC_STATES where SYS_NAME = 'WAIT_RESP_DECIS';
update OD_DOCS set ID = 0, STATE = @STATE where ID = @CLISER_ID; --WAIT_RESP_DECIS = Ожидание ответа Response/Decision
end
else
if @EVENT_TYPE in ('BJ_DECISION_CONFIRM', 'BJ_CP_CONFIRM') begin
--TODO эти события для СТРОКИ!!!
update OD_DOCS set ID = 0, STATE = 8 where ID = @CLISER_ID; --RECIEVED = Принят: ожидает обработки
end
else
if @EVENT_TYPE in ('BJ_DECISION_REJECT', 'BJ_CP_REJECT') begin
--TODO эти события для СТРОКИ!!!
update OD_DOCS set ID = 0, STATE = 3 where ID = @CLISER_ID; --REJECT = Отмена обработки
end
else
if @EVENT_TYPE = 'BJ_SERVICE_ERROR' begin
update OD_DOCS set ID = 0, STATE = 3 where ID = @CLISER_ID; --REJECT = Отмена обработки
end
--else
--if @EVENT_TYPE = 'BJ_DECISION_REJECT' and @DIRECTION = 'IN' begin
-- --M2M_STATUS = 10 TODO!!!!!!!!!!!!!!!!!
-- update D_CLISER_M2M_DOL set M2M_STATUS = 10, M2M_TEXT = '???' where DOL = @DOL_ID;
-- --только если отказ по всем строкам подвала документа
-- if not exists (select top 1 DOL from D_CLISER_M2M_DOL F left join OD_DOLS L on L.ID = F.DOL where L.DOC = @CLISER_ID and (M2M_STATUS is null or M2M_TEXT is null)) begin
-- update OD_DOCS set ID = 0, STATE = 3 where ID = @CLISER_ID; --REJECT - Отмена обработки
-- end;
--end
--else
--if @EVENT_TYPE = 'BJ_CP_REJECT' and @DIRECTION = 'OUT' begin
-- --M2M_STATUS = 10 TODO!!!!!!!!!!!!!!!!!
-- update D_CLISER_M2M_DOL set M2M_STATUS = 10, M2M_TEXT = '???' where DOL = @DOL_ID;
-- --только если отказ по всем строкам подвала документа
-- --TODO зачем проверять все строки подвала, если мы не будем делать многострочные исходящие???
-- if not exists (select top 1 DOL from D_CLISER_M2M_DOL F left join OD_DOLS L on L.ID = F.DOL where L.DOC = @CLISER_ID and (M2M_STATUS is null or M2M_TEXT is null)) begin
-- update OD_DOCS set ID = 0, STATE = 3 where ID = @CLISER_ID; --REJECT - Отмена обработки
-- end;
--end
else
if @EVENT_TYPE = 'BJ_ORDER_SENT' begin
select @STATE = ID from OD_DOC_STATES where SYS_NAME = 'WAIT_OPER';
update OD_DOCS set ID = 0, STATE = @STATE where ID = @CLISER_ID; --WAIT_OPER = Ожидание исполнения операции
end
else
if @EVENT_TYPE = 'BJ_ORDER_ACCEPTED' begin
--Создаем операцию и проводим ее
exec FTV_M2M_PROCESS_OPERATION @GUID, @REFERENCE, @EVENT_DATE, @PARAMETERS, @OPER_ID out;
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
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 в финале и с проводками, что делать-то?
else
if @EVENT_TYPE = 'BJ_EXECUTED' begin
print 'BJ_EXECUTED --Оно уже в событии BJ_ORDER_ACCEPTED в финале и с проводками, что делать-то?';
end
else
if @EVENT_TYPE = 'BJ_CANCELLED' begin
update OD_DOCS set ID = 0, STATE = 3 where ID = @CLISER_ID; --REJECT = Отмена обработки
end
else
if @EVENT_TYPE = 'BJ_GATEWAY_REJECT' begin
update OD_DOCS set ID = 0, STATE = 3 where ID = @CLISER_ID; --REJECT = Отмена обработки
--ОНО по строке, и не понятно что делать
end
else
--TODO что делать если контрагент проставил статус не по всем строкам документа??
if @EVENT_TYPE = 'BJ_CP_CONFIRM' and @DIRECTION = 'OUT' begin
update OD_DOCS set ID = 0, STATE = 1 where ID = @CLISER_ID; --START - Начало обработки (зарегистрирован) --ОНО И ТАК УЖЕ ДОЛЖНО БЫТЬ В ЭТОМ СОСТОЯНИИ!!!
end
else
if @EVENT_TYPE in
(
'BJ_ORDER_LATE',
'BJ_PING',
'BJ_QUIK_BLOCKED',
'BJ_QUIK_RELEASED',
'BJ_QUIK_SIGNED',
'BJ_QUIK_DEPOSITED'
) begin
print 'ничего не делать';
end
else begin
set @RAISERROR = 'От сервиса BJ получено неизвестное событие ' + @EVENT_TYPE;
raiserror (@RAISERROR, 16, 1);
end;