PROCEDURE ou FUNCTION

Forum sobre SQL.

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

A diferença básica entre PROCEDURE e FUNCTION é que PROCEDURE pode retornar o resultado de uma consulta, enquanto FUNCTION retorna um único valor.
Até aí.... ok.

Mas... há alguma restrição no uso?

Como teste, estou criando esta função:

Código: Selecionar todos

CREATE FUNCTION ze_PedidoCalculo1( nIdPedido INT )
RETURNS INT

BEGIN
IF nIdPedido IS NULL THEN
   RETURN 0;
END IF;

IF nIdPedido = 0 THEN
   RETURN 0;
END IF;

UPDATE JPPEDIDO
JOIN
 (
   SELECT IPPEDIDO, SUM( IPQTDE * IPPREPED ) AS SOMA
   FROM JPITPED
   WHERE IPPEDIDO = nIdPedido
   GROUP BY IPPEDIDO) AS TEMP
ON TEMP.IPPEDIDO = JPPEDIDO.IDPEDIDO
SET JPPEDIDO.PDVALPRO = TEMP.SOMA
WHERE IDPEDIDO = nIdPedido;

UPDATE JPITPED
JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO
SET IPVALADI = ROUND( JPPEDIDO.PDVALADI / IF( PDVALPRO = 0, 1, PDVALPRO ) * ( JPITPED.IPPREPED * JPITPED.IPQTDE ), 2 )
WHERE JPITPED.IPPEDIDO = nIdPedido;

UPDATE JPITPED
JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO
SET JPITPED.IPPRENOT = ROUND( IF( IPQTDE = 0, 0, ( ( JPITPED.IPPREPED + JPITPED.IPVALADI ) * JPITPED.IPQTDE )
 * ( ( 100 - JPPEDIDO.PDPERDES ) / 100 ) * ( ( 100 + JPPEDIDO.PDPERADI ) / 100 )
 / IF( JPITPED.IPQTDE = 0, 1, JPITPED.IPQTDE ) ), 5 )
WHERE JPITPED.IPPEDIDO = nIdPedido;

UPDATE JPITPED SET IPVALPRO = IPPRENOT * IPQTDE
WHERE IPPEDIDO = nIdPedido;

UPDATE JPPEDIDO
JOIN
 (
SELECT SUM( IPVALPRO ) AS SOMA
FROM JPITPED
WHERE IPPEDIDO = nIdPedido
GROUP BY IPPEDIDO) AS TEMP SET PDVALPRO = TEMP.SOMA
WHERE IDPEDIDO = nIdPedido;

UPDATE JPITPED
JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO SET
 IPVALPRO = ROUND( IPPRENOT * IPQTDE, 2),
 IPVALFRE = ROUND( JPPEDIDO.PDVALFRE * IPVALPRO / IF( JPPEDIDO.PDVALPRO = 0, 1, JPPEDIDO.PDVALPRO ), 2 ),
 IPVALSEG = ROUND( JPPEDIDO.PDVALSEG * IPVALPRO / IF( JPPEDIDO.PDVALPRO = 0, 1, JPPEDIDO.PDVALPRO ), 2 ),
 IPVALOUT = ROUND( JPPEDIDO.PDVALOUT * IPVALPRO / IF( JPPEDIDO.PDVALPRO = 0, 1, JPPEDIDO.PDVALPRO ), 2 ),
 IPVALEXT = ROUND( JPPEDIDO.PDVALEXT * IPVALPRO / IF( JPPEDIDO.PDVALPRO = 0, 1, JPPEDIDO.PDVALPRO ), 2 ),
 IPVALDES = ROUND( JPPEDIDO.PDVALDES * IPVALPRO / IF( JPPEDIDO.PDVALPRO = 0, 1, JPPEDIDO.PDVALPRO ), 2 ),
 IPVALADI = ROUND( JPPEDIDO.PDVALADI * IPVALPRO / IF( JPPEDIDO.PDVALPRO = 0, 1, JPPEDIDO.PDVALPRO ), 2 )
WHERE JPITPED.IPPEDIDO = nIdPedido;

UPDATE JPITPED SET IPVALNOT = IPVALPRO
WHERE IPPEDIDO = nIdPedido;

UPDATE JPPEDIDO
JOIN
 (
   SELECT SUM( IPVALNOT ) AS SOMA
   FROM JPITPED
   WHERE IPPEDIDO = nIdPedido
   GROUP BY IPPEDIDO ) AS TEMP
SET JPPEDIDO.PDVALNOT = TEMP.SOMA
WHERE IDPEDIDO = nIdPedido;

RETURN 1;

END;
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Por enquanto peguei uma diferença.

CALL ze_PedidoCalculo1(1) não funciona se for FUNCTION, só pra PROCEDURE.
SELECT ze_PedidoCalculo1(1) funciona se for FUNCTION, mas não pra PROCEDURE.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Mais uma diferença: não deu pra usar RETURN.
Criei o bloco com o nome de THIS, e pra sair é LEAVE THIS, mas pode ser o nome que quiser.

Código: Selecionar todos

CREATE PROCEDURE ze_CalculaPedido( nIdPedido INT )

THIS: BEGIN
IF nIdPedido IS NULL THEN
   LEAVE THIS;
END IF;

IF nIdPedido = 0 THEN
   LEAVE THIS;
END IF;
.....
END;
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Pensando bem... acho que mais interessante assim:
(nem sei se precisa verificar o parâmetro, porque não deve aceitar NULL)

Código: Selecionar todos

IF COALESCE( nIdPedido, 0 ) = 0 THEN
   LEAVE THIS
END IF
...
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Estou pensando em converter isto:

Código: Selecionar todos

