Титов Александр
 
 
  Joined: 26 Jul 2002 Posts: 975 Location: Титов Александр Александрович Occupation: Компания БЭСТ Interests: Москва
  | 
		
			
				 Posted: 01 Sep 2005 14:29    Post subject:  | 
				     | 
			 
			
				
  | 
			 
			
				 	  | garik wrote: | 	 		  Хоть и стара тема.Но как здорово было бы посмотреть код этого алгоритма.Может в свете последних тенденций к открытию новых возможностей и поворота лицом к программистам, господа разработчики выложат данный код?   | 	  
 
 
Добрый день!
 
Код выложить не проблема (см.ниже). А вот подробно описать - это сложнее. Если кто будет разбираться - готов ответить на вопросы.
 
 
 	  | Code: | 	 		  //
 
// Функция ЕСН нужна для формирования справок по социальному налогу
 
// в АРМ-е главного бухгалтера. Обрабатывает всех сотрудников предприятия.
 
// независимо от установленных фильтров и т.д.
 
// Пример:   ЕСН("001","2001.01","2001.04", 0, 100000, "С")
 
// "001" - код фонда единого социального налога
 
// "2001.01 - период начала обработки
 
// "2001.04 - период окончания обработки
 
// 0 - налогооблагаемая база от ...
 
// 100000 - налогооблагаемая база до ...
 
// cPens русские буквы  "С" -  страховая часть
 
//                      "Н" -  накопительная часть
 
// BYear - год рождения ОТ
 
// EYear - год рождения ДО
 
// cSex  - пол сотрудника
 
// cLgot - признак вычета льготы из налоговой базы
 
// nSotr - количество людей имеющих наибольший доход
 
// функция возвращает массив из четырех элементов:
 
// aRet[1] - общий облагаемый доход обрабатываемых сотрудников
 
// aRet[2] - количество сотрудников
 
// aRet[3] - общая сумма льготы по сотрудникам
 
// aRet[4] - общая сумма начисления в фонд по всем сотрудникам
 
// aRet[5] - общая сумма дохода обрабатываемых сотрудников
 
//
 
Function N4_2( cFond, cBPer, cEPer, SM1, SM2, cPens, BYear, EYear, cSex, cLgot, nSotr )
 
   Local aPens    := { {"Н","НАКОП"},;
 
                       {"С","СТРАХ"};
 
                     }
 
   Local aSexL    := {{"М","1"},{"Ж","2"}}
 
   Local nPens
 
   Local cTNum
 
   Local aRet     := { 0, 0, 0, 0, 0 }
 
   Local aRetSotr := {}
 
   Local aBases   := {"CodeInc","Arc_Inc","IncStaff", "CardSpri", "CardsSec"}
 
   // если не задан первый параметр - возвращаем нули
 
   if Empty( cFond )
 
      Return aRet
 
   endif
 
   // если период начала не задан, то он берется как январь года,
 
   // текущего расчетного периода из зарплаты.
 
   If( Y_Nil(cBPer) .OR. Empty(cBPer), cBPer := Left( S_PERIOD, 4) + ".01", NIL )
 
   // если период окончаняи не задан, то он берется как текущий
 
   // расчетный из зарплаты
 
   If( Y_Nil(cEPer) .OR. Empty(cEPer), cEPer := S_PERIOD, NIL )
 
   // если период начала обработки больше периода окончания, то возвращаем нули.
 
   if cBPer > cEPer
 
      Return aRet
 
   endif
 
 
   cPens := if( Y_Type(cPens, "C") .AND. Len(cPens) == 1 .AND.;
 
                ( nPens := ASCAN(aPens, {|a|a[1] == cPens} ) ) <> 0,;
 
                aPens[nPens,2],;
 
                NIL;
 
              )
 
   cSex  := if( Y_Type(cSex, "C") .AND. Len(cSex) == 1 .AND.;
 
                ( nPens := ASCAN( aSexL, {|a,i|a[1] == cSex} ) ) <> 0 ,;
 
                aSexL[nPens,2],;
 
                NIL;
 
              )
 
 
   if( Y_Type(BYear, "N") .AND. !Empty(BYear), NIL, BYear := NIL )
 
   if( Y_Type(EYear, "N") .AND. !Empty(EYear), NIL, EYear := NIL )
 
   SM1   := if( Y_Nil(SM1) .OR. Empty(SM1), NIL, if( Y_Type(SM1,'C'), Val( SM1 ), SM1 ) )
 
   SM2   := if( Y_Nil(SM2) .OR. Empty(SM2), 9999999999999999, if( Y_Type( SM2,'C'), Val( SM2 ), SM2 ) )
 
 
   DbOpenBases( aBases )
 
 
 
   DbxEval( "CardSpri", "01",,,;
 
           {|a|;
 
              a := S_ESN( cFond, cBPer, cEPer, cPens, cLgot ),;
 
              IF( ( Y_Nil(SM1) .OR. a[1] >= SM1 ) .AND. a[1] <= SM2,;
 
                  If( N_Nil(nSotr),;
 
                      AADD( aRetSotr, a ),;
 
                      AEval( a, {|x,i|aRet[i] += x });
 
                    ),;
 
                  NIL;
 
                );
 
           },;
 
           {|| Empty( FiGet(STNum) ) .AND.;
 
               ( Y_Nil(cSex)  .OR. ( CardsSec->SEX == cSex ) ) .AND.;
 
               ( Y_Nil(BYear) .OR. ( YEAR(CardsSec->BIRTHDATE) >= BYear ) ) .AND.;
 
               ( Y_Nil(EYear) .OR. ( YEAR(CardsSec->BIRTHDATE) <= EYear ) );
 
           },,;
 
           {|| DBSetRelation( "CardsSec", {|| UPPER(TNUM)},"UPPER(TNUM)")},;
 
           {|| DBClearRelation()};
 
          )
 
   // Возврат суммы дохода (максимальной) по заданному количеству людей
 
   If N_Nil(nSotr) .AND. Y_Type(nSotr, "N") .AND. nSotr > 0
 
      ASort( aRetSotr,,, {|x,y|x[1] > y[1]} )
 
      AEval( aRetSotr, {|a|AEval( a, {|x,i|aRet[i] += x}) }, 1, nSotr)
 
   EndIf
 
   DBCloseBases( aBases )
 
 
