Project

splittable

0.0
No release in over 3 years
Splittable solves the common problem of dividing monetary values where the sum of rounded installments doesn't equal the original total. It ensures precise financial calculations by truncating values to the specified precision and attributing any difference to the first installment. Perfect for e-commerce payments, invoice distribution, and subscription billing.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Runtime

 Project Readme

Splittable

Gem Version Ruby Ruby Version License

🎯 Problem Solved

When dividing monetary values, you often get results with many decimal places that need to be rounded to cents (2 decimal places). This creates a common problem: the sum of rounded installments doesn't equal the original total.

Example of the problem:

# Dividing $100.00 into 3 equal parts
100.00 / 3 = 33.333333...

# If we round each installment to 2 decimal places:
[33.33, 33.33, 33.33].sum = 99.99  # ❌ Missing $0.01!

Splittable solves this by:

  • Truncating values to the specified precision
  • Adding the difference to the first installment
  • Ensuring the sum always equals the original value

🚀 Installation

Add this line to your application's Gemfile:

gem 'splittable'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install splittable

📖 Usage

Division Method

Split a total value into equal installments:

# Basic usage - split $0.12 into 3 equal parts
Splittable.division(value: 0.12, quantity: 3)
# => [0.04, 0.04, 0.04]  # Sum: 0.12

# Custom precision - 3 decimal places
Splittable.division(value: 10, quantity: 3, precision: 3)
# => [3.334, 3.333, 3.333]  # Sum: 10.000

Normalize Method

Normalize existing installments to match a total value:

# Normalize installments to sum exactly $100.00
Splittable.normalize(value: 100.00, installments: [33.33, 33.33, 33.33])
# => [33.34, 33.33, 33.33]  # Sum: 100.00

# With custom precision
Splittable.normalize(value: 100, installments: [33.333, 33.333, 33.333], precision: 3)
# => [33.334, 33.333, 33.333]  # Sum: 100.000

💡 Real-World Examples

E-commerce Payment Splitting

# Split a $99.99 order into 3 monthly payments
payments = Splittable.division(value: 99.99, quantity: 3)
# => [33.33, 33.33, 33.33]
# Total: $99.99 ✅

Invoice Distribution

# Distribute a $1,000.00 invoice across departments
departments = ['Sales', 'Marketing', 'Support']
amounts = [400.00, 350.00, 250.00]

normalized = Splittable.normalize(value: 1000.01, installments: amounts)
# => [400.01, 350.00, 250.00]
# Total: $1,000.01 ✅

Subscription Billing

# Annual subscription split into monthly payments
monthly_payment = Splittable.division(value: 120.01, quantity: 12)
# => [10.01, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00]
# Total: $120.01 ✅

⚠️ Error Handling

# Invalid quantity (must be positive)
Splittable.division(value: 100, quantity: 0)
# => ArgumentError: quantity should be positive

# Empty installments array
Splittable.normalize(value: 100, installments: [])
# => ArgumentError: installments should be a non-empty array

# Nil installments
Splittable.normalize(value: 100, installments: nil)
# => ArgumentError: installments should be a non-empty array

🛠️ Development

Setup

git clone https://github.com/m4rcelotoledo/splittable.git
cd splittable
bundle install

Running Tests

# Run all tests
bundle exec rspec

# Run with coverage
bundle exec rspec --format documentation

# Run specific test file
bundle exec rspec spec/splittable_spec.rb

Code Quality

# Run RuboCop
bundle exec rubocop

# Auto-fix RuboCop issues
bundle exec rubocop -a

Interactive Console

bundle exec bin/console

Project Structure

lib/
├── splittable.rb           # Main module with public methods
├── splittable/
│   ├── version.rb         # Gem version
│   ├── division.rb        # Division logic
│   └── normalize.rb       # Normalization logic
spec/
├── spec_helper.rb         # Test configuration
└── splittable_spec.rb     # Test cases

📦 Release Process

Automatic Release

  1. Update version in lib/splittable/version.rb
  2. Update CHANGELOG.md with relevant changes
  3. Merge to master branch
  4. GitHub Actions will automatically publish to RubyGems

Manual Release

# Update version and changelog first
bundle exec rake release

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Bug reports and pull requests are welcome on GitHub at https://github.com/m4rcelotoledo/splittable/blob/master/CONTRIBUTING.md.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

📚 Code of Conduct

This project follows the Contributor Covenant code of conduct.