Skip to content

PTHMINT-91: Implement Decimal precision for monetary calculations#41

Merged
danielcivit merged 3 commits intomasterfrom
PTHMINT-91
Feb 5, 2026
Merged

PTHMINT-91: Implement Decimal precision for monetary calculations#41
danielcivit merged 3 commits intomasterfrom
PTHMINT-91

Conversation

@zulquer
Copy link
Collaborator

@zulquer zulquer commented Dec 3, 2025

Description

  • Add validators to convert values to Decimal for precise calculations
  • Extract DecimalEncoder to separate util/json_encoder.py module
  • Ensure all monetary values use Decimal to avoid floating-point errors
  • Update order_manager to use DecimalEncoder for JSON serialization
  • Add CartItem.update_forward_refs() to resolve Weight forward reference
  • Fix checkout_data.py to multiply Decimal by int instead of float
  • Update all tests to assert Decimal values instead of float values

Copilot Description

This pull request introduces a comprehensive migration of monetary values in the codebase from floating-point types to the more precise Decimal type, improving accuracy in all financial calculations and API interactions. It also ensures correct JSON serialization of Decimal values by introducing a custom DecimalEncoder. The changes affect cart items, costs, order management, and utility functions, providing stricter type handling and validation for monetary fields.

Precision improvements for monetary values:

  • Changed unit_price in CartItem and amount in Costs from float to Decimal, and introduced Pydantic validators to ensure all assignments and inputs are converted to Decimal for accuracy. Methods that add or manipulate these values have been updated to accept multiple types and convert them as needed. (src/multisafepay/api/shared/cart/cart_item.py, src/multisafepay/api/shared/costs.py) [1] [2] [3] [4] [5] [6]

  • Updated tax rate and percentage handling in CartItem to use Decimal for all arithmetic, with improved validation and conversion logic. (src/multisafepay/api/shared/cart/cart_item.py) [1] [2] [3] [4] [5]

JSON serialization and API compatibility:

  • Introduced a new DecimalEncoder class for JSON serialization, converting Decimal values to float when sending data to APIs. Updated all relevant API request methods in OrderManager to use this encoder. (src/multisafepay/util/json_encoder.py, src/multisafepay/api/paths/orders/order_manager.py, src/multisafepay/util/__init__.py) [1] [2] [3] [4] [5] [6] [7]

Utility and support improvements:

  • Added a recursive utility function to convert nested Decimal values to float for JSON serialization in utility modules. (src/multisafepay/util/total_amount.py)

Minor corrections and consistency:

  • Standardized the sign inversion in refund calculations for unit prices to use integer multiplication instead of float. (src/multisafepay/api/paths/orders/order_id/refund/request/components/checkout_data.py)
  • Updated typing hints and imports for better maintainability and type safety throughout the affected modules. [1] [2]

These changes ensure financial calculations throughout the SDK are reliable and consistent, eliminating floating-point errors and improving compatibility with APIs expecting float values in JSON.- Replace float with Decimal in cart_item, costs, unit_price, total_amount

@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.62%. Comparing base (6b31b1a) to head (e032bec).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #41      +/-   ##
==========================================
- Coverage   90.69%   90.62%   -0.07%     
==========================================
  Files         143      144       +1     
  Lines        2471     2539      +68     
==========================================
+ Hits         2241     2301      +60     
- Misses        230      238       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- **Refactor**: Introduced `DecimalAmount` Value Object to handle decimal precision for monetary values, replacing inline Pydantic validators in `CartItem` and `Costs`.
- **Fix**: Resolved an `AttributeError` in `create_refund_request` by accessing `.quantity` directly instead of `.get_quantity()`.
- **DX**: Added support for `API_KEY` and `TEST_API_KEY` environment variables.
- **DX**: Improved code quality by adding missing docstrings and return types across various files.
- **Tests**: Updated unit and integration tests to reflect the architectural changes.
@danielcivit danielcivit requested a review from Copilot February 5, 2026 15:47
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request implements comprehensive Decimal precision for all monetary calculations throughout the codebase, replacing floating-point types to prevent rounding errors in financial operations. The changes introduce a new DecimalAmount value object, update cart items and costs to use Decimal types, and add a custom JSON encoder to serialize Decimal values for API compatibility.

Changes:

  • Replaced UnitPrice value object with DecimalAmount for monetary precision
  • Updated CartItem and Costs models to use Decimal for all monetary values
  • Added DecimalEncoder for JSON serialization of Decimal values in API requests
  • Enhanced total amount calculation utilities with configurable rounding strategies
  • Comprehensive test coverage for new Decimal-based calculations and rounding behaviors

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/multisafepay/unit/value_object/test_unit_price.py Removed old float-based unit price tests
tests/multisafepay/unit/value_object/test_decimal_amount.py Added new tests for Decimal-based amount handling
tests/multisafepay/unit/util/test_unit_total_amount.py Updated assertions to expect Decimal values and added rounding strategy tests
tests/multisafepay/unit/api/shared/test_unit_costs.py Updated cost assertions to verify Decimal precision
tests/multisafepay/unit/api/shared/cart/test_unit_cart_item.py Updated cart item unit price assertions for Decimal
tests/multisafepay/unit/api/path/orders/request/test_unit_order_request.py Added tests for amount validation with rounding strategies
tests/multisafepay/integration/api/shared/cart/test_integration_cart_item.py Updated integration tests for Decimal unit prices
tests/multisafepay/integration/amounts/*.py Added comprehensive rounding and tax calculation integration tests
tests/multisafepay/e2e/conftest.py Added pytest configuration to skip E2E tests without API_KEY
src/multisafepay/value_object/unit_price.py Removed float-based UnitPrice class
src/multisafepay/value_object/decimal_amount.py Added new DecimalAmount value object with validator
src/multisafepay/value_object/init.py Updated exports to use DecimalAmount instead of UnitPrice
src/multisafepay/util/total_amount.py Enhanced with Decimal arithmetic and rounding strategy support
src/multisafepay/util/json_encoder.py Added DecimalEncoder for API serialization
src/multisafepay/util/init.py Exported DecimalEncoder utility
src/multisafepay/api/shared/costs.py Updated to use Decimal for amount field
src/multisafepay/api/shared/cart/cart_item.py Updated to use Decimal for unit_price and tax calculations
src/multisafepay/api/paths/orders/request/order_request.py Added rounding parameters to validate_amount
src/multisafepay/api/paths/orders/order_manager.py Updated to use DecimalEncoder for JSON serialization
src/multisafepay/api/paths/orders/order_id/refund/request/components/checkout_data.py Fixed to multiply Decimal by int instead of float

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@danielcivit danielcivit requested a review from Copilot February 5, 2026 16:56
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@danielcivit danielcivit merged commit 8cf684c into master Feb 5, 2026
6 checks passed
@danielcivit danielcivit deleted the PTHMINT-91 branch February 5, 2026 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants