Простой пример - вычеты в 2010 году, первый с начала года по пустую дату, второй с середины года по конец года.
По стандартным правилам результат - отсутствие вычетов в первой половине года!
А вот перенос измененными правилами, как видно, все переносится!
На сегодня, 06.03.11, я изменил текущие стандартные правила от 27.02.11.
Видеоурок по использованию измененных правил уже почти готов, на следующей неделе выкладываю (за праздники поднажму).
Далее, для искушенных в коде, представляю алгоритм изменения выгрузки вычетов по НДФЛ на детей. Для начала маленькая проверка самих вычетов:
//******************************************************Изменил Самойлов 17.11.10
// В ЗиК отсутствует проверка правильности периода, дату начала можно установить большей, чем дата окончания
КоличествоСтрокТЗ = ТаблицаВычетовНаДетей.КоличествоСтрок();
НомСтроки = 1;
Для Сч=1 По КоличествоСтрокТЗ Цикл
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(НомСтроки);
Если (ТаблицаВычетовНаДетей.Период > ТаблицаВычетовНаДетей.ПериодЗавершения)И(ПустоеЗначение(ТаблицаВычетовНаДетей.ПериодЗавершения)=0) Тогда
Сообщить("Некорректный период для вычета на детей у "+Источник);
Сообщить("ДатаНачалаВычета (начала работы в организации)- "+ТаблицаВычетовНаДетей.Период+", дата окончания вычета - "+ТаблицаВычетовНаДетей.ПериодЗавершения);
ТаблицаВычетовНаДетей.УдалитьСтроку(НомСтроки);
Иначе
НомСтроки = НомСтроки + 1;
КонецЕсли;
КонецЦикла;
//*******************************************************************************
А вот и сами изменения алгоритма выгрузки, а точнее инвентаризации всевозможных случаев:
ТаблицаВычетовНаДетей.Свернуть("Физлицо, Период, ПериодЗавершения, КодВычета", "КоличествоДетей, КоличествоДетейЗавершения");
ТаблицаВычетовНаДетей.Сортировать("+Период,+ПериодЗавершения");
Пока ТаблицаВычетовНаДетей.КоличествоСтрок() > 0 Цикл
Если ТаблицаВычетовНаДетей.КоличествоСтрок() > 1 Тогда
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(1);
Для Номер = 2 По ТаблицаВычетовНаДетей.КоличествоСтрок() Цикл
КодВычета = ТаблицаВычетовНаДетей.ПолучитьЗначение(Номер, "КодВычета");
Если КодВычета <> ТаблицаВычетовНаДетей.КодВычета Тогда
Продолжить;
КонецЕсли;
// Правила обработки двух пересекающихся периодов
// Всегда у первого периода дата начала меньше чем у второго
// С одинаковой датой начала, первым пойдет пустой период
// 1. даты окончания заполнены и совпадают
// в первом периоде: дата окончания становится на день меньше даты начала второго периода
// во втором периоде: количество детей - сумма первого и второго периодов
// 2. у первого периода не заполнена дата окончания, у второго - заполнена
// в первом периоде: дата начала становится на день позже даты окончания второго периода
// во втором периоде: количество детей - сумма первого и второго периодов
// 3. у первого и второго периодов совпадают даты начала
// в первом периоде: количество детей - сумма первого и второго периодов
// во втором периоде: дата начала становится на день больше даты окончания первого периода
// 4. даты окончания заполнены, не совпадают
// в первом периоде: дата окончания становится на день меньше даты начала второго периода
// во втором периоде: дата начала становится на день больше даты окончания первого периода
// добавляется еще один период:
// с даты окончания первого до даты начала второго периода,
// количество детей - сумма первого и второго периодов
БудущийПериод = ТаблицаВычетовНаДетей.ПолучитьЗначение(Номер, "Период");
БудущийПериодЗавершения = ТаблицаВычетовНаДетей.ПолучитьЗначение(Номер, "ПериодЗавершения");
БудущееКоличествоДетей = ТаблицаВычетовНаДетей.ПолучитьЗначение(Номер, "КоличествоДетей");
//******************************************************Изменил Самойлов 17.11.10
//Наложение, ограниченное равенством справа
//А1___________________________________________________А2
// Б1_____________________________Б2
//
//А2=Б1-1 Передвигаем конец первого периода до пересечения, количество суммируем во втором периоде
//*******************************************************************************
Если БудущийПериодЗавершения = ТаблицаВычетовНаДетей.ПериодЗавершения Тогда
// Запомним количество детей текущей записи
КоличествоДетей = ТаблицаВычетовНаДетей.КоличествоДетей;
// У текущей записи уменьшим дату окончания
ТаблицаВычетовНаДетей.ПериодЗавершения = БудущийПериод-1;
// Исправим количество детей следующей записи
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(Номер);
ТаблицаВычетовНаДетей.КоличествоДетей = ТаблицаВычетовНаДетей.КоличествоДетей + КоличествоДетей;
Прервать;
КонецЕсли;
//******************************************************Изменил Самойлов 17.11.10
//Если (ПустоеЗначение(ТаблицаВычетовНаДетей.ПериодЗавершения) = 1) Тогда
//// Запомним период завершения текущей записи
//ПериодЗавершения = ТаблицаВычетовНаДетей.ПериодЗавершения;
//
//// Запомним количество детей текущей записи
//КоличествоДетей = ТаблицаВычетовНаДетей.КоличествоДетей;
//
//// У текущей записи уменьшим дату начала
//ТаблицаВычетовНаДетей.Период = БудущийПериодЗавершения+1;
//// Исправим количество детей следующей записи
//ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(Номер);
//ТаблицаВычетовНаДетей.КоличествоДетей = ТаблицаВычетовНаДетей.КоличествоДетей + КоличествоДетей;
// Выше закомментировал, т.к. меняют начало первого периода, что считаю неправильным,
// потому, что все зиждется на сортировке по началу периода
//Наложение, ограниченное равенством слева
//конец первого периода может быть только пустое значение,
//если будет конкретная дата, то сортировкой периоды поменяются местами и попадут в след. условие
//А1___________________________________________________А2
//Б1_____________________________Б2
//
//А2=Б2 Передвигаем конец первого периода до конца пересечения, количество суммируем в первом периоде
//Б1=Б2+1 Б2=А2 Превращаем второй период в кусок первого после пересечения
Если (ПустоеЗначение(ТаблицаВычетовНаДетей.ПериодЗавершения) = 1)//к стандарту добавлю еще условие:
и (БудущийПериод = ТаблицаВычетовНаДетей.Период) Тогда
// Запомним период завершения текущей записи
А2 = ТаблицаВычетовНаДетей.ПериодЗавершения;
// Запомним количество детей текущей записи
КоличествоДетейА = ТаблицаВычетовНаДетей.КоличествоДетей;
// Передвигаем конец первого периода до конца пересечения
ТаблицаВычетовНаДетей.ПериодЗавершения = БудущийПериодЗавершения; //А2=Б2
// Превращаем второй период в кусок первого после пересечения
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(Номер);
КоличествоДетейБ = ТаблицаВычетовНаДетей.КоличествоДетей;
ТаблицаВычетовНаДетей.КоличествоДетей = КоличествоДетейА;
ТаблицаВычетовНаДетей.Период = ТаблицаВычетовНаДетей.ПериодЗавершения + 1; //Б1=Б2+1
ТаблицаВычетовНаДетей.ПериодЗавершения = А2; //Б2=А2
//количество суммируем в первом периоде
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(1);
ТаблицаВычетовНаДетей.КоличествоДетей = КоличествоДетейА + КоличествоДетейБ;
//*******************************************************************************
Прервать;
КонецЕсли;
Если (БудущийПериод = ТаблицаВычетовНаДетей.Период) Тогда
// Запомним период завершения текущей записи
ПериодЗавершения = ТаблицаВычетовНаДетей.ПериодЗавершения;
// У текущей записи исправим количество детей
ТаблицаВычетовНаДетей.КоличествоДетей = ТаблицаВычетовНаДетей.КоличествоДетей + КоличествоДетей;
// Исправим дату начала следующей записи
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(Номер);
ТаблицаВычетовНаДетей.Период = ПериодЗавершения + 1;
Прервать;
КонецЕсли;
//******************************************************Изменил Самойлов 17.11.10
//Если (БудущийПериод < ТаблицаВычетовНаДетей.ПериодЗавершения) Тогда
//Выше - Наложение, ограниченное равенством слева
//конец первого периода меньше
//А1__________________А2
//Б1_____________________________Б2
//
//Б1=А2+1 Передвигаем начало второго периода после пересечения, количество суммируем в первом периоде
//Дальше
//Второй период находится внутри первого
//А1____________________________________________________________________А2
// Б1_____________________________Б2
//
//А2=Б1-1 Первый период становится куском первого периода до пересечения
//Б1=Б2+1 Б2=А2 Второй период становится куском первого периода после пересечения
//В1=Б1 В2=Б2 Создаем третий период - пересечение
Если ((БудущийПериод < ТаблицаВычетовНаДетей.ПериодЗавершения) // условие для Б1, равно быть не может
ИЛИ((БудущийПериод > ТаблицаВычетовНаДетей.ПериодЗавершения) //Если Б1>А2, то только если А2 пустое
И(ПустоеЗначение(ТаблицаВычетовНаДетей.ПериодЗавершения) = 1))) И //теперь условие для Б2
(((БудущийПериодЗавершения < ТаблицаВычетовНаДетей.ПериодЗавершения)И(ПустоеЗначение(БудущийПериодЗавершения) = 0))
ИЛИ ((БудущийПериодЗавершения > ТаблицаВычетовНаДетей.ПериодЗавершения)
И(ПустоеЗначение(ТаблицаВычетовНаДетей.ПериодЗавершения) = 1))) Тогда
// Запомним реквизиты текущей записи
ПериодЗавершения = ТаблицаВычетовНаДетей.ПериодЗавершения;
КоличествоДетей = ТаблицаВычетовНаДетей.КоличествоДетей;
// У текущей записи уменьшим дату окончания
ТаблицаВычетовНаДетей.ПериодЗавершения = БудущийПериод-1; //А2=Б1-1
// Исправим дату начала следующей записи
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(Номер);
ТаблицаВычетовНаДетей.Период = ТаблицаВычетовНаДетей.ПериодЗавершения + 1; //Б1=Б2+1
ТаблицаВычетовНаДетей.ПериодЗавершения = ПериодЗавершения; //Б2=А2
// Добавим новую запись между первым и вторым периодом
ТаблицаВычетовНаДетей.НоваяСтрока();
ТаблицаВычетовНаДетей.Физлицо = Источник;
ТаблицаВычетовНаДетей.Период = БудущийПериод; //В1=Б1
ТаблицаВычетовНаДетей.ПериодЗавершения = БудущийПериодЗавершения; //В2=Б2
ТаблицаВычетовНаДетей.КодВычета = КодВычета;
ТаблицаВычетовНаДетей.КоличествоДетей = КоличествоДетей + БудущееКоличествоДетей;
ТаблицаВычетовНаДетей.КоличествоДетейЗавершения = КоличествоДетей;
Прервать;
КонецЕсли;
//Периоды пересекаются краями
//А1______________________________А2
// Б1_____________________________Б2
//
//А2=Б1-1 Первый период становится куском первого периода до пересечения
//Б1=А2+1 Второй период становится куском второго периода после пересечения
//В1=Б1 В2=А2 Создаем третий период - пересечение
Если ((БудущийПериод < ТаблицаВычетовНаДетей.ПериодЗавершения) // условие для Б1, равно быть не может
ИЛИ((БудущийПериод > ТаблицаВычетовНаДетей.ПериодЗавершения) //Если Б1>А2, то только если А2 пустое
И(ПустоеЗначение(ТаблицаВычетовНаДетей.ПериодЗавершения) = 1))) И //теперь условие для Б2
((БудущийПериодЗавершения > ТаблицаВычетовНаДетей.ПериодЗавершения )
ИЛИ((БудущийПериодЗавершения < ТаблицаВычетовНаДетей.ПериодЗавершения )
И(ПустоеЗначение(БудущийПериодЗавершения) = 1))) Тогда
//*******************************************************************************
// Запомним реквизиты текущей записи
ПериодЗавершения = ТаблицаВычетовНаДетей.ПериодЗавершения;
КоличествоДетей = ТаблицаВычетовНаДетей.КоличествоДетей;
// У текущей записи уменьшим дату окончания
ТаблицаВычетовНаДетей.ПериодЗавершения = БудущийПериод-1;
// Исправим дату начала следующей записи
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(Номер);
ТаблицаВычетовНаДетей.Период = ПериодЗавершения + 1;
// Добавим новую запись между первым и вторым периодом
ТаблицаВычетовНаДетей.НоваяСтрока();
ТаблицаВычетовНаДетей.Физлицо = Источник;
ТаблицаВычетовНаДетей.Период = БудущийПериод;
ТаблицаВычетовНаДетей.ПериодЗавершения = ПериодЗавершения;
ТаблицаВычетовНаДетей.КодВычета = КодВычета;
ТаблицаВычетовНаДетей.КоличествоДетей = КоличествоДетей + БудущееКоличествоДетей;
ТаблицаВычетовНаДетей.КоличествоДетейЗавершения = КоличествоДетей;
Прервать;
КонецЕсли;
КонецЦикла;
ТаблицаВычетовНаДетей.Свернуть("Физлицо, Период, ПериодЗавершения, КодВычета", "КоличествоДетей, КоличествоДетейЗавершения");
ТаблицаВычетовНаДетей.Сортировать("+Период,+ПериодЗавершения");
КонецЕсли;
ТаблицаВычетовНаДетей.ПолучитьСтрокуПоНомеру(1);
ВыгрузитьПоПравилу(ТаблицаВычетовНаДетей, , , , "НДФЛСтандартныеВычетыНаДетей");
ТаблицаВычетовНаДетей.УдалитьСтроку(1);
КонецЦикла;
Благодарю alexk-is за //infostart.ru/public/19856/
Публикация //infostart.ru/public/19622/ не активна, но все равно, благодарю Владислава Томашевича.
Изменения новых правил, дополнения отслеживаем на моем блоге: Изменить 1С