АСНА — различия между версиями
Материал из wiki.standart-n.ru
Agk (обсуждение | вклад) (→Общие сведения) |
Agk (обсуждение | вклад) |
||
(не показано 7 промежуточных версии этого же участника) | |||
Строка 2: | Строка 2: | ||
[http://www.asna.ru АСсоциация Независимых Аптек (АСНА)] | [http://www.asna.ru АСсоциация Независимых Аптек (АСНА)] | ||
− | Описание формата взаимодействия есть в регламенте информационного взаимодействия Приложение | + | Описание формата взаимодействия есть в регламенте информационного взаимодействия Приложение на 2018 год [[Файл:Приложение 2. Регламент информационного обмена 2018-10-18.zip]] |
Согласно него нужно выгрузить 4 файла: | Согласно него нужно выгрузить 4 файла: | ||
1) goods.dbf - справочник товаров; | 1) goods.dbf - справочник товаров; | ||
Строка 9: | Строка 9: | ||
4) *_RST.txt - остатки в каждой аптеке на последний день периода выгрузки; | 4) *_RST.txt - остатки в каждой аптеке на последний день периода выгрузки; | ||
− | == | + | ==Скрипт для обновления структуры базы (сводная или серверная базы)== |
<nowiki> | <nowiki> | ||
/******************************************************************************/ | /******************************************************************************/ | ||
Строка 409: | Строка 409: | ||
</nowiki> | </nowiki> | ||
− | == | + | ==Описание изменения структуры базы== |
+ | 1) <b>Таблица ASNA_GOODS</b>: | ||
+ | приведенный справочник товаров. Соответствует формату файла goods.dbf из регламента. | ||
+ | Наполнение автоматически триггером WARES_BU0_MGN_NAME_ASNA. | ||
+ | Логика: при появлении новой позиции в wares с пустым mgn_name триггер ищет по ШК уже приведенное наименование и подставляет его, | ||
+ | если по ШК не найдено ищем по name_id, если не найдено, подставляем из VALS по name_id. | ||
+ | Далее если этой позции не найдено в ASNA_GOODS ни по имени ни по ШК, добавляем новую запись. <b>НЕ ОЧИЩАТЬ!</b> | ||
+ | |||
+ | 2) <b>Таблица ASNA_G$PROFILES</b>: | ||
+ | От АСНЫ получен файл "Коды АСНА.xls", там соответствие имени аптеки и внутреннего АСНА-кода. | ||
+ | В таблице ASNA_G$PROFILES хранится соответствие АСНА-кода и кода профиля аптеки. <b>НЕ ОЧИЩАТЬ!</b> | ||
+ | [[Файл:АСНА_аптеки.png|left|Пример]] | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | 3) <b>Таблица ASNA_AGENT_REGION</b>: | ||
+ | хранится соответствие ИНН и кода региона контрагента; <b>НЕ ОЧИЩАТЬ!</b> | ||
+ | |||
+ | 4) <b>Таблица ASNA_WAREBASE</b>: | ||
+ | временная таблица для сборки остатков (файл *_RST.txt), заполняется в момент работы ТМС, потом данные не нужны, каждый раз очищается автоматически. | ||
+ | |||
+ | 5) <b>Таблица ASNA_AGENTS_G$PROFILES</b>: | ||
+ | т.к. контрагенты у нас не централизованы, в этой таблице хранится соответствие ID/G$PROFILE_ID из AGENTS и кода профиля в таблице G$PROFILES. <b>НЕ ОЧИЩАТЬ!</b> | ||
+ | |||
+ | ==Выгрузка== | ||
+ | Файлы выгрузки формируется ТМС "Выгрузка в АСНА" в spacepro, запуск из планировщика заданий. | ||
+ | Файлы формируются примерно 1 час, после чего запускается из планировщика новое задание (т.к. spacepro не умеет работать с ftp сам) | ||
+ | по выгрузке их на ftp (IP, логин/пароль в файле "Коды АСНА.xls "). | ||
+ | АСНА просит выгружать ежедневно, чтобы файлы в 22-00 были на ftp. Каждый раз выгрузка идет за последнюю неделю, при этом данные в хранилище АСНЫ удаляются | ||
+ | и загружаются заново, после чего на ftp файлы переносятся в папку с бекапами. | ||
+ | Если на ftp положить 2 раза одни и те же движения/остатки, то при выгрузке данные <b>задублируются!</b> | ||
+ | |||
+ | |||
+ | ==TMS== | ||
+ | <nowiki> | ||
+ | uses | ||
+ | Classes, Graphics, Controls, Forms, Dialogs, | ||
+ | undm, IBQuery,DB, IBDatabase,ADODB, SysUtils, | ||
+ | unMain,ShellApi,cfutils,Windows,StdCtrls, ComCtrls, ExtCtrls,DB,IBDatabase; | ||
+ | |||
+ | var q: TIBQuery; | ||
+ | ac: TAdoConnection; | ||
+ | AdoWork: Tadoquery; | ||
+ | t,comments,gd,sname, path_tmp,path, INN,org_code,def_region: String; | ||
+ | FileName : String; | ||
+ | sl: TStringList; | ||
+ | FT : TextFile; | ||
+ | date1,date2:string; | ||
+ | |||
+ | begin | ||
+ | path_tmp:='C:\Standart-N\ASNA\'; //Временная папка для файлов | ||
+ | date1:= DateToStr(Date-21); //'01.05.2016'; // | ||
+ | date2:= DateToStr(Date); //'30.06.2016'; // | ||
+ | INN:='1234567890'; //ИНН | ||
+ | org_code:='Org_TEST'; //Код юр. лица АСНА | ||
+ | def_region:='18'; | ||
+ | |||
+ | q:=dm.TempQuery(nil); | ||
+ | q.Active:=false; | ||
+ | //1) ---------------- Структура файла «Справочник товаров» Имя файла «goods.dbf» ------------------------------------------- | ||
+ | if 1=1 Then | ||
+ | Begin | ||
+ | q.SQL.text:='select id, Replace(MGN_NAME,'' : '','''') as name, PRODUCER, COUNTRY, EAN from ASNA_GOODS order by MGN_NAME'; | ||
+ | q.Active:=true; | ||
+ | |||
+ | ac:=TAdoConnection.Create(application); | ||
+ | AdoWork:=Tadoquery.create(application); | ||
+ | ac.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=dBASE IV;User ID=Admin;Password=;Data Source='+path_tmp; | ||
+ | ac.LoginPrompt:=false; | ||
+ | AdoWork.Connection:=ac; | ||
+ | if FileExists(path_tmp+'goods.dbf') then | ||
+ | begin | ||
+ | deletefile(path_tmp+'goods.dbf'); | ||
+ | end | ||
+ | AdoWork.Active:=false; | ||
+ | t:='CREATE TABLE goods (ID CHAR(250),NAME CHAR(250),PRODUCER CHAR(250), COUNTRY CHAR(250), EAN CHAR(250))'; | ||
+ | // frmSpacePro.Logit(t); | ||
+ | AdoWork.SQL.Text:=t; | ||
+ | AdoWork.ExecSQL; | ||
+ | |||
+ | while not q.Eof do | ||
+ | begin | ||
+ | t:='insert into goods (ID,NAME,PRODUCER,COUNTRY,EAN) values ('''+ | ||
+ | Trim(stringreplace(q.FieldByName('ID').AsString,'''','.',1))+''','''+ | ||
+ | stringreplace(q.FieldByName('NAME').AsString,'''','.',1)+''','''+ | ||
+ | stringreplace(q.FieldByName('PRODUCER').AsString,'''','.',1)+''','''+ | ||
+ | stringreplace(q.FieldByName('COUNTRY').AsString,'''','.',1)+''','''+ | ||
+ | stringreplace(q.FieldByName('EAN').AsString,'''','.',1)+''');'; | ||
+ | // frmSpacePro.LogIt(t); | ||
+ | AdoWork.SQL.Text:=t; | ||
+ | AdoWork.ExecSQL; | ||
+ | q.Next; | ||
+ | end; | ||
+ | q.Transaction.Commit; | ||
+ | q.Transaction.StartTransaction; | ||
+ | end; | ||
+ | // FTP.Put(path_tmp+'goods.dbf', 'goods.dbf', TRUE); | ||
+ | |||
+ | //2) ---------------- Структура файла «Контрагенты» Имя файла «vendor.dbf»» ------------------------------------------- | ||
+ | if 1=1 Then | ||
+ | Begin | ||
+ | q.Active:=false; | ||
+ | q.SQL.text:='select ''1'' as id, ''Мелкооптовый покупатель'' as name, '''+INN+''' as inn from rdb$database | ||
+ | union | ||
+ | select ''2'' as id, ''Розничный покупатель (ККМ)'' as name, '''+INN+''' as inn from rdb$database | ||
+ | union | ||
+ | select ''3'' as id, ''Ввод остатков'' as name, '''+INN+''' as inn from rdb$database | ||
+ | union | ||
+ | select cast(a.id as varchar(255))||''_''||cast(g$profile_id as varchar(255)) as ID, caption as name, coalesce(INN,'''') as INN from agents a inner join ASNA_G$PROFILES ga on ga.id = a.g$profile_id where ga.id is not null and a.id > 0 | ||
+ | order by 2'; | ||
+ | // frmSpacePro.LogIt(q.SQL.text); | ||
+ | q.Active:=true; | ||
+ | |||
+ | ac:=TAdoConnection.Create(application); | ||
+ | AdoWork:=Tadoquery.create(application); | ||
+ | ac.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=dBASE IV;User ID=Admin;Password=;Data Source='+path_tmp; | ||
+ | ac.LoginPrompt:=false; | ||
+ | AdoWork.Connection:=ac; | ||
+ | if FileExists(path_tmp+'vendor.dbf') then | ||
+ | begin | ||
+ | deletefile(path_tmp+'vendor.dbf'); | ||
+ | end | ||
+ | AdoWork.Active:=false; | ||
+ | t:='CREATE TABLE vendor(ID CHAR(250),NAME CHAR(250),INN CHAR(250))'; | ||
+ | // frmSpacePro.Logit(t); | ||
+ | AdoWork.SQL.Text:=t; | ||
+ | AdoWork.ExecSQL; | ||
+ | |||
+ | while not q.Eof do | ||
+ | begin | ||
+ | t:='insert into vendor(ID,NAME,INN) values ('''+ | ||
+ | stringreplace(q.FieldByName('ID').AsString,'''','.',1)+''','''+ | ||
+ | stringreplace(q.FieldByName('NAME').AsString,'''','.',1)+''','''+ | ||
+ | stringreplace(q.FieldByName('INN').AsString,'''','.',1)+''');'; | ||
+ | //frmSpacePro.LogIt(t); | ||
+ | AdoWork.SQL.Text:=t; | ||
+ | AdoWork.ExecSQL; | ||
+ | q.Next; | ||
+ | end; | ||
+ | q.Transaction.Commit; | ||
+ | end; | ||
+ | |||
+ | //3) ---------------- Структура файла «Данные о товародвижении» Имя файла «название юридического лица_название торгового объекта_дата и время формирования файла.TXT»» ------------------------------------------- | ||
+ | if 1=1 Then | ||
+ | begin | ||
+ | //q.Transaction.StartTransaction; | ||
+ | q.Active:=false; | ||
+ | q.SQL.text:='select '''+org_code+'''||''_''||ga.asna_code||''_''||replace(cast(current_date as varchar(255)),''-'','''')||''T''||replace(left(cast(current_time as varchar(255)),5),'':'','''')||''.txt'' as filename, | ||
+ | cast(dd.id as varchar(255))||''_''||cast(dd.g$profile_id as varchar(255)) as ID, | ||
+ | cast(d.id as varchar(255))||''_''||cast(d.g$profile_id as varchar(255)) as DOC_ID, | ||
+ | '''+org_code+''' as ur_l, | ||
+ | ga.asna_code, | ||
+ | case d.doc_type | ||
+ | when 11 then 1 --мелкооптовый отпуск | ||
+ | when 3 then 2 --продажа через ККМ | ||
+ | when 1 then 3 --приход товара | ||
+ | when 9 then 4 --возврат от покупателя | ||
+ | when 37 then 4 --возврат от покупателя | ||
+ | when 4 then 5 --возврат поставщику | ||
+ | when 2 then 6 --межскладская передача | ||
+ | when 17 then 7 --Списание | ||
+ | when 10 then 7 --Списание | ||
+ | when 5 then 7 --Списание | ||
+ | when 20 then 8 --Ввод остатков | ||
+ | end as doc_type, | ||
+ | case d.doc_type | ||
+ | when 11 then '''+INN+''' --мелкооптовый отпуск | ||
+ | when 3 then '''+INN+''' --продажа через ККМ | ||
+ | when 1 then coalesce(a.inn,'''') --приход товара | ||
+ | when 2 then (select asna_code from ASNA_G$PROFILES where id = ga_ag.g$profile_id_apt) --межскладская передача | ||
+ | when 17 then ga.asna_code --Списание | ||
+ | when 10 then ga.asna_code --Списание | ||
+ | when 5 then ga.asna_code --Списание | ||
+ | when 20 then ga.asna_code --Ввод остатков | ||
+ | else '''' | ||
+ | end as sagent, | ||
+ | left(cast(d.commitdate as varchar(255)),19) as doc_date, | ||
+ | case d.doc_type | ||
+ | when 3 then d.docnum||''Ч''||(select max(docnum) from docs d2 where d2.g$profile_id = d.g$profile_id and d2.status = 1 and d2.doc_type=13 and d2.vshift = d.vshift and d2.device_num = d.device_num) | ||
+ | else d.docnum | ||
+ | end as docnum, | ||
+ | dcard, | ||
+ | (select GOODS_ID from PR_ASNA_GET_GOODS(p.ware_id)) as GOODS_ID, | ||
+ | abs(dd.quant) as quant, | ||
+ | (select inn from agents where id = (select AGENT_ID from PR_GETMOTHERPART(dd.part_id, dd.g$profile_id) ) and g$profile_id = dd.g$profile_id) as inn, | ||
+ | abs(Round((dd.quant*p.price_o*100/(100+dp.nds)),2)) as sum_b_nds, | ||
+ | abs(dd.summa_o) as summa_o, | ||
+ | abs(Round((dd.summa_o-dd.quant*p.price_o*100/(100+dp.nds)),2)) as sum_nds, | ||
+ | abs(dd.summa+dd.sum_dsc) as summa_b_dsc, | ||
+ | abs(dd.summa) as summa, | ||
+ | abs(dd.sum_dsc) as sum_dsc, | ||
+ | d.status, | ||
+ | coalesce((select region from ASNA_AGENT_REGION where inn = a.inn),'+def_region+') as region | ||
+ | from doc_detail dd | ||
+ | inner join docs d on dd.doc_id = d.id and dd.g$profile_id = d.g$profile_id | ||
+ | inner join ASNA_G$PROFILES ga on ga.id = d.g$profile_id | ||
+ | inner join agents a on a.id=d.agent_id and a.g$profile_id = d.g$profile_id | ||
+ | inner join parts p on p.g$profile_id = dd.g$profile_id and dd.part_id = p.id | ||
+ | inner join deps dp on p.g$profile_id = dp.g$profile_id and p.dep = dp.id | ||
+ | left join asna_agents_g$profiles ga_ag on ga_ag.agent_id = a.id and ga_ag.g$profile_id = a.g$profile_id | ||
+ | where ga.id is not null and d.status = 1 and d.doc_type in (11,2,3,1,37,9,4,17,10,5,20) and dd.doc_commitdate between '''+date1+''' and '''+date2+''' | ||
+ | and (select GOODS_ID from PR_ASNA_GET_GOODS(p.ware_id)) is not null | ||
+ | order by 1 '; | ||
+ | |||
+ | |||
+ | q.Active:=true; | ||
+ | filename:=''; | ||
+ | while not q.Eof do | ||
+ | begin | ||
+ | If filename='' Then | ||
+ | begin | ||
+ | filename:= path_tmp+q.FieldByName('filename').AsString; | ||
+ | AssignFile(FT, FileName); | ||
+ | if FileExists(FileName) then | ||
+ | Append(FT) | ||
+ | else | ||
+ | Rewrite(FT); | ||
+ | end; | ||
+ | |||
+ | if filename = path_tmp+q.FieldByName('filename').AsString Then | ||
+ | begin | ||
+ | t:='"'+q.FieldByName('ID').AsString+'"|"'+q.FieldByName('DOC_ID').AsString+'"|"'+q.FieldByName('ur_l').AsString+'"|"'+q.FieldByName('asna_code').AsString+'"|'+ | ||
+ | q.FieldByName('DOC_TYPE').AsString+'|"'+q.FieldByName('SAGENT').AsString+'"|'+q.FieldByName('DOC_DATE').AsString+'|"'+q.FieldByName('DOCNUM').AsString+'"|1|"'+ | ||
+ | q.FieldByName('DCARD').AsString+'"|"1"|"'+q.FieldByName('DCARD').AsString+'"|"'+q.FieldByName('DCARD').AsString+'"|"'+Trim(q.FieldByName('GOODS_ID').AsString)+'"|'+ | ||
+ | stringreplace(q.FieldByName('QUANT').AsString,',','.',1)+'|"'+q.FieldByName('INN').AsString+'"|'+q.FieldByName('region').AsString+'|'+stringreplace(q.FieldByName('sum_b_nds').AsString,',','.',1)+'|'+ | ||
+ | stringreplace(q.FieldByName('summa_o').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('sum_nds').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('summa').AsString,',','.',1)+'|'+ | ||
+ | stringreplace(q.FieldByName('summa_b_dsc').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('sum_dsc').AsString,',','.',1)+'|'+q.FieldByName('status').AsString; | ||
+ | // frmSpacePro.LogIt(t); | ||
+ | WriteLn(FT, t); | ||
+ | end | ||
+ | else | ||
+ | Begin | ||
+ | CloseFile(FT); | ||
+ | filename:= path_tmp+q.FieldByName('filename').AsString; | ||
+ | AssignFile(FT, FileName); | ||
+ | if FileExists(FileName) then | ||
+ | Append(FT) | ||
+ | else | ||
+ | Rewrite(FT); | ||
+ | end; | ||
+ | q.Next; | ||
+ | end; | ||
+ | CloseFile(FT); | ||
+ | q.Transaction.Commit; | ||
+ | end; | ||
+ | |||
+ | //4) ---------------- Структура файла «Данные об остатках» Имя файла «название юридического лица_название торгового объекта_дата и время формирования файла_суфиксRST.TXT»» ------------------------------------------- | ||
+ | //Предподготовка к выгрузке остатков - расчет остатков на конец периода | ||
+ | q.Transaction.StartTransaction; | ||
+ | q.Active:=false; | ||
+ | q.SQL.Text:='delete from ASNA_WAREBASE'; | ||
+ | q.ExecSQL; | ||
+ | q.Transaction.Commit; | ||
+ | |||
+ | q.Transaction.StartTransaction; | ||
+ | q.Active:=false; | ||
+ | q.SQL.Text:='insert into ASNA_WAREBASE(part_id, G$PROFILE_ID,ddate) select id, G$PROFILE_ID, '''+date2+''' from parts p'; | ||
+ | q.ExecSQL; | ||
+ | q.Transaction.Commit; | ||
+ | |||
+ | q.Transaction.StartTransaction; | ||
+ | q.Active:=false; | ||
+ | q.SQL.Text:='select '''+org_code+'''||''_''||ga.asna_code||''_''||replace(cast(current_date as varchar(255)),''-'','''')||''T''||replace(left(cast(current_time as varchar(255)),5),'':'','''')||''_RST.txt'' as filename, | ||
+ | '''+org_code+''' as ur_l, | ||
+ | ga.asna_code, | ||
+ | a.inn, | ||
+ | left(cast(cast(dateadd(1 day to w.ddate) as dm_datetime) as varchar(255)),19) as beg_date, | ||
+ | left(cast(d.commitdate as varchar(255)),19) as post_date, | ||
+ | (select GOODS_ID from PR_ASNA_GET_GOODS(w.ware_id)) as GOODS_ID, | ||
+ | w.quant, | ||
+ | coalesce(abs(Round((w.quant*w.price_o*100/(100+w.nds)),2)),0) as sum_b_nds, | ||
+ | coalesce(abs(Round(w.quant*w.price_o,2)),0) as summa_o, | ||
+ | coalesce(abs(Round((w.quant*w.price_o-w.quant*w.price_o*100/(100+w.nds)),2)),0) as sum_nds, | ||
+ | coalesce(abs(round(w.quant*w.price,2)),0) as summa, | ||
+ | coalesce((select region from ASNA_AGENT_REGION where inn = a.inn),'+def_region+') as region | ||
+ | from ASNA_WAREBASE w | ||
+ | inner join docs d on w.doc_id = d.id and w.g$profile_id = d.g$profile_id | ||
+ | inner join ASNA_G$PROFILES ga on ga.id = w.g$profile_id | ||
+ | inner join agents a on a.id=d.agent_id and a.g$profile_id = d.g$profile_id | ||
+ | where ga.id is not null and w.quant > 0.01 and (select GOODS_ID from PR_ASNA_GET_GOODS(w.ware_id)) is not null | ||
+ | order by 1' | ||
+ | q.Active:=true; | ||
+ | filename:=''; | ||
+ | while not q.Eof do | ||
+ | begin | ||
+ | If filename='' Then | ||
+ | begin | ||
+ | filename:= path_tmp+q.FieldByName('filename').AsString; | ||
+ | AssignFile(FT, FileName); | ||
+ | if FileExists(FileName) then | ||
+ | Append(FT) | ||
+ | else | ||
+ | Rewrite(FT); | ||
+ | end; | ||
+ | |||
+ | if filename = path_tmp+q.FieldByName('filename').AsString Then | ||
+ | begin | ||
+ | t:='"'+q.FieldByName('ur_l').AsString+'"|"'+q.FieldByName('asna_code').AsString+'"|"'+q.FieldByName('INN').AsString+'"|'+q.FieldByName('region').AsString+'|'+ | ||
+ | q.FieldByName('beg_date').AsString+'|'+q.FieldByName('post_date').AsString+'|"'+Trim(q.FieldByName('GOODS_ID').AsString)+'"|'+ | ||
+ | stringreplace(q.FieldByName('QUANT').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('sum_b_nds').AsString,',','.',1)+'|'+ | ||
+ | stringreplace(q.FieldByName('summa_o').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('sum_nds').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('summa').AsString,',','.',1); | ||
+ | WriteLn(FT, t); | ||
+ | end | ||
+ | else | ||
+ | Begin | ||
+ | CloseFile(FT); | ||
+ | filename:= path_tmp+q.FieldByName('filename').AsString; | ||
+ | AssignFile(FT, FileName); | ||
+ | if FileExists(FileName) then | ||
+ | Append(FT) | ||
+ | else | ||
+ | Rewrite(FT); | ||
+ | end; | ||
+ | q.Next; | ||
+ | end; | ||
+ | CloseFile(FT); | ||
+ | q.Transaction.Commit; | ||
+ | |||
+ | end; | ||
+ | </nowiki> | ||
+ | |||
+ | ==Выгрузка на FTP== | ||
+ | Для выгрузки используется программа [[Файл:Ncftpput.zip]], [http://www.7-zip.org 7-Zip] для архивирования и bat файл (uploadftp.bat), содержимое последнего ниже: | ||
+ | <nowiki> | ||
+ | @Echo Off | ||
+ | C:\Standart-N\asna_ftp\ncftpput.exe -F -u Org_TEST -p password123 ftp.fttech.ru \ C:\Standart-N\ASNA\*.dbf | ||
+ | C:\Standart-N\asna_ftp\ncftpput.exe -F -u Org_TEST -p password123 ftp.fttech.ru \ C:\Standart-N\ASNA\*.txt | ||
+ | ping -n 600 127.0.0.1 > NUL | ||
+ | MD C:\Standart-N\ASNA\%date:~-10% | ||
+ | move /y C:\Standart-N\ASNA\*.txt C:\Standart-N\ASNA\%date:~-10% | ||
+ | move /y C:\Standart-N\ASNA\*.dbf C:\Standart-N\ASNA\%date:~-10% | ||
+ | "C:\Program Files\7-Zip\7z.exe" a -tzip -ssw -mx7 -r0 C:\Standart-N\ASNA\%date:~-10%.zip C:\Standart-N\ASNA\%date:~-10% | ||
+ | RD /S /Q C:\Standart-N\ASNA\%date:~-10% | ||
+ | </nowiki> | ||
+ | |||
+ | ==FAQ (ЧаВо)== | ||
+ | 1) Необходимо по какой-то причине выгрузить данные за определенный период: | ||
+ | - открываем в своднике ТМС по выгрузке АСНА; | ||
+ | - правим в начале даты начала и конца периода, запускаем на выполнение; | ||
+ | - после выгрузки, копируем созданные файлы (путь к временной папке прописан тут же в коде ТМС) на ftp; | ||
+ | - возвращаем код ТМС (даты) в прежнее положение. | ||
+ | |||
+ | 2) Вопрос клиента: "Для Асны в выгрузке не вижу Цетиризин-Тева 10мг №10, Бинт Пеха хафт 4х6". | ||
+ | Наши действия: | ||
+ | - проверить в выгружаемой базе таблицу wares поле mgn_name по указанным препаратам, скорее всего неправильно сработало приведение; | ||
+ | - исправить на правильное значение; | ||
+ | - выгрузить данные заново за требуемый период. |
Текущая версия на 09:49, 28 июня 2023
Содержание
Общие сведения
АСсоциация Независимых Аптек (АСНА)
Описание формата взаимодействия есть в регламенте информационного взаимодействия Приложение на 2018 год Файл:Приложение 2. Регламент информационного обмена 2018-10-18.zip
Согласно него нужно выгрузить 4 файла: 1) goods.dbf - справочник товаров; 2) vendor.dbf - контрагенты; 3) *.txt - движения товаров по каждой аптеке за выгружаемый период; 4) *_RST.txt - остатки в каждой аптеке на последний день периода выгрузки;
Скрипт для обновления структуры базы (сводная или серверная базы)
/******************************************************************************/ /*** Generated by IBExpert 11.07.2016 11:33:31 ***/ /******************************************************************************/ /******************************************************************************/ /*** Following SET SQL DIALECT is just for the Database Comparer ***/ /******************************************************************************/ SET SQL DIALECT 3; /******************************************************************************/ /*** Tables ***/ /******************************************************************************/ CREATE TABLE ASNA_AGENTS_G$PROFILES ( AGENT_ID DM_ID /* DM_ID = BIGINT NOT NULL */, G$PROFILE_ID DM_ID /* DM_ID = BIGINT NOT NULL */, G$PROFILE_ID_APT DM_ID /* DM_ID = BIGINT NOT NULL */ ); /******************************************************************************/ /*** Primary Keys ***/ /******************************************************************************/ ALTER TABLE ASNA_AGENTS_G$PROFILES ADD CONSTRAINT PK_ASNA_AGENTS_G$PROFILES_1 PRIMARY KEY (AGENT_ID, G$PROFILE_ID); /******************************************************************************/ /*** Privileges ***/ /******************************************************************************/ /******************************************************************************/ /*** Generated by IBExpert 11.07.2016 11:33:40 ***/ /******************************************************************************/ /******************************************************************************/ /*** Following SET SQL DIALECT is just for the Database Comparer ***/ /******************************************************************************/ SET SQL DIALECT 3; /******************************************************************************/ /*** Tables ***/ /******************************************************************************/ CREATE TABLE ASNA_AGENT_REGION ( INN DM_TEXT NOT NULL /* DM_TEXT = VARCHAR(250) */, REGION INTEGER NOT NULL, COMMENT DM_TEXT /* DM_TEXT = VARCHAR(250) */ ); /******************************************************************************/ /*** Primary Keys ***/ /******************************************************************************/ ALTER TABLE ASNA_AGENT_REGION ADD CONSTRAINT PK_ASNA_AGENT_REGION_1 PRIMARY KEY (INN); /******************************************************************************/ /*** Privileges ***/ /******************************************************************************/ /******************************************************************************/ /*** Generated by IBExpert 11.07.2016 11:33:47 ***/ /******************************************************************************/ /******************************************************************************/ /*** Following SET SQL DIALECT is just for the Database Comparer ***/ /******************************************************************************/ SET SQL DIALECT 3; /******************************************************************************/ /*** Tables ***/ /******************************************************************************/ CREATE TABLE ASNA_G$PROFILES ( ID DM_ID /* DM_ID = BIGINT NOT NULL */, ASNA_CODE DM_TEXT NOT NULL /* DM_TEXT = VARCHAR(250) */ ); /******************************************************************************/ /*** Primary Keys ***/ /******************************************************************************/ ALTER TABLE ASNA_G$PROFILES ADD CONSTRAINT PK_ASNA_G$PROFILES_1 PRIMARY KEY (ID); /******************************************************************************/ /*** Indices ***/ /******************************************************************************/ CREATE UNIQUE DESCENDING INDEX IDX_ASNA_G$PROFILES_1 ON ASNA_G$PROFILES (ID); ALTER INDEX IDX_ASNA_G$PROFILES_1 INACTIVE; /******************************************************************************/ /*** Privileges ***/ /******************************************************************************/ /******************************************************************************/ /*** Generated by IBExpert 11.07.2016 11:33:53 ***/ /******************************************************************************/ /******************************************************************************/ /*** Following SET SQL DIALECT is just for the Database Comparer ***/ /******************************************************************************/ SET SQL DIALECT 3; /******************************************************************************/ /*** Tables ***/ /******************************************************************************/ CREATE TABLE ASNA_GOODS ( ID DM_UUID /* DM_UUID = CHAR(36) NOT NULL */, MGN_NAME DM_TEXT1024 NOT NULL /* DM_TEXT1024 = VARCHAR(1024) */, PRODUCER DM_TEXT /* DM_TEXT = VARCHAR(250) */, COUNTRY DM_TEXT /* DM_TEXT = VARCHAR(250) */, EAN DM_TEXT /* DM_TEXT = VARCHAR(250) */, INSERTDT DM_DATETIME /* DM_DATETIME = TIMESTAMP */ ); /******************************************************************************/ /*** Unique Constraints ***/ /******************************************************************************/ ALTER TABLE ASNA_GOODS ADD CONSTRAINT UNQ1_ASNA_GOODS UNIQUE (MGN_NAME); /******************************************************************************/ /*** Primary Keys ***/ /******************************************************************************/ ALTER TABLE ASNA_GOODS ADD CONSTRAINT PK_ASNA_GOODS PRIMARY KEY (ID); /******************************************************************************/ /*** Indices ***/ /******************************************************************************/ CREATE INDEX ASNA_GOODS_IDX1 ON ASNA_GOODS (EAN); CREATE INDEX ASNA_GOODS_IDX2 ON ASNA_GOODS (INSERTDT); /******************************************************************************/ /*** Triggers ***/ /******************************************************************************/ SET TERM ^ ; /******************************************************************************/ /*** Triggers for tables ***/ /******************************************************************************/ /* Trigger: ASNA_GOODS_BI0 */ CREATE OR ALTER TRIGGER ASNA_GOODS_BI0 FOR ASNA_GOODS ACTIVE BEFORE INSERT POSITION 0 AS begin if (new.id is null) then new.id = UUID_TO_CHAR(GEN_UUID()); new.insertdt = CURRENT_TIMESTAMP; end ^ SET TERM ; ^ /******************************************************************************/ /*** Privileges ***/ /******************************************************************************/ /******************************************************************************/ /*** Generated by IBExpert 11.07.2016 11:34:00 ***/ /******************************************************************************/ /******************************************************************************/ /*** Following SET SQL DIALECT is just for the Database Comparer ***/ /******************************************************************************/ SET SQL DIALECT 3; /******************************************************************************/ /*** Tables ***/ /******************************************************************************/ CREATE TABLE ASNA_WAREBASE ( PART_ID DM_ID /* DM_ID = BIGINT NOT NULL */, G$PROFILE_ID DM_ID /* DM_ID = BIGINT NOT NULL */, MOTHERPART_ID DM_ID_NULL /* DM_ID_NULL = BIGINT */, QUANT DM_DOUBLE /* DM_DOUBLE = DOUBLE PRECISION */, DDATE DM_DATE /* DM_DATE = DATE */, DOC_ID DM_ID_NULL /* DM_ID_NULL = BIGINT */, PRICE DM_DOUBLE /* DM_DOUBLE = DOUBLE PRECISION */, PRICE_O DM_DOUBLE /* DM_DOUBLE = DOUBLE PRECISION */, NDS DM_DOUBLE /* DM_DOUBLE = DOUBLE PRECISION */, WARE_ID DM_UUID_NULL /* DM_UUID_NULL = CHAR(36) */ ); /******************************************************************************/ /*** Primary Keys ***/ /******************************************************************************/ ALTER TABLE ASNA_WAREBASE ADD CONSTRAINT PK_ASNA_WAREBASE_1 PRIMARY KEY (PART_ID, G$PROFILE_ID); /******************************************************************************/ /*** Triggers ***/ /******************************************************************************/ SET TERM ^ ; /******************************************************************************/ /*** Triggers for tables ***/ /******************************************************************************/ /* Trigger: ASNA_WAREBASE_AI0 */ CREATE OR ALTER TRIGGER ASNA_WAREBASE_AI0 FOR ASNA_WAREBASE ACTIVE AFTER INSERT POSITION 0 AS begin if (abs(coalesce(new.quant,0))< 0.01) then delete from ASNA_WAREBASE w where w.part_id = new.part_id and w.g$profile_id = new.g$profile_id; end ^ /* Trigger: ASNA_WAREBASE_BI0 */ CREATE OR ALTER TRIGGER ASNA_WAREBASE_BI0 FOR ASNA_WAREBASE ACTIVE BEFORE INSERT POSITION 0 AS begin if (new.DDATE is not null) then select sum(dd2.quant) from doc_detail dd2 left join docs d on dd2.doc_id = d.id and dd2.g$profile_id = d.g$profile_id where dd2.part_id = new.part_id and dd2.g$profile_id = new.g$profile_id and dd2.doc_commitdate <= new.DDATE and d.status = 1 into new.quant; if (abs(coalesce(new.quant,0)) > 0.01) then begin select MOTHERPART_ID,DOC_ID from PR_GETMOTHERPART(new.part_id,new.g$profile_id) into new.MOTHERPART_ID, new.DOC_ID; select PRICE, PRICE_O , WARE_ID, dp.nds from parts p inner join deps dp on p.g$profile_id = dp.g$profile_id and p.dep = dp.id where p.g$profile_id = new.g$profile_id and p.id = new.part_id into new.PRICE, new.PRICE_O, new.WARE_ID, new.nds; end end ^ SET TERM ; ^ /******************************************************************************/ /*** Privileges ***/ /******************************************************************************/ SET TERM ^ ; create or alter procedure PR_ASNA_GET_GOODS ( WARE_ID DM_UUID_NULL) returns ( GOODS_ID DM_UUID_NULL) as declare variable MGN_NAME DM_TEXT1024; declare variable BARCODE DM_TEXT; begin GOODS_ID = Null; select w.mgn_name, w.barcode from WARES w where id = :ware_id into :mgn_name, :barcode; if (:mgn_name is null and coalesce(:barcode, '') <> '') then select first 1 w.mgn_name from WARES w where barcode = :barcode into :mgn_name; if (:mgn_name is null and coalesce(:barcode, '') = '') then GOODS_ID = Null; else begin select id from asna_goods ag where ag.mgn_name = coalesce(Trim(:mgn_name),'$$$') into :GOODS_ID; if (:GOODS_ID is null) Then select first 1 id from asna_goods ag where ag.ean = coalesce(:barcode,'$$$') into :GOODS_ID; end suspend; end^ SET TERM ; ^ /* Following GRANT statetements are generated automatically */ GRANT SELECT ON WARES TO PROCEDURE PR_ASNA_GET_GOODS; GRANT SELECT ON ASNA_GOODS TO PROCEDURE PR_ASNA_GET_GOODS; /* Existing privileges on this procedure */ GRANT EXECUTE ON PROCEDURE PR_ASNA_GET_GOODS TO SYSDBA; SET SQL DIALECT 3; SET TERM ^ ; CREATE OR ALTER TRIGGER WARES_BU0_MGN_NAME_ASNA FOR WARES ACTIVE BEFORE INSERT OR UPDATE POSITION 0 AS begin --20150922 А.К. авто приведение, чтоб не запускать Менеджер if ((new.mgn_name is null) and (coalesce(Trim(new.barcode),'') <> '')) then select first 1 mgn_name from wares w where w.barcode = new.barcode and mgn_name <> '' into new.mgn_name; if (new.mgn_name is null) then select first 1 mgn_name from wares w where w.name_id = new.name_id and mgn_name <> '' into new.mgn_name; if (new.mgn_name is null) then select svalue from vals v where v.id = new.name_id into new.mgn_name; if (new.MGN_NAME is null) Then exit; --если в справочнике нет ни по названию ни по ШК, то заносим в ASNA_GOODS if ( (((select count(*) from ASNA_GOODS where MGN_NAME = coalesce(Trim(new.MGN_NAME),'$$$')) > 0) and new.MGN_NAME is not null) or (((select count(*) from ASNA_GOODS where ean = coalesce(new.barcode, '$$$')) > 0) and new.barcode is not null) ) Then begin end else Begin insert into ASNA_GOODS(MGN_NAME, producer, country, ean) select Trim(new.MGN_NAME), (select svalue from vals where id = new.izg_id), (select svalue from vals where id = new.country_id), iif(coalesce(new.barcode,'') = '', (select first 1 barcode from wares w where w.MGN_NAME = Trim(new.MGN_NAME) and coalesce(new.barcode,'') <> ''), new.barcode) from rdb$database; end end ^ SET TERM ; ^ update WARES set id = id;
Описание изменения структуры базы
1) Таблица ASNA_GOODS: приведенный справочник товаров. Соответствует формату файла goods.dbf из регламента. Наполнение автоматически триггером WARES_BU0_MGN_NAME_ASNA. Логика: при появлении новой позиции в wares с пустым mgn_name триггер ищет по ШК уже приведенное наименование и подставляет его, если по ШК не найдено ищем по name_id, если не найдено, подставляем из VALS по name_id. Далее если этой позции не найдено в ASNA_GOODS ни по имени ни по ШК, добавляем новую запись. НЕ ОЧИЩАТЬ!
2) Таблица ASNA_G$PROFILES: От АСНЫ получен файл "Коды АСНА.xls", там соответствие имени аптеки и внутреннего АСНА-кода. В таблице ASNA_G$PROFILES хранится соответствие АСНА-кода и кода профиля аптеки. НЕ ОЧИЩАТЬ!
3) Таблица ASNA_AGENT_REGION: хранится соответствие ИНН и кода региона контрагента; НЕ ОЧИЩАТЬ!
4) Таблица ASNA_WAREBASE: временная таблица для сборки остатков (файл *_RST.txt), заполняется в момент работы ТМС, потом данные не нужны, каждый раз очищается автоматически.
5) Таблица ASNA_AGENTS_G$PROFILES: т.к. контрагенты у нас не централизованы, в этой таблице хранится соответствие ID/G$PROFILE_ID из AGENTS и кода профиля в таблице G$PROFILES. НЕ ОЧИЩАТЬ!
Выгрузка
Файлы выгрузки формируется ТМС "Выгрузка в АСНА" в spacepro, запуск из планировщика заданий. Файлы формируются примерно 1 час, после чего запускается из планировщика новое задание (т.к. spacepro не умеет работать с ftp сам) по выгрузке их на ftp (IP, логин/пароль в файле "Коды АСНА.xls "). АСНА просит выгружать ежедневно, чтобы файлы в 22-00 были на ftp. Каждый раз выгрузка идет за последнюю неделю, при этом данные в хранилище АСНЫ удаляются и загружаются заново, после чего на ftp файлы переносятся в папку с бекапами. Если на ftp положить 2 раза одни и те же движения/остатки, то при выгрузке данные задублируются!
TMS
uses Classes, Graphics, Controls, Forms, Dialogs, undm, IBQuery,DB, IBDatabase,ADODB, SysUtils, unMain,ShellApi,cfutils,Windows,StdCtrls, ComCtrls, ExtCtrls,DB,IBDatabase; var q: TIBQuery; ac: TAdoConnection; AdoWork: Tadoquery; t,comments,gd,sname, path_tmp,path, INN,org_code,def_region: String; FileName : String; sl: TStringList; FT : TextFile; date1,date2:string; begin path_tmp:='C:\Standart-N\ASNA\'; //Временная папка для файлов date1:= DateToStr(Date-21); //'01.05.2016'; // date2:= DateToStr(Date); //'30.06.2016'; // INN:='1234567890'; //ИНН org_code:='Org_TEST'; //Код юр. лица АСНА def_region:='18'; q:=dm.TempQuery(nil); q.Active:=false; //1) ---------------- Структура файла «Справочник товаров» Имя файла «goods.dbf» ------------------------------------------- if 1=1 Then Begin q.SQL.text:='select id, Replace(MGN_NAME,'' : '','''') as name, PRODUCER, COUNTRY, EAN from ASNA_GOODS order by MGN_NAME'; q.Active:=true; ac:=TAdoConnection.Create(application); AdoWork:=Tadoquery.create(application); ac.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=dBASE IV;User ID=Admin;Password=;Data Source='+path_tmp; ac.LoginPrompt:=false; AdoWork.Connection:=ac; if FileExists(path_tmp+'goods.dbf') then begin deletefile(path_tmp+'goods.dbf'); end AdoWork.Active:=false; t:='CREATE TABLE goods (ID CHAR(250),NAME CHAR(250),PRODUCER CHAR(250), COUNTRY CHAR(250), EAN CHAR(250))'; // frmSpacePro.Logit(t); AdoWork.SQL.Text:=t; AdoWork.ExecSQL; while not q.Eof do begin t:='insert into goods (ID,NAME,PRODUCER,COUNTRY,EAN) values ('''+ Trim(stringreplace(q.FieldByName('ID').AsString,'''','.',1))+''','''+ stringreplace(q.FieldByName('NAME').AsString,'''','.',1)+''','''+ stringreplace(q.FieldByName('PRODUCER').AsString,'''','.',1)+''','''+ stringreplace(q.FieldByName('COUNTRY').AsString,'''','.',1)+''','''+ stringreplace(q.FieldByName('EAN').AsString,'''','.',1)+''');'; // frmSpacePro.LogIt(t); AdoWork.SQL.Text:=t; AdoWork.ExecSQL; q.Next; end; q.Transaction.Commit; q.Transaction.StartTransaction; end; // FTP.Put(path_tmp+'goods.dbf', 'goods.dbf', TRUE); //2) ---------------- Структура файла «Контрагенты» Имя файла «vendor.dbf»» ------------------------------------------- if 1=1 Then Begin q.Active:=false; q.SQL.text:='select ''1'' as id, ''Мелкооптовый покупатель'' as name, '''+INN+''' as inn from rdb$database union select ''2'' as id, ''Розничный покупатель (ККМ)'' as name, '''+INN+''' as inn from rdb$database union select ''3'' as id, ''Ввод остатков'' as name, '''+INN+''' as inn from rdb$database union select cast(a.id as varchar(255))||''_''||cast(g$profile_id as varchar(255)) as ID, caption as name, coalesce(INN,'''') as INN from agents a inner join ASNA_G$PROFILES ga on ga.id = a.g$profile_id where ga.id is not null and a.id > 0 order by 2'; // frmSpacePro.LogIt(q.SQL.text); q.Active:=true; ac:=TAdoConnection.Create(application); AdoWork:=Tadoquery.create(application); ac.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=dBASE IV;User ID=Admin;Password=;Data Source='+path_tmp; ac.LoginPrompt:=false; AdoWork.Connection:=ac; if FileExists(path_tmp+'vendor.dbf') then begin deletefile(path_tmp+'vendor.dbf'); end AdoWork.Active:=false; t:='CREATE TABLE vendor(ID CHAR(250),NAME CHAR(250),INN CHAR(250))'; // frmSpacePro.Logit(t); AdoWork.SQL.Text:=t; AdoWork.ExecSQL; while not q.Eof do begin t:='insert into vendor(ID,NAME,INN) values ('''+ stringreplace(q.FieldByName('ID').AsString,'''','.',1)+''','''+ stringreplace(q.FieldByName('NAME').AsString,'''','.',1)+''','''+ stringreplace(q.FieldByName('INN').AsString,'''','.',1)+''');'; //frmSpacePro.LogIt(t); AdoWork.SQL.Text:=t; AdoWork.ExecSQL; q.Next; end; q.Transaction.Commit; end; //3) ---------------- Структура файла «Данные о товародвижении» Имя файла «название юридического лица_название торгового объекта_дата и время формирования файла.TXT»» ------------------------------------------- if 1=1 Then begin //q.Transaction.StartTransaction; q.Active:=false; q.SQL.text:='select '''+org_code+'''||''_''||ga.asna_code||''_''||replace(cast(current_date as varchar(255)),''-'','''')||''T''||replace(left(cast(current_time as varchar(255)),5),'':'','''')||''.txt'' as filename, cast(dd.id as varchar(255))||''_''||cast(dd.g$profile_id as varchar(255)) as ID, cast(d.id as varchar(255))||''_''||cast(d.g$profile_id as varchar(255)) as DOC_ID, '''+org_code+''' as ur_l, ga.asna_code, case d.doc_type when 11 then 1 --мелкооптовый отпуск when 3 then 2 --продажа через ККМ when 1 then 3 --приход товара when 9 then 4 --возврат от покупателя when 37 then 4 --возврат от покупателя when 4 then 5 --возврат поставщику when 2 then 6 --межскладская передача when 17 then 7 --Списание when 10 then 7 --Списание when 5 then 7 --Списание when 20 then 8 --Ввод остатков end as doc_type, case d.doc_type when 11 then '''+INN+''' --мелкооптовый отпуск when 3 then '''+INN+''' --продажа через ККМ when 1 then coalesce(a.inn,'''') --приход товара when 2 then (select asna_code from ASNA_G$PROFILES where id = ga_ag.g$profile_id_apt) --межскладская передача when 17 then ga.asna_code --Списание when 10 then ga.asna_code --Списание when 5 then ga.asna_code --Списание when 20 then ga.asna_code --Ввод остатков else '''' end as sagent, left(cast(d.commitdate as varchar(255)),19) as doc_date, case d.doc_type when 3 then d.docnum||''Ч''||(select max(docnum) from docs d2 where d2.g$profile_id = d.g$profile_id and d2.status = 1 and d2.doc_type=13 and d2.vshift = d.vshift and d2.device_num = d.device_num) else d.docnum end as docnum, dcard, (select GOODS_ID from PR_ASNA_GET_GOODS(p.ware_id)) as GOODS_ID, abs(dd.quant) as quant, (select inn from agents where id = (select AGENT_ID from PR_GETMOTHERPART(dd.part_id, dd.g$profile_id) ) and g$profile_id = dd.g$profile_id) as inn, abs(Round((dd.quant*p.price_o*100/(100+dp.nds)),2)) as sum_b_nds, abs(dd.summa_o) as summa_o, abs(Round((dd.summa_o-dd.quant*p.price_o*100/(100+dp.nds)),2)) as sum_nds, abs(dd.summa+dd.sum_dsc) as summa_b_dsc, abs(dd.summa) as summa, abs(dd.sum_dsc) as sum_dsc, d.status, coalesce((select region from ASNA_AGENT_REGION where inn = a.inn),'+def_region+') as region from doc_detail dd inner join docs d on dd.doc_id = d.id and dd.g$profile_id = d.g$profile_id inner join ASNA_G$PROFILES ga on ga.id = d.g$profile_id inner join agents a on a.id=d.agent_id and a.g$profile_id = d.g$profile_id inner join parts p on p.g$profile_id = dd.g$profile_id and dd.part_id = p.id inner join deps dp on p.g$profile_id = dp.g$profile_id and p.dep = dp.id left join asna_agents_g$profiles ga_ag on ga_ag.agent_id = a.id and ga_ag.g$profile_id = a.g$profile_id where ga.id is not null and d.status = 1 and d.doc_type in (11,2,3,1,37,9,4,17,10,5,20) and dd.doc_commitdate between '''+date1+''' and '''+date2+''' and (select GOODS_ID from PR_ASNA_GET_GOODS(p.ware_id)) is not null order by 1 '; q.Active:=true; filename:=''; while not q.Eof do begin If filename='' Then begin filename:= path_tmp+q.FieldByName('filename').AsString; AssignFile(FT, FileName); if FileExists(FileName) then Append(FT) else Rewrite(FT); end; if filename = path_tmp+q.FieldByName('filename').AsString Then begin t:='"'+q.FieldByName('ID').AsString+'"|"'+q.FieldByName('DOC_ID').AsString+'"|"'+q.FieldByName('ur_l').AsString+'"|"'+q.FieldByName('asna_code').AsString+'"|'+ q.FieldByName('DOC_TYPE').AsString+'|"'+q.FieldByName('SAGENT').AsString+'"|'+q.FieldByName('DOC_DATE').AsString+'|"'+q.FieldByName('DOCNUM').AsString+'"|1|"'+ q.FieldByName('DCARD').AsString+'"|"1"|"'+q.FieldByName('DCARD').AsString+'"|"'+q.FieldByName('DCARD').AsString+'"|"'+Trim(q.FieldByName('GOODS_ID').AsString)+'"|'+ stringreplace(q.FieldByName('QUANT').AsString,',','.',1)+'|"'+q.FieldByName('INN').AsString+'"|'+q.FieldByName('region').AsString+'|'+stringreplace(q.FieldByName('sum_b_nds').AsString,',','.',1)+'|'+ stringreplace(q.FieldByName('summa_o').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('sum_nds').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('summa').AsString,',','.',1)+'|'+ stringreplace(q.FieldByName('summa_b_dsc').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('sum_dsc').AsString,',','.',1)+'|'+q.FieldByName('status').AsString; // frmSpacePro.LogIt(t); WriteLn(FT, t); end else Begin CloseFile(FT); filename:= path_tmp+q.FieldByName('filename').AsString; AssignFile(FT, FileName); if FileExists(FileName) then Append(FT) else Rewrite(FT); end; q.Next; end; CloseFile(FT); q.Transaction.Commit; end; //4) ---------------- Структура файла «Данные об остатках» Имя файла «название юридического лица_название торгового объекта_дата и время формирования файла_суфиксRST.TXT»» ------------------------------------------- //Предподготовка к выгрузке остатков - расчет остатков на конец периода q.Transaction.StartTransaction; q.Active:=false; q.SQL.Text:='delete from ASNA_WAREBASE'; q.ExecSQL; q.Transaction.Commit; q.Transaction.StartTransaction; q.Active:=false; q.SQL.Text:='insert into ASNA_WAREBASE(part_id, G$PROFILE_ID,ddate) select id, G$PROFILE_ID, '''+date2+''' from parts p'; q.ExecSQL; q.Transaction.Commit; q.Transaction.StartTransaction; q.Active:=false; q.SQL.Text:='select '''+org_code+'''||''_''||ga.asna_code||''_''||replace(cast(current_date as varchar(255)),''-'','''')||''T''||replace(left(cast(current_time as varchar(255)),5),'':'','''')||''_RST.txt'' as filename, '''+org_code+''' as ur_l, ga.asna_code, a.inn, left(cast(cast(dateadd(1 day to w.ddate) as dm_datetime) as varchar(255)),19) as beg_date, left(cast(d.commitdate as varchar(255)),19) as post_date, (select GOODS_ID from PR_ASNA_GET_GOODS(w.ware_id)) as GOODS_ID, w.quant, coalesce(abs(Round((w.quant*w.price_o*100/(100+w.nds)),2)),0) as sum_b_nds, coalesce(abs(Round(w.quant*w.price_o,2)),0) as summa_o, coalesce(abs(Round((w.quant*w.price_o-w.quant*w.price_o*100/(100+w.nds)),2)),0) as sum_nds, coalesce(abs(round(w.quant*w.price,2)),0) as summa, coalesce((select region from ASNA_AGENT_REGION where inn = a.inn),'+def_region+') as region from ASNA_WAREBASE w inner join docs d on w.doc_id = d.id and w.g$profile_id = d.g$profile_id inner join ASNA_G$PROFILES ga on ga.id = w.g$profile_id inner join agents a on a.id=d.agent_id and a.g$profile_id = d.g$profile_id where ga.id is not null and w.quant > 0.01 and (select GOODS_ID from PR_ASNA_GET_GOODS(w.ware_id)) is not null order by 1' q.Active:=true; filename:=''; while not q.Eof do begin If filename='' Then begin filename:= path_tmp+q.FieldByName('filename').AsString; AssignFile(FT, FileName); if FileExists(FileName) then Append(FT) else Rewrite(FT); end; if filename = path_tmp+q.FieldByName('filename').AsString Then begin t:='"'+q.FieldByName('ur_l').AsString+'"|"'+q.FieldByName('asna_code').AsString+'"|"'+q.FieldByName('INN').AsString+'"|'+q.FieldByName('region').AsString+'|'+ q.FieldByName('beg_date').AsString+'|'+q.FieldByName('post_date').AsString+'|"'+Trim(q.FieldByName('GOODS_ID').AsString)+'"|'+ stringreplace(q.FieldByName('QUANT').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('sum_b_nds').AsString,',','.',1)+'|'+ stringreplace(q.FieldByName('summa_o').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('sum_nds').AsString,',','.',1)+'|'+stringreplace(q.FieldByName('summa').AsString,',','.',1); WriteLn(FT, t); end else Begin CloseFile(FT); filename:= path_tmp+q.FieldByName('filename').AsString; AssignFile(FT, FileName); if FileExists(FileName) then Append(FT) else Rewrite(FT); end; q.Next; end; CloseFile(FT); q.Transaction.Commit; end;
Выгрузка на FTP
Для выгрузки используется программа Файл:Ncftpput.zip, 7-Zip для архивирования и bat файл (uploadftp.bat), содержимое последнего ниже: @Echo Off C:\Standart-N\asna_ftp\ncftpput.exe -F -u Org_TEST -p password123 ftp.fttech.ru \ C:\Standart-N\ASNA\*.dbf C:\Standart-N\asna_ftp\ncftpput.exe -F -u Org_TEST -p password123 ftp.fttech.ru \ C:\Standart-N\ASNA\*.txt ping -n 600 127.0.0.1 > NUL MD C:\Standart-N\ASNA\%date:~-10% move /y C:\Standart-N\ASNA\*.txt C:\Standart-N\ASNA\%date:~-10% move /y C:\Standart-N\ASNA\*.dbf C:\Standart-N\ASNA\%date:~-10% "C:\Program Files\7-Zip\7z.exe" a -tzip -ssw -mx7 -r0 C:\Standart-N\ASNA\%date:~-10%.zip C:\Standart-N\ASNA\%date:~-10% RD /S /Q C:\Standart-N\ASNA\%date:~-10%
FAQ (ЧаВо)
1) Необходимо по какой-то причине выгрузить данные за определенный период: - открываем в своднике ТМС по выгрузке АСНА; - правим в начале даты начала и конца периода, запускаем на выполнение; - после выгрузки, копируем созданные файлы (путь к временной папке прописан тут же в коде ТМС) на ftp; - возвращаем код ТМС (даты) в прежнее положение.
2) Вопрос клиента: "Для Асны в выгрузке не вижу Цетиризин-Тева 10мг №10, Бинт Пеха хафт 4х6". Наши действия: - проверить в выгружаемой базе таблицу wares поле mgn_name по указанным препаратам, скорее всего неправильно сработало приведение; - исправить на правильное значение; - выгрузить данные заново за требуемый период.