financial 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/.infinity_test +16 -0
- data/.rspec +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +74 -0
- data/README.markdown +157 -0
- data/Rakefile +1 -0
- data/duck_tales.gif +0 -0
- data/example.png +0 -0
- data/examples/two_accounts.rb +32 -0
- data/features/portuguese_dsl.feature +93 -0
- data/features/print_financial_table.feature +318 -0
- data/features/support/env.rb +1 -0
- data/financial.gemspec +22 -0
- data/lib/financial.rb +39 -0
- data/lib/financial/account.rb +129 -0
- data/lib/financial/account_manager.rb +26 -0
- data/lib/financial/balance.rb +11 -0
- data/lib/financial/balance_calculation.rb +35 -0
- data/lib/financial/cost.rb +34 -0
- data/lib/financial/costs.rb +30 -0
- data/lib/financial/deposit.rb +30 -0
- data/lib/financial/deposits.rb +15 -0
- data/lib/financial/dsl.rb +16 -0
- data/lib/financial/financial_date.rb +18 -0
- data/lib/financial/financial_table.rb +109 -0
- data/lib/financial/locale.rb +153 -0
- data/lib/financial/locales/en.yml +34 -0
- data/lib/financial/locales/pt.yml +67 -0
- data/lib/financial/parcels.rb +87 -0
- data/lib/financial/per_cent.rb +12 -0
- data/lib/financial/print_table.rb +34 -0
- data/lib/financial/revenue.rb +40 -0
- data/lib/financial/revenues.rb +16 -0
- data/lib/financial/rspec_matchers.rb +32 -0
- data/lib/financial/tax.rb +4 -0
- data/lib/financial/version.rb +3 -0
- data/spec/financial/account_manager_spec.rb +38 -0
- data/spec/financial/account_spec.rb +399 -0
- data/spec/financial/balance_spec.rb +44 -0
- data/spec/financial/cost_spec.rb +78 -0
- data/spec/financial/costs_spec.rb +18 -0
- data/spec/financial/deposit_spec.rb +78 -0
- data/spec/financial/deposits_spec.rb +23 -0
- data/spec/financial/english_spec.rb +76 -0
- data/spec/financial/financial_date_spec.rb +50 -0
- data/spec/financial/financial_spec.rb +14 -0
- data/spec/financial/financial_table_spec.rb +31 -0
- data/spec/financial/locale_spec.rb +37 -0
- data/spec/financial/parcels_spec.rb +179 -0
- data/spec/financial/per_cent_spec.rb +24 -0
- data/spec/financial/portuguese_spec.rb +117 -0
- data/spec/financial/print_table_spec.rb +76 -0
- data/spec/financial/revenue_spec.rb +89 -0
- data/spec/financial/revenues_spec.rb +18 -0
- data/spec/financial/tax_spec.rb +42 -0
- data/spec/spec_helper.rb +25 -0
- metadata +139 -0
@@ -0,0 +1,153 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Financial
|
3
|
+
class Locale
|
4
|
+
attr_accessor :name
|
5
|
+
attr_reader :file
|
6
|
+
|
7
|
+
LOCALES_FOLDER = File.join(File.dirname(__FILE__), 'locales')
|
8
|
+
|
9
|
+
def initialize(locale_name)
|
10
|
+
raise LocaleDontAvailable unless available_locales.include?(locale_name)
|
11
|
+
@name = locale_name
|
12
|
+
@file = YAML.load_file(File.join(LOCALES_FOLDER, "#{@name}.yml"))
|
13
|
+
@locale_methods = @file['methods']
|
14
|
+
@names = @file['names']
|
15
|
+
@date_format = @file['date']
|
16
|
+
@table = file['table']
|
17
|
+
send("create_alias_methods_for_#{@name}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def right_date_format(day, month, year)
|
21
|
+
if portuguese_language?
|
22
|
+
"#{day}/#{month}/#{year}"
|
23
|
+
else
|
24
|
+
"#{month}/#{day}/#{year}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def date_to_s(date)
|
29
|
+
right_date_format(date.day.to_s.rjust(2, '0'), date.month.to_s.rjust(2, '0'), date.year)
|
30
|
+
end
|
31
|
+
|
32
|
+
def initial_balance
|
33
|
+
@table['initial_balance']
|
34
|
+
end
|
35
|
+
|
36
|
+
def final_balance
|
37
|
+
@table['final_balance']
|
38
|
+
end
|
39
|
+
|
40
|
+
def header_for(account, initial_date, final_date)
|
41
|
+
if portuguese_language?
|
42
|
+
initial_date = date_to_s(initial_date)
|
43
|
+
final_date = date_to_s(final_date)
|
44
|
+
"Nome da Conta: #{account.banner} (de: #{initial_date}, até: #{final_date})"
|
45
|
+
else
|
46
|
+
"Account name: #{account.banner} (from: #{initial_date}, to: #{final_date})"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def table_headings
|
51
|
+
@table['headings']
|
52
|
+
end
|
53
|
+
|
54
|
+
def date_format
|
55
|
+
@date_format['format']
|
56
|
+
end
|
57
|
+
|
58
|
+
def month_names
|
59
|
+
@date_format['month_names']
|
60
|
+
end
|
61
|
+
|
62
|
+
def month_for(month)
|
63
|
+
find_month_for month, month_names
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_month_for(month, month_names)
|
67
|
+
month_name = month_names.find { |month_name| month_name.equal?(month) }
|
68
|
+
unless month_name
|
69
|
+
raise MonthDontExist, "Month #{month} dont exist in locale: #{@name}. Availables months: #{month_names}"
|
70
|
+
else
|
71
|
+
month_names.index(month_name) + 1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def available_locales
|
76
|
+
[:pt, :en]
|
77
|
+
end
|
78
|
+
|
79
|
+
def create_alias_methods_for_pt
|
80
|
+
@locale_methods.each do |klass, alias_pt_methods|
|
81
|
+
eval("Financial::#{klass}").class_eval do
|
82
|
+
alias_pt_methods.each do |pt_method, original_method_name|
|
83
|
+
alias_method pt_method, original_method_name
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def add_per_cent_aliases
|
90
|
+
Numeric.class_eval do
|
91
|
+
alias_method :por_cento, :per_cent
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def name_of_the_parcel
|
96
|
+
@names['parcel']
|
97
|
+
end
|
98
|
+
|
99
|
+
def balance_name
|
100
|
+
@names['balance']
|
101
|
+
end
|
102
|
+
|
103
|
+
def deposit_name
|
104
|
+
@names['deposit']
|
105
|
+
end
|
106
|
+
|
107
|
+
def received_deposit_name
|
108
|
+
@names['received_deposit']
|
109
|
+
end
|
110
|
+
|
111
|
+
def coin
|
112
|
+
@file['coin']
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_alias_methods_for_en
|
116
|
+
# skip
|
117
|
+
end
|
118
|
+
|
119
|
+
def ==(other_locale)
|
120
|
+
name.equal?(other_locale.name)
|
121
|
+
end
|
122
|
+
|
123
|
+
def to_coin(value)
|
124
|
+
"#{coin} #{format_coin(value)}"
|
125
|
+
end
|
126
|
+
|
127
|
+
def format_coin(value)
|
128
|
+
%{#{sprintf("%.2f", value.to_s).gsub(period_separator, separator)}}
|
129
|
+
end
|
130
|
+
|
131
|
+
def portuguese_language?
|
132
|
+
@name.equal? :pt
|
133
|
+
end
|
134
|
+
|
135
|
+
# I prefer to not use constants
|
136
|
+
#
|
137
|
+
def period_separator
|
138
|
+
'.'
|
139
|
+
end
|
140
|
+
|
141
|
+
# I prefer to not use constants
|
142
|
+
#
|
143
|
+
def separator
|
144
|
+
','
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class LocaleDontAvailable < StandardError
|
149
|
+
end
|
150
|
+
|
151
|
+
class MonthDontExist < StandardError
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
names:
|
2
|
+
parcel: Parcel
|
3
|
+
balance: Balance
|
4
|
+
deposit: Deposit
|
5
|
+
received_deposit: Deposit from
|
6
|
+
|
7
|
+
methods:
|
8
|
+
|
9
|
+
date:
|
10
|
+
format: "%m/%d/%Y"
|
11
|
+
month_names:
|
12
|
+
- !ruby/symbol january
|
13
|
+
- !ruby/symbol february
|
14
|
+
- !ruby/symbol march
|
15
|
+
- !ruby/symbol april
|
16
|
+
- !ruby/symbol may
|
17
|
+
- !ruby/symbol june
|
18
|
+
- !ruby/symbol july
|
19
|
+
- !ruby/symbol august
|
20
|
+
- !ruby/symbol september
|
21
|
+
- !ruby/symbol october
|
22
|
+
- !ruby/symbol november
|
23
|
+
- !ruby/symbol december
|
24
|
+
|
25
|
+
table:
|
26
|
+
headings:
|
27
|
+
- Date
|
28
|
+
- Name
|
29
|
+
- Value($)
|
30
|
+
- Total
|
31
|
+
initial_balance: Initial Balance
|
32
|
+
final_balance: Final Balance
|
33
|
+
|
34
|
+
coin: $
|
@@ -0,0 +1,67 @@
|
|
1
|
+
names:
|
2
|
+
parcel: Parcela
|
3
|
+
balance: Saldo
|
4
|
+
deposit: Deposito
|
5
|
+
received_deposit: Deposito recebido
|
6
|
+
|
7
|
+
methods:
|
8
|
+
Account:
|
9
|
+
custos: costs
|
10
|
+
faturamento: revenues
|
11
|
+
depositos: deposits
|
12
|
+
|
13
|
+
Cost:
|
14
|
+
na_data: in_date
|
15
|
+
|
16
|
+
Costs:
|
17
|
+
parcelas: parcels
|
18
|
+
|
19
|
+
Deposit:
|
20
|
+
na_conta: in_account
|
21
|
+
|
22
|
+
Deposits:
|
23
|
+
deposite: deposit
|
24
|
+
|
25
|
+
DSL:
|
26
|
+
conta: account
|
27
|
+
imprima_conta: print_account
|
28
|
+
|
29
|
+
Parcels:
|
30
|
+
de: of
|
31
|
+
todo_dia: every_day
|
32
|
+
comecando_no_mes_de: beginning
|
33
|
+
|
34
|
+
PrintTable:
|
35
|
+
de: from
|
36
|
+
até: to
|
37
|
+
|
38
|
+
Revenue:
|
39
|
+
imposto: tax
|
40
|
+
na_data: in_date
|
41
|
+
|
42
|
+
date:
|
43
|
+
format: "%d/%m/%Y"
|
44
|
+
month_names:
|
45
|
+
- !ruby/symbol janeiro
|
46
|
+
- !ruby/symbol fevereiro
|
47
|
+
- !ruby/symbol março
|
48
|
+
- !ruby/symbol abril
|
49
|
+
- !ruby/symbol maio
|
50
|
+
- !ruby/symbol junho
|
51
|
+
- !ruby/symbol julho
|
52
|
+
- !ruby/symbol agosto
|
53
|
+
- !ruby/symbol setembro
|
54
|
+
- !ruby/symbol outubro
|
55
|
+
- !ruby/symbol novembro
|
56
|
+
- !ruby/symbol dezembro
|
57
|
+
|
58
|
+
table:
|
59
|
+
headings:
|
60
|
+
- Data
|
61
|
+
- Nome
|
62
|
+
- Valor(R$)
|
63
|
+
- Total
|
64
|
+
initial_balance: Saldo Inicial
|
65
|
+
final_balance: Saldo Final
|
66
|
+
|
67
|
+
coin: R$
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Financial
|
2
|
+
class Parcels < Cost
|
3
|
+
attr_accessor :number, :name
|
4
|
+
attr_reader :value_of_the_parcels, :day_of_the_parcels, :beginning_month, :month_number
|
5
|
+
|
6
|
+
def initialize(number_of_parcels)
|
7
|
+
@name = Financial.locale.name_of_the_parcel
|
8
|
+
@number = number_of_parcels
|
9
|
+
@day_of_the_parcels = 1
|
10
|
+
@value_of_the_parcels = 0
|
11
|
+
@beginning_month = Date.today.month
|
12
|
+
end
|
13
|
+
|
14
|
+
def of(value)
|
15
|
+
@value_of_the_parcels = value
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def every_day(day)
|
20
|
+
@day_of_the_parcels = day
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def beginning(month)
|
25
|
+
@beginning_month = Financial.locale.month_for(month)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_cost
|
30
|
+
@today = Date.today
|
31
|
+
number.times.collect do |parcel_number|
|
32
|
+
day = @day_of_the_parcels
|
33
|
+
month = choose_month_for(parcel_number)
|
34
|
+
year = choose_year_for(:parcel_number => parcel_number)
|
35
|
+
date = Financial.locale.right_date_format(day, month, year)
|
36
|
+
Cost.new(@name, @value_of_the_parcels).in_date(date)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def day_of_the_parcel_is_in_this_month?
|
41
|
+
@day_of_the_parcels >= @today.day
|
42
|
+
end
|
43
|
+
|
44
|
+
# TODO: Change this procedural code :\
|
45
|
+
#
|
46
|
+
def choose_month_for(parcel_number)
|
47
|
+
months = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
48
|
+
index = @beginning_month - 1 + parcel_number
|
49
|
+
if index >= 12
|
50
|
+
months[index - 12]
|
51
|
+
else
|
52
|
+
months[index]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# TODO: Change this procedural code :\
|
57
|
+
#
|
58
|
+
def choose_year_for(options)
|
59
|
+
parcel_number = options[:parcel_number]
|
60
|
+
@current_year = current_date.year
|
61
|
+
@month_number = @beginning_month + parcel_number
|
62
|
+
if @month_number >= 12
|
63
|
+
find_year_for_parcel
|
64
|
+
else
|
65
|
+
@current_year
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def value
|
70
|
+
@value_of_the_parcels * @number
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def find_year_for_parcel
|
75
|
+
sum = 0
|
76
|
+
while (@month_number > 12) do
|
77
|
+
@month_number = @month_number - 12
|
78
|
+
sum += 1
|
79
|
+
end
|
80
|
+
@current_year + sum
|
81
|
+
end
|
82
|
+
|
83
|
+
def current_date
|
84
|
+
Date.today
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Financial
|
2
|
+
class PrintTable
|
3
|
+
attr_accessor :account_name, :account, :initial_date, :final_date
|
4
|
+
attr_reader :financial_tables
|
5
|
+
|
6
|
+
def initialize(name)
|
7
|
+
current_date = Date.today
|
8
|
+
@account_name = name
|
9
|
+
@account = Financial.account_manager.find_account(account_name)
|
10
|
+
@initial_date = current_date
|
11
|
+
@final_date = current_date
|
12
|
+
@financial_tables = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def from(initial_date_value)
|
16
|
+
@initial_date = Financial::FinancialDate.new(initial_date_value).date
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def to(final_date_value)
|
21
|
+
@final_date = Financial::FinancialDate.new(final_date_value).date
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def print!
|
26
|
+
@financial_tables = @account.collect{|account_instance| FinancialTable.new(account_instance, self)}
|
27
|
+
@financial_tables.each do |financial_table|
|
28
|
+
puts financial_table.header
|
29
|
+
puts financial_table.to_s
|
30
|
+
puts
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Financial
|
2
|
+
class Revenue
|
3
|
+
attr_accessor :name, :method_name, :value, :date
|
4
|
+
def initialize(*args)
|
5
|
+
args.flatten!
|
6
|
+
@method_name = args.shift
|
7
|
+
@name = @method_name.to_s.split('_').join(' ').capitalize
|
8
|
+
@value = args.shift
|
9
|
+
@date = Date.today
|
10
|
+
end
|
11
|
+
|
12
|
+
def tax(*args)
|
13
|
+
return @tax if args.empty?
|
14
|
+
@tax = Tax.new(@method_name, tax_value_for(args))
|
15
|
+
end
|
16
|
+
|
17
|
+
def in_date(date)
|
18
|
+
@date = Financial::FinancialDate.new(date).date
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def format_value
|
23
|
+
"+ #{Financial.locale.format_coin(value)}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def is_a_received_deposit?(account)
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def tax_value_for(args)
|
32
|
+
tax_value = args.first
|
33
|
+
if tax_value.is_a?(Hash)
|
34
|
+
tax_value[:decreases]
|
35
|
+
else
|
36
|
+
value * args.first
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Financial
|
2
|
+
class Revenues < Array
|
3
|
+
def method_missing(meth, *args, &blk)
|
4
|
+
unless args.empty?
|
5
|
+
revenue = Revenue.new(meth, args)
|
6
|
+
self.push(revenue)
|
7
|
+
revenue
|
8
|
+
else
|
9
|
+
raise RevenueWithoutValue, "Revenue: #{meth} don't have a value. Pass a value!"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class RevenueWithoutValue < StandardError
|
15
|
+
end
|
16
|
+
end
|