METHOD CalculaValores( nIdPedido ) CLASS SubPedidoClass

   LOCAL nCont, mLei, mpdDifCal, mpdLeis
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   IF nIdPedido == 0
      RETURN NIL
   ENDIF

   // Parte 1 - Rateia over, se houver

   // soma tudo primeiro
   WITH OBJECT cnSQL
      :cSQL := "UPDATE JPPEDIDO" + ;
         " JOIN " + ;
         " ( SELECT IPPEDIDO, SUM( IPQTDE * IPPREPED ) AS SOMA" + ;
         " FROM JPITPED WHERE IPPEDIDO = " + NumberSQL( nIdPedido ) + ;
         " GROUP BY IPPEDIDO ) AS TEMP" + ;
         " ON TEMP.IPPEDIDO = JPPEDIDO.IDPEDIDO" + ;
         " SET JPPEDIDO.PDVALPRO = TEMP.SOMA" + ;
         " WHERE IDPEDIDO = " + NumberSQL( nIdPedido )
      :ExecuteCmd()

      // valor adicional rateado

      :cSQL := "UPDATE JPITPED" + ;
         " JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO" + ;
         " SET IPVALADI = Round( JPPEDIDO.PDVALADI / IF( PDVALPRO = 0, 1, PDVALPRO) * ( JPITPED.IPPREPED * JPITPED.IPQTDE ), 2 )" + ;
         " WHERE JPITPED.IPPEDIDO = " + NumberSQL( nIdPedido )
      :ExecuteCmd()

      :cSQL := "UPDATE JPITPED" + ;
         " JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO" + ;
         " SET JPITPED.IPPRENOT = Round( IF( IPQTDE = 0, 0, ( ( JPITPED.IPPREPED + JPITPED.IPVALADI ) * JPITPED.IPQTDE )" + ;
         " * ( ( 100 - JPPEDIDO.PDPERDES ) / 100 ) * ( ( 100 + JPPEDIDO.PDPERADI ) / 100 )" + ;
         " / IF( JPITPED.IPQTDE = 0, 1, JPITPED.IPQTDE ) ), 5 ) WHERE JPITPED.IPPEDIDO = " + NumberSQL( nidPedido )
      :ExecuteCmd()

      :cSQL := "UPDATE JPITPED" + ;
         " SET IPVALPRO = IPPRENOT * IPQTDE" + ;
         " WHERE IPPEDIDO = " + NumberSQL( nIdPedido )
      :ExecuteCmd()

      // Parte 3 - Soma pra calcular valores rateados

      :cSQL := "UPDATE JPPEDIDO" + ;
         " JOIN" + ;
         " ( SELECT SUM( IPVALPRO ) AS SOMA" + ;
         " FROM JPITPED WHERE IPPEDIDO = " + NumberSQL( nIdPedido ) + ;
         " GROUP BY IPPEDIDO ) AS TEMP" + ;
         " SET PDVALPRO = TEMP.SOMA" + ;
         " WHERE IDPEDIDO = " + NumberSQL( nIdPedido )
      :ExecuteCmd()

      // Parte 4 - Rateio e totais

      :cSQL := "UPDATE JPITPED" + ;
         " JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO" + ;
         " SET" + ;
         " IPVALPRO = Round( IPPRENOT * IPQTDE, 2 ), " + ;
         " IPVALFRE = Round( JPPEDIDO.PDVALFRE * IPVALPRO / IF( JPPEDIDO.PDVALPRO  = 0, 1, JPPEDIDO.PDVALPRO ), 2 ), " + ;
         " IPVALSEG = Round( JPPEDIDO.PDVALSEG * IPVALPRO / IF( JPPEDIDO.PDVALPRO  = 0, 1, JPPEDIDO.PDVALPRO ), 2 ), " + ;
         " IPVALOUT = Round( JPPEDIDO.PDVALOUT * IPVALPRO / IF( JPPEDIDO.PDVALPRO  = 0, 1, JPPEDIDO.PDVALPRO ), 2 ), " + ;
         " IPVALEXT = Round( JPPEDIDO.PDVALEXT * IPVALPRO / IF( JPPEDIDO.PDVALPRO  = 0, 1, JPPEDIDO.PDVALPRO ), 2 ), " + ;
         " IPVALDES = Round( JPPEDIDO.PDVALDES * IPVALPRO / IF( JPPEDIDO.PDVALPRO  = 0, 1, JPPEDIDO.PDVALPRO ), 2 ), " + ;
         " IPVALADI = Round( JPPEDIDO.PDVALADI * IPVALPRO / IF( JPPEDIDO.PDVALPRO  = 0, 1, JPPEDIDO.PDVALPRO ), 2 ) " + ;
         " WHERE JPITPED.IPPEDIDO = " + NumberSQL( nIdPedido )
      :ExecuteCmd()

      :cSQL := "UPDATE JPITPED" + ;
         " SET IPVALNOT = IPVALPRO" + ;
         " WHERE IPPEDIDO = " + NumberSQL( nIdPedido )
      :ExecuteCmd()

      :cSQL := "UPDATE JPPEDIDO" + ;
         " JOIN" + ;
         " ( SELECT SUM( IPVALNOT ) AS SOMA" + ;
         " FROM JPITPED" + ;
         " WHERE IPPEDIDO = " + NumberSQL( nIdPedido ) + ;
         " GROUP BY IPPEDIDO ) AS TEMP" + ;
         " SET JPPEDIDO.PDVALNOT = TEMP.SOMA" + ;
         " WHERE IDPEDIDO = " + NumberSQL( nIdPedido )
      :ExecuteCmd()

      // aqui grava tudo no dbf
      :cSQL := "SELECT * FROM JPITPED WHERE IPPEDIDO = " + NumberSQL( nIdPedido )
      :Execute()
      DO WHILE ! :Eof()
         ::CalculaImpostosProduto( :Number( "IDITPED" ) )
         :MoveNext()
      ENDDO
   ENDWITH

   WITH OBJECT cnSQL
      :cSQL := "UPDATE JPPEDIDO" + ;
         " JOIN" + ;
         ;
         " ( SELECT SUM( IPISSBAS ) AS ISSBAS, SUM( IPISSVAL ) AS ISSVAL, " + ;
         " SUM( IPIIBAS ) AS IIBAS, SUM( IPIIVAL ) AS IIVAL, " + ;
         " SUM( IPIPIBAS ) AS IPIBAS, SUM( IPIPIVAL ) AS IPIVAL, " + ;
         " SUM( IPICMBAS ) AS ICMBAS, SUM( IPICMVAL ) AS ICMVAL, " + ;
         " SUM( IPFCPVAL ) AS FCPVAL, SUM( IPSUBBAS ) AS SUBBAS, " + ;
         " SUM( IPSUBVAL ) AS SUBVAL, " + ;
         " SUM( IPDIFVALI ) AS DIFVALI, SUM( IPDIFVALF ) AS DIFVALF, " + ;
         " SUM( IPPISBAS ) AS PISBAS, SUM( IPPISVAL ) AS PISVAL," + ;
         " SUM( IPCOFBAS ) AS COFBAS, SUM( IPCOFVAL ) AS COFVAL," + ;
         " SUM( IPVALNOT ) AS VALNOT, SUM( IPICSBAS ) AS ICSBAS," + ;
         " SUM( IPICSVAL ) AS ICSVAL, SUM( IPVALADU ) AS VALADU," + ;
         " SUM( IPVALIOF ) AS VALIOF, SUM( IPIMPVAL ) AS IMPVAL," + ;
         " SUM( IPVALCUS ) AS VALCUS, AVG( IPICSALI ) AS ICSALI" + ;
         " FROM JPITPED" + ;
         " WHERE IPPEDIDO = " + NumberSQL( nIdPedido ) + ;
         " GROUP BY IPPEDIDO ) AS TEMP" + ;
         ;
         " SET PDISSBAS = TEMP.ISSBAS, PDISSVAL = TEMP.ISSVAL," + ;
         " PDIIBAS = TEMP.IIBAS, PDIIVAL = TEMP.IIVAL," + ;
         " PDIPIBAS = TEMP.IPIBAS, PDIPIVAL = TEMP.IPIVAL," + ;
         " PDICMBAS = TEMP.ICMBAS, PDICMVAL = TEMP.ICMVAL," + ;
         " PDFCPVAL = TEMP.FCPVAL, PDSUBBAS = TEMP.SUBBAS," + ;
         " PDSUBVAL = TEMP.SUBVAL, PDDIFVALI = TEMP.DIFVALI," + ;
         " PDDIFVALF = TEMP.DIFVALF, PDPISBAS = TEMP.PISBAS," + ;
         " PDPISVAL = TEMP.PISVAL, PDCOFBAS = TEMP.COFBAS," + ;
         " PDCOFVAL = TEMP.COFVAL, PDVALNOT = TEMP.VALNOT," + ;
         " PDICSBAS = TEMP.ICSBAS, PDICSVAL = TEMP.ICSVAL," + ;
         " PDVALADU = TEMP.VALADU, PDVALIOF = TEMP.VALIOF," + ;
         " PDIMPVAL = TEMP.IMPVAL, PDVALCUS = TEMP.VALCUS," + ;
         " PDICSALI = TEMP.ICSALI" + ;
         " WHERE JPPEDIDO.IDPEDIDO = " + NumberSQL( nIdPedido )
      :ExecuteCmd()

      :cSQL := "SELECT * FROM JPITPED WHERE IPPEDIDO = " + NumberSQL( nIdPedido )
      :Execute()
      mpdLeis   := ""
      mpdDifCal := "N"
      DO WHILE ! :Eof()
         mpdDifCal := iif( :String( "IPDIFCAL", 1 ) == "S", "S", mpdDifCal )
         FOR nCont = 1 TO Len( :String( "IPLEIS" ) ) STEP 7
            mLei := Substr( :String( "IPLEIS" ), nCont, 6 )
            IF Val( mLei ) # 0 .AND. ! mLei $ mpdLeis
               mpdLeis := mpdLeis + mLei + ","
            ENDIF
         NEXT
         :MoveNext()
      ENDDO
      :CloseRecordset()

      :QueryCreate()
      :QueryAdd( "PDLEIS", mpdLeis )
      :QueryAdd( "PDDIFCAL", mpdDifCal )
      :QueryExecuteUpdate( "JPPEDIDO", "IDPEDIDO = " + NumberSQL( nIdPedido ) )

   ENDWITH

   RETURN NIL

