Skip to content

Commit c7f4736

Browse files
committed
add convert method
1 parent 793eafd commit c7f4736

File tree

9 files changed

+87
-38
lines changed

9 files changed

+87
-38
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
],
1818
"require": {
1919
"php": "^8.1",
20+
"brick/money": "^0.10.1",
2021
"illuminate/contracts": "^10.0||^11.0||^12.0",
2122
"saloonphp/cache-plugin": "^3.0",
2223
"saloonphp/laravel-plugin": "^3.0",

src/Facades/Forex.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace Elegantly\Forex\Facades;
66

7+
use Brick\Money\Currency;
8+
use Brick\Money\Money;
9+
use Carbon\Carbon;
710
use Illuminate\Support\Facades\Facade;
811

912
/**
@@ -15,6 +18,7 @@
1518
* @method static array<string, int|float> queryRates()
1619
* @method static array<string, array<string, int|float>> getLatest()
1720
* @method static array<string, array<string, array<string, int|float>>> getRates()
21+
* @method static Money convert(Money $money, string|Currency $currency, RoundingMode $roundingMode = RoundingMode::HALF_UP, ?Carbon $date = null)
1822
*
1923
* @see \Elegantly\Forex\Forex
2024
*/

src/Forex.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
namespace Elegantly\Forex;
66

7+
use Brick\Math\RoundingMode;
8+
use Brick\Money\Currency;
9+
use Brick\Money\CurrencyConverter;
10+
use Brick\Money\ExchangeRateProvider\BaseCurrencyProvider;
11+
use Brick\Money\ExchangeRateProvider\ConfigurableProvider;
12+
use Brick\Money\Money;
713
use Carbon\Carbon;
814

915
class Forex
@@ -96,4 +102,38 @@ public function getClient(): ForexClient
96102
{
97103
return $this->client;
98104
}
105+
106+
public function convert(
107+
Money $money,
108+
string|Currency $currency,
109+
RoundingMode $roundingMode = RoundingMode::HALF_UP,
110+
?Carbon $date = null,
111+
): Money {
112+
113+
$currency = is_string($currency) ? $currency : $currency->getCurrencyCode();
114+
115+
if ($money->getCurrency()->is($currency)) {
116+
return $money;
117+
}
118+
119+
$rates = $date ? $this->rates($date, $currency) : $this->latest($currency);
120+
121+
$provider = new BaseCurrencyProvider(
122+
provider: (new ConfigurableProvider)->setExchangeRate(
123+
$money->getCurrency()->getCurrencyCode(),
124+
$currency,
125+
$rates[$currency]
126+
),
127+
baseCurrencyCode: $money->getCurrency()->getCurrencyCode()
128+
);
129+
130+
$converter = new CurrencyConverter($provider);
131+
132+
return $converter->convert(
133+
$money,
134+
$currency,
135+
roundingMode: $roundingMode
136+
);
137+
138+
}
99139
}

tests/ExampleTest.php

Lines changed: 0 additions & 7 deletions
This file was deleted.

