d05cba44ec
По ответу программиста 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
245 lines
9.7 KiB
Transact-SQL
245 lines
9.7 KiB
Transact-SQL
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;
|