METHOD CalculaImpostosProduto( nIdItPed ) CLASS SubPedidoClass

   LOCAL mipIcmBas, mipIcmAli, mipIcmRed, mipIcmVal, cIDCfop, nIDImposto, cIdIpiCst, cIdIpiEnq
   LOCAL mipFcpAli, mipFcpVal, cIdIcmCst, cIdPisCst, cIDPisEnq, cIDCofCst, cIDCofEnq
   LOCAL mipIpiBas, mipIpiAli, mipIpiVal, mipImpAli, mipImpVal
   LOCAL mipIssBas, mipIssAli, mipIssVal
   LOCAL mipPisBas, mipPisAli, mipPisVal
   LOCAL mipCofBas, mipCofAli, mipCofVal
   LOCAL mipSubBas, mipSubIva, mipSubAli, mipSubRed, mipSubVal
   LOCAL mipValNot, mipIIBas, mipIIVal
   LOCAL mipIcsBas, mipIcsVal, mipIcsAli, mipIpiIcm
   LOCAL mipValPro, mipValFre, mipValSeg, mipValOut, mipLeis, mipValExt
   LOCAL mipValDes, mipIIAli, mipDifAlii, mipDifAliu, mipDifAlif, mipDifVali, mipDifValf, mipDifBas, mipDifCal
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   IF nIdItPed == 0
      RETURN NIL
   ENDIF
   WITH OBJECT cnSQL
      :cSQL := ;
         " SELECT JPITPED.*," + ;
         " JPPEDIDO.PDTRANSACAO," + ;
         " JPCADASTRO.CDUFENT, JPCADASTRO.CDTRICAD," + ;
         " JPITEM.IETRIPRO," + ;
         " JPTABUF.UFTRIUF," + ;
         " JPTRANSACAO.TRREACAO," + ;
         " JPTABIBPT.IBNACALI," + ;
         " JPTABIBPT.IBIMPALI," + ;
         " JPIMPOSTO.*" + ;
         " FROM JPITPED" + ;
         " LEFT JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO" + ;
         " LEFT JOIN JPCADASTRO ON JPCADASTRO.IDCADASTRO = JPPEDIDO.PDCADASTRO" + ;
         " LEFT JOIN JPITEM ON JPITEM.IDPRODUTO = JPITPED.IPPRODUTO" + ;
         " LEFT JOIN JPTABUF ON JPTABUF.IDUF = JPCADASTRO.CDUFENT" + ;
         " LEFT JOIN JPTRANSACAO ON JPTRANSACAO.IDTRANSACAO = JPPEDIDO.PDTRANSACAO" + ;
         " LEFT JOIN JPIMPOSTO" + ;
         " ON  JPIMPOSTO.IMTRANSACAO = JPPEDIDO.PDTRANSACAO" + ;
         " AND JPIMPOSTO.IMTRIUF = JPTABUF.UFTRIUF" + ;
         " AND JPIMPOSTO.IMTRICAD = JPCADASTRO.CDTRICAD" + ;
         " AND JPIMPOSTO.IMTRIPRO = JPITEM.IETRIPRO" + ;
         " LEFT JOIN JPTABIBPT ON JPTABIBPT.IBCODIGO = JPITEM.IENCM" + ;
         " WHERE IDITPED = " + NumberSQL( nidItPed )
      :Execute()
      nIdImposto := :Number( "IDIMPOSTO" )
      cIdCfOp    := iif( nIdImposto == 999999, :String( "IPCFOP" ),   :String( "IMCFOP" ) )
      mipIIAli   := iif( nIdImposto == 999999, :Number( "IPIIALI" ),  :Number( "IMIIALI" ) )
      mipIssAli  := iif( nIdImposto == 999999, :Number( "IPISSALI" ), :Number( "IMISSALI" ) )
      cIdIpiCst  := iif( nIdImposto == 999999, :String( "IPIPICST" ), :String( "IMIPICST" ) )
      mipIpiAli  := iif( nIdImposto == 999999, :Number( "IPIPIALI" ), :Number( "IMIPIALI" ) )
      mipIpiIcm  := iif( nIdImposto == 999999, :String( "IPIPIICM", 1 ), :String( "IMIPIICM", 1 ) )
      cidIpiEnq  := iif( nIdImposto == 999999, :String( "IPIPIENQ" ), :String( "IMIPIENQ" ) )
      cidIcmCst  := iif( nIdImposto == 999999, :String( "IPICMCST" ), :String( "IMICMCST" ) )
      mipIcmAli  := iif( nIdImposto == 999999, :Number( "IPICMALI" ), :Number( "IMICMALI" ) )
      mipIcmRed  := iif( nIdImposto == 999999, :Number( "IPICMRED" ), :Number( "IMICMRED" ) )
      mipFcpAli  := iif( nIdImposto == 999999, :Number( "IPFCPALI" ), :Number( "IMFCPALI" ) )
      mipSubAli  := iif( nIdImposto == 999999, :Number( "IPSUBALI" ), :Number( "IMSUBALI" ) )
      mipSubIva  := iif( nIdImposto == 999999, :Number( "IPSUBIVA" ), :Number( "IMSUBIVA" ) )
      mipSubRed  := iif( nIdImposto == 999999, :Number( "IPSUBRED" ), :Number( "IMSUBRED" ) )
      mipDifCal  := iif( nIdImposto == 999999, :String( "IPDIFCAL", 1 ), :String( "IMDIFCAL", 1 ) )
      mipDifAlii := iif( nIdImposto == 999999, :Number( "IPDIFALII" ), :Number( "IMDIFALII" ) )
      mipDifAliu := iif( nIdImposto == 999999, :Number( "IPDIFALIU" ), :Number( "IMDIFALIU" ) )
      mipDifAlif := iif( nIdImposto == 999999, :Number( "IPDIFALIF" ), :Number( "IMDIFALIF" ) )
      cIdPisCst  := iif( nIdImposto == 999999, :String( "IPPISCST" ),  :String( "IMPISCST" ) )
      mipPisAli  := iif( nIdImposto == 999999, :Number( "IPPISALI" ),  :Number( "IMPISALI" ) )
      cIdPisEnq  := iif( nIdImposto == 999999, :String( "IPPISENQ" ),  :String( "IMPISENQ" ) )
      cIdCofCst  := iif( nIdImposto == 999999, :String( "IPCOFCST" ),  :String( "IMCOFCST" ) )
      mipCofAli  := iif( nIdImposto == 999999, :Number( "IPCOFALI" ),  :Number( "IMCOFALI" ) )
      cIdCofEnq  := iif( nIdImposto == 999999, :String( "IPCOFENQ" ),  :String( "IMCOFENQ" ) )
      mipIcsAli  := iif( nIdImposto == 999999, :Number( "IPICSALI" ),  :Number( "IMICSALI" ) )
      mipLeis    := iif( nIdImposto == 999999, :String( "IPLEIS" ),    :String( "IMLEIS" ) )
      IF "CONSUMIDOR" $ :String( "TRREACAO" )
         IF hb_ASCan( { "0", "3", "4", "5" }, Left( cIdIcmCst, 1 ),,, .T. ) != 0
            mipImpAli := :Number( "IBNACALI" )
         ELSE
            mipImpAli := :Number( "IBIMPALI" )
         ENDIF
      ELSE
         mipImpAli := 0
      ENDIF
      mipValPro  := Round( :Number( "IPPRENOT" ) * :Number( "IPQTDE" ), 2 )
      mipValFre  := :Number( "IPVALFRE" )
      mipValSeg  := :Number( "IPVALSEG" )
      mipValOut  := :Number( "IPVALOUT" )
      mipValExt  := :Number( "IPVALEXT" )
      mipValDes  := :Number( "IPVALDES" )
      :CloseRecordset()
   ENDWITH
   IF mipIIAli > 0
      mipIIBas := mipValPro
      mipIIVal := Int( mipIIBas * mipIIAli ) / 100
   ELSE
      mipIIBas := 0
      mipIIVal := 0
   ENDIF
   IF mipIssAli > 0
      mipIssBas := mipValPro  + mipIIVal
      mipIssVal := Int( mipIssBas * mipIssAli ) / 100
   ELSE
      mipIssBas := 0
      mipIssAli := 0
      mipIssVal := 0
   ENDIF
   IF mipIpiAli > 0
      mipIpiBas := mipValPro + mipIIVal
      mipIpiVal := Int( mipIpiBas * mipIpiAli ) / 100
   ELSE
      mipIpiBas := 0
      mipIpiAli := 0
      mipIpiVal := 0
   ENDIF
   IF mipIcmAli > 0 .AND. hb_AScan( { "00", "10", "20", "70", "90", "201", "202", "203", "900" }, Substr( cIdIcmCst, 2 ),,, .T. ) != 0
      mipIcmBas := mipValPro + mipValFre + mipValSeg + mipValOut + mipIIVal
      IF mipIpiIcm != "N"
         mipIcmBas += mipIpiVal
      ENDIF
      IF mipIcmRed > 0 .AND. hb_ASCan( { "20", "70", "90", "202", "202", "203", "900" }, Substr( cIdIcmCst, 2 ),,,.T. ) != 0
         mipIcmBas := mipIcmBas - ( Int( mipIcmBas * mipIcmRed ) / 100 )
      ELSE
         mipIcmRed := 0
      ENDIF
      mipIcmVal := Int( mipIcmBas * mipIcmAli ) / 100
   ELSE
      mipIcmBas := 0
      mipIcmAli := 0
      mipIcmVal := 0
   ENDIF
   IF mipFcpAli > 0
      mipFcpVal := Int( mipIcmBas * mipFcpAli ) / 100
   ELSE
      mipFcpVal := 0
   ENDIF
   IF mipSubAli > 0 .AND. hb_ASCan( { "10", "30", "70", "90", "900" }, Substr( cIdIcmCst, 2 ),,, .T. ) != 0
      mipSubBas := mipValPro + mipValFre + mipValSeg + mipValOut + mipIIVal
      IF mipIpiIcm != "N"
         mipSubBas += mipIpiVal
      ENDIF
      mipSubBas := mipSubBas + ( Int( mipSubBas * mipSubIva ) / 100)
      IF mipSubRed > 0 .AND. hb_ASCan( { "20", "70", "90", "900" }, Substr( cIdIcmCst, 2 ),,, .T. ) != 0
         mipSubBas := mipSubBas - ( Int( mipSubBas * mipSubRed ) / 100 )
      ELSE
         mipSubRed := 0
      ENDIF
      mipSubVal := Int( mipSubBas * mipSubAli ) / 100
      mipSubVal := mipSubVal - mipIcmVal
      IF mipSubVal < 0
         mipSubVal := 0
      ENDIF
   ELSE
      mipSubBas := 0
      mipSubIva := 0
      mipSubAli := 0
      mipSubRed := 0
      mipSubVal := 0
   ENDIF
   IF mipDifCal == "S"
      mipDifBas := mipValPro + mipValFre + mipValSeg + mipValOut + mipIIVal
      IF mipIpiIcm != "N"
         mipDifBas += mipIpiVal
      ENDIF
      mipDifVali := Max( Int( ( mipDifBas * mipDifAliu ) - ( mipDifBas * mipDifAlii ) ) / 100, 0 )
      mipDifValf := Int( mipDifBas * mipDifAlif ) / 100
   ELSE
      mipDifBas  := 0
      mipDifVali := 0
      mipDifValf := 0
   ENDIF
   // Aqui sem ST
   mipValNot := mipValPro + mipIIVal + mipIpiVal + mipValFre + mipValSeg + mipValOut + mipValExt
   IF mipPisAli > 0
      mipPisBas := mipValNot
      mipPisVal := Int( mipPisBas * mipPisAli ) / 100
   ELSE
      mipPisBas := 0
      mipPisVal := 0
   ENDIF
   IF mipCofAli > 0
      mipCofBas := mipValNot
      mipCofVal := Int( mipCofBas * mipCofAli ) / 100
   ELSE
      mipCofBas := 0
      mipCofVal := 0
   ENDIF
   IF mipIcsAli > 0
      mipIcsBas := mipValNot
      mipIcsVal := Int( mipIcsBas * mipIcsAli ) / 100
   ELSE
      mipIcsBas := 0
      mipIcsVal := 0
   ENDIF
   // Soma pra nota ST e desconto
   mipValNot := mipValNot - mipValDes + mipSubVal

   IF Left( cIdCfop, 1 ) = "3" .AND. Left( cIdIcmCst, 1 ) == "1" // Importacao direta
      // Formula Pis/Cofins retirada de http://www4.receita.fazenda.gov.br/simulador/Simulacao-tag.jsp
      // Demais retiradas de http://www.comexblog.com.br/importacao/calculando-uma-nf-de-entrada-na-importacao
      mipPisBas := mipValPro * ( ( 1 + ( mipIcmAli / 100 * ( mipIIAli / 100 + ( mipIpiAli / 100 * ( 1 + mipIIAli / 100 ) ) ) ) ) / ( ( 1 - mipPisAli / 100 - mipCofAli / 100 ) * ( 1 - mipIcmAli / 100 ) ) )
      mipPisVal := mipPisBas * mipPisAli / 100
      mipCofBas := mipValPro * ( ( 1 + ( mipIcmAli / 100 * ( mipIIAli / 100 + ( mipIpiAli / 100 * ( 1 + mipIIAli / 100 ) ) ) ) ) / ( ( 1 - mipPisAli / 100 - mipCofAli / 100 ) * ( 1 - mipIcmAli / 100 ) ) )
      mipCofVal := mipCofBas * mipCofAli / 100
      mipIcmBas := mipValPro + mipValFre + mipValSeg + mipValOut + mipIIVal // + mipPisVal + mipCofVal // Pis/Cof calculado sobre ICMS
      IF mipIpiIcm != "N"
         mipIcmBas += mipIpiVal
      ENDIF
      mipIcmBas := Int( mipIcmBas / ( 100 - mipIcmAli ) * 10000 ) / 100
      mipIcmVal := Int( mipIcmBas * mipIcmAli ) / 100
      mipValNot := mipPisBas // equivalente a soma de tudo
   ENDIF
   IF Len( Trim( cIdIcmCst ) ) > 3 .AND. ! Substr( cIdIcmCst, 2 ) == "900" // Simples Nacional
      mipIcmAli := 0
      mipIcmVal := 0
   ENDIF
   //IF jpitped->ipCfOp == "1.604 "
   //   mipValNot := 0
   //ENDIF
   mipImpVal := Round( mipValNot * mipImpAli / 100, 2 )
   WITH OBJECT cnSQL
      :QueryCreate()
      :QueryAdd( "IPVALPRO",  mipValPro )
      :QueryAdd( "IPVALNOT",  mipValNot )
      :QueryAdd( "IPCFOP",    cIdCfop )
      :QueryAdd( "IPTRIBUT",  StrZero( nIdImposto, 6 ) )
      :QueryAdd( "IPCOFALI",  mipCofAli )
      :QueryAdd( "IPCOFBAS",  mipCofBas )
      :QueryAdd( "IPCOFCST",  cIdCofCst )
      :QueryAdd( "IPCOFENQ",  cIdCofEnq )
      :QueryAdd( "IPCOFVAL",  mipCofVal )
      :QueryAdd( "IPDIFALIF", mipDifALif )
      :QueryAdd( "IPDIFALII", mipDifAlii )
      :QueryAdd( "IPDIFALIU", mipDifAliu )
      :QueryAdd( "IPDIFBAS",  mipDifBas )
      :QueryAdd( "IPDIFCAL",  mipDifCal )
      :QueryAdd( "IPDIFVALF", mipDifValf )
      :QueryAdd( "IPDIFVALI", mipDifVAli )
      :QueryAdd( "IPFCPALI",  mipFcpAli )
      :QueryAdd( "IPFCPVAL",  mipFcpVal )
      :QueryAdd( "IPICMALI",  mipIcmAli )
      :QueryAdd( "IPICMBAS",  mipIcmBas )
      :QueryAdd( "IPICMCST",  cIdIcmCst )
      :QueryAdd( "IPICMRED",  mipIcmRed )
      :QueryAdd( "IPICMVAL",  mipIcmVal )
      :QueryAdd( "IPICSBAS",  mipIcsBas )
      :QueryAdd( "IPICSALI",  mipIcsAli )
      :QueryAdd( "IPICSVAL",  mipIcsVal )
      :QueryAdd( "IPIIBAS",   mipIIBas )
      :QueryAdd( "IPIIVAL",   mipIIVal )
      :QueryAdd( "IPIMPVAL",  mipImpVal )
      :QueryAdd( "IPIPIBAS",  mipIpiBas )
      :QueryAdd( "IPIPICST",  cIdIpiCst )
      :QueryAdd( "IPIPIENQ",  cIdIpiEnq )
      :QueryAdd( "IPIPIVAL",  mipIpiVal )
      :QueryAdd( "IPISSALI",  mipIssAli )
      :QueryAdd( "IPISSBAS",  mipIssBas )
      :QueryAdd( "IPISSVAL",  mipIssVal )
      :QueryAdd( "IPLEIS",    mipLeis )
      :QueryAdd( "IPPISALI",  mipPisAli )
      :QueryAdd( "IPPISBAS",  mipPisBas )
      :QueryAdd( "IPPISCST",  cIdPisCst )
      :QueryAdd( "IPPISENQ",  cIdPisEnq )
      :QueryAdd( "IPPISVAL",  mipPisVal )
      :QueryAdd( "IPSUBALI",  mipSubAli )
      :QueryAdd( "IPSUBBAS",  mipSubBas )
      :QueryAdd( "IPSUBIVA",  mipSubIVA )
      :QueryAdd( "IPSUBRED",  mipSubRed )
      :QueryAdd( "IPSUBVAL",  mipSubVal )
      :QueryAdd( "IPINFALT",  LogInfo() )
      :QueryExecuteUpdate( "JPITPED", "IDITPED = " + NumberSQL( nidItPed ) )
   ENDWITH

   RETURN .T.
