BrazilUtils API

Se dudansk for eu (rsrsrsrs) to no projeto já. Mandarei mp pro Rafael ver o que ele está precisando pra eu ir dando uma ajuda… espero poder contribuir com algo útil neste projeto :stuck_out_tongue:

Sobre java 1.4 ou 5, vou me esforçar então para utilizar o 1.4. Vi agora que o tal MathContext é só no 5, então vou procurar não usar essa classe.

flw

Douglas, compreendo isso.

Na minha visão limitada, de developer lidando com o pacote currency.br, Java 5 é a escolha sem sombra de dúvidas. O processamento das rotinas será pesado, e vamos utiilzar BigDecimal pra todo que é canto. Mas, além da velocidade, tem outros motivos pelo qual eu usaria o Java 5 aqui.

Note que é uma visão bem focada nesse caso específico, e reconheço que, ampliando a perspectiva, Java 1.4 pode ser a melhor solução.

Mas recomendo: vamos resolver essa questão e, assim que resolvida, todos terão que “vestir a camisa” para não voltar mais nesse assunto e partirmos para os outros problemas que nos esperam!

T+!

Bem vindo!

Como disse ao Dudaskank, estou pensando em fazer algo parecido com o que o Douglas fez com as classes para inscrição estadual, cnpj, só que focando cálculos de impostos, etc. A parte financeira/tributária é bastante complexa no Brasil e, segundo um professor meu, que é administrador, sempre nos dá (programadores) muito trabalho.

Tenho que fazer um documento de requisitos para o currency.br, mas pretendo fazer algo além de conversões entre moedas. Se estiverem de acordo com esse proposto, poderemos seguir adiante.

Ok.Vou mudar lá.

Certo, um TODO é sempre bom.

E eu nem precisei quebrar a cabeça! Olha só o que vocês mesmo andaram sugerindo logo no começo do projeto:

[quote]Requisitos do pacote currency.br

Sugeridos pelo thingol:

  • validação de módulo 10 e 11, de boletos bancários e de concessionárias públicas;
  • validação de números de contas dos diversos bancos;
  • validação de números de cartões de crédito (o algoritmo de Luhn vale para todas as operadoras, ou tem mais alguma coisa?)

Sugeridos pelo Douglas:

  • cálculos padronizados de impostos federais, estaduais e municipais;
  • valores de alíquotas de impostos como constantes;
  • enquadramento nas faixas e cálculo do Imposto de Renda para sistemas de RH;
  • GenericNotaFiscal e AbstractOrdemDeServico
  • coisas como valor/percentual de retenção de imposto, qual imposto recolher dependendo do valor e outras.[/quote]

Como ponto de partida, está ótimo.

O que fiz até agora, com base num artigo que me passaram. Essa primeira parte está quase pronta.

Mas, tenho ainda que descobrir como fazer os milhões, bilhões e trilhões da vida ficarem no plural quando for o caso, colocar a vírgula quando necessário.

*EDITADO: esqueçam as vírgulas!!!

Depois, acho que fica mais fácil. A partir de um BigDecimal, verifica-se a escala. Se estiver beleza, separa a parte inteira dos centavos, transforma os dois em int e joga no método convert.

[code]
package org.brazilutils.currency.br;

import java.math.BigDecimal;
import java.lang.StringBuffer;

/**
*

  • @author Rafael Fiume

  • @version 0.1

  • @see http://www.rgagnon.com/javadetails/java-0426.html
    */
    public class CurrencyConverterToText {

    private static final String[] grandeNumeros = {
    “”,
    “mil”,
    “milhão”,
    “bilhão”,
    “trilhão”,
    “quatrilhão”
    };

    private static final String[] grandeNumerosPlural = {
    “”,
    “mil”,
    “milhões”,
    “bilhões”,
    “trilhões”,
    “quatrilhões”
    };

    private static final String[] centenas = {
    “”,
    “cento”,
    “duzentos”,
    “trezentos”,
    “quatrocentos”,
    “quinhentos”,
    “seissentos”,
    “setecentos”,
    “oitocentos”,
    “novecentos”
    };

    private static final String[] dezenas = {
    “”,
    “dez”, // Apenas para deixar cada número “em seu lugar” -> dezenas[2] == “vinte”
    “vinte”,
    “trinta”,
    “quarenta”,
    “cinqüenta”,
    “sessenta”,
    “setenta”,
    “oitenta”,
    “noventa”
    };

    private static final String[] numeros = {
    “”,
    “um”,
    “dois”,
    “três”,
    “quantro”,
    “cinco”,
    “seis”,
    “sete”,
    “oito”,
    “nove”,
    “dez”,
    “onze”,
    “doze”,
    “treze”,
    “quatorze”,
    “quinze”,
    “dezesseis”,
    “dezessete”,
    “dezoito”,
    “dezenove”
    };

    private StringBuffer convertLessThanOneThousand(int numero) {
    StringBuffer numPorExtenso = new StringBuffer("");

     if (numero == 0) 
     	return numPorExtenso;
    
     if (numero % 100 < 20){
     	numPorExtenso.append(numeros[numero % 100]);
     	numero /= 100;
        
     	if(numero > 0) {
     		numPorExtenso.insert(0, " e ");
     	}
     	
     } else {
     	numPorExtenso.append(numeros[numero % 10]);
     	numero /= 10;
     	
     	numPorExtenso.insert(0, " e ");
     	
         numPorExtenso.insert(0, dezenas[numero % 10]);
         numero /= 10;
     }    
     
     if(numero > 0) {
     	numPorExtenso.insert(0, " e ");
     }
     
     return numPorExtenso.insert(0, centenas[numero]);
    

    }

    private String convert(int numero) {

     StringBuffer numPorExtenso = new StringBuffer("");
     String prefix = "";
     String sufix = "";
     
     if (numero == 0) { 
     	return ""; 
     }
    
     /* Números negativos ficam entre parênteses. 
      * Ex: positivo -> 1269, negativo -> (1269) */
     if (numero < 0) {
     	numero = -numero;
         prefix = "(";
         sufix  = ")";
     }
     
     int casa_milhar = 0;
    
     do {	        
     	int n = numero % 1000;
         
     	if (n != 0) {	            
     		StringBuffer s = convertLessThanOneThousand(n);
             numPorExtenso = s.append(" " + grandeNumeros[casa_milhar]).append(" " + numPorExtenso);
         }
     	
         casa_milhar++;
         numero /= 1000;	        
         
     
     } while (numero > 0);
    
     return (prefix + numPorExtenso + sufix).trim();
    

    }

//////////////////////////////////////////////////////////////////////////////////////////

/*
 * Retorna o valor monetário por extenso, a partir de um BigDecimal com
 * escala dois ou três.
 * 
 * @param currency currency o valor do dinheiro @returns dinheiro por
 * extenso.
 */
public static String porExtenso(BigDecimal currency) {
    
    int scale= currency.scale();
    
    if ((scale != 2) || (scale != 3)) {
           throw new RuntimeException("A escala deve ser igual a dois ou três.");
    }
                   
    return new String(); // 
}

/*
 * Retorna o valor monetário por extenso, a partir de uma representação
 * textual de valor monetário.
 * 
 * @param currency currency o valor do dinheiro @returns dinheiro por
 * extenso.
 */
public static String porExtenso(String currency) {
    
	return "Ainda não implementado";
}

public static void main(String[] args) {
	
	CurrencyConverterToText converter = new CurrencyConverterToText();
	System.out.println(converter.convert(12687));
	System.out.println(converter.convert(324));
	System.out.println(converter.convert(25));
	System.out.println(converter.convert(5));
	System.out.println(converter.convert(896558475));
	System.out.println(converter.convert(9));
	System.out.println(converter.convert(-255445852));
}

}[/code]
O resultado do método main (utilizado como teste):

doze mil seissentos e oitenta e sete trezentos e vinte e quantro vinte e cinco cinco oitocentos e noventa e seis milhão quinhentos e cinqüenta e oito mil quatrocentos e setenta e cinco nove (duzentos e cinqüenta e cinco milhão quatrocentos e quarenta e cinco mil oitocentos e cinqüenta e dois )

Rafael, algumas dessas features terão que ser revistas.
Boletos bancários ficam melhor no JBoleto:
http://jboleto.kobi.com.br/

Eu não tinha lhe passado um que já fazia até os centavos?
O problema estava no milhar de centavos…

E vejo um problema com o nome da classe:
CurrencyConverterToText
Melhor deixar integralmente em inglês, e talvez por algo dizendo que o texto esta sendo convertido para reais, ou vc vai criar uma classe genérica de conversão de número para texto por extenso(o que é uma boa), e quanto for necessário, usar um método “converterParaReais” ou algo assim???

RESPOSTA 1: E quem vai redefinir os requisitos?

RESPOSTA 2: Calma, rapaz! Um passo por vez. Aproveitei ao máximo um tempinho que arranjei. Como eu disse, nem essa primeira parte está pronta ainda. Se você ler novamente o passo-a-passo que fiz antes do código, vai ver que entre as etapas a serem feitas está “separar a parte inteira dos centavos”.

RESPOSTA 3: E não, não estou pensando em localizar genéricamente a classe, porque meu grande interesse nesse projeto é mesmo as coisas especificas do Brasil.

Me dê uma sugestão pro nome da classe. Pode me sugerir, Inclusive, nomes de métodos e variáveis se achar necessário.

T+!

Vamos discutir isso na lista ou lá no blog?Vou dar um toque no Douglas, mas desses apresentados, quais vc acha que conseguiria tocar?Para o mini release, faça só as classes de conversão para texto mesmo.

Tá ok.Não entendi o que vc tava fazendo.

Vc misturou os idiomas: CurrencyConverterToText
Deixa ConvertToText.Mas eu preferia ConvertToReais.Assim pode rolar um ConvertToDollars,ToEuros…(claro, em diferentes packages)
Eu tinha pensado que vc tava fazendo uma classe genérica de conversão e daí na ConvertToReais vc estenderia o necessário.huahua… eu que viajei no q vc tava fazendo! :lol:

Pode ser que eu esteja viajando, mas acho que esse tipo de discussão, que envolve muita troca de mensagens entre muitos participantes, se dá mehor na lista de discussões do java.net ou num grupo como o yahoogrupos.

O blog do BrazilUTILS poderia ser uma espécie de canal de relações públicas. Você poderia deixar posts sobre o caminhar do projeto, planos futuros, suas impressões sobre os resultados. Daí os usuários do BrazilUTILS e nós mesmos íamos comentando.

E o guj é ideal para colocar códigos, tirar dúvidas, mostrar as primeiras idéias de requisitos para ver se a comunidade aprova. O guj facilita a colaboração, e mesmo o chumbo grosso de críticas (às vezes) é bem vindo, desde que não apenas critiquem, mas contribuam com uma solução.

Todos. Aos poucos, espero que nem tão aos poucos assim, eles vão saindo. Depois isso é só o começo, tem muita coisa a ser feita e tenho certeza que não vou fazer tudo sozinho. Tem muita gente nesse projeto. O Dudaskank já está trabalhando neles também.

ConvertToReais é bem melhor! Valeu!

A saída do valor por extenso de um número negativo pode ser de dois jeitos:

(mil novecentos e oito reais negativo) ou apenas

(mil novecentos e oito reais) Qual a melhor forma?

Só confirmando, o nome da classe é org.brazilutils.currency.br.ConvertToReais ?

Tb acho.Vou deixar o blog para press release então.

Ignore números negativos.O que importa são eles por extenso.Se alguém precisar, colocaria esse negativo depois.

É.

Foi mal não te responder antes, mas fiquei sem net ontem.

Pronto!

Isso aqui:[code]
ConvertToReais converter = new ConvertToReais();

System.out.println(converter.porExtenso(new BigDecimal(-1).setScale(2, RoundingMode.HALF_DOWN)));
System.out.println(converter.porExtenso(new BigDecimal(896558475).setScale(2, RoundingMode.HALF_DOWN)));
System.out.println(converter.porExtenso(new BigDecimal(0.01).setScale(2, RoundingMode.HALF_DOWN)));
System.out.println(converter.porExtenso(new BigDecimal(30).setScale(2, RoundingMode.HALF_DOWN)));
System.out.println(converter.porExtenso(new BigDecimal(0.001).setScale(3, RoundingMode.HALF_DOWN)));
System.out.println(converter.porExtenso(new BigDecimal(-100.04).setScale(2, RoundingMode.HALF_DOWN)));
System.out.println(converter.porExtenso(new BigDecimal(120.04).setScale(2, RoundingMode.HALF_DOWN)));
System.out.println(converter.porExtenso(“100101.87”));
System.out.println(converter.porExtenso(“1001000000.991”));
System.out.println(converter.porExtenso(new BigDecimal(12687.013).setScale(3, RoundingMode.HALF_DOWN)));

converter.setNegativePrefix("(");
converter.setNegativeSufix(") - Negativo?!! haha! Se mata véio…");
converter.setPositivePrefix("");
converter.setPositiveSufix(" - Fala amigão!! ");
System.out.println(converter.porExtenso(new BigDecimal(100000000).setScale(2, RoundingMode.HALF_DOWN)));
System.out.println(converter.porExtenso(new BigDecimal(-2000000000).setScale(2, RoundingMode.HALF_DOWN)));

// Pau aqui!!! Escala diferente de dois ou três.
//System.out.println(converter.porExtenso(new BigDecimal(0.3).setScale(1, RoundingMode.HALF_DOWN)));
//System.out.println(converter.porExtenso(new BigDecimal(1413.1411).setScale(4, RoundingMode.HALF_DOWN)));[/code]

deve resultar em: um real oitocentos e noventa e seis milhões quinhentos e cinqüenta e oito mil quatrocentos e setenta e cinco reais um centavo trinta reais um milhar de real cem reais e quatro centavos cento e vinte reais e quatro centavos cem mil cento e um reais e oitenta e sete centavos um bilhão um milhão de reais e novecentos e noventa e um milhar de real doze mil seissentos e oitenta e sete reais e treze milhar de real cem milhões de reais - Fala amigão!! (dois bilhões de reais) - Negativo?!! haha! Se mata véio...

Melhor deixar o usuário definir quais prefixos e sufixos usar, a moda DecimalFormat.

[EDITADO]
[color=darkred]Atenção:[/color] esse código-fonte está desatualizado.
Para obter o código atualizado, utilize o CVS do projeto BrazilUtils em https://brazilutils.dev.java.net
[/EDITADO]

Hehehe, ficou legal mesmo.

Só ta faltando passar o corretor ortográfico…

doze mil seissentos e oitenta e sete reais e treze milhar de real

600 = seiscentos :wink:

Mas… voltando ao nome ainda. Essa classe pode ser usada não só para reais, mas pra qualquer número, então acho que ConvertToReais não parece pra mim um bom nome…

Sei lá, que tal uma interface NumeroPorExtenso (em inglês não sei como fica) e depois as implementações dela, pelo menos uma pra Português BR, como NumeroPorExtensoPTBR?

Ah, Rafael, mandei pra vc e depois pro Ironlynx umas classes que fiz também, veja o que acha e me fala… flw

[edit]Epa, deixa pra lá o que eu disse, nesse caso é só pra Real mesmo hehehe, mas a idéia está dada (NumeroPorExtensoReais?) rsrsrs

Putz!! :shock:

Ía mostrar pra minha mãe essa classe e nem vou mais! hehe!

O que o sono não faz com uma pessoa. Essa escapou, mas as outras (oitocentos, etc.) estão certas, né? Melhor vocês verificarem, porque já estou dormindo aqui…

Quanto a generalização da classe, não é bem assim não! Cada língua tem as suas particularidades, suas regras. o que muda completamente o algoritmo. Fazer uma dessa em inglês é bem mais fácil, já em francês é mais difícil.
A única coisa que é possível generalizar é o nome dos métodos públicos, o que irá render no máximo uma interface.

Bem, o nome da classe… Sei lá! Acho que agora eu vou dormir, mesmo!

T+!

Esquenta não, normal… mas tudo que tem centos no nome é com c mesmo.

Vai dormir é? Queria estar em casa dormindo ou não fazendo nada… mas enfim. Só depois das 20:00.

flw

[edit]sua mãe é programadora também?

Tô ligado! Foi um escorregão… Pode ver que os outros (setecentos, oitocentos, novecentos) estão certos. Fui correndo ver! hehe

Minha mão nem sabe lidar com computador, quanto mais programar!! Mas é que eu fiquei tão feliz em terminar essa classe! :smiley: haha

Queria estar em casa, é? Azar teu! :lol: Ou faça como eu, trabalhe de madrugada. Acho muito melhor.

*EDITADO: outra coisa Dudaskank! Se você for verificar o método divideAndRemainder, vai ver que o seu nome está lá, como o autor daquele método. Beleza?

**EDITADO: e cadê as classes que você disse que mandou?

Eu ainda prefiro dormir de madrugada… pelo menos de 2ª a 5ª…

Estranho, mandei pro seu e-mail… vou anexar por aqui também então. E valeu pela lembrança no método lá hehehe

e o último arquivo faltando…

tem método main pra testar em CheckLuhn e LuhnInputVerifier, mas precisa ajustar os pacotes antes de rodar eles. Tá parecendo que funciona, pelo menos com meu cartão passou.

flw

Tô lendo as classes de vcs aqui…
Rafael, milhar não, milésimos de real.Use comentários em inglês.
Quando for testar a funcionalidade, crie uma classe a parte, algo do tipo ConvertToReaisTest, sacou?

dudansk(eduardo), o algotimo de luhn atende a todas as operadoras de cartão de crédito???
Eu tava vando aqui para comparar com a sua(Vc fez GUI e tudo mais):
http://www.theeggeadventure.com/wikimedia/index.php/LUHN_Source_Code