Skip to content

Class WhittakerTech::Midas::Coin::Allocation

Inherits: Object

Allocation represents a per-unit interpretation of a Coin.

Conceptual model

Coin -> canonical, payable money (what exists) Allocation -> "this Coin, spread across N units, using policy X"

An Allocation answers two questions:

  1. What does one unit cost?#value
  2. What does a given quantity cost?#price

Immutability

Allocation is: * immutable@coin, @divisor, and @rounding_policy are frozen on construction and never mutated. * not persisted — Allocation is a pure value object. * minor-unit safe — it never stores sub-minor-unit amounts; rounding is applied before returning a Coin.

See also: Coin#allocate

  • @since 0.1.0

@example Per-unit price from a bulk price

bulk = Coin.value(10_000, 'USD')  # $100.00 for a pack of 6
alloc = bulk.allocate(per: 6, rounding_policy: :ceil)
alloc.value          # => Coin($16.67)
alloc.price(qty: 2)  # => Coin($33.34)

Attributes

coin [R]

  • @return [Coin] the total monetary amount this Allocation is based on
  • @since 0.1.0

divisor [R]

  • @return [Numeric] the number of units the coin covers (the divisor)
  • @since 0.1.0

rounding_policy [R]

  • @return [Symbol] the rounding policy applied to per-unit calculations
  • @since 0.1.0

Public Instance Methods

initialize(coin:, divisor:, rounding_policy:)

  • @param coin [Coin] the total monetary value
  • @param divisor [Numeric] the number of units; must be positive
  • @param rounding_policy [Symbol] one of WhittakerTech::Midas::ROUNDING_POLICIES
  • @raise [TypeError] if coin is not a Coin
  • @raise [TypeError] if divisor is not a positive Numeric
  • @raise [ArgumentError] if rounding_policy is not a recognised policy key
  • @return [Allocation] a new instance of Allocation
  • @since 0.1.0

inspect()

Human-readable representation for logs and console output. - @return [String] - @since 0.1.0

price(qty: = 1)

Returns the total price for a given quantity of units.

Uses (total_minor * qty) / divisor rounded via #rounding_policy. Equivalent to qty units at the per-unit rate, but computed from the original total to minimise accumulated rounding error. - @param qty [Numeric] the number of units; must be >= 0 - @raise [ArgumentError] if qty is negative or not Numeric - @return [Coin] - @since 0.1.0

@example

alloc = Coin.value(10_000, 'USD').allocate(per: 6)
alloc.price(qty: 3)   # => Coin($50.00)  (10000 * 3 / 6 = 5000 cents)

value()

Returns the per-unit Coin after dividing by #divisor and applying the #rounding_policy.

The result is still a Coin — payable money representing a single unit. - @return [Coin] - @since 0.1.0