É todo cálculo do pedido, e trata-se de ler do mysql pra salvar em seguida.
Parece o uso ideal de STORED PROCEDURE.

Dá pra dizer que é converter o aplicativo pra qualquer coisa, sem nem saber que "coisa" vai ser essa, sem importar linguagem de programação ou sistema operacional.
E tudo rodando no servidor, com velocidade máxima !

Continuar assim...
Pode ser interessante pensar em criar telas também no MySQL.... ou com ajuda dele...
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Aproveitando....

Minha rotina já era assim no DBF.
Antes de migrar pro MySQL, já tinha deixado as rotinas de certa forma independentes, só dependendo do posicionamento.
Em MySQL foi ajustá-las, pra posicionar primeiro através do SELECT.
E com STORED PROCEDURE vai ser só converter os cálculos, porque os comandos serão os mesmos.

Já comentei isso sobre fontes: a gente dá uma geral, facilitando para o que vém depois.

Alterei os fontes de DBF, USANDO DBF, mas no jeito pra usar MySQL depois.
Depois ao usar MySQL, procurei aproveitar o MySQL pras atualizações.
A cada etapa eu vou alterando um pouquinho, então sem muito trabalho ou surpresa.
E isso acabou deixando no jeito pra STORED PROCEDURE, e eu nem sabia que poderia usar isso no futuro.

