require "extenso_pt/version" require "bigdecimal/util" # @author Hernâni Rodrigues Vaz module ExtensoPt class Error < StandardError; end LC=[:pt,:br] A0020={pt: ["","UM","DOIS","TRÊS","QUATRO","CINCO","SEIS","SETE","OITO","NOVE","DEZ","ONZE","DOZE","TREZE","CATORZE","QUINZE","DEZASSEIS","DEZASSETE","DEZOITO","DEZANOVE"], br: ["","UM","DOIS","TRES","QUATRO","CINCO","SEIS","SETE","OITO","NOVE","DEZ","ONZE","DOZE","TREZE","QUATORZE","QUINZE","DEZESSEIS","DEZESSETE","DEZOITO","DEZENOVE"]} A0100={pt: ["","","VINTE","TRINTA","QUARENTA","CINQUENTA","SESSENTA","SETENTA","OITENTA","NOVENTA"], br: ["","","VINTE","TRINTA","QUARENTA","CINQUENTA","SESSENTA","SETENTA","OITENTA","NOVENTA"]} A1000={pt: ["","CEM","CENTO","DUZENTOS","TREZENTOS","QUATROCENTOS","QUINHENTOS","SEISCENTOS","SETECENTOS","OITOCENTOS","NOVECENTOS"], br: ["","CEM","CENTO","DUZENTOS","TREZENTOS","QUATROCENTOS","QUINHENTOS","SEISCENTOS","SETECENTOS","OITOCENTOS","NOVECENTOS"]} A1e24={pt: ["","MIL"," MILHÃO"," MIL MILHÃO"," BILIÃO"," MIL BILIÃO"," TRILIÃO"," MIL TRILIÃO",""," MIL"," MILHÕES"," MIL MILHÕES"," BILIÕES"," MIL BILIÕES"," TRILIÕES"," MIL TRILIÕES"], br: ["","MIL"," MILHÃO"," BILHÃO"," TRILHÃO"," QUADRILHÃO"," QUINTILHÃO"," SEXTILHÃO",""," MIL"," MILHÕES"," BILHÕES"," TRILHÕES"," QUADRILHÕES"," QUINTILHÕES"," SEXTILHÕES"]} # Produz o extenso dum grupo de 3 digitos em portugûes de portugal ou brasil. # # @param [Integer] mil o valor dum grupo de 3 digitos a converter # @param [Integer] pos posição deste grupo de 3 digitos no valor monetário em tratamento # @return [String] o extenso dum grupo de 3 digitos def self.e999(mil,pos=0) cem=mil%100 A1000[@@lc][(mil>100?1:0)+mil/100]+(mil>100&&cem>0?" E ":"")+ # extenso das centenas A0100[@@lc][cem/10]+(mil>20&&mil%10>0?" E ":"")+ # extenso dos dezenas A0020[@@lc][pos==1&&mil==1?0:cem<20?cem:cem%10] # extenso das unidades mais 10-19 end # Produz o extenso dum valor monetário em portugûes de portugal ou brasil. # # @param [Integer] pos posição actual nos grupos de 3 digitos do valor monetário # @param [String] ext extenso actual em construção # @return [String] o extenso dum valor monetário def self.enumerico(pos=0,ext="") # testa fim do valor monetário if (pos>=@@ai.count) # soma os grupos de 3 digitos para controle de singular/plural so1=@@ai[0].to_i+@@ai[1].to_i*2 # primeiros dois grupos so2=@@ai[2..-1].to_a.inject(:+).to_i*2 # restantes grupos if (so1+so2+@@nf==0) "ZERO "+@@mp # caso especial de zero else ext+=" DE" if (so2>0&&so1==0) # proposição DE para valores >1e6 mas 0 nos primeiros 6 digitos ext+=" "+@@ms if (so1+so2==1) # singular da moeda ext+=" "+@@mp if (so1+so2>1) # plural da moeda ext+=" E " if (so1+so2>0&&@@nf>0) # proposição E entre parte inteira e parte fracionária ext+=e999(@@nf) # extenso da parte fracionária ext+=" "+@@cs if (@@nf==1) # singular da parte fracionária ext+=" "+@@cp if (@@nf>1) # plural da parte fracionária ext end else # extenso do grupo actual de 3 digitos dg3 =e999(@@ai[pos],pos) dg3+=A1e24[@@lc][@@ai[pos]>0?@@ai[pos]>1?8+pos:pos:0] # qualificador do grupo actual dg3+=pos>0?@@ai[pos-1]>100?" ":@@ai[pos-1]>0?" E ":"":"" # separação entre grupo actual e anterior # proximo grupo de 3 digitos enumerico(pos+1,dg3+ext) end end # Converte um objeto criando extenso(s) em portugûes de portugal ou brasil. # # @param [Object] objeto o objeto a converter pode ser (String, Float, Integer, Array, Range, Hash) ou uma mistura # @return [String, Array, Hash] extenso se o objecto for (String, Float, Integer), Array dos extensos se o objecto for (Array, Range) ou Hash dos extensos se o objecto for (Hash) def self.eobjeto(obj) if (obj.kind_of?Hash) # converte os valores do Hash nos seus extensos mantendo as chaves - devolve um Hash obj.map{|k,v|[k,eobjeto(v)]}.to_h elsif (obj.respond_to?:to_a) # converte o objecto num Array e converte os valores do Array nos seus extensos - devolve um Array obj.to_a.map{|a|eobjeto(a)} else # converte objeto numa string de digitos usando bigdecimal/util para evitar bugs com valores superiores a 1e12 # qualquer valor não convertivel (ex: texto) resulta em "0.0" svalor=obj.to_d.to_s('F') # array da parte inteira do valor monetário dividido em grupos de 3 digitos ex: 123022.12 => [22, 123] @@ai=svalor[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map{|i|i.reverse.to_i} # parte fracionária do valor monetário ex: 123022.12 => 12 # arredondada a 2 casas decimais (cêntimos/centavos) @@nf=(svalor[/\.\d*/].to_f*100).round # valores superiores a 1e24 não são tratados if (@@ai.count>8) "" else # extenso num numerico enumerico end end end # Produz extenso(s) de objeto(s) em portugûes de portugal ou brasil. # # @param [Hash] moeda as opcoes para parametrizar a moeda/fração # @option moeda [Symbol] :lc locale do extenso - portugûes de portugal (:pt) ou brasil (:br) # @option moeda [String] :msingular moeda no singular - pode ser inferido do plural menos "S" # @option moeda [String] :fsingular fração no singular - pode ser inferido do plural menos "S" # @option moeda [String] :mplural moeda no plural - pode ser inferido do singular mais "S" # @option moeda [String] :fplural fração no plural - pode ser inferido do singular mais "S" # @return [String, Array, Hash] extenso se o objecto for (String, Float, Integer), Array dos extensos se o objecto for (Array, Range) ou Hash dos extensos se o objecto for (Hash) def extenso(moeda={lc:(:pt),msingular:"EURO",fsingular:"CÊNTIMO"}) # parametrização por defeito para locale => :br if (moeda[:lc]==:br&&!moeda[:mplural]&&!moeda[:fplural]) moeda={lc:(:br),msingular:"REAL",mplural:"REAIS",fsingular:"CENTAVO"} end # se locale nao for [:pt,:br] entao :pt if (LC.include?moeda[:lc]) @@lc=moeda[:lc] else @@lc=:pt end # inferir singular da moeda a partir do plural if (moeda[:msingular]) @@ms=moeda[:msingular] elsif (moeda[:mplural].to_s[-1]=="S") @@ms=moeda[:mplural][0..-2] else @@ms="EURO" end # inferir singular da fração a partir do plural if (moeda[:fsingular]) @@cs=moeda[:fsingular] elsif (moeda[:fplural].to_s[-1]=="S") @@cs=moeda[:fplural][0..-2] else @@cs="CÊNTIMO" end # inferir plural da moeda a partir do singular if (moeda[:mplural]) @@mp=moeda[:mplural] else @@mp=@@ms+"S" end # inferir plural da fração a partir do singular if (moeda[:fplural]) @@cp=moeda[:fplural] else @@cp=@@cs+"S" end # extenso do objeto ExtensoPt.eobjeto(self) end end class Hash; include ExtensoPt;end class Array; include ExtensoPt;end class Range; include ExtensoPt;end class Float; include ExtensoPt;end class Integer;include ExtensoPt;end class String; include ExtensoPt;end