IE2017

Точный расчет пропорционально зависимых значений в спецификации.

Программирование - Практика программирования

Больше статья, чем программа. Прилагаемая внешняя обработка - пример расчета на таблице значений.

Точный расчет пропорционально зависимых значений в спецификации.
(Пример на сумме накладной и НДС)

Проблема возникает при округлении значений в расчетных колонках спецификации.
Накопление этих округлений приводит иногда к ощутимой погрешности расчетного итогового значения:

Итог по расчетной колонке <> Расчетное значение по итогу "колонки-основания" для расчета (1)

(проще говоря)

Итог("НДС") <> СтавкаНДС * Итог("Сумма") 




Погрешность в 1-2 копейки возникает очень часто, если количество строк в документе большое,
может достигать 10-20 копеек.

На первый взгляд проблема надуманна или несущественна.
Она имеет организационное решение: выверять сумму построчно в накладных;
расставаться с поставщиками, которые присылают такие документы;
в силу несущественности оставить как есть.

Исключения всегда есть:

- Валютная накладная с курсом, - пересчет спецификации на момент ввода в "рублевую" учетную систему,
- Необходимость распространения общей скидки / надбавки от суммы документа на его спецификацию (скидка, бонус, доп. расходы).
- Документы перепродажи между собственными юрлицами с небольшой наценкой (десятые доли процента), -
разница между "исходящим" и "входящим" НДС может сильно отличаться от нормативной по ставке от наценки.

Идея точного расчета состоит в том, чтобы условие (1) выполнялось на любой момент пересчета спецификации.
Таким образом, на примере НДС для позиции i спецификации (единая ставка для всей спецификации):

НДС_i = Окр(СтавкаНДС * Сумма_i,2); // по старому
    
НДС_i = Окр(СтавкаНДС * ПромИтог("Сумма",1,i),2) -
                                           ПромИтог("НДС",1,i-1); // по новому

 

ПромИтог(<Колонка>,<ГраницаОтВкл>,<ГраницаДоВкл>) - промежуточный итог по указанной колонке
по диапазону строк с указанными границами.

Или, словами: НДС для позиции это разница между ставкой НДС от накопленной суммы на данную позицию
минус накопленный НДС на предыдущую позицию.

Пример для НДС условный, таким же образом могут сводиться в ноль любые процентные расчеты.

Реализация метода - в прилагающейся внешней обработке.

Скачать файлы

Наименование Файл Версия Размер
PinPointCalc
.1174486780 6,59Kb
25.09.09
71
.1174486780 6,59Kb 71 Скачать бесплатно

См. также

Комментарии
1. rjhev korum (корум) 310 25.04.07 11:58 Сейчас в теме
Есть ли пример встраивания в "типовые" процедуры? (глПересчетТабличнойЧасти и т.п.)
перелопачивать весь глобальник+все документы как-то сильно не хочется...
2. Михаил Семенов (Shaman100M) 1179 25.04.07 13:18 Сейчас в теме
Если говорить о ТиС, взять реквизит ТЧ "СуммаНДС" (или "СуммаНП"), то можно поискать обращение к процедуре глРасчетНалога(),
встречается не так часто:

глПересчетТаблЧасти()
глПересчитатьСтрокиДокумента()
глПересчитатьСкидки()

Описанная метода может отработать там, где осуществляется полный перебор строк и полный пересчет, т.е. в
глПересчитатьСтрокиДокумента и глПересчитатьСкидки.