Pois é... enquanto eu aprendia MySQL, ia aprendendo a fazer as coisas de um modo diferente e mais eficiente em DBF.
É como se eu estivesse fazendo treinamento encima do que eu já sabia, como se estivesse fazendo um curso de revisão.
Desse jeito, a gente aprende coisa nova, e vai ficando com o que já conhece "na ponta da língua", pronto pra usar a qualquer hora.

Durante a migração nem percebi isso.

Tem a ver com aquilo de fonte fácil, e de usar compilação -w3 -es2.
A gente não percebe mesmo, mas a mudança principal não é nos fontes.
É como tirar ferrugem do cérebro, um pouquinho por dia, sem nem perceber.

No MySQL tá fazendo muita falta uma checagem estilo -w3 -es2.
Mas é tanto tempo vendo os erros que a compilação -w3 -es2 avisa, que acaba sendo a primeira coisa que vamos conferir.
Algo do tipo: ah este erro... se fosse a compilação -w3 -es2, seria por causa disto... vamos ver...
E isso ajuda muito, porque temos noção de que tipo de erro procurar.

Lembrando:

Você pode compilar com -w3 -es2, ajustar algumas coisas, e voltar a compilar com -w0.
Não precisa tentar o milagre de mudar tudo de uma vez, porque em aplicativo grande isso é impossível.
Pode começar resolvendo erro de faltar LOCAL GetList := {} nos fontes, ficar craque nisso, e depois vai vendo outras coisas.

A propósito....
CLEAR também usa a variável GetList.
Pra limpar a tela, o correto seria CLS, e não CLEAR.
Na compilação -w3 -es2 talvez perceba isso, ou talvez apenas não consiga entender porque reclama de criar GetList sem usar, ou de usar sem ter criado.
é que CLEAR é traduzido pra CLS;GetList := {},SetPos(0,0), se não me engano, comandos a mais que não precisaria só pra limpar tela.
Este é só um exemplo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Se entendi direito, vou ter que criar CURSOR.
Acusa variável não existe, referente a campos do SELECT.

Código: Selecionar todos

CREATE PROCEDURE CalculaImpostosProduto( nIdItPed INT )

THIS:
BEGIN
DECLARE nipIcmBas, nipIcmAli, nIpIcmRed, nipIcmVal, nipFcpAli, nipFcpVal DOUBLE(16,2);
DECLARE nipIpiBas, nipIpiAli, nipIpiVal, nipImpAli, nipImpVal DOUBLE(16,2);
DECLARE nipIssBas, nipIssAli, nipIssVal DOUBLE(16,2);
DECLARE nipPisBas, nipPisAli, nipPisVal DOUBLE(16,2);
DECLARE nipCofBas, nipCofAli, nipCofVal DOUBLE(16,2);
DECLARE nipSubBas, nipSubIva, nipSubAli, nipSubRed, nipSubVal DOUBLE(16,2);
DECLARE nipValNot, nipIIBas, nipIIVal DOUBLE(16,2);
DECLARE nipIcsBas, nipIcsVal, nipIcsAli DOUBLE(16,2);
DECLARE nipValPro, nipValFre, nipValSeg, nipValOut, nipValExt DOUBLE(16,2);
DECLARE nipValDes, nipIIAli, nipDifAlii, nipDifAliu, nipDifAlif DOUBLE(16,2);
DECLARE nipDifVali, nipDifValf, nipDifBas DOUBLE(16,2);
DECLARE cIDCfop, nIDImposto, cIdIpiCst, cIdIpiEnq VARCHAR(50);
DECLARE cIdIcmCst, cIdPisCst, cIDPisEnq, cIDCofCst, cIDCofEnq VARCHAR(50);
DECLARE mipIpiIcm, mipLeis, mipDifCal VARCHAR(50);

IF COALESCE( nIdItPed, 0 ) = 0 THEN
   LEAVE THIS;
END IF;

SELECT JPITPED.*,
   JPPEDIDO.PDTRANSACAO,
   JPCADASTRO.CDUFENT, JPCADASTRO.CDTRICAD,
   JPITEM.IETRIPRO,
   JPTABUF.UFTRIUF,
   JPTRANSACAO.TRREACAO,
   JPTABIBPT.IBNACALI,
   JPTABIBPT.IBIMPALI,
   JPIMPOSTO.*
