nbrb_currency 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +59 -0
- data/README.md +128 -0
- data/lib/money/rates_store/nbrb_historical_store.rb +38 -0
- data/lib/nbrb_currency/rates_document.rb +35 -0
- data/lib/nbrb_currency/version.rb +5 -0
- data/lib/nbrb_currency.rb +216 -33
- metadata +37 -70
- data/.gitignore +0 -4
- data/Gemfile +0 -3
- data/README.rdoc +0 -31
- data/Rakefile +0 -11
- data/nbrb_currency.gemspec +0 -27
- data/spec/exchange_rates.xml +0 -192
- data/spec/exchange_rates.yml +0 -28
- data/spec/nbrb_currency_spec.rb +0 -79
- data/spec/spec_helper.rb +0 -7
- data/spec/tmp/.gitkeep +0 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b19f134db3e29e87e74d1c58239099587ac8f3bfa3563a407f8ad4b84dce8690
|
|
4
|
+
data.tar.gz: 9c3de588bada21ac5a81179dee21b3983f15625028da3e731e92daa04e51012e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 1fd4d6970ba3c58c1f3f153ccca68d6643172e7a4dfb0fd2c86d5cdb94e8849ef773d8d607e0de89da2c6a7b8be260e477faa5af9105b26c011b50f736f813fd
|
|
7
|
+
data.tar.gz: 1e1ce7921df0a8ecc44cef88438fd1094b4d38ed66d5280e86a5fd70e742559b4105f5a5f5201dfe510029c2975401a97661f1bd4b7157080699b0b4bb213881
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [2.0.0] - 2025-12-05
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
- Minimum Ruby version now 3.1.0
|
|
9
|
+
- Updated to money gem ~> 6.19
|
|
10
|
+
- Default base currency changed from BYR to BYN (with automatic date-based selection)
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Historical rates support with date-based exchange rates
|
|
14
|
+
- Dual currency support: BYR (pre-July 1, 2016) and BYN (post-July 1, 2016)
|
|
15
|
+
- `update_historical_rates(cache, date)` method for fetching historical rates
|
|
16
|
+
- `save_historical_rates(cache, date)` method for saving historical rates
|
|
17
|
+
- Date parameter support in `exchange()` and `exchange_with()` methods
|
|
18
|
+
- SAX parser for efficient XML parsing
|
|
19
|
+
- BigDecimal precision (5 decimal places) for accurate calculations
|
|
20
|
+
- `CurrencyUnavailable` exception for better error handling
|
|
21
|
+
- Export/import rates functionality (YAML, JSON, Ruby Marshal)
|
|
22
|
+
- Thread-safe transaction support via historical rates store
|
|
23
|
+
- Metadata in gemspec (changelog_uri, source_code_uri, bug_tracker_uri)
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Refactored to match eu_central_bank architecture patterns
|
|
27
|
+
- Updated NBRB API URLs to use HTTPS
|
|
28
|
+
- Modernized gemspec to RubyGems 4.0 standards
|
|
29
|
+
- Updated specs to RSpec 3.x standards
|
|
30
|
+
- Converted README from RDoc to Markdown
|
|
31
|
+
|
|
32
|
+
### Removed
|
|
33
|
+
- Removed obsolete development dependencies (rr, shoulda, monetize)
|
|
34
|
+
- Removed support for Ruby < 3.1.0
|
|
35
|
+
|
|
36
|
+
## [Unreleased] - 2015-04-07
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- Updated for Money 6.x compatibility
|
|
40
|
+
- Fixed Money::Currency::TABLE removal in Money 5.0.0
|
|
41
|
+
- Fixed subunit conversion
|
|
42
|
+
- Updated RSpec should syntax
|
|
43
|
+
- Removed LVL and LTL (disappeared from NBRB XML)
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
- Monetize core extensions support
|
|
47
|
+
|
|
48
|
+
## [1.0.1] - 2011-11-02
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
- Money version bump
|
|
52
|
+
- JPY currency handling workaround
|
|
53
|
+
|
|
54
|
+
## [1.0.0] - 2011-10-26
|
|
55
|
+
|
|
56
|
+
### Initial Release
|
|
57
|
+
- Basic exchange rate functionality from NBRB
|
|
58
|
+
- BYR currency support
|
|
59
|
+
- Money gem compatibility
|
data/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# NBRB Currency
|
|
2
|
+
|
|
3
|
+
Exchange rates from the National Bank of the Republic of Belarus (NBRB). Compatible with the [money](https://github.com/RubyMoney/money) gem.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
gem install nbrb_currency
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or add to your Gemfile:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
gem 'nbrb_currency'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
require 'nbrb_currency'
|
|
21
|
+
|
|
22
|
+
# Create bank instance
|
|
23
|
+
bank = NbrbCurrency.new
|
|
24
|
+
|
|
25
|
+
# Update rates from NBRB
|
|
26
|
+
bank.update_rates
|
|
27
|
+
|
|
28
|
+
# Exchange money
|
|
29
|
+
money = Money.new(100_00, "USD")
|
|
30
|
+
money.exchange_to("BYN") # => Money.new(250_00, "BYN")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Historical Rates
|
|
34
|
+
|
|
35
|
+
The gem supports both BYR (pre-2016) and BYN (post-2016) currencies with automatic date-based selection:
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
# Fetch historical rates for a specific date
|
|
39
|
+
bank.update_historical_rates(nil, Date.new(2020, 1, 15))
|
|
40
|
+
|
|
41
|
+
# Exchange with historical rates
|
|
42
|
+
bank.exchange(100_00, "USD", "BYN", Date.new(2020, 1, 15))
|
|
43
|
+
|
|
44
|
+
# Pre-redenomination rates (before July 1, 2016)
|
|
45
|
+
bank.exchange(100_00, "USD", "BYR", Date.new(2015, 1, 1))
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Caching
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
# Save rates to file
|
|
52
|
+
bank.save_rates('/tmp/nbrb_rates.xml')
|
|
53
|
+
|
|
54
|
+
# Load rates from cache
|
|
55
|
+
bank.update_rates('/tmp/nbrb_rates.xml')
|
|
56
|
+
|
|
57
|
+
# Save historical rates
|
|
58
|
+
bank.save_historical_rates('/tmp/nbrb_historical.xml', Date.new(2020, 1, 1))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Export/Import Rates
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
# Export rates
|
|
65
|
+
yaml_string = bank.export_rates(:yaml)
|
|
66
|
+
json_string = bank.export_rates(:json)
|
|
67
|
+
|
|
68
|
+
# Import rates
|
|
69
|
+
bank.import_rates(:yaml, yaml_string)
|
|
70
|
+
bank.import_rates(:json, json_string)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Currency Support
|
|
74
|
+
|
|
75
|
+
Supports major currencies including: USD, EUR, RUB, PLN, UAH, GBP, JPY, CNY, CHF, SEK, NOK, DKK, CAD, AUD, NZD, TRY, KRW, SGD, HKD.
|
|
76
|
+
|
|
77
|
+
Legacy support for BYR (Belarusian Ruble before July 1, 2016 redenomination).
|
|
78
|
+
|
|
79
|
+
## Currency Detection
|
|
80
|
+
|
|
81
|
+
The gem automatically detects BYR vs BYN based on:
|
|
82
|
+
- **Date**: Before July 1, 2016 → BYR, after → BYN
|
|
83
|
+
- **Rate magnitude**: > 100 → BYR, < 100 → BYN (when date is ambiguous)
|
|
84
|
+
|
|
85
|
+
## Error Handling
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
begin
|
|
89
|
+
bank.exchange(100, 'USD', 'XXX')
|
|
90
|
+
rescue CurrencyUnavailable => e
|
|
91
|
+
puts "Currency not supported: #{e.message}"
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Migrating from 1.x
|
|
96
|
+
|
|
97
|
+
### Breaking Changes
|
|
98
|
+
- Minimum Ruby version: 2.x → 3.4.7
|
|
99
|
+
- Default currency: BYR → BYN (automatic based on date)
|
|
100
|
+
- API changed from XML to JSON
|
|
101
|
+
|
|
102
|
+
### Code Changes
|
|
103
|
+
```ruby
|
|
104
|
+
# v1.x
|
|
105
|
+
bank.get_rate("USD", "BYR")
|
|
106
|
+
|
|
107
|
+
# v2.0
|
|
108
|
+
bank.get_rate("USD", "BYN") # For current rates
|
|
109
|
+
bank.get_rate("USD", "BYR", Date.new(2015, 1, 1)) # For historical pre-2016
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Requirements
|
|
113
|
+
|
|
114
|
+
- Ruby >= 3.4.7
|
|
115
|
+
- money gem >= 6.19
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
MIT License. See LICENSE file for details.
|
|
120
|
+
|
|
121
|
+
## Contributing
|
|
122
|
+
|
|
123
|
+
1. Fork the repository
|
|
124
|
+
2. Create your feature branch
|
|
125
|
+
3. Add tests for your changes
|
|
126
|
+
4. Commit your changes
|
|
127
|
+
5. Push to the branch
|
|
128
|
+
6. Create a Pull Request
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Money
|
|
4
|
+
module RatesStore
|
|
5
|
+
class NbrbHistoricalStore < Money::RatesStore::Memory
|
|
6
|
+
INDEX_DATE_SEPARATOR = '_AT_'
|
|
7
|
+
|
|
8
|
+
def add_rate(currency_iso_from, currency_iso_to, rate, date = nil)
|
|
9
|
+
transaction { rates[rate_key_for(currency_iso_from, currency_iso_to, date)] = rate }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def get_rate(currency_iso_from, currency_iso_to, date = nil)
|
|
13
|
+
transaction { rates[rate_key_for(currency_iso_from, currency_iso_to, date)] }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def each_rate(&)
|
|
17
|
+
enum = Enumerator.new do |yielder|
|
|
18
|
+
rates.each do |key, rate|
|
|
19
|
+
iso_from, iso_to = key.split(Memory::INDEX_KEY_SEPARATOR)
|
|
20
|
+
iso_to, date = iso_to.split(INDEX_DATE_SEPARATOR)
|
|
21
|
+
date = Date.parse(date) if date
|
|
22
|
+
yielder.yield iso_from, iso_to, rate, date
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
block_given? ? enum.each(&) : enum
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def rate_key_for(currency_iso_from, currency_iso_to, date = nil)
|
|
32
|
+
key = [currency_iso_from, currency_iso_to].join(Memory::INDEX_KEY_SEPARATOR)
|
|
33
|
+
key = [key, date.to_s].join(INDEX_DATE_SEPARATOR) if date
|
|
34
|
+
key.upcase
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class NbrbCurrency
|
|
4
|
+
class RatesDocument
|
|
5
|
+
attr_reader :rates, :updated_at
|
|
6
|
+
|
|
7
|
+
def initialize(json_data)
|
|
8
|
+
@rates = {}
|
|
9
|
+
@updated_at = nil
|
|
10
|
+
parse(json_data)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def parse(json_data)
|
|
16
|
+
data = JSON.parse(json_data)
|
|
17
|
+
|
|
18
|
+
data.each { |rate_data| add_rate_entry(rate_data) }
|
|
19
|
+
|
|
20
|
+
raise 'No rates parsed' if @rates.empty? || @updated_at.nil?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def add_rate_entry(rate_data)
|
|
24
|
+
date = Date.parse(rate_data['Date'])
|
|
25
|
+
@updated_at ||= date
|
|
26
|
+
@rates[date] ||= []
|
|
27
|
+
|
|
28
|
+
currency = rate_data['Cur_Abbreviation']
|
|
29
|
+
rate = rate_data['Cur_OfficialRate'].to_s
|
|
30
|
+
scale = rate_data['Cur_Scale'].to_s
|
|
31
|
+
|
|
32
|
+
@rates[date] << [currency, rate, scale]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/nbrb_currency.rb
CHANGED
|
@@ -1,55 +1,238 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'open-uri'
|
|
3
|
-
require '
|
|
4
|
+
require 'json'
|
|
4
5
|
require 'money'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
require_relative 'nbrb_currency/version'
|
|
8
|
+
require_relative 'money/rates_store/nbrb_historical_store'
|
|
9
|
+
|
|
10
|
+
class InvalidCache < StandardError; end
|
|
11
|
+
class CurrencyUnavailable < StandardError; end
|
|
12
|
+
|
|
13
|
+
class NbrbCurrency < Money::Bank::VariableExchange # rubocop:disable Metrics/ClassLength
|
|
14
|
+
include NbrbCurrencyVersion
|
|
15
|
+
|
|
16
|
+
attr_accessor :last_updated, :rates_updated_at, :historical_last_updated, :historical_rates_updated_at
|
|
17
|
+
|
|
18
|
+
SERIALIZER_DATE_SEPARATOR = '_AT_'
|
|
19
|
+
DECIMAL_PRECISION = 5
|
|
20
|
+
NBRB_RATES_URL = 'https://api.nbrb.by/exrates/rates?periodicity=0'
|
|
21
|
+
NBRB_HISTORICAL_URL = 'https://api.nbrb.by/exrates/rates?ondate=%s&periodicity=0'
|
|
7
22
|
|
|
8
|
-
|
|
23
|
+
# BYN redenomination date: July 1, 2016 (10000:1)
|
|
24
|
+
REDENOMINATION_DATE = Date.new(2016, 7, 1)
|
|
25
|
+
# Threshold to detect BYR vs BYN (BYR rates are typically > 1000, BYN < 100)
|
|
26
|
+
BYR_THRESHOLD = 100
|
|
9
27
|
|
|
10
|
-
|
|
11
|
-
|
|
28
|
+
CURRENCIES = %w(USD EUR RUB PLN UAH GBP JPY CNY CHF SEK NOK DKK CAD AUD NZD TRY KRW SGD HKD).freeze
|
|
29
|
+
LEGACY_CURRENCIES = %w(BYR).freeze
|
|
30
|
+
|
|
31
|
+
def initialize(store = Money::RatesStore::NbrbHistoricalStore.new, &)
|
|
32
|
+
super
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def update_rates(cache = nil)
|
|
36
|
+
update_parsed_rates(doc(cache, NBRB_RATES_URL))
|
|
37
|
+
end
|
|
12
38
|
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
39
|
+
def update_historical_rates(cache = nil, date = nil)
|
|
40
|
+
url = date ? (NBRB_HISTORICAL_URL % date.strftime('%Y-%m-%d')) : NBRB_RATES_URL
|
|
41
|
+
update_parsed_historical_rates(doc(cache, url))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def save_rates(cache, url = NBRB_RATES_URL)
|
|
45
|
+
raise InvalidCache unless cache
|
|
46
|
+
|
|
47
|
+
File.open(cache, 'w') do |file|
|
|
48
|
+
URI.parse(url).open { |io| io.each_line { |line| file.puts line } }
|
|
20
49
|
end
|
|
21
|
-
add_rate("BYR", "BYR", 1)
|
|
22
50
|
end
|
|
23
51
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
52
|
+
def save_historical_rates(cache, date = nil)
|
|
53
|
+
url = date ? (NBRB_HISTORICAL_URL % date.strftime('%Y-%m-%d')) : NBRB_RATES_URL
|
|
54
|
+
save_rates(cache, url)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def exchange(cents, from_currency, to_currency, date = nil)
|
|
58
|
+
exchange_with(Money.new(cents, from_currency), to_currency, date)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def exchange_with(from, to_currency, date = nil)
|
|
62
|
+
base_currency = base_currency_for_date(date)
|
|
63
|
+
rate = get_rate(from.currency, to_currency,
|
|
64
|
+
date) || calculate_cross_rate(from.currency, to_currency, base_currency, date)
|
|
65
|
+
|
|
66
|
+
calculate_exchange(from, to_currency, rate)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def get_rate(from, to, date = nil)
|
|
70
|
+
return 1 if from == to
|
|
71
|
+
|
|
72
|
+
check_currency_available(from, date)
|
|
73
|
+
check_currency_available(to, date)
|
|
74
|
+
|
|
75
|
+
date = date[:date] if date.is_a?(Hash)
|
|
76
|
+
|
|
77
|
+
store.get_rate(::Money::Currency.wrap(from).iso_code, ::Money::Currency.wrap(to).iso_code, date)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def set_rate(from, to, rate, date = nil)
|
|
81
|
+
date = date[:date] if date.is_a?(Hash)
|
|
82
|
+
store.add_rate(::Money::Currency.wrap(from).iso_code, ::Money::Currency.wrap(to).iso_code, rate, date)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def rates
|
|
86
|
+
store.each_rate.with_object({}) do |(from, to, rate, date), hash|
|
|
87
|
+
key = [from, to].join(SERIALIZER_SEPARATOR)
|
|
88
|
+
key = [key, date.to_s].join(SERIALIZER_DATE_SEPARATOR) if date
|
|
89
|
+
hash[key] = rate
|
|
29
90
|
end
|
|
30
91
|
end
|
|
31
92
|
|
|
32
|
-
def
|
|
33
|
-
|
|
93
|
+
def export_rates(format, file = nil, _opts = {})
|
|
94
|
+
raise Money::Bank::UnknownRateFormat unless RATE_FORMATS.include? format
|
|
95
|
+
|
|
96
|
+
store.transaction do
|
|
97
|
+
s = case format
|
|
98
|
+
when :json
|
|
99
|
+
JSON.dump(rates)
|
|
100
|
+
when :ruby
|
|
101
|
+
Marshal.dump(rates)
|
|
102
|
+
when :yaml
|
|
103
|
+
YAML.dump(rates)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
File.write(file, s) unless file.nil?
|
|
107
|
+
s
|
|
108
|
+
end
|
|
34
109
|
end
|
|
35
110
|
|
|
36
|
-
def
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
111
|
+
def import_rates(format, data, _opts = {})
|
|
112
|
+
raise Money::Bank::UnknownRateFormat unless RATE_FORMATS.include? format
|
|
113
|
+
|
|
114
|
+
store.transaction do
|
|
115
|
+
parsed_data = parse_import_data(format, data)
|
|
116
|
+
|
|
117
|
+
parsed_data.each do |key, rate|
|
|
118
|
+
from, to = key.split(SERIALIZER_SEPARATOR)
|
|
119
|
+
to, date = to.split(SERIALIZER_DATE_SEPARATOR)
|
|
120
|
+
store.add_rate from, to, BigDecimal(rate, DECIMAL_PRECISION), date
|
|
121
|
+
end
|
|
43
122
|
end
|
|
44
|
-
|
|
123
|
+
|
|
124
|
+
self
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def check_currency_available(currency, date = nil)
|
|
128
|
+
currency_string = currency.to_s
|
|
129
|
+
base = base_currency_for_date(date)
|
|
130
|
+
return true if currency_string == base
|
|
131
|
+
return true if CURRENCIES.include?(currency_string)
|
|
132
|
+
return true if LEGACY_CURRENCIES.include?(currency_string)
|
|
133
|
+
|
|
134
|
+
raise CurrencyUnavailable, "No rates available for #{currency_string}"
|
|
45
135
|
end
|
|
46
136
|
|
|
47
137
|
protected
|
|
48
138
|
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
139
|
+
def base_currency_for_date(date)
|
|
140
|
+
(date && date < REDENOMINATION_DATE) ? 'BYR' : 'BYN'
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def detect_base_currency_from_rate(usd_rate)
|
|
144
|
+
(usd_rate.to_f > BYR_THRESHOLD) ? 'BYR' : 'BYN'
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def doc(cache, url = NBRB_RATES_URL)
|
|
148
|
+
json_data = cache ? File.read(cache) : URI.parse(url).open.read
|
|
149
|
+
::NbrbCurrency::RatesDocument.new(json_data)
|
|
53
150
|
end
|
|
54
151
|
|
|
152
|
+
def update_parsed_rates(rates_document)
|
|
153
|
+
store.transaction do
|
|
154
|
+
copy_rates_with_document_date(rates_document, false)
|
|
155
|
+
end
|
|
156
|
+
@rates_updated_at = rates_document.updated_at
|
|
157
|
+
@last_updated = Time.now
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def copy_rates_with_document_date(rates_document, with_date)
|
|
161
|
+
rates_document.rates.each do |date, rates|
|
|
162
|
+
usd_rate = rates.find { |curr, _, _| curr == 'USD' }
|
|
163
|
+
base = usd_rate ? detect_base_currency_from_rate(usd_rate[1]) : base_currency_for_date(date)
|
|
164
|
+
|
|
165
|
+
rates.each { |currency, rate, scale| process_currency_rate(currency, rate, scale, base, with_date ? date : nil) }
|
|
166
|
+
set_rate(base, base, 1, with_date ? date : nil)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def update_parsed_historical_rates(rates_document)
|
|
171
|
+
store.transaction do
|
|
172
|
+
copy_rates_with_document_date(rates_document, true)
|
|
173
|
+
end
|
|
174
|
+
@historical_rates_updated_at = rates_document.updated_at
|
|
175
|
+
@historical_last_updated = Time.now
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
def parse_import_data(format, data)
|
|
181
|
+
case format
|
|
182
|
+
when :json
|
|
183
|
+
JSON.parse(data)
|
|
184
|
+
when :ruby
|
|
185
|
+
Marshal.load(data) # rubocop:disable Security/MarshalLoad
|
|
186
|
+
when :yaml
|
|
187
|
+
if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0')
|
|
188
|
+
YAML.safe_load(data, permitted_classes: [BigDecimal])
|
|
189
|
+
else
|
|
190
|
+
YAML.safe_load(data, [BigDecimal], [], true)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def process_currency_rate(currency, rate, scale, base, date)
|
|
196
|
+
return if currency == 'XDR'
|
|
197
|
+
return unless currency_recognized?(currency)
|
|
198
|
+
|
|
199
|
+
adjusted_rate = BigDecimal(rate, DECIMAL_PRECISION) / BigDecimal(scale, DECIMAL_PRECISION)
|
|
200
|
+
set_rate(currency, base, adjusted_rate, date)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def currency_recognized?(currency)
|
|
204
|
+
Money::Currency.wrap(currency)
|
|
205
|
+
true
|
|
206
|
+
rescue Money::Currency::UnknownCurrency
|
|
207
|
+
false
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def calculate_cross_rate(from_currency, to_currency, base_currency, date)
|
|
211
|
+
from_base_rate = nil
|
|
212
|
+
to_base_rate = nil
|
|
213
|
+
|
|
214
|
+
store.transaction do
|
|
215
|
+
from_base_rate = get_rate(from_currency.to_s, base_currency, date)
|
|
216
|
+
to_base_rate = get_rate(to_currency, base_currency, date)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
unless from_base_rate && to_base_rate
|
|
220
|
+
message = "No conversion rate known for '#{from_currency.iso_code}' -> '#{to_currency}'"
|
|
221
|
+
message << " on #{date}" if date
|
|
222
|
+
raise Money::Bank::UnknownRate, message
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
from_base_rate / to_base_rate
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def calculate_exchange(from, to_currency, rate)
|
|
229
|
+
to_currency_money = Money::Currency.wrap(to_currency).subunit_to_unit
|
|
230
|
+
from_currency_money = from.currency.subunit_to_unit
|
|
231
|
+
decimal_money = BigDecimal(to_currency_money,
|
|
232
|
+
DECIMAL_PRECISION) / BigDecimal(from_currency_money, DECIMAL_PRECISION)
|
|
233
|
+
money = (decimal_money * from.cents * rate).round
|
|
234
|
+
Money.new(money, to_currency)
|
|
235
|
+
end
|
|
55
236
|
end
|
|
237
|
+
|
|
238
|
+
require_relative 'nbrb_currency/rates_document'
|
metadata
CHANGED
|
@@ -1,115 +1,82 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nbrb_currency
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 2.0.0
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
|
-
-
|
|
9
|
-
autorequire:
|
|
7
|
+
- Alexander Grebennik
|
|
10
8
|
bindir: bin
|
|
11
9
|
cert_chain: []
|
|
12
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
11
|
dependencies:
|
|
14
12
|
- !ruby/object:Gem::Dependency
|
|
15
|
-
name:
|
|
16
|
-
requirement:
|
|
17
|
-
none: false
|
|
13
|
+
name: bigdecimal
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
18
15
|
requirements:
|
|
19
|
-
- -
|
|
16
|
+
- - ">="
|
|
20
17
|
- !ruby/object:Gem::Version
|
|
21
18
|
version: '0'
|
|
22
19
|
type: :runtime
|
|
23
20
|
prerelease: false
|
|
24
|
-
version_requirements:
|
|
25
|
-
- !ruby/object:Gem::Dependency
|
|
26
|
-
name: money
|
|
27
|
-
requirement: &9840100 !ruby/object:Gem::Requirement
|
|
28
|
-
none: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
29
22
|
requirements:
|
|
30
|
-
- -
|
|
23
|
+
- - ">="
|
|
31
24
|
- !ruby/object:Gem::Version
|
|
32
|
-
version:
|
|
33
|
-
type: :runtime
|
|
34
|
-
prerelease: false
|
|
35
|
-
version_requirements: *9840100
|
|
36
|
-
- !ruby/object:Gem::Dependency
|
|
37
|
-
name: rspec
|
|
38
|
-
requirement: &9839060 !ruby/object:Gem::Requirement
|
|
39
|
-
none: false
|
|
40
|
-
requirements:
|
|
41
|
-
- - ! '>='
|
|
42
|
-
- !ruby/object:Gem::Version
|
|
43
|
-
version: 2.0.0
|
|
44
|
-
type: :development
|
|
45
|
-
prerelease: false
|
|
46
|
-
version_requirements: *9839060
|
|
25
|
+
version: '0'
|
|
47
26
|
- !ruby/object:Gem::Dependency
|
|
48
|
-
name:
|
|
49
|
-
requirement:
|
|
50
|
-
none: false
|
|
27
|
+
name: money
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
51
29
|
requirements:
|
|
52
|
-
- -
|
|
30
|
+
- - ">="
|
|
53
31
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
55
|
-
type: :
|
|
32
|
+
version: '6.19'
|
|
33
|
+
type: :runtime
|
|
56
34
|
prerelease: false
|
|
57
|
-
version_requirements:
|
|
58
|
-
- !ruby/object:Gem::Dependency
|
|
59
|
-
name: shoulda
|
|
60
|
-
requirement: &9836840 !ruby/object:Gem::Requirement
|
|
61
|
-
none: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
62
36
|
requirements:
|
|
63
|
-
- -
|
|
37
|
+
- - ">="
|
|
64
38
|
- !ruby/object:Gem::Version
|
|
65
|
-
version: '
|
|
66
|
-
type: :development
|
|
67
|
-
prerelease: false
|
|
68
|
-
version_requirements: *9836840
|
|
39
|
+
version: '6.19'
|
|
69
40
|
description: This gem reads exchange rates from the National Bank of the Republic
|
|
70
41
|
of Belarus website. It uses it to calculates exchange rates. It is compatible with
|
|
71
42
|
the money gem
|
|
72
43
|
email:
|
|
73
|
-
-
|
|
44
|
+
- sl.bug.sl@gmail.com
|
|
74
45
|
executables: []
|
|
75
46
|
extensions: []
|
|
76
47
|
extra_rdoc_files: []
|
|
77
48
|
files:
|
|
78
|
-
- .
|
|
79
|
-
- Gemfile
|
|
49
|
+
- CHANGELOG.md
|
|
80
50
|
- LICENSE
|
|
81
|
-
- README.
|
|
82
|
-
-
|
|
51
|
+
- README.md
|
|
52
|
+
- lib/money/rates_store/nbrb_historical_store.rb
|
|
83
53
|
- lib/nbrb_currency.rb
|
|
84
|
-
- nbrb_currency.
|
|
85
|
-
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
54
|
+
- lib/nbrb_currency/rates_document.rb
|
|
55
|
+
- lib/nbrb_currency/version.rb
|
|
56
|
+
homepage: https://github.com/slbug/nbrb_currency
|
|
57
|
+
licenses:
|
|
58
|
+
- MIT
|
|
59
|
+
metadata:
|
|
60
|
+
changelog_uri: https://github.com/slbug/nbrb_currency/blob/main/CHANGELOG.md
|
|
61
|
+
source_code_uri: https://github.com/slbug/nbrb_currency
|
|
62
|
+
bug_tracker_uri: https://github.com/slbug/nbrb_currency/issues
|
|
63
|
+
rubygems_mfa_required: 'true'
|
|
93
64
|
rdoc_options: []
|
|
94
65
|
require_paths:
|
|
95
66
|
- lib
|
|
96
67
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
97
|
-
none: false
|
|
98
68
|
requirements:
|
|
99
|
-
- -
|
|
69
|
+
- - ">="
|
|
100
70
|
- !ruby/object:Gem::Version
|
|
101
|
-
version:
|
|
71
|
+
version: 3.4.7
|
|
102
72
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
|
-
none: false
|
|
104
73
|
requirements:
|
|
105
|
-
- -
|
|
74
|
+
- - ">="
|
|
106
75
|
- !ruby/object:Gem::Version
|
|
107
|
-
version:
|
|
76
|
+
version: '0'
|
|
108
77
|
requirements: []
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
signing_key:
|
|
112
|
-
specification_version: 3
|
|
78
|
+
rubygems_version: 3.7.2
|
|
79
|
+
specification_version: 4
|
|
113
80
|
summary: Calculates exchange rates based on rates from National Bank of the Republic
|
|
114
81
|
of Belarus. Money gem compatible.
|
|
115
82
|
test_files: []
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/README.rdoc
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
= nbrb_currency
|
|
2
|
-
|
|
3
|
-
== Introduction
|
|
4
|
-
|
|
5
|
-
This gem downloads the exchange rates from the National Bank of the Republic of Belarus. You can calculate exchange rates with it. It is compatible with the money gem.
|
|
6
|
-
|
|
7
|
-
== Installation
|
|
8
|
-
|
|
9
|
-
$ gem install nbrb_currency
|
|
10
|
-
|
|
11
|
-
== Dependencies
|
|
12
|
-
|
|
13
|
-
* nokogiri
|
|
14
|
-
* money
|
|
15
|
-
|
|
16
|
-
== Usage
|
|
17
|
-
|
|
18
|
-
Check documentation for https://github.com/RubyMoney/eu_central_bank, it's almost the same
|
|
19
|
-
|
|
20
|
-
== Note on Patches/Pull Requests
|
|
21
|
-
|
|
22
|
-
* Fork the project.
|
|
23
|
-
* Make your feature addition or bug fix.
|
|
24
|
-
* Add tests for it. This is important so I don't break it in a
|
|
25
|
-
future version unintentionally.
|
|
26
|
-
* Commit, do not mess with rakefile, version, or history.
|
|
27
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
|
28
|
-
|
|
29
|
-
== Copyright
|
|
30
|
-
|
|
31
|
-
Copyright (c) 2010 RubyMoney. See LICENSE for details.
|
data/Rakefile
DELETED
data/nbrb_currency.gemspec
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
-
|
|
4
|
-
Gem::Specification.new do |s|
|
|
5
|
-
s.name = "nbrb_currency"
|
|
6
|
-
s.version = "1.0.0"
|
|
7
|
-
s.platform = Gem::Platform::RUBY
|
|
8
|
-
s.authors = ["Aleks Grebennik"]
|
|
9
|
-
s.email = ["aleks.grebennik@gmail.com"]
|
|
10
|
-
s.homepage = "http://github.com/slbug/nbrb_currency"
|
|
11
|
-
s.summary = %q{Calculates exchange rates based on rates from National Bank of the Republic of Belarus. Money gem compatible.}
|
|
12
|
-
s.description = %q{This gem reads exchange rates from the National Bank of the Republic of Belarus website. It uses it to calculates exchange rates. It is compatible with the money gem}
|
|
13
|
-
|
|
14
|
-
s.required_rubygems_version = ">= 1.3.6"
|
|
15
|
-
|
|
16
|
-
s.add_dependency "nokogiri"
|
|
17
|
-
s.add_dependency "money", "~> 3.7.1"
|
|
18
|
-
|
|
19
|
-
s.add_development_dependency "rspec", ">= 2.0.0"
|
|
20
|
-
s.add_development_dependency "rr"
|
|
21
|
-
s.add_development_dependency "shoulda"
|
|
22
|
-
|
|
23
|
-
s.files = `git ls-files`.split("\n")
|
|
24
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
25
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
26
|
-
s.require_paths = ["lib"]
|
|
27
|
-
end
|
data/spec/exchange_rates.xml
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="windows-1251"?>
|
|
2
|
-
<DailyExRates Date="10/26/2011">
|
|
3
|
-
<Currency Id="170">
|
|
4
|
-
<NumCode>036</NumCode>
|
|
5
|
-
<CharCode>AUD</CharCode>
|
|
6
|
-
<Scale>1</Scale>
|
|
7
|
-
<Name>������������� ������</Name>
|
|
8
|
-
<Rate>8920.87</Rate>
|
|
9
|
-
</Currency>
|
|
10
|
-
<Currency Id="191">
|
|
11
|
-
<NumCode>975</NumCode>
|
|
12
|
-
<CharCode>BGN</CharCode>
|
|
13
|
-
<Scale>1</Scale>
|
|
14
|
-
<Name>������c��� ���</Name>
|
|
15
|
-
<Rate>6059.74</Rate>
|
|
16
|
-
</Currency>
|
|
17
|
-
<Currency Id="224">
|
|
18
|
-
<NumCode>980</NumCode>
|
|
19
|
-
<CharCode>UAH</CharCode>
|
|
20
|
-
<Scale>1</Scale>
|
|
21
|
-
<Name>������</Name>
|
|
22
|
-
<Rate>1064.87</Rate>
|
|
23
|
-
</Currency>
|
|
24
|
-
<Currency Id="36">
|
|
25
|
-
<NumCode>208</NumCode>
|
|
26
|
-
<CharCode>DKK</CharCode>
|
|
27
|
-
<Scale>1</Scale>
|
|
28
|
-
<Name>������� �����</Name>
|
|
29
|
-
<Rate>1592.06</Rate>
|
|
30
|
-
</Currency>
|
|
31
|
-
<Currency Id="145">
|
|
32
|
-
<NumCode>840</NumCode>
|
|
33
|
-
<CharCode>USD</CharCode>
|
|
34
|
-
<Scale>1</Scale>
|
|
35
|
-
<Name>������ ���</Name>
|
|
36
|
-
<Rate>8520</Rate>
|
|
37
|
-
</Currency>
|
|
38
|
-
<Currency Id="19">
|
|
39
|
-
<NumCode>978</NumCode>
|
|
40
|
-
<CharCode>EUR</CharCode>
|
|
41
|
-
<Scale>1</Scale>
|
|
42
|
-
<Name>����</Name>
|
|
43
|
-
<Rate>11860</Rate>
|
|
44
|
-
</Currency>
|
|
45
|
-
<Currency Id="166">
|
|
46
|
-
<NumCode>960</NumCode>
|
|
47
|
-
<CharCode>XDR</CharCode>
|
|
48
|
-
<Scale>1</Scale>
|
|
49
|
-
<Name>������� ��� (SDR) �� ���</Name>
|
|
50
|
-
<Rate>13467.99</Rate>
|
|
51
|
-
</Currency>
|
|
52
|
-
<Currency Id="219">
|
|
53
|
-
<NumCode>985</NumCode>
|
|
54
|
-
<CharCode>PLN</CharCode>
|
|
55
|
-
<Scale>1</Scale>
|
|
56
|
-
<Name>������</Name>
|
|
57
|
-
<Rate>2714.33</Rate>
|
|
58
|
-
</Currency>
|
|
59
|
-
<Currency Id="67">
|
|
60
|
-
<NumCode>392</NumCode>
|
|
61
|
-
<CharCode>JPY</CharCode>
|
|
62
|
-
<Scale>10</Scale>
|
|
63
|
-
<Name>����</Name>
|
|
64
|
-
<Rate>1119.43</Rate>
|
|
65
|
-
</Currency>
|
|
66
|
-
<Currency Id="264">
|
|
67
|
-
<NumCode>364</NumCode>
|
|
68
|
-
<CharCode>IRR</CharCode>
|
|
69
|
-
<Scale>1000</Scale>
|
|
70
|
-
<Name>�������� ����</Name>
|
|
71
|
-
<Rate>794.63</Rate>
|
|
72
|
-
</Currency>
|
|
73
|
-
<Currency Id="58">
|
|
74
|
-
<NumCode>352</NumCode>
|
|
75
|
-
<CharCode>ISK</CharCode>
|
|
76
|
-
<Scale>1</Scale>
|
|
77
|
-
<Name>���������� �����</Name>
|
|
78
|
-
<Rate>74.54</Rate>
|
|
79
|
-
</Currency>
|
|
80
|
-
<Currency Id="23">
|
|
81
|
-
<NumCode>124</NumCode>
|
|
82
|
-
<CharCode>CAD</CharCode>
|
|
83
|
-
<Scale>1</Scale>
|
|
84
|
-
<Name>��������� ������</Name>
|
|
85
|
-
<Rate>8494.94</Rate>
|
|
86
|
-
</Currency>
|
|
87
|
-
<Currency Id="254">
|
|
88
|
-
<NumCode>156</NumCode>
|
|
89
|
-
<CharCode>CNY</CharCode>
|
|
90
|
-
<Scale>1</Scale>
|
|
91
|
-
<Name>��������� ����</Name>
|
|
92
|
-
<Rate>1339.46</Rate>
|
|
93
|
-
</Currency>
|
|
94
|
-
<Currency Id="72">
|
|
95
|
-
<NumCode>414</NumCode>
|
|
96
|
-
<CharCode>KWD</CharCode>
|
|
97
|
-
<Scale>1</Scale>
|
|
98
|
-
<Name>���������� �����</Name>
|
|
99
|
-
<Rate>30996.47</Rate>
|
|
100
|
-
</Currency>
|
|
101
|
-
<Currency Id="176">
|
|
102
|
-
<NumCode>428</NumCode>
|
|
103
|
-
<CharCode>LVL</CharCode>
|
|
104
|
-
<Scale>1</Scale>
|
|
105
|
-
<Name>���������� ���</Name>
|
|
106
|
-
<Rate>16836.28</Rate>
|
|
107
|
-
</Currency>
|
|
108
|
-
<Currency Id="177">
|
|
109
|
-
<NumCode>440</NumCode>
|
|
110
|
-
<CharCode>LTL</CharCode>
|
|
111
|
-
<Scale>1</Scale>
|
|
112
|
-
<Name>��������� ���</Name>
|
|
113
|
-
<Rate>3432.51</Rate>
|
|
114
|
-
</Currency>
|
|
115
|
-
<Currency Id="178">
|
|
116
|
-
<NumCode>498</NumCode>
|
|
117
|
-
<CharCode>MDL</CharCode>
|
|
118
|
-
<Scale>1</Scale>
|
|
119
|
-
<Name>���������� ���</Name>
|
|
120
|
-
<Rate>730.39</Rate>
|
|
121
|
-
</Currency>
|
|
122
|
-
<Currency Id="101">
|
|
123
|
-
<NumCode>578</NumCode>
|
|
124
|
-
<CharCode>NOK</CharCode>
|
|
125
|
-
<Scale>1</Scale>
|
|
126
|
-
<Name>���������� �����</Name>
|
|
127
|
-
<Rate>1544.71</Rate>
|
|
128
|
-
</Currency>
|
|
129
|
-
<Currency Id="190">
|
|
130
|
-
<NumCode>643</NumCode>
|
|
131
|
-
<CharCode>RUB</CharCode>
|
|
132
|
-
<Scale>1</Scale>
|
|
133
|
-
<Name>���������� �����</Name>
|
|
134
|
-
<Rate>279</Rate>
|
|
135
|
-
</Currency>
|
|
136
|
-
<Currency Id="119">
|
|
137
|
-
<NumCode>702</NumCode>
|
|
138
|
-
<CharCode>SGD</CharCode>
|
|
139
|
-
<Scale>1</Scale>
|
|
140
|
-
<Name>��������c��� ������</Name>
|
|
141
|
-
<Rate>6743.71</Rate>
|
|
142
|
-
</Currency>
|
|
143
|
-
<Currency Id="223">
|
|
144
|
-
<NumCode>417</NumCode>
|
|
145
|
-
<CharCode>KGS</CharCode>
|
|
146
|
-
<Scale>1</Scale>
|
|
147
|
-
<Name>���</Name>
|
|
148
|
-
<Rate>187.97</Rate>
|
|
149
|
-
</Currency>
|
|
150
|
-
<Currency Id="222">
|
|
151
|
-
<NumCode>398</NumCode>
|
|
152
|
-
<CharCode>KZT</CharCode>
|
|
153
|
-
<Scale>1</Scale>
|
|
154
|
-
<Name>�����</Name>
|
|
155
|
-
<Rate>57.58</Rate>
|
|
156
|
-
</Currency>
|
|
157
|
-
<Currency Id="256">
|
|
158
|
-
<NumCode>949</NumCode>
|
|
159
|
-
<CharCode>TRY</CharCode>
|
|
160
|
-
<Scale>1</Scale>
|
|
161
|
-
<Name>�������� ����</Name>
|
|
162
|
-
<Rate>4714.74</Rate>
|
|
163
|
-
</Currency>
|
|
164
|
-
<Currency Id="143">
|
|
165
|
-
<NumCode>826</NumCode>
|
|
166
|
-
<CharCode>GBP</CharCode>
|
|
167
|
-
<Scale>1</Scale>
|
|
168
|
-
<Name>���� ����������</Name>
|
|
169
|
-
<Rate>13618.37</Rate>
|
|
170
|
-
</Currency>
|
|
171
|
-
<Currency Id="171">
|
|
172
|
-
<NumCode>203</NumCode>
|
|
173
|
-
<CharCode>CZK</CharCode>
|
|
174
|
-
<Scale>1</Scale>
|
|
175
|
-
<Name>������� �����</Name>
|
|
176
|
-
<Rate>475.9</Rate>
|
|
177
|
-
</Currency>
|
|
178
|
-
<Currency Id="129">
|
|
179
|
-
<NumCode>752</NumCode>
|
|
180
|
-
<CharCode>SEK</CharCode>
|
|
181
|
-
<Scale>1</Scale>
|
|
182
|
-
<Name>�������� �����</Name>
|
|
183
|
-
<Rate>1300.6</Rate>
|
|
184
|
-
</Currency>
|
|
185
|
-
<Currency Id="130">
|
|
186
|
-
<NumCode>756</NumCode>
|
|
187
|
-
<CharCode>CHF</CharCode>
|
|
188
|
-
<Scale>1</Scale>
|
|
189
|
-
<Name>����������� �����</Name>
|
|
190
|
-
<Rate>9684.57</Rate>
|
|
191
|
-
</Currency>
|
|
192
|
-
</DailyExRates>
|
data/spec/exchange_rates.yml
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
currencies:
|
|
2
|
-
AUD: 8920.87
|
|
3
|
-
BGN: 6059.74
|
|
4
|
-
UAH: 1064.87
|
|
5
|
-
DKK: 1592.06
|
|
6
|
-
USD: 8520
|
|
7
|
-
EUR: 11860
|
|
8
|
-
PLN: 2714.33
|
|
9
|
-
JPY: 111.943
|
|
10
|
-
IRR: 0.79463
|
|
11
|
-
ISK: 74.54
|
|
12
|
-
CAD: 8494.94
|
|
13
|
-
CNY: 1339.46
|
|
14
|
-
KWD: 30996.47
|
|
15
|
-
LVL: 16836.28
|
|
16
|
-
LTL: 3432.51
|
|
17
|
-
MDL: 730.39
|
|
18
|
-
NOK: 1544.71
|
|
19
|
-
RUB: 279
|
|
20
|
-
SGD: 6743.71
|
|
21
|
-
KGS: 187.97
|
|
22
|
-
KZT: 57.58
|
|
23
|
-
TRY: 4714.74
|
|
24
|
-
GBP: 13618.37
|
|
25
|
-
CZK: 475.9
|
|
26
|
-
SEK: 1300.6
|
|
27
|
-
CHF: 9684.57
|
|
28
|
-
|
data/spec/nbrb_currency_spec.rb
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
-
require 'yaml'
|
|
3
|
-
|
|
4
|
-
describe "NbrbCurrency" do
|
|
5
|
-
before(:each) do
|
|
6
|
-
@bank = NbrbCurrency.new
|
|
7
|
-
@cache_path = File.expand_path(File.dirname(__FILE__) + '/exchange_rates.xml')
|
|
8
|
-
@yml_cache_path = File.expand_path(File.dirname(__FILE__) + '/exchange_rates.yml')
|
|
9
|
-
@tmp_cache_path = File.expand_path(File.dirname(__FILE__) + '/tmp/exchange_rates.xml')
|
|
10
|
-
@exchange_rates = YAML.load_file(@yml_cache_path)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
after(:each) do
|
|
14
|
-
if File.exists? @tmp_cache_path
|
|
15
|
-
File.delete @tmp_cache_path
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
it "should save the xml file from nbrb given a file path" do
|
|
20
|
-
@bank.save_rates(@tmp_cache_path)
|
|
21
|
-
File.exists?(@tmp_cache_path).should == true
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it "should raise an error if an invalid path is given to save_rates" do
|
|
25
|
-
lambda { @bank.save_rates(nil) }.should raise_exception
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it "should update itself with exchange rates from nbrb website" do
|
|
29
|
-
stub(OpenURI::OpenRead).open(NbrbCurrency::NBRB_RATES_URL) {@cache_path}
|
|
30
|
-
@bank.update_rates
|
|
31
|
-
NbrbCurrency::CURRENCIES.each do |currency|
|
|
32
|
-
@bank.get_rate(currency, "BYR").should > 0
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
it "should update itself with exchange rates from cache" do
|
|
37
|
-
@bank.update_rates(@cache_path)
|
|
38
|
-
NbrbCurrency::CURRENCIES.each do |currency|
|
|
39
|
-
@bank.get_rate(currency, "BYR").should > 0
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "should return the correct exchange rates using exchange" do
|
|
44
|
-
@bank.update_rates(@cache_path)
|
|
45
|
-
NbrbCurrency::CURRENCIES.reject{|c| %w{JPY KWD}.include?(c) }.each do |currency|
|
|
46
|
-
@bank.exchange(100, currency, "BYR").cents.should == (@exchange_rates["currencies"][currency].to_f * 100).round
|
|
47
|
-
end
|
|
48
|
-
subunit = Money::Currency.wrap("KWD").subunit_to_unit.to_f
|
|
49
|
-
@bank.exchange(1000, "KWD", "BYR").cents.should == ((subunit / 1000) * @exchange_rates["currencies"]['KWD'].to_f * 100).round
|
|
50
|
-
subunit = Money::Currency.wrap("JPY").subunit_to_unit.to_f
|
|
51
|
-
@bank.exchange(100, "JPY", "BYR").cents.should == ((subunit / 100) * @exchange_rates["currencies"]['JPY'].to_f * 100).round
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "should return the correct exchange rates using exchange_with" do
|
|
55
|
-
@bank.update_rates(@cache_path)
|
|
56
|
-
NbrbCurrency::CURRENCIES.reject{|c| %w{JPY KWD}.include?(c) }.each do |currency|
|
|
57
|
-
@bank.exchange_with(Money.new(100, currency), "BYR").cents.should == (@exchange_rates["currencies"][currency].to_f * 100).round
|
|
58
|
-
@bank.exchange_with(1.to_money(currency), "BYR").cents.should == (@exchange_rates["currencies"][currency].to_f * 100).round
|
|
59
|
-
end
|
|
60
|
-
@bank.exchange_with(5000.to_money('JPY'), 'BYR').cents.should == 55971500 # 559715 BYR
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# in response to #4
|
|
64
|
-
it "should exchange btc" do
|
|
65
|
-
Money::Currency::TABLE[:btc] = {
|
|
66
|
-
:priority => 1,
|
|
67
|
-
:iso_code => "BTC",
|
|
68
|
-
:name => "Bitcoin",
|
|
69
|
-
:symbol => "BTC",
|
|
70
|
-
:subunit => "Cent",
|
|
71
|
-
:subunit_to_unit => 1000,
|
|
72
|
-
:separator => ".",
|
|
73
|
-
:delimiter => ","
|
|
74
|
-
}
|
|
75
|
-
@bank.add_rate("USD", "BTC", 1 / 13.7603)
|
|
76
|
-
@bank.add_rate("BTC", "USD", 13.7603)
|
|
77
|
-
@bank.exchange(100, "BTC", "USD").cents.should == 138
|
|
78
|
-
end
|
|
79
|
-
end
|
data/spec/spec_helper.rb
DELETED
data/spec/tmp/.gitkeep
DELETED
|
File without changes
|