Получается, она не применима для изменения и пересчета одной строки документа, что делается в глПересчетТаблЧасти() и глРасчетНалога() :( . Ну, можно попробовать считать значение СуммыНДС для текущей строки как "последнее дополняющее до точного итогового", но стремно это.

Сам использовал данный пересчет в нетиповой конфиге при программном создании документов. В формах документов добавлял кнопку и доп. диалог для "сведения" суммы и НДС. Можно пересчитывать при сохранении.
3. Михаил Семенов (Shaman100M) 1179 25.04.07 13:49 Сейчас в теме
...хотя... "последнее дополняющее до точного итогового" + итоговый пересчет при сохранении потянет
4. Сhe Burashka (CheBurator) 14.08.07 05:39 Сейчас в теме
возьмем 8-ую строку... типа НДС..
пришел я вот такой злостный налоговый инспектор... ткнул пальцем в первичку.. что у нас тут.. ага... НДСик д.б. 0.435045 = 0.44, а у вас что = 0.43.. ОПС! на цугундер!!! утаили копеечку от государства!!!
5. Poppy (poppy) 3314 14.08.07 12:15 Сейчас в теме
Алгоритм правильный, но реализация уж больно мудреная. Предлагаю более простой вариант:

Код
Процедура Сформировать()
   
   ПромИтогСумма = ТЗ1.Итог("СуммаЭталон");
   ПромИтогРасчет = ПримерРасчета(ТЗ1.Итог("СуммаЭталон"));

   ТЗ1.ВыбратьСтроки();
   Пока ТЗ1.ПолучитьСтроку()=1 Цикл
      
      ТЗ1.РасчетПоНовому = Окр(ТЗ1.СуммаЭталон * ПромИтогРасчет / ПромИтогСумма ,2);
      
      ПромИтогСумма = ПромИтогСумма - ТЗ1.СуммаЭталон;
      ПромИтогРасчет = ПромИтогРасчет - ТЗ1.РасчетПоНовому;
      
      ТЗ1.РасчетПоСтарому=ПримерРасчета(ТЗ1.СуммаЭталон); // по старому
   КонецЦикла;
   
КонецПроцедуры //Сформировать()

Показать полностью
6. Poppy (poppy) 3314 14.08.07 12:21 Сейчас в теме
(4)
Если инспектор никогда не читал НК, то это не злостный, но беспредельщик. Такие обычно не тычут в первичку, а сразу предлагают разобраться по-хорошему.
7. Poppy (poppy) 3314 14.08.07 12:25 Сейчас в теме
Применение рассматриваемого алгоритма не ограничивается пересчетом НДС в документах.

Например, при закрытии затратных счетов 44, 26, 25, 23, 20 без такого алгоритма = никуда.
8. Михаил Семенов (Shaman100M) 1179 14.08.07 13:07 Сейчас в теме
(4) А мож он сначала в итоги посмотрит? Ну, можно, конечно, начать разбирать не работающий системник, не убедившись , что просто не включен "пилот". :)

(5) можно бы проверить это алгоритм, т.к. при последнем проходе
[code] ТЗ1.РасчетПоНовому = Окр(ТЗ1.СуммаЭталон * ПромИтогРасчет / ПромИтогСумма ,2); [code]
тоже идет округление результата деления, - не факт, что ТЗ1.Итог("РасчетПоНовому") будет равен первичному ПромИтогРасчет , а это - основная цель разработки.

Реализация сделана сложнее, т.к. предполагает универсальность и минимум дополнительного кода в основной цикл пересчета (одна строка в цикле, одна до него)

Спасибо за комменты.
9. Poppy (poppy) 3314 14.08.07 13:45 Сейчас в теме
(8) >тоже идет округление результата деления, - не факт, что ТЗ1.Итог("РасчетПоНовому") будет равен первичному ПромИтогРасчет , а это - основная цель разработки.

В том то и дело, что на последнем проходе ТЗ1.СуммаЭталон тождественно равно ПромИтогСумма. Это значит, что ТЗ1.РасчетПоНовому = ПромИтогРасчет. Никакого округления не будет, т.к. ПромИтогРасчет всегда округлен.

По окончании цикла, ПромИтогРасчет всегда будет равен нулю. А значит, ТЗ1.Итог("РасчетПоНовому") будет равен первичному ПромИтогРасчет.
10. Михаил Семенов (Shaman100M) 1179 14.08.07 14:44 Сейчас в теме
(9) Да, согласен. От перестановки мест множителей произведение не меняется, но знак деления уже не смущает:

code] ТЗ1.РасчетПоНовому = Окр(ПромИтогРасчет * ТЗ1.СуммаЭталон / ПромИтогСумма ,2);
[/code]
Оставьте свое сообщение