FROM JPITPED
LEFT JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO
LEFT JOIN JPCADASTRO ON JPCADASTRO.IDCADASTRO = JPPEDIDO.PDCADASTRO
LEFT JOIN JPITEM ON JPITEM.IDPRODUTO = JPITPED.IPPRODUTO
LEFT JOIN JPTABUF ON JPTABUF.IDUF = JPCADASTRO.CDUFENT
LEFT JOIN JPTRANSACAO ON JPTRANSACAO.IDTRANSACAO = JPPEDIDO.PDTRANSACAO
LEFT JOIN JPIMPOSTO
ON  JPIMPOSTO.IMTRANSACAO = JPPEDIDO.PDTRANSACAO
   AND JPIMPOSTO.IMTRIUF = JPTABUF.UFTRIUF
   AND JPIMPOSTO.IMTRICAD = JPCADASTRO.CDTRICAD
   AND JPIMPOSTO.IMTRIPRO = JPITEM.IETRIPRO
LEFT JOIN JPTABIBPT ON JPTABIBPT.IBCODIGO = JPITEM.IENCM
WHERE IDITPED = nidItPed;

SET nIdImposto = IDIMPOSTO;

SET cIdCfOp    = IF( nIdImposto = 999999, IPCFOP,    IMCFOP );
SET nipIIAli   = IF( nIdImposto = 999999, IPIIALI,   IMIIALI );
SET nipIssAli  = IF( nIdImposto = 999999, IPISSALI,  IMISSALI );
SET cIdIpiCst  = IF( nIdImposto = 999999, IPIPICST,  IMIPICST );
SET nipIpiAli  = IF( nIdImposto = 999999, IPIPIALI,  IMIPIALI );
SET cipIpiIcm  = IF( nIdImposto = 999999, IPIPIICM,  IMIPIICM );
SET cidIpiEnq  = IF( nIdImposto = 999999, IPIPIENQ,  IMIPIENQ );
SET cidIcmCst  = IF( nIdImposto = 999999, IPICMCST,  IMICMCST );
SET nipIcmAli  = IF( nIdImposto = 999999, IPICMALI,  IMICMALI );
SET nipIcmRed  = IF( nIdImposto = 999999, IPICMRED,  IMICMRED );
SET nipFcpAli  = IF( nIdImposto = 999999, IPFCPALI,  IMFCPALI );
SET nipSubAli  = IF( nIdImposto = 999999, IPSUBALI,  IMSUBALI );
SET nipSubIva  = IF( nIdImposto = 999999, IPSUBIVA,  IMSUBIVA );
SET nipSubRed  = IF( nIdImposto = 999999, IPSUBRED,  IMSUBRED );
SET cipDifCal  = IF( nIdImposto = 999999, IPDIFCAL,  IMDIFCAL );
SET nipDifAlii = IF( nIdImposto = 999999, IPDIFALII, IMDIFALII );
SET nipDifAliu = IF( nIdImposto = 999999, IPDIFALIU, IMDIFALIU );
SET nipDifAlif = IF( nIdImposto = 999999, IPDIFALIF, IMDIFALIF );
SET cIdPisCst  = IF( nIdImposto = 999999, IPPISCST,  IMPISCST );
SET nipPisAli  = IF( nIdImposto = 999999, IPPISALI,  IMPISALI );
SET cIdPisEnq  = IF( nIdImposto = 999999, IPPISENQ,  IMPISENQ );
SET cIdCofCst  = IF( nIdImposto = 999999, IPCOFCST,  IMCOFCST );
SET nipCofAli  = IF( nIdImposto = 999999, IPCOFALI,  IMCOFALI );
SET cIdCofEnq  = IF( nIdImposto = 999999, IPCOFENQ,  IMCOFENQ );
SET nipIcsAli  = IF( nIdImposto = 999999, IPICSALI,  IMICSALI );
SET cipLeis    = IF( nIdImposto = 999999, IPLEIS,    IMLEIS );

IF TRREACAO LIKE '%CONSUMIDOR%' THEN
   IF LEFT( cIdIcmCst, 1 ) IN ( '0', '3', '4', '5' ) THEN
      SET nipImpAli = IBNACALI;
   ELSE
      SET nipImpAli = IBIMPALI;
   END IF;
ELSE
   SET nipImpAli = 0;
END IF;

SET nipValPro = Round( IPPRENOT * IPQTDE, 2 );
SET nipValFre = IPVALFRE;
SET nipValSeg = IPVALSEG;
SET nipValOut = IPVALOUT;
SET nipValExt = IPVALEXT;
SET nipValDes = IPVALDES;

IF nipIIAli > 0 THEN
   SET nipIIBas = nipValPro;
   SET nipIIVal = Floor( nipIIBas * nipIIAli ) / 100;
ELSE
   SET nipIIBas = 0;
   SET nipIIVal = 0;
END IF;
IF nipIssAli > 0 THEN
   SET nipIssBas = nipValPro  + nipIIVal;
   SET nipIssVal = Floor( nipIssBas * nipIssAli ) / 100;
ELSE
   SET nipIssBas = 0;
   SET nipIssAli = 0;
   SET nipIssVal = 0;
END IF;
IF nipIpiAli > 0 THEN
   SET nipIpiBas = nipValPro + nipIIVal;
   SET nipIpiVal = Floor( nipIpiBas * nipIpiAli ) / 100;
ELSE
   SET nipIpiBas = 0;
   SET nipIpiAli = 0;
   SET nipIpiVal = 0;
END IF;
IF nipIcmAli > 0 AND Substr( cIdIcmCst, 2 ) IN ( '00', '10', '20', '70', '90', '201', '202', '203', '900' ) THEN
   SET nipIcmBas = nipValPro + nipValFre + nipValSeg + nipValOut + nipIIVal;
   IF NOT cipIpiIcm = 'N' THEN
      SET nipIcmBas = nipIcmBas + nipIpiVal;
   END IF;
   IF nipIcmRed > 0 AND Substr( cIdIcmCst, 2 ) IN ( '20', '70', '90', '202', '202', '203', '900' ) THEN
      SET nipIcmBas = nipIcmBas - ( Floor( nipIcmBas * nipIcmRed ) / 100 );
   ELSE
      SET nipIcmRed = 0;
   END IF;
   SET nipIcmVal = Floor( nipIcmBas * nipIcmAli ) / 100;
ELSE
   SET nipIcmBas = 0;
   SET nipIcmAli = 0;
   SET nipIcmVal = 0;
END IF;
IF nipFcpAli > 0 THEN
   SET nipFcpVal = Floor( nipIcmBas * nipFcpAli ) / 100;
ELSE
   SET nipFcpVal = 0;
END IF
IF nipSubAli > 0 AND Substr( cIdIcmCst, 2 ) IN ( '10', '30', '70', '90', '900' ) THEN
   SET nipSubBas = nipValPro + nipValFre + nipValSeg + nipValOut + nipIIVal;
   IF NOT cipIpiIcm = 'N' THEN
      SET nipSubBas = nipSubBas + nipIpiVal;
   END IF;
   SET nipSubBas = nipSubBas + ( Floor( nipSubBas * nipSubIva ) / 100 );
   IF nipSubRed > 0 .AND. Substr( cIdIcmCst, 2 ) IN ( '20', '70', '90', '900' ) THEN
      SET nipSubBas = nipSubBas - ( Floor( nipSubBas * nipSubRed ) / 100 );
   ELSE
      SET nipSubRed = 0;
   END IF
   SET nipSubVal = Floor( nipSubBas * nipSubAli ) / 100;
   SET nipSubVal = nipSubVal - nipIcmVal;
   IF nipSubVal < 0 THEN
      SET nipSubVal = 0;
   END IF
ELSE
   SET nipSubBas = 0;
   SET nipSubIva = 0;
   SET nipSubAli = 0;
   SET nipSubRed = 0;
   SET nipSubVal = 0;
END IF
IF cipDifCal = 'S' THEN
   SET nipDifBas = nipValPro + nipValFre + nipValSeg + nipValOut + nipIIVal;
   IF NOT cipIpiIcm = 'N' THEN
      SET nipDifBas = nipDifBas + nipIpiVal;
   END IF
   SET nipDifVali = Max( Floor( ( nipDifBas * nipDifAliu ) - ( nipDifBas * nipDifAlii ) ) / 100, 0 );
   SET nipDifValf = Floor( nipDifBas * nipDifAlif ) / 100;