tests/Fixtures/Saloon/exchange-rates-api/latest.json

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"statusCode": 200,
3+
"headers": {
4+
"Date": "Wed, 30 Apr 2025 18:14:19 GMT",
5+
"Content-Type": "application\/json",
6+
"Transfer-Encoding": "chunked",
7+
"Connection": "keep-alive",
8+
"access-control-allow-origin": "*",
9+
"Cache-Control": "public, max-age=3600",
10+
"x-content-type-options": "NOSNIFF",
11+
"x-frame-options": "SAMEORIGIN",
12+
"Last-Modified": "Wed, 30 Apr 2025 16:54:40 GMT",
13+
"CF-Cache-Status": "HIT",
14+
"Age": "2634",
15+
"Report-To": "{\"endpoints\":[{\"url\":\"https:\\\/\\\/a.nel.cloudflare.com\\\/report\\\/v4?s=3%2BYMuaC86YCcmFTGXoi6Zu0MevtnVt%2BJSWCKOokyUXHTYhATOE2krcER6gWiCs7Uw5UhV8BjrQpyNYoMOHs66jIAyXvqfr%2FRhP%2FLQdKlwMOXXwVp4zW318NepOaLx%2BkgXRrACQq0gGicbeFvyw%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}",
16+
"NEL": "{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}",
17+
"Server": "cloudflare",
18+
"CF-RAY": "938904a33ebd76f0-LHR",
19+
"server-timing": "cfL4;desc=\"?proto=TCP&rtt=77344&min_rtt=77028&rtt_var=22213&sent=7&recv=9&lost=0&retrans=0&sent_bytes=3925&recv_bytes=1810&delivery_rate=66750&cwnd=253&unsent_bytes=0&cid=b58add9ca1c81ecf&ts=113&x=0\""
20+
},
21+
"data": "{\"result\":\"success\",\"provider\":\"https:\/\/www.exchangerate-api.com\",\"documentation\":\"https:\/\/www.exchangerate-api.com\/docs\/free\",\"terms_of_use\":\"https:\/\/www.exchangerate-api.com\/terms\",\"time_last_update_unix\":1745971351,\"time_last_update_utc\":\"Wed, 30 Apr 2025 00:02:31 +0000\",\"time_next_update_unix\":1746059261,\"time_next_update_utc\":\"Thu, 01 May 2025 00:27:41 +0000\",\"time_eol_unix\":0,\"base_code\":\"USD\",\"rates\":{\"USD\":1,\"AED\":3.6725,\"AFN\":70.95836,\"ALL\":86.781974,\"AMD\":389.902071,\"ANG\":1.79,\"AOA\":918.242865,\"ARS\":1170.67,\"AUD\":1.564538,\"AWG\":1.79,\"AZN\":1.700519,\"BAM\":1.717355,\"BBD\":2,\"BDT\":121.500036,\"BGN\":1.71761,\"BHD\":0.376,\"BIF\":2954.238265,\"BMD\":1,\"BND\":1.30854,\"BOB\":6.917642,\"BRL\":5.654984,\"BSD\":1,\"BTN\":85.218352,\"BWP\":13.70413,\"BYN\":3.052413,\"BZD\":2,\"CAD\":1.383898,\"CDF\":2882.821528,\"CHF\":0.824097,\"CLP\":943.679514,\"CNY\":7.27428,\"COP\":4210.863097,\"CRC\":504.954335,\"CUP\":24,\"CVE\":96.820374,\"CZK\":21.902743,\"DJF\":177.721,\"DKK\":6.55238,\"DOP\":58.849459,\"DZD\":132.397288,\"EGP\":50.801637,\"ERN\":15,\"ETB\":132.338319,\"EUR\":0.87807,\"FJD\":2.252843,\"FKP\":0.74606,\"FOK\":6.552179,\"GBP\":0.746061,\"GEL\":2.749737,\"GGP\":0.74606,\"GHS\":14.340327,\"GIP\":0.74606,\"GMD\":72.700014,\"GNF\":8698.170261,\"GTQ\":7.701682,\"GYD\":209.68957,\"HKD\":7.758339,\"HNL\":25.92619,\"HRK\":6.615817,\"HTG\":130.664153,\"HUF\":355.071344,\"IDR\":16731.457786,\"ILS\":3.623992,\"IMP\":0.74606,\"INR\":85.218447,\"IQD\":1308.719495,\"IRR\":41991.816131,\"ISK\":128.346259,\"JEP\":0.74606,\"JMD\":158.411928,\"JOD\":0.709,\"JPY\":142.324599,\"KES\":129.292345,\"KGS\":87.093523,\"KHR\":4026.795543,\"KID\":1.564972,\"KMF\":431.982057,\"KRW\":1433.503978,\"KWD\":0.306408,\"KYD\":0.833333,\"KZT\":512.103058,\"LAK\":21704.102867,\"LBP\":89500,\"LKR\":299.341271,\"LRD\":199.886111,\"LSL\":18.544097,\"LYD\":5.466531,\"MAD\":9.260138,\"MDL\":17.15025,\"MGA\":4505.466407,\"MKD\":54.237907,\"MMK\":2098.853267,\"MNT\":3581.085356,\"MOP\":7.99109,\"MRU\":39.740795,\"MUR\":45.051653,\"MVR\":15.444373,\"MWK\":1741.606043,\"MXN\":19.572566,\"MYR\":4.32765,\"MZN\":63.78196,\"NAD\":18.544097,\"NGN\":1601.178198,\"NIO\":36.791363,\"NOK\":10.369369,\"NPR\":136.349363,\"NZD\":1.683584,\"OMR\":0.384497,\"PAB\":1,\"PEN\":3.667201,\"PGK\":4.102792,\"PHP\":56.086682,\"PKR\":281.14514,\"PLN\":3.749038,\"PYG\":8026.098846,\"QAR\":3.64,\"RON\":4.371332,\"RSD\":102.914413,\"RUB\":81.934897,\"RWF\":1451.628705,\"SAR\":3.75,\"SBD\":8.550346,\"SCR\":14.633521,\"SDG\":460.924881,\"SEK\":9.634203,\"SGD\":1.30854,\"SHP\":0.74606,\"SLE\":22.6844,\"SLL\":22684.400139,\"SOS\":571.318515,\"SRD\":36.692335,\"SSP\":4594.846713,\"STN\":21.512712,\"SYP\":12884.774625,\"SZL\":18.544097,\"THB\":33.410303,\"TJS\":10.746862,\"TMT\":3.499564,\"TND\":2.979248,\"TOP\":2.35541,\"TRY\":38.51759,\"TTD\":6.742504,\"TVD\":1.564972,\"TWD\":32.21244,\"TZS\":2687.385631,\"UAH\":41.560412,\"UGX\":3661.325882,\"UYU\":42.028172,\"UZS\":12935.074414,\"VES\":86.8465,\"VND\":26020.988733,\"VUV\":120.688005,\"WST\":2.75839,\"XAF\":575.976077,\"XCD\":2.7,\"XCG\":1.79,\"XDR\":0.737159,\"XOF\":575.976077,\"XPF\":104.781834,\"YER\":245.118425,\"ZAR\":18.544104,\"ZMW\":28.198324,\"ZWL\":26.8115}}"
22+
}

