CREATE OR REPLACE Package Pre_par is

   kCia                    Varchar2(3);
   kMetodo_Calculo         CHAR(1);
   kTomaMargen             CHAR(1);
   kReqAutoriza            CHAR(1);
   kRegulado               CHAR(1);
   kPrecioivi              CHAR(1);
   kLista_precio           CHAR(3);
   kMon_Base               VARCHAR2(3);
   kMultiMon               CHAR(1);
   kMoneda_Principal       VARCHAR2(3);
   kDerivacion             varchar2(1);

   Procedure Inicializar(pCia in char);
   Function pPrecioIvi return varchar2;
   Function pMon_base return varchar2;
   Function pMultiMon return varchar2;
   Function pLista_Precio return varchar2;
   Function pMetodo_Calculo return varchar2;
   Function pReqAutoriza return varchar2;
   Function pMoneda_Principal return varchar2;
 
   Function EsRegulado(pCia in varchar2, pLinea in varchar2) return boolean;
   FUNCTION Calcula_precio(pCosto in number, pUtilidad in number, pImpvta in number,
                           pDesfijo in number, pDesprom in number, pSelcon in number) RETURN number;
   FUNCTION PrecioBase(pPrecio in number, pUtilidad in number) RETURN number;
   FUNCTION PrecioUtil(pPrecio in number, pUtilidad in number) RETURN number;
   FUNCTION PrecioNuevo(pCia in varchar2, pPrecio in number, pUtilidad in number, pDesc in number, pNuevaUtil in number) RETURN number;
   FUNCTION Calcula_utilidad (pCosto in number, pPrecio in number, pImpvta in number,
                              pDesfijo in number, pDesprom in number, pSelcon in number) RETURN number;
   Function MargenProveedor(pCia in varchar2, pProv in varchar2, pLista in varchar2,
                            pMoneda in varchar2, pArticulo in varchar2) return number;
   Function MargenLista(pCia in varchar2, pLista in varchar2, pMoneda in varchar2,
                        pArticulo in varchar2, pProv in varchar2) return number;
   Function ObtenerMargen(pCia in varchar2, pProv in varchar2,  pLista in varchar2, pMoneda in varchar2,
                          pArticulo in varchar2) return number;
   Procedure CalculaTotales(pPrecio in number, pCantidad in number, pPorcdescuento in number,
                            pPorcImpArt in number, pPorcImpCli in number,
                            pTotalLinea out number, pImpuesto out number);
   Function Derivacion Return Varchar2;
   Function UtilidadDerivada(pPrecioMadre in Number, pDescuento in Number, 
                             pPrecioUnitario in Number) RETURN Number;
   Function PorcVar(pUtilidad in number, pDesc in number) RETURN number;

end;
/

