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.
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