Проверка подлинности СНИЛС через сервис СМЭВ без использования RS-Connect

Автор:demaio73
Дата:10.03.2017
Просмотров:5698
Скачиваний:649
Оценка:, Оценок - 2
Скачать (rar-файл; Размер - 6145)

Обсудить в форуме

Описание

Проверка подлинности СНИЛС через сервис СМЭВ без использования RS-Connect

Текст примера

 /*
  Проверка подлинности СНИЛС через сервис СМЭВ без использования RS-Connect
  Будет работать, если у вас работает обмен с ГИС-ГМП через "Электронный обмен"
  Васильев Д.В., КБ "РИАЛ-КРЕДИТ"
  декабрь 2016

  Для использования макроса необходим пользовательский макрос ldmklbr.mac,
  есть в "Примеры/Библиотеки разработчика/Динамическое создание диалогов из макроса средствами языка RSL"
*/
import Bankinter, rsexts, rslxml, txml, txmlelem, tdocxml, smev_send, smev_xsd_check;
import RsbCryptoInter;
import no_common;
import smev_gis_gmp_notice_cmn;
// далее идёт включение "пользовательского" макроса
import "..\\mac\\userb\\ldmklbr.mac";

const REG_PATH_SM_1        = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\ИДЕНТИФИКАТОР УЗЛА СМЭВ";
const REG_PATH_SM_2        = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\ИДЕНТИФИКАТОР ИНИЦИАТОРА В СМЭВ";
const REG_PATH_SM_3        = "BANK_INI\\ОБЩИЕ ПАРАМЕТРЫ\\ПЕРЕМЕННЫЕ\\TIMEZONE";
const REG_PATH_SM_5        = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\ИДЕНТИФИКАТОР ЕГПУ В СМЭВ";
const REG_PATH_SM_6        = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\РЕЖИМ ОН-ЛАЙН";
const REG_PATH_SM_7        = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\КОПИЯ ФАЙЛА";
const REG_PATH_SM_8        = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\АДРЕС СМЭВ";
const REG_PATH_SM_9        = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\ЭЦП";
const REG_PATH_SM_10       = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\ДИРЕКТОРИЯ ФАЙЛОВ ИЗ СМЭВ";
const REG_PATH_SM_12       = "ЭЛЕКТРОННЫЙ ОБМЕН\\ГИС ГМП\\ИДЕНТИФИКАТОР УЧАСТНИКА В ТОФК";

const КодУчастникаСМЭВ = "553001771";
const НаименованиеБанка= "Коммерческий банк РИАЛ-КРЕДИТ (ООО)";

private var crypto_api: CRslCryptoApi;
private var СНИЛС_Фамилия, СНИЛС_Имя, СНИЛС_Отчество, СНИЛС_Пол, СНИЛС_ДРожд, СНИЛС_СНИЛС;

//========================================================
// Процедура возвращает номер позиции последнего вхождения
//   строки string2 в строке string1 или 0, 
// если строка string2 не найдена в string1
//========================================================
macro LastIndex(string1, string2)

  var
    k  = 1,
    k1 = 0;

  while (k > 0)
    k = index(string1, string2);   
    string1 = substr(string1, k + 1);
    if (k > 0)
      k1 = k1 + k
    end;
  end;               
  return k1
end;

private macro DateToDDMMYYYY(d)

  var dd, mm, yyyy, dtstr = "";
  DateSplit(d, dd, mm, yyyy);
  if (dd < 10)
    dtstr = dtstr + "0" + string(dd);
  else
    dtstr = dtstr + string(dd);
  end;
  if (mm < 10)
    dtstr = dtstr + "-" + "0" + string(mm);
  else
    dtstr = dtstr + "-" + string(mm);
  end;
  return dtstr + "-" + string(yyyy);
end;