CREATE OR REPLACE Package Body Pre_par is

   Procedure Inicializar(pCia in char) is
      Siregs number(5);
      Noregs number(5);
   Begin
      select METODO_CALCULO,TOMAMARGEN, REQAUTORIZA,
             PRECIOIVI, LISTA_PRINCIPAL, MULTIMON, MONEDA_PRINCIPAL, DERIVACION
         INTO kMetodo_Calculo, kTomaMargen, kReqAutoriza,
              kPrecioivi, kLista_precio, kMultimon, kMoneda_principal, kDerivacion
      from preparametro
      where cod_cia=pCia;
      kCia:=pCia;
      select count(*)
         into Siregs
      from inv_linea
      where cod_cia=pCia
        and precio_regulado='S';
      select count(*)
         into Noregs
      from inv_linea
      where cod_cia=pCia
        and precio_regulado='N';
      if nvl(Siregs,0)>0 and nvl(Noregs,0)>0 then
      	 kRegulado:='C';
      elsif nvl(Siregs,0)>0 then
      	 kRegulado:='S';
      else
      	 kRegulado:='N';
      end if;
      begin
         select cod_moneda_base into kMon_base 
         from gen_parametro
         where cod_cia=pCia;
      Exception
      	 when no_data_found then
      	    null;
      End;
   End Inicializar;

   Function pPrecioIvi return varchar2 is
   begin
      return kPrecioIvi;
   end;

   Function pMon_Base return varchar2 is
   begin
      return kMon_base;
   end;

   Function pMultiMon return varchar2 is
   begin
      return kMultiMon;
   end;

   Function pLista_Precio return varchar2 is
   begin
      return kLista_Precio;
   end;

   Function pMetodo_Calculo return varchar2 is
   begin
      return kMetodo_Calculo;
   end;

   Function pReqAutoriza return varchar2 is
   begin
      return kReqAutoriza;
   end;

   Function pMoneda_Principal return varchar2 is
   begin
      return kMoneda_Principal;
   end;

   Function EsRegulado(pCia in varchar2, pLinea in varchar2) return boolean is
      vRegulado   inv_linea.precio_regulado%type;
   Begin   
      if kRegulado='C' and pLinea is not null then
	 begin
	    select precio_regulado 
	       into vRegulado
	    from inv_linea
	    where cod_cia=pCia
            and cod_linea=pLinea;
         exception
	    when no_data_found then
               vRegulado:='N';
         end;
      else
      	 vRegulado:=kRegulado;
      end if;
      return (vRegulado='S');
   End EsRegulado;

   FUNCTION Calcula_precio(pCosto in number, pUtilidad in number, pImpvta in number,
                           pDesfijo in number,pDesprom in number, pSelcon in number) RETURN number IS
      vAux     number;
      vPrecio predetlista.precio_unitario%type;
   BEGIN
      vAux :=   nvl(pCosto,0) * (1-(nvl(pDesfijo/100,0)+nvl(pDesprom/100,0))) * (1+nvl(pSelcon/100,0));
      if kMetodo_Calculo = 'M' then
         vAux:=vAux/(1-pUtilidad/100);
      else
         vAux:=vAux*(1+pUtilidad/100);
      end if;
      if pImpvta>0 and kPrecioivi='S' then
         vPrecio := vAux*(1+pImpvta/100);
      else
         vPrecio := vAux;
      end if;
      return vPrecio;
   END Calcula_precio;

   FUNCTION PrecioBase(pPrecio in number, pUtilidad in number) RETURN number IS
   BEGIN
      if kDerivacion='C' then
         if kMetodo_Calculo = 'M' then
            return pPrecio*(1-pUtilidad/100);
         else
            return pPrecio/(1+pUtilidad/100);
         end if;
      else
         return pPrecio;
      end if;
   END PrecioBase;

   FUNCTION PrecioUtil(pPrecio in number, pUtilidad in number) RETURN number IS
   BEGIN
      if kDerivacion='C' and kMetodo_Calculo='M' then
         return pPrecio/(1-pUtilidad/100);
      else
         return pPrecio*(1+pUtilidad/100);
      end if;
   END PrecioUtil;

   FUNCTION PrecioNuevo(pCia in varchar2, pPrecio in number, pUtilidad in number, pDesc in number, pNuevaUtil in number) RETURN number is
   begin
      if nvl(kCia,' x ')!=pCia then
         inicializar(pCia);
      end if;
      if kDerivacion='C' then
         if kMetodo_Calculo = 'M' then
            return (pPrecio*(1-pUtilidad/100)/(1-pDesc/100))/(1-pNuevaUtil/100);
         else
            return pPrecio/((1+pUtilidad/100)*(1-pDesc/100))*(1+pNuevaUtil/100);
         end if;
      else
         return pPrecio*(1+pNuevaUtil/100);
      end if;
      
   end;

   FUNCTION Calcula_utilidad (pCosto in number, pPrecio in number, pImpvta in number,
                              pDesfijo in number, pDesprom in number, pSelcon in number) RETURN number is
      vutl    number(14,4);
      vcosto  number;
      vprecio number;
   BEGIN
      if pimpvta>0 and kPrecioivi='S' then
         vPrecio := pPrecio/(1+pImpvta/100);
      else
   	 vPrecio := pPrecio;
      end if;  
      vcosto := nvl(pCosto,0)*(1-(nvl(pDesfijo/100,0)+nvl(pDesprom/100,0)))*(1+nvl(pSelcon/100,0));
      if kMetodo_Calculo = 'M' then
   	 vUtl:=100*(1-vCosto/vPrecio);
      else
   	 if vCosto=0 then
   	    vUtl:=100;
   	 else
   	    vUtl:=100*((vPrecio/vCosto)-1);
   	 end if;
      end if;
      if vUtl>=1000 then
   	 return 999.99;
      else
         return vUtl;
      end if;
   End Calcula_Utilidad;

   Function MargenProveedor(pCia in varchar2, pProv in varchar2, pLista in varchar2,
                            pMoneda in varchar2, pArticulo in varchar2) return number is
      vMargen  predetlista.porc_utilidad%type;
   begin
      select margen_sug 
         into vMargen
      from prec_proveedor
      where cod_cia       = pCia
      and   cod_proveedor = pProv
      and   cod_lista_precio = pLista;
      return vMargen;
   exception
      when no_data_found then
 	 if pMoneda is not null  then
 	    return MargenLista(pCia, pLista, pMoneda, pArticulo, null);
 	 else
 	    return 0;
 	 end if;
   end MargenProveedor;

   Function MargenLista(pCia in varchar2, pLista in varchar2, pMoneda in varchar2,
                        pArticulo in varchar2, pProv in varchar2) return number is
      vMargen  predetlista.porc_utilidad%type;
   begin
      select porc_utilidad-descuento
         into vMargen
      from predetlista
      where cod_cia          = pCia
      and   cod_lista_precio = pLista
      and   cod_moneda       = pMoneda
      and   cod_articulo     = pArticulo;
      return vMargen;
   exception
      when no_data_found then
         if Pprov is not null then
            return MargenProveedor(pCia, pProv, pLista, null, null);
 	 else
 	    return 0;
         end if;
   end MargenLista;

   Function ObtenerMargen(pCia in varchar2, pProv in varchar2,  pLista in varchar2,
                          pMoneda in varchar2, pArticulo in varchar2) RETURN number IS
   BEGIN
      if kTomamargen='P' then
         return MargenProveedor(pCia, pProv, pLista, pMoneda, pArticulo);
      else
   	 return MargenLista(pCia, pLista, pMoneda, pArticulo, pProv);
      end if;    
   END ObtenerMargen;

   Procedure CalculaTotales(pPrecio in number, pCantidad in number, pPorcdescuento in number,
                            pPorcImpArt in number, pPorcImpCli in number,
                            pTotalLinea out number, pImpuesto out number) IS
      vSubTotal  number;
      vImpLista  number;
   BEGIN
      vSubtotal:=pPrecio*pCantidad-Dsc.Redondeo(pPrecio*pPorcDescuento/100, pCantidad);
      if pre_par.pPrecioIvi='S' then
         vImpLista:=Round(vSubTotal*(1-1/(1+pPorcImpArt/100)), 2);
         pImpuesto:=Round(vImpLista*pPorcImpCli/100, 2);
      else
         vImpLista:=0;
         pImpuesto:=Round(vSubtotal*pPorcImpart*pPorcImpCli/10000, 2);
      end if;
      pTotallinea:=Round(vSubtotal-vImpLista+pImpuesto, 2);
   END CalculaTotales;

   Function Derivacion Return Varchar2 Is
   Begin
      Return kDerivacion;
   End Derivacion;

   Function UtilidadDerivada(pPrecioMadre in Number, pDescuento in Number, 
                             pPrecioUnitario in Number) RETURN Number Is
   Begin
      If Nvl(pPrecioMadre, 0) = 0 Then
         Return 999.99;
      End If;
  
      Return 100*pPrecioUnitario/pPrecioMadre - 100 + pDescuento;
   End UtilidadDerivada;

   FUNCTION PorcVar(pUtilidad in number, pDesc in number) RETURN number IS
   BEGIN
      if kMetodo_Calculo = 'M' then
         return (pUtilidad-pDesc)/(1-pDesc/100);
      else
         return pUtilidad-pDesc-pDesc*pUtilidad/100;
      end if;
   END PorcVar;

