Class: MoreMoney::Price

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/more_money/price.rb,
lib/more_money/price.rb

Overview

class methods for price

Constant Summary collapse

TAXES =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cents, currency = Money.default_currency, tax = Price.default_tax, tax_inclusive = Price.default_inclusive) ⇒ Price

Creates a new price object.

Price.new(100)


79
80
81
82
83
84
85
86
87
# File 'lib/more_money/price.rb', line 79

def initialize(cents, currency = Money.default_currency, tax = Price.default_tax, tax_inclusive = Price.default_inclusive)
  @money = Money.new(cents, currency)
  self.class.check_tax(tax)
  @tax = TAXES[tax]
  @tax_code = tax
  @tax_amounts = []
  @tax_inclusive = tax_inclusive
  @tax_inclusive ? discount_tax : apply_tax
end

Instance Attribute Details

#moneyObject (readonly)

Returns the value of attribute money.



73
74
75
# File 'lib/more_money/price.rb', line 73

def money
  @money
end

#taxObject (readonly)

Returns the value of attribute tax.



73
74
75
# File 'lib/more_money/price.rb', line 73

def tax
  @tax
end

#tax_amountsObject (readonly)

Returns the value of attribute tax_amounts.



73
74
75
# File 'lib/more_money/price.rb', line 73

def tax_amounts
  @tax_amounts
end

#tax_codeObject (readonly)

Returns the value of attribute tax_code.



73
74
75
# File 'lib/more_money/price.rb', line 73

def tax_code
  @tax_code
end

#tax_inclusiveObject (readonly)

Returns the value of attribute tax_inclusive.



73
74
75
# File 'lib/more_money/price.rb', line 73

def tax_inclusive
  @tax_inclusive
end

Class Method Details

.add_tax(tax) ⇒ Object

adds a tax to the set of available ones.

MoreMoney::Price.add_tax(tax_obj)

a tax object is a generic ruby object that responds to the methods

* apply -> lamba that applies the tax to a net value
* discount -> lambda that drops the tax from the gross value
* code -> short code for the tax
* formatted code -> code for display purpouse


56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/more_money/price.rb', line 56

def self.add_tax(tax)
  case tax
    when Hash
      TAXES[tax[:code]] = tax[:taxes].map { |t| TAXES[t] }
  else
      mandatory_methods = [:apply, :discount, :code, :formatted_code]
      mandatory_methods.each do |m|
        raise TaxMissingMethod, "#{m} method is not defined by #{tax.inspect}" unless tax.respond_to? m
      end
    TAXES[tax.code] = tax
  end
end

.check_tax(tax_code) ⇒ Object

Raises:



69
70
71
# File 'lib/more_money/price.rb', line 69

def self.check_tax(tax_code)
  raise PriceInvalidTax, "#{tax_code} is not defined as a tax" unless TAXES.key?(tax_code)
end

.default_inclusiveObject

show if by default prices are tax inclusive/exclusive



35
36
37
# File 'lib/more_money/price.rb', line 35

def self.default_inclusive
  @default_inclusive
end

.default_inclusive=(default_inclusive) ⇒ Object

set if by default prices are tax inclusive

Raises:

  • (ArgumentError)


40
41
42
43
# File 'lib/more_money/price.rb', line 40

def self.default_inclusive=(default_inclusive)
  raise ArgumentError, "default inclusive can be only true or false" unless [TrueClass, FalseClass].member?(default_inclusive.class)
  @default_inclusive = default_inclusive
end

.default_taxObject

the current default tax



22
23
24
# File 'lib/more_money/price.rb', line 22

def self.default_tax
  @default_tax
end

.default_tax=(tax_code) ⇒ Object

set the default tax

MoreMoney::Money.default_tax_rate = 'GBP'


30
31
32
# File 'lib/more_money/price.rb', line 30

def self.default_tax=(tax_code)
  @default_tax = tax_code
end

.partial_sum(*args) ⇒ Object

returns an array with the sum of the given arguments grouped by tax code it can only sum



220
221
222
223
224
225
# File 'lib/more_money/price.rb', line 220

