Код:
DECLARE
out_file UTL_FILE.FILE_TYPE; --штуковина для работы с файлом
out_file_name VARCHAR2(20) := 'proba2.txt'; -- имя файла
razd string(1) := chr(59); -- строка разделителя
--------------------------------------------------------
mhname varchar2(300); -- имя места хранения
cards varchar2(10); -- карточки
cname varchar2(255); -- имя товара
contract varchar2(50); -- контракт
dzak varchar2(50); -- дата заказа
vzak varchar2(50); -- время заказа
dbp date; -- дата ближайшей поставки
dsp date; -- дата следующей поставки
daynp varchar2(2); -- дней до следующей поставки
daybp varchar2(2); -- дней до ближайшей поставки
dday char(7); -- переменная для хранения дней доставки
minq number(8); -- переменная для хранения минимального количества из контракта
dterm number(5); -- срок поставки в днях
type1 number(14, 3); -- остаток в заказе
type2 number(14, 3); -- остаток по документам
type3 number(14, 3); -- остаток по актам
type4 number(14, 3); -- остаток по чекам
sum_ost number(14, 3); -- суммарный остаток
ssreal number(14, 3); -- среднесуточная реализация
min_days number(14, 3); -- минимальный запас в днях
min_days_nat number(14, 3); -- минимальный запас в натуральном исчислении
facing number(14, 3); -- фэйсинг
ost_bp number(14,3); -- остаток на дату ближайшей поставки
min_zap_nat_dsp number(14, 3); -- минимальный запас в натуральном исчислении на дату след. поставки
kzakazu number(18, 3); -- количество к заказу
posn integer(1) := 1; -- переменная хранящая позицию при использовании instr
upc number(10); -- переменная для хранения размера упаковки
llid number(8); -- место хранения по сср
variat integer(1) := 1;
numday number(8) :=1 + mod(to_number(to_char(sysdate, 'J')), 7);
part1 number(14,3);
part2 number(14,3);
part3 number(14,3);
--------------------------------------------------------------------
CURSOR art_ost is -- курсор по артикулам и остаткам
with operg as
(select god.article art,
god.storeloc locid,
og.article art1,
nvl(sum(og.salequantity), 0) - nvl(sum(og.returnquantity), 0) chk
from smgoods god
left join smopergoods og
on god.article = og.article where god.storeloc = '32'
group by god.article, og.article, god.storeloc) -- вот здесь берутся все остатки в т.ч и оперативные
Select c.article, -- артикул из карточки
c.name, -- наименование из карточки
g.awaitedquantity, -- количество которое должно поступить по документам в заданное место хранения
g.quantity, -- число единиц фактически находящееся на данном складе
g.foundquantity, -- в актах
opg.chk, -- в чеках
(g.awaitedquantity + g.quantity + g.foundquantity) - opg.chk summ_ost, -- суммарный остаток
lv.salerate, -- сср
lv.mindays, -- минимальное количество дней
lv.mindays * lv.salerate, -- запас в натуральном исчислении
lv.showlevel, -- выбираем все что касается артикулов и остатков
(lv.mindays*lv.salerate) + lv.showlevel, -- минимальный запас в натуральном исчислении на дату следующей поставки
lv.storeloc -- место хранения сср
From smcard c, sacardclass cc, smgoods g, smstocklevels lv, operg opg -- таблицы для выбора (карточки,классификатор,остатки,уровень реализации)
Where c.idclass = cc.id -- связываем карточки и классификатор
and c.article = g.article -- связываем артикулы и остатки по данным артикулам
and lv.article = c.article -- связываем реализацию и карточки
and lv.article = g.article -- реализацию и остатки
and lv.storeloc = g.storeloc -- и по месту хранение
and lv.storeloc = 32
and opg.locid = g.storeloc
and opg.art = g.article
and (cc.tree like 'бла-бла-бла%');
CURSOR contracts is -- открываем выборку по контрактам
SELECT
l.name, --имя места хранения из таблицы мест хранения
con.id, -- контракт
to_char(sysdate, 'dd.mm.yyyy') data_zakaza, -- дата заказа
to_char(sysdate, 'HH24:MI:SS') vremya_zakaza, -- время заказа
con.deliverydays, --дни доставки
con.minquantity, -- минимальное количество к заказу из контракта
con.deliveryterm, --периодичность
pack.packsize --размер упаковки
FROM
smdocuments doc, -- таблица документов
smspec spec, -- таблица спецификаций
smcontracts con, -- таблица контрактов
smsupplycase uc, -- отсюда берем поставщиков
smcontractpacks pack, -- размер упаковки
smstorelocations l -- место хранения
WHERE doc.doctype = spec.doctype -- связь документа и спецификации по типу документа
and doc.id = spec.docid -- связь документа и спецификации
and doc.doctype = con.doctype -- связь документа и контракта
and pack.doctype = con.doctype -- связь упаковки с типом документа
and pack.docid = con.id -- связь упаковки с контрактом
and pack.specitem = spec.specitem -- связь упаковки со спецификацией
and doc.id = con.id -- связка документа и контракта
and uc.idsupplier = doc.clientindex -- связка поставщика и документа
and uc.article = spec.article -- связка по артикулам
and spec.article = cards -- артикулы из 1-й выборки
and doc.location = llid --связка по месту хранения с переменной storeloc из smstocklevels из 1 выборки
and l.id = doc.location --связка по месту хранения (берем для получения имени места хранения)
and doc.doctype = 'CO' -- контракт
and doc.docstate = '2' -- действующий
and con.endsat is null; -- указываем чтобы дата окончания контракта была NULL
BEGIN
out_file := UTL_FILE.fopen('SM_DATA', out_file_name, 'w'); -- открываем файл в который бум писать
utl_file.putf(out_file,'артикулы по контрактам' || '\n'); -- пишем ему заголовок
utl_file.putf(out_file,
'дата заказа' || razd || 'время заказа' || razd ||
'место хранения' || razd || 'артикул' || razd ||
'Наименование товара' || razd || 'контракт' || razd ||
'дата ближайшей поставки' || razd ||
'дата следующей поставки' || razd ||
'дней до следующей поставки' || razd || 'остаток в заказах' || razd ||
'Остаток по документам' || razd || 'Подснятия' || razd ||
'В чеках' || razd || 'Cуммарный остаток' || razd || 'CCP' || razd ||'Вариативность'|| razd ||
'Минимальный запас в днях' || razd ||
'Минимальный запас в натуральном исчислении' || razd ||
'Фейсинг' || razd || 'Остаток на дату ближайшей поставки' || razd ||
'Минимальный запас в натуральном исчислении на дату следующей поставки' || razd ||
'Количество к заказу' || razd || '\n'); -- пишем ему хидеры
OPEN art_ost; --открываем выборку которая содержит артикулы остатки сср и.т.д(все что связ)
LOOP
Fetch art_ost into cards,cname,type1,type2,type3,type4,sum_ost,ssreal,min_days,min_days_nat,min_zap_nat_dsp,facing,llid;
EXIT WHEN art_ost%NOTFOUND; -- другое условие выхода
/* IF (art_ost%ROWCOUNT) > 100 -- выходим по условию
THEN
EXIT;
END IF; */-- конец условия
OPEN contracts; -- открываем выборку которая содержит контракты
LOOP
-- начинаем циклу
FETCH contracts
INTO mhname, contract, dzak, vzak, dday, minq, dterm, upc; -- выбираем в переменные
EXIT WHEN contracts%NOTFOUND;
/* IF (contracts%ROWCOUNT) > 100 -- выходим по условию
THEN
EXIT; -- выходим
END IF; -- выходим из условия
*/ IF (instr(dday, '1', posn) = numday) -- проверка на позицию 1 в поле deliverydays если 1 не равно текущей дате
THEN
dzak := to_date(dzak,'dd.mm.yyyy');
dbp := to_date(dzak, 'dd.mm.yyyy') + 1; -- дату ближайшей поставки определяем как завтра
dsp := to_date(dbp,'dd.mm.yyyy')+dterm;
daybp := dbp - to_date(sysdate,'dd.mm.yyyy'); -- дней до ближайшей поставки(дата ближайшей поставки минус сегодняшняя дата)
daynp := dsp - to_date(sysdate,'dd.mm.yyyy'); -- дней до следующей поставки получаем путем вычитания от даты след. поставки сегодняшней даты
ost_bp := sum_ost-(daybp * ssreal*variat);
IF (ost_bp < 0) -- если этот остаток <0 тогда остаток до ближвйшей поставки делаем 0
THEN
ost_bp := 0;
END IF;
part1:=min_zap_nat_dsp;
part2:=daynp*ssreal*variat;
part3:=ost_bp;
kzakazu := (part1+part2)-part3;
IF (kzakazu<0)
THEN
kzakazu := 0;
ELSE
kzakazu := (part1+part2)-part3;
END IF;
ELSE
IF(numday = 5)
THEN
dzak := to_date(dzak,'dd.mm.yyyy');
dbp := to_date(dzak, 'dd.mm.yyyy') + 1; -- дату ближайшей поставки определяем как завтра
dsp := to_date(dbp,'dd.mm.yyyy')+3; -- дату следующей устанавливаем ближайшим понедельником
daybp := dbp - to_date(sysdate,'dd.mm.yyyy'); -- дней до ближайшей поставки(дата ближайшей поставки минус сегодняшняя дата)
daynp := dsp - to_date(sysdate,'dd.mm.yyyy'); -- дней до следующей поставки получаем путем вычитания от даты след. поставки сегодняшней даты
ost_bp := sum_ost-(daybp * ssreal*variat);
IF (ost_bp < 0) -- если этот остаток <0 тогда остаток до ближвйшей поставки делаем 0
THEN
ost_bp := 0;
END IF;
part1:=min_zap_nat_dsp;
part2:=daynp*ssreal*variat;
part3:=ost_bp;
kzakazu := (part1+part2)-part3;
IF (kzakazu<0)
THEN
kzakazu := 0;
ELSE
kzakazu := (part1+part2)-part3;
kzakazu :=round(kzakazu,0);
END IF;
ELSE
IF(numday = 6)
THEN
dzak :=to_date(dzak,'dd.mm.yyyy');
dbp := to_date(dzak, 'dd.mm.yyyy') + 1; -- дату ближайшей поставки определяем как завтра
dsp := to_date(dbp,'dd.mm.yyyy')+2; -- дату следующей устанавливаем ближайшим понедельником
daybp := dbp - to_date(sysdate,'dd.mm.yyyy'); -- дней до ближайшей поставки(дата ближайшей поставки минус сегодняшняя дата)
daynp := dsp - to_date(sysdate,'dd.mm.yyyy'); -- дней до следующей поставки получаем путем вычитания от даты след. поставки сегодняшней даты
ost_bp := sum_ost-(daybp * ssreal*variat);
IF (ost_bp < 0) -- если этот остаток <0 тогда остаток до ближвйшей поставки делаем 0
THEN
ost_bp := 0;
END IF;
part1:=min_zap_nat_dsp;
part2:=daynp*ssreal*variat;
part3:=ost_bp;
kzakazu := (part1+part2)-part3;
IF (kzakazu<0)
THEN
kzakazu := 0;
ELSE
kzakazu := (part1+part2)-part3;
END IF;
ELSE
IF(numday = 7)
THEN
dzak :=to_date(dzak,'dd.mm.yyyy');
dbp := to_date(dzak, 'dd.mm.yyyy') + 1; -- дату ближайшей поставки определяем как завтра
dsp := to_date(dbp,'dd.mm.yyyy')+dterm; -- дату следующей устанавливаем ближайшим понедельником
daybp := dbp - to_date(sysdate,'dd.mm.yyyy'); -- дней до ближайшей поставки(дата ближайшей поставки минус сегодняшняя дата)
daynp := dsp - to_date(sysdate,'dd.mm.yyyy'); -- дней до следующей поставки получаем путем вычитания от даты след. поставки сегодняшней даты
ost_bp := (daybp * ssreal*variat)-sum_ost;
IF (ost_bp < 0) -- если этот остаток <0 тогда остаток до ближвйшей поставки делаем 0
THEN
ost_bp := 0;
END IF;
part1:=min_zap_nat_dsp;
part2:=daynp*ssreal*variat;
part3:=ost_bp;
kzakazu := (part1+part2)-part3;
IF (kzakazu<0)
THEN
kzakazu := 0;
ELSE
kzakazu := (part1+part2)-part3;
END IF;
END IF;
END IF;
END IF;
END IF;
UTL_FILE.PUTF(out_file,
dzak || razd || vzak || razd || mhname || razd || cards || razd ||
cname || razd || contract || razd || dbp || razd || dsp || razd ||
daynp || razd || type1 || razd || type2 || razd ||
type3 || razd || type4 || razd || sum_ost || razd ||
ssreal || razd ||variat|| razd || min_days || razd || min_days_nat || razd ||
facing || razd || ost_bp || razd || min_zap_nat_dsp || razd ||
kzakazu || razd || '\n'); -- вывод результатов в файл
UTL_FILE.FFLUSH(out_file);
END LOOP; -- закрываем вложенный цикл
CLOSE contracts; -- закрываем курсор по контрактам
END LOOP; -- конец цикла
UTL_FILE.FCLOSE(out_file); -- закрываем файл
CLOSE art_ost; -- закрываем курсор по остаткам
EXCEPTION
WHEN UTL_FILE.INVALID_PATH THEN
RAISE_APPLICATION_ERROR(-20100, 'Invalid Path');
WHEN UTL_FILE.INVALID_MODE THEN
RAISE_APPLICATION_ERROR(-20101, 'Invalid Mode');
WHEN UTL_FILE.INVALID_OPERATION THEN
RAISE_APPLICATION_ERROR(-20101, 'Invalid Operation');
WHEN UTL_FILE.INVALID_FILEHANDLE THEN
RAISE_APPLICATION_ERROR(-20300, 'Invalid File Handle');
WHEN UTL_FILE.WRITE_ERROR THEN
RAISE_APPLICATION_ERROR(-20301, 'Write Error');
WHEN UTL_FILE.INTERNAL_ERROR THEN
RAISE_APPLICATION_ERROR(-20302, 'Internal Error');
END;