RubyMoney/money

MGA and MRU subunits

matid opened this issue · 0 comments

Similar to HUF, MGA and MRU don’t have in line with ISO 4217 due to a non-standard subunit_to_unit of 5.

According to Wikipedia MGA is notionally subdivided into 5 units.
However, ISO treats MGA as a 2 decimal place currency and considers its subunit to be 0.01, not 0.2.

Money on the other hand returns 1 for its exponent:

> Money::Currency.find('MGA').exponent
=> 1

The correct fix here depends on what the desired behavior of the cents method is.

The current behavior returns the count of subunits in the currency, so for MGA it returns 5:

> Money.from_amount(1, 'MGA').cents
=> 5

If the intent is to follow the ISO 4217 and return the currency without decimal places, the correct behavior would be this:

> Money.from_amount(1, 'MGA').cents
=> 100

This behavior is useful when interacting with banks and payment processors that often expect amounts to be provided in the currency’s smallest unit (not necessarily multiple of smallest coin). Here’s relevant documentation from Stripe: https://docs.stripe.com/currencies#zero-decimal

For example, to charge 10 USD Stripe expects amount of 1000, but to charge 500 JPY, amount of 500 since JPY is a zero-decimal place currency according to both Stripe and ISO 4217.

In Money, this can be done using the cents method:

Money.from_amount(100, 'USD').cents # 1000
Money.from_amount(500, 'JPY').cents # 500

MGA is an especially interesting edge case because Stripe doesn’t follow ISO here either. They consider it a zero-decimal currency and expect you to pass in 1 MGY as 1 instead of 100.

In my mind, it’d be better to follow ISO here and consider MGA as having 2 decimal places. Alternatively, subunit_to_unit should be separated from decimal_places and allow for MGA to be subdivided into 5 sub-units but have 2 decimal places.