financial 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +4 -0
  2. data/.infinity_test +16 -0
  3. data/.rspec +3 -0
  4. data/.rvmrc +1 -0
  5. data/Gemfile +15 -0
  6. data/Gemfile.lock +74 -0
  7. data/README.markdown +157 -0
  8. data/Rakefile +1 -0
  9. data/duck_tales.gif +0 -0
  10. data/example.png +0 -0
  11. data/examples/two_accounts.rb +32 -0
  12. data/features/portuguese_dsl.feature +93 -0
  13. data/features/print_financial_table.feature +318 -0
  14. data/features/support/env.rb +1 -0
  15. data/financial.gemspec +22 -0
  16. data/lib/financial.rb +39 -0
  17. data/lib/financial/account.rb +129 -0
  18. data/lib/financial/account_manager.rb +26 -0
  19. data/lib/financial/balance.rb +11 -0
  20. data/lib/financial/balance_calculation.rb +35 -0
  21. data/lib/financial/cost.rb +34 -0
  22. data/lib/financial/costs.rb +30 -0
  23. data/lib/financial/deposit.rb +30 -0
  24. data/lib/financial/deposits.rb +15 -0
  25. data/lib/financial/dsl.rb +16 -0
  26. data/lib/financial/financial_date.rb +18 -0
  27. data/lib/financial/financial_table.rb +109 -0
  28. data/lib/financial/locale.rb +153 -0
  29. data/lib/financial/locales/en.yml +34 -0
  30. data/lib/financial/locales/pt.yml +67 -0
  31. data/lib/financial/parcels.rb +87 -0
  32. data/lib/financial/per_cent.rb +12 -0
  33. data/lib/financial/print_table.rb +34 -0
  34. data/lib/financial/revenue.rb +40 -0
  35. data/lib/financial/revenues.rb +16 -0
  36. data/lib/financial/rspec_matchers.rb +32 -0
  37. data/lib/financial/tax.rb +4 -0
  38. data/lib/financial/version.rb +3 -0
  39. data/spec/financial/account_manager_spec.rb +38 -0
  40. data/spec/financial/account_spec.rb +399 -0
  41. data/spec/financial/balance_spec.rb +44 -0
  42. data/spec/financial/cost_spec.rb +78 -0
  43. data/spec/financial/costs_spec.rb +18 -0
  44. data/spec/financial/deposit_spec.rb +78 -0
  45. data/spec/financial/deposits_spec.rb +23 -0
  46. data/spec/financial/english_spec.rb +76 -0
  47. data/spec/financial/financial_date_spec.rb +50 -0
  48. data/spec/financial/financial_spec.rb +14 -0
  49. data/spec/financial/financial_table_spec.rb +31 -0
  50. data/spec/financial/locale_spec.rb +37 -0
  51. data/spec/financial/parcels_spec.rb +179 -0
  52. data/spec/financial/per_cent_spec.rb +24 -0
  53. data/spec/financial/portuguese_spec.rb +117 -0
  54. data/spec/financial/print_table_spec.rb +76 -0
  55. data/spec/financial/revenue_spec.rb +89 -0
  56. data/spec/financial/revenues_spec.rb +18 -0
  57. data/spec/financial/tax_spec.rb +42 -0
  58. data/spec/spec_helper.rb +25 -0
  59. 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,12 @@
1
+ module Financial
2
+ module PerCent
3
+ def self.included(base)
4
+ Numeric.class_eval do
5
+ def per_cent
6
+ self / 100.0
7
+ end
8
+ Financial.locale.add_per_cent_aliases
9
+ end
10
+ end
11
+ end
12
+ 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