-- Шаблон создан мастером бланков
-- 10.10.2012 11:43:34
--
БланкСШаблоном "Доступ к ТБ из других программ";

--Служебные функции для удобства
FToGet[]:S;
FToGet2[]:S;

Func GetField(wa:I;typ:I;Field:S):S;
--Возвращает выражение присвоения для Питона

--mtlSUBTAB – поля подтаблицы
--mtlREF – ссылочные поля
--mtlTimed – периодические поля
  if typ=mtlSTRING:
    ^"'"+getFieldS(wa,1,Field)+"'";
    |typ=mtlInteger:
    ^STR(GetFieldI(wa,1,Field),0);
    |typ=mtlREAL:
    ^GetFieldS(wa,1,Field);--!!!!!
    |typ=mtlBOOLEAN:
    ^if(GetFieldL(wa,1,Field),"True","False");
    |typ=mtlDATE:
    ^Раб.Python.DateCast(GetFieldD(wa,1,Field));
  fi;

end;

proc GetRecord(cb:S);
var Card,key:S;
var OWA,n,nn,typ:I;
  ClearVariable(FToGet);
  --Раб.Python.Exec("from datetime import date");
  Раб.Python.Import("copy");
  РАБ.Python.Exec("gr_res={}");
--Первый параметр - имя картотеки;
  Card=РАБ.Python.Eval(cb+".f_args[0]");
  --Второй параметр - ключ целым числом
  key="{"+РАБ.Python.Eval(cb+".f_args[1]")+"}";
  nn=GetCardFileFields(Card,FToGet,mtlAll);
  OWA=OpenWorkArea(Card,"","Ukey="+key);
  try
    if Records(OWA) = 0:
       РАБ.Python.Exec(cb+".f_res = None");
    else
       for n=1..nn do
         typ=GetCardFileFieldType(Card,FToGet[n]);
         РАБ.Python.Exec("gr_res['"+FToGet[n]+"']="+GetField(OWA,typ,FToGet[n]));
       od;
    fi;
  finally
    CloseWorkArea(OWA);
  end;
end;

proc GetRecordIds(cb:S);
var Card,fld:S;
var OWA,n,nn:I;
  --Первый параметр - имя картотеки;
  Card=РАБ.Python.Eval(cb+".f_args[0]");
  --Второй параметр - фильтр
  OWA=OpenWorkArea(Card,"",РАБ.Python.Eval(cb + ".f_args[1]"));
  try
    nn = Records(OWA);
    РАБ.Python.Exec(cb+".f_res = []");
    for n = 1 .. nn do
        РАБ.Python.Exec(cb+".f_res.append(" + Str(RecordToInteger(GetRecordKey(OWA,n)),0) + ")");
    od;
  finally
    CloseWorkArea(OWA);
  end;
end;

proc GetRecordField(cb:S);
var Card,fld:S;
var OWA,typ:I;
  --Первый параметр - имя картотеки;
  Card=РАБ.Python.Eval(cb+".f_args[0]");
  --Второй параметр - ключ целым числом
  OWA=OpenWorkArea(Card,"","Ukey={" + РАБ.Python.Eval(cb + ".f_args[1]") + "}");
  try
    if Records(OWA) = 0:
       РАБ.Python.Exec(cb+".f_res = None");
    else
       --Третий параметр- Имя
       fld=РАБ.Python.Eval(cb+".f_args[2]");
       typ=GetCardFileFieldType(Card,fld);
       РАБ.Python.Exec(cb+".f_res = " + GetField(OWA,typ,fld));
     fi;
  finally
    CloseWorkArea(OWA);
  end;
end;