End;
/

CREATE OR REPLACE PACKAGE Precios IS

   procedure Inserta(pCia in char, pLista in varchar2, pMoneda in varchar2, pArt in varchar2,
                     pCosto in number, pPrecio in number, pPorcUt in number, pDesc in number);
   Procedure RenovarLista(pCia in varchar2, pLista in varchar2, pMoneda in varchar2);
   Function PrecioBase(pCia in varchar2, pLista in varchar2, pArt in varchar2, pMoneda in varchar2,
                       pPrecioCorto in varchar2 default 'N') return number;
   Function VariacionPrecio(pCia in varchar2, pLista in varchar2, pArt in varchar2, pMoneda in varchar2) return number;
   Function PrecioLista(pCia IN varchar2, pLista IN varchar2,
              pArt IN varchar2, pMoneda IN varchar2) RETURN number;
   Function PrecioLista(pCia IN varchar2, pLista IN varchar2,
              pArt IN varchar2, pMoneda IN varchar2, pPrecioBase In number) RETURN number;
   Function PrecioDer(pCia in varchar2, pListaMadre in varchar2, pArt in varchar2, pMoneda IN varchar2,
                      pPorc in number, pPrecioBase in number default null) RETURN number;
   Function PrecioIvi(pPreciolista in number, pPorcImpto in number) RETURN number;
   Function PrecioSinIv(pPreciolista in number, pPorcimpto in number) RETURN NUMBER;
   Function PrecioSinIv(pCia in varchar2, pArt in varchar2, pLinea in varchar2, pLista in varchar2,
                        pMoneda in varchar2, pImptoVtas in varchar2) return number;
   Function PrecioNeto(pCia in varchar2, pPreciolista in number, pLinea in varchar2, pMoneda in varchar2) RETURN number;

   Function Precio(pCia in varchar2, pPrecioBase in number, pLinea in varchar2, pMoneda in varchar2, pImptoVtas in varchar2) return number;

   Function Precio(pCia in varchar2, pArt in varchar2, pLinea in varchar2, pLista in varchar2,
                   pMoneda in varchar2, pImptoVtas in varchar2) return number;
   Function Precio(pCia in varchar2, pArt in varchar2, pLinea in varchar2, pLista in varchar2,
                   pMoneda in varchar2, pPorcimpto in number) return number;
   Function Precio(pCia in varchar2, pArt in varchar2, pLinea in varchar2, pPrecioBase in number,
                   pListaMadre in varchar2, pMoneda in varchar2, pPorc in number, pDesc in number,
                   pPorcImpto in number) RETURN number;
   Function CostoBase(pCia in varchar2, pLista in varchar2, pArt in varchar2, pMoneda in varchar2) return number;
   Function CostoLista(pCia in varchar2, pLista in varchar2, pArt in varchar2,
                      pMoneda in varchar2) return number;

   Function Redondeo(pCia in varchar2, pMoneda in varchar2, pMonto in number) return number;
   Procedure LimpiarMoneda;
   FUNCTION ObtImpuesto(pCia in char, pImp in char, pDef in number default 0) RETURN number;
   Function RedondeoLibPre(pCia in Varchar2, pMon in Varchar2, pMonto in Number) return Number;
   Function PrecioDerDesc(pCia in varchar2, pListaMadre in varchar2, pArt in varchar2, pMoneda IN varchar2,
                          pPorc in number, pDesc in number, pPrecioBase in number default null) RETURN number;
                          