class TCreateMessage( _dir:string, _date_form:date, _time_form:time, _recipient:string, _recipient_name:string )

   private var m_objXML           = TXML(not IsStandAlone(), "UTF-8");
   private var m_objCon           = CWebInterface();
   private var m_root;
   private var m_sroot;
   private var m_proot;
   private var m_identifier:string = "";

   private const m_dir_out_setting = _dir;
   private var m_file_name_creator:SMEVFileName;
   private var m_notif:string  = "";
   private var m_uid:string = "";

   private var m_xsd = TSmevXsdCheck();
   var m_timestamp;
   var m_date_form = _date_form;
   var m_time_form = _time_form;
   var m_rec:string = _recipient;
   var m_rec_name:string = _recipient_name;

   macro GetMode():bool
      var mode = false,
          err;
      GetRegistryValue(REG_PATH_SM_6, V_BOOL, mode, err);
      return mode;
   end;

   macro GetDSMode():bool
      var mode = false,
          err;
      GetRegistryValue(REG_PATH_SM_9, V_BOOL, mode, err);
      return mode;
   end;

   macro GetFileCopy():bool
      var value = false,
          err;
      GetRegistryValue(REG_PATH_SM_7, V_BOOL, value, err);
      return value;
   end;

   macro GetAddressSMEV():string
      var value:string = "",
          err;
      //GetRegistryValue(REG_PATH_SM_8, V_STRING, value, err);
      //return value;
      return "http://oraas.rt.ru:7777/gateway/services/SID0003822";
   end;

   macro GetNMSenderIdentifier():String
      var value:string = "",
          err;
      GetRegistryValue(REG_PATH_SM_12, V_STRING, value, err);
      return value;
   end;

   private var OnlineMode:bool = GetMode();
   private var Address:string = GetAddressSMEV();

   macro CreateAttr( name:string, value )
      var node = m_objXML.m_doc.createAttribute(name);
      node.value = value;
      m_root.setAttributeNode(node);
   end;

   macro GetUID() : string
      var id, err;
      GetRegistryValue(REG_PATH_SM_1, V_STRING, id, err);

      if ( err )
         id = "";
      end;

      return id;
   end;

   macro GetInitiator() : string
      var id, err;
      GetRegistryValue(REG_PATH_SM_2, V_STRING, id, err);

      if ( err )
         id = "";
      end;

      return id;
   end;

   macro GetTimezone() : string
      var zone, err;
      GetRegistryValue(REG_PATH_SM_3, V_STRING, zone, err);

      if ( err )
         zone = "";
      end;

      return zone;
   end;

   macro CreateError(recv : string)
      m_notif = m_notif + GenXmlErrMsg(recv) + "\n";
   end;

   macro CreateErrorXSD( recv )
      m_notif = m_notif + "!Нарушение формата: " + recv + "\n";
   end;

   macro CreateBodyMessage():integer
   end;

   macro CreateSMEV():integer
      var err = 0, id;
      var StrOut:string = "";
      var m_header, m_mes, m_post;

      m_header = m_objXML.m_doc.appendChild(m_objXML.m_doc.createElement("soapenv:Envelope"));
      m_root = m_header;

      CreateAttr("xmlns:soapenv", "http://schemas.xmlsoap.org/soap/envelope/");

      m_sroot = m_root.appendChild(m_objXML.m_doc.createElement("soapenv:Header"));

      var _hour:integer = 0;
      var _min:integer = 0;
      var _sec:integer = 0;
      var _msec;

      TimeSplit( m_time_form, _hour, _min, _sec, _msec);
      _msec = LZ( _msec, 3 );
      m_timestamp = DtTm( m_date_form, Time(_hour, _min, _sec, _msec) );
      m_timestamp = valtoxml(m_timestamp);
      m_timestamp = m_timestamp + "." + _msec + GetTimezone();

      m_root = m_header.appendChild(m_objXML.m_doc.createElement("soapenv:Body"));
      CreateAttr("xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
      CreateAttr("wsu:Id"   , "body");

      m_mes = m_root.appendChild(m_objXML.m_doc.createElement("snil:SnilsValidationRequest"));
      m_root = m_mes;
      CreateAttr("xmlns:snil", "http://snils-validation.skmv.rstyle.com");
      CreateAttr("xmlns:pfr", "http://pfr.skmv.rstyle.com");
      CreateAttr("xmlns:rev", "http://smev.gosuslugi.ru/rev120315");

      m_proot = m_mes.appendChild(m_objXML.m_doc.createElement("rev:Message"));
      m_sroot = m_proot.appendChild(m_objXML.m_doc.createElement("rev:Sender"));
      m_root  = m_sroot.appendChild(m_objXML.m_doc.createElement("rev:Code"));
      m_root.text = КодУчастникаСМЭВ;
      m_root  = m_sroot.appendChild(m_objXML.m_doc.createElement("rev:Name"));
      ToUTF8(StrUpr(НаименованиеБанка), StrOut);
      m_root.text = StrOut;

      m_sroot = m_proot.appendChild(m_objXML.m_doc.createElement("rev:Recipient"));
      m_root  = m_sroot.appendChild(m_objXML.m_doc.createElement("rev:Code"));
      m_root.text = "PFRF01001";
      m_root  = m_sroot.appendChild(m_objXML.m_doc.createElement("rev:Name"));
      //ToUTF8("Пенсионный фонд РФ", StrOut); - почему-то перекодировка такой строки не отрабатывает, формируем по-другому, сами
      m_root.text = "" + StrFor(128+(15)) + StrFor(128+(37)) + StrFor(128+(45)) + StrFor(128+(97)) + StrFor(128+(40)) + StrFor(128+(46)) + StrFor(128+(45)) + StrFor(128+(45))
                       + StrFor(128+(107)) + StrFor(128+(41)) + " " + StrFor(128+(100)) + StrFor(128+(46)) + StrFor(128+(45)) + StrFor(128+(36)) + " " 
                       + StrFor(128+(16)) + StrFor(128+(20));

      m_sroot = m_proot.appendChild(m_objXML.m_doc.createElement("rev:Service"));
      m_root  = m_sroot.appendChild(m_objXML.m_doc.createElement("rev:Mnemonic"));
      m_root.text = "SNILS_VALIDATION";
      m_root  = m_sroot.appendChild(m_objXML.m_doc.createElement("rev:Version"));
      m_root.text = "1.00";

      m_root = m_proot.appendChild(m_objXML.m_doc.createElement("rev:TypeCode"));
      StrOut = ("GSRV");//GSRV - взаимодействие в рамках оказания госуслуг.
      m_root.text = StrOut;
      m_root = m_proot.appendChild(m_objXML.m_doc.createElement("rev:Status"));
      StrOut = ("REQUEST");
      m_root.text = StrOut;
      m_root = m_proot.appendChild(m_objXML.m_doc.createElement("rev:Date"));
      StrOut = (m_timestamp);
      m_root.text = StrOut;
      m_root = m_proot.appendChild(m_objXML.m_doc.createElement("rev:ExchangeType"));
      m_root.text = "2";
      m_root = m_proot.appendChild(m_objXML.m_doc.createElement("rev:TestMsg"));
      StrOut = ("");
      m_root.text = StrOut;

      /*<rev:MessageData>*/
      m_root  = m_mes.appendChild(m_objXML.m_doc.createElement("rev:MessageData"));
      m_root  = m_root.appendChild(m_objXML.m_doc.createElement("rev:AppData"));

      m_root  = m_root.appendChild(m_objXML.m_doc.createElement("rev:request"));
      m_proot = m_root.appendChild(m_objXML.m_doc.createElement("snil:fio"));
      m_post  = m_proot.appendChild(m_objXML.m_doc.createElement("pfr:FirstName"));
      ToUTF8(StrUpr(СНИЛС_Имя), StrOut);
      m_post.text = StrOut;
      m_post  = m_proot.appendChild(m_objXML.m_doc.createElement("pfr:LastName"));
      ToUTF8(StrUpr(СНИЛС_Фамилия), StrOut);
      m_post.text = StrOut;
      m_post  = m_proot.appendChild(m_objXML.m_doc.createElement("pfr:Patronymic"));
      ToUTF8(StrUpr(СНИЛС_Отчество), StrOut);
      m_post.text = StrOut;

      m_post = m_root.appendChild(m_objXML.m_doc.createElement("snil:snils"));
      StrOut = (СНИЛС_СНИЛС);
      m_post.text = StrOut;

      m_proot = m_root.appendChild(m_objXML.m_doc.createElement("snil:gender"));
      StrOut = (СНИЛС_Пол);
      m_proot.text = StrOut;

      m_proot = m_root.appendChild(m_objXML.m_doc.createElement("snil:pfr_date"));
      StrOut = DateToDDMMYYYY(СНИЛС_ДРожд);
      m_proot.text = StrOut;

      //DEBUG ONLY !!!
      //var fn ="..\\txtfile\\smev_fns\\test_snils_do_podpisi.xml";
      //m_objXML.m_doc.save(fn);
   end;

   macro CreateMessage():integer
   end;

   macro ConvertDir(dir:string)
     var j:integer = 1,
         ind:integer = 1;
     while ( (j < strlen(dir)) )
        if  ((substr( dir, j, 1) != ".") and (substr( dir, j, 1) != "\\") and (substr( dir, j, 1) != "$"))
            break;
        end;
            j = j + 1;
     end;
     dir = substr( dir, j );
     return dir;
   end;

   macro getFileNameCreator(type /* ==V_UNDEF*/):SMEVFileName
      if ( ValType( m_file_name_creator ) == V_UNDEF )
         m_file_name_creator = SMEVFileName(type, m_date_form, getServfilePath(m_dir_out_setting));
      end;
      return m_file_name_creator;
   end;

   macro GetFileName(type : string) : integer
      getFileNameCreator(type);
      return 0;
   OnError(er)
      return 1;
   end;

   macro CopyFileFromTempPath()

      macro copyFileExt(from, to)
         var ret:Bool = false;
         if(not isStandalone())
            to = "$" + to;
         end;
         ret = CopyFile(from, to);
         return ret;
      end;

      private var ret:Bool = copyFileExt(getFileNameCreator().getTempFilePath() , getFileNameCreator().getFullFilePath());
      return ret;
   end;

   macro CheckByXSD()
      var errstr:String;
      if( not m_xsd.validate(m_objXML.m_doc.xml, errstr))
         CreateErrorXSD(errstr);
         return false;
      end;
      return true;
   end;

   macro Send()
      m_objCon.Send( Trim(Address), m_objXML.m_doc.xml, getFileNameCreator());
   end;

   macro SaveXMLDoc():bool
      //Какие-то телодвижения по сохранению документа.
      var sreg   = p_REGVAL_2;
      p_REGVAL_2 = true;
      p_noSaveArh = true;

      m_objXML.save( getFileNameCreator().getTempFilePath(), "UTF-8");

      p_noSaveArh = false;
      p_REGVAL_2 = sreg;

      return true;
   OnError( er )
      m_notif = m_notif + er.Message + "\n";
      return false;
   end;


   macro SignIfNeedAndCheck()
      var ret = true;
      if(GetDSMode()) //Все нижеследующее имеет смысл лишь при включенной и настроенной криптографии

         if(ValType(crypto_api) == V_UNDEF)
            crypto_api = CRslCryptoApi(); //Инициализация cryptoApi
         end;

         if ( ExistFile(getFileNameCreator().getTempFilePath()) ) //Если есть что подписывать
            m_objXML = null; //Освобождаем объект.
            crypto_api.PutFileSign( CRYPD_SMEV_MESSAGES, getFileNameCreator().getTempFilePath(), getFileNameCreator().getTempSignedFilePath());
            CopyFile(getFileNameCreator().getTempSignedFilePath(), getFileNameCreator().getTempFilePath());
            RemoveFile(getFileNameCreator().getTempSignedFilePath());
            m_objXML = TXML(not IsStandAlone(), "UTF-8"); //загружаем подписанный файл
            m_objXML.load(getFileNameCreator().getTempFilePath());
         else
            RunError("ЭЦП:Нет файла для подписания:"+getFileNameCreator().getTempFilePath());
         end;

         ret = CheckByXSD(); //Проверим подписанный файлик.
      end;
      return ret;
   OnError( er )
      m_notif = m_notif + er.Message + "\n";
      return false;
   end;
end;

class (TCreateMessage) TCreateSmevMsg( smparm )


   macro CreateBodyMessage():integer
      var m_post;
      var StrOut:string = "";

      CreateSMEV();

      return 0;
   end;


   macro CreateMessage():integer
      var stat:integer = 0;

      if ( not CreateBodyMessage() )

         m_root = m_objXML.m_doc.documentElement;
         m_proot = m_root.getElementsByTagName("soapenv:Header").item(0);

         if ( GetFileName( "02") )
            return 1;
         end;

         //Сохраняем сформированный файл.
         if( not SaveXMLDoc())
            return 1; //Не получилось сохранить
         end;

         //Подписываем при необходимости.
         if(not SignIfNeedAndCheck())
            return 1; //Не получилось подписать
         end;

         if ( not stat )
            CopyFileFromTempPath(); //Копируем файл из временного каталога в каталог из насторойки, только если ранее не было ошибок (При подписании, проверке по xsd, итп)

            if ( OnlineMode )
               Send();
            end;
         end;
      else
         stat = 1;
      end;
      return stat;
   end;

   macro ReadSMEVResponse()

     var response_fn, request_fn = getFileNameCreator().getFullFilePath();
     var dom = activeX("MSXML2.DOMDocument");
     var root, node0, node1, node2, node3, blocks, i, tag, val;

     response_fn = "..\\workfile\\response" + substr(request_fn, LastIndex(request_fn, "\\") + 1);
     response_fn = strsubst(response_fn, ".xml", "." + UserNumber());

     while (not ExistFile(response_fn))
       message("Ждём файл ответа...");
     end;

     dom.Load(response_fn);

     blocks = dom.getElementsByTagName("Status");
     i = 0;
     while (i < blocks.length)
      tag = blocks.item(i);
      val = tag.childnodes(0).text;
      i = i + 1;
     end;

     if   (val == "INVALID")
       blocks = dom.getElementsByTagName("ns3:message");
       i = 0;
       while (i < blocks.length)
        tag = blocks.item(i);
        val = tag.childnodes(0).text;
        i = i + 1;
       end;
       msgbox("Ошибка при проверке СНИЛС:|" + val);
     elif (val == "RESULT")
       blocks = dom.getElementsByTagName("ns4:result");
       i = 0;
       while (i < blocks.length)
        tag = blocks.item(i);
        val = tag.childnodes(0).text;
        i = i + 1;
       end;
       if (val == "true")
         msgbox("Валидация успешна!|СНИЛС соответствует данной фамильно-именной группе");
       else
         msgbox("Валидация НЕ УСПЕШНА!|СНИЛС  НЕ  соответствует данной фамильно-именной группе");
       end;
     else
       msgbox("Неизвестный статус в ответе: " + val);
     end;

   end;

   initTCreateMessage(smparm.Dir, smparm.DateForm, smparm.TimeForm, smparm.Recipient, smparm.Recipient_name);
end;


macro CreateAndSendSMEVMessage() : bool
   var l_rec = TRecHandler("smevparm.tmp", "rs_temp.def");
   var res : bool = true;
   l_rec.rec.Dir         = "..\\txtfile\\smev_fns\\";
   l_rec.rec.DateForm       = date;
   l_rec.rec.TimeForm       = time;
   l_rec.rec.Recipient      = "SID0003822";
   l_rec.rec.Recipient_name = "snils-validation";
   var obj = TCreateSmevMsg(l_rec.rec);
   var stat = obj.CreateMessage();
   if(0 != stat)
      res = false;
   else
     obj.ReadSMEVResponse();
   end;
   return res;
end;



// ═════════════════════════════ Диалог ═════════════════════════════════════════════════════

Macro CheckFields(dlg)

  if (dlg.rec.Фамилия == "")
     msgbox("Задайте фамилию!");
     SetFocus(dlg, FldIndex(dlg, "Фамилия"));
     return false;
  end;
  if (dlg.rec.Имя == "")
     msgbox("Задайте имя!");
     SetFocus(dlg, FldIndex(dlg, "Имя"));
     return false;
  end;
  if (dlg.rec.Отчество == "")
     msgbox("Задайте отчество!");
     SetFocus(dlg, FldIndex(dlg, "Отчество"));
     return false;
  end;
  /*
  if ((dlg.rec.Пол != "M") and (dlg.rec.Пол != "F"))
     msgbox("Задайте пол!");
     SetFocus(dlg, FldIndex(dlg, "Пол"));
     return false;
  end;
  */
  if ((dlg.rec.СНИЛС == "") or (StrLen(dlg.rec.СНИЛС) != 14))
     msgbox("Задайте СНИЛС в правильном ФОРМАТЕ!");
     SetFocus(dlg, FldIndex(dlg, "СНИЛС"));
     return false;
  end;
  return true;
end;

Macro SaveFields(dlg)

  СНИЛС_Фамилия   = dlg.rec.Фамилия;
  СНИЛС_Имя       = dlg.rec.Имя;
  СНИЛС_Отчество  = dlg.rec.Отчество;
  СНИЛС_Пол       = dlg.rec.Пол;
  СНИЛС_ДРожд     = dlg.rec.ДРожд;
  СНИЛС_СНИЛС     = dlg.rec.СНИЛС;
End;

Macro DlgProc(dlg, cmd, id, key)

  array mn;
  var   stat = CM_DEFAULT;

  if   (cmd == DLG_INIT)
     //InitFields(dlg);
     UpdateFields(dlg);
     stat = CM_IGNORE;
  elif (cmd == DLG_REMFOCUS)
     if (fldname(dlg, id) == "СНИЛС")
        // dlg.rec. = ...;     ничего
        UpdateFields(dlg);
     end;
  elif (cmd == DLG_KEY)
     if (key == K_F2)
        if (CheckFields(dlg))
           SaveFields(dlg);
           if (CreateAndSendSMEVMessage())
             stat = CM_SAVE;
           else
             msgbox("Ошибка при формировании и отправке запроса в СМЭВ!|Обратитесь в ИТ отдел!");
           end;
        else
           stat = CM_IGNORE;
        end;
     elif (key == K_F3)
        if (fldname(dlg, id) == "Пол")
           mn(0) = "M";
           mn(1) = "F";
           stat = menu(mn, "Пол", "Пол", 30, 10);
           if (stat >= 0)
             dlg.rec.Пол = mn(stat);
           end;
           stat = CM_IGNORE;
        end;
     elif (key == K_ENTER)
        if (fldname(dlg, id) == "ДРожд")
           SetFocus(dlg, FldIndex(dlg, "Фамилия"));
           stat = CM_IGNORE;
        end;
     elif (key == K_ESC)
        stat = CM_CANCEL;
     end;
     UpdateFields(dlg);
  end;
  return stat;
End;

// ══════════════════════════════════════════════════════════════════════════════════════════
Macro mkSNILSlbr(lbr)
  Var
     rc = lbr.AddPanel( "SNILS", 2, 2, 70, 15, lbr.EColour.SHLP, lbr.EFRame.UNARY ),
     elem;

  rc.Title      = "Валидация СНИЛС через СМЭВ (сервис ПФР)";
  rc.StatusLine = " F3 - выбор, F2 - Проверка, Esc - выход ";


  elem = rc.AddLabel(  5,  2, "Фамилия:" );
  elem = rc.AddField( 28,  2, lbr.EFieldType.EDIT, lbr.EFocus.YES, lbr.EDataType.V_STRING,   "Фамилия", 30, 1 );

  elem = rc.AddLabel(  5,  4, "Имя:" );
  elem = rc.AddField( 28,  4, lbr.EFieldType.EDIT, lbr.EFocus.YES, lbr.EDataType.V_STRING,   "Имя", 30, 1 );

  elem = rc.AddLabel(  5,  6, "Отчество:" );
  elem = rc.AddField( 28,  6, lbr.EFieldType.EDIT, lbr.EFocus.YES, lbr.EDataType.V_STRING,   "Отчество", 30, 1 );

  elem = rc.AddLabel( 5,   8, "СНИЛС (123-456-789 12) :" );
  elem = rc.AddField( 28,  8, lbr.EFieldType.EDIT, lbr.EFocus.YES, lbr.EDataType.V_STRING, "СНИЛС", 14, 1);

  elem = rc.AddLabel( 5,  10, "Пол:" );
  elem = rc.AddField( 28, 10, lbr.EFieldType.NOEDIT, lbr.EFocus.YES, lbr.EDataType.V_STRING, "Пол", 1, 1);

  elem = rc.AddLabel( 5,  12, "Дата рождения:" );
  elem = rc.AddField( 28, 12, lbr.EFieldType.EDIT, lbr.EFocus.YES, lbr.EDataType.V_DATE, "ДРожд", 10);


  elem = rc.AddLabel( 16, 16, "F3 - выбор, F2 - Проверить, Esc - выход" );
End;

// ══════════════════════════════════════════════════════════════════════════════════════════
Macro MkLbrFile
  Var  LbrName = "..\\mac\\userb\\snils.lbr",
       lbr     = TLbrFile( LbrName, "C" );

  mkSNILSlbr( lbr );

  lbr.Save();	//сохраняем ресурсы в файле
  lbr = NULL;
  return LbrName;
End;

// ══════════════════════════════════════════════════════════════════════════════════════════
//                                ВХОД В ПРОГРАММУ
// ══════════════════════════════════════════════════════════════════════════════════════════

Var LbrName = MkLbrFile();
Var test    = TRecHandler( "snils", LbrName, TRUE );

// ═════════════════════════════ Диалог ═════════════════════════════════════════════════════
if (not RunDialog(test, "DlgProc"))
   exit(1);
end;
exit(1);
// ═════════════════════════════ Диалог ═════════════════════════════════════════════════════