proc SetRecordField(cb:S);
var Card,fld:S;
var OWA,typ,n:I;
  --Первый параметр - имя картотеки;
  Card=РАБ.Python.Eval(cb+".f_args[0]");
  --Второй параметр - ключ целым числом
  OWA=OpenWorkArea(Card,"","Ukey={" + РАБ.Python.Eval(cb + ".f_args[1]") + "}");
  try
    if Records(OWA) > 0:
       --Третий параметр- Имя
       fld=РАБ.Python.Eval(cb+".f_args[2]");
       typ=GetCardFileFieldType(Card,fld);
       try
         BeginChanging(OWA);
         --Четвертый - значение
         if typ=mtlSTRING:
           n=PutFieldS(OWA,1,fld,РАБ.Python.Eval(cb+".f_args[3]"));
           |typ=mtlInteger:
           n=PutFieldI(OWA,1,fld,РАБ.Python.EvalI(cb+".f_args[3]"));
           |typ=mtlREAL:
           n=PutFieldN(OWA,1,fld,РАБ.Python.EvalN(cb+".f_args[3]"));
           |typ=mtlBOOLEAN:
           n=PutFieldL(OWA,1,fld,РАБ.Python.EvalL(cb+".f_args[3]"));
           |typ=mtlDATE:
           n=PutFieldD(OWA,1,fld,РАБ.Python.EvalD(cb+".f_args[3]"));
         fi;
         РАБ.Python.Exec(cb+".f_res = " + GetField(OWA,typ,fld));
         EndChanging(OWA);
       except
         CancelChanging(OWA);
         raise;
       end;
     fi;
  finally
    CloseWorkArea(OWA);
  end;
  --РАБ.Python.Exec(cb+".f_res = True");

end;

proc SetRecordFields_(Card:S;OWA:I;n:I;pairsmas:S);
var fld, typ_:S;
var typ,i,ii:I;
   --Третий параметр- массив пар поле/значение (имя питоновского объекта)
   ii = РАБ.Python.EvalI("len("+pairsmas+")");
   for i = 0 .. ii-1 do
     fld = РАБ.Python.Eval(pairsmas+"["+Str(i)+"][0]");
     typ = GetCardFileFieldType(Card,fld);
     if typ=mtlSTRING or РАБ.Python.EvalL("isinstance("+pairsmas+"["+Str(i)+"][1], basestring)"):
       n=PutFieldS(OWA,n,fld,РАБ.Python.Eval(pairsmas+"["+Str(i)+"][1]"));
       |typ=mtlInteger:
       n=PutFieldI(OWA,n,fld,РАБ.Python.EvalI(pairsmas+"["+Str(i)+"][1]"));
       |typ=mtlREF:
       n=PutFieldR(OWA,n,fld,IntegerToRecord(РАБ.Python.EvalI(pairsmas+"["+Str(i)+"][1]")));
       |typ=mtlREAL:
       n=PutFieldN(OWA,n,fld,РАБ.Python.EvalN(pairsmas+"["+Str(i)+"][1]"));
       |typ=mtlBOOLEAN:
       n=PutFieldL(OWA,n,fld,РАБ.Python.EvalL(pairsmas+"["+Str(i)+"][1]"));
       |typ=mtlDATE:
       n=PutFieldD(OWA,n,fld,РАБ.Python.EvalD(pairsmas+"["+Str(i)+"][1]"));
     fi;
   od;
END;

proc SetRecordFields(cb:S);
var Card,fld:S;
var OWA,typ,n,i,ii:I;
  --Первый параметр - имя картотеки;
  Card=РАБ.Python.Eval(cb+".f_args[0]");
  --Второй параметр - ключ целым числом
  OWA=OpenWorkArea(Card,"","Ukey={" + РАБ.Python.Eval(cb + ".f_args[1]") + "}");
  try
    if Records(OWA) > 0:
       --Третий параметр- словарь поле/значение
       РАБ.Python.Exec("pairs = "+cb+".f_args[2].items()");
       try
         BeginChanging(OWA);
           SetRecordFields_(Card,OWA,1,"pairs");
         EndChanging(OWA);
         РАБ.Python.Exec(cb+".f_res = True");
       except
         CancelChanging(OWA);
         raise;
       end;
     fi;
  finally
    CloseWorkArea(OWA);
  end;
  --РАБ.Python.Exec(cb+".f_res = None");
