import "layer92.dll"

unsigned int NumOfOrder=0; /* переменная для отслежеивания порядкового номера     */
                         /* печатаемой записи при печати в формате пользователя */
double Itog=0;
int LenStrItog=0;

User_Print_Title_Script( HandleOutputFile )
/**************************************************************
** Функция печатает заголовок в файл.
** Используется при передачи кассовых ведомостей и ордеров
** в файл в формате пользователя.
***************************************************************
*/
{
  // return Sys_Print_Title_Script( HandleOutputFile );

  // ВНИМАНИЕ !!! Файл открыт для записи в двоичном режиме
// { для УБРиР  12.05.00
  char Title[81]; char CurData[11];
  var EndTable="АДДДДДБДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДБДДДДДДДДДДЩ\r\n";
  int LenStrTable=strlen(EndTable);

  strcpy(CurData,datatek);
  CurData[6] = CurData[8]; // эти манипуляции необходимы
  CurData[7] = CurData[9]; // чтобы привести дату из формата
  CurData[8] = '\0';       // ДД.ММ.ГГГГ в формат ДД.ММ.ГГ
  sprintf(Title,"%.8s 98 2 3 4 75000 \r\n",CurData);
  write(HandleOutputFile, Title, strlen(Title));

  write(HandleOutputFile,
       "ЪДДДДДВДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДВДДДДДДДДДДї\r\n", LenStrTable);
/*
  write(HandleOutputFile,
       "і  N  і Ќ®¬Ґа Є ав®зЄЁ    і ‘г¬¬  ®ЇҐа жЁЁ  і  ‘зҐв    і\r\n", LenStrTable);
  write(HandleOutputFile,
       "ГДДДДДЕДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДЕДДДДДДДДДДґ\r\n", LenStrTable);
*/
  write(HandleOutputFile, EndTable, LenStrTable);
  NumOfOrder=0;
// } для УБРиР  12.05.00
  return;
}

