financial 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|