// Функции определяющие набор ID организаций в ЛС и особенность выделения сумм // на этот ID (по-месячно, по исполняемой должности, по источнику) var gSaveAPropBEFilterNDFL; // переменная использующаяся для сброса фильтра по APropBE при приеме по исп.должностям и источникам var gIDOrgsCollection6NDFL_2; // Хранилка, для проверки уникальности IDOrg для раздела 2 формы 6-НДФЛ var gIDOrgsSubstitute=0; // Хранилка "замен" для IDOrg: используется в том случае если разные подразделения имеют одинаковый набор // ИНН-КПП-ОКТМО в противном случае у нас возможно появление двух отчетов с одинаковыми ИНН-КПП-ОКТМО var gUniqueINN_KPP_OKTMO=0; // Хранилка уникальных сочетаний ИНН-КПП-ОКТМО и первой IdOrg для них. var gFirstTimeIdOrg = 0; // Хранилка-признак, что IdOrg встретился первый раз при создании отчета var gTypeOKTMO_NDFL = 0; // 0 - ЛС относится на единственный ОКТМО, 1 - разбивка по полю КЧ, 2 - по исп.доложности, 3 - по ист.фин. ChangePaidIncome(Tn, &Paids, &Type, &Ar) // Пример скриптовой функции которая вызывается при заполнении дат у дохода // Tn - табельный номер // Paids - класс PaidIncomeCollection состоящий из одного элемента PaidIncome // для которого и требуется установить/заменить даты и/или суммы // Type - тип дохода в PaidIncome TI6NDFL_???? // Ar - массив доп.параметров, возможность для расширения без изменения сигнатуры. // в настоящий момент не используется // Возвращает 0 - данные изменены и должны быть применены для формирования 6-НДФЛ // ESC - изменений не было // -1 - не требуется дальнейшая обработка этого элемента поставочным алгоритмом заполнения дат { int Podr = Poln_Tn/sizetn; struct PaidIncome OnePaid; Paids.GetItem(0,OnePaid); // Если подразделение первое и выплата зарплатная, то меняем дату выплаты // зарплаты за февраль var Dat = CreateObject("KDate"); if ( Podr==1 && Type == TI6NDFL_ZP ) { if ( OnePaid.MonthTax == absmec(201602.01) ) { Dat.SetDate("17.03.2016"); OnePaid.DateTaxUd = Dat.GetInt(); Paids.SetItem(0,OnePaid); return 0; } } if ( Type == TI6NDFL_ZP ) { double CodeNU =GetFullCodeNU(OnePaid.CodeNU,OnePaid.Extension); string ExtSubj = IntSubjectToExt(GetIDSubjectOfCod(CodeNU)); char ExtSrc[2]; ExtSrc[1]=0; ExtSrc[0]=IntSrcToExt(GetSrcOfCod(CodeNU)); if ( ExtSrc=="Ѓ" ) { Dat.SetDateD(GetHappyDatePayOff(17, 1, OnePaid.MonthTax)); OnePaid.DateTaxUd = Dat.GetInt(); Paids.SetItem(0,OnePaid); return 0; } } return ESC; } var DefEntID_firstTimeAfterLoadCall = GetNothing(); DefineEnterpriseID_NDFL(&DateBeg, &DateEnd,NumForm) // DateBeg,DateEnd - KDate которые задают период, для которого определяем // набор ID организаций // NumForm = 2 - 2-НДФЛ // NumForm = 6 - 6-НДФЛ // NumForm = 8 - 6-НДФЛ-2021 + если задана Ndfl6v2021PersonRawData значит создаем 6НДФЛ2021 и нужно наполнить этот класс Ndfl6v2021PersonRawData коллекцию PaidData // NumForm = 10 - налоговые уведомления + должна быть задана (создана) EnpNoticePersonData // NumForm = 66 - вспомогательные таблицы для заполнения доп.таблицы в ЛС // NumForm = 67 - вспомогательная таблица для заполнения дат выплаты дохода // NumForm = 70,71,72 - вспомогательная таблица для разноски уплаты НДФЛ // NumForm = 60 - 6-НДФЛ (Реестр в разрезе месяцев учета) { if ( IsNothing(DefEntID_firstTimeAfterLoadCall) ) { var T = CreateObject("CurPrnTbl"); SaveAndReadTablePeriodParams(T); DefEntID_firstTimeAfterLoadCall = 0; } gTypeOKTMO_NDFLCurLS = GetEmpty(); // Тип разбивки для конкретного ЛС может быть отключен (если у этого ЛС сущностей много, но ОКТМО одно) gPolnTnTypeOKTMO_NDFL = 0; gIDOrgsCollection6NDFL_2 = 0; int cntEnt = GetEnterpriseCount(0); if ( cntEnt<1 ) cntEnt=1; // int BaseEnterpriseID = GetOrgForPodr(-1); gTypeOKTMO_NDFL = DefineTypeOKTMO_NDFL(); if ( cntEnt<2 || !gTypeOKTMO_NDFL ) { var kcp = CreateObject("KPeriodsIterations"); kcp.ClearAll(); double Tax70=0.; if ( NumForm!=2 ) // 66 Вторая часть, для всего кроме 2-НДФЛ AddInfoPart2_6NDFL(0, kcp, NumForm,Tax70,DateBeg,DateEnd,0); //if ( NumForm==6 || NumForm==2 ) // 66 Только для 2-НДФЛ и 6-НДФЛ, для вспомогательных таблиц не надо // kcp.AddPeriod(GetKeyForFormNDFL(0,NumForm,Tax70),DateBeg.GetStr(),DateEnd.GetStr()); if ( NumForm==6 || NumForm==60 || NumForm==2 || NumForm==8) // 66 Только для 2-НДФЛ и 6-НДФЛ, для вспомогательных таблиц не надо { if ( NumForm==60 ) NumForm=6; // Для реестра все аналогично 6-НДФЛ kcp.AddPeriod(GetKeyForFormNDFL(0,NumForm,Tax70),DateBeg.GetStr(),DateEnd.GetStr()); } return 0; } int rc = PriorityCall("UserDefineEnterpriseID_NDFL","SysDefineEnterpriseID_NDFL",DateBeg,DateEnd,NumForm); // return rc; // Если раскомментировать эту строчку, то подготовка справок будет без дополнительной оптимизации // Дополнительная оптимизация. Чтобы не делать лишней разбивки в тех случаях, когда "сущностей" несколько (источников, должностей и т.п.) а ОКТМО одно. // До этого эта "оптимизация" делалась за счет "склейки" строк в таблице. Но у нее был ряд недостатков, например "+- рубль" или двойные вычеты на иждивенцев и т.п. int countIdOrg=0; long osnOrg = GetOrgForPodr(Poln_Tn/sizetn); var kcp = CreateObject("KPeriodsIterations"); // Такую оптимизацию нельзя делать, т.к. нам дополнительно надо сравнить IdOrg по сущности на которую настроена разбивка // с IdOrg подразделения в котором находится ЛС в списке ЛС // if ( kcp.Size()<=1 ) countIdOrg=1; // else { var mapIdOrg = CreateObject("MapLong"); for( kcp.SetBegin(); !kcp.End(); kcp.Next() ) { long curIdOrg = GetCurrentOrgID_NDFL(NumForm); if ( mapIdOrg.IsExist(curIdOrg) ) continue; mapIdOrg.Add(curIdOrg,curIdOrg); // нам достаточно знать, что количество IdOrg больше 1 if ( mapIdOrg.Size()>1 ) break; } // Важно!!! Через эту переменная могли установить фильтр // на совместительство,объект,источник при получении кода организации // так как мы получали не для вызова RTax а только для получения списка организаций // здесь ее обнулим gSaveAPropBEFilterNDFL=0; // У клиентов возможна странная ситуация: ЛС находится в подразделении, относящемся // к одной организации, а при этом "сущность" по которой делаем разбивку ОКТМО относится // к другой организации (например разбивка по полю КЧ, и в поле КЧ сказано что ЛС на самом деле // относится к другому ОКТМО). Чтобы в этом случае не отключить разбивку для этого человека // надо добавить еще организацию к которой относится он по месту нахождения в списке ЛС if ( !mapIdOrg.IsExist(osnOrg) ) mapIdOrg.Add(osnOrg,osnOrg); countIdOrg = mapIdOrg.Size(); } // В случае налоговых уведомлений вся нужна информация собрана в EnpNoticePersonData и разбивка таблицы по строкам не требуется if ( NumForm == 10 ) { // Для текущего ЛС сбрасываем признак необходимости разбивки по ОКТМО gTypeOKTMO_NDFL = gTypeOKTMO_NDFLCurLS = 0; gPolnTnTypeOKTMO_NDFL = Poln_Tn; // А также чистим список итерации по заполнению таблицы kcp.ClearAll(); double Tax70=0.; kcp.AddPeriod(GetKeyForFormNDFL(0,NumForm,Tax70),DateBeg.GetStr(),DateEnd.GetStr()); } else if ( countIdOrg<2 && (GetCommonCnfInt("NoOptimize","6ndfl")&0x01)==0 ) // Если количество уникальных организаций - одна, то и разбивка не нужна. // Настройка отключения оптимизации - нужна в тех случаях, когда заполение информации // по удержанным суммам НДФЛ накладно по времени (как в СКБ Банке). Чтобы не собирать ее же второй раз // (то есть в основном сейчас для отключения второго вызова AddInfoPart2_6NDFL) { if (IsObject(Ndfl6v2021PersonRawData)) { var paidRaw160 = Ndfl6v2021PersonRawData.PaidRaw160; for(int i = 0; i< paidRaw160.Count; ++i) { var paidRaw = paidRaw160.Get(i); if (osnOrg!=paidRaw.IdOrg) return rc; } var PaidRawData = Ndfl6v2021PersonRawData.PaidRawData; for(int i = 0; i< PaidRawData.Count; ++i) { var paidRaw = PaidRawData.Get(i); if (osnOrg!=paidRaw.IdOrg) return rc; } var T = CreateObject("CurPrnTbl"); var mainMgr = T.VarL; Ndfl6v2021PersonRawData = mainMgr.CreatePersonRawData(); } // Для текущего ЛС сбрасываем признак необходимости разбивки по ОКТМО gTypeOKTMO_NDFL = gTypeOKTMO_NDFLCurLS = 0; gPolnTnTypeOKTMO_NDFL = Poln_Tn; // А также чистим список итерации по заполнению таблицы kcp.ClearAll(); double Tax70=0.; if ( NumForm!=2 ) // 66 Вторая часть, для всего кроме 2-НДФЛ AddInfoPart2_6NDFL(0, kcp, NumForm,Tax70,DateBeg,DateEnd,0); //if ( NumForm==6 || NumForm==2 ) // 66 Только для 2-НДФЛ и 6-НДФЛ, для вспомогательных таблиц не надо // kcp.AddPeriod(GetKeyForFormNDFL(0,NumForm,Tax70),DateBeg.GetStr(),DateEnd.GetStr()); if ( NumForm==6 || NumForm==60 || NumForm==2 || NumForm==8) // 66 Только для 2-НДФЛ и 6-НДФЛ, для вспомогательных таблиц не надо { if ( NumForm==60 ) NumForm=6; // Для реестра все аналогично 6-НДФЛ kcp.AddPeriod(GetKeyForFormNDFL(0,NumForm,Tax70),DateBeg.GetStr(),DateEnd.GetStr()); } return 0; } return rc; } GetCurrentOrgID_NDFL(NumForm) { return PriorityCall("UserGetCurrentOrgID_NDFL","SysGetCurrentOrgID_NDFL",NumForm); } // Получение текущего значения ID организации (в цикле таблицы) SysGetCurrentOrgID_NDFL(NumForm) { bool b6NDFL = NumForm!=2 && NumForm!=8; var kcp = CreateObject("KPeriodsIterations"); string key = kcp.GetCurCod(); // В форме 6-НДФЛ (и вспомогательных таблиц для 6-НДФЛ) // для второй части отчета в строке хранится сразу ID организации // а не ID сущности, по которой осуществляется разбивка // (подразделение, исполняемая должность, источник) // Поэтому для второй части никаких доп.действий не надо // Надо сразу возвращать ID if ( b6NDFL && GetCurrentPart6NDFLStr(key)==2 ) return atoi(key); // перенес условие сюда, чтобы в противном случае из доп.таблиц не выбирался // тот idOrg который там был проставлен, если отключалась // "разбивка по ОКТМО одного работника" if ( !gTypeOKTMO_NDFL ) return 0; if ( gTypeOKTMO_NDFL==1 || gTypeOKTMO_NDFL==5 ) // По полю КЧ { // из-за необходимости прямой сортировки по месяцам (январь, февраль,...) // для 2-НДФЛ первым идет не id сущности (подразделения) а значение для сортировки // Для 6-НДФЛ первым идет сразу id сущности var ar = SplitStr(key,","); long idOrgFromKch = IsSubStrPresent(key,",")?atol(ar[b6NDFL?0:1]):atol(key); if ( gTypeOKTMO_NDFL==5 ) // КЧ зависит от совместительства - надо установить совместительство { int cnt= GetUBound(ar)+1; long Combine = atol(ar[cnt-1]); var h=GetCurPropCountLS(); h.SetCombine(Combine); gSaveAPropBEFilterNDFL=0; gSaveAPropBEFilterNDFL=CreateObject("TempCommonSrc"); gSaveAPropBEFilterNDFL.InitialProp(CMN_SRC_COUNT_LS,h); } return idOrgFromKch; } else if ( gTypeOKTMO_NDFL==2 ) // По исп.должности { long Combine = atol(key); var h=GetCurPropCountLS(); h.SetCombine(Combine); gSaveAPropBEFilterNDFL=0; gSaveAPropBEFilterNDFL=CreateObject("TempCommonSrc"); gSaveAPropBEFilterNDFL.InitialProp(CMN_SRC_COUNT_LS,h); return GetOrgIDByCombine_NDFL(Combine); } else if ( gTypeOKTMO_NDFL==3 ) // По источнику финансирования { char Src = atoi(key); var h=GetCurPropCountLS(); h.SetSrc(Src); gSaveAPropBEFilterNDFL=0; gSaveAPropBEFilterNDFL=CreateObject("TempCommonSrc"); gSaveAPropBEFilterNDFL.InitialProp(CMN_SRC_COUNT_LS,h); return GetOrgIDBySrc_NDFL(Src); } else if ( gTypeOKTMO_NDFL==4 ) // По объекту { long Subject = atoi(key); var h=GetCurPropCountLS(); h.SetSubject(Subject); gSaveAPropBEFilterNDFL=0; gSaveAPropBEFilterNDFL=CreateObject("TempCommonSrc"); gSaveAPropBEFilterNDFL.InitialProp(CMN_SRC_COUNT_LS,h); return GetOrgIDBySubject_NDFL(Subject); } return 0; } // Для формы 2-НДФЛ достаточной ID организации, для 6-НДФЛ еще указываем // номер первой части GetKeyForFormNDFL(Key,NumForm,Tax70) { char Buf[256]; sprintf(Buf,"%ld",Key); if ( NumForm==6 ) return to_string(Buf)+","+"1,"+to_string(Tax70); return to_string(Buf); } GetKeyForFormNDFLWhenOnlyTaxExist(Key,NumForm,Tax70) { char Buf[256]; sprintf(Buf,"%ld",Key); if ( NumForm==6 ) return to_string(Buf)+","+"9,"+to_string(Tax70); return to_string(Buf); } CheckDateOnePay_6NDFL(TypeDate,&OnePaid,date1,date2,absm) { // выборка делается помесячно, а R_Tax(1000) всегда заполняет массив // за весь период, поэтому независимо от TypeDate всегда анализируем // месяц учета и берем только элементы из нужного нам месяца if ( OnePaid.MonthTax!=absm ) return false; if ( !TypeDate ) { var D = CreateObject("KDate"); D.SetInt(date1); if ( absmD.GetAbs() ) return false; return true; } TypeDate = GetTypeDate6NDFL(absm); bool bD100 = (TypeDate & 0x01)!=0; bool bD110 = (TypeDate & 0x02)!=0; bool bD120 = (TypeDate & 0x04)!=0; // Если не подошла дата для строки 100 if ( bD100 && (OnePaid.DateIncomedate2) ) return false; if ( bD110 && (OnePaid.DateTaxUddate2) ) return false; if ( bD120 && (OnePaid.DateTaxSenddate2) ) return false; return true; } AddToEnpNoticePersonData(CurIDOrg, dateSend, taxRate, taxRateToMinus, kbkKind, kbkKindToMinus, sumTax) { if ( !IsObject(EnpNoticePersonData) ) return; // в таблице есть корректировка! ее же нужно сделать и тут int curIdOrgCorr = NDFLReportCheckOrgID(CurIDOrg,gIDOrgsSubstitute,gUniqueINN_KPP_OKTMO); var taxElem = EnpNoticePersonData.GetOrAddTaxesElem(CurIDOrg); var taxData = taxElem.TaxData; var taxKey = taxElem.NewTaxKey(); taxKey.TaxKind = 1; // 1 - удержание, -1 - возврат taxKey.Date = dateSend.GetVariantDate(); taxKey.KbkKind = kbkKind; taxKey.TaxRate = taxRate; if ( taxData.ContainsKey(taxKey) ) taxData.Set(taxKey,taxData.Get(taxKey) + sumTax); else taxData.Add(taxKey,sumTax); // todo посмотреть можно ли реализовать через [] if (taxRateToMinus!=0) // вычтем из 0 kbk эту сумму { var taxKey = taxElem.NewTaxKey(); taxKey.TaxKind = 1; // 1 - удержание, -1 - возврат taxKey.Date = dateSend.GetVariantDate(); taxKey.TaxRate = taxRateToMinus; taxKey.KbkKind = kbkKindToMinus; if ( taxData.ContainsKey(taxKey) ) taxData.Set(taxKey,taxData.Get(taxKey) - sumTax); else taxData.Add(taxKey,-sumTax); } } AddToNdfl6PersonRawData(CurIDOrg, dateSend, taxRate, taxRateToMinus, kbkKind, sumTax, to160) { if (!IsObject(Ndfl6v2021PersonRawData)) return; // в таблице есть корректировка! ее же нужно сделать и тут int curIdOrgCorr = NDFLReportCheckOrgID(CurIDOrg,gIDOrgsSubstitute,gUniqueINN_KPP_OKTMO); var rawData = to160? Ndfl6v2021PersonRawData.AddNew160() : Ndfl6v2021PersonRawData.AddNew(); rawData.IdOrg = curIdOrgCorr; rawData.TaxKind = 1; // 1 - удержание, -1 - возврат //todo!!! KZ-3594 Заполнять из ЛС возвращенные суммы налога rawData.Date = dateSend.GetVariantDate(); rawData.KbkKind = kbkKind; rawData.TaxRate = taxRate; rawData.TaxSum = sumTax; if (taxRateToMinus!=0) // вычтем из 0 kbk эту сумму { var rawData = to160? Ndfl6v2021PersonRawData.AddNew160() : Ndfl6v2021PersonRawData.AddNew(); rawData.IdOrg = curIdOrgCorr; rawData.Date = dateSend.GetVariantDate(); rawData.TaxKind = 1; // 1 - удержание, -1 - возврат //todo!!! KZ-3594 Заполнять из ЛС возвращенные суммы налога rawData.KbkKind = 0; rawData.TaxRate = taxRateToMinus; rawData.TaxSum = -sumTax; } } int EnpNoticeStrVznOneTimeTn = -1; AddInfoPart2_6NDFL(IdOrg, &kcp, NumForm, &Tax70,&_DateBeg, &_DateEnd, PaidsExt) { bool bTableReestrNDFL = false; if ( NumForm==60 ) // Таблица 6-НДФЛ Реестр по работникам(в разрезе месяцев учета) { NumForm=6; // Для реестра все аналогично 6-НДФЛ bTableReestrNDFL = true; // нужно только для случая, когда собираем ндфл по доп таблице, суммы // ндфл по ведомости не выбираются (собираем их отдельно в раздел 3) } bool bFillPaids = IsObject(PaidsExt); bool isNoticeENP = NumForm==10; // уведомление ЕНП bool bMassCorrect = NumForm!=6 && NumForm!=8 && !isNoticeENP; // таблицы массовой обработки "выплат" или что-то на их основе bool bTableChangeDatePay = NumForm==67; // Если это спец.таблица для корректировки Id организации bool bTableCorrectIdOrg = NumForm==68; // Таблица с информацией по НДФЛ // ее интересует только НДФЛ и его распределение по ОКТМО // 70,71,72 - выборка НДФЛ без его распределения по доходам // подходит для ситуаций когда нет разбивки ЛС по ОКТМО или если // разбивка происходит по полю КЧ. Для остальных случаев распределения // по ОКТМО эта выборка подойдет, только если для должности/источника/объекта // заведен в ЛС свой вид налога (5хх) bool bTableInfoNDFLByNach = NumForm==71 /*|| (NumForm==70 && GetCommonCnfInt("TaxInfoIdV","payNDFL")==1)*/; bool bTableInfoNDFLByDateVed = NumForm==72 /*|| (NumForm==70 && GetCommonCnfInt("TaxInfoIdV","payNDFL")==2)*/; bool bTableInfoNDFL = NumForm==70 || NumForm==71 || NumForm==72; // Если работаем с таблице корректировки Id организации // То сюда попадаем один раз и все что надо делаем сразу // Отсекаем "внешний" цикл по IdOrg путем обнуления IdOrg if ( bTableCorrectIdOrg ) IdOrg = 0; int lenBuf=1023; char Buf[lenBuf+1]; var MapCodeNU = CreateObject("MapLong"); // Для таблицы разноски месяца выплаты задается набор видов, которые надо принять if ( bTableChangeDatePay ) { char FlagIns=!Str_Cmp(Str_Cod,"***","")?1:0; if ( !FlagIns ) MapCodeNU.Add(Extern_To_Intern(atoi(Str_Cod)),0); else { for ( int iC=0; iC12 ) cntPredMonth = 12; // Сколько захватить дополнительных прошлых месяцев cntFutureMonth = GetCommonCnfInt("Rzd2DopMF","6ndfl"); if ( cntFutureMonth<0 ) cntFutureMonth = 0; if ( cntFutureMonth>12 ) cntFutureMonth= 12; } var DIncome = CreateObject("KDate"); // Дата в строку 100 (дата фактического получения дохода) var DTaxUd = CreateObject("KDate"); // Дата в строку 110 (дата удержания налога) var DTaxSend = CreateObject("KDate"); // Дата в строку 120 (срок перечисления) // Период определяется по дате конца. Месяц начала всегдя январь var d = CreateObject("KDate"); d.SetDate(_DateEnd.GetStr()); int absm2=d.GetAbs(); d.SetDateII(d.CountDay(),absm2); int date2 = d.GetInt(); string strD2 = d.GetStr(); int m2 = d.GetMonth(); GetKchValue("status",Buf,255,d); int StatusForTax = atoi(Buf); // Таблицы массовой обработки вызываем за заданный период, а форму 6-НДФЛ // только с начала года if ( !bMassCorrect ) { d.SetDateIII(1,1,d.GetYear()); int lowBoundMonth = d.GetAbs()-cntPredMonth; if ( lowBoundMonth3 && !bTableReestrNDFL ) { if ( m2>9 ) // годовая d.SetDateIII(1,10,d.GetYear()); else if ( m2>6 ) d.SetDateIII(1,7,d.GetYear()); else d.SetDateIII(1,4,d.GetYear()); strD1 = d.GetStr(); date1 = d.GetInt(); absm1 = d.GetAbs(); } var mTax = CreateObject("KMonth"); // месяц учета в алгоритме налога var mv = CreateObject("KMonth"); // месяц начисления суммы дохода int PaidsUsr=0; // признак того что коллекция заполнялась пользователем // -1 - нет не заполнялась, и не надо больше пытаться. var PaidsDopTbl = CreateObject("PaidIncomeCollection"); PaidsDopTbl.Initial(false); var PaidsTax = CreateObject("PaidIncomeCollection"); int countidx = 2; bool row160by20 = (GetCommonCnfInt("TypeFld70","6ndfl")&0x01)!=0; if (NumForm==8 || NumForm==10) // todo на самом деле "налоговые уведомления" будут отличаться от 6НДФЛ_2021 (из-за дивидендов сверх 5 млн.) { countidx = 3; // idxTax==2 - 206 алгоритм if (row160by20 || NumForm==10) // idxTax==3 - 208 или 210 Дивиденды countidx = StatusForTax<2?5:4; // idxTax==4 - 209 алг выгода (207 ее не видит если статус >2 но учитывает если ==2) if ( NumForm==10 && _DateBeg.GetYear()>2022 ) countidx = 6; // idxTax==5 - 211 алг дивиденды сверх 5 млн. (их видит 206 алгоритм и 205) } // Для налоговых уведомлений нужны еще страховые взносы. int curTn = Poln_Tn%sizetn; if ( NumForm==10 && EnpNoticeStrVznOneTimeTn!=curTn/*(!IdOrg || IdOrg==GetOrgForPodr(Poln_Tn/sizetn))*/ ) { EnpNoticeStrVznOneTimeTn = curTn; // страховые собираем без разбивки по организациям, поэтому берем IdOrg от создаваемого отчета. // Для уведомлений это точно норм, потому что у уведомлений одна основная организация (разбивка блоков НДФЛ по ОКТМО не в счет) int IdOrgActive = MgrGetCurrentManager().Id; // GetOrgForPodr(Poln_Tn/sizetn); int taxRate = 0, taxRateToMinus = 0, kbkKindToMinus=0; var DTaxSend = KDateFromInt_LastDay(_DateBeg.GetAbs()-1); int absm = DTaxSend.GetAbs(); var map = CreateObject("Map"); // решили развести взносы до 2023 года и с 2023 года разными kbkKind if ( DTaxSend.GetYear()>2022 ) { map.Add(100,Oem("А")); // СФР (единый взнос) map.Add(200,Oem("М")); // ФОМС для судей map.Add(300,Oem("Ц")); // ФСС для судей } else { map.Add(2022100,Oem("А")); // ПФ map.Add(2022200,Oem("М")); // ФОМС map.Add(2022300,Oem("Ц")); // ФСС } map.Add(101,Oem("256")); // ПФ Список 1 без спец.оценки map.Add(102,Oem("257")); // ПФ Список 2 без спец.оценки map.Add(103,Oem("261-131,261-132,261-133,261-134,261-140")); // ПФ Список 1 СОУТ map.Add(104,Oem("261-231,261-232,261-233,261-234,261-240")); // ПФ Список 2 СОУТ var _CodAddTaxFlyer=GetCommonCnfStr("ATaxFlyer","rsv2017"); if ( Str_Cmp(_CodAddTaxFlyer,"","") ) map.Add(111,TrimN(_CodAddTaxFlyer)); // ПФ Летчики var _CodAddTaxMiner=GetCommonCnfStr("ATaxMiner","rsv2017"); if ( Str_Cmp( _CodAddTaxMiner,"","") ) map.Add(112,TrimN( _CodAddTaxMiner)); // ПФ Шахтеры for ( map.InitIterator(); !map.IsEnd(); map.Next() ) { int kbkKind = map.GetCurKey(); string strAlg = map.GetCurValue(); var whatTax = 7; double sum = GetSumTaxOneMonth(whatTax, strAlg, absm); if ( nabs(sum)>0.001 ) AddToEnpNoticePersonData(IdOrgActive, DTaxSend, taxRate, taxRateToMinus, kbkKind, kbkKindToMinus, sum); } } // До 2023 дивиденды не выделяли на отдельный kbkKind // В 2023 пока сделали, только для уведомлений по ЕНП // 0 - не выделять, 1 - выделять, -1 - как задумаем по умолчанию int kindTaxDiv = _DateBeg.GetYear()<2023 ? 0 : (NumForm==10?GetCommonCnfInt("KindTaxDiv", "notice"):0); // Из-за ВКС, ЕАЭС и т.п. необходимо организовать двойной цикл. // Так как для статусов больше 2, 205 и 207 алгоритмы не видят друг друга for ( int idxTax = 0; idxTaxabsm2+cntFutureMonth ) absmEnd = absm2+cntFutureMonth; GetPaidIncomes_6NDFL(NumAlg, absmBeg-mtek, absmEnd-mtek); // Для таблицы с информацией по НДФЛ разбивку налогов и переопределение дат не делаем // Не надо делать разбивки по доходам и если выбираем налог для уведомлений if ( !bTableInfoNDFL && NumForm!=10 ) { // Распределяем налог и делаем первоначальное заполнение дат DistributeTax_6NDFL(PaidsTax); UpdateDates_6NDFL(PaidsTax); } } if ( !bTableInfoNDFL ) { // Сначала пробуем получить из пользовательской скриптовой функции: if ( PaidsUsr!=-1 ) PaidsUsr=GetPaidIncomeCollection_6NDFL(NumAlg,absm,PaidsDopTbl); // Если ручное заполнение ничего не дало пробуем получить из доп.таблицы // todo надо научиться получать разные типы налогов // Для уведомлений ЕНП доп.таблицу пока отключаем if ( PaidsUsr<1 && !isNoticeENP ) { PaidsDopTbl.InitialByTableLS(-1,absm,absm,strD1,strD2,4); // Признак выборки из доп.таблицы bByDopTable = PaidsDopTbl.Count()!=0; } for ( int idxTI=0; idxTI0 || TypeDopTable==0 ) { if ( bTableReestrNDFL ) // Только для реестра (выбрать суммы НДФЛ по ведомостям, в случае доп таблиц) DopInfIdVedForReestr(PaidsTax,bTableChangeDatePay,MapCodeNU,IdOrg,ZeroTax,bTableInfoNDFL, TypeDateNDFL,date0,date1,date2,absm,bTableInfoNDFLByDateVed,bTableInfoNDFLByNach,TypeDate, TypeFld70,Tax70,bFillPaids,PaidsExt,kcp,strD1,strD2); break; } else { if ( (TypeDopTable&0x02) != 0 ) bAddRecalcSumFromLS=true; if ( (TypeDopTable&0x01) != 0 ) bAddOtherTypeIncome=true; } } // Если выборка шла не по доп.таблице, то на второй итерации точно нечего делать // В противном случае из ЛС добираем отсутствующие типы доходов. if ( !bByDopTable && idxIter ) break; bool UseDopTbl = PaidsUsr>0 || !(bTableInfoNDFL || bTableChangeDatePay || !bByDopTable || idxIter); var Paids = !UseDopTbl?PaidsTax:PaidsDopTbl; int cnt = Paids.Count(); for ( int i=0; i=TI6NDFL_CNT ) TypeInc = TI6NDFL_OTHER; // Если есть данные в доп.таблице то на первом проходе помечаем встретившиеся // типы доходов. На втором проходе, из ЛС берем только те доходы // которых нет в доп.таблице if ( bByDopTable ) { if ( !idxIter ) bFlagTypeIncDopTable[TypeInc]=true; else { if ( !bAddRecalcSumFromLS ) { if ( bFlagTypeIncDopTable[TypeInc] ) continue; } else { // Если не смотря на наличие доп.таблицы нас попросили добавлять // пересчетные суммы, то добавляем сумму в том случае, если // она пересчетная и настроена на обложение по месяцу принадлежности if ( OnePaid.Month==OnePaid.MonthTax && OnePaid.Month!=OnePaid.MonthV ) ; else if ( !bAddOtherTypeIncome || bFlagTypeIncDopTable[TypeInc] ) continue; } } } if ( bTableChangeDatePay && !MapCodeNU.IsExist(OnePaid.CodeNU) ) continue; double CodeNU = 0.; if ( OnePaid.CodeNU>0. ) CodeNU = GetFullCodeNU(OnePaid.CodeNU,OnePaid.Extension); // Код организации действующий "сейчас" (нужен для таблицы // проверяющий корректность разнесенных idOrg) int IdOrgActive = IdOrg?IdOrg:GetOrgForPodr(Poln_Tn/sizetn); bool bNeedDefineActiveIdOrg = bTableCorrectIdOrg && bByDopTable; int CurIDOrg = OnePaid.ID_Org; // Определяем CurIDOrg по полю КЧ или совместительству, если еще не определен // Или если нам нужна сверка того что есть (в доп.таблице) и того что сейчас было бы // если бы в доп.таблице не было данных if ( (!CurIDOrg || bNeedDefineActiveIdOrg) && gTypeOKTMO_NDFL ) IdOrgActive = DefineIdOrgForIncome(gTypeOKTMO_NDFL,absm,CodeNU); if ( !CurIDOrg ) CurIDOrg=IdOrgActive; OnePaid.ID_Org=CurIDOrg; /* int IncomeCode = OnePaid.IncomeCode; double SumT = OnePaid.SumTax; double Sum = OnePaid.Sum; int di = OnePaid.DateIncome; int du = OnePaid.DateTaxUd; int idved = OnePaid.IdVed; int idorg = OnePaid.ID_Org; du = du; */ // Отсеиваем суммы не попадающие в отчет if ( IdOrg && CurIDOrg && IdOrg!=CurIDOrg ) continue; // Для уведомления isNoticeENP это вредная настройка if ( !isNoticeENP && ZeroTax==1 && nabs(OnePaid.SumTax)<1 ) continue; // Если это налог то его пропускаем (он уже д.б. распределен) // Для таблице с инфой о налоге (без разбивки по доходам) наоборот // нужна информация только о строчках налога if ( (!bTableInfoNDFL && NumForm!=10 && OnePaid.IncomeCode==0) || ((bTableInfoNDFL || NumForm==10) && OnePaid.IncomeCode!=0)) continue; DIncome.SetInt(OnePaid.DateIncome); DTaxUd.SetInt(OnePaid.DateTaxUd); // Для накопления удержанного НДФЛ Накапливаем всегда. // Какой из удержанных налогов взять, решает сама форма if ( NumForm!=10 && CheckDateOnePay_6NDFL(TypeDateNDFL,OnePaid,date0,date2,absm) ) { if ( (TypeFld70 & 0x02)==0 || DTaxUd.GetYear()==DIncome.GetYear() ) { Tax70 += OnePaid.SumTax; if (row160by20 && nabs(OnePaid.SumTax)>0.001) AddToNdfl6PersonRawData(CurIDOrg, DTaxUd, taxRate, taxRateToMinus, kbkKind, OnePaid.SumTax, true); } } // Для таблицы уведомлений все "непросто": // - страховые взносы за предыдущий месяц (выбираются проще, см. до цикла по idxTax) // - НДФЛ для января с 1 по 22 // - НДФЛ для остальных месяцев с 23 предыдущего по 22 текущего // - у декабря есть еще период с 23-го по 31 todo!!! if ( NumForm==10 ) { if ( OnePaid.IdVed>0 ) d.SetDate(GetKassVedInfo(OnePaid.IdVed, 0)); else if ( OnePaid.DateTaxUd!=0 ) d.SetInt(OnePaid.DateTaxUd); else d = KDateFromInt_LastDay(OnePaid.Month); // todo? плановая дата выплата для налога не захваченными ведомостями? var date = _DateBeg; // месяц для сборки уведомления var dfirst,dsecond; if ( date.GetMonth()==1 ) { dfirst = KDateFromInt_WithDay(1,date.GetAbs()); dsecond = KDateFromInt_WithDay(22,date.GetAbs()); } //else if ( date.GetMonth()==12 && типрасчета - последний за год ) // todo!!! тут надо условие определяющее отчет за последний период декабря //{ // dfirst = KDateFromInt_WithDay(23,date.GetAbs()); // dsecond = KDateFromInt_WithDay(31,date.GetAbs()); //} else // для всех остальных { dfirst = KDateFromInt_WithDay(23,date.GetAbs()-1); dsecond = KDateFromInt_WithDay(22,date.GetAbs()); } if ( d.LT(dfirst) || d.GT(dsecond) ) continue; OnePaid.DateTaxUd = d.GetInt(); DTaxUd.SetInt(OnePaid.DateTaxUd); } // Для таблицы с информацией по удержанному ведомостями налогу ориентируемся на дату ведомости // для всех остальных на "триаду" дат else if ( !bTableInfoNDFLByNach && (!bTableInfoNDFLByDateVed || OnePaid.IdVed<=0) ) { if ( !CheckDateOnePay_6NDFL(TypeDate,OnePaid,date1,date2,absm) ) continue; } else if ( bTableInfoNDFLByDateVed ) // таблица с информацией об удержанном налоге c фильтрацией по дате ведомости { d.SetDate(GetKassVedInfo(OnePaid.IdVed, 0)); int am = d.GetAbs(); if ( amabsm2 ) continue; } else if ( bTableInfoNDFLByNach ) { int am = OnePaid.MonthV; if ( amabsm2 ) continue; } DTaxSend.SetInt(OnePaid.DateTaxSend); if ( bFillPaids ) PaidsExt.PushBack(OnePaid); if (IsObject(Ndfl6v2021PersonRawData)) { if (nabs(OnePaid.SumTax)<0.001) continue; // 6-НДФЛ 2021 собирается с информацией о сроке перечисления AddToNdfl6PersonRawData(CurIDOrg, DTaxSend, taxRate, taxRateToMinus, kbkKind, OnePaid.SumTax, false); } else if ( IsObject(EnpNoticePersonData) ) { if (nabs(OnePaid.Sum)<0.001) continue; // Уведомления ЕНП собираются с информацией о дате удержания AddToEnpNoticePersonData(CurIDOrg, DTaxUd, taxRate, taxRateToMinus, kbkKind, kbkKindToMinus, OnePaid.Sum); } else { sprintf(Buf,"%-d,2,%s,%s,%s,%.2f,%.0f,%d,%d,%d,%d,%d,%d,%f,%d,%d,%d",CurIDOrg,DIncome.GetStr(),DTaxUd.GetStr(),DTaxSend.GetStr(), OnePaid.Sum,OnePaid.SumTax,Paids.TypeIncome(i),OnePaid.MonthTax,OnePaid.IdVed,Paids.ID_Income(i),OnePaid.Month,OnePaid.MonthV,CodeNU,IdOrgActive, UseDopTbl?1:0,// налог из доп.таблицы (OnePaid.IncomeCode==-1&&nabs(OnePaid.Sum)<1)?1:0); //нераспределенная сумма налога kcp.AddPeriod(to_string(Buf),strD1,strD2); // признак приема в раздел2 в старой форме ("уплаты") - ненулевые OnePaid.Sum,OnePaid.SumTax } } // for ( int i=0; i=TI6NDFL_CNT ) TypeInc = TI6NDFL_OTHER; if ( bTableChangeDatePay && !MapCodeNU.IsExist(OnePaid.CodeNU) ) continue; double CodeNU = 0.; if ( OnePaid.CodeNU>0. ) CodeNU = GetFullCodeNU(OnePaid.CodeNU,OnePaid.Extension); // Код организации действующий "сейчас" (нужен для таблицы // проверяющий корректность разнесенных idOrg) int IdOrgActive = IdOrg?IdOrg:GetOrgForPodr(Poln_Tn/sizetn); bool bNeedDefineActiveIdOrg = false;//bTableCorrectIdOrg && bByDopTable; int CurIDOrg = OnePaid.ID_Org; // Определяем CurIDOrg по полю КЧ или совместительству, если еще не определен // Или если нам нужна сверка того что есть (в доп.таблице) и того что сейчас было бы // если бы в доп.таблице не было данных if ( (!CurIDOrg || bNeedDefineActiveIdOrg) && gTypeOKTMO_NDFL ) IdOrgActive = DefineIdOrgForIncome(gTypeOKTMO_NDFL,absm,CodeNU); if ( !CurIDOrg ) CurIDOrg=IdOrgActive; OnePaid.ID_Org=CurIDOrg; // Отсеиваем суммы не попадающие в отчет if ( IdOrg && CurIDOrg && IdOrg!=CurIDOrg ) continue; if ( ZeroTax==1 && nabs(OnePaid.SumTax)<1 ) continue; // Если это налог то его пропускаем (он уже д.б. распределен) // Для таблице с инфой о налоге (без разбивки по доходам) наоборот // нужна информация только о строчках налога if ( (!bTableInfoNDFL && OnePaid.IncomeCode==0) || (bTableInfoNDFL && OnePaid.IncomeCode!=0)) continue; DIncome.SetInt(OnePaid.DateIncome); DTaxUd.SetInt(OnePaid.DateTaxUd); // Для накопления удержанного НДФЛ Накапливаем всегда. // Какой из удержанных налогов взять, решает сама форма if ( CheckDateOnePay_6NDFL(TypeDateNDFL,OnePaid,date0,date2,absm) ) { if ( (TypeFld70 & 0x02)==0 || DTaxUd.GetYear()==DIncome.GetYear() ) Tax70 += OnePaid.SumTax; } // Для таблицы с информацией по удержанному ведомостями налогу ориентируемся на дату ведомости // для всех остальных на "триаду" дат if ( !bTableInfoNDFLByNach && (!bTableInfoNDFLByDateVed || OnePaid.IdVed<=0) ) { if ( !CheckDateOnePay_6NDFL(TypeDate,OnePaid,date1,date2,absm) ) continue; } else if ( bTableInfoNDFLByDateVed ) // таблица с информацией об удержанном налоге c фильтрацией по дате ведомости { d.SetDate(GetKassVedInfo(OnePaid.IdVed, 0)); int am = d.GetAbs(); if ( amabsm2 ) continue; } else if ( bTableInfoNDFLByNach ) { int am = OnePaid.MonthV; if ( amabsm2 ) continue; } DTaxSend.SetInt(OnePaid.DateTaxSend); if ( bFillPaids ) PaidsExt.PushBack(OnePaid); if (OnePaid.IdVed==0) continue; sprintf(Buf,"%-d,3,%s,%s,%s,%.2f,%.0f,%d,%d,%d,%d,%d,%d,%f,%d,0,0",CurIDOrg,DIncome.GetStr(),DTaxUd.GetStr(),DTaxSend.GetStr(), OnePaid.Sum,OnePaid.SumTax,Paids.TypeIncome(i),OnePaid.MonthTax,OnePaid.IdVed,Paids.ID_Income(i),OnePaid.Month,OnePaid.MonthV,CodeNU,IdOrgActive); kcp.AddPeriod(to_string(Buf),strD1,strD2); } // for ( int i=0; i=0 && kch_comb(numKCH) ) // gTypeOKTMO_NDFL=5; } // по полю КЧ if ( gTypeOKTMO_NDFL == 1 || gTypeOKTMO_NDFL == 5 ) { bool bMassCorrect = NumForm!=6 && NumForm!=8 && NumForm!=10; // Сколько захватить дополнительных прошлых месяцев int cntPredMonth = 0; // Дата "начала" периода с учетом смещения для второго раздела var DateBeg00 = CreateObject("KDate"); DateBeg00.SetInt(DateBeg.GetInt()); // Для 6-НДФЛ 2021 сюда должны попадать. Основной смысл этого блока: не забыть захватить переходящие с прошлых годов суммы удержанного НДФЛ. if ( !bMassCorrect && !b2NDFL ) // todo!!! KZ-3562 дописать условие и проверить как это повлияет на 2НДФЛ внтури 6НДФЛ2021 { // Сколько захватить дополнительных прошлых месяцев cntPredMonth = GetCommonCnfInt("Rzd2DopM","6ndfl"); if ( cntPredMonth<0 ) cntPredMonth = 0; if ( cntPredMonth>12 ) cntPredMonth = 12; if ( cntPredMonth ) DateBeg00.SetDateII(DateBeg.GetDay(),DateBeg.GetAbs()-cntPredMonth); } var CL=CreateObject("CombineList"); var it = CL.CreateIterator(); for (it.SetBegin();!it.IsEnd();it.Next()) //цикл по совместительствам ( it.CurKey() - внутр.код совместительства ) { long Combine = gTypeOKTMO_NDFL==1?CL.GetBaseID():it.CurKey(); var tmp_comb = CreateObject("TmpCurCombine"); tmp_comb.InitSimple(Combine); // Получим все возможные "подразделения" из поля КЧ var PodrPeriods; KchToPeriods(ps_kch,DateBeg00.GetStr(),DateEnd.GetStr(),0,PodrPeriods); //периоды, для которых не заполнен код подразделения нас не интересуют.. PodrPeriods.ClearCod("#emptystring#"); // условное слово для очистки именно "пустых кодов" // в КЧ могут быть заполнены не все периоды из отчетного, для отсутствующих периодов // нам надо поставить подразделение ЛС var FreePeriods = CreateObject("KDatePeriods"); FreePeriods.AddFreePeriods(PodrPeriods); { int podr = CL.GetPodr(Combine); // подразделение выбранного совм-ва // Берем основное подразделение ЛС если для совместительства подразделение не указано, или если // разбивка просто по полям КЧ (т.к. для простой разбивки по КЧ всегда учитывалось подразделение где располагается ЛС) if (!podr || gTypeOKTMO_NDFL==1) podr = Poln_Tn/sizetn; // В том случае если работаем без конвертации подразделение-организация // надо сразу сделать конвертацию, т.к. GetOrgIDByKch ее делать не будет if ( bCodOrgKch ) podr = GetOrgForPodr(podr); FreePeriods.Invert(DateBeg00.GetStr(),DateEnd.GetStr(),to_string(podr)); PodrPeriods.UpdatePeriods(FreePeriods,to_string(podr)); } // По подразделениям получим коды организаций var OrgPeriods = CreateObject("KDatePeriods"); for ( PodrPeriods.SetBegin(); !PodrPeriods.End(); PodrPeriods.Next() ) { string strPodr = PodrPeriods.GetCurCod(); long idOrg = DefineOrgByKchValue(strPodr,bStringKch,bCodOrgKch); OrgPeriods.AddFreePeriod(PodrPeriods.GetCurBeg().GetStr(),PodrPeriods.GetCurEnd().GetStr(),to_string(idOrg)); } int order=1; // сейчас не надо в обратном порядке поэтому с 1, раньше обходили в обратном порядке 1000000; var Date1=CreateObject("KDate"); // для раздела 1 // Список организаций, по которым был найден удержанный НДФЛ в разделе 2, то есть их надо показать и в разделе 1 // даже если сама организация в отчетном периоде уже отсутствовала (то есть удерживался НДФЛ прошлого периода) var MapOrgWithTax70InPart2=CreateObject("Map"); // просматриваем все найденные значения idOrg, действовавшие в заданный период for ( OrgPeriods.SetBegin(); !OrgPeriods.End(); OrgPeriods.Next() ) { int idOrg = atoi(OrgPeriods.GetCurCod()); var Date = OrgPeriods.GetCurBeg(); if ( !Date.IsValid() || Date.LT(DateBeg00) ) Date.SetInt(DateBeg00.GetInt()); var DateEndKch = OrgPeriods.GetCurEnd(); if ( !DateEndKch.IsValid() || DateEndKch.GT(DateEnd) ) DateEndKch.SetInt(DateEnd.GetInt()); Date1.SetInt(Date.GetInt()); // В том случае если нам надо захватить сколько-то прошлых месяцев // для раздела 2, то отдельно делаем еще контроль для даты первого раздела if ( cntPredMonth && Date1.LT(DateBeg) ) Date1.SetInt(DateBeg.GetInt()); if ( b2NDFL ) { // Раньше order был нужен, из-за того что поля КЧ находили "задом наперед", а для 2-НДФЛ было критичным, чтобы // периоды шли строко по возрастанию. Сейчас периоды идут в нужном порядке, но order все равно пришлось оставить. // во-первых чтобы не править остальной код, во-вторых без order сортировка произойдет по коду организации // sprintf(Buf,"%10d,%s",order--,GetKeyForFormNDFL(idOrg,NumForm,0)); if ( gTypeOKTMO_NDFL==5 ) sprintf(Buf,"%10d,%s,%d",order++,GetKeyForFormNDFL(idOrg,NumForm,0),Combine); else sprintf(Buf,"%10d,%s",order++,GetKeyForFormNDFL(idOrg,NumForm,0)); kcp.AddPeriod(to_string(Buf),Date1.GetStr(),DateEndKch.GetStr()); } else { double Tax70=0.; AddInfoPart2_6NDFL(idOrg, kcp, NumForm,Tax70,DateBeg,DateEnd,0); if ( nabs(Tax70)>0.001 ) MapOrgWithTax70InPart2.Add(idOrg,Tax70); if ( NumForm==6 || NumForm==8) // 66 // todo KZ-3562 правильно ли сюда заходить и получается что пропустили условие выше^^ { // todo KZ-3562 что это? проверить другие kcp.AddPeriod // Добавляем строчку в раздел 1 если ее можно добавлять // Если дата конца текущего периода из-за того что рассматриваем со смещением ДО даты начала отчетного периода, то // такой период нам НЕ нужен в разделе 1 if ( DateEndKch.IsValid() && DateEndKch.GT(Date1) ) { // Если в списке организаций с удержанным НДФЛ за период, есть запись, оттуда не забываем взять сумму удержанного НДФЛ if ( MapOrgWithTax70InPart2.IsExist(idOrg) ) { Tax70 = MapOrgWithTax70InPart2.GetValue(idOrg); MapOrgWithTax70InPart2.Delete(idOrg); } if ( NumForm!=8 ) { if ( gTypeOKTMO_NDFL==5 ) sprintf(Buf,"%s,%d",GetKeyForFormNDFL(idOrg,NumForm,Tax70),Combine); else sprintf(Buf,"%s",GetKeyForFormNDFL(idOrg,NumForm,Tax70)); } else // 6-НДФЛ 2021 построен на базе таблицы 2-НДФЛ { if ( gTypeOKTMO_NDFL==5 ) sprintf(Buf,"%10d,%s,%d",order++,GetKeyForFormNDFL(idOrg,NumForm,0),Combine); else sprintf(Buf,"%10d,%s",order++,GetKeyForFormNDFL(idOrg,NumForm,0)); } kcp.AddPeriod(to_string(Buf),Date1.GetStr(),DateEndKch.GetStr()); } } } } // Если мы заполняем форму 6-НДФЛ, то надо убедиться, что мы уже удержанный налог добавили в раздел 2 формы if ( NumForm==6 ) // 66 // todo KZ-3562 if (NumForm==8) заполнить Ndfl6v2021PersonRawData ?? { for ( MapOrgWithTax70InPart2.InitIterator(); !MapOrgWithTax70InPart2.IsEnd(); MapOrgWithTax70InPart2.Next() ) { int idOrg = MapOrgWithTax70InPart2.GetCurKey(); double Tax70 = MapOrgWithTax70InPart2.GetCurValue(); if ( nabs(Tax70)>0.001 ) { if ( gTypeOKTMO_NDFL==5 ) sprintf(Buf,"%s,%d",GetKeyForFormNDFLWhenOnlyTaxExist(idOrg,NumForm,Tax70),-1); else sprintf(Buf,"%s",GetKeyForFormNDFLWhenOnlyTaxExist(idOrg,NumForm,Tax70)); kcp.AddPeriod(to_string(Buf),DateBeg.GetStr(),DateEnd.GetStr()); } } } if ( gTypeOKTMO_NDFL == 1 ) break; } // for (it.SetBegin();!it.IsEnd();it.Next()) //цикл по совместительствам ( it.CurKey() - внутр.код совместительства ) } else if ( gTypeOKTMO_NDFL == 2 ) { var CL=CreateObject("CombineList"); var it = CL.CreateIterator(); for (it.SetBegin();!it.IsEnd();it.Next()) //цикл по совместительствам ( it.CurKey() - внутр.код совместительства ) { long Combine =it.CurKey(); double Tax70=0.; if ( NumForm!=2 ) // 66 Вторая часть, для всего кроме 2-НДФЛ AddInfoPart2_6NDFL(GetOrgIDByCombine_NDFL(Combine), kcp, NumForm,Tax70,DateBeg,DateEnd,0); if ( NumForm==6 || NumForm==2 || NumForm==8 ) // 66 Только для 2-НДФЛ и 6-НДФЛ, для вспомогательных таблиц не надо kcp.AddPeriod(GetKeyForFormNDFL(Combine,NumForm,Tax70),DateBeg.GetStr(),DateEnd.GetStr()); } } else if ( gTypeOKTMO_NDFL == 3 ) { var APropArr=CreateObject("APropArray"); APropArr.GetPropListLS(); var listSrc=APropArr.GetSources(); int cntSrc = GetUBound(listSrc)+1; char gSrc = GetGeneralSrcLS(); // GetGeneralSubjectLS for (int idxSrc=0; idxSrc0.?Intern_To_ExternE(cod):0; } GetCurrentActiveIdOrg_6NDFL() { var kcp = CreateObject("KPeriodsIterations"); string key = kcp.GetCurCod(); int id= atoi(SplitStr(key,",")[14]); return id?id:GetOrgForPodr(Poln_Tn/sizetn); } GetCurrentMonth_Reestr() { var kcp = CreateObject("KPeriodsIterations"); string key = kcp.GetCurCod(); int m= atoi(SplitStr(key,",")[8]); var Month = CreateObject("KMonth"); Month.SetMonth(m); return Month.GetStr(); } GetCurrentRelMonth_Reestr() { var kcp = CreateObject("KPeriodsIterations"); string key = kcp.GetCurCod(); int m= atoi(SplitStr(key,",")[8]); var Month = CreateObject("KMonth"); Month.SetMonth(m); return Month.GetRel(); } GetCurrentTaxDopTbl_Reestr() { var kcp = CreateObject("KPeriodsIterations"); string key = kcp.GetCurCod(); return atoi(SplitStr(key,",")[15]); } GetCurrentTaxUndistr_Reestr() { var kcp = CreateObject("KPeriodsIterations"); string key = kcp.GetCurCod(); return atoi(SplitStr(key,",")[16]); } GetSrcByDopTable(_Tn,_ID) { int Tn = atoi(_Tn); int ID = atoi(_ID); if ( !Tn || !ID ) return ""; var Tbl = CreateObject("CurPrnTbl"); Tbl.InitialAdditionalRefLS(NDFL6_DOP_TABLE,Tn); int FldId = Tbl.Find_Name_Fld("ID"); int FldSrc = Tbl.Find_Name_Fld("Src"); if ( FldId==-1 || FldSrc==-1 ) return ""; int Rcr = Tbl.Find_Db(0,Tbl.Count_Rcr()-1,to_string(_ID),FldId); if ( Rcr==-1 ) return ""; string Src = Tbl.Text(FldSrc,Rcr); FreeSpaceString(Src,3,""); return Src; } GetSubjectByDopTable(_Tn,_ID) { int Tn = atoi(_Tn); int ID = atoi(_ID); if ( !Tn || !ID ) return ""; var Tbl = CreateObject("CurPrnTbl"); Tbl.InitialAdditionalRefLS(NDFL6_DOP_TABLE,Tn); int FldId = Tbl.Find_Name_Fld("ID"); int FldSubject = Tbl.Find_Name_Fld("Subject"); if ( FldId==-1 || FldSubject==-1 ) return ""; int Rcr = Tbl.Find_Db(0,Tbl.Count_Rcr()-1,to_string(_ID),FldId); if ( Rcr==-1 ) return ""; string Src = Tbl.Text(FldSubject,Rcr); FreeSpaceString(Src,3,""); return Src; } var Ndfl6v2021PersonRawData; // Функция организующая цикл для заполнения формы 6-НДФЛ 2021 // с разбивкой по ОКТМО EnterpriseID2CodPeriods_6NDFL2021() // один раз на весь ЛС! наполняет KPeriodsIterations теми же ключами что были для 2НДФЛ плюс добавляет записи в mainMgr.AddPersonRawData { var Tbl = CreateObject("CurPrnTbl"); Tbl.Initial(Tbl.GetAdr()); // очень важно! т.к. по умолчанию CurPrnTbl работает по ссылке с глобальной меременной! которая при работе с несколькими таблицами может меняться var mainMgr = MgrInitMainManager(Tbl); Ndfl6v2021PersonRawData = mainMgr.CreatePersonRawData(); int rc = DefineEnterpriseID_NDFLCommon(8); if (rc!=ESC) mainMgr.AddPersonRawData(Ndfl6v2021PersonRawData); // может сворачивать по лицевому по ключевым полям чтобы не расходовать память Ndfl6v2021PersonRawData = GetEmpty(); return rc; } var EnpNoticePersonData; // персон-дата для налоговых уведомлений // Функция организующая сбор информации для налоговый уведомлений 2023 // с разбивкой по ОКТМО // EnterpriseIDCodPeriods_EnpNotice() // один раз на весь ЛС! наполняет KPeriodsIterations теми же ключами что были для 2НДФЛ плюс добавляет записи в mainMgr.AddPersonRawData // { // var Tbl = CreateObject("CurPrnTbl"); // Tbl.Initial(Tbl.GetAdr()); // очень важно! т.к. по умолчанию CurPrnTbl работает по ссылке с глобальной меременной! которая при работе с несколькими таблицами может меняться // var mainMgr = MgrInitMainManager(Tbl); // // EnpNoticePersonData = mainMgr.CreatePersonData(); // // int rc = DefineEnterpriseID_NDFLCommon(10); // // EnpNoticePersonData = GetEmpty(); // return rc; // } EnpNoticeFillPersonDataTaxes(persData) { EnpNoticePersonData = persData; int rc = DefineEnterpriseID_NDFLCommon(10); EnpNoticePersonData = GetEmpty(); } DefineEnterpriseID_NDFLCommon(NumForm) { var D1 = KDateFromStr(Str_Date_0); D1.ImproveDay(); var D2 = KDateFromStr(Str_Date_1); D2.ImproveDay(); D2.SetDateII(D2.CountDay(),D2.GetAbs()); // UnloadScriptModule("forms\\DefineEnterpriseID"); // LoadScriptModule("forms\\DefineEnterpriseID"); var rc = DefineEnterpriseID_NDFL(D1,D2,NumForm); // UnloadScriptModule("forms\\DefineEnterpriseID"); return rc; } // Функция организующая цикл заполнения для формы 6-НДФЛ EnterpriseID2CodPeriods_6NDFL() { return DefineEnterpriseID_NDFLCommon(6); } // Функция организующая цикл заполнения для формы 6-НДФЛ Реестр по работникам(в разрезе месяцев учета) EnterpriseID2CodPeriods_6NDFLReestr() { return DefineEnterpriseID_NDFLCommon(60); } // Функция организующая цикл для таблиц готовящих данные // по разделу 2 формы 6-НДФЛ для доп.таблицы в ЛС EnterpriseID2CodPeriods_66NDFL() { return DefineEnterpriseID_NDFLCommon(66); } // Функция организующая цикл заполнения для спец.таблички, занимающейся // разноской дат выплаты в суммы в лицевом счете EnterpriseID2CodPeriods_67NDFL() { return DefineEnterpriseID_NDFLCommon(67); } // Функция организующая цикл заполнения для спец.таблички, // c Ё­д®а¬ жЁҐ© ®Ў Ќ„”‹ EnterpriseID2CodPeriods_70NDFL() { return DefineEnterpriseID_NDFLCommon(70); } // То же самое что и EnterpriseID2CodPeriods_70NDFL(), только // фильтрация идет не по месяцу принадлежности суммы налога, а по дате ведомости EnterpriseID2CodPeriods_72NDFL() { return DefineEnterpriseID_NDFLCommon(72); } // То же самое что и EnterpriseID2CodPeriods_70NDFL(), только // фильтрация идет не по месяцу принадлежности суммы налога, а по месяцу начисления EnterpriseID2CodPeriods_71NDFL() { return DefineEnterpriseID_NDFLCommon(71); } // Функция организующая цикл для заполнения формы 2-НДФЛ // с разбивкой по ОКТМО EnterpriseID2CodPeriods_2NDFL() { return DefineEnterpriseID_NDFLCommon(2); } // Функция организующая цикл заполнения для спец.таблички, занимающейся // сверкой IdOrg EnterpriseID2CodPeriods_68NDFL() { return DefineEnterpriseID_NDFLCommon(68); } GetPaidIncomeCollection_6NDFL(NumAlg,absm,&Paids) // самостоятельное заполнение коллекции выплат // возвращает кол-во элементов в коллекции или -1 - если "ручного" заполнения нет. { return PriorityCall("UsrGetPaidIncomeCollection_6NDFL","SysGetPaidIncomeCollection_6NDFL",NumAlg,absm,Paids); } SysGetPaidIncomeCollection_6NDFL(NumAlg,absm,&Paids) { Paids.Clear(); return -1; } DistributeTax_6NDFL(&PaidsTax) { return PriorityCall("UserDistributeTax_6NDFL","SysDistributeTax_6NDFL",PaidsTax); } SysDistributeTax_6NDFL(&PaidsTax) { PaidsTax.DistributeTax(); } UpdateDates_6NDFL(&PaidsTax) { return PriorityCall("UserUpdateDates_6NDFL","SysUpdateDates_6NDFL",PaidsTax); } SysUpdateDates_6NDFL(&PaidsTax) { PaidsTax.UpdateDates(); } GetDateKassVed(IdVed) { var D = CreateObject("KDate"); if ( IdVed ) { var cvl = CreateObject("CashVedInfoList"); var cashVedInfo = cvl.GetVedInfo(IdVed); if ( !IsNothing(cashVedInfo) && IsObject(cashVedInfo) ) D.SetInt(cashVedInfo.Date()); } return D.GetStr(); } IsNewIDOrg(_idOrg, pfReportParams) { // Если нулевки нам не нужны, то и возвращать признак, что это новая // организация не будем int FlagZeroReport = GetCommonCnfInt("ZeroReport","6ndfl"); if ( FlagZeroReport==0 ) return 0; // Нулевки можно отдельно отключать для старого и нового интерфейса отчетности bool bNeedZeroForNew = (FlagZeroReport & 0x01)!=0; bool bNeedZeroForOld = (FlagZeroReport & 0x02)!=0; bool bNewRegim = IsObject(pfReportParams); if ( (!bNeedZeroForNew && bNewRegim) || (!bNeedZeroForOld && !bNewRegim ) ) return 0; long idOrg = atol(to_string(_idOrg)); if ( !IsObject(gFirstTimeIdOrg) ) gFirstTimeIdOrg = CreateObject("MapLong"); if ( gFirstTimeIdOrg.IsExist(idOrg) ) return 0; gFirstTimeIdOrg.Add(idOrg,idOrg); return 1; } int TypeNumeration2NDFL = 0; // 0 - по-порядку, 1 - табельный номер, 2 - ID лицевого счета GetNumber2NDFL(strTN,LsID,OrgID,CurrentNumber) { if ( TypeNumeration2NDFL==1 ) return atoi(strTN); if ( TypeNumeration2NDFL==2 ) return atoi(LsID); // Если хотим порядковую нумерацию, то из-за фильтрации // ее лучше сделать по окончании формирования таблицы return CurrentNumber; // GetNumber2NDFLByOrgID(OrgID); } // Номер поля для сохранения порядка записи (требуется для нового интерфейса) int fld2NDFLNeedRestoreOrderRow = -1; // учет последнего присвоенного номера справки с разбивкой по организациям var Numbers2NDFLByOrgID = CreateObject("MapLong"); InitNumbers2NDFLByOrgID(AdrTbl,psOrgID, psNum) { Numbers2NDFLByOrgID.Clear(); if ( AdrTbl!=0 ) { var T = CreateObject("CurPrnTbl"); T.Initial(AdrTbl); int FldOrg = T.Find_Name_Fld(psOrgID); int FldNum = T.Find_Name_Fld(psNum); int InitialNumber = atoi(StrNumDoc)-1; if ( FldNum!=-1 ) for ( int Rcr=0; RcrCurNum ) Numbers2NDFLByOrgID.Add(OrgID,Num); } } } GetNumber2NDFLByOrgID(OrgID) { int StartNumber = atoi(StrNumDoc)-1; int Number = StartNumber; // именно так! Сначала инициализируем, потом присваиваем значение из мэпа. // если в мэпе ключа не будет, он значение переменной не меняет! Number = Numbers2NDFLByOrgID.GetValue(OrgID); if ( Number Месяц конца EndMonth C 10 /0 R_Date(4) > Абс. месяц конца ABMES N 5 /0 МЕС(7,EndMonth); > Дата концапериода DKP C 10 /0 var m=CreateObject("KMonth");m.SetMonth(atoi(ABMES));var d=CreateObject("KDate");d.SetDateIM(m.CountDay(),m);return d.GetStr(); * Номер раздела формы NR N 1 /0 DefineCodPeriods(EnterpriseID2CodPeriods_6NDFL);SCRIPT(return GetCurrentPart6NDFL();) подpазделение FCpodr C 10 /0 R_Face(podr,DKP,0 ) Подразделение НДФЛ NalPodr N 10 /0 return GetCurrentOrgID_6NDFL(); * ID обособл. подразделе IDDepart N 5 /0 int depId = atoi(NalPodr); if (!depId) depId=GetOrgForPodr(atoi(FCpodr)); CorrectDepartmentId(depId, __SilentParam); AddDepartmentIdToTable(depId, ABMES, __SilentParam); return depId; ID ведомости IDVed C 15 /0 if (atoi(NR)!=2) return 0; return GetCurrentIDVed_6NDFL(); ID типа дохода IDTypeInc C 3 /0 if (atoi(NR)!=2) return 0; return GetCurrentIDTypeIncome_6NDFL(); * Дата фактического получения доходаFld100 D 10 /0 if (atoi(NR)!=2) return " . . "; return GetCurrent100_6NDFL(); * Дата удержания налога Fld110 D 10 /0 if (atoi(NR)!=2) return " . . "; return GetCurrent110_6NDFL(); * Срок перечисления налога Fld120 D 10 /0 if (atoi(NR)!=2) return " . . "; return GetCurrent120_6NDFL(); + Сумма полученного дохода Fld130 N 14 /2 if (atoi(NR)!=2) return 0.; return GetCurrent130_6NDFL(); + Сумма удержанного налога Fld140 N 14 /2 if (atoi(NR)!=2) return 0.; return GetCurrent140_6NDFL(); Статус STAT_KCH C 2 /0 R_Face(status,DKP,0); IF(_EQ(STAT_KCH)@R_C(1)@R_C(STAT_KCH)) > Статусдля таблиц STATUS C 2 /0 return atoi(STAT_KCH)<3 || GetCommonCnfInt("Status_Nal", "r0alg") ? STAT_KCH : 1; + Начисленный доход - дивидендFld20_div N 14 /2 IF(_NE(NR-1)@R_C(0)@R_Tax(1,1,*,*,Источник выплаты,*,С)) + Вычеты - дивиденды Fld30_div N 14 /2 if (atoi(NR)!=1) return 0.;return atof(Fld20_div)-TaxValue(4); + Авансовые платежи - дивидендFld50_div N 14 /2 if (atoi(NR)!=1) return 0.;return 0.; + Исчисленный налог - дивидендFld40_div N 14 /2 if (atoi(NR)!=1) return 0.;return TaxValue(7); + Удержанный налог - дивидендFld70_div N 14 /2 if (atoi(NR)!=1) return 0.;return TaxValue(13); + Начисленный доход - 35% Fld20_35 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)>1) return 0.; return R_TaxSc1(1,"*","*",'Ф',__W,__A); + Вычеты - 35% Fld30_35 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)>1) return 0.; return atof(Fld20_35)-TaxValue(4); + Исчисленный налог - 35% Fld40_35 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)>1) return 0.; return TaxValue(7); + Авансовые платежи - 35% Fld50_35 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)>1) return 0.; return TaxValue(163); + Удержанный налог - 35% Fld70_35 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)>1) return 0.; return TaxValue(13); + Начисленный доход - 13% Fld20_13 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==2) return 0.; return atof(R_TaxSc11(1,"*","*",-205,__W,__A)) - (atoi(STATUS)<2?atof(Fld20_35):0.); + в т.ч. дивиденды - 13% Fld25_13 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)!=1) return 0.;return atof(Fld20_div); + Вычеты - 13% Fld30_13 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==2) return 0.;return TaxValue(1)-TaxValue(4) - (atoi(STATUS)<2?atof(Fld30_35):0.); + Авансовые платежи - 13% Fld50_13 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==2) return 0.;return TaxValue(162); + Исчисленный налог - 13% Fld40_13 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==2) return 0.;return TaxValue(7) - (atoi(STATUS)<2?atof(Fld40_35):0.); + в т.ч. налог сдивидендов - 13% Fld45_13 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)!=1) return 0.; return atof(Fld40_div); + Удержанный налог - 13% Fld70_13 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==2) return 0.;return TaxValue(13)-(atoi(STATUS)<2?atof(Fld70_35):0.); + Начисленный доход - 15% Fld20_15 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==1) return 0.;return atof(Fld20_div); + в т.ч. дивиденды - 15% Fld25_15 N 14 /2 R_C(Fld20_15) + Вычеты - 15% Fld30_15 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==1) return 0.;return atof(Fld30_div); + Авансовые платежи - 15% Fld50_15 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==1) return 0.;return atof(Fld50_div); + Исчисленный налог - 15% Fld40_15 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)==1) return 0.;return atof(Fld40_div); + в т.ч. налог сдивидендов - 15% Fld45_15 N 14 /2 R_C(Fld40_15) + Начисленный доход - 30% Fld20_30 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)<2) return 0.;return atof(R_TaxSc11(1,"*","*",-207,__W,__A))-atof(Fld20_div); + Вычеты - 30% Fld30_30 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)<2) return 0.;return TaxValue(1)-TaxValue(4)-atof(Fld30_div); + Авансовые платежи - 30% Fld50_30 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)<2) return 0.;return 0.; + Исчисленный налог - 30% Fld40_30 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)<2) return 0.;return TaxValue(7)-atof(Fld40_div); + Удержанный налог - 30% Fld70_30 N 14 /2 if (atoi(NR)!=1 || atoi(STATUS)<2) return 0.;return TaxValue(13)-atof(Fld70_div); + Исчисленный налог (весь) Fld40_all N 14 /2 R_C(_EQ(NR-1)*(Fld40_div+Fld40_35+Fld40_13+Fld40_30)) + Авансовые платежи (все) Fld50_all N 14 /2 R_C(_EQ(NR-1)*(Fld50_div+Fld50_35+Fld50_13+Fld50_30)) + Удержанный по строкам 140 Fld70_140 N 14 /2 return atoi(NR)==2?0.:GetCurrentTax70_6NDFL(); + Удержанный налог по ЛС Fld70_LS N 14 /2 R_C(_EQ(NR-1)*(Fld70_div+Fld70_35+Fld70_13+Fld70_30)) + Удержанный налог Fld70 N 14 /2 return (GetCommonCnfInt("TypeFld70","6ndfl")&0x01)!=0?Fld70_140:Fld70_LS; + Неудержанный налог Fld80 N 14 /2 R_C(_EQ(NR-1)*(Fld40_all-Fld70_LS-Fld50_all));R_C(_GE(Fld80)*Fld80) #R_C(_EQ(NR-1)*(Fld40_all-Fld70_LS-Fld50_all));R_C(_GE(Fld80)*Fl + Возвращенный налог Fld90 N 14 /2 R_C(_EQ(NR-1)*0) + Наличие информации по 13% Flag13 N 9 /0 R_C(_EQ(NR-1)*(_NE(Fld20_13)+_NE(Fld30_13)+_NE(Fld40_13)+_NE(Fld50_13)+_NE(Fld70_13)));R_C(_NE(Flag13)) + Наличие информации по 15% Flag15 N 9 /0 R_C(_EQ(NR-1)*(_NE(Fld20_15)+_NE(Fld30_15)+_NE(Fld40_15)+_NE(Fld50_15)+_NE(Fld70_15)));R_C(_NE(Flag15)) + Наличие информации по 30% Flag30 N 9 /0 R_C(_EQ(NR-1)*(_NE(Fld20_30)+_NE(Fld30_30)+_NE(Fld40_30)+_NE(Fld50_30)+_NE(Fld70_30)));R_C(_NE(Flag30)) + Наличие информации по 35% Flag35 N 9 /0 R_C(_EQ(NR-1)*(_NE(Fld20_35)+_NE(Fld30_35)+_NE(Fld40_35)+_NE(Fld50_35)+_NE(Fld70_35)));R_C(_NE(Flag35)) Признак "попадёт в 2-НДФЛ" FlagNDFL2 N 1 /0 R_C(_EQ(NR-1)*_NE(Flag13+Flag15+Flag30+Flag35)) Признак приемав раздел 1 FlagPriem1 N 1 /0 R_C(_NE(NR-2)*_NE(Flag13+Flag15+Flag30+Flag35+_NE(Fld70))) Признак приемав раздел 2 FlagPriem2 N 1 /0 R_C(_EQ(NR-2)*(_NE(Fld130)+_NE(Fld140))) Признак приема(нулевки) FlagPriem3 N 1 /0 if ( atoi(NR)!=1 ) return 0; return IsNewIDOrg(IDDepart, __SilentParam); !!Признак приемав таблицу FlagPriem N 1 /0 R_C(_NE(FlagPriem1+FlagPriem2+FlagPriem3)) > Количество налогоплательщиков CountFL N 5 /0 R_C(_NE(FlagNDFL2)) Grp _MarkGroup C 1 /0 Последний столбец _Last C 5 /0 gSaveAPropBEFilterNDFL=0; return 0; */