END;
/

CREATE OR REPLACE PACKAGE DbPrecios IS

   procedure Inserta(pCia in char, pLista in varchar2, pMoneda in varchar2, pArt in varchar2,
                     pCosto in number, pPrecio in number, pPorcUt in number, pDesc in number);

END;
/

CREATE OR REPLACE PACKAGE BODY Precios IS

   kCia         CHAR(3);
   kListaActual CHAR(3);
   kMoneda      VARCHAR2(3);
   kListaMadre  CHAR(3);
   kPorcentaje  NUMBER(7,4);
   kMonMadre    VARCHAR2(3);
   kCalcAju     CHAR(1);
   kCiaRed      CHAR(3);
   kMonRed      VARCHAR2(3);
   kCompRed     NUMBER(5,2);
   kMultRed     NUMBER(5,2);
   kFactAju     NUMBER;
   kCompSic     NUMBER(6,2);
   kMultSic     NUMBER(6,2);
   kCiaRedLp    CHAR(3);
   kMonRedLp    VARCHAR2(3);
   kCompRedLp   NUMBER(5,2);
   kMultRedLp   NUMBER(5,2);   
   kCompSicLp   Number(6,2); 
   KMultSicLp   Number(6,2);

   procedure Inserta(pCia in char, pLista in varchar2, pMoneda in varchar2, pArt in varchar2,
                     pCosto in number, pPrecio in number, pPorcUt in number, pDesc in number) is
      pragma autonomous_transaction;
   begin
      begin
         insert into predetlista
            (COD_CIA, COD_LISTA_PRECIO, COD_MONEDA, COD_ARTICULO, COSTO,
             PRECIO_UNITARIO, PORC_UTILIDAD, DESCUENTO, DOCUMENTO)
            values (pCia, pLista, pMoneda, pArt, pCosto, pPrecio, pPorcUt, pDesc, null);
      exception
         when dup_val_on_index then
            null;
      end;
      commit;
   end Inserta;

   Procedure CargarRedondeo(pCia in varchar2, pMoneda in varchar2) is
   begin
      if pCia!=nvl(kCiaRed,' x ') or pMoneda!=nvl(kMonRed,' x ') then
         kCiaRed:=pCia;
         kMonRed:=pMoneda;
         select multredondeo, compredondeo, multsic, compsic
            into kMultRed, kCompRed, kMultSic, kCompSic
         from preparmoneda
         where cod_cia = pCia
           and moneda  = pMoneda
           and tipo    = 'F';
      end if;
   exception
      when no_data_found then
         kCompred:=0;
         kMultred:=0.01;
         kCompsic:=0;
         kMultsic:=0.01;
   end;

   Procedure RenovarLista(pCia in varchar2, pLista in varchar2, pMoneda in varchar2) is
      vCompAju     prelistamon.compaju%type;
      vMultAju     prelistamon.multaju%type;
      vTipCambOri  gen_tipo_cambio.mon_tip_cam%type;
      vTipCambDes  gen_tipo_cambio.mon_tip_cam%type;
   begin
      If pCia<>nvl(kCia,' x ') or pLista<>nvl(kListaActual,' x ') then
         Pre_par.Inicializar(pCia);
         if pLista is not null then
  	    select lista_madre, porcentaje
   	       into kListaMadre, kPorcentaje
            from prelista
   	    where cod_cia=pCia
   	    and cod_lista_precio=pLista;
         else
            kListaMadre:=null;
            kPorcentaje:=null;
         end if;
   	 kCia:=pCia;
   	 kListaActual:=pLista;
   	 kMoneda:=Null;
      elsif nvl(Pre_par.kCia,' x ')!=pCia then
         Pre_par.Inicializar(pCia);
      end if;
      If pMoneda<>nvl(kMoneda,' x ') then
   	 kMonMadre:=null;
   	 kFactAju:=1;
   	 kCalcAju:='N';
         kMoneda:=pMoneda;
      end if;
      if kMoneda is not null and kListaActual is not null then
         begin
            select moneda_orig, AjusteCalculo, CompAju, MultAju
               into kMonMadre, kCalcAju, vCompAju, vMultAju
            from prelistamon
            where cod_cia=pCia
              and cod_lista_precio=kListaActual
              and cod_moneda=kMoneda;
            vTipCambOri:=ConvMoneda.Tipocambio(kMonMadre, sysdate);
            vTipCambDes:=ConvMoneda.Tipocambio(kMoneda, sysdate);
            if kCalcAju='O' then
               vTipCambOri:=trunc((vTipCambOri+nvl(vCompAju,0))/vMultAju)*vMultAju;
            elsif kCalcAju='D' then
               vTipCambDes:=trunc((vTipCambDes+nvl(vCompAju,0))/vMultAju)*vMultAju;
            end if;
            kFactAju:=vTipCambDes/vTipCambOri;
            if kCalcAju='F' then
               kFactAju:=trunc((kFactAju+nvl(vCompAju,0))/vMultAju)*vMultAju;
            end if;
   	 exception
   	    when no_data_found then
   	       null;
         end;
      end if;
   End;
   
   Function PrecioBase(pCia in varchar2, pLista in varchar2, pArt in varchar2, pMoneda in varchar2,
                       pPrecioCorto in varchar2 default 'N') return number is
      vPrecio predetlista.precio_unitario%type;
      vUtil   predetlista.porc_utilidad%type;
      vDesc   predetlista.descuento%type;
      vMonFn  predetlista.cod_moneda%type:=nvl(kMonMadre, pMoneda);
   begin
      select precio_unitario, porc_utilidad, descuento
         into   vPrecio, vUtil, vDesc
      from   predetlista
      where  cod_cia          = pCia
      and    cod_lista_precio = pLista
      and    cod_moneda       = vMonFn
      and    cod_articulo     = pArt;
      if pPrecioCorto='S' then
         vPrecio:=Pre_par.PrecioBase(vPrecio, Pre_par.PorcVar(vUtil, vDesc));
      end if;
      if kMonMadre is not null then
   	 return vPrecio*kFactAju;
      else
         return vPrecio;
      end if;
   exception
      when no_data_found then
   	 return null;
   end PrecioBase;

  Function VariacionPrecio(pCia in varchar2, pLista in varchar2, pArt in varchar2, pMoneda in varchar2) return number is
      Vporc predetlista.porc_utilidad%type;
  begin
      select Pre_Par.PorcVar(porc_utilidad, descuento)
         into Vporc
      from   predetlista
      where  cod_cia          = pCia
      and    cod_lista_precio = pLista
      and    cod_moneda       = pMoneda
      and    cod_articulo     = pArt;
      return nvl(Vporc, 0);
   exception
      when no_data_found then
   	 return kPorcentaje;
   end VariacionPrecio;
   
   FUNCTION PrecioLista(pCia         IN varchar2,
                        pLista       IN varchar2,
                        pArt         IN varchar2,
                        pMoneda      IN varchar2) RETURN number IS
      vPorc   prelista.porcentaje%type;
      vprecio predetlista.precio_unitario%type;
   Begin
      renovarLista(pCia, pLista, pMoneda);
      if kListaMadre is not null then
      	 vprecio:=PrecioBase(pCia, kListaMadre, pArt, pMoneda, 'S');
      	 if vPrecio is not null then
      	    vPorc:=VariacionPrecio(pCia, pLista, pArt, pMoneda);
            vPrecio:=Pre_par.PrecioUtil(vPrecio, vPorc);
      	 end if;
      else
         vprecio:=PrecioBase(pCia, pLista, pArt, pMoneda);
      end if;
      if vPrecio is null and pre_par.klista_precio not in (kListaMadre, pLista) then
         vprecio:=PrecioBase(pCia, pre_par.klista_precio, pArt, pMoneda);
      end if;
      return vPrecio;
   End PrecioLista;
   
   FUNCTION PrecioLista(pCia         IN varchar2,
                        pLista       IN varchar2,
                        pArt         IN varchar2,
                        pMoneda      IN varchar2,
                        pPrecioBase  IN number) RETURN number IS
      vPorc    prelista.porcentaje%type;
      vPrecio  predetlista.precio_unitario%type;
   Begin
      renovarLista(pCia, pLista, pMoneda);
      if kListaMadre is not null then
         vPorc:=VariacionPrecio(pCia, pLista, pArt, pMoneda);
         vPrecio:=Pre_par.PrecioUtil(pPrecioBase, vPorc);
      else
         vPrecio:=pPrecioBase;
      end if;
      return vPrecio;
   end PrecioLista;
   
   Function PrecioDer(pCia in varchar2, pListaMadre in varchar2, pArt in varchar2, pMoneda IN varchar2,
                      pPorc in number, pPrecioBase in number default null) RETURN number is
      vPrecioBase predetlista.precio_unitario%type;
   Begin
      RenovarLista(pCia, null, pMoneda);
      if pPrecioBase is null and pListaMadre is not null then
         vPrecioBase:=PrecioBase(pCia, pListamadre, pArt, pMoneda, 'S');
      else
         vPrecioBase:=pPrecioBase;
      end if;
      return Pre_par.PrecioUtil(vPrecioBase, nvl(pPorc, kPorcentaje));
   End PrecioDer;

   Function PrecioIvi(pPreciolista in number, pPorcImpto in number) RETURN number is
   Begin
      if pPorcimpto>0 and pre_par.kPrecioivi='N' then
         return pPrecioLista*(1+nvl(pPorcimpto,0)/100);
      else
      	 return pPrecioLista;
      end if;
   End PrecioIvi;

   Function PrecioSinIv(pPreciolista in number, pPorcimpto in number) RETURN NUMBER IS
   BEGIN
      if nvl(pPorcimpto,0)>0 and pre_par.kPrecioivi='S' then
         return pPreciolista/(1+nvl(pPorcimpto,0)/100);
      else
         return pPreciolista;
      end if;
   END;   

   Function PrecioSinIv(pCia in varchar2, pArt in varchar2, pLinea in varchar2, pLista in varchar2, pMoneda in varchar2, pImptoVtas in varchar2) return number is
   Begin
      Return PrecioSinIv(PrecioNeto(pCia, PrecioLista(pCia, pLista, pArt, pMoneda), pLinea, pMoneda),
   	                 ObtImpuesto(pCia, pImptovtas));
   End;
   
   Function PrecioNeto(pCia in varchar2, pPreciolista in number, pLinea in varchar2, pMoneda in varchar2) RETURN number is
   Begin
      if Not Pre_Par.EsRegulado(pCia, pLinea) then
      	 return Redondeo(pCia, pMoneda, pPrecioLista);
      else
         return pPrecioLista;
      end if;
   End PrecioNeto;

   Function Precio(pCia in varchar2, pPrecioBase in number, pLinea in varchar2, pMoneda in varchar2, pImptoVtas in varchar2) return number is
   Begin
      Return PrecioNeto(pCia, PrecioIvi(pPrecioBase, ObtImpuesto(pCia, pImptovtas)),
   	                pLinea, pMoneda);
   End Precio;

   Function Precio(pCia in varchar2, pArt in varchar2, pLinea in varchar2, pLista in varchar2,
                   pMoneda in varchar2, pImptoVtas in varchar2) return number is
   Begin
      Return PrecioNeto(pCia, PrecioIvi(PrecioLista(pCia, pLista, pArt, pMoneda),
   	                                ObtImpuesto(pCia, pImptovtas)),
   	                pLinea, pMoneda);
   End Precio;

   Function Precio(pCia in varchar2, pArt in varchar2, pLinea in varchar2, pLista in varchar2,
                   pMoneda in varchar2, pPorcimpto in number) return number is
   Begin
      Return PrecioNeto(pCia, PrecioIvi(PrecioLista(pCia, pLista, pArt, pMoneda), pPorcimpto),
   	                pLinea, pMoneda);
   End Precio;

   Function Precio(pCia in varchar2, pArt in varchar2, pLinea in varchar2, pPrecioBase in number,
                   pListaMadre in varchar2, pMoneda in varchar2, pPorc in number, pDesc in number,
                   pPorcImpto in number) RETURN number IS
   Begin
      if pListaMadre is null then
         Return PrecioNeto(pCia, PrecioIvi(pPrecioBase, pPorcImpto), pLinea, pMoneda);
         --Deberia incluir Pre_par.PrecioUtil(pPrecioBase, nvl(pDeltaPorc, kPorcentaje))? No por compatibilidad
      else
         Return PrecioNeto(pCia, PrecioIvi(PrecioDerDesc(pCia, pListaMadre, pArt, pMoneda, pPorc, pDesc, pPrecioBase),
                                           pPorcImpto),
                           pLinea, pMoneda);
      end if;
   End Precio;

   Function CostoBase(pCia in varchar2, pLista in varchar2, pArt in varchar2, pMoneda in varchar2) return number is
      Vcosto predetlista.costo%type;
      vMonFn predetlista.cod_moneda%type:=nvl(kMonMadre, pMoneda);
   begin
      select costo into   Vcosto
      from   predetlista
      where  cod_cia          = pCia
      and    cod_lista_precio = pLista
      and    cod_moneda       = vMonFn
      and    cod_articulo     = pArt;
      if kMonMadre is not null then
   	 return Vcosto*kFactAju;
      else
         return Vcosto;
      end if;
   exception
      when no_data_found then
   	 return null;
   end CostoBase;

   FUNCTION CostoLista(pCia    in varchar2,
                       pLista  in varchar2,
                       pArt    IN varchar2,
                       pMoneda    IN varchar2) RETURN number IS
      Vcosto predetlista.costo%type;
   Begin
      renovarLista(pCia, pLista, pMoneda);
      if kListaMadre is not null then
      	 Vcosto:=CostoBase(pCia, kListaMadre, pArt, pMoneda);
      else
         Vcosto:=CostoBase(pCia, pLista, pArt, pMoneda);
      end if;
      if Vcosto is null and pre_par.kLista_precio not in (kListaMadre, pLista) then
         Vcosto:=CostoBase(pCia, pre_par.kLista_precio, pArt, pMoneda);
      end if;
      return Vcosto;
   End CostoLista;

   Function Redondeo(pCia in varchar2, pMoneda in varchar2, pMonto in number) return number is
      vResult number(14,2);
   begin
      CargarRedondeo(pCia, pMoneda);
      if kMultRed>0 then
         vResult:=trunc((pMonto+nvl(kCompRed,0))/kMultRed)*kMultRed;
      else
         vResult:=pMonto;
      end if;
      if kMultSic!=0 and Vresult>=kMultSic and mod(Vresult,kMultSic)=0 then
         vResult:=vResult-kCompSic;
      end if;
      return vResult;
   end Redondeo;

   Procedure LimpiarMoneda is
   Begin
      kMoneda:=null;
   End;

   FUNCTION ObtImpuesto(pCia in char, pImp in char, pDef in number default 0) RETURN number IS
      vPorc gen_impuesto.porcentaje%type;
   BEGIN
      if pImp is null then
	 vPorc := 0;
      else
         select porcentaje
            into vPorc
         from gen_impuesto
         where cod_cia=pCia
           and impuesto=pImp;
      end if;
      return nvl(Vporc,0);
   Exception
      when no_data_found then
         return nvl(pDef, 0);
   END;

   Procedure CargarRedondeoLibPre(pCia in Varchar2, pMon in Varchar2) is
   begin
      if pCia!=nvl(kCiaRedLp,' x ') or pMon!=nvl(kMonRedLp,' x ') then
         kCiaRedLp := pCia;
         kMonRedLp := pMon;
         
         select multredondeo, compredondeo, multsic, compsic
            into kMultRedLp, kCompRedLp, kMultSicLp, KCompSicLp
         from preparmoneda
         where cod_cia = pCia
           and moneda  = pMon
           and tipo    = 'P';
      end if;
   exception
      when no_data_found then
         KCompRedLp := 0;
         KMultRedLp := 0.01;
         KCompSicLp := 0;
         KMultSicLp := 0;
   end;

   Function RedondeoLibPre(pCia in Varchar2, pMon in Varchar2, pMonto in Number) return Number is
      vResult number(14,2);
   begin
      CargarRedondeoLibPre(pCia, pMon);
      vResult := trunc((pmonto+nvl(kCompRedLp,0))/kMultRedLp)*kMultRedLp;
      if kMultSicLp!=0 and vResult>=kMultSicLp and Mod(vResult, kMultSicLp)=0 then
      	 vResult:=Vresult-kCompSicLp;
      end if;
      return vResult;
   end RedondeoLibPre;   

   Function PrecioDerDesc(pCia in varchar2, pListaMadre in varchar2, pArt in varchar2, pMoneda IN varchar2,
                          pPorc in number, pDesc in number, pPrecioBase in number default null) RETURN number is
      vPrecioBase predetlista.precio_unitario%type;
   Begin
      RenovarLista(pCia, null, pMoneda);
      if pPrecioBase is null and pListaMadre is not null then
         vPrecioBase:=PrecioBase(pCia, pListamadre, pArt, pMoneda, 'S');
      else
         vPrecioBase:=pPrecioBase;
      end if;
      return Pre_par.PrecioUtil(vPrecioBase, pre_par.PorcVar(nvl(pPorc, kPorcentaje), pDesc));
   End PrecioDerDesc;

END;
/

CREATE OR REPLACE PACKAGE Body DbPrecios IS

   procedure Inserta(pCia in char, pLista in varchar2, pMoneda in varchar2, pArt in varchar2,
                     pCosto in number, pPrecio in number, pPorcUt in number, pDesc in number) is
   Begin
      Precios.Inserta(pCia, pLista, pMoneda, pArt, pCosto, pPrecio, pPorcUt, pDesc);
   End;

END;
/