Return( aRet )
 
 
 
 
// обработка данных по фонду социального налога для конкретного сотрудника
 
// Используется из АРМ Главного бухгалтера ОБ.СУМ_ЕСН(cFond, cBPer, cEPer, cPens, cLgot)
 
// cFond        - код фонда (или массив кодов)
 
// cBPer, cEPer - интервал за который необходимо собрать данные
 
// cPens        - данные по пенсионному накопительная или страховая
 
// cLgot        - признак вычета льготы из налоговой базы
 
Function S_ESN( cFond, cBPer, cEPer, cPens, cLgot )
 
 
   Local aPens    := { {"2", "НАКОП"},;
 
                       {"1", "СТРАХ"};
 
                     }
 
   Local nPens
 
   Local aRett    := { 0, 0, 0, 0, 0}
 
   Local cTNum    := CardSpri->TNum
 
   Local bFor     := If( Y_Type(cFond, "A"),{|| ASCAN( cFond,{|x|Upper(FiGet(Fond)) == Upper(x)}) <> 0},{||Upper( FiGet(Fond) ) == Upper( cFond )})
 
   Local bWork    := {|a, l|;
 
                        a := Any("CodeInc", "IDCode", FiGet(IDCodeInc), {"CodeInCTG", "TaxIncCtg"} ),;
 
                        l := ( Empty(cPens) .OR. a[2] == cPens ),;
 
                        if( a[1] == '00', ( aRett[1] += FiGet(SummaInc), aRett[5] += FiGet(Summa)), NIL ),;
 
                        if( a[1] == '02', aRett[3] += FiGet(Summa), NIL ),;
 
                        if( l .AND. a[1] == '20' .AND. ( Empty(a[2]) .OR. !Empty(cPens) ),;
 
                                                  aRett[4] += FiGet(Summa), NIL );
 
                     }
 
 
   cPens := if( Y_Type(cPens, "C") .AND. (nPens := ASCAN( aPens, {|a|a[2] == cPens} )) <> 0,;
 
                aPens[nPens,1],;
 
                "";
 
              )
 
   // если период начала не задан, то он берется как январь года,
 
   // текущего расчетного периода из зарплаты.
 
   PV_Init(@cBPer, @cEPer)
 
 
   If( Y_Nil(cBPer) .OR. Empty(cBPer), cBPer := Left( S_PERIOD, 4) + ".01", NIL )
 
   // если период окончаняи не задан, то он берется как текущий
 
   // расчетный из зарплаты
 
   If( Y_Nil(cEPer) .OR. Empty(cEPer), cEPer := S_PERIOD, NIL )
 
   // если период начала обработки больше периода окончания, то возвращаем нули.
 
   if cBPer > cEPer
 
      Return aRett
 
   endif
 
 
   If cBPer < S_PERIOD
 
      DbxEval( "Arc_Inc", "TNUM1",,{"UPPER(TNUM+FPERIOD)", Upper(cTNum+cBPer), Upper(cTNum+cEPer)},;
 
               bWork, bFor;
 
             )
 
   EndIf
 
   If cEPer >= S_PERIOD .AND. ( CardSpri->SumIn != 0 .OR. CardSpri->SumOut != 0 )
 
      DbxEval( "IncStaff", "TNUM1",,{"UPPER(TNUM)", Upper(cTNum)}, bWork, bFor )
 
   EndIf
 
   if( ( aRett[3] := Min( aRett[1], aRett[3] ) ) <= 0, aRett[3] := 0, NIL)
 
   aRett[1] := aRett[1] - if( Empty(cPens) .AND. Empty(cLgot), aRett[3], 0 )
 
   aRett[2] := If( aRett[1] == 0 .AND. aRett[3] == 0 .AND. aRett[4] == 0, 0, 1)
 
Return aRett | 	 
  _________________ С уважением, Александр Титов, Компания БЭСТ, Москва, отдел разрабо | 
			 
		  |