InitNDFL6_16(AdrTbl)
{
   UnloadNDFL6Modules_Create();
   LoadNDFL6Modules_Create();
   // отсортируем по ключевым полям
   var T=CreateObject("CurPrnTbl"); 
   T.Initial(AdrTbl);
   T.Sort_Field(0); 

   iScriptGlobalNumOrg = -1;   // сбросим кэш по организациям
   gSaveAPropBEFilterNDFL = 0; // фильтр по APropBE
   return 0;
}

FinalNDFL6_16(AdrTbl)
{
   // отсортируем по ключевым полям
   var T=CreateObject("CurPrnTbl"); 
   T.Initial(AdrTbl);
//   T.Fill_Bottom_Text_2();

//   if ( gTypeOKTMO_NDFL == 1 )
//   {
      // При разбивке по ОКТМО по КЧ возможна ситуация, когда
      // "начислений" уже нет (остались в прошлом месяце) а удержанный налог есть
      // поэтому для создания первого раздела и простановки туда удержанного 
      // налога в поле 070 используется "уловка" - временно ставим номер раздела 9
      // а по окончании приема меняем его на 1
//      int FldNR = T.Find_Name_Fld("NR");
//      if ( FldNR!=-1 )
//         for ( int Rcr=0; Rcr<T.Count_Rcr(); ++Rcr )
//         {
//             if ( atoi(T.Text(FldNR,Rcr))==9 )
//                T.SText(FldNR,Rcr,"1");
//         }
//   }
   // Необходимо подвести итоги "схлопнув" информацию по работникам 
   // (оставив в ключевых только IDOrg, и даты для раздела 2)
   // При подведении подитогов, надо:
   // 1. просуммировать кол-во физ.лиц
   // 2. перестать считать ключевыми столбцы:
   //     Табельный номер, ID ведомости, тип дохода
   var arrNameSumFld = GetArray("CountFL");
   int cntSumFld = GetUBound(arrNameSumFld)+1;
   int fldSum[cntSumFld];
   string OldValueSum[cntSumFld];
   char TmpFlagSum[2];
   TmpFlagSum[0]=' ';TmpFlagSum[1]=0;
   for ( int i=0; i<cntSumFld; ++i )
   {
      fldSum[i] = T.Find_Name_Fld(arrNameSumFld[i]);
      if ( fldSum[i]!=-1 )
      {
         TmpFlagSum[0]=T.FlagSumField(fldSum[i]);
         OldValueSum[i] = TmpFlagSum;
         T.SetFlagSumField(fldSum[i],"+");
      }
   }

//___________________________общие итоги____________________________________
//   var arrNameKeyFld = GetArray("C_FIO","IDVed","IDTypeInc");
//   int cntKeyFld = GetUBound(arrNameKeyFld)+1;
//   int fldKey[cntKeyFld];                       // массив  fldKey[4]
//   for ( int i=0; i<cntKeyFld; ++i )
//   {
//      fldKey[i] = T.Find_Name_Fld(arrNameKeyFld[i]);
//      if ( fldKey[i]!=-1 )
//         T.SetFlagKeyField(fldKey[i]," ");
//   }

//   T.Make_Group_Key();
   // Восстанавливаем признаки ключевых и суммируемых полей
//   for ( int i=0; i<cntKeyFld; ++i )
//      if ( fldKey[i]!=-1 )
//         T.SetFlagKeyField(fldKey[i],"*");
//   for ( int i=0; i<cntSumFld; ++i )
//      if ( fldSum[i]!=-1 )
//         T.SetFlagSumField(fldSum[i],OldValueSum[i]);

//   T.Sort_Field(0,1); 


   // при создании пустой таблицы без выбранных ЛС (это возможно, для 6-НДФЛ есть флаг CanBeWithoutLS) 
   // надо добавить информацию об организации (если ее там нет)
   var keyVals = T.GetKeyValueCollections(true);
   if (!keyVals.IsCollectionExist(depInfoKey) && IsObject(T.SilentParam))
   {
      int depId = (T.SilentParam.PfParamsVer() != 0) ? T.SilentParam.PfPacketParams.OrgId : GetOrgForPodr(-1);
      CorrectDepartmentId(depId, T.SilentParam);
      var month = CreateObject("KMonth");
      month.SetDateIII(1,T.SilentParam.Month, T.SilentParam.Year);
      AddDepartmentIdToKeyVals(depId, month.GetAbs(), T.SilentParam, keyVals);         
   }

   // с 17.02.2017 не надо, запись сделает сам код "приема ЛС" в таблицу
   // T.Rewrite();

   iScriptGlobalNumOrg = -1;   // сбросим кэш по организациям
   gSaveAPropBEFilterNDFL = 0; // фильтр по APropBE
   // Временно, пока обдумывается решение.
   // У нас функция "начала приема" вызывается один раз, а "конец приема"
   // столько раз сколько таблиц создается
   // Поэтому при подготовке с разбивкой по организациям уже на второй таблице
   // оказывалось, что глобальной переменной gSaveAPropBEFilterNDFL нет
   // UnloadNDFL6Modules_Create();
   return 0;
}