ELSE
   SET nipDifBas  = 0;
   SET nipDifVali = 0;
   SET nipDifValf = 0;
END IF;
/* Aqui sem ST */
SET nipValNot = nipValPro + nipIIVal + nipIpiVal + nipValFre + nipValSeg + nipValOut + nipValExt;
IF nipPisAli > 0 THEN
   SET nipPisBas = nipValNot;
   SET nipPisVal = Floor( nipPisBas * nipPisAli ) / 100;
ELSE
   SET nipPisBas = 0;
   SET nipPisVal = 0;
END IF;
IF nipCofAli > 0 THEN
   SET nipCofBas = nipValNot;
   SET nipCofVal = Floor( nipCofBas * nipCofAli ) / 100;
ELSE
   SET nipCofBas = 0;
   SET nipCofVal = 0;
END IF;
IF nipIcsAli > 0 THEN
   SET nipIcsBas = nipValNot;
   SET nipIcsVal = Floor( nipIcsBas * nipIcsAli ) / 100;
ELSE
   SET nipIcsBas = 0;
   SET nipIcsVal = 0;
END IF;
/* Soma pra nota ST e desconto */
SET nipValNot = nipValNot - nipValDes + nipSubVal;

IF Left( cIdCfop, 1 ) = '3' AND Left( cIdIcmCst, 1 ) = '1' THEN /* Importacao direta */
   /* Formula Pis/Cofins retirada de http://www4.receita.fazenda.gov.br/simulador/Simulacao-tag.jsp */
   /* Demais retiradas de http://www.comexblog.com.br/importacao/calculando-uma-nf-de-entrada-na-importacao */
   SET nipPisBas = nipValPro * ( ( 1 + ( nipIcmAli / 100 * ( nipIIAli / 100 + ( nipIpiAli / 100 * ( 1 + nipIIAli / 100 ) ) ) ) ) / ( ( 1 - nipPisAli / 100 - nipCofAli / 100 ) * ( 1 - nipIcmAli / 100 ) ) );
   SET nipPisVal = nipPisBas * nipPisAli / 100;
   SET nipCofBas = nipValPro * ( ( 1 + ( nipIcmAli / 100 * ( nipIIAli / 100 + ( nipIpiAli / 100 * ( 1 + nipIIAli / 100 ) ) ) ) ) / ( ( 1 - nipPisAli / 100 - nipCofAli / 100 ) * ( 1 - nipIcmAli / 100 ) ) );
   SET nipCofVal = nipCofBas * nipCofAli / 100;
   SET nipIcmBas = nipValPro + nipValFre + nipValSeg + nipValOut + nipIIVal ;// + mipPisVal + mipCofVal // Pis/Cof calculado sobre ICMS
   IF NOT cipIpiIcm = 'N' THEN
      SET nipIcmBas = nipIcmBas + nipIpiVal;
   END IF;
   SET nipIcmBas = Floor( nipIcmBas / ( 100 - nipIcmAli ) * 10000 ) / 100;
   SET nipIcmVal = Floor( nipIcmBas * nipIcmAli ) / 100;
   SET nipValNot = nipPisBas; /* equivalente a soma de tudo */
END IF;
IF Len( Trim( cIdIcmCst ) ) > 3 .AND. NOT Substr( cIdIcmCst, 2 ) = '900' THEN /* Simples Nacional */
   SET nipIcmAli = 0;
   SET nipIcmVal = 0;
END IF;

/* IF jpitped->ipCfOp = '1.604 ' */
/*   mipValNot = 0 */
/* END IF */

SET nipImpVal = Round( nipValNot * nipImpAli / 100, 2 );

UPDATE JPITPED SET
IPVALPRO  = nipValPro,
IPVALNOT  = nipValNot,
IPCFOP    = cIdCfop,
IPTRIBUT  = nIdImposto,
IPCOFALI  = nipCofAli,
IPCOFBAS  = nipCofBas,
IPCOFCST  = cIdCofCst,
IPCOFENQ  = cIdCofEnq,
IPCOFVAL  = nipCofVal,
IPDIFALIF = nipDifALif,
IPDIFALII = nipDifAlii,
IPDIFALIU = nipDifAliu,
IPDIFBAS  = nipDifBas,
IPDIFCAL  = nipDifCal,
IPDIFVALF = nipDifValf,
IPDIFVALI = nipDifVAli,
IPFCPALI  = nmipFcpAli,
IPFCPVAL  = nipFcpVal,
IPICMALI  = nipIcmAli,
IPICMBAS  = nipIcmBas,
IPICMCST  = cIdIcmCst,
IPICMRED  = nipIcmRed,
IPICMVAL  = nipIcmVal,
IPICSBAS  = nipIcsBas,
IPICSALI  = nipIcsAli,
IPICSVAL  = nipIcsVal,
IPIIBAS   = nipIIBas,
IPIIVAL   = nipIIVal,
IPIMPVAL  = nipImpVal,
IPIPIBAS  = nipIpiBas,
IPIPICST  = cIdIpiCst,
IPIPIENQ  = cIdIpiEnq,
IPIPIVAL  = nipIpiVal,
IPISSALI  = nipIssAli,
IPISSBAS  = nipIssBas,
IPISSVAL  = nipIssVal,
IPLEIS    = nipLeis,
IPPISALI  = nipPisAli,
IPPISBAS  = nipPisBas,
IPPISCST  = cIdPisCst,
IPPISENQ  = cIdPisEnq,
IPPISVAL  = nipPisVal,
IPSUBALI  = nipSubAli,
IPSUBBAS  = nipSubBas,
IPSUBIVA  = nipSubIVA,
IPSUBRED  = nipSubRed,
IPSUBVAL  = nipSubVal,
IPINFALT  = LogInfo()
WHERE IDITPED = nIdItPed;

END

José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

A propósito....

Lembra arquivo BATCH. (BAT)

Código: Selecionar todos

:LOOP
SET VARIAVEL = 5
É interessante que, mudando o ponto de vista, acaba achando tudo conhecido.... rs

E o ponto e vírgula (;)...
É pra que seja executado igual BAT, um comando por vez.

Fica até interessante entender o porquê do ponto e vírgula....
Tudo é uma linha só, e o MySQL sempre otimiza tudo.
De repente, ele poderia fazer certas contas primeiro, pra ser mais rápido, e bagunçar todo resultado.
Além disso, tudo junto acaba sendo comando inexistente.
O ponto e vírgula é justamente pra indicar cada comando, e cada ponto de parada antes de prosseguir, já que um resultado pode depender de resultados anteriores.

No Harbour:

Código: Selecionar todos

IF n > 10; n := 0; ENDIF
Olhem aí mais outra coisa conhecida... não é exatamente igual, mas é parecido.

Estou mostrando essas coisas, assim chama a atenção que o que pode parecer diferente, até já usamos no Harbour.
Pode ajudar aos que ainda acham tudo uma dificuldade.

O SQL acaba lembrando dBASE, Clipper, Harbour, Visual Basic, Delphi, tudo ao mesmo tempo, igual a tudo e diferente de tudo.
É tudo questão de paciência, e de pegar os pontos conhecidos como referência.

O que parece coisa de doido.... acaba parecendo as doideiras que nós doidos sempre usamos kkkk

Nota: só estou enxergando o que está na frente do nariz... isso ajuda a entender um pouco mais fácil, e aproveitando pra compartilhar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Esqueci de dizer:

Isso do ponto e vírgula, já se trata de funções ou rotinas criadas dentro do servidor.
No uso normal, isso não entra.
Por enquanto isso está só em meus testes, no aplicativo não tem nada disso.

Mas com certeza, alguns já fazem uso disso faz tempo, e conhecem muito mais que eu.

Ainda estou aprendendo, ainda NÃO funcionaram essas duas primeiras STORED PROCEDUREs.
Parece ser aquilo que comentei, algo sobre definir CURSOR para as consultas.
Devagar eu chego lá...