User_Transfer_One_Script( &pDoc, HandleOutputFile, Num, Flag, Otbor )
/*-------------------------------------------------------------------*/
/* Pазноска одной стpоки из списка оpдеpов или ведомости.            */
/* pDoc - указатель на объект (ордер или ведомость)                  */
/* HandleOutputFile - файл в который пишем                           */
/* Num -  номеp стpоки в списке оpдеpов или в ведомости.             */
/* Flag - 'O' pазноска оpдеpа.                                       */
/* Flag - 'I' pазноска ведомости.                                    */
/* Otbor - 0  передача только непереданных ЛС                        */
/* Otbor - 1  передача всех ЛС (независимо от того, передавался он   */
/*            раньше или нет)                                        */
/* Функция используется при передачи кассовых ведомостей и ордеров   */
/* в файл в формате пользователя.                                    */
/*-------------------------------------------------------------------*/
{
  // return Sys_Transfer_One_Script( pDoc, HandleOutputFile, Num, Flag, Otbor );

  var Ved =  CreateObject("Doc");
  Ved.Initial(static_cast_to_string(pDoc));

  int N_Fld_Transf=Ved.GetNumFld("TRANSFER"); // Номер поля с именем TRANSFER в которое заносится
                                              // признак передачи в файл (в АРМ).

   // Проверка: "оpдеp или стpока ведомости pазнесены в АРМ"
   // Если поле TRANSFER отсутствует в ордере или ведомости то разноска
   // все равно будет происходить, только не будет проставлятся признак
   // разноски.
   // Если не надо передавать уже переданные ЛС и есть отметка, что
   // текущий ЛС передан, то его мы передавать не будем
   if ( Ved.Char_From_Field( N_Fld_Transf,Num )=='Џ' && !Otbor )
      return;

// { 12.05.00 для УБРиР
   var EndTable="АДДДДДБДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДБДДДДДДДДДДЩ\r\n";
   long tn=sizetn*atol(Ved.TextS(Ved.Get_N_POD(), Num))
                 +atol(Ved.TextS(Ved.Get_N_TAB(), Num));

   int c = LSRead(tn, 2);
   if ( c != 1) return;

    // Записываем номер карточки
    char NumCard[17];       /* Номер карточки                                 */
    kch_from("kart",NumCard);
// } 12.05.00 для УБРиР

   // Записываем ТН
                           /* Табельный номер                                */
   long Tab_Num = atol( static_cast_to_string(Ved.TextS(Ved.Get_N_TAB(), Num)) );
   char Fio[40],           /* ФИО                                            */
        Name_Podr[81],     /* Название подразделения                         */
        Data_Transf[11],   /* Дата передачи                                  */
        Month[3], Year[5]; /* Месяц и год, за которые сумма                  */
   double Summa=0.;        /* Сумма, которая разносится                      */


    // Записываем название подразделения
    long Dep = atol( static_cast_to_string(Ved.TextS(Ved.Get_N_POD(), Num)) );
    sprintf(Name_Podr,"%.80s",GetOtdName(Dep));

    // Записываем текущую дату
    sprintf(Data_Transf,"%.10s",datatek);

    // Записываем месяц и год за которые передана сумма
    sprintf(Month,"%d",Month_Cash);
    sprintf(Year, "%d",Year_Cash);

    // Записываем сумму
    Summa = atof( static_cast_to_string(Ved.TextS(Ved.Get_N_SUM(), Num)) );

    // Печать в файл сформированной записи
    // ВНИМАНИЕ !!! Файл открыт для записи в двоичном режиме

// { для УБРиР  12.05.00
   char str[255];
   int LenStrTable=strlen(EndTable);

   if ( !NumOfOrder ) Itog=LenStrItog=0;

   Itog+=Summa;
   // подготовимся к печати первой строки
   sprintf( str, "і %3d і  %16.16s і %15.2f і          і\r\n", ++NumOfOrder, NumCard, Summa);
   lseek(HandleOutputFile, -(LenStrTable+LenStrItog), SEEK_CUR);
   write(HandleOutputFile, str, LenStrTable);
   write(HandleOutputFile, EndTable, LenStrTable);
   sprintf( str, "  €’ЋѓЋ: %34.2f\r\n", Itog);
   LenStrItog = strlen(str);
   write(HandleOutputFile, str, LenStrItog);
// } для УБРиР  12.05.00

    // Заполнение столбца разноски
    if ( N_Fld_Transf != -1 )
       Ved.SetText( N_Fld_Transf, Num, "Џ");
   return;
}

User_Before_Summa_W( &Doc , Kind_Form)
{
   // Функция вызываемая перед приемом ЛС в кассовую ведомость
   // если вернуть 0 - текущий лс по текущему фильтру не будет приниматься (не будет вызвана Summa_W_Script)
   // вернуть 1 для приема суммы
   // Doc - объект класса Doc 

   return 1;
}

User_Summa_W_Script( &pDoc, Kind_Form )
/********************************************************************/
/* Вычисление суммы в ведомость или оpдеp                           */
/* Kind_Form - тип ведомости/оpдеpа ( Аванс, Заpплата и т.д. )      */
/********************************************************************/
{
   return Sys_Summa_W_Script( pDoc, Kind_Form );
}

User_Forma_W_Script( &pDoc, Kind_Form, Code, Col )
//////////////////////////////////////////////////////////////////////
// Вспомогательная функция для панели Panel_Cash
//////////////////////////////////////////////////////////////////////
{
   return Sys_Forma_W_Script( pDoc, Kind_Form, Code, Col );
}

