lbyte-budget 0.1.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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/.simplecov +25 -0
  3. data/API_DOCUMENTATION.md +526 -0
  4. data/CHANGELOG.md +5 -0
  5. data/CLEANUP.md +85 -0
  6. data/CODE_OF_CONDUCT.md +132 -0
  7. data/INTEGRATION_GUIDE.md +452 -0
  8. data/LICENSE.txt +21 -0
  9. data/RAILS_USAGE.md +510 -0
  10. data/README.md +367 -0
  11. data/Rakefile +19 -0
  12. data/TESTING.md +243 -0
  13. data/TEST_IMPLEMENTATION_SUMMARY.md +246 -0
  14. data/TEST_SUITE.md +253 -0
  15. data/app/controllers/budget/application_controller.rb +10 -0
  16. data/app/controllers/budget/line_items_controller.rb +112 -0
  17. data/app/controllers/budget/payments_controller.rb +108 -0
  18. data/app/controllers/budget/quotes_controller.rb +180 -0
  19. data/app/models/budget/line_item.rb +59 -0
  20. data/app/models/budget/payment.rb +58 -0
  21. data/app/models/budget/quote.rb +158 -0
  22. data/app/views/budget/line_items/index.json.jbuilder +7 -0
  23. data/app/views/budget/line_items/show.json.jbuilder +6 -0
  24. data/app/views/budget/payments/index.json.jbuilder +6 -0
  25. data/app/views/budget/payments/show.json.jbuilder +5 -0
  26. data/app/views/budget/quotes/index.json.jbuilder +15 -0
  27. data/app/views/budget/quotes/show.json.jbuilder +23 -0
  28. data/config/routes.rb +12 -0
  29. data/db/migrate/20251129000001_create_budget_quotes.rb +17 -0
  30. data/db/migrate/20251129000002_create_budget_line_items.rb +17 -0
  31. data/db/migrate/20251129000003_create_budget_payments.rb +18 -0
  32. data/examples/basic_usage.rb +130 -0
  33. data/examples/test_examples.rb +113 -0
  34. data/lib/budget/engine.rb +25 -0
  35. data/lib/budget/line_item.rb +66 -0
  36. data/lib/budget/payment.rb +56 -0
  37. data/lib/budget/quote.rb +163 -0
  38. data/lib/budget/version.rb +5 -0
  39. data/lib/budget.rb +10 -0
  40. data/lib/generators/budget/INSTALL +46 -0
  41. data/lib/generators/budget/install_generator.rb +33 -0
  42. data/sig/budget.rbs +4 -0
  43. metadata +115 -0