Por enquanto basta estar achando tudo parecido com coisas já usadas, assim dá pra fazer testes mais tranquilamente, e com coisas muito úteis.
Quem é que não vai calcular impostos/pedidos?
Acho que depois desse, o resto vai ser refresco.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Já vi que isto aqui vai gerar um trabalhão extra:

Código: Selecionar todos

SET nIdImposto = IDIMPOSTO;

SET cIdCfOp    = IF( nIdImposto = 999999, IPCFOP,    IMCFOP );
SET nipIIAli   = IF( nIdImposto = 999999, IPIIALI,   IMIIALI );
SET nipIssAli  = IF( nIdImposto = 999999, IPISSALI,  IMISSALI );
SET cIdIpiCst  = IF( nIdImposto = 999999, IPIPICST,  IMIPICST );
SET nipIpiAli  = IF( nIdImposto = 999999, IPIPIALI,  IMIPIALI );
SET cipIpiIcm  = IF( nIdImposto = 999999, IPIPIICM,  IMIPIICM );
SET cidIpiEnq  = IF( nIdImposto = 999999, IPIPIENQ,  IMIPIENQ );
SET cidIcmCst  = IF( nIdImposto = 999999, IPICMCST,  IMICMCST );
SET nipIcmAli  = IF( nIdImposto = 999999, IPICMALI,  IMICMALI );
SET nipIcmRed  = IF( nIdImposto = 999999, IPICMRED,  IMICMRED );
SET nipFcpAli  = IF( nIdImposto = 999999, IPFCPALI,  IMFCPALI );
SET nipSubAli  = IF( nIdImposto = 999999, IPSUBALI,  IMSUBALI );
SET nipSubIva  = IF( nIdImposto = 999999, IPSUBIVA,  IMSUBIVA );
SET nipSubRed  = IF( nIdImposto = 999999, IPSUBRED,  IMSUBRED );
SET cipDifCal  = IF( nIdImposto = 999999, IPDIFCAL,  IMDIFCAL );
SET nipDifAlii = IF( nIdImposto = 999999, IPDIFALII, IMDIFALII );
SET nipDifAliu = IF( nIdImposto = 999999, IPDIFALIU, IMDIFALIU );
SET nipDifAlif = IF( nIdImposto = 999999, IPDIFALIF, IMDIFALIF );
SET cIdPisCst  = IF( nIdImposto = 999999, IPPISCST,  IMPISCST );
SET nipPisAli  = IF( nIdImposto = 999999, IPPISALI,  IMPISALI );
SET cIdPisEnq  = IF( nIdImposto = 999999, IPPISENQ,  IMPISENQ );
SET cIdCofCst  = IF( nIdImposto = 999999, IPCOFCST,  IMCOFCST );
SET nipCofAli  = IF( nIdImposto = 999999, IPCOFALI,  IMCOFALI );
SET cIdCofEnq  = IF( nIdImposto = 999999, IPCOFENQ,  IMCOFENQ );
SET nipIcsAli  = IF( nIdImposto = 999999, IPICSALI,  IMICSALI );
SET cipLeis    = IF( nIdImposto = 999999, IPLEIS,    IMLEIS );
Isso porque eu teria que declarar TUDO, praticamente triplicar as variáveis.
Mas já tive uma idéia:

Código: Selecionar todos

IF nIdImposto <> 999999 THEN
   UPDATE JPITPED SET ....;
END IF;
Deste jeito, ao invés de triplicar as variáveis, já vém pronto.
Tudo bem, vou acabar colocando os dois nomes no comando de atualização, mas elas deixam de ser variáveis.

Acho que vou fazer isso no fonte Harbour primeiro, porque nele é mais "confortável" mexer.
E já limpa o fonte antes da conversão.
Jogar fora o que já fiz, fazer o que....

Às vezes fico imaginando se fosse direto no MySQL, se seria tão interessante.
Converter um fonte que já existe é uma coisa, mas fazer do ZERO... pode ter diferença.

Das duas uma: ou complica, ou a gente encontra formas melhores de fazer, como aconteceu agora.

Pois é... a gente vai se adaptando às necessidades e/ou recursos.

Só traduzindo essa parte:
É como se eu usasse um REPLACE ALL nos produtos do pedido.
Isso vai deixar gravado o que está nesses iifs(), e depois é só pegar direto o que está gravado, pra completar os cálculos.

O comando FETCH copia direto da consulta para as variáveis, mas tem que indicar os nomes da consulta e das variáveis.

Comparando, seria como no dbase:
SUM(VALOR), SUM(IMPOSTO) TO A,B FOR pedido = 10

Pelo menos vai eliminar muitas linhas com SET variavel = valor.

Pois é... complica ao mesmo tempo que facilita.

Se tiver outra forma de fazer isso... por favor avisem.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

PROCEDURE ou FUNCTION

Mensagem por alxsts »

Olá!

Segundo os mais experientes com SQL, o uso de cursores (CURSOR = CUrrent Set Of Records) deve ser sempre a última opção a ser escolhida.

SQL foi projetado para trabalhar com conjuntos de linhas. Assim, a abordagem procedural (linha a linha) é sempre mais lenta. Esta lentidão varia entre os SGBDS. Dizem que no SQL Server é bem ruim e que no Oracle é melhor.

O artigo Understanding “Set based” and “Procedural” approaches in SQL pode ajudar a entender mais sobre o assunto.
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

alxsts escreveu: Segundo os mais experientes com SQL, o uso de cursores (CURSOR = CUrrent Set Of Records) deve ser sempre a última opção a ser escolhida.
É que só encontrei essa opção na internet.
Não encontrei outra.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

PROCEDURE ou FUNCTION

Mensagem por alxsts »

Olá!

Está pensando em CURSOR para poder fazer o FETCH para dentro das variáveis? Dentro da stored procedure, você pode fazer isto com INTO:

Código: Selecionar todos

SELECT Id, dateCreated
  INTO val_id, val_datecreated
 FROM products
 WHERE pName = iName
A lista de colunas tem que ter a mesma quantidade tanto no SELECT como no INTO e devem estar na mesma ordem, é claro. E não dá para usar SELECT *.
JoséQuintas escreveu:01 SET nIdImposto = IDIMPOSTO;
02  
03 SET cIdCfOp    = IF( nIdImposto = 999999, IPCFOP,    IMCFOP );
04 SET nipIIAli   = IF( nIdImposto = 999999, IPIIALI,   IMIIALI );
Na linha 01 acima, de onde vem IDIMPOSTO?

Estes SETs da linha 03 em diante, acho que dá pra resolver os IFs no próprio SELECT e jogar os resultados nas variáveis com INTO.
Algo parecido com:

Código: Selecionar todos

SELECT CASE WHEN COALESCE(IDIMPOSTO, 999999) = 999999 THEN IPCFOP ELSE IMCFOP END,
       CASE WHEN COALESCE(IDIMPOSTO, 999999) = 999999 THEN IPIIALI ELSE IMIIALI END
  INTO nIdImposto, nipIIAli 
FROM ...;
Como são itens de pedido, acho que tem que ser CURSOR mesmo. Mas são poucas linhas.
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

PROCEDURE ou FUNCTION

Mensagem por JoséQuintas »

Ok, valeu, depois encontrei isso, do INTO.

A sugestão do SELECT é interessante, e dá até pra alterar agora mesmo no comando original, antes da SP.
Deste jeito, acaba até seguindo o que costumo comentar: antes de partir pra uma coisa nova, fazer revisão nos fontes primeiro, e isso tá valendo também para comandos SQL.
Estarei movendo do Harbour para o comando SQL, e depois vai ser só usar o mesmo comando SQL na SP.
O chato é ter que alterar os nomes e usar alias, mas só é chato pros fontes velhos, porque vão precisar alteração.

Acho que vou fazer mais um teste:

STORED PROCEDURE significa PROCEDURE armazenada.
De repente dá pra usar PROCEDURE NÃO armazenada.
Vou testar BEGIN/END nos comandos, pra enviar mais de um comando por vez.
Se der certo, vou ter a procedure pronta, antes mesmo de salvá-la no servidor.
Até agora só tenho usado um comando por vez, e talvez seja isso que falte.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder