amortizy 1.0.0 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '098cde951446da868e5cc5790b832794a09dd7ba991ffb34125f02053e59489e'
4
- data.tar.gz: 923b3440f1046b7c0c92483997c24934623f234c5e47f78333b9d87ca8536bfa
3
+ metadata.gz: 00f0ccad91127633326557a81254c429737b526a834bb18de2235b842390f7ef
4
+ data.tar.gz: fcf4c2b4d999c1c276446fb36ea85984c7d380b4819b9592f55afcdb405985d2
5
5
  SHA512:
6
- metadata.gz: 01c8a63684018625527eb633d6b7febc03b92d37ed20221b6138dc66080908ba4d5a0ef4649ae65172cbe67a9d1cb6c455ad70d95804ef9b64e9df083c75ec1b
7
- data.tar.gz: d57d565cf0631f7f7016776111b1c1fe680549ae1a7583f30ba2c0cdf7b44bf2650e029a43e1593368f162c9209c1c5bca2d93c3eb5e7e95e96c98571b5d2de8
6
+ metadata.gz: 73e33d2c4a0ee6f0ab15d9618d4aa53df5bbbe16608630f125dac377e674e82bf8c576362e492257692c928b6ec0328781cd91c752a57b8d55c36946154fb804
7
+ data.tar.gz: 0c9e25aabdceee720c8fb6fcf2367b101fbce214642e4be84022f0ea2ca166478ea2bbeb190018bca41c03fe63b5e87963e5c79f1fc23b4b333cea71d72d8314
data/CHANGELOG.md CHANGED
@@ -1,5 +1,170 @@
1
- ## [Unreleased]
1
+ # Changelog
2
2
 
3
- ## [0.1.0] - 2025-12-02
3
+ All notable changes to this project will be documented in this file.
4
4
 
