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
This commit is contained in:
fontvielle
2026-10-28 14:25:27 +03:00
parent 03918b1e58
commit d05cba44ec
7 changed files with 157 additions and 11 deletions
@@ -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 в финале и с проводками, что делать-то?
@@ -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 */