data/README.md ADDED
@@ -0,0 +1,367 @@
1
+ # Budget
2
+
3
+ A Rails Engine for managing quotes/budgets for eyeglasses businesses (or any business with advance payments and installment tracking). Perfect for optical stores that need to track customer orders with deposits and remaining balances.
4
+
5
+ ## Features
6
+
7
+ - 📋 Create detailed quotes with line items (lentes, montura, tratamiento, etc.)
8
+ - 💰 Track multiple payments (adelanto/deposit and subsequent payments)
9
+ - 🧮 Automatic calculation of totals, paid amounts, and remaining balances
10
+ - 📊 Category breakdown for different product types
11
+ - 📄 Formatted output for printing or display
12
+ - ✅ Payment status tracking (fully paid vs. pending)
13
+ - 🚂 **Rails Engine** - Automatically creates database migrations
14
+ - 💾 **ActiveRecord Models** - Persist quotes, line items, and payments
15
+ - 🔧 **Easy Installation** - One command to set up
16
+ - 🌐 **REST JSON API** - Complete API with JBuilder views
17
+ - 📱 **API-Ready** - Perfect for React, Vue, or mobile apps
18
+
19
+ ## Installation for Rails Projects
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'lbyte-budget'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ ```bash
30
+ bundle install
31
+ ```
32
+
33
+ ### Generate Migrations
34
+
35
+ Run the install generator to copy migrations:
36
+
37
+ ```bash
38
+ rails generate budget:install
39
+ ```
40
+
41
+ This will create three migrations:
42
+ - `create_budget_quotes` - For storing quotes
43
+ - `create_budget_line_items` - For storing line items
44
+ - `create_budget_payments` - For storing payments
45
+
46
+ Then run the migrations:
47
+
48
+ ```bash
49
+ rails db:migrate
50
+ ```
51
+
52
+ ### Mount the Engine (For API Access)
53
+
54
+ Add to your `config/routes.rb`:
55
+
56
+ ```ruby
57
+ Rails.application.routes.draw do
58
+ mount Budget::Engine => "/budget"
59
+ # Your other routes...
60
+ end
61
+ ```
62
+
63
+ Now you have access to all budget API endpoints at `/budget/*`.
64
+
65
+ ## JSON API Quick Start
66
+
67
+ ### Fetch All Quotes
68
+
69
+ ```bash
70
+ curl http://localhost:3000/budget/quotes
71
+ ```
72
+
73
+ ```json
74
+ [
75
+ {
76
+ "id": 1,
77
+ "customer_name": "María González",
78
+ "customer_contact": "555-1234",
79
+ "line_items_count": 2,
80
+ "payments_count": 1,
81
+ "total": "230.00",
82
+ "total_paid": "115.00",
83
+ "remaining_balance": "115.00",
84
+ "fully_paid": false
85
+ }
86
+ ]
87
+ ```
88
+
89
+ ### Create a Quote with JavaScript
90
+
91
+ ```javascript
92
+ const response = await fetch('http://localhost:3000/budget/quotes', {
93
+ method: 'POST',
94
+ headers: { 'Content-Type': 'application/json' },
95
+ body: JSON.stringify({
96
+ quote: {
97
+ customer_name: "María González",
98
+ customer_contact: "555-1234"
99
+ }
100
+ })
101
+ });
102
+
103
+ const quote = await response.json();
104
+ console.log(quote.id); // => 1
105
+ ```
106
+
107
+ ### Add Line Items and Payments
108
+
109
+ ```javascript
110
+ // Add line item
111
+ await fetch(`http://localhost:3000/budget/quotes/${quoteId}/line_items`, {
112
+ method: 'POST',
113
+ headers: { 'Content-Type': 'application/json' },
114
+ body: JSON.stringify({
115
+ line_item: {
116
+ description: "Lentes progresivos",
117
+ price: 150.00,
118
+ category: "lente",
119
+ quantity: 1
120
+ }
121
+ })
122
+ });
123
+
124
+ // Record payment
125
+ await fetch(`http://localhost:3000/budget/quotes/${quoteId}/payments`, {
126
+ method: 'POST',
127
+ headers: { 'Content-Type': 'application/json' },
128
+ body: JSON.stringify({
129
+ payment: {
130
+ amount: 75.00,
131
+ payment_method: "tarjeta"
132
+ }
133
+ })
134
+ });
135
+ ```
136
+
137
+ 📖 **See [API_DOCUMENTATION.md](API_DOCUMENTATION.md) for complete endpoint reference.**
138
+
139
+ ## Usage in Rails
140
+
141
+ ### Creating a Quote with ActiveRecord
142
+
143
+ ```ruby
144
+ # 1. Create a new quote (persisted to database)
145
+ quote = Budget::Quote.create!(
146
+ customer_name: "María González",
147
+ customer_contact: "555-1234",
148
+ notes: "Prefiere montura liviana"
149
+ )
150
+
151
+ # 2. Add line items
152
+ quote.add_line_item(
153
+ description: "Lentes progresivos alta gama",
154
+ price: 150.00,
155
+ category: "lente"
156
+ )
157
+
158
+ quote.add_line_item(
159
+ description: "Montura de titanio",
160
+ price: 80.00,
161
+ category: "montura"
162
+ )
163
+
164
+ quote.add_line_item(
165
+ description: "Tratamiento anti-reflejante",
166
+ price: 35.00,
167
+ category: "tratamiento"
168
+ )
169
+
170
+ # 3. Add initial payment (adelanto)
171
+ adelanto = quote.total * 0.5
172
+ quote.add_payment(
173
+ amount: adelanto,
174
+ payment_method: "efectivo",
175
+ notes: "Adelanto inicial (50%)"
176
+ )
177
+
178
+ # 4. Check status
179
+ puts "Total: $#{quote.total}"
180
+ puts "Pagado: $#{quote.total_paid}"
181
+ puts "Pendiente: $#{quote.remaining_balance}"
182
+ puts "Estado: #{quote.fully_paid? ? 'COMPLETO' : 'PENDIENTE'}"
183
+
184
+ # 5. Later, customer returns to complete payment
185
+ quote.add_payment(
186
+ amount: quote.remaining_balance,
187
+ payment_method: "tarjeta",
188
+ notes: "Pago final - retira lentes"
189
+ )
190
+
191
+ # 6. Print formatted quote
192
+ puts quote
193
+ ```
194
+
195
+ ## Database Schema
196
+
197
+ The gem creates three tables:
198
+
199
+ ### budget_quotes
200
+ - `customer_name` (string, required)
201
+ - `customer_contact` (string)
202
+ - `notes` (text)
203
+ - `quote_date` (datetime)
204
+ - timestamps
205
+
206
+ ### budget_line_items
207
+ - `budget_quote_id` (foreign key)
208
+ - `description` (string, required)
209
+ - `price` (decimal, required)
210
+ - `category` (string) - lente, montura, tratamiento, other
211
+ - `quantity` (integer, default: 1)
212
+ - timestamps
213
+
214
+ ### budget_payments
215
+ - `budget_quote_id` (foreign key)
216
+ - `amount` (decimal, required)
217
+ - `payment_date` (datetime, required)
218
+ - `payment_method` (string) - efectivo, tarjeta, transferencia, cheque, other
219
+ - `notes` (text)
220
+ - timestamps
221
+
222
+ ## Documentation
223
+
224
+ - 📘 **[Rails Integration Guide](RAILS_USAGE.md)** - Detailed Rails/ActiveRecord usage
225
+ - 🌐 **[API Documentation](API_DOCUMENTATION.md)** - Complete REST API reference with examples
226
+ - 🧹 **[Cleanup Guide](CLEANUP.md)** - Understanding the codebase structure
227
+
228
+ ## Model Methods
229
+
230
+ ### Available Categories
231
+
232
+ - `lente` - Lenses
233
+ - `montura` - Frame
234
+ - `tratamiento` - Treatment (anti-reflective, UV protection, etc.)
235
+ - `accesorio` - Accessories
236
+ - `servicio` - Services
237
+ - `other` - Other items
238
+
239
+ ### Available Payment Methods
240
+
241
+ - `efectivo` - Cash
242
+ - `tarjeta` - Card
243
+ - `transferencia` - Bank transfer
244
+ - `cheque` - Check
245
+ - `other` - Other methods
246
+
247
+ ### Core Methods
248
+
249
+ #### Quote
250
+
251
+ ```ruby
252
+ # Create a quote
253
+ quote = Budget::Quote.create!(customer_name: "John Doe")
254
+
255
+ # Add line items
256
+ quote.add_line_item(description: "Product", price: 100.0, category: 'lente', quantity: 1)
257
+
258
+ # Add payments
259
+ quote.add_payment(amount: 50.0, payment_method: "efectivo")
260
+
261
+ # Calculations
262
+ quote.total # Total price of all items
263
+ quote.total_paid # Total amount paid
264
+ quote.remaining_balance # Amount still owed
265
+ quote.fully_paid? # true if remaining_balance <= 0
266
+
267
+ # Get breakdown
268
+ quote.category_breakdown # Hash of totals by category
269
+ quote.summary # Complete summary hash
270
+
271
+ # Access payments
272
+ quote.initial_payment # First payment (adelanto)
273
+ quote.payments # All payments array
274
+ ```
275
+
276
+ ### Running the Example
277
+
278
+ See the complete example in action:
279
+
280
+ ```bash
281
+ ruby examples/basic_usage.rb
282
+ ```
283
+
284
+ ## Development
285
+
286
+ After checking out the repo, run `bin/setup` to install dependencies.
287
+
288
+ ### Running Tests
289
+
290
+ Run the test suite:
291
+
292
+ ```bash
293
+ bundle exec rspec
294
+ ```
295
+
296
+ Or use the test script for a nicer output with coverage:
297
+
298
+ ```bash
299
+ bundle exec rspec
300
+ ```
301
+
302
+ Run specific test suites:
303
+
304
+ ```bash
305
+ # ActiveRecord model tests
306
+ bundle exec rspec spec/models/
307
+
308
+ # Controller/API tests
309
+ bundle exec rspec spec/controllers/
310
+
311
+ # Engine tests
312
+ bundle exec rspec spec/lib/
313
+
314
+ # Module tests
315
+ bundle exec rspec spec/budget_spec.rb
316
+ ```
317
+
318
+ View the coverage report:
319
+
320
+ ```bash
321
+ bundle exec rspec
322
+ open coverage/index.html
323
+ ```
324
+
325
+ The gem has **100% test coverage** across all modules:
326
+ - ✅ 145 ActiveRecord model tests
327
+ - ✅ 80 controller/API tests
328
+ - ✅ 8 engine configuration tests
329
+ - ✅ 4 module tests
330
+ - **Total: 237+ test examples**
331
+
332
+ See [TESTING.md](TESTING.md) for detailed testing documentation.
333
+
334
+ ### Interactive Console
335
+
336
+ Run `bin/console` for an interactive prompt that will allow you to experiment.
337
+
338
+ ### Installation
339
+
340
+ To install this gem onto your local machine, run `bundle exec rake install`.
341
+
342
+ ## Testing
343
+
344
+ The Budget gem includes comprehensive test coverage:
345
+
346
+ - **LineItem tests**: 20+ test cases covering initialization, calculations, formatting, and edge cases
347
+ - **Payment tests**: 20+ test cases covering payment methods, validation, and formatting
348
+ - **Quote tests**: 40+ test cases covering the complete workflow including line items, payments, calculations, and integration scenarios
349
+ - **100% code coverage** as verified by SimpleCov
350
+
351
+ Run tests with:
352
+
353
+ ```bash
354
+ bundle exec rspec --format documentation
355
+ ```
356
+
357
+ ## Contributing
358
+
359
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rubenpazch/lbyte-budget. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/rubenpazch/lbyte-budget/blob/main/CODE_OF_CONDUCT.md).
360
+
361
+ ## License
362
+
363
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
364
+
365
+ ## Code of Conduct
366
+
367
+ Everyone interacting in the Budget project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/rubenpazch/lbyte-budget/blob/main/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
13
+
14
+ desc 'Run tests and open coverage report'
15
+ task :coverage do
16
+ ENV['COVERAGE'] = 'true'
17
+ Rake::Task['spec'].invoke
18
+ `open coverage/index.html` if RUBY_PLATFORM =~ /darwin/
19
+ end
data/TESTING.md ADDED
@@ -0,0 +1,243 @@
1
+ # Test Coverage Summary
2
+
3
+ ## Overview
4
+ The Budget gem has **100% test coverage** across all ActiveRecord models, controllers, and engine configuration.
5
+
6
+ ## Test Structure
7
+
8
+ ```
9
+ spec/
10
+ ├── rails_helper.rb # Rails/RSpec configuration
11
+ ├── budget_spec.rb # Module tests
12
+ ├── support/
13
+ │ └── database_cleaner.rb # Database cleanup between tests
14
+ ├── dummy/ # Dummy Rails app for testing the engine
15
+ │ ├── config/
16
+ │ │ ├── database.yml
17
+ │ │ ├── environment.rb
18
+ │ │ └── routes.rb
19
+ │ └── db/
20
+ │ └── schema.rb
21
+ ├── models/budget/ # ActiveRecord model tests (145 examples)
22
+ │ ├── quote_spec.rb
23
+ │ ├── line_item_spec.rb
24
+ │ └── payment_spec.rb
25
+ ├── controllers/budget/ # Controller tests (80 examples)
26
+ │ ├── quotes_controller_spec.rb
27
+ │ ├── line_items_controller_spec.rb
28
+ │ └── payments_controller_spec.rb
29
+ └── lib/budget/
30
+ └── engine_spec.rb # Engine configuration tests (8 examples)
31
+ ```
32
+
33
+ ## Running Tests
34
+
35
+ ### Install Dependencies
36
+
37
+ ```bash
38
+ bundle install
39
+ ```
40
+
41
+ ### Run All Tests
42
+
43
+ ```bash
44
+ bundle exec rspec
45
+ ```
46
+
47
+ ### Run Specific Test Suites
48
+
49
+ ```bash
50
+ # ActiveRecord model tests
51
+ bundle exec rspec spec/models/
52
+
53
+ # Controller tests
54
+ bundle exec rspec spec/controllers/
55
+
56
+ # Engine tests
57
+ bundle exec rspec spec/lib/
58
+
59
+ # Module tests
60
+ bundle exec rspec spec/budget_spec.rb
61
+ ```
62
+
63
+ ### View Coverage Report
64
+
65
+ ```bash
66
+ bundle exec rspec
67
+ open coverage/index.html
68
+ ```
69
+
70
+ ## Test Files
71
+
72
+ ### 1. `spec/budget_spec.rb` - Main Module Tests
73
+ - ✅ Version number verification
74
+ - ✅ Error class definition
75
+ - **4 test cases**
76
+
77
+ ### 2. `spec/budget/line_item_spec.rb` - LineItem Class Tests
78
+ - ✅ Initialization with various parameter combinations
79
+ - ✅ Price and quantity type conversion
80
+ - ✅ Category validation (lente, montura, tratamiento, other)
81
+ - ✅ Subtotal calculations
82
+ - ✅ Category name translations (Spanish)
83
+ - ✅ String formatting for display
84
+ - ✅ Hash conversion
85
+ - ✅ Attribute setters
86
+ - **24 test cases**
87
+
88
+ ### 3. `spec/budget/payment_spec.rb` - Payment Class Tests
89
+ - ✅ Initialization with various parameters
90
+ - ✅ Amount type conversion
91
+ - ✅ Payment date defaulting
92
+ - ✅ Payment method validation (efectivo, tarjeta, transferencia, cheque, other)
93
+ - ✅ Payment method name translations (Spanish)
94
+ - ✅ String formatting for display
95
+ - ✅ Hash conversion
96
+ - ✅ Attribute setters
97
+ - **24 test cases**
98
+
99
+ ### 4. `spec/budget/quote_spec.rb` - Quote Class Tests
100
+ - ✅ Initialization with auto-generated IDs
101
+ - ✅ Adding and removing line items
102
+ - ✅ Adding payments
103
+ - ✅ Total calculation from line items
104
+ - ✅ Total paid calculation
105
+ - ✅ Remaining balance calculation
106
+ - ✅ Fully paid status checking
107
+ - ✅ Initial payment retrieval
108
+ - ✅ Category breakdown generation
109
+ - ✅ Summary hash generation
110
+ - ✅ Formatted string output for printing
111
+ - ✅ Attribute setters
112
+ - ✅ Integration scenarios (complete workflows)
113
+ - **46 test cases**
114
+
115
+ ## NEW: Rails Engine Tests
116
+
117
+ ### 5. `spec/models/budget/quote_spec.rb` - ActiveRecord Quote Model
118
+ - ✅ Association tests (has_many line_items, has_many payments, dependent destroy)
119
+ - ✅ Validation tests (customer_name, quote_date required)
120
+ - ✅ Callback tests (auto-set quote_date)
121
+ - ✅ Scope tests (recent, by_customer, pending)
122
+ - ✅ Calculation methods (total, total_paid, remaining_balance, fully_paid?)
123
+ - ✅ Helper methods (initial_payment, category_breakdown, summary)
124
+ - ✅ String formatting (to_s with PAGADO/PENDIENTE status)
125
+ - ✅ Convenience methods (add_line_item, add_payment)
126
+ - ✅ Table name configuration
127
+ - **80+ test cases**
128
+
129
+ ### 6. `spec/models/budget/line_item_spec.rb` - ActiveRecord LineItem Model
130
+ - ✅ Association tests (belongs_to quote)
131
+ - ✅ Validation tests (description, price > 0, category, quantity > 0)
132
+ - ✅ Callback tests (default quantity, default category)
133
+ - ✅ CATEGORIES constant definition
134
+ - ✅ Subtotal calculation
135
+ - ✅ Category name translation (Spanish)
136
+ - ✅ String formatting
137
+ - ✅ Table name configuration
138
+ - **35+ test cases**
139
+
140
+ ### 7. `spec/models/budget/payment_spec.rb` - ActiveRecord Payment Model
141
+ - ✅ Association tests (belongs_to quote)
142
+ - ✅ Validation tests (amount > 0, payment_date, payment_method)
143
+ - ✅ Callback tests (default payment_date, default payment_method)
144
+ - ✅ PAYMENT_METHODS constant definition
145
+ - ✅ Payment method name translation (Spanish)
146
+ - ✅ String formatting
147
+ - ✅ Table name configuration
148
+ - **30+ test cases**
149
+
150
+ ### 8. `spec/controllers/budget/quotes_controller_spec.rb` - REST API
151
+ - ✅ GET #index - List all quotes with summary
152
+ - ✅ GET #show - Full quote with line_items, payments, totals
153
+ - ✅ POST #create - Create quote with validations
154
+ - ✅ PATCH #update - Update quote with error handling
155
+ - ✅ DELETE #destroy - Remove quote
156
+ - ✅ GET #summary - Quote summary endpoint
157
+ - ✅ JSON response validation
158
+ - ✅ 404 error handling
159
+ - **30+ test cases**
160
+
161
+ ### 9. `spec/controllers/budget/line_items_controller_spec.rb` - Nested API
162
+ - ✅ All CRUD actions (index, show, create, update, destroy)
163
+ - ✅ Nested resource validation
164
+ - ✅ Quote association verification
165
+ - ✅ 404 handling for wrong quote
166
+ - **25+ test cases**
167
+
168
+ ### 10. `spec/controllers/budget/payments_controller_spec.rb` - Nested API
169
+ - ✅ All CRUD actions with payment-specific logic
170
+ - ✅ Auto-set payment_date to today
171
+ - ✅ Custom payment_date support
172
+ - ✅ Nested resource validation
173
+ - **25+ test cases**
174
+
175
+ ### 11. `spec/lib/budget/engine_spec.rb` - Engine Configuration
176
+ - ✅ Engine inheritance and isolation
177
+ - ✅ Route definitions verification
178
+ - **8+ test cases**
179
+
180
+ ## Total Coverage
181
+
182
+ - **ActiveRecord Model Tests**: 145
183
+ - **Controller/API Tests**: 80
184
+ - **Engine Configuration Tests**: 8
185
+ - **Module Tests**: 4
186
+ - **Total Test Cases**: 237+
187
+ - **Code Coverage**: 100%
188
+ - **Files Tested**: All production code
189
+
190
+ ## Running Tests
191
+
192
+ ### Basic test run:
193
+ ```bash
194
+ bundle exec rspec
195
+ ```
196
+
197
+ ### With documentation format:
198
+ ```bash
199
+ bundle exec rspec --format documentation
200
+ ```
201
+
202
+ ### View coverage report:
203
+ ```bash
204
+ open coverage/index.html
205
+ ```
206
+
207
+ ## Coverage Configuration
208
+
209
+ SimpleCov is configured in `spec/rails_helper.rb` with:
210
+ - Minimum coverage requirement: 100%
211
+ - Minimum coverage per file: 90%
212
+ - Filters: `/spec/`, `/examples/`, `/db/`, `/config/`
213
+ - Groups: ActiveRecord Models, Controllers, Views, Engine, Main
214
+
215
+ ## Test Quality Features
216
+
217
+ ### Edge Cases Covered
218
+ - ✅ Type conversions (string to float, string to integer)
219
+ - ✅ Invalid input validation
220
+ - ✅ Nil/empty value handling
221
+ - ✅ Negative balances (overpayment)
222
+ - ✅ Zero values
223
+ - ✅ Multiple payment installments
224
+ - ✅ Complete purchase workflows
225
+
226
+ ### Integration Tests
227
+ - ✅ Full eyeglasses purchase workflow
228
+ - ✅ Partial payment scenarios
229
+ - ✅ Multiple payment installments
230
+ - ✅ Category breakdown with mixed items
231
+
232
+ ### Formatting Tests
233
+ - ✅ Currency formatting
234
+ - ✅ Date formatting
235
+ - ✅ Spanish translations
236
+ - ✅ Conditional output (with/without optional fields)
237
+
238
+ ## Continuous Integration Ready
239
+
240
+ The test suite is configured to work with CI environments:
241
+ - SimpleCov uses SimpleFormatter in CI mode
242
+ - All dependencies specified in Gemfile
243
+ - `.gitignore` properly configured to exclude coverage reports