
-- Function: fifo_tetel(integer)

-- DROP FUNCTION fifo_tetel(integer);

CREATE OR REPLACE FUNCTION fifo_tetel(p_tetel_kod integer)
  RETURNS boolean AS
'declare

v_tetel_kod                 tetel.kod%type;

v_work_sorszam              integer;

v_datum                     raktar_mozgas_fej.datum%type;
v_ido                       raktar_mozgas_fej.ido%type;
v_sztornozo_bizonylat_kod   raktar_mozgas_fej.sztornozo_bizonylat_kod%type;
v_sztornozott_bizonylat_kod raktar_mozgas_fej.sztornozott_bizonylat_kod%type;
v_kod                       raktar_mozgas.kod%type;
v_forras_raktar_kod         raktar_mozgas.forras_raktar_kod%type;
v_cel_raktar_kod            raktar_mozgas.cel_raktar_kod%type;
v_work_raktar_kod           raktar_mozgas.forras_raktar_kod%type;
v_mennyiseg                 raktar_mozgas.mennyiseg%type;
v_work_mennyiseg            raktar_mozgas.mennyiseg%type;
v_netto_osszeg_huf          raktar_mozgas.netto_osszeg_huf%type;

v_szt_mennyiseg             raktar_mozgas.mennyiseg%type;
v_szt_netto_osszeg_huf      raktar_mozgas.netto_osszeg_huf%type;

v_sorszam                   tetel_raktar_fifo.sorszam%type;
v_beszerzes                 tetel_raktar_fifo.beszerzes%type;
v_beszerzes_ertek           tetel_raktar_fifo.beszerzes_ertek%type;
v_maradek                   tetel_raktar_fifo.maradek%type;

v_ertek                     double precision;

v_update                    char;

v_max_sorszam               tetel_raktar_fifo.sorszam%type;
v_utolsobeszerzesiar        tetel.utolsobeszerzesiar%type;


c_forgalom cursor for

select rf.datum,
       rf.ido,
       rf.sztornozo_bizonylat_kod,
       rf.sztornozott_bizonylat_kod,
       rt.kod,
       rt.forras_raktar_kod,
       rt.cel_raktar_kod,
       rt.mennyiseg,
       rt.netto_osszeg_huf
  from raktar_mozgas_fej rf,
       raktar_mozgas rt
 where rf.kod = rt.fej_kod
   and rt.tetel_kod = v_tetel_kod
   and rt.csak_fobizonylat_tetel<>1
 order by rf.datum,
       rf.ido,
       rt.kod;


c_beszerzesek cursor for

select sorszam,
       beszerzes,
       beszerzes_ertek,
       maradek
  from tetel_raktar_fifo
 where tetel_kod = v_tetel_kod
   and raktar_kod = v_work_raktar_kod
   and maradek>0 
 order by sorszam;


