shopify-money 0.16.0 → 1.0.2.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -2
- data/UPGRADING.md +59 -0
- data/config/currency_historic.yml +14 -0
- data/config/currency_iso.yml +22 -4
- data/lib/money/allocator.rb +3 -1
- data/lib/money/config.rb +25 -0
- data/lib/money/core_extensions.rb +1 -1
- data/lib/money/helpers.rb +8 -4
- data/lib/money/money.rb +48 -23
- data/lib/money/parser/accounting.rb +11 -0
- data/lib/money/parser/fuzzy.rb +174 -0
- data/lib/money/parser/locale_aware.rb +52 -0
- data/lib/money/parser/simple.rb +30 -0
- data/lib/money/rails/job_argument_serializer.rb +22 -0
- data/lib/money/railtie.rb +19 -0
- data/lib/money/version.rb +1 -1
- data/lib/money.rb +7 -2
- data/lib/money_column/active_record_hooks.rb +12 -7
- data/spec/config_spec.rb +48 -0
- data/spec/helpers_spec.rb +11 -5
- data/spec/money_column_spec.rb +54 -33
- data/spec/money_spec.rb +129 -62
- data/spec/{accounting_money_parser_spec.rb → parser/accounting_spec.rb} +9 -15
- data/spec/{money_parser_spec.rb → parser/fuzzy_spec.rb} +25 -13
- data/spec/parser/locale_aware_spec.rb +208 -0
- data/spec/parser/simple_spec.rb +62 -0
- data/spec/rails/job_argument_serializer_spec.rb +20 -0
- data/spec/rails_spec_helper.rb +11 -0
- data/spec/spec_helper.rb +15 -0
- metadata +27 -11
- data/lib/money/accounting_money_parser.rb +0 -8
- data/lib/money/money_parser.rb +0 -156
data/lib/money/money_parser.rb
DELETED
@@ -1,156 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Parse an amount from a string
|
4
|
-
class MoneyParser
|
5
|
-
class MoneyFormatError < ArgumentError; end
|
6
|
-
|
7
|
-
MARKS = %w[. , · ’ ˙ '] + [' ']
|
8
|
-
|
9
|
-
ESCAPED_MARKS = Regexp.escape(MARKS.join)
|
10
|
-
ESCAPED_NON_SPACE_MARKS = Regexp.escape((MARKS - [' ']).join)
|
11
|
-
ESCAPED_NON_DOT_MARKS = Regexp.escape((MARKS - ['.']).join)
|
12
|
-
ESCAPED_NON_COMMA_MARKS = Regexp.escape((MARKS - [',']).join)
|
13
|
-
|
14
|
-
NUMERIC_REGEX = /(
|
15
|
-
[\+\-]?
|
16
|
-
[\d#{ESCAPED_NON_SPACE_MARKS}][\d#{ESCAPED_MARKS}]*
|
17
|
-
)/ix
|
18
|
-
|
19
|
-
# 1,234,567.89
|
20
|
-
DOT_DECIMAL_REGEX = /\A
|
21
|
-
[\+\-]?
|
22
|
-
(?:
|
23
|
-
(?:\d+)
|
24
|
-
(?:[#{ESCAPED_NON_DOT_MARKS}]\d{3})+
|
25
|
-
(?:\.\d{2,})?
|
26
|
-
)
|
27
|
-
\z/ix
|
28
|
-
|
29
|
-
# 1.234.567,89
|
30
|
-
COMMA_DECIMAL_REGEX = /\A
|
31
|
-
[\+\-]?
|
32
|
-
(?:
|
33
|
-
(?:\d+)
|
34
|
-
(?:[#{ESCAPED_NON_COMMA_MARKS}]\d{3})+
|
35
|
-
(?:\,\d{2,})?
|
36
|
-
)
|
37
|
-
\z/ix
|
38
|
-
|
39
|
-
# 12,34,567.89
|
40
|
-
INDIAN_NUMERIC_REGEX = /\A
|
41
|
-
[\+\-]?
|
42
|
-
(?:
|
43
|
-
(?:\d+)
|
44
|
-
(?:\,\d{2})+
|
45
|
-
(?:\,\d{3})
|
46
|
-
(?:\.\d{2})?
|
47
|
-
)
|
48
|
-
\z/ix
|
49
|
-
|
50
|
-
# 1,1123,4567.89
|
51
|
-
CHINESE_NUMERIC_REGEX = /\A
|
52
|
-
[\+\-]?
|
53
|
-
(?:
|
54
|
-
(?:\d+)
|
55
|
-
(?:\,\d{4})+
|
56
|
-
(?:\.\d{2})?
|
57
|
-
)
|
58
|
-
\z/ix
|
59
|
-
|
60
|
-
def self.parse(input, currency = nil, **options)
|
61
|
-
new.parse(input, currency, **options)
|
62
|
-
end
|
63
|
-
|
64
|
-
def parse(input, currency = nil, strict: false)
|
65
|
-
currency = Money::Helpers.value_to_currency(currency)
|
66
|
-
amount = extract_amount_from_string(input, currency, strict)
|
67
|
-
Money.new(amount, currency)
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def extract_amount_from_string(input, currency, strict)
|
73
|
-
unless input.is_a?(String)
|
74
|
-
return input
|
75
|
-
end
|
76
|
-
|
77
|
-
if input.strip.empty?
|
78
|
-
return '0'
|
79
|
-
end
|
80
|
-
|
81
|
-
number = input.scan(NUMERIC_REGEX).flatten.first
|
82
|
-
number = number.to_s.strip
|
83
|
-
|
84
|
-
if number.empty?
|
85
|
-
raise MoneyFormatError, "invalid money string: #{input}" if strict
|
86
|
-
Money.deprecate("invalid money strings will raise in the next major release \"#{input}\"")
|
87
|
-
return '0'
|
88
|
-
end
|
89
|
-
|
90
|
-
marks = number.scan(/[#{ESCAPED_MARKS}]/).flatten
|
91
|
-
if marks.empty?
|
92
|
-
return number
|
93
|
-
end
|
94
|
-
|
95
|
-
if marks.size == 1
|
96
|
-
return normalize_number(number, marks, currency)
|
97
|
-
end
|
98
|
-
|
99
|
-
# remove end of string mark
|
100
|
-
number.sub!(/[#{ESCAPED_MARKS}]\z/, '')
|
101
|
-
|
102
|
-
if amount = number[DOT_DECIMAL_REGEX] || number[INDIAN_NUMERIC_REGEX] || number[CHINESE_NUMERIC_REGEX]
|
103
|
-
return amount.tr(ESCAPED_NON_DOT_MARKS, '')
|
104
|
-
end
|
105
|
-
|
106
|
-
if amount = number[COMMA_DECIMAL_REGEX]
|
107
|
-
return amount.tr(ESCAPED_NON_COMMA_MARKS, '').sub(',', '.')
|
108
|
-
end
|
109
|
-
|
110
|
-
raise MoneyFormatError, "invalid money string: #{input}" if strict
|
111
|
-
Money.deprecate("invalid money strings will raise in the next major release \"#{input}\"")
|
112
|
-
|
113
|
-
normalize_number(number, marks, currency)
|
114
|
-
end
|
115
|
-
|
116
|
-
def normalize_number(number, marks, currency)
|
117
|
-
digits = number.rpartition(marks.last)
|
118
|
-
digits.first.tr!(ESCAPED_MARKS, '')
|
119
|
-
|
120
|
-
if last_digits_decimals?(digits, marks, currency)
|
121
|
-
"#{digits.first}.#{digits.last}"
|
122
|
-
else
|
123
|
-
"#{digits.first}#{digits.last}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def last_digits_decimals?(digits, marks, currency)
|
128
|
-
# Thousands marks are always different from decimal marks
|
129
|
-
# Example: 1,234,456
|
130
|
-
*other_marks, last_mark = marks
|
131
|
-
other_marks.uniq!
|
132
|
-
if other_marks.size == 1
|
133
|
-
return other_marks.first != last_mark
|
134
|
-
end
|
135
|
-
|
136
|
-
# Thousands always have more than 2 digits
|
137
|
-
# Example: 1,23 must be 1 dollar and 23 cents
|
138
|
-
if digits.last.size < 3
|
139
|
-
return !digits.last.empty?
|
140
|
-
end
|
141
|
-
|
142
|
-
# 0 before the final mark indicates last digits are decimals
|
143
|
-
# Example: 0,23
|
144
|
-
if digits.first.to_i.zero?
|
145
|
-
return true
|
146
|
-
end
|
147
|
-
|
148
|
-
# legacy support for 1.000 USD
|
149
|
-
if digits.last.size == 3 && digits.first.size <= 3 && currency.minor_units < 3
|
150
|
-
return false
|
151
|
-
end
|
152
|
-
|
153
|
-
# The last mark matches the one used by the provided currency to delimiter decimals
|
154
|
-
currency.decimal_mark == last_mark
|
155
|
-
end
|
156
|
-
end
|