tests/ForexTest.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,32 @@
22

33
declare(strict_types=1);
44

5+
use Brick\Money\Money;
56
use Elegantly\Forex\Facades\Forex;
67

7-
it('can query forex', function () {
8-
$rates = Forex::get('USD');
8+
it('can query forex latest rates', function () {
9+
10+
$rates = Forex::latest('USD');
911

1012
expect($rates)
1113
->toBeArray()
1214
->toHaveKey('EUR');
1315

1416
expect((float) $rates['USD'])->toBe(1.0);
1517

16-
expect(Forex::getRates())
17-
->toHaveKey('USD');
1818
});
19+
20+
it('can convert money to another currency', function ($money, $expected) {
21+
22+
$converted = Forex::convert(
23+
$money,
24+
$expected->getCurrency(),
25+
);
26+
27+
expect((string) $converted)->toBe((string) $expected);
28+
29+
})->with([
30+
[Money::of(100, 'USD'), Money::of(100, 'USD')],
31+
[Money::of(100, 'USD'), Money::of(87.81, 'EUR')],
32+
[Money::of(100, 'USD'), Money::of(74.61, 'GBP')],
33+
]);

tests/Pest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
->beforeEach(function () {
2020
MockClient::destroyGlobal();
2121
MockClient::global([
22-
LatestRequest::class => MockResponse::fixture('exchange-rates-api/latest'),
22+
LatestRequest::class => MockResponse::fixture('exchangerate-api-free/latest'),
2323
]);
2424
})
2525
->in(__DIR__);

tests/TestCase.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,5 @@ protected function getPackageProviders($app)
2929
public function getEnvironmentSetUp($app)
3030
{
3131
config()->set('database.default', 'testing');
32-
33-
/*
34-
$migration = include __DIR__.'/../database/migrations/create_laravel-forex_table.php.stub';
35-
$migration->up();
36-
*/
3732
}
3833
}

0 commit comments

Comments
 (0)