5
- - Initial release
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.1.0] - 2026-04-20
9
+
10
+ ### Added
11
+
12
+ #### Commercial Financing Disclosure Module
13
+ - **`Amortizy::Disclosure`** - new class that computes disclosure data elements for
14
+ closed-end commercial loan transactions per California SB 1235 (Title 10, Chapter 3)
15
+ - **APR calculation** using the actuarial method per Appendix J of Regulation Z
16
+ (12 CFR Part 1026, section 940) with Newton-Raphson solver and bisection fallback
17
+ - **Finance charge** - total dollar cost of financing including interest and all fees (section 943)
18
+ - **Amount financed** - principal adjusted for prepaid finance charges (section 900(a)(1)(B))
19
+ - **Recipient funds** - net amount disbursed to borrower after third-party payoffs (section 900(a)(26))
20
+ - **Term display** - formatted per regulation: days for terms <= 1 year,
21
+ years/months for longer terms (section 901(a)(4))
22
+ - **Average monthly cost** - automatically computed for non-monthly payment frequencies (section 910(a)(12))
23
+ - **Prepayment information** - structured data for prepayment penalty disclosures (section 910(a)(8-10))
24
+ - **`#to_h`** - flat hash of all computed values
25
+ - **`#to_labeled_h`** - hash with regulation-correct labels from section 910
26
+
27
+ #### Design Notes
28
+ - Disclosure class wraps an existing `AmortizationSchedule` — no changes to the engine API
29
+ - Values are jurisdiction-agnostic: computed per the most stringent methodology (California),
30
+ usable for any state's commercial financing disclosure requirements
31
+ - Origination fee is treated as a prepaid finance charge by default
32
+ - APR rounded to nearest 10 basis points per section 901(a)(5)
33
+ - APR accuracy within 1/8 of 1 percentage point tolerance per section 955
34
+
35
+ ## [2.0.0] - 2026-04-19
36
+
37
+ ### Added
38
+
39
+ #### Dynamic Payment Engine
40
+ - **Monthly payment frequency** - the most common loan payment type, now supported
41
+ - **Bi-weekly payment frequency** - every 14 days
42
+ - **`num_payments` input** - specify exact payment count instead of term length
43
+ - **Any term length** - no longer restricted to 6, 9, 12, 15, 18 months
44
+ - Dynamic payment count calculation based on frequency and term
45
+
46
+ #### Public API
47
+ - `#schedule` - returns frozen array of payment hashes (replaces private `generate_schedule_data`)
48
+ - `#summary` - returns hash with loan totals, dates, and payment info
49
+ - `#end_date` - last payment date
50
+ - `#total_interest` - sum of all interest payments
51
+ - `#total_paid` - sum of all payments
52
+ - `#payment_amount` - regular payment amount
53
+
54
+ #### Code Organization
55
+ - Extracted `ConsoleFormatter` for terminal output
56
+ - Extracted `CsvFormatter` for CSV export
57
+ - Engine class now focused on amortization math only
58
+
59
+ ### Changed
60
+ - `term_months` is now optional (provide `term_months` OR `num_payments`, not both)
61
+ - Removed hardcoded payment count lookup table - all counts calculated dynamically
62
+ - Minimum Ruby version bumped to 3.0
63
+
64
+ ### Breaking Changes
65
+ - `term_months` is no longer a required keyword argument
66
+ - **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.
67
+ - Weekly frequency payment counts may differ by 0-1 due to rounding in dynamic calculation
68
+ - `principal` must now be positive (zero and negative values raise `ArgumentError`)
69
+
70
+ ## [1.0.0] - 2024-12-02
71
+
72
+ ### Added
73
+
74
+ #### Core Features
75
+ - Initial release of Amortizy gem
76
+ - Daily payment frequency support
77
+ - Weekly payment frequency support
78
+ - Flexible loan terms: 6, 9, 12, 15, and 18 months
79
+ - Simple interest calculation method (accrued daily)
80
+ - Precomputed interest calculation method (fixed per payment)
81
+
82
+ #### Advanced Loan Features
83
+ - Grace period handling with automatic interest capitalization
84
+ - Interest-only payment periods
85
+ - Origination fee support (added to principal)
86
+ - Additional fee support with three treatment options:
87
+ - Distributed across all payments
88
+ - Added to principal upfront
89
+ - Collected as separate first payment
90
+
91
+ #### Bank Day Calculations
92
+ - Weekend skipping (Saturday/Sunday)
93
+ - US Federal Reserve holiday support (11 holidays)
94
+ - Automatic weekend observation rules for holidays
95
+
96
+ #### Output Options
97
+ - Console output with formatted tables
98
+ - CSV export functionality
99
+ - Programmatic access to schedule data
100
+
101
+ #### Testing
102
+ - Comprehensive RSpec test suite with 29 test cases
103
+ - 100% test pass rate
104
+ - Coverage of all features and edge cases
105
+
106
+ #### Documentation
107
+ - Complete README with API reference
108
+ - Usage examples for common scenarios
109
+ - Detailed parameter documentation
110
+ - Contributing guidelines
111
+
112
+ ### Dependencies
113
+ - holidays gem (~> 8.0) for federal holiday detection
114
+ - RSpec (~> 3.0) for testing
115
+
116
+ ### Requirements
117
+ - Ruby 2.7 or higher
118
+
119
+ ---
120
+
121
+ ## Version History
122
+
123
+ ### [1.0.0] - 2024-12-02
124
+ Initial public release
125
+
126
+ ---
127
+
128
+ ## Upgrade Guide
129
+
130
+ ### From Pre-release to 1.0.0
131
+
132
+ If you were testing pre-release versions, upgrade by:
133
+
134
+ ```bash
135
+ gem uninstall amortizy
136
+ gem install amortizy
137
+ ```
138
+
139
+ Or in your Gemfile:
140
+
141
+ ```ruby
142
+ gem 'amortizy', '~> 1.0'
143
+ ```
144
+
145
+ Then run:
146
+
147
+ ```bash
148
+ bundle update amortizy
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Future Plans
154
+
155
+ Potential features for future releases:
156
+
157
+ - More interest calculation methods
158
+ - Support for additional holiday calendars (state, international)
159
+ - Balloon payment support
160
+ - Variable interest rates
161
+ - Payment modification capabilities
162
+ - Enhanced reporting formats
163
+
164
+ ---
165
+
166
+ ## Links
167
+
168
+ - [RubyGems](https://rubygems.org/gems/amortizy)
169
+ - [GitHub Repository](https://github.com/zapatify/amortizy)
170
+ - [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
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2025 Zapata
3
+ Copyright (c) 2025 Rich Zapata
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal