amortizy 1.0.0 → 2.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +142 -3
- data/CONTRIBUTING.md +290 -0
- data/LICENSE.txt +1 -1
- data/README.md +385 -14
- data/Rakefile +3 -3
- data/lib/amortizy/console_formatter.rb +70 -0
- data/lib/amortizy/csv_formatter.rb +43 -0
- data/lib/amortizy/engine.rb +200 -278
- data/lib/amortizy/version.rb +1 -1
- data/lib/amortizy.rb +4 -2
- data/tasks/todo.md +74 -0
- metadata +11 -9
- data/.DS_Store +0 -0
- data/CODE_OF_CONDUCT.md +0 -132
- data/lib/.DS_Store +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1bf3cd11455f5c2c301066d64f911a15e696dd1b033c2b865a5d7ddaff93e05
|
|
4
|
+
data.tar.gz: 34482d2f3553108c4ad04d3dd238ff486e3c72aa266fd4f19582607720df98ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e1d49aaa154f7dbce6a7f5e9fddf77c04a4f6ea90af9662b4cfa1c6ed787a70672277cd6a8425346277067fef6af76ac2d3ec32ddfd2f7b3d972f049cdd43846
|
|
7
|
+
data.tar.gz: 94aaf0a040ba624cedc10ea49db5a873712b8682a6f6191439088eb02df8f74d27bb86c14cb9288607a51217d9f091ab643b3d4108fb83b3e04dcf8e28a11dd3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,144 @@
|
|
|
1
|
-
|
|
1
|
+
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [2.0.0] - 2026-04-19
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
#### Dynamic Payment Engine
|
|
13
|
+
- **Monthly payment frequency** - the most common loan payment type, now supported
|
|
14
|
+
- **Bi-weekly payment frequency** - every 14 days
|
|
15
|
+
- **`num_payments` input** - specify exact payment count instead of term length
|
|
16
|
+
- **Any term length** - no longer restricted to 6, 9, 12, 15, 18 months
|
|
17
|
+
- Dynamic payment count calculation based on frequency and term
|
|
18
|
+
|
|
19
|
+
#### Public API
|
|
20
|
+
- `#schedule` - returns frozen array of payment hashes (replaces private `generate_schedule_data`)
|
|
21
|
+
- `#summary` - returns hash with loan totals, dates, and payment info
|
|
22
|
+
- `#end_date` - last payment date
|
|
23
|
+
- `#total_interest` - sum of all interest payments
|
|
24
|
+
- `#total_paid` - sum of all payments
|
|
25
|
+
- `#payment_amount` - regular payment amount
|
|
26
|
+
|
|
27
|
+
#### Code Organization
|
|
28
|
+
- Extracted `ConsoleFormatter` for terminal output
|
|
29
|
+
- Extracted `CsvFormatter` for CSV export
|
|
30
|
+
- Engine class now focused on amortization math only
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- `term_months` is now optional (provide `term_months` OR `num_payments`, not both)
|
|
34
|
+
- Removed hardcoded payment count lookup table - all counts calculated dynamically
|
|
35
|
+
- Minimum Ruby version bumped to 3.0
|
|
36
|
+
|
|
37
|
+
### Breaking Changes
|
|
38
|
+
- `term_months` is no longer a required keyword argument
|
|
39
|
+
- **Daily frequency payment counts changed significantly.** v1.0 used a hardcoded lookup table with business-day-approximate counts (e.g., 248 payments for 12 months). v2.0 calculates dynamically using calendar days (365 for 12 months) unless `bank_days_only: true` is set. This is a ~47% increase in payment count for daily-frequency loans without `bank_days_only`. If your application relied on v1.0 daily payment counts, set `bank_days_only: true` to get business-day counts, or use `num_payments` to specify the exact count.
|
|
40
|
+
- Weekly frequency payment counts may differ by 0-1 due to rounding in dynamic calculation
|
|
41
|
+
- `principal` must now be positive (zero and negative values raise `ArgumentError`)
|
|
42
|
+
|
|
43
|
+
## [1.0.0] - 2024-12-02
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
#### Core Features
|
|
48
|
+
- Initial release of Amortizy gem
|
|
49
|
+
- Daily payment frequency support
|
|
50
|
+
- Weekly payment frequency support
|
|
51
|
+
- Flexible loan terms: 6, 9, 12, 15, and 18 months
|
|
52
|
+
- Simple interest calculation method (accrued daily)
|
|
53
|
+
- Precomputed interest calculation method (fixed per payment)
|
|
54
|
+
|
|
55
|
+
#### Advanced Loan Features
|
|
56
|
+
- Grace period handling with automatic interest capitalization
|
|
57
|
+
- Interest-only payment periods
|
|
58
|
+
- Origination fee support (added to principal)
|
|
59
|
+
- Additional fee support with three treatment options:
|
|
60
|
+
- Distributed across all payments
|
|
61
|
+
- Added to principal upfront
|
|
62
|
+
- Collected as separate first payment
|
|
63
|
+
|
|
64
|
+
#### Bank Day Calculations
|
|
65
|
+
- Weekend skipping (Saturday/Sunday)
|
|
66
|
+
- US Federal Reserve holiday support (11 holidays)
|
|
67
|
+
- Automatic weekend observation rules for holidays
|
|
68
|
+
|
|
69
|
+
#### Output Options
|
|
70
|
+
- Console output with formatted tables
|
|
71
|
+
- CSV export functionality
|
|
72
|
+
- Programmatic access to schedule data
|
|
73
|
+
|
|
74
|
+
#### Testing
|
|
75
|
+
- Comprehensive RSpec test suite with 29 test cases
|
|
76
|
+
- 100% test pass rate
|
|
77
|
+
- Coverage of all features and edge cases
|
|
78
|
+
|
|
79
|
+
#### Documentation
|
|
80
|
+
- Complete README with API reference
|
|
81
|
+
- Usage examples for common scenarios
|
|
82
|
+
- Detailed parameter documentation
|
|
83
|
+
- Contributing guidelines
|
|
84
|
+
|
|
85
|
+
### Dependencies
|
|
86
|
+
- holidays gem (~> 8.0) for federal holiday detection
|
|
87
|
+
- RSpec (~> 3.0) for testing
|
|
88
|
+
|
|
89
|
+
### Requirements
|
|
90
|
+
- Ruby 2.7 or higher
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Version History
|
|
95
|
+
|
|
96
|
+
### [1.0.0] - 2024-12-02
|
|
97
|
+
Initial public release
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Upgrade Guide
|
|
102
|
+
|
|
103
|
+
### From Pre-release to 1.0.0
|
|
104
|
+
|
|
105
|
+
If you were testing pre-release versions, upgrade by:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
gem uninstall amortizy
|
|
109
|
+
gem install amortizy
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Or in your Gemfile:
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
gem 'amortizy', '~> 1.0'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Then run:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
bundle update amortizy
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Future Plans
|
|
127
|
+
|
|
128
|
+
Potential features for future releases:
|
|
129
|
+
|
|
130
|
+
- Additional payment frequencies (monthly, bi-weekly)
|
|
131
|
+
- More interest calculation methods
|
|
132
|
+
- Support for additional holiday calendars (state, international)
|
|
133
|
+
- Balloon payment support
|
|
134
|
+
- Variable interest rates
|
|
135
|
+
- Payment modification capabilities
|
|
136
|
+
- Enhanced reporting formats
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Links
|
|
141
|
+
|
|
142
|
+
- [RubyGems](https://rubygems.org/gems/amortizy)
|
|
143
|
+
- [GitHub Repository](https://github.com/zapatify/amortizy)
|
|
144
|
+
- [Issue Tracker](https://github.com/zapatify/amortizy/issues)
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# Contributing to Amortizy
|
|
2
|
+
|
|
3
|
+
First off, thank you for considering contributing to Amortizy! It's people like you that make Amortizy such a great tool.
|
|
4
|
+
|
|
5
|
+
## Code of Conduct
|
|
6
|
+
|
|
7
|
+
This project and everyone participating in it is governed by the principle of respect and professionalism. By participating, you are expected to uphold this standard.
|
|
8
|
+
|
|
9
|
+
## How Can I Contribute?
|
|
10
|
+
|
|
11
|
+
### Reporting Bugs
|
|
12
|
+
|
|
13
|
+
Before creating bug reports, please check the [existing issues](https://github.com/zapatify/amortizy/issues) to avoid duplicates.
|
|
14
|
+
|
|
15
|
+
When you are creating a bug report, please include as many details as possible:
|
|
16
|
+
|
|
17
|
+
* **Use a clear and descriptive title**
|
|
18
|
+
* **Describe the exact steps to reproduce the problem**
|
|
19
|
+
* **Provide specific examples** - Include code snippets, loan parameters, or output
|
|
20
|
+
* **Describe the behavior you observed** and what you expected to see
|
|
21
|
+
* **Include your environment details**:
|
|
22
|
+
- Ruby version (`ruby -v`)
|
|
23
|
+
- Amortizy version (`gem list amortizy`)
|
|
24
|
+
- Operating system
|
|
25
|
+
|
|
26
|
+
**Example Bug Report:**
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Title: Grace period interest not capitalizing correctly for weekly frequency
|
|
30
|
+
|
|
31
|
+
Description:
|
|
32
|
+
When using weekly payment frequency with a 7-day grace period, the interest
|
|
33
|
+
is not being properly capitalized into the principal.
|
|
34
|
+
|
|
35
|
+
Steps to Reproduce:
|
|
36
|
+
1. Create schedule with weekly frequency
|
|
37
|
+
2. Set grace_period_days to 7
|
|
38
|
+
3. Generate schedule
|
|
39
|
+
4. Check effective principal
|
|
40
|
+
|
|
41
|
+
Expected: Principal should increase by ~7 days of interest
|
|
42
|
+
Actual: Principal remains unchanged
|
|
43
|
+
|
|
44
|
+
Environment:
|
|
45
|
+
- Ruby 3.2.0
|
|
46
|
+
- Amortizy 1.0.0
|
|
47
|
+
- macOS Sonoma
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Suggesting Enhancements
|
|
51
|
+
|
|
52
|
+
Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, please include:
|
|
53
|
+
|
|
54
|
+
* **Use a clear and descriptive title**
|
|
55
|
+
* **Provide a detailed description** of the suggested enhancement
|
|
56
|
+
* **Explain why this enhancement would be useful** to most Amortizy users
|
|
57
|
+
* **List any similar features** in other tools if applicable
|
|
58
|
+
|
|
59
|
+
**Example Enhancement Request:**
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Title: Add monthly payment frequency option
|
|
63
|
+
|
|
64
|
+
Description:
|
|
65
|
+
Currently Amortizy supports daily and weekly frequencies. Adding monthly
|
|
66
|
+
would be useful for traditional mortgage-style loans.
|
|
67
|
+
|
|
68
|
+
Use Case:
|
|
69
|
+
Many personal and business loans use monthly payments. This would make
|
|
70
|
+
Amortizy useful for a broader range of applications.
|
|
71
|
+
|
|
72
|
+
Similar Features:
|
|
73
|
+
- Most online loan calculators support monthly
|
|
74
|
+
- Banking systems typically use monthly
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Pull Requests
|
|
78
|
+
|
|
79
|
+
Pull requests are the best way to propose changes to the codebase.
|
|
80
|
+
|
|
81
|
+
1. **Fork the repo** and create your branch from `main`
|
|
82
|
+
2. **Make your changes**
|
|
83
|
+
3. **Add tests** if you've added code that should be tested
|
|
84
|
+
4. **Ensure the test suite passes** (`bundle exec rspec`)
|
|
85
|
+
5. **Update documentation** if needed
|
|
86
|
+
6. **Write a clear commit message**
|
|
87
|
+
7. **Open a Pull Request**
|
|
88
|
+
|
|
89
|
+
#### Pull Request Guidelines
|
|
90
|
+
|
|
91
|
+
* Follow the existing code style
|
|
92
|
+
* Write clear, descriptive commit messages
|
|
93
|
+
* Include tests for new functionality
|
|
94
|
+
* Update README.md if adding features
|
|
95
|
+
* Update CHANGELOG.md under [Unreleased]
|
|
96
|
+
* Keep PRs focused - one feature/fix per PR
|
|
97
|
+
|
|
98
|
+
**Example PR Description:**
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
## Description
|
|
102
|
+
Adds support for bi-weekly payment frequency
|
|
103
|
+
|
|
104
|
+
## Changes
|
|
105
|
+
- Added :biweekly to frequency validation
|
|
106
|
+
- Updated payment calculations for bi-weekly schedules
|
|
107
|
+
- Added tests for bi-weekly frequency
|
|
108
|
+
- Updated README with bi-weekly examples
|
|
109
|
+
|
|
110
|
+
## Testing
|
|
111
|
+
- All existing tests pass
|
|
112
|
+
- Added 3 new tests for bi-weekly functionality
|
|
113
|
+
- Manually tested with various loan parameters
|
|
114
|
+
|
|
115
|
+
## Documentation
|
|
116
|
+
- Updated README.md with bi-weekly examples
|
|
117
|
+
- Updated API reference table
|
|
118
|
+
- Added to CHANGELOG.md
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Development Setup
|
|
122
|
+
|
|
123
|
+
### Prerequisites
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Install Ruby 2.7 or higher
|
|
127
|
+
ruby -v
|
|
128
|
+
|
|
129
|
+
# Install Bundler
|
|
130
|
+
gem install bundler
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Setup
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Clone your fork
|
|
137
|
+
git clone https://github.com/YOUR_USERNAME/amortizy.git
|
|
138
|
+
cd amortizy
|
|
139
|
+
|
|
140
|
+
# Install dependencies
|
|
141
|
+
bundle install
|
|
142
|
+
|
|
143
|
+
# Run tests
|
|
144
|
+
bundle exec rspec
|
|
145
|
+
|
|
146
|
+
# Run the CLI
|
|
147
|
+
bundle exec exe/amortizy
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Running Tests
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Run all tests
|
|
154
|
+
bundle exec rspec
|
|
155
|
+
|
|
156
|
+
# Run specific test file
|
|
157
|
+
bundle exec rspec spec/engine_spec.rb
|
|
158
|
+
|
|
159
|
+
# Run with coverage (if configured)
|
|
160
|
+
COVERAGE=true bundle exec rspec
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Code Style
|
|
164
|
+
|
|
165
|
+
* Follow Ruby community style guidelines
|
|
166
|
+
* Use 2 spaces for indentation (not tabs)
|
|
167
|
+
* Keep lines under 100 characters when reasonable
|
|
168
|
+
* Use meaningful variable and method names
|
|
169
|
+
* Add comments for complex logic
|
|
170
|
+
|
|
171
|
+
**Good Example:**
|
|
172
|
+
```ruby
|
|
173
|
+
def calculate_daily_interest(principal, annual_rate)
|
|
174
|
+
# Convert annual rate to daily and multiply by principal
|
|
175
|
+
(principal * annual_rate) / 365.0
|
|
176
|
+
end
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Bad Example:**
|
|
180
|
+
```ruby
|
|
181
|
+
def calc(p,r)
|
|
182
|
+
p*r/365.0 # calculate interest
|
|
183
|
+
end
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Project Structure
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
amortizy/
|
|
190
|
+
├── lib/
|
|
191
|
+
│ ├── amortizy.rb # Main entry point
|
|
192
|
+
│ └── amortizy/
|
|
193
|
+
│ ├── version.rb # Version number
|
|
194
|
+
│ └── engine.rb # Core logic
|
|
195
|
+
├── spec/
|
|
196
|
+
│ ├── spec_helper.rb # RSpec configuration
|
|
197
|
+
│ └── engine_spec.rb # Main test file
|
|
198
|
+
└── amortizy.gemspec # Gem specification
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Testing Guidelines
|
|
202
|
+
|
|
203
|
+
### Writing Tests
|
|
204
|
+
|
|
205
|
+
* Use descriptive test names
|
|
206
|
+
* Follow Arrange-Act-Assert pattern
|
|
207
|
+
* Test both happy paths and edge cases
|
|
208
|
+
* Mock external dependencies when appropriate
|
|
209
|
+
|
|
210
|
+
**Example Test:**
|
|
211
|
+
```ruby
|
|
212
|
+
describe 'grace period' do
|
|
213
|
+
it 'capitalizes interest during grace period' do
|
|
214
|
+
# Arrange
|
|
215
|
+
schedule = Amortizy::AmortizationSchedule.new(
|
|
216
|
+
start_date: "2025-01-15",
|
|
217
|
+
principal: 100000.00,
|
|
218
|
+
term_months: 12,
|
|
219
|
+
annual_rate: 10.0,
|
|
220
|
+
frequency: :daily,
|
|
221
|
+
grace_period_days: 5
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
# Act
|
|
225
|
+
effective_principal = schedule.send(:effective_principal)
|
|
226
|
+
|
|
227
|
+
# Assert
|
|
228
|
+
expect(effective_principal).to be > 100000.00
|
|
229
|
+
expect(effective_principal).to be < 100200.00
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Commit Message Guidelines
|
|
235
|
+
|
|
236
|
+
Write clear, concise commit messages that explain what and why:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
# Good commit messages
|
|
240
|
+
git commit -m "Add bi-weekly payment frequency support"
|
|
241
|
+
git commit -m "Fix interest calculation for leap years"
|
|
242
|
+
git commit -m "Update README with precomputed interest examples"
|
|
243
|
+
|
|
244
|
+
# Bad commit messages
|
|
245
|
+
git commit -m "fix bug"
|
|
246
|
+
git commit -m "updates"
|
|
247
|
+
git commit -m "wip"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
For larger commits, use multi-line messages:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
git commit -m "Add support for adjustable rate mortgages
|
|
254
|
+
|
|
255
|
+
- Add rate_changes parameter to accept rate change schedule
|
|
256
|
+
- Update interest calculation to handle variable rates
|
|
257
|
+
- Add comprehensive tests for ARM scenarios
|
|
258
|
+
- Update documentation with ARM examples
|
|
259
|
+
|
|
260
|
+
Closes #42"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Documentation
|
|
264
|
+
|
|
265
|
+
When adding features, update:
|
|
266
|
+
|
|
267
|
+
1. **README.md** - Add usage examples
|
|
268
|
+
2. **CHANGELOG.md** - Add to [Unreleased] section
|
|
269
|
+
3. **Code comments** - Explain complex logic
|
|
270
|
+
4. **RDoc/YARD** - Document public methods (if applicable)
|
|
271
|
+
|
|
272
|
+
## Release Process
|
|
273
|
+
|
|
274
|
+
(For maintainers)
|
|
275
|
+
|
|
276
|
+
1. Update version in `lib/amortizy/version.rb`
|
|
277
|
+
2. Update CHANGELOG.md with release date
|
|
278
|
+
3. Commit changes: `git commit -am "Bump version to X.Y.Z"`
|
|
279
|
+
4. Create tag: `git tag -a vX.Y.Z -m "Version X.Y.Z"`
|
|
280
|
+
5. Push: `git push && git push --tags`
|
|
281
|
+
6. Build: `gem build amortizy.gemspec`
|
|
282
|
+
7. Publish: `gem push amortizy-X.Y.Z.gem`
|
|
283
|
+
|
|
284
|
+
## Questions?
|
|
285
|
+
|
|
286
|
+
Feel free to open an issue with the label "question" or reach out to the maintainers.
|
|
287
|
+
|
|
288
|
+
## Thank You!
|
|
289
|
+
|
|
290
|
+
Your contributions to open source, large or small, make projects like this possible. Thank you for taking the time to contribute.
|
data/LICENSE.txt
CHANGED