| 
 
  
	| Модуль выгрузки заявлений на соц выплаты 
 
 |  
	
		| Предыдущая тема :: Следующая тема |  
		| Автор | Сообщение |  
		| MVZ Участник со стажем
 
 
 Вступление в Клуб: 14.03.2023
 
 | 
			
				|  Пт Апр 21, 2023 08:26   Модуль выгрузки заявлений на соц выплаты |   |  
				| Полезность: Нет оценки 
 |  
				| Коллеги так уж случилось, что я ухожу из банка, в котором мне посчастливилось прикоснуться к системе ЦФТ. За примерно 2 месяца, конечно много мне не удалось узнать, однако я реализовал один небольшой проект, по выгрузке заявлений на соц выплаты, для последующей отправки в правительство.
 Хочу попросить вашей экспертной оценки моего кода
 
 Тело
 
  	  | Код: |  	  | /*
 *   Дата      Автор               Задача         Описание
 *   ----------      --------------   ----------   ---------------------------------------------------
 *   27.03.2023   ***.    [MZ]      #28906   Согласно ТЗ необходимо реализовать следующий функционал
 *                                       1. Сформировать реестр документов типа *** (заявление о зачислении соц.выплат)
 *
 *                                       2. Выгрузить архивы документов с сортировкой по городским округам в ***
 *                                          - Согласно комметариев от *** "... всё, что не входит в обозначенные ГО - уходят в папку ***."
 *
 *
 *
 */
 
 BEGIN
 
 NULL;
 
 END;
 
 | 
 
 Проверка
 
  	  | Код: |  	  | pragma include ([RUNTIME]::[MACRO_LIB]);
 pragma include ([RUNTIME]::[CSMD]);
 pragma include ([RUNTIME]::[DEBUG_MACRO]);
 pragma include ([FILE_SALARY]::[MACRO_LIB]);
 pragma include ([DEFVALS]::[SLIB]);
 
 TYPE clients_query IS
 
 SELECT cl( cl                           :    id,
 cl.[NAME]                     :   C_NAME,
 cl.[DOCS].[DOC_TYPE].[NAME]       :   C_DOC_TYPE,
 cl.[DOCS].[CREATED]             :   C_DOC_DATE,
 addr%class                     :   C_C,
 addr_str.[NAME]                  :   C_STR_NAME,
 addr_dst%id                     :   C_DISTRICT_ID,
 addr_dst.[NAME]                  :   C_DISTRICT_NAME,
 addr_cty.[NAME]                  :   C_CITY_NAME,
 addr_reg.[OFF_NAME]            :   C_REGION_NAME,
 addr_reg.[NAME]                  :   C_ICWINNER,
 (select u(u%id) in ::[PATT_SIGNS] all where u%collection = cl.[DOCS].[DATA] fetch 1) : C_REF_FILE_DATA
 ) IN ::[CL_PRIV]
 
 LEFT JOIN ( ::[PERSONAL_ADDRESS] ALL : addr) ON addr%collection = cl.[ADDRESSES] AND addr.[TYPE] = ::[ADDRESS_TYPE](KOD = 'REGISTRATION')
 
 LEFT JOIN(::ADDRESS_OBJ ALL : addr_str ) ON addr.[ADDR_OBJ] = addr_str%id
 LEFT JOIN(::ADDRESS_OBJ ALL : addr_cty ) ON addr_str.[PARENT_M]  = addr_cty%id
 LEFT JOIN(::ADDRESS_OBJ ALL : addr_dst ) ON addr_cty.[PARENT_M] = addr_dst%id
 LEFT JOIN(::ADDRESS_OBJ ALL : addr_reg ) ON addr_dst.[PARENT_M] = addr_reg%id
 
 WHERE cl.[DOCS].[DOC_TYPE] = ::[TYPE_GRAPHIC](CODE = 'ITR_ZACH_SOTS')
 AND cl.[DOCS].[CREATED] >= V_DATE_BEG
 AND cl.[DOCS].[CREATED] <= V_DATE_END
 AND addr_reg.[OFF_NAME] = '***'
 ORDER BY addr_dst.[NAME], cl.[NAME] ;
 
 TYPE clients_query_ref IS REF CURSOR RETURN clients_query;
 v_cur clients_query_ref;
 
 i INTEGER := 0;
 
 TYPE o_fio IS RECORD ( first_name STRING, last_name STRING, patr_name STRING );
 
 BEGIN
 &prn_dbg('::[PRC_SCHEME].[LIST_SCH_PRC]%type = ' || ::[PRC_SCHEME].[LIST_SCH_PRC]%type);
 
 IF P_MESSAGE = 'DEFAULT' THEN
 V_DATE_END := SYSDATE();
 
 VAR sName VARCHAR2;
 VAR casta VARCHAR2;
 VAR foundation VARCHAR2;
 VAR SPLITTER    VARCHAR2(1) := ',';
 
 ::[USER].[LIB_DL].GetDlByUser(::[RUNTIME].[STDLIB].UserId(), 'И', P_EMPLOYEE, casta, foundation);
 
 ELSIF P_MESSAGE = 'VALIDATE' THEN
 
 IF P_INFO = 'BTN_BUILD_LIST' THEN
 V_INFO := '';
 var l_unload_path STRING; -- Путь для выгрузки файлов
 
 v_cur.open(clients_query);
 P_STATEMENTS_LIST.delete;
 var o_refTemp ref [PATT_SIGNS];
 
 FOR v_client IN  CURSOR clients_query LOOP
 
 i             := P_STATEMENTS_LIST.count+1;
 l_unload_path   := '';
 o_refTemp       := v_client.C_REF_FILE_DATA;
 
 P_STATEMENTS_LIST(i).[IS_UNLOAD]         := TRUE;
 P_STATEMENTS_LIST(i).[URBAN_DISTRICT]      := v_client.C_DISTRICT_NAME;
 P_STATEMENTS_LIST(i).[APPLICANT]          := INITCAP(v_client.c_name);
 P_STATEMENTS_LIST(i).[STATEMENT_DATE]    := v_client.C_DOC_DATE;
 P_STATEMENTS_LIST(i).[STATEMENT_CITY]    := v_client.C_CITY_NAME;
 P_STATEMENTS_LIST(i).[REF_PATT_SIGNS]    := o_refTemp;
 
 P_STATEMENTS_LIST(i).[STATUS]             := 'Добавлен в реестр на выгрузку.';
 P_STATEMENTS_LIST(i).[UNLOAD_PATH]       := '***' ||  v_client.C_DISTRICT_NAME;
 
 END LOOP; -- FOR v_client IN  CURSOR clients_query
 
 V_INFO := 'За указанный период найдено ' || i || ' заявлений о зачислении соц.выплат.';
 v_cur.CLOSE;
 
 END IF;--  'BTN_BUILD_LIST'
 
 /*--------------------------------------------------*/
 
 IF P_INFO = 'BTN_SAVE_2_DISK' THEN
 VAR l_io_result_code INTEGER;
 VAR xblob         [BLOB];
 VAR out_blob      [BLOB];
 VAR l_fileName       STRING;
 VAR l_archName   STRING;
 VAR file_extension   STRING;
 VAR fio             o_fio;
 VAR v_ret         varchar2(32000);
 -- Формируем временную папку для файлов
 VAR pathServer [SYSTEM_PARAMS]::[VALUE]%type := GetPath2TempFolderOnServer();
 var rFile_name    varchar2(255);      --имя создаваемого файла
 var v_res       integer;
 var iTxt         integer;
 var vStr         varchar2(1000);
 
 rFile_name    :=  'Пртокол-выгрузки-' || TO_CHAR(SYSDATE, 'DD-MON-YY') || '.csv';
 iTxt          := stdio.open(pathServer,rFile_name,'w');
 
 vStr :=   'ВРЕМЯ' ||
 SPLITTER || 'ФАЙЛ АБС' ||
 SPLITTER || 'ГОРОДСКОЙ ОКРУГ' ||
 SPLITTER || 'ВЛАДЕЛЕЦ' ||
 SPLITTER || 'ИМЯ ФАЙЛА ДЛЯ ЦСПСО' ||
 SPLITTER || 'ПУТЬ ВЫГРУЗКИ';
 vStr      := vStr || chr(13)  || chr(10);
 
 v_res    := stdio.WRITE_STR(iTxt,vStr,null,stdio.WINTEXT,false);
 
 FOR i in 1..P_STATEMENTS_LIST.Count LOOP
 
 IF (P_STATEMENTS_LIST(i).[IS_UNLOAD]) THEN
 vStr := '';
 -- 1.
 --    Разберем ФИО и сформируем правильное имя файла.
 --    В АБС системе файлы с Заявлениями *** именуются "по-разному" от соцка.pdf до бесконечности.
 --    будет правильным присвоить ему более описательное имя и на английском языке, чтобы избежать возможных проблемм с кодировкой на стороне приема
 --    На выходе из  прим .соцка.pdf от Иванова Ивана Ивановича будет ***-SSA-Ivanov_II.pdf
 --   SSA от Social Security Application Заявление на Социальную Выплату
 
 fio.last_name   := INITCAP(Translit2Eng(regexp_substr(P_STATEMENTS_LIST(i).[APPLICANT], '^[^ ]*')));
 fio.first_name   := SUBSTR(Translit2Eng(trim(replace(regexp_substr(P_STATEMENTS_LIST(i).[APPLICANT], ' .*[. ]'), '.'))),1,1);
 fio.patr_name   := SUBSTR(Translit2Eng(regexp_substr(P_STATEMENTS_LIST(i).[APPLICANT], '[^ .]*$')),1,1);
 file_extension    := REGEXP_SUBSTR( P_STATEMENTS_LIST(i).[REF_PATT_SIGNS].[FILENAME],'(.[^.]*)?$', 1, 1, null, 1);
 l_fileName      := 'ITURUP-SSA-' || fio.last_name || fio.first_name || fio.patr_name ||  '_' || TO_CHAR(P_STATEMENTS_LIST(i).[STATEMENT_DATE], 'DD-MM-YY') || file_extension;
 l_archName      := 'ITURUP-SSA-' || fio.last_name || fio.first_name || fio.patr_name ||  '_' || TO_CHAR(P_STATEMENTS_LIST(i).[STATEMENT_DATE], 'DD-MM-YY') || '.zip';
 
 -- 2.
 --   Выгрузим файл на сервер
 [LOB_UTILS].blob2file(P_STATEMENTS_LIST(i).[REF_PATT_SIGNS].[IMAGE], pathServer, l_fileName);
 
 -- 3.
 --   Сформируем архив с файлом
 --    Подготовим транзитный буфер
 dbms_lob.CreateTemporary(xblob, true);
 dbms_lob.CreateTemporary(out_blob, true);
 
 ::[RUNTIME].[LOB_UTILS].file2blob(xblob, pathServer, l_fileName);
 ::[RUNTIME].[ZIP].add_file(out_blob, l_fileName, xblob);
 ::[RUNTIME].[ZIP].finish_zip(out_blob);
 [LOB_UTILS].blob2file(out_blob, pathServer, l_archName);
 
 -- Чистим буфер
 dbms_lob.FreeTemporary(out_blob);
 dbms_lob.FreeTemporary(xblob);
 
 --&prn_dbg('full name  = ' || P_STATEMENTS_LIST(i).[APPLICANT]);
 --&prn_dbg('File name = ' || l_fileName);
 
 -- 4.
 --    Удалим временный файл
 BEGIN
 stdio.delete_file(pathServer || SysInfo.GetValue('DEF_SLASH') || l_fileName);
 P_STATEMENTS_LIST(i).[STATUS] := 'Выгружен. см.: ' || rFile_name;
 
 EXCEPTION WHEN OTHERS THEN
 P_STATEMENTS_LIST(i).[STATUS] := 'ОШИБКА ПРИ ПОПЫТКЕ УДАЛЕНИЯ ФАЙЛА: '|| l_fileName || 'НА СЕРВЕРЕ АБС.';
 END;
 
 -- 6.
 --   Копируем архив с папки на сервере АБС в сетевую папку на клиенте АБС
 BEGIN
 SendFile( pathServer || SysInfo.GetValue('DEF_SLASH') || l_archName,   -- Откуда
 P_STATEMENTS_LIST(i).[UNLOAD_PATH],               -- Куда
 true);                                          -- Удалять после копирования ?
 
 vStr :=    TO_CHAR(SYSDATE, 'HH24:MI:SS') ||
 SPLITTER || P_STATEMENTS_LIST(i).[REF_PATT_SIGNS].[FILENAME] ||
 SPLITTER || P_STATEMENTS_LIST(i).[URBAN_DISTRICT] ||
 SPLITTER || P_STATEMENTS_LIST(i).[APPLICANT] ||
 SPLITTER || l_fileName ||
 SPLITTER || P_STATEMENTS_LIST(i).[UNLOAD_PATH] || '' || l_archName;
 
 EXCEPTION WHEN OTHERS THEN
 
 vStr :=    'ОШИБКА ПЕРЕНОСА ФАЙЛА С СЕРВЕРА АБС НА СЕТЕВОЙ ДИСК' ||
 SPLITTER || P_STATEMENTS_LIST(i).[REF_PATT_SIGNS].[FILENAME] ||
 SPLITTER || P_STATEMENTS_LIST(i).[URBAN_DISTRICT] ||
 SPLITTER || P_STATEMENTS_LIST(i).[APPLICANT] ||
 SPLITTER || l_fileName ||
 SPLITTER || P_STATEMENTS_LIST(i).[UNLOAD_PATH] || '' || l_archName;
 END;
 
 -- 7.
 --   Добавим информацию в протокол выгрузки
 vStr      := vStr || chr(13)  || chr(10);
 v_res    := stdio.WRITE_STR(iTxt,vStr,null,stdio.WINTEXT,false);
 
 END IF;
 END LOOP;
 
 -- 8
 --   Добавим информацию об отвественном лице
 vStr    := chr(13)  || chr(10) ;
 vStr    := vStr || 'Отвественный(ая): ' || P_EMPLOYEE;
 vStr    := vStr || chr(13)  || chr(10);
 v_res    := stdio.WRITE_STR(iTxt,vStr,null,stdio.WINTEXT,false);
 
 stdio.close(iTxt);
 
 -- 9.
 --   Перенесем протокол с сервера на сетевой диск
 
 SendFile( pathServer || SysInfo.GetValue('DEF_SLASH') || rFile_name,   -- Откуда
 'R:Обмен данными с ЦСПСО',                        -- Куда
 true);                                          -- Удалять после копирования ?
 
 END IF; -- 'BTN_SAVE_2_DISK'
 
 
 END IF;
 
 END;
 
 
 | 
 
 Локальные описания
 
  	  | Код: |  	  | pragma include (::[RUNTIME].[MACRO_LIB]);
 pragma include(::[CIT_INTERFACE].[LIB_EA]);
 pragma macro(cf,   '::[DOCUMENT].[COPYFILES]');
 pragma macro(quote,   '[1]', substitute, quoted);
 
 sDebugPipeName STRING := 'MVZ';
 pragma macro(prn_dbg, 'stdio.put_line_pipe(''::['' || &METHOD$CLASS || ''].['' || &METHOD$SNAME || '']: '' || [1], sDebugPipeName)', substitute);
 
 --TYPE o_fio IS RECORD ( first_name STRING, last_name STRING, patr_name STRING );
 
 function get_parent_addr_obj         -- Получение для адресного объекта первого вышестоящего заданного типа(класса).
 ( p_obj ref [ADDRESS_OBJ]      -- Ссылка на адресный объект.
 , p_class varchar2(128)          -- Требуемый тип(класс) адресного объекта
 , p_level integer := null          -- Требуемый уровень адресного объекта
 )
 return ref [ADDRESS_OBJ] -- Ссылка на адресный объект
 is
 begin
 if p_level is null then
 for (with recursive rc(id, parent, cls, nocyc) as (
 select x(x, x.[PARENT], x%class, ','||x||',') in ::[ADDRESS_OBJ] where x = p_obj
 union all
 select x(x, x.[PARENT], x%class, rr.nocyc||x||',')
 in ::[ADDRESS_OBJ]
 join (rc : rr) on rr.parent = x and rr.cls <> p_class and instr(rr.nocyc, ','||x||',') = 0)
 select r(r.id : obj) in rc where r.cls = p_class)
 loop
 return r.obj;
 end loop;
 else
 for (with recursive rc(id, parent, lvl, nocyc) as (
 select x(x, x.[PARENT], 1, ','||x||',') in ::[ADDRESS_OBJ] where x = p_obj
 union all
 select x(x, x.[PARENT], rr.lvl+1, rr.nocyc||x||',')
 in ::[ADDRESS_OBJ]
 join (rc : rr) on rr.parent = x and instr(rr.nocyc, ','||x||',') = 0)
 select o(o : obj)
 in ::[ADDRESS_OBJ]
 join (rc : rr) on o = rr.id
 join (::[PEOPLE_PLACE] : t) on o.[KIND] = t and t.[OBJ_LEVEL] = p_level
 where o%class = p_class
 order by rr.lvl)
 loop
 return o.obj;
 end loop;
 end if;
 return null;
 end;
 
 l_def_slash constant varchar2(1)   := ::[RUNTIME].[STDIO].get_setting('DEF_SLASH');
 
 -- [MZ]  Функция создает временный каталог для файлов, которые собираются при записи на диск и возвращает путь к нему
 --       Заимствованна из модуля [Продукты].[Электронный архив].[Библиотека]
 public function GetPath2TempFolderOnServer( p_emp integer := null ) return string(250) is
 TmpPath string(250)      := '';
 res integer;
 --l_def_slash string(8)    :=  SysInfo.GetValue('DEF_SLASH');
 l_fio_root_dir string(250)   := rtrim(trim(stdio.Get_Env('FIO_ROOT_DIR')), l_def_slash);
 l_win_csid number       := ::[RUNTIME].[CHARSET].map_charset('CL8MSWIN1251',2,1);
 
 begin
 TmpPath := l_fio_root_dir || l_def_slash;
 
 TmpPath := TmpPath || 'EARCHIVE' || l_def_slash;
 res := stdio.MkDir(TmpPath, 255);
 
 TmpPath := TmpPath || 'TEMP_DIR' || l_def_slash;
 res := stdio.MkDir(TmpPath, 255);
 
 TmpPath := TmpPath || 'EARCHIVE_TMP_CSPO';
 res := stdio.MkDir(TmpPath, 255);
 
 return TmpPath;
 end;
 
 -- [MZ] Заимствована из модуля Идетификация клиента -> Продукты -> Договор банка с клиентом
 function Translit2Eng
 /* Транслитерация символов строки */
 ( P_STR         string
 /* Строка для обработки */
 )
 /* Возвращается преобразованная строка */
 return   string is
 s string(2000);
 begin
 s := P_STR;
 s := upper(s);
 s := standard.replace(s,  'Ж', 'ZH');
 s := standard.replace(s,  'Х', 'KH');
 s := standard.replace(s,  'Ю', 'IU');
 s := standard.replace(s,  'Ц', 'TS');
 s := standard.replace(s,  'Ч', 'CH');
 s := standard.replace(s,  'Ш', 'SH');
 s := standard.replace(s,  'Щ', 'SHCH');
 s := standard.replace(s,  'Ъ', 'IE');
 s := standard.replace(s,  'Ь', '');
 s := standard.replace(s,  'Я', 'IA');
 s := standard.translate
 ( s   ,'ЁУКЕНГЗФЫВАПРОЛДЭСМИТБЙ'
 ,'EUKENGZFYVAPROLDASMITBI'
 );
 
 return s;
 end;
 
 -- [MZ] Заимствованна из [Типы данных] -> [Справочники] -> [ОП Данные Библиотека. Работа с файлом]
 /** Функция возвращает имя файла из переданного пути.
 */
 public function GetFile(p_file varchar2(32767)) return varchar2 is
 vFile   varchar2(32767);
 begin
 vFile := CorrectPath(p_file);
 return substr(vFile, instr(vFile, l_def_slash, -1) +1);
 end;
 
 -- [MZ] Заимствованна из [Типы данных] -> [Справочники] -> [ОП Данные Библиотека. Работа с файлом]
 --   Путь до каталога на сервере, предназначенного для выполнения файловых операций
 public function default_server_path return varchar2 is
 begin
 return CorrectPath(coalesce(::[SYSTEM_PARAMS].[GET]('REPS_PATH', null), ::[SYSTEM_PARAMS].[GET]('PATH', null), '.'));
 end;
 
 -- [MZ] Заимствованна из [Типы данных] -> [Справочники] -> [ОП Данные Библиотека. Работа с файлом]
 --   Путь до каталога на локальной станции пользователя
 public function default_local_path return varchar2 is
 begin
 return CorrectPath(coalesce(::[SYSTEM_PARAMS].[GET]('PATH_LOCAL', true), '.'), p_windows == true);
 end;
 
 -- [MZ] Заимствованна из [Типы данных] -> [Справочники] -> [ОП Данные Библиотека. Работа с файлом]
 /**   Функция выполняет корректировку пути p_path к гарантированно валидному в системе.
 *   Если производится корректировка путей локальной станции, следует указать флаг p_windows == true
 *   Возвращает корректный путь.
 */
 public function CorrectPath
 (
 p_file varchar2(32767)
 ,   p_windows boolean := false
 )
 return varchar2
 is
 vTmp   varchar2(32767);
 vFile   varchar2(32767);
 begin
 --   заменяем все обратные слэши на прямые. Теперь в строке есть только прямые слэши
 vTmp   := replace(p_file, '', '/');
 vFile   := vTmp;
 
 -- Если в строке встречаются парные слэши, то заменяем их на одинарный
 while vTmp like '%//%' loop
 vTmp := replace(vTmp, '//', '/');
 end loop;
 
 -- убираем последний в строке пробел и последний разделитель
 vTmp := rtrim(vTmp, ' /');
 
 -- заменяем прямой слэш на установленный в системе и возвращаем преобразованную строку
 vTmp := replace(vTmp,'/', l_def_slash);
 
 --   если корректировка осуществляется с путём на локальной станции пользователя (с ОС Windows), то заменяем прямые слэши на обратные
 if p_windows then
 if vFile like '//%' then
 return replace('/'||vTmp,'/','');
 end if;
 return replace(vTmp,'/','');
 end if;
 
 return vTmp ;
 end;
 
 -- [MZ] Заимствованна из [Типы данных] -> [Справочники] -> [ОП Данные Библиотека. Работа с файлом]
 /** Функция возвращает цепочку каталогов из переданного пути. Если пути нет, возвращает null.
 *   По умолчанию функция работает по правилам обработки путей формата UNIX.
 *   Для обработки по правилам обработки путей формата WINDOWS, нужно передать параметр p_windows == true.
 */
 public function GetPath(p_file varchar2(32767), p_windows boolean := false) return varchar2 is
 vFile   varchar2(32767);
 vSlash   varchar2(32767);
 begin
 --   подготавливаем переменные
 vFile := CorrectPath(p_file, p_windows);
 
 vSlash := l_def_slash;
 if p_windows then
 vSlash := '';
 end if;
 
 --   Выполняем поиск последнего вхождения слэша, возвращаем результат.
 return substr(vFile, 1, instr(vFile, vSlash, -1) - 1);
 end;
 
 /**   Инициализация структуры COPYFILES
 */
 procedure InitCopyFiles is
 begin
 for i in nvl(&cf.tbl_F$L.first, 1) .. nvl(&cf.tbl_F$L.last, 0) loop
 if &cf.tbl_F$L(i).[SRC_TYPE] is null then
 &cf.tbl_F$L.delete;
 exit;
 end if;
 end loop;
 
 &cf.idx := nvl(&cf.tbl_F$L.last, 0);
 end;
 
 -- [MZ] Заимствованна из [Типы данных] -> [Справочники] -> [ОП Данные Библиотека. Работа с файлом]
 /**   Функция подготавливает файл для отправки с сервера на локальную станцию.
 *   Возвращает строку запуска.
 *   параметр p_src_file - указывает путь и имя файла на сервере;
 *   параметр p_target_file - указывает путь и имя файла на локальной станции, в который файл нужно сохранить при передаче;
 *   Путь на сервере может быть полный или относительный.
 *   Путь на локальной станции должен быть полным.
 *   Пример использования:
 *   stdio.put_line_buf(
 *      ::[REPS_DATA].[LIB_FILE].SendFile(   './qwerty123.log'
 *                              ,   'c:ibsodokqwerty123_log.txt'
 *                              ,   true   )
 *   );
 */
 public function SendFile(
 p_src_file      varchar2(32767)
 ,   p_target_file   varchar2(32767)
 ,   p_del_src      boolean      := false
 ) return varchar2 is
 vSrcFile   varchar2(32767);
 vSrcDir   varchar2(32767);
 vTgtFile   varchar2(32767);
 vTgtDir   varchar2(32767);
 
 vTmp      varchar2(32767);
 begin
 InitCopyFiles;
 
 --   источник - сервер
 --   разделяем полное имя файла на путь и имя файла
 vSrcFile      := p_src_file;
 vSrcDir      := coalesce(GetPath(vSrcFile), default_server_path);
 vSrcDir      := CorrectPath(vSrcDir);
 vSrcFile      := GetFile(vSrcFile);
 
 --   заполняем значение элемента в массиве
 &cf.tbl_F$L(&cf.idx+1).[SRC_TYPE]      := true;      --   server size
 &cf.tbl_F$L(&cf.idx+1).[SRC_NAME]      := vSrcFile;   --   имя файла-источника
 &cf.tbl_F$L(&cf.idx+1).[SRC_PATH]      := vSrcDir;      --   путь до файла-источника
 &cf.tbl_F$L(&cf.idx+1).[SRC_DELETE]   := p_del_src;   --   признак удаления
 
 --   получатель - клиент
 --   разделяем полное имя файла на путь и имя файла
 /* [MZ] Дистрибутивный код закомментирован
 vTgtFile   := p_target_file;
 vTgtDir   := coalesce(GetPath(vTgtFile, true), default_local_path);
 vTgtDir   := CorrectPath(vTgtDir, true);
 vTgtDir   := vTgtDir;
 vTgtFile   := GetFile(vTgtFile);
 */
 vTgtFile   := vSrcFile;
 vTgtDir   := p_target_file || '';
 
 --   заполняем значение элемента в массиве
 &cf.tbl_F$L(&cf.idx+1).[DST_TYPE]      := false;      --   client size
 &cf.tbl_F$L(&cf.idx+1).[DST_NAME]      := vTgtFile;   --   имя файла-приёмника
 &cf.tbl_F$L(&cf.idx+1).[DST_PATH]      := vTgtDir;   --   путь до файла-приёмника
 &cf.tbl_F$L(&cf.idx+1).[DST_DELETE]   := false;      --   не удалять
 
 &cf.idx := 0;
 
 --   возвращаем строчку запуска
 vTmp := "e(&cf);
 vTmp := translate(vTmp, ':[].', '    ');
 vTmp := regexp_replace(' '||vTmp||' ', ' +', ' ');
 
 &prn_dbg('Копирую файл с сервера: "' ||
 vSrcDir || vSrcFile ||
 '" на клиента в: "' ||
 vTgtDir ||  vTgtFile || '"');
 
 stdio.put_line_buf('<% CALL DOCUMENT COPYFILES '||nvl(::[SYSTEM]%id, 1)||' %>');
 return '<% CALL' || vTmp || nvl(::[SYSTEM]%id, 1) || ' %>';
 end;
 
 /**   Функция проверяет существование каталога p_path
 */
 public function DirectoryExists(p_path varchar2(32767))
 return boolean is
 iState   integer;
 vPath   varchar2(32767);
 begin
 vPath := CorrectPath(p_path);
 iState := ::[RUNTIME].[STDIO].opendir(dirname == vPath, dir_flag == 1);
 if iState = -2 then -- каталог не найден
 return false;
 elsif iState < 0 then
 return false;
 end if;
 
 iState := ::[RUNTIME].[STDIO].closedir(iState);
 return true;
 end;
 
 
 
 | 
 
 Кстати сказать, буду рад поработать с ЦФТ в удаленном формате. Если ест предложения пишите в личку.
 
 С Уважением,
 Максим.
 |  |  
		|  |  
		|  |  
  
	| 
 
 | Вы не можете начинать темы Вы не можете отвечать на сообщения
 Вы не можете редактировать свои сообщения
 Вы не можете удалять свои сообщения
 Вы не можете голосовать в опросах
 
 |  |