Página 1 de 1

Vencimentos malucos

Enviado: 30 Ago 2013 21:37
por JoséQuintas
Difícil decidir em que tópico colocar, mas de certa forma, o Harbour é que vai acabar fazendo os cálculos.

Consegui criar uma configuração de prazos de pagamento.
Queria saber de outros prazos, pra ver se consegui pegar todos.

O cliente tem alguns prazos que parecem malucos, mas por incrível que pareça são reais.

- Tradicional, N dias e N parcelas, como exemplo 5 parcelas vencendo em 2/5/7/10/20 dias
- Vencimento em determinado dia do próximo mês
- Emissão de 1 a 10 vence 10/mes seguinte, 11 a 20 vence 20/mes seguinte, 21 a 31 vence 30/mes seguinte
- Emissão de 1 a 10 vence 23/mes seguinte, 11 a 20 vence 5/mes seguinte, 21 a 31 vence 23/mes+2
- Emissão de terça vence em 18 dias, emissão de quinta vence em 15 dias (tudo indica que é pra vencer no feriado)
- Emissão de um mês vence dia 15 do mês seguinte

Acho que basicamente são esses, com algumas variações.

Depois aconteceu a seguinte situação:
Nota emitida na sexta, com vencimento 2 dias, pra ser entregue na segunda.
Resultado: a mercadoria chegaria na segunda com a fatura já vencida.
Então acrescentei a opção de fazer o cálculo pela data de saída no próprio cadastro de formas de pagamento (inicialmente o cliente iria modificar todas, mas tive essa idéia)

Algum prazo mais maluco?

Obs. Acho que ficou relativamente fácil para o usuário. Hoje até acrescentei checagem de prazo repetido, já que é só comparar configuração.

Vencimentos malucos

Enviado: 10 Dez 2013 14:36
por JoséQuintas
E não é que apareceram mais:

- Vencimento tem que ser ou terça feira ou quinta feira da mesma semana
- Vencimento tem que ser quarta feira da semana em que completar 21 dias, ou seja, se o cálculo de 21 dias resultar em segunda ou terça avança pra quarta, se resultar quinta ou sexta volta pra quarta da mesma semana.

O curioso é que geralmente são grandes empresas que pedem esse tipo de vencimento diferente.

Vencimentos malucos

Enviado: 11 Dez 2013 11:32
por asimoes
José,

Complicada essa regra !

Vencimentos malucos

Enviado: 11 Dez 2013 12:35
por JoséQuintas
Pois é.
Mas por incrível que pareça, resolvi com os parâmetros que já tinha antes, e um pequeno ajuste.
Tenho lá na configuração:

P-Padrão, D-Dia do mês, S-Dia da Semana

No P-Padrão, apenas quantidade de dias, e é o único que aceita várias parcelas, tipo: 30,60,90,120, o sistema divide o valor por 4 e calcula o vencimento somando esses dias.

No D-Dia e S-Semana é vencimento único, com 5 regras contendo isto:
De
Até
Avançar mês em
Avançar dia em
Dia Final

No de/até e dia final é um número.
Esse número pode ser DIA ou SEMANA.

O que alterei agora, em tela, foi pra aceitar semana NEGATIVA.
E talvez aumente pra 7 regras, para o caso de precisar uma regra pra cada dia da semana.

O segundo caso foi mais fácil:

De 1 a 7 (domingo a sábado), avançar dia em 21, e dia final = -4 (quarta da mesma semana)

No primeiro caso, precisa usar mais de uma regra:
De 1 a 4 (domingo a quarta), avançar dia em 21, e dia final = 3 (terça)
De 5 a 7 (quinta a sábado), avançar dia em 21, e dia final = -5 (quinta da mesma semana)

E até que a rotina não está tão complicada.
Está grande, mas não complicada.

Ah sim, e também a opção pela data de emissão da nota, ou data de saída.
Porque existe vencimento 1 dia, e se a nota fosse emitida na sexta pra entrega na segunda, chegaria já vencida.

Vencimentos malucos

Enviado: 11 Dez 2013 12:39
por JoséQuintas
Vou postar em partes a rotina de cálculo.
Ela também calcula acréscimo/desconto, e calcula as parcelas (se for a padrão)
Inicialmente pensei em fórmulas ou codeblock, mas achei melhor assim.

Código: Selecionar todos

