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 a moeda e o extenso da parte fracionaria do valor monetário em portugûes de portugal ou brasil.
#
# @param [Integer] fracao parte fracionaria do valor monetário ex: 100022.12 = 12
# @return [String] a moeda e o extenso da parte fracionaria do valor monetário
def self.efracao(fracao)
inteira=@@ai.find{|v|v>0}.to_i+@@ai[1..-1].to_a.find{|v|v>0}.to_i
total=inteira+fracao
(@@ai[2..-1].to_a.find{|v|v>0}.to_i>0&&@@ai[0..1].inject(:+).to_i==0?" DE":@@ai.count>0&&total==0?"ZERO "+@@mp:"")+
(inteira>0?inteira>1?" "+@@mp:" "+@@ms:"")+
(inteira>0&&fracao>0?" E ":"")+e999(fracao)+
(fracao>0?fracao>1?" "+@@cp:" "+@@cs:"")
end
# Produz o extenso dum valor (entre 0-999) em portugûes de portugal ou brasil.
#
# @param [Integer] mil o valor a converter
# @param [Integer] pos posição actual de mil no valor monetário em tratamento
# @return [String] o extenso de mil
def self.e999(mil,pos=0)
cem=mil%100
A1000[@@lc][(mil>100?1:0)+mil/100]+(mil>100&&mil%100>0?" E ":"")+
A0100[@@lc][cem/10]+(mil>20&&mil%10>0?" E ":"")+
A0020[@@lc][pos==1&&mil==1?0:cem<20?cem:cem%10]
end
# Produz recursivamente o extenso da parte inteira do valor monetário em portugûes de portugal ou brasil.
#
# @param [Integer] pos posição actual do valor monetário em tratamento
# @param [String] ext extenso actual em tratamento
# @return [String] o extenso da parte inteira
def self.erecursivo(pos=0,ext="")
if (pos>=@@ai.count)
ext
else
ctl=pos>0?@@ai[pos-1]:0
ext=e999(@@ai[pos],pos)+A1e24[@@lc][@@ai[pos]>0?@@ai[pos]>1?8+pos:pos:0]+(ctl>100?" ":ctl>0?" E ":"")+ext
erecursivo(pos+1,ext)
end
end
# Converte um objeto no seu extenso 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 :mplural menos "S"
# @option moeda [String] :fsingular Fração no singular - pode ser inferido do :fplural menos "S"
# @option moeda [String] :mplural Moeda no plural - pode ser inferido do :msingular+"S"
# @option moeda [String] :fplural Fração no plural - pode ser inferido do :fsingular+"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"})
moeda={lc:(:br),msingular:"REAL",mplural:"REAIS",fsingular:"CENTAVO"} if (moeda[:lc]==:br&&!moeda[:mplural]&&!moeda[:fplural])
@@lc=LC.include?(moeda[:lc])?moeda[:lc]:(:pt)
@@ms=moeda[:msingular]?moeda[:msingular]:moeda[:mplural].to_s[-1]=="S"?moeda[:mplural][0..-2]:"EURO"
@@cs=moeda[:fsingular]?moeda[:fsingular]:moeda[:fplural].to_s[-1]=="S"?moeda[:fplural][0..-2]:"CÊNTIMO"
@@mp=moeda[:mplural]?moeda[:mplural]:@@ms+"S"
@@cp=moeda[:fplural]?moeda[:fplural]:@@cs+"S"
if (self.kind_of?Hash)
# converte os valores do Hash nos seus extensos mantendos as chaves devolve um Hash
self.map{|k,v|[k,v.extenso(lc:(@@lc),msingular:@@ms,fsingular:@@cs,mplural:@@mp,fplural:@@cp)]}.to_h
elsif (self.respond_to?:to_a)
# converte o objecto num Array e converte os valores nos seus extensos devolve um Array
self.to_a.map{|a|a.extenso(lc:(@@lc),msingular:@@ms,fsingular:@@cs,mplural:@@mp,fplural:@@cp)}
else
# converter com bigdecimal/util para evitar bugs com valores superiores a 1e12
n=self.to_d.to_s('F')
# dividir parte inteira em grupos de 3 digitos ex: 123022.12 => [22, 123]
@@ai=n[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map{|i|i.reverse.to_i}
@@ai.count>8?"":ExtensoPt.erecursivo+ExtensoPt.efracao((n[/\.\d*/].to_f*100).round)
end
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