blend_spreadsheet_loan_generator 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +7 -0
- data/README.md +36 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/blend_spreadsheet_loan_generator.gemspec +35 -0
- data/exe/bslg +5 -0
- data/lib/blend_spreadsheet_loan_generator.rb +37 -0
- data/lib/blend_spreadsheet_loan_generator/concerns/csv_concern.rb +29 -0
- data/lib/blend_spreadsheet_loan_generator/concerns/spreadsheet_concern.rb +123 -0
- data/lib/blend_spreadsheet_loan_generator/early_repay.rb +163 -0
- data/lib/blend_spreadsheet_loan_generator/formula.rb +211 -0
- data/lib/blend_spreadsheet_loan_generator/generate.rb +73 -0
- data/lib/blend_spreadsheet_loan_generator/init.rb +36 -0
- data/lib/blend_spreadsheet_loan_generator/linear.rb +20 -0
- data/lib/blend_spreadsheet_loan_generator/loan.rb +127 -0
- data/lib/blend_spreadsheet_loan_generator/normal_interests.rb +21 -0
- data/lib/blend_spreadsheet_loan_generator/realistic_interests.rb +19 -0
- data/lib/blend_spreadsheet_loan_generator/restructure.rb +121 -0
- data/lib/blend_spreadsheet_loan_generator/simple_interests.rb +18 -0
- data/lib/blend_spreadsheet_loan_generator/standard.rb +25 -0
- data/lib/blend_spreadsheet_loan_generator/version.rb +13 -0
- metadata +141 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 740b10d39f33e08cc9522d153db7fd353d90711139f1dea78577ff00294745e9
|
4
|
+
data.tar.gz: e99017730cf0b998baf028f90b2237151c3eba8c2d0b1f581b808f7c8ada1438
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4496083db9061a2521f248554d5da3fbe2c63c8bf955b2a788640aae0244670ad0a213e2df8550632524e6089685ddabd47156e07ce5f1a64cbb648d18bffe73
|
7
|
+
data.tar.gz: bd42f93b037d7813f854c6228bc1d5b54203c74f32f6788bbbe43bd962f0a496edece072c2ded50efc9de6aeb628f6dd0dd68ec8c99c94535a7e20dfa57d3410
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# SpreadsheetLoanGenerator
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/spreadsheet_loan_generator`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'spreadsheet_loan_generator'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install spreadsheet_loan_generator
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/blend_spreadsheet_loan_generator.
|
36
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "blend_spreadsheet_loan_generator"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'lib/blend_spreadsheet_loan_generator/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'blend_spreadsheet_loan_generator'
|
5
|
+
spec.version = BlendSpreadsheetLoanGenerator::VERSION
|
6
|
+
spec.authors = ['MZiserman']
|
7
|
+
spec.email = ['martinziserman@gmail.com']
|
8
|
+
|
9
|
+
spec.summary = 'Generate spreadsheets amortization schedules from the command line'
|
10
|
+
spec.homepage = 'https://github.com/CapSens/blend_spreadsheet_loan_generator'
|
11
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
|
12
|
+
|
13
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
14
|
+
|
15
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
16
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
17
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
end
|
24
|
+
spec.bindir = 'exe'
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.executables << 'bslg'
|
27
|
+
|
28
|
+
spec.require_paths = ['lib']
|
29
|
+
|
30
|
+
spec.add_runtime_dependency 'activesupport'
|
31
|
+
spec.add_runtime_dependency 'csv'
|
32
|
+
spec.add_runtime_dependency 'dry-cli', '0.6'
|
33
|
+
spec.add_runtime_dependency 'google_drive'
|
34
|
+
spec.add_development_dependency 'pry'
|
35
|
+
end
|
data/exe/bslg
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'dry/cli'
|
2
|
+
require 'google_drive'
|
3
|
+
require 'active_support/all'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'csv'
|
6
|
+
|
7
|
+
require 'blend_spreadsheet_loan_generator/version'
|
8
|
+
|
9
|
+
module BlendSpreadsheetLoanGenerator
|
10
|
+
class Error < StandardError; end
|
11
|
+
|
12
|
+
extend Dry::CLI::Registry
|
13
|
+
|
14
|
+
autoload :SpreadsheetConcern, 'blend_spreadsheet_loan_generator/concerns/spreadsheet_concern'
|
15
|
+
autoload :CsvConcern, 'blend_spreadsheet_loan_generator/concerns/csv_concern'
|
16
|
+
|
17
|
+
autoload :Linear, 'blend_spreadsheet_loan_generator/linear'
|
18
|
+
autoload :Standard, 'blend_spreadsheet_loan_generator/standard'
|
19
|
+
autoload :NormalInterests, 'blend_spreadsheet_loan_generator/normal_interests'
|
20
|
+
autoload :SimpleInterests, 'blend_spreadsheet_loan_generator/simple_interests'
|
21
|
+
autoload :RealisticInterests, 'blend_spreadsheet_loan_generator/realistic_interests'
|
22
|
+
autoload :Formula, 'blend_spreadsheet_loan_generator/formula'
|
23
|
+
|
24
|
+
autoload :Loan, 'blend_spreadsheet_loan_generator/loan'
|
25
|
+
|
26
|
+
autoload :Version, 'blend_spreadsheet_loan_generator/version'
|
27
|
+
autoload :Generate, 'blend_spreadsheet_loan_generator/generate'
|
28
|
+
autoload :Restructure, 'blend_spreadsheet_loan_generator/restructure'
|
29
|
+
autoload :EarlyRepay, 'blend_spreadsheet_loan_generator/early_repay'
|
30
|
+
autoload :Init, 'blend_spreadsheet_loan_generator/init'
|
31
|
+
|
32
|
+
register 'init', Init, aliases: ['i', '-i', '--init']
|
33
|
+
register 'version', Version, aliases: ['v', '-v', '--version']
|
34
|
+
register 'generate', Generate, aliases: ['g', '-g', '--generate']
|
35
|
+
register 'restructure', Restructure, aliases: ['r', '-r', '--restructure']
|
36
|
+
register 'early_repay', EarlyRepay, aliases: ['er', '-er', '--early_repay']
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module BlendSpreadsheetLoanGenerator
|
2
|
+
module CsvConcern
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def generate_csv(worksheet:, target_path:)
|
7
|
+
filename = File.join(target_path, "#{loan.name}.csv")
|
8
|
+
CSV.open(filename, 'wb') do |csv|
|
9
|
+
loan.duration.times do |line|
|
10
|
+
row = []
|
11
|
+
columns.each.with_index do |name, column|
|
12
|
+
row << (
|
13
|
+
case name
|
14
|
+
when 'index'
|
15
|
+
worksheet[line + 2, column + 1]
|
16
|
+
when 'due_on'
|
17
|
+
Date.parse(worksheet[line + 2, column + 1]).strftime('%m/%d/%Y')
|
18
|
+
else
|
19
|
+
worksheet[line + 2, column + 1].gsub(',', '.').to_f
|
20
|
+
end
|
21
|
+
)
|
22
|
+
end
|
23
|
+
csv << row
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module BlendSpreadsheetLoanGenerator
|
2
|
+
module SpreadsheetConcern
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def columns
|
7
|
+
%w[
|
8
|
+
index
|
9
|
+
due_on
|
10
|
+
remaining_capital_start
|
11
|
+
remaining_capital_end
|
12
|
+
period_theoric_interests
|
13
|
+
delta
|
14
|
+
accrued_delta
|
15
|
+
amount_to_add
|
16
|
+
period_interests
|
17
|
+
period_capital
|
18
|
+
total_paid_capital_end_of_period
|
19
|
+
total_paid_interests_end_of_period
|
20
|
+
period_total
|
21
|
+
capitalized_interests_start
|
22
|
+
capitalized_interests_end
|
23
|
+
period_rate
|
24
|
+
period_calculated_capital
|
25
|
+
period_calculated_interests
|
26
|
+
period_reimbursed_capitalized_interests
|
27
|
+
period_leap_days
|
28
|
+
period_non_leap_days
|
29
|
+
period_fees
|
30
|
+
period_calculated_fees
|
31
|
+
capitalized_fees_start
|
32
|
+
capitalized_fees_end
|
33
|
+
period_reimbursed_capitalized_fees
|
34
|
+
period_fees_rate
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
def currency_columns
|
39
|
+
%w[
|
40
|
+
remaining_capital_start
|
41
|
+
remaining_capital_end
|
42
|
+
amount_to_add
|
43
|
+
period_interests
|
44
|
+
period_capital
|
45
|
+
total_paid_capital_end_of_period
|
46
|
+
total_paid_interests_end_of_period
|
47
|
+
period_total
|
48
|
+
capitalized_interests_start
|
49
|
+
capitalized_interests_end
|
50
|
+
period_reimbursed_capitalized_interests
|
51
|
+
period_fees
|
52
|
+
capitalized_fees_start
|
53
|
+
capitalized_fees_end
|
54
|
+
period_reimbursed_capitalized_fees
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
def precise_columns
|
59
|
+
%w[
|
60
|
+
period_theoric_interests
|
61
|
+
period_calculated_interests
|
62
|
+
period_calculated_capital
|
63
|
+
delta
|
64
|
+
accrued_delta
|
65
|
+
period_rate
|
66
|
+
period_calculated_fees
|
67
|
+
period_fees_rate
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def column_letter(column)
|
72
|
+
('A'..'ZZ').to_a[columns.index(column)]
|
73
|
+
end
|
74
|
+
|
75
|
+
def apply_formats(worksheet:)
|
76
|
+
precise_columns.each do |column|
|
77
|
+
index = columns.index(column) + 1
|
78
|
+
worksheet.set_number_format(1, index, loan.duration + 1, 1, '0.00000000')
|
79
|
+
end
|
80
|
+
currency_columns.each do |column|
|
81
|
+
index = columns.index(column) + 1
|
82
|
+
worksheet.set_number_format(1, index, loan.duration + 1, 1, '0.00')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def apply_formulas(worksheet:)
|
87
|
+
columns.each.with_index do |title, column|
|
88
|
+
worksheet[1, column + 1] = title
|
89
|
+
end
|
90
|
+
loan.duration.times do |line|
|
91
|
+
columns.each.with_index do |title, column|
|
92
|
+
worksheet[line + 2, column + 1] = @formula.send("#{title}_formula", line: line + 2)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def column_range(column: 'A', upto: , exclude_head: true)
|
98
|
+
start_line = exclude_head ? 2 : 1
|
99
|
+
|
100
|
+
"#{column}#{start_line}:#{column}#{upto}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def index_to_line(index:)
|
104
|
+
index + 1 # first term is on line 2
|
105
|
+
end
|
106
|
+
|
107
|
+
def excel_float(float)
|
108
|
+
float.to_s.gsub('.', ',')
|
109
|
+
end
|
110
|
+
|
111
|
+
# used heavily in formula concern
|
112
|
+
def respond_to_missing?(method_name, include_private = false)
|
113
|
+
columns.include?(method_name.to_s) || super
|
114
|
+
end
|
115
|
+
|
116
|
+
def method_missing(method_name, *args, **kwargs)
|
117
|
+
return super unless respond_to_missing?(method_name)
|
118
|
+
|
119
|
+
"#{column_letter(method_name.to_s)}#{args.first}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module BlendSpreadsheetLoanGenerator
|
2
|
+
class EarlyRepay < Dry::CLI::Command
|
3
|
+
include SpreadsheetConcern
|
4
|
+
include CsvConcern
|
5
|
+
|
6
|
+
attr_accessor :loan
|
7
|
+
|
8
|
+
desc "Generate spreadsheet"
|
9
|
+
|
10
|
+
argument :last_paid_term, type: :integer, required: true, desc: 'last paid term, restructuration starts at last_paid + 1'
|
11
|
+
argument :amount_paid, type: :integer, required: true, desc: 'amount early repaid'
|
12
|
+
argument :from_path, type: :string, required: true, desc: 'csv to restructure'
|
13
|
+
argument :rate, type: :float, required: true, desc: 'year rate post restructuration'
|
14
|
+
|
15
|
+
option :period_duration, type: :integer, default: 1, desc: 'duration of a period in months'
|
16
|
+
option :due_on, type: :date, default: Date.today, desc: 'date of the pay day of the first period DD/MM/YYYY'
|
17
|
+
option :deferred_and_capitalized, type: :integer, default: 0, desc: 'periods with no capital or interests paid'
|
18
|
+
option :deferred, type: :integer, default: 0, desc: 'periods with only interests paid'
|
19
|
+
option :type, type: :string, default: 'standard', values: %w[standard linear], desc: 'type of amortization'
|
20
|
+
option :interests_type, type: :string, default: 'simple', values: %w[simple realistic normal], desc: 'type of interests calculations'
|
21
|
+
option :fees_rate, type: :float, default: 0.0, required: true, desc: 'year fees rate'
|
22
|
+
option :starting_capitalized_interests, type: :float, default: 0.0, desc: 'starting capitalized interests (if ongoing loan)'
|
23
|
+
option :starting_capitalized_fees, type: :float, default: 0.0, desc: 'starting capitalized fees (if ongoing loan)'
|
24
|
+
option :target_path, type: :string, default: './', desc: 'where to put the generated csv'
|
25
|
+
|
26
|
+
def call(last_paid_term:, amount_paid:, from_path:, rate:, **options)
|
27
|
+
begin
|
28
|
+
session = GoogleDrive::Session.from_config(
|
29
|
+
File.join(ENV['SPREADSHEET_LOAN_GENERATOR_DIR'], 'config.json')
|
30
|
+
)
|
31
|
+
rescue StandardError => e
|
32
|
+
if ENV['SPREADSHEET_LOAN_GENERATOR_DIR'].blank?
|
33
|
+
puts 'please set SPREADSHEET_LOAN_GENERATOR_DIR'
|
34
|
+
else
|
35
|
+
puts 'Cannot connect to google drive. Did you run slg init CLIENT_ID CLIENT_SECRET ?'
|
36
|
+
end
|
37
|
+
return
|
38
|
+
end
|
39
|
+
|
40
|
+
f = CSV.open(from_path)
|
41
|
+
values = f.to_a
|
42
|
+
values.map! { |r| set_types([columns, r].transpose.to_h.with_indifferent_access) }
|
43
|
+
|
44
|
+
last_paid_line = values.index { |term| term[:index] == last_paid_term.to_i }
|
45
|
+
|
46
|
+
total_to_be_paid = (
|
47
|
+
values[last_paid_line + 1][:remaining_capital_start] +
|
48
|
+
values[last_paid_line + 1][:capitalized_interests_start] +
|
49
|
+
values[last_paid_line + 1][:capitalized_fees_start]
|
50
|
+
)
|
51
|
+
|
52
|
+
amount_paid = amount_paid.to_f
|
53
|
+
duration = (
|
54
|
+
if total_to_be_paid == amount_paid
|
55
|
+
1
|
56
|
+
else
|
57
|
+
values.last[:index] - values[last_paid_line][:index]
|
58
|
+
end
|
59
|
+
)
|
60
|
+
|
61
|
+
starting_capitalized_interests = 0.0
|
62
|
+
starting_capitalized_fees = 0.0
|
63
|
+
|
64
|
+
due_on = values[last_paid_line + 1][:due_on] + 1.month
|
65
|
+
|
66
|
+
capital_paid = amount_paid.to_f - (
|
67
|
+
values[last_paid_line + 1][:capitalized_interests_start] +
|
68
|
+
values[last_paid_line + 1][:capitalized_fees_start]
|
69
|
+
)
|
70
|
+
|
71
|
+
@loan = Loan.new(
|
72
|
+
amount: values[last_paid_line][:remaining_capital_end],
|
73
|
+
duration: duration,
|
74
|
+
rate: rate,
|
75
|
+
fees_rate: options.fetch(:fees_rate),
|
76
|
+
period_duration: options.fetch(:period_duration),
|
77
|
+
due_on: due_on,
|
78
|
+
deferred_and_capitalized: options.fetch(:deferred_and_capitalized),
|
79
|
+
deferred: options.fetch(:deferred),
|
80
|
+
type: options.fetch(:type),
|
81
|
+
interests_type: options.fetch(:interests_type),
|
82
|
+
starting_capitalized_interests: starting_capitalized_interests,
|
83
|
+
starting_capitalized_fees: starting_capitalized_fees
|
84
|
+
)
|
85
|
+
|
86
|
+
spreadsheet = session.create_spreadsheet(loan.name)
|
87
|
+
worksheet = spreadsheet.add_worksheet(loan.type, loan.duration + 2, columns.count + 1, index: 0)
|
88
|
+
|
89
|
+
@formula = Formula.new(loan: loan)
|
90
|
+
|
91
|
+
apply_formulas(worksheet: worksheet)
|
92
|
+
|
93
|
+
worksheet[2, columns.index('remaining_capital_start') + 1] =
|
94
|
+
excel_float(values[last_paid_line][:remaining_capital_end])
|
95
|
+
|
96
|
+
worksheet[2, columns.index('remaining_capital_end') + 1] =
|
97
|
+
excel_float(values[last_paid_line][:remaining_capital_end] - capital_paid)
|
98
|
+
|
99
|
+
worksheet[2, columns.index('period_interests') + 1] =
|
100
|
+
excel_float(values[last_paid_line + 1][:period_interests])
|
101
|
+
|
102
|
+
worksheet[2, columns.index('period_fees') + 1] =
|
103
|
+
excel_float(values[last_paid_line + 1][:period_fees])
|
104
|
+
|
105
|
+
worksheet[2, columns.index('period_capital') + 1] =
|
106
|
+
excel_float(capital_paid)
|
107
|
+
|
108
|
+
worksheet[2, columns.index('capitalized_interests_start') + 1] =
|
109
|
+
excel_float(values[last_paid_line + 1][:capitalized_interests_start])
|
110
|
+
|
111
|
+
worksheet[2, columns.index('capitalized_fees_start') + 1] =
|
112
|
+
excel_float(values[last_paid_line + 1][:capitalized_fees_start])
|
113
|
+
|
114
|
+
worksheet[2, columns.index('period_reimbursed_capitalized_interests') + 1] =
|
115
|
+
excel_float(values[last_paid_line + 1][:capitalized_interests_start])
|
116
|
+
|
117
|
+
worksheet[2, columns.index('period_reimbursed_capitalized_fees') + 1] =
|
118
|
+
excel_float(values[last_paid_line + 1][:capitalized_fees_start])
|
119
|
+
|
120
|
+
apply_formats(worksheet: worksheet)
|
121
|
+
|
122
|
+
worksheet.save
|
123
|
+
worksheet.reload
|
124
|
+
|
125
|
+
generate_csv(worksheet: worksheet, target_path: options.fetch(:target_path))
|
126
|
+
|
127
|
+
puts worksheet.human_url
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_types(h)
|
131
|
+
h[:index] = h[:index].to_i
|
132
|
+
|
133
|
+
h[:due_on] = Date.strptime(h[:due_on], '%m/%d/%Y')
|
134
|
+
h[:remaining_capital_start] = h[:remaining_capital_start].to_f
|
135
|
+
h[:remaining_capital_end] = h[:remaining_capital_end].to_f
|
136
|
+
h[:period_theoric_interests] = h[:period_theoric_interests].to_f
|
137
|
+
h[:delta] = h[:delta].to_f
|
138
|
+
h[:accrued_delta] = h[:accrued_delta].to_f
|
139
|
+
h[:amount_to_add] = h[:amount_to_add].to_f
|
140
|
+
h[:period_interests] = h[:period_interests].to_f
|
141
|
+
h[:period_capital] = h[:period_capital].to_f
|
142
|
+
h[:total_paid_capital_end_of_period] = h[:total_paid_capital_end_of_period].to_f
|
143
|
+
h[:total_paid_interests_end_of_period] = h[:total_paid_interests_end_of_period].to_f
|
144
|
+
h[:period_total] = h[:period_total].to_f
|
145
|
+
h[:capitalized_interests_start] = h[:capitalized_interests_start].to_f
|
146
|
+
h[:capitalized_interests_end] = h[:capitalized_interests_end].to_f
|
147
|
+
h[:period_rate] = h[:period_rate].to_f
|
148
|
+
h[:period_calculated_capital] = h[:period_calculated_capital].to_f
|
149
|
+
h[:period_calculated_interests] = h[:period_calculated_interests].to_f
|
150
|
+
h[:period_reimbursed_capitalized_interests] = h[:period_reimbursed_capitalized_interests].to_f
|
151
|
+
h[:period_leap_days] = h[:period_leap_days].to_i
|
152
|
+
h[:period_non_leap_days] = h[:period_non_leap_days].to_i
|
153
|
+
h[:period_fees] = h[:period_fees].to_f
|
154
|
+
h[:period_calculated_fees] = h[:period_calculated_fees].to_f
|
155
|
+
h[:capitalized_fees_start] = h[:capitalized_fees_start].to_f
|
156
|
+
h[:capitalized_fees_end] = h[:capitalized_fees_end].to_f
|
157
|
+
h[:period_reimbursed_capitalized_fees] = h[:period_reimbursed_capitalized_fees].to_f
|
158
|
+
h[:period_fees_rate] = h[:period_fees_rate].to_f
|
159
|
+
|
160
|
+
h
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|