end;

proc InsertRec(cb:S);
var Card,fld:S;
var OWA,n,typ:I;
  --Первый параметр - имя картотеки;
  Card=РАБ.Python.Eval(cb+".f_args[0]");
  OWA=OpenWorkArea(Card,"","1=0");
  try
    BeginChanging(OWA);
    try
      n = InsertRecord(OWA);
      if РАБ.Python.EvalI("len("+cb+".f_args)")=2:
         --Второй (опциональный) параметр - словарь поле/значение
         РАБ.Python.Exec("pairs = "+cb+".f_args[1].items()");
         SetRecordFields_(Card,OWA,n,"pairs");
      fi;
      РАБ.Python.Exec(cb+".f_res = " + Str(RecordToInteger(GetRecordKey(OWA,n)),0));
      EndChanging(OWA);
    except
      CancelChanging(OWA);
        РАБ.Python.Exec(cb+".f_res = None");
      raise;
    end;
  finally
    CloseWorkArea(OWA);
  end;
end;

proc InsertRecords(cb:S);
var Card,fld:S;
var OWA,n,typ,i,ii:I;
  --Первый параметр - имя картотеки;
  Card=РАБ.Python.Eval(cb+".f_args[0]");
  OWA=OpenWorkArea(Card,"","1=0");
  try
    BeginChanging(OWA);
    try
      ii =РАБ.Python.EvalI("len("+cb+".f_args[1])");
      РАБ.Python.Exec(cb+".f_res = []");
      for i = 0 .. ii-1 do
        --Второй параметр - массив словарей поле/значение
        РАБ.Python.Exec("pairs = "+cb+".f_args[1]["+Str(i)+"].items()");
        n = InsertRecord(OWA);
        SetRecordFields_(Card,OWA,n,"pairs");
        РАБ.Python.Exec(cb+".f_res.append(" + Str(RecordToInteger(GetRecordKey(OWA,n)))+")");
      od;
      EndChanging(OWA);
    except
      CancelChanging(OWA);
        РАБ.Python.Exec(cb+".f_res = None");
      raise;
    end;
  finally
    CloseWorkArea(OWA);
  end;
end;

proc SignList(cb:S);
var cond,el:S;
  РАБ.Python.Exec("res=[]");
  RefreshAna;
  cond = РАБ.Python.Eval(cb+".f_args[0]");
  for Sign el = cond do
      РАБ.Python.Exec("res.append(r'"+el+"')");
  od;
  РАБ.Python.Exec(cb+".f_res=res");
end;

proc AccList(cb:S);
var cond,el:S;
  РАБ.Python.Exec("res=[]");
  cond = РАБ.Python.Eval(cb+".f_args[0]");
  for Account el = cond do
      РАБ.Python.Exec("res.extend(r'"+el+"')");
  od;
  РАБ.Python.Exec(cb+".f_res=res");
end;

proc TransList(cb:S);
var cond,xsum:S;
var ДН, ДК:Date;
var n:I;
  РАБ.Python.Exec("res=[]");
  cond = РАБ.Python.Eval(cb+".f_args[0]");
  ДН = РАБ.Python.EvalD(cb+".f_args[1]");
  ДК = РАБ.Python.EvalD(cb+".f_args[2]");
  xsum = РАБ.Python.Eval(cb+".f_args[3]");
  for Transaction n = cond, ДН, ДК do
      --Trace(Str(n));
      РАБ.Python.Exec("el={}");
      РАБ.Python.Exec("el['sum']='"+Str(TransSum(n),2)+"'");
      if xsum<>"":
         РАБ.Python.Exec("el['xsum']='"+Str(TransSum(n,xsum),4)+"'");
      fi;
      РАБ.Python.Exec("el['deb']='"+TransDeb(n)+"'");
      РАБ.Python.Exec("el['cre']='"+TransCre(n)+"'");
      РАБ.Python.Exec("el['ana']='"+TransSigns(n)+"'");

      РАБ.Python.Exec("res.append(el)");
  od;
  РАБ.Python.Exec(cb+".f_res=res");