def self.partial_sum(*args)
  return nil if (to_sum = args.flatten.compact).size == 0
  raise PricesWithDifferentInclusiveClause unless to_sum.collect { |p| p.tax_inclusive }.uniq.size == 1
  same_tax_groups = to_sum.collect { |p| p.tax }.uniq.map { |tax| to_sum.select { |p| p.tax == tax } }
  same_tax_group_sums = same_tax_groups.map { |g| g.inject(Price.new(0, g.first.currency, g.first.tax_code, g.first.tax_inclusive)) { |tot, p| tot + p } }
end

.sum(*args) ⇒ Object



227
228
229
230
231
232
# File 'lib/more_money/price.rb', line 227

def self.sum(*args)
  return nil if args.flatten.size == 0
  type = args.last.is_a?(Symbol) ? args.pop : :gross
  partial = [true, false].map { |t| partial_sum(args.flatten.select { |a| a.tax_inclusive == t }) }.flatten.compact
  partial.inject(Money.new(0, partial.first.currency)) { |tot, p| tot + p.send(type == :gross ? :gross : :net) }
end

Instance Method Details

#*(fixnum) ⇒ Object

multiply money by fixnum



144
145
146
# File 'lib/more_money/price.rb', line 144

def *(fixnum)
  Price.new(money.cents * fixnum, currency, tax_code, tax_inclusive)
end

#-@Object



139
140
141
# File 'lib/more_money/price.rb', line 139

def -@
  self.class.new(-cents, currency, tax_code, tax_inclusive)
end

#/(fixnum) ⇒ Object

divide money by fixnum



149
150
151
# File 'lib/more_money/price.rb', line 149

def /(fixnum)
  Price.new(money.cents / fixnum, currency, tax_code, tax_inclusive)
end

#<=>(other_price) ⇒ Object



118
119
120
121
# File 'lib/more_money/price.rb', line 118

def <=>(other_price)
  raise_different_tax(other_price)
  net <=> other_price.net
end

#centsObject



103
104
105
# File 'lib/more_money/price.rb', line 103

def cents
  money.cents
end

#currencyObject

currency



108
109
110
# File 'lib/more_money/price.rb', line 108

def currency
  money.currency
end

#eql?(other_price) ⇒ Boolean

Do two money objects equal? Only works if both objects are of the same currency

Returns:

  • (Boolean)


113
114
115
116
# File 'lib/more_money/price.rb', line 113

def eql?(other_price)
  raise_different_tax(other_price)
  net == other_price.net
end

#format(*rules) ⇒ Object

Format the price according rules

Currently supported are :with_tax_inclusion, :with_tax All the extra rules specified will be passed to the money object



168
169
170
171
172
173
174
# File 'lib/more_money/price.rb', line 168

def format(*rules)
  rules = rules.flatten
  price_string = []
  price_string << (tax.formatted_code) if rules.delete(:with_tax)
  price_string << (tax_inclusive ? 'inc.' : 'exc.') if rules.delete(:with_tax_inclusion)
  ([money.format(rules)] + price_string).join(' ')
end

#grossObject

returns a Money object with the gross amount



99
100
101
# File 'lib/more_money/price.rb', line 99

def gross
  tax_inclusive ? money : tax_amounts.inject(net) { |sum, a| sum + a[1] }
end

#netObject

returns a Money object with the net amount



94
95
96
# File 'lib/more_money/price.rb', line 94

def net
  tax_inclusive ? tax_amounts.inject(gross) { |sum, a| sum - a[1] } : money
end

#no_cost?Boolean

Test if the price is zero

Returns:

  • (Boolean)


159
160
161
# File 'lib/more_money/price.rb', line 159

def no_cost?
  return (money.zero? || money.cents.nil?)
end

#tax_inclusive?Boolean

Returns:

  • (Boolean)


89
90
91
# File 'lib/more_money/price.rb', line 89

def tax_inclusive?
  tax_inclusive
end

#to_priceObject

Conversation to self



182
183
184
# File 'lib/more_money/price.rb', line 182

def to_price
  self
end

#to_sObject

Money.new(100, ‘USD’).to_s => “1.00”



177
178
179
# File 'lib/more_money/price.rb', line 177

def to_s
  cents.nil? ? '' : sprintf("%.2f", money.cents.to_f / 100  )
end

#zero?Boolean

Test if the price is zero

Returns:

  • (Boolean)


154
155
156
# File 'lib/more_money/price.rb', line 154

def zero?
  return money.zero?
end