FUNCTION CalculaVencto( nValorTotal, dDatEmi, dDatSai, oParcelas, ;
   cEmiSai, cPadrao, cParcelas, nAdiciona, nDesconto, ;
   nDe1, nAte1, nQtMes1, nQtDia1, nDiaFim1, ;
   nDe2, nAte2, nQtMes2, nQtDia2, nDiaFim2, ;
   nDe3, nAte3, nQtMes3, nQtDia3, nDiaFim3, ;
   nDe4, nAte4, nQtMes4, nQtDia4, nDiaFim4, ;
   nDe5, nAte5, nQtMes5, nQtDia5, nDiaFim5 )
//   nDe6, nAte6, nQtMes6, nQtDia6, nDiaFim6 )
   LOCAL dDatRef, nCont
   IF cEmiSai == "S"
      dDatRef := dDatSai
   ELSE
      dDatRef := dDatEmi
   ENDIF
   oParcelas := Array( 25 )
   FOR nCont = 1 TO 25
      oParcelas[ nCont ] := { 0, Ctod(""), 0 }
   NEXT
   IF nAdiciona != 0 .OR. nDesconto != 0
      nValorTotal := nValorTotal + ( Int( nValorTotal * nAdiciona ) / 100 )
      nValorTotal := nValorTotal - ( Int( nValorTotal * nAdiciona ) / 100 )
   ENDIF
   oParcelas[ 1, 1 ] := nValorTotal
   oParcelas[ 1, 2 ] := dDatRef
   IF cPadrao == "S"
      IF     CalculaVenctoSemana( @oParcelas, nDe1, nAte1, nQtMes1, nQtDia1, nDiaFim1 )
	  ELSEIF CalculaVenctoSemana( @oParcelas, nDe2, nAte2, nQtMes2, nQtDia2, nDiaFim2 )
	  ELSEIF CalculaVenctoSemana( @oParcelas, nDe3, nAte3, nQtMes3, nQtDia3, nDiaFim3 )
	  ELSEIF CalculaVenctoSemana( @oParcelas, nDe4, nAte4, nQtMes4, nQtDia4, nDiaFim4 )
      ELSEIF CalculaVenctoSemana( @oParcelas, nDe5, nAte5, nQtMes5, nQtDia5, nDiaFim5 )
//      ELSEIF CalculaVenctoSemana( @oParcelas, nDe6, nAte6, nQtMes6, nQtDia6, nDiaFim6 )
	  ENDIF
   ELSEIF cPadrao == "D"
      IF     CalculaVenctoDia( @oParcelas, nDe1, nAte1, nQtMes1, nQtDia1, nDiaFim1 )
	  ELSEIF CalculaVenctoDia( @oParcelas, nDe2, nAte2, nQtMes2, nQtDia2, nDiaFim2 )
	  ELSEIF CalculaVenctoDia( @oParcelas, nDe3, nAte3, nQtMes3, nQtDia3, nDiaFim3 )
	  ELSEIF CalculaVenctoDia( @oParcelas, nDe4, nAte4, nQtMes4, nQtDia4, nDiaFim4 )
      ELSEIF CalculaVenctoDia( @oParcelas, nDe5, nAte5, nQtMes5, nQtDia5, nDiaFim5 )
//      ELSEIF CalculaVenctoDia( @oParcelas, nDe6, nAte6, nQtMes6, nQtDia6, nDiaFim6 )
	  ENDIF
   ELSE
      CalculaVenctoPadrao( @oParcelas, cParcelas )
   ENDIF
   FOR nCont = 1 TO Len( oParcelas )
      oParcelas[ nCont, 3 ] := oParcelas[ nCont, 2 ] - dDatRef
   NEXT
   RETURN NIL

Vencimentos malucos

Enviado: 11 Dez 2013 12:43
por JoséQuintas

Código: Selecionar todos

FUNCTION CalculaVenctoPadrao( oParcelas, cLstDias )
   LOCAL acQtDias := {}, nCont, nVlParcela, nDias, nValorTotal, dDatEmissao
   nValorTotal := oParcelas[ 1, 1 ]
   dDatEmissao := oParcelas[ 1, 2 ]
   HB_SYMBOL_UNUSED( oParcelas )
   FOR nCont = 1 TO Len( Trim( cLstDias ) )
      nDias := Val( Substr( cLstDias, nCont * 5 - 4, 4 ) )
      IF nDias != 0
         AAdd( acQtDias, nDias )
      ENDIF
   NEXT
   IF Len( acQtDias ) == 0
      AAdd( acQtDias, 0 )
   ENDIF
   nVlParcela := Int( nValorTotal * 100 / Len( acQtDias ) ) / 100
   FOR nCont = 1 TO Len( acQtDias )
      IF nCont == 1
         oParcelas[ nCont, 1 ] := nValorTotal - ( ( Len( acQtDias ) - 1 ) * nVlParcela ) // com a diferenca
      ELSE
         oParcelas[ nCont, 1 ] := nVlParcela
      ENDIF
      oParcelas[ nCont, 2 ] := dDatEmissao + acQtDias[ nCont ]
   NEXT
   RETURN .T.

