Skip to content

Commit

Permalink
✨feature: currency conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
ScuffedNewt committed Feb 9, 2024
1 parent 1eac0fb commit 0f89e0a
Show file tree
Hide file tree
Showing 12 changed files with 638 additions and 3 deletions.
2 changes: 2 additions & 0 deletions app/Http/Controllers/Admin/Data/CurrencyController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public function getEditCurrency($id) {

return view('admin.currencies.create_edit_currency', [
'currency' => $currency,
'currencies' => Currency::where('id', '!=', $id)->get()->sortBy('name')->pluck('name', 'id'),
]);
}

Expand All @@ -73,6 +74,7 @@ public function postCreateEditCurrency(Request $request, CurrencyService $servic
'name', 'abbreviation', 'description',
'is_displayed', 'allow_user_to_user', 'allow_user_to_character', 'allow_character_to_user',
'icon', 'image', 'remove_icon', 'remove_image',
'conversion_id', 'rate',
]);
if ($id && $service->updateCurrency(Currency::find($id), $data, Auth::user())) {
flash('Currency updated successfully.')->success();
Expand Down
51 changes: 50 additions & 1 deletion app/Http/Controllers/Users/BankController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public function getIndex() {
return view('home.bank', [
'currencyOptions' => Currency::where('allow_user_to_user', 1)->where('is_user_owned', 1)->whereIn('id', UserCurrency::where('user_id', Auth::user()->id)->pluck('currency_id')->toArray())->orderBy('sort_user', 'DESC')->pluck('name', 'id')->toArray(),
'userOptions' => User::visible()->where('id', '!=', Auth::user()->id)->orderBy('name')->pluck('name', 'id')->toArray(),

// only get currency with currency_conversions relationship
'convertOptions' => Currency::where('is_user_owned', 1)->whereHas('conversions')->orderBy('sort_user', 'DESC')->pluck('name', 'id')->toArray(),
]);
}

Expand All @@ -51,4 +52,52 @@ public function postTransfer(Request $request, CurrencyManager $service) {

return redirect()->back();
}

/**
* Gets the currency conversion form for the user.
*
* @param App\Services\CurrencyManager $service
*
* @return \Illuminate\Http\RedirectResponse
*/
public function getConvertCurrency($id) {
$currency = Currency::where('is_user_owned', 1)->where('id', $id)->first();
$convertOptions = Currency::whereIn('id', $currency->conversions->pluck('conversion_id')->toArray())->orderBy('sort_user', 'DESC')->pluck('name', 'id')->toArray();
return view('home._bank_convert', [
'convertOptions' => $convertOptions,
]);
}

/**
* Gets the currency conversion rate for the user.
*
* @param App\Services\CurrencyManager $service
*
* @return \Illuminate\Http\RedirectResponse
*/
public function getConvertCurrencyRate($currency_id, $conversion_id) {
$currency = Currency::where('is_user_owned', 1)->where('id', $currency_id)->first();

return $currency->conversions()->where('conversion_id', $conversion_id)->first()->ratio();
}

/**
* Converts currency from one type to another.
*
* @param App\Services\CurrencyManager $service
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postConvertCurrency(Request $request, CurrencyManager $service) {
$data = $request->only(['currency_id', 'conversion_id', 'quantity']);
if ($service->convertCurrency(Currency::find($data['currency_id']), Currency::find($data['conversion_id']), $data['quantity'], Auth::user())) {
flash('Currency converted successfully.')->success();
} else {
foreach ($service->errors()->getMessages()['error'] as $error) {
flash($error)->error();
}
}

return redirect()->back();
}
}
14 changes: 14 additions & 0 deletions app/Models/Currency/Currency.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Models\Currency;

use App\Models\Model;
use App\Models\Currency\CurrencyConversion;

class Currency extends Model {
/**
Expand Down Expand Up @@ -49,6 +50,19 @@ class Currency extends Model {
'image' => 'mimes:png',
];

/**********************************************************************************************
RELATIONSHIPS
**********************************************************************************************/

/**
* Get the conversion options for the currency.
*/
public function conversions() {
return $this->hasMany(CurrencyConversion::class, 'currency_id');
}

/**********************************************************************************************
ACCESSORS
Expand Down
254 changes: 254 additions & 0 deletions app/Models/Currency/CurrencyConversion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
<?php

namespace App\Models\Currency;

use App\Models\Model;
use App\Models\Currency\Currency;

class CurrencyConversion extends Model {

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'currency_id', 'conversion_id', 'rate',
];

/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'currency_conversions';
/**
* Validation rules for creation.
*
* @var array
*/
public static $createRules = [
'currency_id' => 'required|exists:currencies,id',
'conversion_id' => 'required|exists:currencies,id',
'rate' => 'required|numeric',
];

/**
* Validation rules for updating.
*
* @var array
*/
public static $updateRules = [
'currency_id' => 'required|exists:currencies,id',
'conversion_id' => 'required|exists:currencies,id',
'rate' => 'required|numeric',
];

/**********************************************************************************************
RELATIONSHIPS
**********************************************************************************************/

/**
* Get the currency that the conversion is for.
*/
public function currency() {
return $this->belongsTo(Currency::class, 'currency_id');
}

/**
* Get the currency that is converted to.
*/
public function convert() {
return $this->belongsTo(Currency::class, 'conversion_id');
}

/**********************************************************************************************
ACCESSORS
**********************************************************************************************/

/**
* Displays the currency as an icon with tooltip.
*
* @return string
*/
public function getDisplayIconAttribute() {
return '<img src="'.$this->currencyIconUrl.'" title="'.$this->name.($this->abbreviation ? ' ('.$this->abbreviation.')' : '').'" data-toggle="tooltip" alt="'.$this->name.'"/>';
}

/**
* Gets the file directory containing the model's image.
*
* @return string
*/
public function getImageDirectoryAttribute() {
return 'images/data/currencies';
}

/**
* Gets the file name of the model's image.
*
* @return string
*/
public function getCurrencyImageFileNameAttribute() {
return $this->hash.$this->id.'-image.png';
}

/**
* Gets the file name of the model's icon image.
*
* @return string
*/
public function getCurrencyIconFileNameAttribute() {
return $this->hash.$this->id.'-icon.png';
}

/**
* Gets the path to the file directory containing the model's image.
*
* @return string
*/
public function getCurrencyImagePathAttribute() {
return public_path($this->imageDirectory);
}

/**
* Gets the path to the file directory containing the model's icon image.
*
* @return string
*/
public function getCurrencyIconPathAttribute() {
return public_path($this->imageDirectory);
}

/**
* Gets the URL of the model's image.
*
* @return string
*/
public function getCurrencyImageUrlAttribute() {
if (!$this->has_image) {
return null;
}

return asset($this->imageDirectory.'/'.$this->currencyImageFileName);
}

/**
* Gets the URL of the model's icon image.
*
* @return string
*/
public function getCurrencyIconUrlAttribute() {
if (!$this->has_icon) {
return null;
}

return asset($this->imageDirectory.'/'.$this->currencyIconFileName);
}

/**********************************************************************************************
ACCESSORS
**********************************************************************************************/

/**
* Displays the model's name, linked to its encyclopedia page.
*
* @return string
*/
public function getDisplayNameAttribute() {
return '<a href="'.$this->url.'" class="display-currency">'.$this->name.'</a>';
}

/**
* Gets the URL of the model's encyclopedia page.
*
* @return string
*/
public function getUrlAttribute() {
return url('world/currencies?name='.$this->name);
}

/**
* Gets the currency's asset type for asset management.
*
* @return string
*/
public function getAssetTypeAttribute() {
return 'currencies';
}

/**
* Gets the admin edit URL.
*
* @return string
*/
public function getAdminUrlAttribute() {
return url('admin/data/currencies/edit/'.$this->id);
}

/**
* Gets the power required to edit this model.
*
* @return string
*/
public function getAdminPowerAttribute() {
return 'edit_data';
}

/**********************************************************************************************
OTHER FUNCTIONS
**********************************************************************************************/

/**
* Displays a given value of the currency with icon, abbreviation or name.
*
* @param mixed $value
*
* @return string
*/
public function display($value) {
$ret = '<span class="display-currency">'.$value.' ';
if ($this->has_icon) {
$ret .= $this->displayIcon;
} elseif ($this->abbreviation) {
$ret .= $this->abbreviation;
} else {
$ret .= $this->name;
}

return $ret.'</span>';
}

/**
* Gets the ratio based on the decimal conversion rate.
*/
public function ratio($return = false) {
$numerator = $this->rate * 100; // Convert rate to avoid floating point issues
$denominator = 100;
$divisor = $this->gcd($numerator, $denominator); // Find GCD to simplify ratio

// Simplify the ratio
$numerator /= $divisor;
$denominator /= $divisor;

if ($return) {
return [$numerator, $denominator];
}
return $numerator . ":" . $denominator;
}

/**
* Gets the greatest common divisor of two numbers.
*/
private function gcd($a, $b) {
return $b ? $this->gcd($b, $a % $b) : $a;
}
}
Loading

0 comments on commit 0f89e0a

Please sign in to comment.