ЦИК-ЦБ-КО 4012-У
Скачать (zip-файл; Размер - 392315)Обсудить в форуме
Описание
Разбор запроса и формирование ответа для взаимодействия кредитной организации и центральной избирательной комиссии через центральный банк.
Только счета (MVODB+Retail), без ценных бумаг.
Без работы с криптографией.
Есть заимствования из раздела Библиотека разработчика.
Только счета (MVODB+Retail), без ценных бумаг.
Без работы с криптографией.
Есть заимствования из раздела Библиотека разработчика.
Текст примера
/* Формирование ответа на запрос ЦИК о счетах кандидатов */ /* Версия 0.6c 20160823 */ /* см Требования к составу, названиям и структуре файлов обмена, используемых при взаимодействии между ФЦИ при ЦИК России, Банком России и участниками финансового рынка */ import rsexts; import boostre; //import "nss_by_nightmare2000.mac"; //https://isupport.softlab.ru/portal/Samples/sample.asp?Typ=7&Id=250 import BankInter, ClnInter, CurrInter, CtgInter; //import formdate; import globals; import "regcls.mac"; import assarray; //для кодов квитанции import feldsher; const ВерсПрог="КБ392 ЦИК-ЦБР 0.6c 20160823"; const КАТЕГОРИЯ_EMAIL_ПОЛЬЗОВАТЕЛЯ=...; //Сделать категорию e-mail по образцу 900 const mybank_ini="tandem.ini"; var folderIN = GetIniString ("CIKCBR_ImportFolder", mybank_ini); //в OBJ должен лежать .ini файл и там строка CIKCBR_ImportFolder=..\Import\CIK_CBR var folderOUT= GetIniString ("CIKCBR_ExportFolder", mybank_ini); //в OBJ должен лежать .ini файл и там строка CIKCBR_ExportFolder=..\Export\CIK_CBR var folderXSD= GetIniString ("CIKCBR_XsdFolder", mybank_ini); //в OBJ должен лежать .ini файл и там строка CIKCBR_XsdFolder=..\Import\CIK_CBR var sOGRN_CIK="1027700466640"; //ОГРН ЦЕНТРАЛЬНАЯ ИЗБИРАТЕЛЬНАЯ КОМИССИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ //var Порог =0.8; //%% совпадения ФИО var reg=TReg("USER_MAC\\CIK_CBR\\"); var flagValidateQuery:Bool =reg.Get("VALIDATE QUERY", true); //проверять запрос по схеме var flagValidateAnswer:Bool=reg.Get("VALIDATE ANSWER",true); //проверять ответ по схеме var flagValidateKvt:Bool=reg.Get("VALIDATE KVT",true); //проверять ответ-квитанцию по схеме var flagKvtNotFound:Bool=reg.Get("KVT 1000",true); //формировать квитанцию если совпадений не найдено var flagKvtXsdError:Bool=reg.Get("KVT 1003",true); //формировать квитанцию если ошибка в XSD схеме var flagUseXsdPathHack:Bool=reg.Get("USE XSD PATH HACK",true); // var flagIgnoreQueryValidateError:Bool =reg.Get("IGNORE QUERY VALIDATE ERROR", true); //прогонять запрос даже если есть ошибки по схеме валидации var modeRetailRestDef=1; if ("3202"=={Reg_Num}) modeRetailRestDef=2; end; var modeRetailRest:Integer=reg.Get("MODE RETAIL REST", modeRetailRestDef); //способ получения остатка по счёту RETAIL 1-pc_drest, 2-sbdepdoc; var ДистанцияФИО:Integer=reg.Get("ДИСТАНЦИЯ СТРОК ФИО", 5); //вместо порога var reportClassName:String=reg.Get("REPORT CLASS",""); //Условное имя класса отчёта для списка на повторную идентификацию (XCR, ODT) var rep; //Отчёт var sOutFileName; var DOMDoc; //запрос, он же ответ var fPaperKind=TBFile("paprkind.dbt","R",1,null,"bank.def"); var okPaperKind:Bool; var fRegDoc=TBFile("regdoc.dbt","R",4,null,"bank.def"); var flagFind:Bool; //flagFindAcc:Bool; var fAccountMvodb =TBFile("account.dbt", "R",4,null, "bank.def"); var fAccountRetail=TBFile("depositr.dbt","R",4,null,"sbbank.def"); var fRestRetail =TBFile("pc_drest.dbt","R",0,null,"sbbank.def"); var fPersn =TBFile("persn.dbt", "R",1,null, "bank.def"); var fClient =TBFile("client.dbt", "R",0,null, "bank.def"); var fSbdepdoc =tbfile("sbdepdoc", "R", 6, "sbdepdoc.dbt", "sbbank.def"); var aAccMask=TArray(); var aAccType=TArray(); var cntPerson=TArray(); //со счетами var cntPersonTotal=TArray(); //всего кандидатов в запросе var cntBadDoc=TArray(); //не найден типдокумента var cntFoundDoc=TArray(); //найден документ var cntFoundFIODR=TArray(); //найден var queryName=TArray(); var cntPersonDoc=TArray(); // найден документ и совпали ФИО var queryXsdResult=TArray(); var answerXsdResult=TArray(); var answerName=TArray(); var iQueryNumber:Integer; //порядковый номер запроса в пределах календарного года (0001, 0002 : 9999) в рамках обмена информацией по которому совершено действие, повлекшее формирование квитанции. var sMessageId:String; var sQueryType:String; // T - тип запроса. Имеет значение Z - для пакетного запроса и P - для персонального запроса; var cntKvt=0; var t_start=Time(); var domXsdQuery, domXsdAnswer; var objQuerySchemaCache; var objXsdErr; aAccMask[0]="40817*, 40820*"; aAccType[0]="Текущий счет"; aAccMask[1]="40802*"; aAccType[1]="Расчетный счет"; aAccMask[2]="40803*, 40804*, 40805*, 40806*, 40809*, 40813*"; aAccType[2]="Специальный банковский счет"; aAccMask[3]="423*,426*,42108-42114"; aAccType[3]="Счет по вкладу (депозиту)"; aAccMask[4]="хз"; aAccType[4]="Обезличенный металлический счет"; //текстовое описание кода квитанции по-умолчанию var aKvtCode=TAssArrayIS( 1001, "некорректная подпись", 1002, "невозможно расшифровать файл обмена", 1003, "формат файла обмена не соответствует схеме", 1004, "ошибка логической обработки файла обмена", 2001, "некорректная подпись", 2002, "невозможно расшифровать файл обмена", 2003, "формат файла обмена не соответствует схеме", 2004, "ошибка логической обработки файла обмена", 1010, "сообщение об успешной отправке запроса", 2010, "сообщение об успешной доставке ответа", 1000, "сообщение об отсутствии информации по проверяемым лицам", 2000, "сообщение об успешной обработке ответа", 2005, "сообщение об успешной обработке ответа, и наличии в ответе проверяемых лиц с изменившимися идентификационными данными", 2006, "несвоевременное представление сведений" ); if (reportClassName=="XCR") if (InstLoadModule("xcr.mac")) //rep=XCReport(); rep=GenObject("XCReport"); rep.SetArrayHead("Код в АБС", "ФИО в АБС", "ФИО в запросе", "Дистанция ФИО", "Тип док. в АБС","Номер док. в АБС", "Тип док. в запросе","Номер док. в запросе","Дата рождения в АБС","Дата рождения в запросе","Адрес в АБС","Адрес в запросе"); end; elif (reportClassName=="ODT") if (InstLoadModule("toffdoc.mac")) //rep=XCReport(); rep=GenObject("TOpenDocForm","На повторную идентификацию.odt"); rep.Table("Повторная_идетификация"); end; end; // структура списка для повторной идентификации var aReIdentReport=TArray(); //список клинтов для повторной идентификации class TReIdentReport(client_) var ClientID=client_; var ClientCode; //код клиента в АБС var fioRS; var fioCIK; var fioDistance; var docTypeRS; var docNumRS; var docTypeCIK; var docNumCIK; var adrRS; var adrCIK; var bdRS; var bdCIK; macro GetRsDoc(iKind) var aRegDoc=TArray(); // если в АБС существует такой тип документа как в запросе ЦИК if (okPaperKind) GetClientDocuments(ClientCode, aRegDoc, fPaperKind.rec.PaperKind, 1); if (aRegDoc.size>0) // и он есть уклиента, то выводим этот документ aReIdentReport[aReIdentReport.Size-1].docTypeRS=fPaperKind.rec.CodeDocum; aReIdentReport[aReIdentReport.Size-1].docNumRS =Trim(aRegDoc[0].rec.Series+" "+aRegDoc[0].rec.DocNum); return; end; end; // иначе выводим паспорт, если есть. глубже не копаем GetClientDocuments(ClientCode, aRegDoc, 0, 1); if (aRegDoc.size>0) aReIdentReport[aReIdentReport.Size-1].docTypeRS ="21"; aReIdentReport[aReIdentReport.Size-1].docNumRS =Trim(aRegDoc[0].rec.Series+" "+aRegDoc[0].rec.DocNum); end; end; //macro ClientCode=GetClientCodeByID(ClientID); adrRS=GetClientAddress (ClientID, ADRTYPE_JUR); bdRS=GetClientBirthday (ClientID); end; macro MakeReportReIdent if (aReIdentReport.size>0) var e; for(e,aReIdentReport) if(ValType(rep)==V_GENOBJ) rep.WriteRow( e.ClientCode, e.fioRS, e.fioCIK, e.fioDistance, e.docTypeRS, e.docNumRS, e.docTypeCIK, e.docNumCIK, e.bdRS, e.bdCIK, e.adrRS, e.adrCIK ); end; end; end; end; macro MakeReport var iQuery; [------------------------------------------------------------------------------------------------------------------------------------]; [################################ ### ##### ##### ##### ##### ##### ##### #### ######################################################] ("Файл","XSD","Всего","Отв.","Док","Д+ФИО","ПлохД","ФИОДР","aXSD","Файл ответа"); For (iQuery, 0, queryName.Size-1,1) if ((queryXsdResult[iQuery]=="OK") or (ValType(queryXsdResult[iQuery])==V_UNDEF) or flagIgnoreQueryValidateError) [################################ ### ##### ##### ##### ##### ##### ##### #### ######################################################] (queryName[iQuery],queryXsdResult[iQuery],cntPersonTotal[iQuery],cntPerson[iQuery],cntFoundDoc[iQuery],cntPersonDoc[iQuery],cntBadDoc[iQuery],cntFoundFIODR[iQuery],answerXsdResult[iQuery],answerName[iQuery]); else [################################ ### ](queryName[iQuery],queryXsdResult[iQuery]); end; end; [------------------------------------------------------------------------------------------------------------------------------------]; [Сформированно квитанций: ###](cntKvt); end; macro GetXPath(strXPath, elem) if (DOMDoc.documentElement==NullVal) return false; end; if (ValType(elem)==V_UNDEF) elem=DOMDoc.documentElement; end; var domNodes=elem.selectNodes(strXPath); if (domNodes.Length>0) return Trim(domNodes.item(0).text); end; return ""; end; //macro GetXPath macro GetXPathItems(strXPath, elem) if (DOMDoc.documentElement==NullVal) return false; end; if (ValType(elem)==V_UNDEF) elem=DOMDoc.documentElement; end; var domNodes=elem.selectNodes(strXPath); return domNodes; end; //macro GetXPath macro CreateXMLObject(strXMLFilePath) var obj:object = NULL; private macro CreateXMLObject_Ver(strVer) obj=ActiveX ("Msxml"+strVer+".DOMDocument.6.0", null, true); obj.async = False; return true; OnError( er ) return false; end; if(not CreateXMLObject_Ver("2")) if(not CreateXMLObject_Ver("")) return null; end; end; if ((V_UNDEF!=ValType(strXMLFilePath)) and (""!=strXMLFilePath)) obj.Load(strXMLFilePath); if ((obj.documentElement==NullVal) or not obj.documentElement) PrintLn("Дом не построен после загрузки "+strXMLFilePath); return null; end; end; obj.setProperty("SelectionLanguage", "XPath"); return obj; end; var aMatch=TArray(); var strErr=""; var iMatch; var dirIN: TDirList = TDirList(); var domPersons; var iAccType; dirIN.List (folderIN+"\\"+"F"+sOGRN_CIK+"*.xml","F"); var iQuery, iPerson; var Фамилия, Имя, Отчество, ДатаРожд; var ДокВид, ДокСер, ДокНом; var ДатаСвед:Date; var Адрес; //для списка на проверку сведений var fioRS, fioCIK; // macro GetRegionName(iRegion) var fRegion=TBFile("ptregion.dbt","R",0,null,"bank.def"); fRegion.rec.CodeRegion=iRegion; if (fRegion.GetEQ) return fRegion.rec.NameRegion; end; return ""; end; //macro GetRegionName() //добавляет к строке адресу элемент из структурированного адреса macro AddAdrPart(sResult:@string, sName, sKind) if (ValType(sResult)==V_UNDEF) sResult=""; end; sName=Trim(sName); if (sName!="") if ((ValType(sKind)!=V_UNDEF) and (Trim(sKind)!="")) sName=sKind+" "+sName; end; if (sResult=="") sResult=sName; else sResult=sResult+", "+sName; end; end; end; macro GetCtg(iObjectID, iCtgId:Integer, ObjType, defValue) var aVal=TArray(); var iType; var sObjId; if (ValType(ObjType)==V_UNDEF) ObjType=OBJTYPE_CLIENT; end; if (OBJTYPE_CLIENT==ObjType) sObjId=GetClientId(iObjectID); elif(14 ==ObjType) if ((Valtype(iObjectID)==V_UNDEF) or (0==iObjectID)) iObjectID={oper}; end; sObjId=String(iObjectID); end; if (GetCtgVal(ObjType, iCtgId, sObjId, aVal)) if (aVal.Size==1) return aVal[0]; elif (aVal.Size==0) //return ZeroValue(iType); //return null; else //return aVal; return aVal[0]; end; end; //return null; return defValue; end; //macro GetCtg //true если клиент открыт на текущую дату macro ClientIsOpen(ClientID) fClient.rec.Client=ClientID; if (fClient.GetEQ) return (fClient.rec.bdFinishDate==Date(0,0,0)) end; exit(0,"Нарушение БД. Клиент "+ClientID); end; // остаток по счёту retail за дату macro RetailRestV1(d) DebugBreak(); fRestRetail.rec.Referenc=fAccountRetail.rec.Referenc; fRestRetail.rec.Type_Object=2001; fRestRetail.rec.Date_Rest=d; if (fRestRetail.GetLE and (fRestRetail.rec.Referenc==fAccountRetail.rec.Referenc) and (fRestRetail.rec.Type_Object==2001) ) return fRestRetail.rec.Rest; end; return 0; end; /* НОКССБАНК Свернуть еще моментик. Таскать остатки из pc_drest.dbt нежелательно. Нужно использовать базу sbdepdoc.dbt ( Eugene Korolev 22.08.2016 13:55:00 ) На вопрос почему - ответ: Потому что :). Ретейл штука такая, с ней бывают (и не раз были уже) при выходе новых сборок разные интересные проблемы. */ const /* Виды документов: */ DD_AR = 8, /* Проводка в архиве */ DD_ARC = 9, /* Корректировка в архиве */ DD_AUDIT_STORN = 14, /* Сторнирование операции */ DD_AUDIT_DELETE = 15, /* Удаление операции */ DD_AUDIT_CORRECT = 16, /* Корректировка операции */ DD_DELETE = 2; macro IsServDocWithEst(doc_rec); var isDoc =( ( doc_rec.rec.KindOp != DD_AR ) AND /* проводка в архиве */ ( doc_rec.rec.KindOp != DD_ARC ) AND /* корректировка в архиве */ ( doc_rec.rec.KindOp != DD_AUDIT_STORN ) AND /* Сторнирование операции */ ( doc_rec.rec.KindOp != DD_AUDIT_DELETE ) AND /* Удаление операции */ ( doc_rec.rec.KindOp != DD_AUDIT_CORRECT ) AND /* Корректировка операции */ ( doc_rec.rec.Action != DD_DELETE ) ); if (isDoc) // isDoc = ( GetBitFlag( doc_rec.Flags, 17 ) == 0 ); /* BIT_FLAG_HIDDEN */ end; return IsDoc; end; //получение остатка по счёту Retail macro RetailRestV2(Date_Document); fSbdepdoc.rec.Referenc = fAccountRetail.rec.Referenc; fSbdepdoc.rec.Date_Document = Date_Document; fSbdepdoc.rec.NumDayDoc = 32000; var RecFound = GetLE( fSbdepdoc ); while ((RecFound) and (fSbdepdoc.rec.Referenc==fAccountRetail.rec.Referenc)and (fSbdepdoc.rec.Date_Document<=Date_Document)) if (not IsServDocWithEst(fSbdepdoc)) RecFound=Prev(fSbdepdoc); else return fSbdepdoc.rec.Rest; end; end; return $0.0; end; //получение остатка по счёту Retail с учётом настройки macro RetailRest(d) if (1==modeRetailRest) return RetailRestV2(d); elif (1==modeRetailRest) return RetailRestV1(d); end; end; // преобразует путь для вставки в атрибут xml macro CnvPath(s) return flUrlCreateFromPath(s); end; //macro CnvPath macro Kvt(Type, ResultCode, ResultText) var domKvt=CreateXMLObject(); domKvt.loadXml("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<File xsi:noNamespaceSchemaLocation='VO_CIK_CB_K_6.xsd' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'></File>"); //var node = domKvt.createElement("File"); var node = domKvt.documentElement; var sKvtFName:String; var sFrom="K"+GetClientRegNumber({OurBankId}); macro AddElement(sName,sValue) //node.SetAttribute(sName,sValue); var node = domKvt.documentElement.appendChild(domKvt.createElement(sName)); node.Text=sValue; end; //macro AddElement if (ValType(ResultCode)==V_INTEGER) ResultCode=String(ResultCode:o:4); end; if (ValType(Type)==V_UNDEF) Type="8"; end; if (ValType(ResultText)==V_UNDEF) ResultText=aKvtCode.Get(Int(ResultCode)); end; cntKvt=cntKvt+1; //YZZZZZZZZZZZZZ_DDMMGG_hhmmss_Т_NNNN_XXXX_YZZZZZZZZZZZZZ.xml sKvtFName=sFrom+"_"+flFormDate("%d%m%y_%H%M%S")+"_K_"+ String(cntKvt:o:4)+"_"+ResultCode+"_"+"F"+sOGRN_CIK; AddElement("AcknowledgementType",Type); AddElement("ResultCode",ResultCode); AddElement("ResultText",ResultText); AddElement("To","F"+sOGRN_CIK); AddElement("From",sFrom); AddElement("MessageID",sKvtFName); AddElement("CorrelationMessageID", sMessageId); AddElement("MessageType","2"); AddElement("Priority","5"); //AddElement("CreateTime",formnowdate("%Y-%m-%d")); AddElement("CreateTime",flFormDate("%d.%m.%Y")); var validateOk=true; if (flagValidateKvt) var domXsdKvt=CreateXMLObject(folderXSD+"\\"+"VO_CIK_CB_K_6.xsd"); var objKvtSchemaCache=ActiveX ("MSXML2.XMLSchemaCache.6.0", null, true); objKvtSchemaCache.Add("", domXsdKvt); if (flagUseXsdPathHack) domKvt.documentElement.SetAttribute("xsi:noNamespaceSchemaLocation",CnvPath(folderXSD+"\\"+"VO_CIK_CB_K_6.xsd")); end; domKvt.Schemas=objKvtSchemaCache; var objXsdErr=domKvt.Validate(); if (objXsdErr.errorCode==0) PrintLn("Проверка квитанции "+sKvtFName+" на соответствие XSD схеме прошла успешно"); answerXsdResult[iQuery]="OK"; else PrintLn("ERROR: Ошибка при проверке квитанции "+sKvtFName+" на соответствие XSD схеме. \n Код: "+" "+String(objXsdErr.errorCode)+". ("+objXsdErr.reason+") "); answerXsdResult[iQuery]="ERR"; validateOk=false; end; if (flagUseXsdPathHack) domKvt.documentElement.SetAttribute("xsi:noNamespaceSchemaLocation","VO_CIK_CB_K_6.xsd"); end; end; domKvt.Save(folderOUT+"\\"+sKvtFName+".xml"); if ((ValType(answerName[iQuery])==V_UNDEF) or (answerName[iQuery]=="")) answerName[iQuery]=sKvtFName+".xml"; else answerName[iQuery]=answerName[iQuery]+","+sKvtFName+".xml"; end; end; //--- if (flagValidateKvt) var domXsdKvt=CreateXMLObject(folderXSD+"\\"+"VO_CIK_CB_K_6.xsd"); var objKvtSchemaCache=ActiveX ("MSXML2.XMLSchemaCache.6.0", null, true); objKvtSchemaCache.Add("", domXsdKvt); end; if (flagValidateQuery or flagValidateAnswer) domXsdQuery=CreateXMLObject(folderXSD+"\\"+"VO_CIK_CB_7.xsd"); objQuerySchemaCache=ActiveX ("MSXML2.XMLSchemaCache.6.0", null, true); objQuerySchemaCache.Add("", domXsdQuery); end; //---- определение параметров КО var aHouseKind=TArray(2); aHouseKind[0]="дом"; aHouseKind[1]="строение"; var НаимКредит, КодСубКред, НеконфАдрКред, КонфАдрКред; GetClientFullName({OurBankID},НаимКредит); var aBankAddr=TArray(); GetClientAddresses ({OurBankID}, aBankAddr, ADRTYPE_JUR, 1); if (aBankAddr.Size>0) КодСубКред=aBankAddr[0].rec.Region; AddAdrPart(@НеконфАдрКред,GetRegionName(aBankAddr[0].rec.Region)); AddAdrPart(@НеконфАдрКред,aBankAddr[0].rec.Area, aBankAddr[0].rec.AreaKind); AddAdrPart(@НеконфАдрКред,aBankAddr[0].rec.City, aBankAddr[0].rec.CityKind); AddAdrPart(@НеконфАдрКред,aBankAddr[0].rec.Settlement, aBankAddr[0].rec.Place ); AddAdrPart(@КонфАдрКред, aBankAddr[0].rec.Street, aBankAddr[0].rec.StreetKind); AddAdrPart(@КонфАдрКред, aBankAddr[0].rec.House, aHouseKind[aBankAddr[0].rec.HouseKind]); AddAdrPart(@КонфАдрКред, aBankAddr[0].rec.Building, "корпус"); AddAdrPart(@КонфАдрКред, aBankAddr[0].rec.Building2, "строение"); AddAdrPart(@КонфАдрКред, aBankAddr[0].rec.Apartment, "офис"); else //Tinkoff? end; var Телефон=GetCtg(null, 900, 14,{Phone_Numb}); var EMail=GetCtg(null, КАТЕГОРИЯ_EMAIL_ПОЛЬЗОВАТЕЛЯ, 14, GetClientEMail({OurBankId},ADRTYPE_JUR)); For (iQuery, 0, dirIN.Count-1,1) PrintLn(dirIN.Name(iQuery)); queryName[iQuery]=dirIN.Name(iQuery); answerXsdResult[iQuery]=""; answerName[iQuery]=""; iMatch=boostre_match("^([A-Z])(\\d{13})_(\\d{6})_([ZP])_(\\d{4})\.xml$", dirIN.Name(iQuery), strErr, aMatch); if (iMatch>0) //1-тип, 2 - id, 3 - дата, 4 - тип запроса, 5 - номер iQueryNumber=Int(aMatch[5]); //для квинанции sMessageId=SubStr(aMatch[0],1,StrLen(aMatch[0])-4); //для квинанции sQueryType=aMatch[4]; DOMDoc=CreateXMLObject(folderIN+"\\"+dirIN.Name(iQuery)); if (not DOMDoc) PrintLn("Ошибка загрузки "+folderIN+"\\"+dirIN.Name(iQuery)); queryXsdResult[iQuery]="ELD"; continue; end; Log_WriteCheckpoint (1002,"Обработка запроса ЦИК ЦБР "+queryName[iQuery]); if (flagValidateQuery) //подменяем путь к XSD if (flagUseXsdPathHack) domDoc.documentElement.SetAttribute("xsi:noNamespaceSchemaLocation",CnvPath(folderXSD+"\\"+"VO_CIK_CB_7.xsd")); end; domDoc.Schemas=objQuerySchemaCache; objXsdErr=domDoc.Validate(); if (objXsdErr.errorCode==0) PrintLn("Проверка запроса на соответствие XSD схеме прошла успешно"); queryXsdResult[iQuery]="OK"; else PrintLn("ERROR: Ошибка при проверке запроса на соответствие XSD схеме. \n Код: "+" "+String(objXsdErr.errorCode)+". ("+objXsdErr.reason+") "+ "\n Строка: "+objXsdErr.Line+", "+objXsdErr.linepos + " в файле: "+objXsdErr.filepos+ "\n Исходный текст: "+objXsdErr.srcText); queryXsdResult[iQuery]="ERR"; if (flagKvtXsdError) Kvt(null, 1003, objXsdErr.reason); end; end; //восстанавливаем путь к XSD if (flagUseXsdPathHack) domDoc.documentElement.SetAttribute("xsi:noNamespaceSchemaLocation","VO_CIK_CB_7.xsd"); end; //если была ошибка в схеме, то дальнейшую обработку не производим if ((objXsdErr.errorCode!=0) and (not flagIgnoreQueryValidateError)) continue; end; end; domPersons=GetXPathItems("/Файл/Персона"); if (ValType(domPersons)==V_GENOBJ) cntPerson[iQuery]=0; cntBadDoc[iQuery]=0; cntPersonTotal[iQuery]=domPersons.length; cntFoundDoc[iQuery]=0; cntPersonDoc[iQuery]=0; cntFoundFIODR[iQuery]=0; for(iPerson, 0, domPersons.length-1, 1) if (0==iPerson) var nodeInfOrg=DOMDoc.documentElement.insertBefore(DOMDoc.CreateElement("ИнфОрг"),domPersons.item(iPerson)); nodeInfOrg.setAttribute("Название", НаимКредит); nodeInfOrg.setAttribute("Адрес", GetClientAddress({OurBankID}, ADRTYPE_JUR)); nodeInfOrg.setAttribute("ИНН", GetClientINN({OurBankID})); nodeInfOrg.setAttribute("ОГРН", GetClientRegNumber({OurBankID})); nodeInfOrg.setAttribute("ФИО", GetFioOper({oper})); nodeInfOrg.setAttribute("Телефон", Телефон ); nodeInfOrg.setAttribute("ЭлПочта", EMail); end; flagFind=false; //flagFindAcc=false; var aNodeAccount=TArray; Фамилия =GetXPath("ПерсИнфо/ФИОД/@Фамилия", domPersons.item(iPerson)); Имя =GetXPath("ПерсИнфо/ФИОД/@Имя", domPersons.item(iPerson)); Отчество =GetXPath("ПерсИнфо/ФИОД/@Отчество", domPersons.item(iPerson)); ДатаРожд =GetXPath("ПерсИнфо/ФИОД/@ДатаРожд", domPersons.item(iPerson)); ДокВид =GetXPath("ПерсИнфо/Документ/@КодВидДок", domPersons.item(iPerson)); ДокСер =GetXPath("ПерсИнфо/Документ/@Серия", domPersons.item(iPerson)); ДокНом =GetXPath("ПерсИнфо/Документ/@Номер", domPersons.item(iPerson)); Адрес =GetXPath("ПерсИнфо/Адрес/@НеконфАдрес", domPersons.item(iPerson))+", " +GetXPath("ПерсИнфо/Адрес/@КонфАдрес", domPersons.item(iPerson)); if ((ДокВид=="21") and (StrLen(ДокСер)==5) and (SubStr(ДокСер,3,1)==" ")) ДокСер=SubStr(ДокСер,1,2)+SubStr(ДокСер,4,2); end; ДатаСвед =Date(GetXPath("СлужИнфо/Наименование/@ДатаСвед", domPersons.item(iPerson))); PrintLn(Фамилия,"\t",Имя,"\t",Отчество,"\t",ДатаРожд); //ищем в таблицах RS чо за документ такой, наверняка же паспорт fPaperKind.rec.CodeDocum=string(int(ДокВид):o:2); okPaperKind=fPaperKind.GetEQ; if (okPaperKind) //а теперь ищем всех клиентов, у которых такой паспорт :) fRegDoc.rec.RDKind=fPaperKind.rec.PaperKind; fRegDoc.rec.Series=ДокСер; fRegDoc.rec.DocNum=ДокНом; fRegDoc.rec.Client=0; var getOk=fRegDoc.GetGE; while (getOk and (fRegDoc.rec.RDKind==fPaperKind.rec.PaperKind) and (fRegDoc.rec.Series==ДокСер) and (fRegDoc.rec.DocNum==ДокНом)) cntFoundDoc[iQuery]=cntFoundDoc[iQuery]+1; GetClientFullName(fRegDoc.rec.Client,fioRS); fioCIK=Trim(Фамилия+" "+Имя+" "+Отчество); //не паримся с алгоритмом её, парных букв, вариантами имён. считаем, что депутаут как террорист //var l=LevensteinDistance(fioRS,fioCIK); //var l=НечеткоеСравнениеСтрок(4,StrUpr(fioRS),StrUpr(fioCIK)); //PrintLn(fioRS + " совпадает с "+ fioCIK+" на "+l); var l=flLevenshteinDistance(StrUpr(fioRS),StrUpr(fioCIK)); PrintLn(fioRS + " отличается от "+ fioCIK+" на "+l); //if (l>=Порог) if (l<=ДистанцияФИО) flagFind=true; cntPersonDoc[iQuery]=cntPersonDoc[iQuery]+1; //поиск по счетам МВОДБ fAccountMvodb.rec.Open_Close=""; fAccountMvodb.rec.Client = fRegDoc.rec.Client; fAccountMvodb.rec.Sort = ""; var getOkAcc=fAccountMvodb.GetGE(); while (getOkAcc and (fAccountMvodb.rec.Open_Close!="X") and (fAccountMvodb.rec.Client==fRegDoc.rec.Client)) for(iAccType,0,aAccMask.Size-1) if (0==CompareStrWithMasks (aAccMask[iAccType], fAccountMvodb.rec.Account)) PrintLn(fAccountMvodb.rec.Account," ",aAccType[iAccType]); //if (fAccountMvodb.rec.R0!=$0) //08.07.2016 и нулевые тоже aNodeAccount[aNodeAccount.Size]=DOMDoc.CreateElement("Счет"); aNodeAccount[aNodeAccount.Size-1].setAttribute("ВидСчета", aAccType[iAccType]); aNodeAccount[aNodeAccount.Size-1].setAttribute("НомерСчета", fAccountMvodb.rec.Account); aNodeAccount[aNodeAccount.Size-1].setAttribute("Остаток", Abs(RestA(fAccountMvodb.rec.Account,0,ДатаСвед-1))); //ДатаСвед-на, (ДатаСвед-1)-за //end; //flagFindAcc=true; break; end; end; getOkAcc=fAccountMvodb.next; end; //поиск по счетам Retail fAccountRetail.rec.CodClient=fRegDoc.rec.Client; fAccountRetail.rec.IsCur =0; fAccountRetail.rec.Number =0; getOkAcc=fAccountRetail.GetGE(); while (getOkAcc and (fAccountRetail.rec.CodClient==fRegDoc.rec.Client)) for(iAccType,0,aAccMask.Size-1) if (0==CompareStrWithMasks (aAccMask[iAccType], fAccountRetail.rec.Account)) PrintLn(fAccountRetail.rec.Account," ",aAccType[iAccType]); //if (fAccountRetail.rec.Sum_Rest!=$0) //08.07.2016 и нулевые тоже if (((fAccountRetail.rec.Close_Date==Date(0,0,0)) or (fAccountRetail.rec.Close_Date>=ДатаСвед)) and (fAccountRetail.rec.Open_Date<ДатаСвед)) aNodeAccount[aNodeAccount.Size]=DOMDoc.CreateElement("Счет"); aNodeAccount[aNodeAccount.Size-1].setAttribute("ВидСчета", aAccType[iAccType]); aNodeAccount[aNodeAccount.Size-1].setAttribute("НомерСчета", fAccountRetail.rec.Account); if (0==fAccountRetail.rec.IsCur) aNodeAccount[aNodeAccount.Size-1].setAttribute("Остаток", RetailRest(ДатаСвед-1)); else aNodeAccount[aNodeAccount.Size-1].setAttribute("Остаток", ConvSum (RetailRest(ДатаСвед-1), Int(SubStr(fAccountRetail.rec.Account,6,3)))); //не паримся с таблицей валют из Retail. дёргаем валюту из счёта end; end; //flagFindAcc=true; break; end; end; //for acc getOkAcc=fAccountRetail.next; end; //while client end; //v0.6список на повторную идентификацию if (l>0) //только тех, у кого стоит признак "Клиент" и он не закрыт if (IsClientOwnerKind(fRegDoc.rec.Client,PTK_CLIENT) and ClientIsOpen(fRegDoc.rec.Client)) aReIdentReport[aReIdentReport.Size]=GenObject("TReIdentReport",fRegDoc.rec.Client); aReIdentReport[aReIdentReport.Size-1].fioRS =fioRS; aReIdentReport[aReIdentReport.Size-1].fioCIK =fioCIK; aReIdentReport[aReIdentReport.Size-1].fioDistance=l; aReIdentReport[aReIdentReport.Size-1].docTypeRS =fPaperKind.rec.CodeDocum; aReIdentReport[aReIdentReport.Size-1].docNumRS =Trim(fRegDoc.rec.Series+" "+fRegDoc.rec.DocNum); aReIdentReport[aReIdentReport.Size-1].docTypeCIK =ДокВид; aReIdentReport[aReIdentReport.Size-1].docNumCIK =Trim(ДокСер+" "+ДокНом); aReIdentReport[aReIdentReport.Size-1].adrCIK =Адрес; aReIdentReport[aReIdentReport.Size-1].bdCIK =ДатаРожд; end; end; getOk=fRegDoc.Next; end; if (not flagFind) PrintLn("Документ "+ ДокВид +" (" +fPaperKind.rec.Name+") " + ДокСер +" "+ ДокНом +" не найден"); end; else cntBadDoc[iQuery]=cntBadDoc[iQuery]+1; PrintLn("ERROR: Не найден документ вида "+ДокВид); end; if (not okPaperKind or not flagFind) //--- а вдруг? fPersn.rec.LastName=Фамилия; var okPersn=fPersn.GetGE(); while (okPersn and (StrUpr(fPersn.rec.LastName)==StrUpr(Фамилия))) if ((StrUpr(fPersn.rec.Name)==StrUpr(Имя)) and (StrUpr(fPersn.rec.Patronymic)==StrUpr(Отчество)) and (String(fPersn.rec.BirthDate:f)==ДатаРожд)) PrintLn("WARNING: "+GetClientCodeById(fPersn.rec.ClientID)+" "+fPersn.rec.Name+" "+fPersn.rec.Patronymic+" "+"Совпало ФИО+Др."); cntFoundFIODR[iQuery]=cntFoundFIODR[iQuery]+1; //v0.6 список на повторную идентификацию //только тех, у кого стоит признак "Клиент" и он не закрыт if (IsClientOwnerKind(fPersn.rec.ClientID,PTK_CLIENT) and ClientIsOpen(fPersn.rec.ClientID)) aReIdentReport[aReIdentReport.Size]=GenObject("TReIdentReport",fPersn.rec.ClientID); aReIdentReport[aReIdentReport.Size-1].fioRS =fioRS; aReIdentReport[aReIdentReport.Size-1].fioCIK =fioCIK; aReIdentReport[aReIdentReport.Size-1].fioDistance=0; aReIdentReport[aReIdentReport.Size-1].docTypeCIK =ДокВид; aReIdentReport[aReIdentReport.Size-1].docNumCIK =Trim(ДокСер+" "+ДокНом); aReIdentReport[aReIdentReport.Size-1].GetRSDoc(); aReIdentReport[aReIdentReport.Size-1].adrCIK =Адрес; aReIdentReport[aReIdentReport.Size-1].bdCIK =ДатаРожд; end; end; okPersn=fPersn.next; end; //--- end; //if (flagFindAcc) if (aNodeAccount.Size>0) var domNodeAcc; var domNodeAccTop; var domNodeInfo=GetXPathItems("СлужИнфо",domPersons.item(iPerson)).item(0); for (domNodeAcc, aNodeAccount) domNodeAccTop=domPersons.item(iPerson).insertBefore(DOMDoc.CreateElement("Счета"),domNodeInfo); domNodeAccTop.setAttribute("ИдСчета",{Reg_Num}+SubStr(domNodeAcc.GetAttribute("НомерСчета"),1,8)+SubStr(domNodeAcc.GetAttribute("НомерСчета"),10,11)); domNodeAccTop.insertBefore(domNodeAcc,domNodeAccTop.childNodes(1)); var domNodeBank=domNodeAccTop.appendChild(DOMDoc.CreateElement("КредитОрг")); domNodeBank.setAttribute("НаимКредит", НаимКредит); domNodeBank.setAttribute("КодСубКред", КодСубКред); domNodeBank.setAttribute("КонфАдрКред", КонфАдрКред); if (НеконфАдрКред!="") domNodeBank.setAttribute("НеконфАдрКред",НеконфАдрКред); end; end; cntPerson[iQuery]=cntPerson[iQuery]+1; else domPersons.item(iPerson).ParentNode.RemoveChild(domPersons.item(iPerson)); end; end; end; domPersons=null; if ((ValType(cntPerson[iQuery])!=V_UNDEF) and (cntPerson[iQuery]>0)) //YZZZZZZZZZZZZZ_DDMMGG_hhmmss_T_NNNN.xml //Y: K - для кредитных организаций, D - для депозитариев, R - для регистраторов, S - для спецдепозитариев sOutFileName="K"+GetClientRegNumber({OurBankId})+"_"+flFormDate("%y%m%d_%H%M%S")+"_"+sQueryType+"_"+String((iQueryNumber+1):o:4); domDoc.documentElement.SetAttribute("ИдФайл",sOutFileName); sOutFileName=sOutFileName+".xml"; domDoc.documentElement.SetAttribute("ВерсПрог",ВерсПрог); //12.07.2016 if (flagValidateAnswer) //подменяем путь к XSD if (flagUseXsdPathHack) domDoc.documentElement.SetAttribute("xsi:noNamespaceSchemaLocation",CnvPath(folderXSD+"\\"+"VO_CIK_CB_7.xsd")); end; if (not flagValidateQuery) domDoc.Schemas=objQuerySchemaCache; end; objXsdErr=domDoc.Validate(); if (objXsdErr.errorCode==0) PrintLn("Проверка ответа "+sOutFileName+" на соответствие XSD схеме прошла успешно"); answerXsdResult[iQuery]="OK"; else PrintLn("ERROR: Ошибка при проверке ответа "+sOutFileName+" на соответствие XSD схеме. \n Код: "+" "+String(objXsdErr.errorCode)+". ("+objXsdErr.reason+") "+ "\n Строка: "+objXsdErr.Line+", "+objXsdErr.linepos + " в файле: "+objXsdErr.filepos+ "\n Исходный текст: "+objXsdErr.srcText); answerXsdResult[iQuery]="ERR"; //continue; end; //восстанавливаем путь к XSD if (flagUseXsdPathHack) domDoc.documentElement.SetAttribute("xsi:noNamespaceSchemaLocation","VO_CIK_CB_7.xsd"); end; end; DOMDoc.Save(folderOUT+"\\"+sOutFileName); answerName[iQuery]=sOutFileName; PrintLn("В ответ на файл "+dirIN.Name(iQuery)+" сформирован файл "+sOutFileName+" количество персон "+cntPerson[iQuery]); else PrintLn("Ответ на файл "+dirIN.Name(iQuery)+" НЕ сформирован. Персоны не найдены "); if (flagKvtNotFound) Kvt(null, 1000, null); end; end; DOMDoc=null; PrintLN(); Log_WriteCheckpoint (1003,"Обработка запроса ЦИК ЦБР "+queryName[iQuery]); elif(iMatch==0) PrintLN("BADFN: "+dirIN.Name(iQuery)); queryXsdResult[iQuery]="EFN"; elif(iMatch<0) PrintLN("ERROR: "+strErr); queryXsdResult[iQuery]="E"; //PrintLN(" RE: "+strRE ); end; end; var t_finish=Time(); MakeReport(); MakeReportReIdent(); PrintLn("Время выполнения: "+String(t_finish-t_start)); //допущение, что не переваливает через полночь /* Словарь: ..\DBFILE\bank.def Структура файла: paprkind.dbt (Виды документов ) ------------------------------------------------------------------------ Имя поля | Тип |Длина|Смещ.| Примечание -----------------------|-------|-----|-----|---------------------------- PaperKind INT 2 0 Номер вида документа, удост.личность Name STRING 90 2 Название вида Definition STRING 165 92 Описание вида CodeDocum STRING 5 257 Код документа FM_CodeDocum STRING 5 262 Соответствующий код в ФМ CodeASV STRING 5 267 Код документа (1417-У) Reserved STRING 60 272 Резерв ------------------------------------------------------------------------ 332 Ключи файла ------------------------------------------------------------------------ Номер| Имя поля | Флаги | Тип |Длина|Смещ.|Примечание -----|-----------------------|----------|-------|-----|-----|----------- 0 PaperKind M E INTEGER 2 0 1 CodeDocum M N E ZSTRING 5 0 4 RDKind DM S E INTEGER 4 0 4 Series DM S E ZSTRING 16 0 4 DocNum DM S E ZSTRING 36 0 4 Client DM E INTEGER 4 0 */ /* /* %a Abbreviated weekday name %A Full weekday name %b Abbreviated month name %B Full month name %c Date and time representation appropriate for locale %d Day of month as decimal number (01 Ц 31) %H Hour in 24-hour format (00 Ц 23) %I Hour in 12-hour format (01 Ц 12) %j Day of year as decimal number (001 Ц 366) %m Month as decimal number (01 Ц 12) %M Minute as decimal number (00 Ц 59) %p Current localeТs A.M./P.M. indicator for 12-hour clock %S Second as decimal number (00 Ц 59) %U Week of year as decimal number, with Sunday as first day of week (00 Ц 53) %w Weekday as decimal number (0 Ц 6; Sunday is 0) %W Week of year as decimal number, with Monday as first day of week (00 Ц 53) %x Date representation for current locale %X Time representation for current locale %y Year without century, as decimal number (00 Ц 99) %Y Year with century, as decimal number %z, %Z Time-zone name or abbreviation; no characters if time zone is unknown %% Percent sign As in the printf function, the # flag may prefix any formatting code. In that case, the meaning of the format code is changed as follows. Format Code Meaning %#a, %#A, %#b, %#B, %#p, %#X, %#z, %#Z, %#% # flag is ignored. %#c Long date and time representation, appropriate for current locale. For example: УTuesday, March 14, 1995, 12:41:29Ф. %#x Long date representation, appropriate to current locale. For example: УTuesday, March 14, 1995Ф. %#d, %#H, %#I, %#j, %#m, %#M, %#S, %#U, %#w, %#W, %#y, %#Y Remove leading zeros (if any */ */