Vencimentos malucos

Enviado: 11 Dez 2013 12:50
por JoséQuintas

Código: Selecionar todos

FUNCTION CalculaVenctoDia( oParcelas, nDe, nAte, nQtMes, nQtDia, nDiaFim )
   LOCAL dDatEmissao, dDatVencto, dDatCalc, nCont
   dDatEmissao := dDatVencto := oParcelas[ 1 , 2 ]
   HB_SYMBOL_UNUSED( oParcelas )
   IF Day( dDatEmissao ) < nDe .OR. Day( dDatEmissao ) > nAte
      RETURN .F.
   ENDIF
   IF nQtMes > 0
      dDatCalc := dDatEmissao
      FOR nCont = 1 TO nQtMes
         DO WHILE Month( dDatCalc ) == Month( dDatVencto )
   	        dDatVencto += 10
         ENDDO
         dDatCalc := dDatVencto
      NEXT
	  dDatVencto := dDatVencto - Day( dDatVencto ) + 1
   ENDIF
   IF nQtDia > 0
      dDatVencto := dDatVencto + nQtDia
   ENDIF
   IF nDiaFim != 0
      IF Month( dDatVencto ) == 2
         IF nDiaFim > 28
            nDiaFim := iif( Mod( Year( dDatVencto ), 4 ) == 0, 29, 28 )
         ENDIF
      ELSEIF StrZero( Month( dDatVencto ), 2 ) $ "04,06,09,11"
         IF nDiaFim > 30
            nDiaFim := 30
         ENDIF
      ENDIF
      DO WHILE Day( dDatVencto ) != nDiaFim
         dDatVencto := dDatVencto + 1
      ENDDO
   ENDIF
   oParcelas[ 1, 2 ] := dDatVencto
   oParcelas[ 1, 3 ] := dDatVencto - dDatEmissao
   RETURN .T.

Vencimentos malucos

Enviado: 11 Dez 2013 12:51
por JoséQuintas

Código: Selecionar todos

STATIC FUNCTION CalculaVenctoSemana( oParcelas, nDe, nAte, nQtMes, nQtDia, nDiaFim )
   LOCAL dDatEmissao, dDatVencto, dDatCalc, nCont
   dDatEmissao := dDatVencto := oParcelas[ 1, 2 ]
   HB_SYMBOL_UNUSED( oParcelas )
   IF Dow( dDatEmissao ) < nDe .OR. Dow( dDatEmissao ) > nAte
      RETURN .F.
   ENDIF
   IF nQtMes > 0
      dDatCalc := dDatEmissao
      FOR nCont = 1 TO nQtMes
         DO WHILE Month( dDatCalc ) == Month( dDatVencto )
            dDatVencto += 10
         ENDDO
         dDatCalc := dDatVencto
      NEXT
	  dDatVencto := dDatVencto - Day( dDatVencto ) + 1
   ENDIF
   IF nQtDia > 0
      dDatVencto := dDatVencto + nQtDia
   ENDIF
   IF nDiaFim != 0 .AND. nDiaFim > -8 .AND. nDiaFim < 8
      IF nDiaFim > 0
         DO WHILE Dow( dDatVencto ) != nDiaFim
            dDatVencto := dDatVencto + 1
         ENDDO
      ELSE
         nDiaFim := Abs( nDiaFim )
         IF Dow( dDatVencto ) < nDiaFim
            DO WHILE Dow( dDatVencto ) != nDiaFim
               dDatVencto := dDatVencto + 1
            ENDDO
         ELSE
            DO WHILE Dow( dDatVencto ) != nDiaFim
               dDatVencto := dDatVencto - 1
            ENDDO
         ENDIF
      ENDIF
   ENDIF
   oParcelas[ 1, 2 ] := dDatVencto
   oParcelas[ 1, 3 ] := dDatVencto - dDatEmissao
   RETURN .T.

Vencimentos malucos

Enviado: 11 Dez 2013 12:54
por JoséQuintas
É como falei: está relativamente simples, porém está grande.

No caso dessas duas novas, que tem a ver com o dia da semana, só ajustei na função CalculaVenctoSemana().
Neste ponto de vista é que está relativamente simples.
Na hora do faturamento, posiciono no registro da fórmula de pagamento e passo tudo como parâmetro.
Na tela de configuração, passo tudo como parâmetro pra função e faço um mapa simulado para 30 dias.

Vencimentos malucos

Enviado: 11 Dez 2013 12:56
por JoséQuintas
A tela de configuração, por enquanto está assim:

