Гость
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Списание себестоимости методом ФИФО / 2 сообщений из 2, страница 1 из 1
02.06.2020, 23:56
    #39965477
Elfix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Списание себестоимости методом ФИФО
Приветствую!

Написал небольшое приложение по расчету себестоимости продаж.
Вся логика реализована прямо в PostgreSQL в хранимых функциях.
Приложение исправно работало, но с появлением новых данных, вдруг обнаружил, что остатки с таблицы "партий" (packages) не списались, в таблицу costs не записалась списанная себестоимость.

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
CREATE OR REPLACE FUNCTION public.write_off_inventory(
	date timestamp with time zone,
	figi character varying,
	quantity numeric)
    RETURNS integer
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE 
    
AS $BODY$DECLARE
	rec packages%rowtype;
	current_quantity numeric(15) = $3;
	current_amount numeric(15, 2);
	current_commission numeric(15, 2);
BEGIN	
	-- Списание методом ФИФО
	-- Удалить из партий
	
	FOR rec IN SELECT * FROM packages AS packages
	WHERE
	packages.date <= $1
	AND packages.figi LIKE $2 
	ORDER BY date ASC LOOP
	
		IF rec.quantity >= current_quantity THEN
			-- Количества хватает, просто списываем и выходим из цикла.
			current_amount := rec.amount / rec.quantity * current_quantity;
			current_commission := rec.commission / rec.quantity * current_quantity;
			UPDATE packages SET quantity = packages.quantity - current_quantity, amount = packages.amount - current_amount, commission = packages.commission - current_commission WHERE id = rec.id;
			INSERT INTO costs ("date", figi, quantity, amount, commission) VALUES ($1, $2, current_quantity, current_amount, current_commission);
			EXIT;
		ELSE
			-- Количества не хватает, берем сколько есть, корректируем current_quantity и продолжаем цикл.
			IF rec.quantity <> 0 THEN
				current_amount := (rec.amount / rec.quantity * rec.quantity);
				current_commission := (rec.commission / rec.quantity * rec.quantity);
			ELSE
				current_amount := 0;
				current_commission := 0;
			END IF;
			UPDATE packages SET quantity = packages.quantity - rec.quantity, amount = packages.amount - current_amount, commission = packages.commission - current_commission WHERE id = rec.id;
			INSERT INTO costs ("date", figi, quantity, amount, commission) VALUES ($1, $2, rec.quantity, current_amount, current_commission);
			IF rec.quantity <> 0 THEN
				current_quantity = current_quantity - rec.quantity;
			END IF;
		END IF;
		
	END LOOP;
	
	DELETE FROM packages AS packages WHERE packages.quantity = 0 AND amount = 0 AND commission = 0;
	RETURN 0;
END;
$BODY$;



Запускаю функцию из другой функции:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
CREATE OR REPLACE FUNCTION public.update_costs(
	"from" timestamp with time zone,
	"to" timestamp with time zone)
    RETURNS integer
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE 
    
AS $BODY$
DECLARE
	rec sales%rowtype;
BEGIN
	-- Обновить себестоимость продаж
	DElETE FROM costs WHERE date BETWEEN "from" AND "to";
	FOR rec IN SELECT * FROM sales LOOP
		PERFORM write_off_inventory(rec."date", rec.figi, rec.quantity);
	END LOOP;
	
	RETURN 0;
END;
$BODY$;



В чем ошибка? В конкретном примере, было куплено 12 штук, продано 12 штук, но в таблицу с себестоимостью (costs) попадает только 11, и в таблице packages остается одна лишняя штука. Т. е. при определенных обстоятельствах (не понимаю при каких), одна единица никак не списывается.

Буду рад любой помощи.
Уже второй день пытаюсь найти ошибку...
...
Рейтинг: 0 / 0
03.06.2020, 03:00
    #39965503
Elfix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Списание себестоимости методом ФИФО
В три часа ночи, я таки нашел ошибку.
Оказалось, когда бегал по таблице продаж, я забыл ее отсортировать в порядке возрастания, в результате чего, функция списания не видела нужной записи, так как она была зафильтрована.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Списание себестоимости методом ФИФО / 2 сообщений из 2, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]