User_Prepar_User_Append_To_Text_Script(HandleOutputFile)
/*************************************************************************
** Функция производит подготовку открытого текстового файла к добавлению
** так, как это требуется пользователю при печати кассовых документов
** в формате пользователя.
** ( Внимание !!! Файл открыт в двоичном виде, т.е. с флагом O_BINARY )
**************************************************************************/
{
  // return Sys_Prepar_User_Append_To_Text_Script(HandleOutputFile);
  // 12.05.00 для УБРиР
  char buffer[4];
  /*********************************************************************
  ** В связи с тем что нужен для печати номер по-порядку, необходимо
  ** определить каким был номер последней напечатанной записи
  **********************************************************************
   */
  char str[81];
  long LengthFile=lseek(HandleOutputFile,0,SEEK_END);
  long CountStr=0;
  // Отойдем назад на две строки (количество строк на которое отходим
  // назад зависит от формы печати!!!), для того чтобы встать на последнюю
  // запись в таблице
  NumOfOrder=0;
  for ( long OffsetFile=4; OffsetFile<=LengthFile; )
  {
    lseek(HandleOutputFile,-OffsetFile++,SEEK_END);
    read(HandleOutputFile, buffer, 2);
    if ( buffer[0]=='\r' && buffer[1]=='\n' && ++CountStr==3 )
    {
      read(HandleOutputFile,str,1);
      read(HandleOutputFile,str,9);
      NumOfOrder = atoi(str);
      break;
    }
    if ( buffer[0]=='\r' && buffer[1]=='\n' && CountStr==1 )
    {
      read(HandleOutputFile,str,20);
      read(HandleOutputFile,str,60);
      Itog = atof(str);
      LenStrItog = OffsetFile-3;
    }
  }
  lseek(HandleOutputFile,0,SEEK_END);
  return;
}

/*
// функция для корректировки названия кассовой ведомости (только ведомости)
// если для разных ЛС или разных источников в одном ЛС функция вернет разные названия, то будут созданы разные кассовые ведомости. 
// Функция вызывается на каждый балансный источник/объект/подразделение/совм-во  по которым делается выборка в ведомость.
// name - имя ведомости в WIN кодировке, заданное пользователем в кассовой панели (например "по набору видов");
// propSum - AProp строки в ведомости;
// propVed - AProp ведомости, будет заполнен если делают с разбивкой "Ведомости по источникам", или = CLL_TOTAL... если "В одну ведомость";
// dop - если содержит флаг 8 (dop & 8) - значит в propVed.GetPodr() указан код организации и ведомости создаются с разбивкой по организациям
// функция должна вернуть name и может его модифицировать (например добавить название банка для загруженного ЛС)
// Обрабатывемый ЛС в этот момент загружен в память и доступен для извлечения необходимых данных из него.
// Табельный номер этого ЛС можно получить из поля кадровой части kch_from_int("tn") или функцией GetTnCurrentLS() 
UserKassVedName(name, doc, kindForm, propVed, propSum, dop)
{
  return name;
}

// функция перед стартом приема в кассовые ведомости (после панели)
// name - имя ведомости в WIN кодировке, заданное пользователем в кассовой панели (например "по набору видов");
// doc - interface IDoc - описание см. в SCRIPT\idl\USEFUL.IDL  
// kindForm -   0, // " Аванс",
//              1, // " Заpплата",
//              2, // " Oтпускные (при выдаче до расчета за месяц)",
//              3, // " К увольнению (при выдаче до расчета за месяц)",
//              4, // " По пpoизвoльному виду Н-У",
//              5, // " По набору видов Н-У",
//              6, // " Выдача суммы",
//              7, // " Частичная выдача "
UserBeforeKass(name, doc, kindForm)
{
  
  // return ESC;  - отменить процесс
}


// функция после приема в кассовые ведомости
// createdVedIds - через запятую созданные idved
UserAfterKass(name, doc, kindForm, createdVedIds)
{
   
}
*/