Código: Selecionar todos

                                                                                                                                  
 Forma de Pagto...: 000002                                                                           Simulação (D)ia/(S)Semana    
                                                                                                         EMI(S+1)  VENCTO         
 Descrição........: DFLSDJFHSDJKHFSDFD                                                               QUA 11/12/13  01/01/14 QUA   
 Acrésc.Total (%).:     0.000                                                                        QUI 12/12/13  01/01/14 QUA   
 Descto.Total (%).:     0.000                                                                        SEX 13/12/13  01/01/14 QUA   
 Emissão ou Saída.: E                                                                                SÁB 14/12/13  01/01/14 QUA   
 Padrão/Dia/Semana: S  ( P, D ou S)                                                                  DOM 15/12/13  08/01/14 QUA   
                                                                                                     SEG 16/12/13  08/01/14 QUA   
 Dias contados da emissão/saída - para padrão selecionado P                                          TER 17/12/13  08/01/14 QUA   
     01:    0     02:    0     03:    0     04:    0     05:    0                                    QUA 18/12/13  08/01/14 QUA   
     06:    0     07:    0     08:    0     09:    0     10:    0                                    QUI 19/12/13  08/01/14 QUA   
     11:    0     12:    0     13:    0     14:    0     15:    0                                    SEX 20/12/13  08/01/14 QUA   
     16:    0     17:    0     18:    0     19:    0     20:    0                                    SÁB 21/12/13  08/01/14 QUA   
     21:    0     22:    0     23:    0     24:    0     25:    0                                    DOM 22/12/13  15/01/14 QUA   
                                                                                                     SEG 23/12/13  15/01/14 QUA   
 Invervalo e Avançar: D (dia do mês) ou S (dia da semana) - para padrão selecionado D ou S           TER 24/12/13  15/01/14 QUA   
 01.Dia/Sem de:  1  até: 31  Avançar mes em:  0  Somar dias:  21  Ajustar p/ dia/sem: -4             QUA 25/12/13  15/01/14 QUA   
 02.Dia/Sem de:  0  até:  0  Avançar mes em:  0  Somar dias:   0  Ajustar p/ dia/sem:  0             QUI 26/12/13  15/01/14 QUA   
 03.Dia/Sem de:  0  até:  0  Avançar mes em:  0  Somar dias:   0  Ajustar p/ dia/sem:  0             SEX 27/12/13  15/01/14 QUA   
 04.Dia/sem de:  0  até:  0  Avançar mes em:  0  Somar dias:   0  Ajustar p/ dia/sem:  0             SÁB 28/12/13  15/01/14 QUA   
 05.Dia/Sem de:  0  até:  0  Avançar mes em:  0  Somar dias:   0  Ajustar p/ dia/sem:  0             DOM 29/12/13  22/01/14 QUA   
                                                                                                     SEG 30/12/13  22/01/14 QUA   
 Importante: Nos padrões D e S existe o avançar até dia.                                             TER 31/12/13  22/01/14 QUA   
 Caso preenchido com 29, 30 ou 31, terá ajuste pra fevereiro e outros meses                          QUA 01/01/14  22/01/14 QUA   
 Intervalo semana: 1=domingo, 2=segunda, 3=terca, 4=quarta, 5=quinta, 6=sexta, 7=sábado              QUI 02/01/14  22/01/14 QUA   
 Se pela data de saída, o simulado nesta tela usa emssão + 1                                         SEX 03/01/14  22/01/14 QUA   
                                                                                                     SÁB 04/01/14  22/01/14 QUA   
 Inf.Inclusão....: 2013/12/10 19:15 JOSEQ      JPA        PJPFORPAG  44B5-D8F5 2013.12.09.1222       DOM 05/01/14  29/01/14 QUA   
 Inf.Alteração...: 2013/12/10 22:31 JOSEQ      JPA        PJPFORPAG  44B5-D8F5 2013.12.09.1222       SEG 06/01/14  29/01/14 QUA   
                                                                                                     TER 07/01/14  29/01/14 QUA   
                                                                                                     QUA 08/01/14  29/01/14 QUA   
                                                                                                     QUI 09/01/14  29/01/14 QUA   
                                                                                                     SEX 10/01/14  29/01/14 QUA   

Vencimentos malucos

Enviado: 11 Dez 2013 13:17
por JoséQuintas
A rotina de cálculo é única, para o simulado e para o faturamento.
Então está certo aqui, estará no faturamento.
Por isso achei interessante deixar o simulado: o usuário já confere o que fez (e o que eu fiz também).
A tela ficou poluída, mas não tem o que melhorar.