FinalNDFL66_16(AdrTbl)
{
   iScriptGlobalNumOrg = -1;   // сбросим кэш по организациям
   gSaveAPropBEFilterNDFL = 0; // фильтр по APropBE
   // Временно, пока обдумывается решение.
   // У нас функция "начала приема" вызывается один раз, а "конец приема"
   // столько раз сколько таблиц создается
   // Поэтому при подготовке с разбивкой по организациям уже на второй таблице
   // оказывалось, что глобальной переменной gSaveAPropBEFilterNDFL нет
   // UnloadNDFL6Modules_Create();
   return 0;
}

UnloadNDFL6Modules_Create()
{
  UnloadScriptModule("forms\\NewReporting");
  UnloadScriptModule("forms\\DefineEnterpriseID");
}

LoadNDFL6Modules_Create()
{
  LoadScriptModule("forms\\NewReporting");
  LoadScriptModule("forms\\DefineEnterpriseID");
}

RemakeOtherDate_66(&Tbl,TypeIncomeUpdate)
// Обновление дат в зависимости от типа дохода
{
   if ( TypeIncomeUpdate<0 || TypeIncomeUpdate>=TI6NDFL_CNT ) return 0;
   // В таблицах обновления задается дата выплаты дохода, в зависимости от нее,
   // перед разноской данных в ЛС, нужно модифицировать дату фактического получения дохода
   // и срок перечисления налога
   int Type120   = GetCommonCnfInt("Type120", "6ndfl");
   int fld100 = Tbl.Find_Name_Fld("Fld100");
   int fld110 = Tbl.Find_Name_Fld("Fld110");
   int fld120 = Tbl.Find_Name_Fld("Fld120");
   if ( fld100==-1 || fld110==-1 || fld120==-1 ) return 0;
   var DIncome = CreateObject("KDate");  // Дата в строку 100 (дата фактического получения дохода)
   var DTaxUd  = CreateObject("KDate");  // Дата в строку 110 (дата удержания налога)
   var DTaxSend = CreateObject("KDate"); // Дата в строку 120 (срок перечисления)

   for ( int Rcr = 0; Rcr<Tbl.Count_Rcr(); ++Rcr )
   {
      DTaxUd.SetDate(to_string(Tbl.Text(fld110,Rcr)));
      // Для всего кроме зарплаты и натур.дохода выставляем дату фактического получения дохода
      // равную введенной дате выплаты дохода
      if ( TypeIncomeUpdate!=TI6NDFL_ZP && TypeIncomeUpdate!=TI6NDFL_NAT && 
           TypeIncomeUpdate!=TI6NDFL_MATV )
      {
         DIncome.SetDate(DTaxUd.GetStr());
         Tbl.SText(fld100,Rcr,DIncome.GetStr());
      }
      // Для отпускных и больничных выставляем срок перечисления равный концу месяца
      // А для всего остального - следующий день после выплаты
      if ( TypeIncomeUpdate==TI6NDFL_OTP || TypeIncomeUpdate==TI6NDFL_BL )
         DTaxSend.SetDateII(DTaxUd.CountDay(),DTaxUd.GetAbs());
      else
      {
         DTaxSend.SetDate(DTaxUd.GetStr());
         DTaxSend.Inc();
      }
      if ( !Type120 )
         DTaxSend.SetDateD(GetHappyDatePayOffEx(DTaxSend.GetDay(), 0, DTaxSend.GetAbs(),1));
      Tbl.SText(fld120,Rcr,DTaxSend.GetStr());
   }
   return 0;
}