/*
Функция UserKassSumma(doc, kind_form, stage, &sum, aprop) - вызывается при приеме в кассовую ведомость (пока только для ведомости по виду Н-У / набору видов)
   Может быть вызвана много раз!

   stage & 1 == 0 
   перед разноской выплат с idved  в ЛС  на выбранные пользователем виды Н-У (в том числе на стадии после расчета алиментов), 
   на данном этапе можно вернуть 1 чтобы отключить системный алгоритм разноски выплат (значение суммы на руки без НДФЛ нужно записать в параметр sum)
   Внимание! Если на этой стадии изменили выплаты то нужно сделать такие же изменения при вызове с параметром stage & 2)

   stage & 1 == 1 
   после разноски выплат с idved  в ЛС  на выбранные пользователем виды Н-У, 
   перед расчетом НДФЛ и пересчетом алиментов (в том числе на стадии после первичного расчета алиментов), 
   на данной стадии можно повлиять на выборку сумм начислений, например изменить выплату по РК если хочется взять только 15% от захваченных выплат.
   Внимание! Если на этой стадии изменили выплаты то нужно сделать такие же изменения при вызове с параметром stage & 2)

   stage & 2 - после расчета алиментов, в ЛС были очищены разнесенные на стадиях 0-1 выплаты и запущен процесс заново! 
               функция с таким stage не вызывается, если прием идет без пересчета алиментов (т.е. либо в панели сняли галку "расчет алиментов", 
               либо на предыдущих stage вернули 4) 

   из функции можно вернуть комбинацию из флагов:
   1  - (только для этапа stage&1==0) разноску выплат сделала сама функция UserKassSumma (значение суммы на руки без НДФЛ нужно записать в параметр sum)
   2  - не запускать расчет НДФЛ
   4  - не запускать расчет алиментов
   8  - не отбрасывать нулевую строку в кассовой ведомости. Без флага программа будет сравнивать с 0 сумму на руки / НДФЛ / алименты (последние по настройкам)
   -1 - отменить прием текущего ЛС по текущему aprop (источник/объект/подразделение/совм-во), 
        в этом случае не вызвается функция UserKassSumma_Final

Функция UserKassSumma_Final(doc, kind_form, &sum, aprop) -  вызывается при приеме в кассовую ведомость после разноски выплат и расчета НДФЛ с алиментами
   коды возврата 8 и -1 работают так же как у предыдущей функции UserKassSumma

   внутри функций:
   месяц выборки сумм == mtek для kind_form==4, но для ведомости по набору видов (kind_form==5)  = doc.GetTargetMV()
   idved разнесенных выплат = doc.GetIdVed()
   дата ведомости = doc.GetDateDoc() // строка

// Приблизительный пример функции для перерасчета РК только с выбранных видов в ведомость по набору НУ (см. комментарии todo!)
UserKassSumma(doc, kind_form, stage, &sum, aprop)
{
   if (!(stage & 1) || kind_form!=5)
      return;                // ^^ работаем только с ведомостью по набору Н-У
      
   int idVed = doc.GetIdVed();
   var MatrLS = GlobalMatrLS();
   int size = MatrLS.Size();
   for (int index = 0; index < size; index++)
   {
      var be = MatrLS.GetBaseElem(index);
      if (VarHasValue(be) && 99 == to_int(be.Code) && (aprop.Total() || aprop.IsEQ(GetPropOfCod(be.Code))))
      {                  //  ^^ внутренний код вида РК  
         var sumVect = be.SumVect;
         for (int i = 0; i < sumVect.Size(); i++)
         {
            var sumElem = sumVect.GetSum(i);
            int paysCount = sumElem.PaysCount();
            double sumAll = 0;
            for (int p = 0; p < paysCount; p++)
            {
               var pay = sumElem.GetPay(p);
               if (pay.IdVed == idVed) // todo! не факт что ведомость захватила сумму РК в лс!
               {
                  double nach = MatrLS.CollectSumm(10, sumElem.m, 0, CL_M | CL_COL | CL_SOURCE, aprop, idVed).Sum;
                  double rk = be.Base*nach/100; // ^^ 11й столбец для расчета РК
                             //  ^^  процент РК из базового значения
                  roundd(rk, 2, rk);
                  if (nabs(rk - pay.Sum) > 0.001)
                  {
                     sum+= rk-pay.Sum; // изменяем сумму на руки на величину корректировки
                     sumElem.DeletePay(p--);
                     --paysCount; // если не будет ниже return то чтобы цикл не дошел до новой добавленной выплаты
                     struct PaidSumS paid;
                     paid.IdVed = idVed;
                     paid.Sum = rk;
                     sumElem.AddPay(paid);
                     return; // todo!  откорректировали только одну выплату!
                  }
               }
            }
         }
      }
   }
}
*/