Приведение наименований в менеджере — различия между версиями
Материал из wiki.standart-n.ru
Aleksnick (обсуждение | вклад) |
Aleksnick (обсуждение | вклад) |
||
Строка 16: | Строка 16: | ||
order by log_insertdt desc | order by log_insertdt desc | ||
</pre> | </pre> | ||
− | ''' | + | '''1. В таблице wares_log есть записи с одинаковыми реальными полями, но они ссылаются на разные товары, а сортировка по log_insertdt неправильна, т.к. это поле не везде заполнено.''' |
+ | '''2. Вроде бы записи с actual_ware_id должны удаляться.''' | ||
+ | '''3. Есть записи, которые ни по id ни по actual_ware_id не ссылаются на существующий варес.''' | ||
<pre> | <pre> | ||
select min(iif(wl.actual_ware_id is null, wl.id, wl.actual_ware_id)), max(iif(wl.actual_ware_id is null, wl.id, wl.actual_ware_id)) | select min(iif(wl.actual_ware_id is null, wl.id, wl.actual_ware_id)), max(iif(wl.actual_ware_id is null, wl.id, wl.actual_ware_id)) |
Версия 09:56, 16 августа 2016
Содержание
Алгоритм работы приведения с Единым Окном
Этап 1: Открытие электронной накладной
При открытии накладной срабатывает процедура PR_MAKEGOODWAREVALUES.
- Вначале неё по каждому полю (sname, sizg, scountry, sorig_name, sorig_izg, sorig_country) ищем id значений из таблицы vals.
select id from vals where vtype=0 and alttype=:alttype and svalue=:sname into :name_id; ...
- Затем вызывается процедура PR_GETWARE_BY_IDS
select ware_id from PR_GETWARE_BY_IDS(:name_id,:izg_id,:country_id,:orig_code,:orig_name_id,:orig_izg_id,:orig_country_id,0,1, :barcode) into :ware_id;
- В данной процедуре идет поиск карточки товара по реальным полям в таблице связок wares_log.
select first 1 iif(actual_ware_id is null, id, actual_ware_id) from wares_log where name_id=:name_id and izg_id=:izg_id and country_id=:country_id and barcode=:barcode order by log_insertdt desc
1. В таблице wares_log есть записи с одинаковыми реальными полями, но они ссылаются на разные товары, а сортировка по log_insertdt неправильна, т.к. это поле не везде заполнено. 2. Вроде бы записи с actual_ware_id должны удаляться. 3. Есть записи, которые ни по id ни по actual_ware_id не ссылаются на существующий варес.
select min(iif(wl.actual_ware_id is null, wl.id, wl.actual_ware_id)), max(iif(wl.actual_ware_id is null, wl.id, wl.actual_ware_id)) from wares_log wl group by wl.name_id, wl.izg_id, wl.country_id, wl.barcode having count(iif(wl.actual_ware_id is null, wl.id, wl.actual_ware_id))>1
- Если мы нашли готовую карточку товара, в связках, то затем находим ее в таблице wares и берем все ее значения. После чего выходим из процедуры:
if (ware_id is not null) then begin select sname, sizg, scountry, barcode from VW_WARES where id=:ware_id into :goodname, :goodizg, :goodcountry, :goodbarcode; if (goodname is null) then goodname = sname; ... exit; end
ЗАЧЕМ??? Если нет связки, то нет и карточки!!!
- Если готовую карточку не нашли, то снова пытаемся ее найти, вызывая процедуру PR_GETWARE_BY_IDS, но уже с параметром searchinlogs=null
select ware_id from PR_GETWARE_BY_IDS(:name_id,:izg_id,:country_id,:orig_code,:orig_name_id,:orig_izg_id,:orig_country_id,0,null, :barcode) into :ware_id;
- Если всетаки нашлась карточка, то берем из нее реальные поля:
if (ware_id is not null) then begin goodname=sname; goodizg=sizg; goodcountry=scountry; goodbarcode=barcode; suspend; exit; end
- Затем пытаемся отдельно привести каждое из реальных полей.
- Если есть оригинальное значение, то ищем первую попавшуюся карточку товара с данным значением:
select first 1 id from wares where orig_name_id=:orig_name_id order by id desc into :ware_id;
Зачем??? В таблице wares оригинальные поля вообще не будут актуальными!!!
- Если не нашли, то приводим значение через связки:
if (ware_id is null) then select first 1 iif(actual_ware_id is null, id, actual_ware_id) from wares_log where orig_name_id=:orig_name_id order by log_id desc into :ware_id;
Поле log_id имеет тип d$uuid - связка может найтись не самая актуальная.
- Если мы ничего не нашли, то ищем по реальному полю. Точно также: сначала в таблице wares, затем wares_log.
if ((ware_id is null) and (name_id is not null)) then begin select first 1 id from wares where name_id=:name_id into :ware_id; if (ware_id is null) then select first 1 iif(actual_ware_id is null, id, actual_ware_id) from wares_log where name_id=:name_id order by log_id desc into :ware_id; end
Почему бы сразу не искать в таблице wares_log???
- Затем точно также делаем по изготовителю и стране.
- Возвращаем полученные значения.
Этап 2: Проведение активного документа
На каждый товар срабатывает процедура PR_GET_WARE.
- Берутся и при необходимости создаются справочные значения для всех реальных и оригинальных полей:
select VAL_ID from PR_GETVAL_ID(:SNAME, 0, :ALTTYPE, :MNN) into :NAME_ID; ...
- Идет поиск карточки товара по реальным полям:
select ID from WARES where NAME_ID = :NAME_ID and IZG_ID = :IZG_ID and COUNTRY_ID = :COUNTRY_ID and BARCODE = :BARCODE into :W_ID;
- Если карточка нашлась, то выходим из процедуры, иначе создаем новую карточку:
if (W_ID is null) then begin W_ID = uuid_to_char(gen_uuid()); insert into WARES (ID, NAME_ID, IZG_ID, COUNTRY_ID, ORIG_CODE, ORIG_NAME_ID, ORIG_IZG_ID, ORIG_COUNTRY_ID, BARCODE, Z_ID, SKLAD_ID) values (:W_ID, :NAME_ID, :IZG_ID, :COUNTRY_ID, :ORIG_CODE, :ORIG_NAME_ID, :ORIG_IZG_ID, :ORIG_COUNTRY_ID, :BARCODE, :Z_ID, :SKLAD_ID); end suspend;
Установка процедур
Устанавливаем процедуру PR_GET_WARE.
SET TERM ^ ; create or alter procedure PR_INSTALL_PR_GET_WARE as declare variable IDX_U_EXISTS DM_STATUS; declare variable IDX_100_EXISTS DM_STATUS; declare variable GLOBAL_ID DM_STATUS; declare variable INDEX_NAME DM_TEXT; declare variable S DM_TEXT_BIG; declare variable FIELD DM_TEXT; begin /* определяем база с глобальными наименованиями или нет */ if ((select upper(RF.RDB$FIELD_SOURCE) from RDB$RELATION_FIELDS RF where 1 = 1 and RF.RDB$FIELD_NAME = 'ID' and RF.RDB$RELATION_NAME = 'WARES') = 'DM_UUID') then GLOBAL_ID = 1; else GLOBAL_ID = 0; /* определяем единое окно установлено или нет */ if ((select first 1 count(1) from RDB$INDICES RIN where RIN.RDB$INDEX_NAME = 'WARES_IDX_U' and RIN.RDB$RELATION_NAME = 'WARES') > 0) then IDX_U_EXISTS = 1; else IDX_U_EXISTS = 0; /* определяем из какого индекса брать список полей, отвечающих за уникальность товаров */ if (IDX_U_EXISTS = 1) then INDEX_NAME = 'WARES_IDX_U'; else INDEX_NAME = 'WARES_IDX1'; /* определяем установлен ли хэш индекс */ if ((select first 1 count(1) from RDB$INDICES RIN where RIN.RDB$INDEX_NAME = 'WARES_IDX100' and RIN.RDB$RELATION_NAME = 'WARES') > 0) then IDX_100_EXISTS = 1; else IDX_100_EXISTS = 0; /* входные параметры процедуры */ S = ' create or alter procedure PR_GET_WARE ( SNAME type of DM_TEXT, SIZG type of DM_TEXT, SCOUNTRY type of DM_TEXT, ORIG_CODE type of DM_TEXT = '''', SORIG_NAME type of DM_TEXT = '''', SORIG_IZG type of DM_TEXT = '''', SORIG_COUNTRY type of DM_TEXT = '''', BARCODE type of DM_TEXT = '''', Z_ID type of DM_ID = 0, SKLAD_ID DM_TEXT = '''', ALTTYPE DM_STATUS = 0, MNN DM_TEXT = '''') returns ( '; /* выходные параметры процедуры */ if (GLOBAL_ID = 1) then S = S || 'W_ID type of DM_UUID_NULL)'; else S = S || 'W_ID type of DM_ID)'; /* внутренние параметры процедуры */ S = S || ' as declare variable OLD_BARCODE DM_TEXT1024;'; /* для базы с глобальными наименованиями типы полей DM_UUID_NULL */ if (GLOBAL_ID = 1) then S = S || ' declare variable NAME_ID type of DM_UUID_NULL; declare variable IZG_ID type of DM_UUID_NULL; declare variable COUNTRY_ID type of DM_UUID_NULL; declare variable ORIG_NAME_ID type of DM_UUID_NULL; declare variable ORIG_IZG_ID type of DM_UUID_NULL; declare variable ORIG_COUNTRY_ID type of DM_UUID_NULL; declare variable WHASH DM_ID; '; else /* для базы без глобальных наименований типы полей DM_ID */ S = S || ' declare variable NAME_ID type of DM_ID; declare variable IZG_ID type of DM_ID; declare variable COUNTRY_ID type of DM_ID; declare variable ORIG_NAME_ID type of DM_ID; declare variable ORIG_IZG_ID type of DM_ID; declare variable ORIG_COUNTRY_ID type of DM_ID; declare variable WHASH DM_ID; '; S = S || ' begin '; /* вставляем в процедуру комментарии */ if (GLOBAL_ID = 1) then S = S || ' /* BASE WITH GLOBAL ID */ '; else S = S || ' /* BASE WITHOUT GLOBAL ID */ '; if (IDX_U_EXISTS = 1) then S = S || ' /* BASE WITH WARES_IDX_U */ '; else S = S || ' /* BASE WITHOUT WARES_IDX_U */ '; if (IDX_100_EXISTS = 1) then S = S || ' /* BASE WITH WARES_IDX100 */ '; else S = S || ' /* BASE WITHOUT WARES_IDX100 */ '; /* находим валсы для всех справочных значений */ S = S || ' if (ORIG_CODE is null) then ORIG_CODE = ''''; select VAL_ID from PR_GETVAL_ID(:SNAME, 0, :ALTTYPE, :MNN) into :NAME_ID; select VAL_ID from PR_GETVAL_ID(:SIZG, 3, :ALTTYPE) into :IZG_ID; select VAL_ID from PR_GETVAL_ID(:SCOUNTRY, 2, :ALTTYPE) into :COUNTRY_ID; select VAL_ID from PR_GETVAL_ID(:SORIG_NAME, 1, :ALTTYPE) into :ORIG_NAME_ID; select VAL_ID from PR_GETVAL_ID(:SORIG_IZG, 6, :ALTTYPE) into :ORIG_IZG_ID; select VAL_ID from PR_GETVAL_ID(:SORIG_COUNTRY, 5, :ALTTYPE) into :ORIG_COUNTRY_ID; '; /* если хэш индекса нет */ if (IDX_100_EXISTS = 0) then begin S = S || ' select ID, BARCODE from WARES where 1 = 1 '; /* ищем варес по всем поляем, которые есть в индексе, отвечающем за уникальность карточек */ select list('and ' || trim(RIS.RDB$FIELD_NAME) || ' = :' || trim(RIS.RDB$FIELD_NAME), ascii_char(13)) from RDB$INDEX_SEGMENTS RIS where RIS.RDB$INDEX_NAME = :INDEX_NAME into :FIELD; S = S || :FIELD || ' into :W_ID, :OLD_BARCODE; '; end else /* если хэш индекс есть в базе */ begin S = S || ' whash = ('; /* генерируем хэш по поляем в индексе */ select list('coalesce(:' || trim(RIS.RDB$FIELD_NAME) || ',''' || trim(RIS.RDB$FIELD_NAME) || ''')', ',') from RDB$INDEX_SEGMENTS RIS where RIS.RDB$INDEX_NAME = :INDEX_NAME into :FIELD; S = S || :FIELD || ');'; /* ищем варес по хэшу */ S = S || ' select ID, BARCODE from WARES WHERE WHASH = :WHASH into :W_ID, :OLD_BARCODE; '; end /* если варес не нашли */ S = S || ' if (W_ID is null) then begin '; /* генерируем id */ if (GLOBAL_ID = 1) then S = S || ' W_ID = uuid_to_char(gen_uuid()); '; else S = S || ' W_ID = gen_id(GEN_WARES_ID, 1); '; /* создаем новый варес */ S = S || ' insert into WARES (ID, NAME_ID, IZG_ID, COUNTRY_ID, ORIG_CODE, ORIG_NAME_ID, ORIG_IZG_ID, ORIG_COUNTRY_ID, BARCODE, Z_ID, SKLAD_ID) values (:W_ID, :NAME_ID, :IZG_ID, :COUNTRY_ID, :ORIG_CODE, :ORIG_NAME_ID, :ORIG_IZG_ID, :ORIG_COUNTRY_ID, :BARCODE, :Z_ID, :SKLAD_ID); end else '; /* если штрихкод не в индексе */ S = S || ' if (OLD_BARCODE <> BARCODE) then update WARES set BARCODE = :BARCODE where ID = :W_ID; '; S = S || ' suspend; end '; execute statement(S); end^ SET TERM ; ^ /* Existing privileges on this procedure */ GRANT EXECUTE ON PROCEDURE PR_INSTALL_PR_GET_WARE TO SYSDBA; EXECUTE PROCEDURE PR_INSTALL_PR_GET_WARE; DROP PROCEDURE PR_INSTALL_PR_GET_WARE;