begin
  v_tetel_kod:=$1;

  -- Regi adatok torlese
  delete from tetel_raktar_fifo
   where tetel_kod = v_tetel_kod;  

  update raktar_mozgas
     set forras_raktar_fifo_ertek = null,
         forras_raktar_fifo_ar = null,
         cel_raktar_fifo_ertek = null,
         cel_raktar_fifo_ar = null
   where tetel_kod = v_tetel_kod;

  -- Az adott cikk forgalmanak feldolgozasa

  v_work_sorszam:=1;
  
  open c_forgalom;

  fetch c_forgalom
   into v_datum,
        v_ido,
        v_sztornozo_bizonylat_kod,
        v_sztornozott_bizonylat_kod,
        v_kod,
        v_forras_raktar_kod,
        v_cel_raktar_kod,
        v_mennyiseg,
        v_netto_osszeg_huf;

  while found loop

    v_ertek:=0;

    -- Kiadas, ez szandekosan az elso lepes!

    if (v_forras_raktar_kod<>0 and v_mennyiseg>0) or 
       (v_cel_raktar_kod<>0    and v_mennyiseg<0) then

      if v_forras_raktar_kod<>0 and v_mennyiseg>0 then
        v_work_raktar_kod:=v_forras_raktar_kod;
        v_update:=''F'';
      else
        v_work_raktar_kod:=v_cel_raktar_kod;
        v_update:=''C'';
      end if;

      -- A sztornozo es sztornozott bizonylatokat kihagyjuk a szamitasbol
      if v_sztornozo_bizonylat_kod = 0 and
         v_sztornozott_bizonylat_kod = 0 then

        v_work_mennyiseg:=abs(v_mennyiseg);
        
        open c_beszerzesek;

        fetch c_beszerzesek
         into v_sorszam,
              v_beszerzes,
              v_beszerzes_ertek,
              v_maradek;

        while found and v_work_mennyiseg>0 loop

          if v_maradek<=v_work_mennyiseg then

            update tetel_raktar_fifo
               set maradek = 0
             where sorszam = v_sorszam
               and tetel_kod = v_tetel_kod;

            v_ertek:=v_ertek + (v_maradek/v_beszerzes) * v_beszerzes_ertek;
            v_work_mennyiseg:=v_work_mennyiseg - v_maradek;            

          else

            update tetel_raktar_fifo
               set maradek = maradek - v_work_mennyiseg
             where sorszam = v_sorszam
               and tetel_kod = v_tetel_kod;

            v_ertek:=v_ertek + (v_work_mennyiseg/v_beszerzes) * v_beszerzes_ertek;
            v_work_mennyiseg:=0;
            
          end if;
        
          fetch c_beszerzesek
           into v_sorszam,
                v_beszerzes,
                v_beszerzes_ertek,
                v_maradek;
              
        end loop;

        close c_beszerzesek;

        -- Ertek visszairasa
        if v_update = ''F'' then

          update raktar_mozgas
             set forras_raktar_fifo_ertek = v_ertek * sign(v_mennyiseg),
                 forras_raktar_fifo_ar = v_ertek  * sign(v_mennyiseg) / mennyiseg
           where kod = v_kod;
           
        else

          update raktar_mozgas
             set cel_raktar_fifo_ertek = v_ertek * sign(v_mennyiseg),
                 cel_raktar_fifo_ar = v_ertek * sign(v_mennyiseg) / mennyiseg
           where kod = v_kod;

        end if;

        if v_work_mennyiseg<>0 then
          raise exception ''Nincs eleg beszerzes! (tetel_kod: % % %)'',v_tetel_kod,v_work_mennyiseg,v_maradek;
        end if;
      end if;

    end if;


    -- Beszerzes
    
    if (v_cel_raktar_kod<>0 and v_mennyiseg>0) then
    
      -- A sztornozo es sztornozott bizonylatokat kihagyjuk a szamitasbol
      if v_sztornozo_bizonylat_kod = 0 and
         v_sztornozott_bizonylat_kod = 0 then

        v_work_mennyiseg:=abs(v_mennyiseg);

        if v_netto_osszeg_huf<>0 then
          v_ertek:=v_netto_osszeg_huf;
        end if;
         
        update tetel_raktar_fifo
           set beszerzes = beszerzes + v_work_mennyiseg,
               beszerzes_ertek = beszerzes_ertek + v_ertek,
               maradek = maradek + v_work_mennyiseg
         where tetel_kod = v_tetel_kod
           and raktar_kod = v_cel_raktar_kod
           and datum = v_datum
           and ido = v_ido;

        if not found then

          insert into tetel_raktar_fifo
          (sorszam,
           tetel_kod,
           raktar_kod,
           datum,
           ido,         
           beszerzes,
           beszerzes_ertek,
           maradek)

          values
      
          (v_work_sorszam,
           v_tetel_kod,
           v_cel_raktar_kod,
           v_datum,
           v_ido,
           v_work_mennyiseg,
           v_ertek,
           v_work_mennyiseg);

          v_work_sorszam:=v_work_sorszam + 1;
        end if;

        -- Ertek visszairasa
        update raktar_mozgas
           set cel_raktar_fifo_ertek = v_ertek * sign(v_mennyiseg),
               cel_raktar_fifo_ar = v_ertek * sign(v_mennyiseg) / mennyiseg
         where kod = v_kod;
      end if;

    end if;


    -- Ez is beszerzes, de maskeppen kell kezelni

    if (v_forras_raktar_kod<>0 and v_mennyiseg<0) then

      -- A sztornozo es sztornozott bizonylatokat kihagyjuk a szamitasbol
      if v_sztornozo_bizonylat_kod = 0 and
         v_sztornozott_bizonylat_kod = 0 then

        v_work_mennyiseg:=abs(v_mennyiseg);

        select max(sorszam)
          into v_max_sorszam
          from tetel_raktar_fifo
         where tetel_kod = p_tetel_kod
           and raktar_kod = v_forras_raktar_kod;

        -- Ha nem volt utolso beszerzes, akkor vegyuk az utolso beszerzesi arat
        if not found or v_max_sorszam is null then

          select utolsobeszerzesiar
            into v_utolsobeszerzesiar
            from tetel
           where kod = p_tetel_kod;

          v_ertek:=v_utolsobeszerzesiar * v_work_mennyiseg;

          insert into tetel_raktar_fifo
          (sorszam,
           tetel_kod,
           raktar_kod,
           datum,
           ido,         
           beszerzes,
           beszerzes_ertek,
           maradek)

          values
      
          (v_work_sorszam,
           v_tetel_kod,
           v_forras_raktar_kod,
           v_datum,
           v_ido,
           v_work_mennyiseg,
           v_ertek,
           v_work_mennyiseg);

          v_work_sorszam:=v_work_sorszam + 1;

          update raktar_mozgas
             set forras_raktar_fifo_ertek = v_ertek,
                 forras_raktar_fifo_ar = v_utolsobeszerzesiar
           where kod = v_kod;

        -- Ha volt utolso beszerzes, akkor vegyuk azt
        else
        
          select beszerzes,
                 beszerzes_ertek
            into v_beszerzes,
                 v_beszerzes_ertek
            from tetel_raktar_fifo
           where tetel_kod = p_tetel_kod
             and sorszam = v_max_sorszam;

          update tetel_raktar_fifo
             set beszerzes = beszerzes + v_work_mennyiseg,
                 beszerzes_ertek = beszerzes_ertek + v_work_mennyiseg * (v_beszerzes_ertek / v_beszerzes),
                 maradek = maradek + v_work_mennyiseg
           where tetel_kod = p_tetel_kod
             and sorszam = v_max_sorszam;        

          update raktar_mozgas
             set forras_raktar_fifo_ertek = v_work_mennyiseg * (v_beszerzes_ertek / v_beszerzes),
                 forras_raktar_fifo_ar = v_beszerzes_ertek / v_beszerzes
           where kod = v_kod;
        end if;
      end if;
    end if;

    -- Kovetkezo tetel
    fetch c_forgalom
     into v_datum,
          v_ido,
          v_sztornozo_bizonylat_kod,
          v_sztornozott_bizonylat_kod,
          v_kod,
          v_forras_raktar_kod,
          v_cel_raktar_kod,
          v_mennyiseg,
          v_netto_osszeg_huf;
  end loop;

  close c_forgalom;

  return true;
end;'
  LANGUAGE 'plpgsql' VOLATILE;


-- ***********************************************************************************************

-- Function: fifo_kezdo()

-- DROP FUNCTION fifo_kezdo();

CREATE OR REPLACE FUNCTION fifo_kezdo()
  RETURNS boolean AS
'declare

  c_cikkek cursor for

  select kod
    from tetel
   order by kod;

  v_tetel_kod integer;
  v_count     integer;

begin
  open c_cikkek;

  fetch c_cikkek
   into v_tetel_kod;

  while found loop
    
    select count(*)
      into v_count
      from raktar_mozgas
     where tetel_kod = v_tetel_kod;

    if v_count>0 then
      perform fifo_tetel(v_tetel_kod);
    end if;

    fetch c_cikkek
     into v_tetel_kod;
  end loop;

  close c_cikkek;

  return true;
end;
'
  LANGUAGE 'plpgsql' VOLATILE;


-- ***********************************************************************************************


-- Function: tr_raktar_mozgas_fifo()

-- DROP FUNCTION tr_raktar_mozgas_fifo();

CREATE OR REPLACE FUNCTION tr_raktar_mozgas_fifo()
  RETURNS "trigger" AS
'begin
    -- Ha nem keszletet mozgatunk, akkor semmit sem kell tenni
  if new.csak_fobizonylat_tetel = ''1'' then
    return new;
  end if;

  -- Keszletet erinto mozgas
  perform fifo_tetel(new.tetel_kod);
  
  return new;
end;'
  LANGUAGE 'plpgsql' VOLATILE;


-- ***********************************************************************************************


-- Trigger: trigger_raktar_mozgas_fifo on raktar_mozgas

-- DROP TRIGGER trigger_raktar_mozgas_fifo ON raktar_mozgas;

CREATE TRIGGER trigger_raktar_mozgas_fifo
  AFTER INSERT
  ON raktar_mozgas
  FOR EACH ROW
  EXECUTE PROCEDURE tr_raktar_mozgas_fifo();