end;


Func Execute(cb:S):L;
--Обрабатывает 1 запрос из каллбэка.
--Возвращает истину, если следует ожидать последующих запросов
--(и ложь, если был вызван Break)
var fname,tmpS:S;
var tmpR:Record;
  --Сбросить флаг готовности к выполнению - обозначает, что мы взялись за задачу.
  --Флаг будет снова взведен, когда нам выдадут следующую.
  РАБ.Python.Exec(cb+".exec_me.clear()");
  fname=РАБ.Python.Eval(cb+".f_name");
  if fname="Break":
    РАБ.Python.Exec(cb+".f_res=None");
    --Блокировку второго потока все равно надо снять.
    РАБ.Python.Exec(cb+".executed.set()");
    return False;
  |fname="GetRecord": --Предварительные наброски, не тестировалось!
    GetRecord(cb);
  |fname="SignList":
    SignList(cb);
  |fname="TransList":
    TransList(cb);
  |fname="InsertRec":
    InsertRec(cb);
  |fname="InsertRecords":
    InsertRecords(cb);
  |fname="GetRecordIds":
    GetRecordIds(cb);
  |fname="GetRecordField":
    GetRecordField(cb);
  |fname="SetRecordField":
    SetRecordField(cb);
  |fname="SetRecordFields":
    SetRecordFields(cb);
  |fname="AccList":
    AccList(cb);
  |fname="SignToRecord":
    tmpR = SignToRecord(РАБ.Python.Eval(cb+".f_args[0]"));
    if tmpR = nil:
       РАБ.Python.Exec(cb+".f_res=None");
      else
       РАБ.Python.Exec(cb+".f_res="+Str(RecordToInteger(tmpR)));
    fi;
  |fname="Name_A":
    РАБ.Python.Exec(cb+".f_res=r'"+Substr(Name_A( РАБ.Python.Eval(cb+".f_args[0]")),1,220) +"'");
  |fname="Trace":
    Trace(РАБ.Python.Eval(cb+".f_args[0]"));
  |fname="RefreshAna":
    RefreshAna;
  |fname="Accuracy":
   if РАБ.Python.Eval(cb+".f_args[0]")="None":
      РАБ.Python.Exec(cb+".f_res="+Str(Accuracy));
     else
      РАБ.Python.Exec(cb+".f_res="+Str(Accuracy(РАБ.Python.Eval(cb+".f_args[0]"))));
   fi;
  |РАБ.Python.Eval(cb+".f_func")="None":
    ExecuteProc(fname,РАБ.Python.Eval(cb+".f_args[0]"));
    РАБ.Python.Exec(cb+".f_res=None");
  |РАБ.Python.Eval(cb+".f_func")="str" and РАБ.Python.EvalI("len("+cb+".f_args)")=1:
    if РАБ.Python.EvalL("type("+cb+".f_args[0]) in [str, unicode]"):
       tmpS=ExecuteFuncS(fname,РАБ.Python.Eval(cb+".f_args[0]"));
      |РАБ.Python.EvalL("type("+cb+".f_args[0]) in [int, long]"):
       tmpS=ExecuteFuncS(fname,РАБ.Python.EvalI(cb+".f_args[0]"));
      |РАБ.Python.EvalL("type("+cb+".f_args[0]) in [float, ]"):
       tmpS=ExecuteFuncS(fname,РАБ.Python.EvalN(cb+".f_args[0]"));
      |РАБ.Python.EvalL("type("+cb+".f_args[0]) in [date, ]"):
       tmpS=ExecuteFuncS(fname,РАБ.Python.EvalD(cb+".f_args[0]"));
      |РАБ.Python.EvalL("str("+cb+".f_args[0])=False"):
       tmpS=ExecuteFuncS(fname,False);
      |РАБ.Python.EvalL("str("+cb+".f_args[0])=True"):
       tmpS=ExecuteFuncS(fname,True);
    fi;
    РАБ.Python.Exec(cb+".f_res='"+tmpS+"'");
  |РАБ.Python.Eval(cb+".f_func")="str" and РАБ.Python.EvalI("len("+cb+".f_args)")=3:
    if РАБ.Python.EvalL("type("+cb+".f_args[0]) in [str, unicode]") and
       РАБ.Python.EvalL("type("+cb+".f_args[1]) in [int, long]") and
       РАБ.Python.EvalL("type("+cb+".f_args[2]) in [str, unicode]"):
       tmpS=ExecuteFuncS(fname,РАБ.Python.Eval(cb+".f_args[0]"),
                               РАБ.Python.EvalI(cb+".f_args[1]"),
                               РАБ.Python.Eval(cb+".f_args[2]"));
    fi;
    РАБ.Python.Exec(cb+".f_res='"+tmpS+"'");
  |РАБ.Python.Eval(cb+".f_func")="str" and РАБ.Python.EvalI("len("+cb+".f_args)")=4:
--    Func ВзятьКодСчета (Source:S; Mode:S; Value:S; Flag:L):S;
    if РАБ.Python.EvalL("type("+cb+".f_args[0]) in [str, unicode]") and
       РАБ.Python.EvalL("type("+cb+".f_args[1]) in [str, unicode]") and
       РАБ.Python.EvalL("type("+cb+".f_args[2]) in [str, unicode]") and
       РАБ.Python.EvalL(cb+".f_args[3]==False or "+cb+".f_args[3]==True"):
       tmpS=ExecuteFuncS(fname,РАБ.Python.Eval(cb+".f_args[0]"),
                               РАБ.Python.Eval(cb+".f_args[1]"),
                               РАБ.Python.Eval(cb+".f_args[2]"),
                               РАБ.Python.EvalL(cb+".f_args[3]"));
    fi;
    РАБ.Python.Exec(cb+".f_res='"+tmpS+"'");
  fi;
  --Выставляем флаг готовности результата.
  --После выставления флага запустится параллельный поток, который считает и использует результат.
  РАБ.Python.Exec(cb+".executed.set()");
  ^True;
end;


Proc Loop(cb:S);
--Функуия прерывается только из Python!
--Действовать аккуратно!
  while True do
    РАБ.Python.Exec(cb+".exec_me.wait()");
    if not Execute(cb):
       Break;
    fi;
  od;
end;

--"Мягкая" обработка запросов.
var cbvar:S;
Timer1:Object;

Proc OnTimer(Sender: String);
 if РАБ.Python.EvalL(cbvar+".exec_me.is_set()"):
    if not Execute(cbvar):
       Timer1.Active=False;
       Раб.Python.UnLoad;
    fi;
 fi;
end;

var Served:S = if(AsLogical(timer1.Active),'СЕРВЕР ЗАПУЩЕН','');
var Stopped:S = if(AsLogical(timer1.Active),'','СЕРВЕР ОСТАНОВЛЕН');


Proc Button1_OnClick(Sender: String);
 Раб.Python.LoadAndImport("tb_callback,SimpleXMLRPCServer,thread",True);
 try
   Раб.Python.Exec("mycb=tb_callback.callback()");
   Раб.Python.Exec("server = SimpleXMLRPCServer.SimpleXMLRPCServer(('localhost', 9766), allow_none=True, encoding='cp1251')");
--   Раб.Python.Exec("server.register_introspection_functions()");
   Раб.Python.Exec("server.register_instance(mycb)");
   Раб.Python.Exec("thread.start_new_thread(SimpleXMLRPCServer.SimpleXMLRPCServer.serve_forever,(server,0.0001))");
   --Loop("mycb");
   --Раб.Python.UnLoad;
   cbvar = 'mycb';
   timer1.Active = True;

 --finally
 except
   Раб.Python.UnLoad;
   Message("Ошибка при работе с Python");
 end;
end;


Proc StopSrv_OnClick(Sender: String);
    Timer1.Active=False;
    Раб.Python.UnLoad;
    cbvar = '';
end;


Конец