TransferToLS66(AdrTbl, TypeIncomeUpdate)
// Разноска информации в ЛС
{
   int FlagUpdate = 0;
   if ( TypeIncomeUpdate<0 )
   {
      FlagUpdate = 4; // удаление
      TypeIncomeUpdate = 0;
   }
   else if ( TypeIncomeUpdate )
      FlagUpdate = 2; // обновление без добавления новых записей
   if ( TypeIncomeUpdate<0 || TypeIncomeUpdate>=TI6NDFL_CNT ) TypeIncomeUpdate=0;


   var T=CreateObject("CurPrnTbl"); 
   T.Initial(AdrTbl);
   int fldTN = T.Find_Name_Fld("C_FIO");
   if ( fldTN==-1 ) return 0;
   T.Sort_Field(fldTN,1); // сортируем по ТН!
   if ( TypeIncomeUpdate )
      RemakeOtherDate_66(T,TypeIncomeUpdate);

   var doneTN = CreateObject("MapLong");
   int cntRcr = T.Count_Rcr();
   for ( int Rcr=0; Rcr<cntRcr; ++Rcr )
   {
      T.UnmarkAllRecord();
      int CurTN = atoi(T.Text(fldTN,Rcr));
      if ( !CurTN ) continue;
      if ( doneTN.IsExist(CurTN) ) continue;
      doneTN.Add(CurTN,Rcr);
      T.Switch_Ins_Record(Rcr);

      for ( int Rcr1 = Rcr+1; Rcr1<cntRcr; ++Rcr1 )
      {
         if ( CurTN != atoi(T.Text(fldTN,Rcr1)) )
            break;
         else
         {
            Rcr = Rcr1; // пользуясь отсортированностью сдвигаем Rcr чтобы ускорить перебор
            T.Switch_Ins_Record(Rcr);
         }
      }
      // сюда попали отметив все строчки с одинаковым ТН
      var TargetTbl = CreateObject("CurPrnTbl");
      TargetTbl.InitialAdditionalRefLS(NDFL6_DOP_TABLE,CurTN,1);
      int FldID = TargetTbl.Find_Name_Fld("ID");
      if ( FldID == -1 ) continue;
      TargetTbl.UpdateByID(T.GetAdr(),FldID,FlagUpdate);
      TargetTbl.Rewrite();
   }
   T.UnmarkAllRecord();
   // Для предотвращения повторной разноски строкам может быть присвоен ID
   // который надо сохранить
   // Если разносим изнутри таблицы, то сохранятся все изменения!
   T.Rewrite();
                  
   return 0;
}

//UpdateInfoFld_NDFL66(AdrTbl)
//{
//   var T=CreateObject("CurPrnTbl"); 
//   T.Initial(AdrTbl);
//   int fldIDInc = T.Find_Name_Fld("IDTypeInc");
//   int fldTypeInc = T.Find_Name_Fld("TypeInc");
//   if ( fldTypeInc==-1 || fldIDInc==-1 ) return 0;
//   for ( int Rcr = 0; Rcr<T.Count_Rcr(); ++Rcr )
//       T.SText(fldTypeInc,Rcr,NameTypeIncome6NDFL(atoi(T.Text(fldIDInc,Rcr))));
//   T.Rewrite();
//   return 0;       
//}

OnPacketStatusChanging_NDLF6(AdrTblList, &PacketParams, NewStatusStr)
{
   if (NewStatusStr != "Submitted" || PacketParams.ReportList.Count <= 0
        || PacketParams.ReportList.Item(0).CorrTypeAsString != "Corrective")
      return;

   UnloadNDFL6Modules_Create();
   LoadNDFL6Modules_Create();
   
   var TList = CreateObject("CurPrnTbl"); 
   TList.Initial(AdrTblList);
   int year = PacketParams.YearPacket;
   int month = PacketParams.MonthPacket;

   int AdrTbl = TList.GetTableFromList(0);
   var T = CreateObject("CurPrnTbl"); 
   T.Initial(AdrTbl);
   
   var allKeyVals = T.GetKeyValueCollections(true);
   var keyVals = allKeyVals.Get(depCorrNumKey, true);
   keyVals.SetBegin();
   while (!keyVals.End())
   {
      int id = atoi(keyVals.GetKey());
      if (id != 0)
      {
         int num = atoi(keyVals.GetValue());
         Ndfl6SetDepartmentCorrNumber(id, month, year, num + 1);
      }
      keyVals.Next();
   }
   
   UnloadNDFL6Modules_Create();
}
