Теория... FIFO



Posted by Валентин, Донецк (195.58.226.37) on February 03, 2001 at 16:07:05:

* На одном из предприятий с большим ассортиментом товара столкнулся с медленным
* пересчетом себестоимости реализованных товаров. Пересмотреный мною алгоритм
* списания у меня не вызывает сомнения в его правильности, как механизма списания,
* а вот как механизм резкого падения скорости пересчета ...
*
* Если кому интересно разобраться и подсказать, где не верный ход или вообще
* неправильна стратегия данного алгоритма прошу ответить. И, вообще, не сильно ли
* я замудрил? Заранее благодарен.

* Списание Себестоимости Товаров
* Файл Включает Также Списание Методом LIFO и По Средневзвешенной Себестоимости
* По Выбору, Но Для Упрощения Они Исключены из Данного Примера, т.к. не Вызывают
* Особых Проблем в Скорости Пересчета.
n = [ep round] До Какого Знака Округление
******************** РЕАЛИЗАЦИЯ ТОВАРА ПО МЕТОДУ LIFO *********************
SS = 0 Начальная Сумма Списания Суммы Реализованного Товара
# _281 Цикл Счета Товаров (По Количеству)
Q = [mk #]-[ep #,6] К-во Реализованного Товара. От Общего Кредитового Оборота
* Колмчества По Товару Отнимается Реализованное К-во Товара Списанного Не по
* Порядку NoNo Партий, уже проведенное другими операциями, а Выбранное Конкретно
* по Конкретному No Партии Товара.
! Q = 0 goto MimAllL Если по Данному Товару Нет Списания
******************* РАСЧЕТ СЕБЕСТОИМОСТИ ОТГРУЗКИ МЕТОДОМ FIFO **************
TV = [n1 #] ; ST = 0 ; NK = Q
* Далее Приводится Модернизированный Пример из Метода LIFO
* (Описанный Е.Шуремовым) в Метод FIFO.
rewind facts
: PovtorF
search part ?NP post ?? tovar TV k_vo ?RP cena ?SP data ?DT
* 1-е Поле Факта - No Партии, Записанный Ранее При Приходе Товара.
* Дата Записывается Для Последующей Аналитики Оставшего Товара, После Его
* Списания Методом FIFO
**************** ПРИМЕР ПРИХОДА ТОВАРА, ВЗЯТЫЙ У Е.ШУРЕМОВА ***************
* (PN = 1 ; DT = [vl [strip [cp [dt dc,mc],1,2]]]+mc/100 )
* Запись Даты Добавлена Мною
* (news part ?PN post ?? tovar SR k_vo ?? cena ?? data ??)
* (if [success] = 1 PN = PN+1 ; endif )
* (fact part PN post SH tovar SR k_vo KV cena CN data DT )
*****************************************************************************
if [success] = 0 Если ни Одной Партии Нет , то это Значит, Что
fact f_err TV ; goto DalF Делаем Запись об Ошибке и Заканчиваем Расчет
endif
*****************************************************************************
if RP < NK Eсли Количество Товара в Данной Партии Меньше Нераспределенного
SS = SS+SP*RP то, Cтоимость Партии Списывается Полностью,
NK = NK-RP а Нераспределенное по Партиям Кол-во Уменьшается на Размер Партии
ro = NK ; call ro ; NK = ro Округление до 0.01
fact sebest TV k_vo RP cena SP summa SP*RP Факт Списания Себестоимости
* После Этого Уничтожается Запись о Приходе Партии за Номером NP
erase part NP post ?? tovar TV k_vo ?? cena ?? data ??
* Пробовал nerase - Еще медленее.
goto PovtorF и переходим к новой партии
endif
*****************************************************************************
* в Противном Случае, т.е., Если Размер Очередной Партии > Нераспр. Остатка,
OP = RP-NK то Вычисляется Остаток Партии Товара в Натуральном Выражении
ro = OP ; call ro ; OP = ro Округление до 0.01
fact sebest TV k_vo NK cena SP summa NK*SP Факт Списания Себестоимости
********************* СТИРАНИЕ НУЛЕВОЙ ПАРТИИ *******************************
* В Случае, Если Остаток < 0.001
! OP < 0.001 erase part NP post ?? tovar TV k_vo ?X cena ?Y data ?? ; goto DalF
******************** ПЕРЕЗАПИСЬ НЕНУЛЕВОЙ ПАРТИИ ****************************
rewind facts
search part NP post ?Z tovar TV k_vo ?X cena ?Y data ?TD
erase part NP post ?Z tovar TV k_vo ?X cena ?Y data ??
* Пробовал nerase - Еще медленее.
fact part NP post Z tovar TV k_vo OP cena SP data TD
: DalF
*****************************************************************************
SS = SS+NK*SP Себестоимость Списанного Товара
************ СОРТИРОВКА ПАРТИЙ ТОВАРОВ ПО УВЕЛИЧЕНИЮ НОМЕРА ПАРТИИ ********
rewind facts
select part ?NP post ?? tovar TV k_vo ?? cena ?? data ??
sort buffer 1
********** ПЕРЕЗАПИСЬ НОМЕРОВ ПАРТИЙ ТОВАРОВ В ПОРЯДКЕ ВОЗРАСТАНИЯ ********
* В Данном Случае у Меня Вызывает Сомнение в Нужности Данной Перезаписи.
* Может Следует Продолжать Нумерацию Партий из Года в Год...?
rewind buffer
N = 0 Начальный No Партии
: LLL
N = N+1 Первый No Партии
search part ?NP post ?AA tovar TV k_vo ?A1 cena ?A2 data ?DA
! [success]
erase part NP post AA tovar TV k_vo A1 cena A2 data ??
* Пробовал nerase - Еще медленее.
fact part N post AA tovar TV k_vo A1 cena A2 data DA
goto LLL
!
: MimAllF
! [ep #,6] > 0 _ # =6 (0) Обнуляем 6-й Параметр на Следующий Месяц
#
* Делаем Проводки Для Украинского Плана счетов
! SS > 0 _ 902 281 (SS) ; _ 791 902 (SS)
*************** ОПРЕДЕЛЕНИЕ ПРИРОСТА БАЛАНСОВОЙ СТОИМОСТИ *****************
* Также по Требованию Украинского Законодательства п. 5.9 Закона о Прибыли
BS = ([ba 281,1]+[ad 281]-[ak 281])-[ba 281,mc] ; $ = BS ; PI = 1
* PI - Переменная Для Дальнейших Выводов Форм в Расчетах (Доходы - Расходы)
! BS > 0 PI = 2
fact vdvr [n1 003] summa BS nomer '0' prin PI NoNo 5
stop
********************** ПОДПРОГРАММА ОКРУГЛЕНИЯ ****************************
* Данная Подпрограмма Взята из Примера, Приведенного Анатолием Анимицей на ПП
* (не знаю склоняется ли фамилия) и Модернизирована в 2-х Местах
* 1. Снято Ограничение Стандартной Функции TR Для Чисел > 2 000 000 000
* Это Сделано с Учетом Будующей Инфляциии, а Может и не Надо.
* 2. Изменено Выражение yx = [tr yx+0.5]*k на yx = [tr yx+0.50001]*k
* После Чего При Применении Этого Изменения Точность Расчетов на Одном
* из Предприятий в Программе и по Показаниям Кассового Аппарата
* Совпадает на 100%. По Моей Просьбе Кассир Отслеживает Этот Вопрос, но
* уже Третий Месяц нет Претензий.
*****************************************************************************
: ro подпрограмма округления вход x выход x точность n знаков после запятой
ru = 20000000 Минимум Округления стандартной функцией [TR]
if ro < ru Если число < 20 000 000
if ~[ce ro] return Если нечего округлять, то возврат
endif
goto Mim2mln ; endif Переход на округление
************* ВЫДЕЛЕНИЕ ЦЕЛОГО ЧИСЛА, ЕСЛИ ЧИСЛО > 20 000 000 *************
mx = 0 Неокругляемое Число
de = ro/ru Делитель числа на 20 000 000
de = [tr de] Целая часть числа раз по 20 000 000
mx = de*ru ; ro = ro-mx Число для округления
if ~[ce ro] ro = ro+mx Если нечего округлять,
return то возврат
endif
call Mim2mln ; ro = ro+mx Округляем и возвращаем полное число
return
******************* НЕПОСРЕДСТВЕННО ПОДПРОГРАММ ОКРУГЛЕНИЯ ****************
: Mim2mln
if ~(n in -3..5)
error подпрограмма ro округляет в диапазоне -3..5 знаков после запятой
endif
*****************************************************************************
k = 1 ; yx = ro ; n = [ro n] округлим показатель на всякий случай
*****************************************************************************
if yx < 0 yx = -yx ; endif округляем положительные числа
*****************************************************************************
if n < 0 нормализация до -n нулей в конце числа
for m = n to -1 в цикле
yx = yx/10 ; k = k*10 число делим на 10, показатель умножаем на 10
endfor
yx = [tr yx+0.50001]*k округляем
*****************************************************************************
elseif n = 0 если требуется просто целое число
yx = [tr yx+0.500001] просто округляем (+0.5+1Е-6)
*****************************************************************************
elseif n > 0 если требуется число с n знаков после запятой
for m = 1 to n в цикле
yx = yx*10 ; k = k/10 число умножаем на 10, показатель делим на 10
endfor
yx = [tr yx+0.50001]*k округляем
endif
*****************************************************************************
if ro >= 0 ro = yx восстанавливаем знак
else ro = -yx
endif
return
*****************************************************************************



Пpишедшие ответы: