05.03.2018 10:59
m1n1mal
 
Здравствуйте!
Подскажите, если ли возможность в Супермаге получить информацию о том, сколько товар отсутствовал в наличии, в днях, в рамках заданного периода?

Например, берем отчетный период с 1 февраля по 1 марта по заданной товарной группе "Группа товаров 1", информация полученная по периоду должна примерно содержать следующее:
Артикул 1 - отсутствовал 7 дней.
Артикул 22 - отсутствовал 3 дня.
Артикул 125 - отсутствовал 1 день.
06.03.2018 22:14
Starter
 
Как мой любимый вариант - использование собственных функций и Бизнес-Анализ.

Ниже как раз такая функция (автор не я, я был заказчиком).

Используется в бизнес анализе. Пример вызова:
Get_Card_Stat({Фильтр. Параметр модели. Отчетный период. FDateFirst},{Фильтр. Параметр модели. Отчетный период. FDateLast},{Место хранения. Код места хранения},{Карточка товара. Артикул},1)

Необходимо учесть, что супер быстрой эту функцию назвать сложно, поэтому не рекомендую запускать по всем артикулам базы.

SQL код:
------------
--
Получить статистику по карточке товара
--входные параметры дата начала периодадата окончания периодакод места храненияартикулчто хотим узнать.
--
варианты что =
--
число днейкогда карточка продавалась
--число днейкогда карточка не продавалась
--число днейкогда остаток по карточке был равен нулю
--число днейкогда остаток был не равен нулю
--число днейкогда остаток был отрицательным.
--
число днейкогда остаток был положительным
--
число днейкогда карточка не продавалась и остаток по ней не был равен нулю.
--
суммарный остаток за все дни периода (для вычисления среднего остаткадля расчета точной оборачиваемости)
--
число днейкогда карточка продавалась или остаток по ней не был больше нуля

create 
or replace function Get_Card_Stat(ADateFrom in dateADateTo in dateALocID in supermag.smstorelocations.id%type,
  
AArticle in supermag.smcard.article%typeAWhat in integer) return integer 
is
  i integer
;
  
error_param_value exception;
  
  function 
SaleDaysCount(ADateFrom in dateADateTo in dateALocID in supermag.smstorelocations.id%type,
    
AArticle in supermag.smcard.article%type) return integer is
    res integer 
:= 0;
  
begin
    select count
(distinct d.createdat)
    
into res
    from supermag
.smdocuments dsupermag.smspec s
    where d
.doctype in ('WO''CS') and d.opcode and d.docstate 
      
and d.createdat between ADateFrom and ADateTo and d.locationfrom ALocID
      
and s.doctype d.doctype and s.docid d.id and s.article AArticle;
    return(
res);
  
exception when no_data_found then    
    
return(0);
  
end;
  function 
GetRemainsOnDate(AOnDate in dateALocID in supermag.smstorelocations.id%type,
    
AArticle in supermag.smcard.article%type) return number 
  is
    res number
;
  
begin
    select nvl
(sum(decode(nvl(d.locationto0), 0, -11) * s.quantity), 0)
    
into res
    from supermag
.smdocuments dsupermag.smspec s
    where d
.doctype in ('WI''WO''IW''CS''CR''PN''PE''PO')
      and 
d.docstate and d.createdat <= AOnDate
      
and nvl(d.locationtod.locationfrom) = ALocID
      
and s.doctype d.doctype and s.docid d.id and s.article AArticle;
    return(
res);
  
exception when no_data_found then
    
return(0);
  
end;
  function 
Calc(ADateFrom in dateADateTo in dateALocID in supermag.smstorelocations.id%type,
    
AArticle in supermag.smcard.article%typeAWhat in integer) return integer
  is
    vRemains number 
:= GetRemainsOnDate(ADateFromALocIDAArticle);
    
res integer := 0;
  
begin
    
for c in (select nvl(sum(nvl(d.quantity0)) over (order by c.dat) + vRemains0) as quantity,
                
nvl(sum(nvl(d.salequantity0)) over (partition by c.dat), 0) as salequantity
              from
                
(select dd.createdatsum(dd.quantity) as quantitysum(dd.salequantity) as salequantity
                 from
                   
(select d.createdatsum(s.quantity) as quantityas salequantity
                    from supermag
.smdocuments dsupermag.smspec s
                    where d
.doctype s.doctype and d.id s.docid and s.article AArticle and d.locationto ALocID
                      
and d.docstate >= and d.createdat between ADateFrom and ADateTo
                    group by d
.createdat
                    union all
                    select d
.createdatsum(-s.quantity) as quantitysum(decode(d.opcode1, -s.quantity0)) as salequantity
                    from supermag
.smdocuments dsupermag.smspec s
                    where d
.doctype s.doctype and d.id s.docid and s.article AArticle and d.locationfrom ALocID
                      
and d.docstate >= and d.createdat between ADateFrom and ADateTo
                    group by d
.createdatdd
                 group by dd
.createdatd,
                (
select dt.dat
                 from 
                   
(select ADateFrom level as dat
                    from dual connect by level 
<= ADateTo ADateFrom 1dtc
              where c
.dat d.createdat(+)) loop
      
if AWhat and c.quantity 0 then -- число днейкогда остаток по карточке был равен нулю
        res 
:= res 1;
      
elsif AWhat and c.quantity != 0 then -- число днейкогда остаток был не равен нулю
        res 
:= res 1;
      
elsif AWhat and c.quantity 0 then -- число днейкогда остаток был отрицательным
        res 
:= res 1;
      
elsif AWhat and c.quantity 0 then -- число днейкогда остаток был положительным
        res 
:= res 1;
      
elsif AWhat and c.quantity 0 then -- cуммостатоккогда остаток был положительным (для расчета оборачиваемости)
        
res := res c.quantity;

      
elsif AWhat and c.salequantity and c.quantity != 0 then -- число днейкогда карточка не продавалась и остаток по ней не был равен нулю
        res 
:= res 1;
      
elsif AWhat and c.salequantity or c.quantity 0 then -- число днейкогда карточка продавалась или остаток по ней не был больше нуля
        res 
:= res 1;
      
end if;
    
end loop;
    return(
res);
  
exception when no_data_found then
    
return(0);
  
end;
  
begin
  
if AWhat 1 then -- число днейкогда карточка продавалась
    
return(SaleDaysCount(trunc(ADateFrom), trunc(ADateTo), ALocIDAArticle));
  
elsif AWhat 2 then -- число днейкогда карточка не продавалась
    
return(trunc(ADateTo) - trunc(ADateFrom) + SaleDaysCount(trunc(ADateFrom), trunc(ADateTo), ALocIDAArticle));
  
elsif AWhat between 3 and 9 then
    
return(Calc(trunc(ADateFrom), trunc(ADateTo), ALocIDAArticleAWhat));
  else
    
raise_application_error(-20999'Параметр AWhat должен быть в диапазоне от 1 до 9.'true);
  
end if;
end;
/  
commit

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.