mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-25 14:58:40 +00:00
Currencies can now be enabled and disabled.
This commit is contained in:
@@ -90,7 +90,7 @@ class CurrencyController extends Controller
|
||||
// access denied:
|
||||
throw new FireflyException('No access to method, user is not owner.'); // @codeCoverageIgnore
|
||||
}
|
||||
if (!$this->repository->canDeleteCurrency($currency)) {
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
throw new FireflyException('No access to method, currency is in use.'); // @codeCoverageIgnore
|
||||
}
|
||||
$this->repository->destroy($currency);
|
||||
@@ -108,7 +108,7 @@ class CurrencyController extends Controller
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$collection = $this->repository->get();
|
||||
$collection = $this->repository->getAll();
|
||||
$count = $collection->count();
|
||||
// slice them:
|
||||
$currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
@@ -53,6 +53,7 @@ class CurrencyRequest extends Request
|
||||
'symbol' => $this->string('symbol'),
|
||||
'decimal_places' => $this->integer('decimal_places'),
|
||||
'default' => $this->boolean('default'),
|
||||
'enabled' => $this->boolean('enabled'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -68,7 +69,9 @@ class CurrencyRequest extends Request
|
||||
'code' => 'required|between:3,3|unique:transaction_currencies,code',
|
||||
'symbol' => 'required|between:1,5|unique:transaction_currencies,symbol',
|
||||
'decimal_places' => 'required|between:0,20|numeric|min:0|max:20',
|
||||
'enabled' => 'required|boolean',
|
||||
'default' => 'boolean',
|
||||
|
||||
];
|
||||
|
||||
switch ($this->method()) {
|
||||
|
@@ -61,6 +61,7 @@ class TransactionCurrencyFactory
|
||||
'code' => $data['code'],
|
||||
'symbol' => $data['symbol'],
|
||||
'decimal_places' => $data['decimal_places'],
|
||||
'enabled' => $data['enabled'],
|
||||
]
|
||||
);
|
||||
} catch (QueryException $e) {
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Requests\CurrencyFormRequest;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
@@ -106,12 +107,12 @@ class CurrencyController extends Controller
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
|
||||
$this->repository->enable($currency);
|
||||
$request->session()->flash('success', (string)trans('firefly.new_default_currency', ['name' => $currency->name]));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a currency.
|
||||
*
|
||||
@@ -132,7 +133,7 @@ class CurrencyController extends Controller
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
if (!$this->repository->canDeleteCurrency($currency)) {
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
$request->session()->flash('error', (string)trans('firefly.cannot_delete_currency', ['name' => $currency->name]));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
@@ -145,7 +146,6 @@ class CurrencyController extends Controller
|
||||
return view('currencies.delete', compact('currency', 'subTitle'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destroys a currency.
|
||||
*
|
||||
@@ -166,7 +166,7 @@ class CurrencyController extends Controller
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
if (!$this->repository->canDeleteCurrency($currency)) {
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
$request->session()->flash('error', (string)trans('firefly.cannot_delete_currency', ['name' => $currency->name]));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
@@ -178,6 +178,49 @@ class CurrencyController extends Controller
|
||||
return redirect($this->getPreviousUri('currencies.delete.uri'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function disableCurrency(Request $request, TransactionCurrency $currency)
|
||||
{
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => env('SITE_OWNER')]));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
$request->session()->flash('error', (string)trans('firefly.cannot_disable_currency', ['name' => $currency->name]));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
|
||||
$this->repository->disable($currency);
|
||||
|
||||
// if no currencies are enabled, enable the first one in the DB (usually the EUR)
|
||||
if (0 === $this->repository->get()->count()) {
|
||||
$first = $this->repository->getAll()->first();
|
||||
if (null === $first) {
|
||||
throw new FireflyException('No currencies found.');
|
||||
}
|
||||
$this->repository->enable($first);
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
}
|
||||
|
||||
session()->flash('success', (string)trans('firefly.currency_is_now_disabled', ['name' => $currency->name]));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a currency.
|
||||
@@ -203,6 +246,15 @@ class CurrencyController extends Controller
|
||||
$subTitle = (string)trans('breadcrumbs.edit_currency', ['name' => $currency->name]);
|
||||
$currency->symbol = htmlentities($currency->symbol);
|
||||
|
||||
// code to handle active-checkboxes
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
$preFilled = [
|
||||
'enabled' => $hasOldInput ? (bool)$request->old('enabled') : $currency->enabled,
|
||||
];
|
||||
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('currencies.edit.fromUpdate')) {
|
||||
$this->rememberPreviousUri('currencies.edit.uri');
|
||||
@@ -212,6 +264,21 @@ class CurrencyController extends Controller
|
||||
return view('currencies.edit', compact('currency', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function enableCurrency(TransactionCurrency $currency)
|
||||
{
|
||||
app('preferences')->mark();
|
||||
|
||||
$this->repository->enable($currency);
|
||||
session()->flash('success', (string)trans('firefly.currency_is_now_enabled', ['name' => $currency->name]));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show overview of currencies.
|
||||
*
|
||||
@@ -225,11 +292,13 @@ class CurrencyController extends Controller
|
||||
$user = auth()->user();
|
||||
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
|
||||
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
|
||||
$collection = $this->repository->get();
|
||||
$collection = $this->repository->getAll();
|
||||
$total = $collection->count();
|
||||
$collection = $collection->sortBy(
|
||||
function (TransactionCurrency $currency) {
|
||||
return $currency->name;
|
||||
$intEnabled = $currency->enabled ? 0 : 1;
|
||||
|
||||
return $intEnabled . $currency->name;
|
||||
}
|
||||
);
|
||||
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
||||
@@ -268,9 +337,10 @@ class CurrencyController extends Controller
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
$data = $request->getCurrencyData();
|
||||
$currency = $this->repository->store($data);
|
||||
$redirect = redirect($this->getPreviousUri('currencies.create.uri'));
|
||||
$data = $request->getCurrencyData();
|
||||
$data['enabled'] = true;
|
||||
$currency = $this->repository->store($data);
|
||||
$redirect = redirect($this->getPreviousUri('currencies.create.uri'));
|
||||
if (null !== $currency) {
|
||||
$request->session()->flash('success', (string)trans('firefly.created_currency', ['name' => $currency->name]));
|
||||
|
||||
|
@@ -100,6 +100,7 @@ class NewUserController extends Controller
|
||||
if (null === $currency) {
|
||||
$currency = $currencyRepository->findByCodeNull('EUR');
|
||||
}
|
||||
$currencyRepository->enable($currency);
|
||||
|
||||
$this->createAssetAccount($request, $currency); // create normal asset account
|
||||
$this->createSavingsAccount($request, $currency, $language); // create savings account
|
||||
|
@@ -52,6 +52,7 @@ class CurrencyFormRequest extends Request
|
||||
'code' => $this->string('code'),
|
||||
'symbol' => $this->string('symbol'),
|
||||
'decimal_places' => $this->integer('decimal_places'),
|
||||
'enabled' => $this->boolean('enabled'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -68,6 +69,7 @@ class CurrencyFormRequest extends Request
|
||||
'code' => 'required|min:3|max:3|unique:transaction_currencies,code',
|
||||
'symbol' => 'required|min:1|max:8|unique:transaction_currencies,symbol',
|
||||
'decimal_places' => 'required|min:0|max:12|numeric',
|
||||
'enabled' => 'in:0,1',
|
||||
];
|
||||
|
||||
/** @var TransactionCurrency $currency */
|
||||
@@ -79,6 +81,7 @@ class CurrencyFormRequest extends Request
|
||||
'code' => 'required|min:3|max:3',
|
||||
'symbol' => 'required|min:1|max:8',
|
||||
'decimal_places' => 'required|min:0|max:12|numeric',
|
||||
'enabled' => 'in:0,1',
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
* @property int $decimal_places
|
||||
* @property int $id
|
||||
* @property string name
|
||||
* @property bool $enabled
|
||||
*
|
||||
*/
|
||||
class TransactionCurrency extends Model
|
||||
@@ -52,9 +53,10 @@ class TransactionCurrency extends Model
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'decimal_places' => 'int',
|
||||
'enabled' => 'bool',
|
||||
];
|
||||
/** @var array Fields that can be filled */
|
||||
protected $fillable = ['name', 'code', 'symbol', 'decimal_places'];
|
||||
protected $fillable = ['name', 'code', 'symbol', 'decimal_places', 'enabled'];
|
||||
|
||||
/**
|
||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||
@@ -84,4 +86,13 @@ class TransactionCurrency extends Model
|
||||
{
|
||||
return $this->hasMany(TransactionJournal::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @return HasMany
|
||||
*/
|
||||
public function transactions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Transaction::class);
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ namespace FireflyIII\Repositories\Currency;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Factory\TransactionCurrencyFactory;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
@@ -55,39 +56,62 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return bool
|
||||
* @return int
|
||||
*/
|
||||
public function canDeleteCurrency(TransactionCurrency $currency): bool
|
||||
public function countJournals(TransactionCurrency $currency): int
|
||||
{
|
||||
if ($this->countJournals($currency) > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// is the only currency left
|
||||
if (1 === $this->get()->count()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// is the default currency for the user or the system
|
||||
$defaultCode = app('preferences')->getForUser($this->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data;
|
||||
if ($currency->code === $defaultCode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// is the default currency for the system
|
||||
$defaultSystemCode = config('firefly.default_currency', 'EUR');
|
||||
|
||||
return !($currency->code === $defaultSystemCode);
|
||||
return $currency->transactions()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return int
|
||||
* @return bool
|
||||
*/
|
||||
public function countJournals(TransactionCurrency $currency): int
|
||||
public function currencyInUse(TransactionCurrency $currency): bool
|
||||
{
|
||||
return $currency->transactionJournals()->count();
|
||||
Log::debug(sprintf('Now in currencyInUse() for #%d ("%s")', $currency->id, $currency->code));
|
||||
$countJournals = $this->countJournals($currency);
|
||||
if ($countJournals > 0) {
|
||||
Log::debug(sprintf('Count journals is %d, return true.', $countJournals));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// is the only currency left
|
||||
if (1 === $this->getAll()->count()) {
|
||||
Log::debug('Is the last currency in the system, return true. ', $countJournals);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// is being used in accounts:
|
||||
$meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((string)$currency->id))->count();
|
||||
if ($meta > 0) {
|
||||
Log::debug(sprintf('Used in %d accounts as currency_id, return true. ', $meta));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// is the default currency for the user or the system
|
||||
$defaultCode = app('preferences')->getForUser($this->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data;
|
||||
if ($currency->code === $defaultCode) {
|
||||
Log::debug('Is the default currency of the user, return true.');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// is the default currency for the system
|
||||
$defaultSystemCode = config('firefly.default_currency', 'EUR');
|
||||
$result = $currency->code === $defaultSystemCode;
|
||||
if (true === $result) {
|
||||
Log::debug('Is the default currency of the SYSTEM, return true.');
|
||||
|
||||
return true;
|
||||
}
|
||||
Log::debug('Currency is not used, return false.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,12 +134,58 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables a currency
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*/
|
||||
public function disable(TransactionCurrency $currency): void
|
||||
{
|
||||
$currency->enabled = false;
|
||||
$currency->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
* Enables a currency
|
||||
*/
|
||||
public function enable(TransactionCurrency $currency): void
|
||||
{
|
||||
$currency->enabled = true;
|
||||
$currency->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find by ID, return NULL if not found.
|
||||
*
|
||||
* @param int $currencyId
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
public function find(int $currencyId): ?TransactionCurrency
|
||||
{
|
||||
return TransactionCurrency::find($currencyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find by currency code, return NULL if unfound.
|
||||
*
|
||||
* @param string $currencyCode
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
public function findByCode(string $currencyCode): ?TransactionCurrency
|
||||
{
|
||||
return TransactionCurrency::where('code', $currencyCode)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find by currency code, return NULL if unfound.
|
||||
* Used in Import Currency!
|
||||
*
|
||||
* @param string $currencyCode
|
||||
*
|
||||
* @deprecated
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
public function findByCodeNull(string $currencyCode): ?TransactionCurrency
|
||||
@@ -123,12 +193,25 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
return TransactionCurrency::where('code', $currencyCode)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find by currency name.
|
||||
*
|
||||
* @param string $currencyName
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findByName(string $currencyName): ?TransactionCurrency
|
||||
{
|
||||
return TransactionCurrency::whereName($currencyName)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find by currency name or return null.
|
||||
* Used in Import Currency!
|
||||
*
|
||||
* @param string $currencyName
|
||||
*
|
||||
* @deprecated
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findByNameNull(string $currencyName): ?TransactionCurrency
|
||||
@@ -136,12 +219,25 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
return TransactionCurrency::whereName($currencyName)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find by currency symbol.
|
||||
*
|
||||
* @param string $currencySymbol
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findBySymbol(string $currencySymbol): ?TransactionCurrency
|
||||
{
|
||||
return TransactionCurrency::whereSymbol($currencySymbol)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find by currency symbol or return NULL
|
||||
* Used in Import Currency!
|
||||
*
|
||||
* @param string $currencySymbol
|
||||
*
|
||||
* @deprecated
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findBySymbolNull(string $currencySymbol): ?TransactionCurrency
|
||||
@@ -155,6 +251,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
*
|
||||
* @param int $currencyId
|
||||
*
|
||||
* @deprecated
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
public function findNull(int $currencyId): ?TransactionCurrency
|
||||
@@ -166,6 +263,14 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
* @return Collection
|
||||
*/
|
||||
public function get(): Collection
|
||||
{
|
||||
return TransactionCurrency::where('enabled', true)->orderBy('code', 'ASC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAll(): Collection
|
||||
{
|
||||
return TransactionCurrency::orderBy('code', 'ASC')->get();
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ interface CurrencyRepositoryInterface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canDeleteCurrency(TransactionCurrency $currency): bool;
|
||||
public function currencyInUse(TransactionCurrency $currency): bool;
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
@@ -55,6 +55,38 @@ interface CurrencyRepositoryInterface
|
||||
*/
|
||||
public function destroy(TransactionCurrency $currency): bool;
|
||||
|
||||
/**
|
||||
* Disables a currency
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*/
|
||||
public function disable(TransactionCurrency $currency): void;
|
||||
|
||||
/**
|
||||
* Enables a currency
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*/
|
||||
public function enable(TransactionCurrency $currency): void;
|
||||
|
||||
/**
|
||||
* Find by ID, return NULL if not found.
|
||||
*
|
||||
* @param int $currencyId
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
public function find(int $currencyId): ?TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency code, return NULL if unfound.
|
||||
*
|
||||
* @param string $currencyCode
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
public function findByCode(string $currencyCode): ?TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency code, return NULL if unfound.
|
||||
*
|
||||
@@ -64,6 +96,15 @@ interface CurrencyRepositoryInterface
|
||||
*/
|
||||
public function findByCodeNull(string $currencyCode): ?TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency name.
|
||||
*
|
||||
* @param string $currencyName
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findByName(string $currencyName): ?TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency name.
|
||||
*
|
||||
@@ -73,6 +114,15 @@ interface CurrencyRepositoryInterface
|
||||
*/
|
||||
public function findByNameNull(string $currencyName): ?TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency symbol.
|
||||
*
|
||||
* @param string $currencySymbol
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findBySymbol(string $currencySymbol): ?TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency symbol.
|
||||
*
|
||||
@@ -96,6 +146,11 @@ interface CurrencyRepositoryInterface
|
||||
*/
|
||||
public function get(): Collection;
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAll(): Collection;
|
||||
|
||||
/**
|
||||
* @param array $ids
|
||||
*
|
||||
|
@@ -25,6 +25,7 @@ namespace FireflyIII\Services\Internal\Update;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class CurrencyUpdateService
|
||||
*/
|
||||
@@ -51,6 +52,7 @@ class CurrencyUpdateService
|
||||
$currency->code = $data['code'];
|
||||
$currency->symbol = $data['symbol'];
|
||||
$currency->name = $data['name'];
|
||||
$currency->enabled = $data['enabled'];
|
||||
$currency->decimal_places = $data['decimal_places'];
|
||||
$currency->save();
|
||||
|
||||
|
@@ -159,6 +159,14 @@ class Amount
|
||||
return TransactionCurrency::orderBy('code', 'ASC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCurrencies(): Collection
|
||||
{
|
||||
return TransactionCurrency::where('enabled', true)->orderBy('code', 'ASC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@@ -278,6 +278,19 @@ class ExpandedForm
|
||||
return $this->currencyField($name, 'balance', $value, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function balanceAll(string $name, $value = null, array $options = null): string
|
||||
{
|
||||
return $this->allCurrencyField($name, 'balance', $value, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param int $value
|
||||
@@ -913,6 +926,60 @@ class ExpandedForm
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
protected function currencyField(string $name, string $view, $value = null, array $options = null): string
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = 'any';
|
||||
$defaultCurrency = $options['currency'] ?? Amt::getDefaultCurrency();
|
||||
/** @var Collection $currencies */
|
||||
$currencies = app('amount')->getCurrencies();
|
||||
unset($options['currency'], $options['placeholder']);
|
||||
|
||||
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
|
||||
$preFilled = session('preFilled');
|
||||
$key = 'amount_currency_id_' . $name;
|
||||
$sentCurrencyId = isset($preFilled[$key]) ? (int)$preFilled[$key] : $defaultCurrency->id;
|
||||
|
||||
Log::debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
|
||||
|
||||
// find this currency in set of currencies:
|
||||
foreach ($currencies as $currency) {
|
||||
if ($currency->id === $sentCurrencyId) {
|
||||
$defaultCurrency = $currency;
|
||||
Log::debug(sprintf('default currency is now %s', $defaultCurrency->code));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure value is formatted nicely:
|
||||
if (null !== $value && '' !== $value) {
|
||||
$value = round($value, $defaultCurrency->decimal_places);
|
||||
}
|
||||
try {
|
||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
Log::debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
|
||||
$html = 'Could not render currencyField.';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $view
|
||||
* @param mixed $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
protected function allCurrencyField(string $name, string $view, $value = null, array $options = null): string
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
|
@@ -33,6 +33,7 @@ use Illuminate\Support\Facades\Facade;
|
||||
*
|
||||
* @method string formatAnything(TransactionCurrency $format, string $amount, bool $coloured = true)
|
||||
* @method Collection getAllCurrencies()
|
||||
* @method Collection getCurrencies()
|
||||
* @method string getCurrencyCode()
|
||||
* @method string getCurrencySymbol()
|
||||
* @method TransactionCurrency getDefaultCurrency()
|
||||
|
@@ -83,6 +83,7 @@ class CurrencyTransformer extends TransformerAbstract
|
||||
'symbol' => $currency->symbol,
|
||||
'decimal_places' => (int)$currency->decimal_places,
|
||||
'default' => $isDefault,
|
||||
'enabled' => $currency->enabled,
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'self',
|
||||
|
@@ -165,7 +165,8 @@ return [
|
||||
// currencies: index, create
|
||||
'currencies_index' => [
|
||||
'intro' => [],
|
||||
'default' => ['element' => '.defaultCurrency'],
|
||||
'default' => ['element' => '#default-currency'],
|
||||
'buttons' => ['element' => '.buttons',]
|
||||
],
|
||||
'currencies_create' => [
|
||||
'code' => ['element' => '#ffInput_code',],
|
||||
|
@@ -188,7 +188,7 @@ return [
|
||||
'is_safe' => ['date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location', 'file',
|
||||
'staticText', 'password', 'nonSelectableAmount', 'number', 'assetAccountList', 'amountNoCurrency', 'currencyList',
|
||||
'ruleGroupList', 'assetAccountCheckList', 'ruleGroupListWithEmpty', 'piggyBankList', 'currencyListEmpty',
|
||||
'activeAssetAccountList', 'percentage', 'activeLongAccountList', 'longAccountList',],],
|
||||
'activeAssetAccountList', 'percentage', 'activeLongAccountList', 'longAccountList','balanceAll'],],
|
||||
'Form' => ['is_safe' => ['input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea', 'file',],
|
||||
],
|
||||
],
|
||||
|
34
database/migrations/2018_11_06_172532_changes_for_v479.php
Normal file
34
database/migrations/2018_11_06_172532_changes_for_v479.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
/**
|
||||
* Class ChangesForV479
|
||||
*/
|
||||
class ChangesForV479 extends Migration
|
||||
{
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table(
|
||||
'transaction_currencies',
|
||||
function (Blueprint $table) {
|
||||
$table->boolean('enabled')->default(0)->after('deleted_at');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@@ -32,7 +32,7 @@ class TransactionCurrencySeeder extends Seeder
|
||||
{
|
||||
$currencies = [];
|
||||
// european currencies
|
||||
$currencies[] = ['code' => 'EUR', 'name' => 'Euro', 'symbol' => '€', 'decimal_places' => 2];
|
||||
$currencies[] = ['code' => 'EUR', 'name' => 'Euro', 'symbol' => '€', 'decimal_places' => 2,'enabled' => 1];
|
||||
$currencies[] = ['code' => 'HUF', 'name' => 'Hungarian forint', 'symbol' => 'Ft', 'decimal_places' => 2];
|
||||
$currencies[] = ['code' => 'GBP', 'name' => 'British Pound', 'symbol' => '£', 'decimal_places' => 2];
|
||||
$currencies[] = ['code' => 'UAH', 'name' => 'Ukrainian hryvnia', 'symbol' => '₴', 'decimal_places' => 2];
|
||||
|
@@ -624,14 +624,21 @@ return [
|
||||
'update_currency' => 'Update currency',
|
||||
'new_default_currency' => ':name is now the default currency.',
|
||||
'cannot_delete_currency' => 'Cannot delete :name because it is still in use.',
|
||||
'cannot_disable_currency' => 'Cannot disable :name because it is still in use.',
|
||||
'deleted_currency' => 'Currency :name deleted',
|
||||
'created_currency' => 'Currency :name created',
|
||||
'could_not_store_currency' => 'Could not store the new currency.',
|
||||
'updated_currency' => 'Currency :name updated',
|
||||
'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.',
|
||||
'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.',
|
||||
'make_default_currency' => 'make default',
|
||||
'make_default_currency' => 'Make default',
|
||||
'default_currency' => 'default',
|
||||
'currency_is_disabled' => 'Disabled',
|
||||
'enable_currency' => 'Enable',
|
||||
'disable_currency' => 'Disable',
|
||||
'currencies_default_disabled' => 'Most of these currencies are disabled by default. To use them, you must enable them first.',
|
||||
'currency_is_now_enabled' => 'Currency ":name" has been enabled',
|
||||
'currency_is_now_disabled' => 'Currency ":name" has been disabled',
|
||||
|
||||
// forms:
|
||||
'mandatoryFields' => 'Mandatory fields',
|
||||
|
@@ -30,6 +30,7 @@ return [
|
||||
'credit_card_limit' => 'Credit card limit',
|
||||
'automatch' => 'Match automatically',
|
||||
'skip' => 'Skip',
|
||||
'enabled' => 'Enabled',
|
||||
'name' => 'Name',
|
||||
'active' => 'Active',
|
||||
'amount_min' => 'Minimum amount',
|
||||
|
@@ -130,7 +130,8 @@ return [
|
||||
|
||||
// currencies
|
||||
'currencies_index_intro' => 'Firefly III supports multiple currencies, which you can change on this page.',
|
||||
'currencies_index_default' => 'Firefly III has one default currency. You can always switch of course using these buttons.',
|
||||
'currencies_index_default' => 'Firefly III has one default currency.',
|
||||
'currencies_index_buttons' => 'Use these buttons to change the default currency or enable other currencies.',
|
||||
|
||||
// create currency
|
||||
'currencies_create_code' => 'This code should be ISO compliant (Google it for your new currency).',
|
||||
|
@@ -19,6 +19,7 @@
|
||||
{{ ExpandedForm.text('symbol',null,{'maxlength' : 8}) }}
|
||||
{{ ExpandedForm.text('code',null,{'maxlength' : 3}) }}
|
||||
{{ ExpandedForm.integer('decimal_places',null,{'maxlength' : 2,'min': 0,'max': 12}) }}
|
||||
{{ ExpandedForm.checkbox('enabled',null) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -10,11 +10,15 @@
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'currencies'|_ }}</h3>
|
||||
<a class="btn btn-success pull-right" href="{{ route('currencies.create') }}">{{ 'create_currency'|_ }}</a>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<p class="text-info">
|
||||
{{ 'currencies_intro'|_ }}
|
||||
</p>
|
||||
<p class="text-info">
|
||||
{{ 'currencies_default_disabled'|_ }}
|
||||
</p>
|
||||
{% if currencies|length > 0 %}
|
||||
<div style="padding-left:8px;">
|
||||
{{ currencies.render|raw }}
|
||||
@@ -41,15 +45,42 @@
|
||||
</div>
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>{{ currency.name }} ({{ currency.code }}) ({{ currency.symbol|raw }})</td>
|
||||
<td>{{ currency.decimal_places }}</td>
|
||||
<td class="defaultCurrency">
|
||||
{% if currency.id == defaultCurrency.id %}
|
||||
<span class="label label-success">{{ 'default_currency'|_ }}</span>
|
||||
{% else %}
|
||||
<a class="btn btn-info btn-xs"
|
||||
href="{{ route('currencies.default',currency.id) }}">{{ 'make_default_currency'|_ }}</a>
|
||||
<td>
|
||||
{% if currency.enabled == false %}
|
||||
<span class="text-muted">
|
||||
{% endif %}
|
||||
{{ currency.name }} ({{ currency.code }}) ({{ currency.symbol|raw }})
|
||||
{% if currency.id == defaultCurrency.id %}
|
||||
<span class="label label-success" id="default-currency">{{ 'default_currency'|_ }}</span>
|
||||
{% endif %}
|
||||
{% if currency.enabled == false %}
|
||||
</span>
|
||||
<br><small class="text-danger">{{ 'currency_is_disabled'|_ }}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td>{{ currency.decimal_places }}</td>
|
||||
<td class="buttons">
|
||||
<div class="btn-group">
|
||||
{% if currency.id != defaultCurrency.id %}
|
||||
<a class="btn btn-default"
|
||||
href="{{ route('currencies.default',currency.id) }}">
|
||||
<i class="fa fa-fw fa-star"></i>
|
||||
{{ 'make_default_currency'|_ }}</a>
|
||||
{% endif %}
|
||||
{% if currency.enabled %}
|
||||
<a class="btn btn-default"
|
||||
href="{{ route('currencies.disable',currency.id) }}">
|
||||
<i class="fa fa-fw fa-square-o"></i>
|
||||
{{ 'disable_currency'|_ }}</a>
|
||||
{% endif %}
|
||||
{% if not currency.enabled %}
|
||||
<a class="btn btn-default"
|
||||
href="{{ route('currencies.enable',currency.id) }}">
|
||||
<i class="fa fa-fw fa-check-square-o"></i>
|
||||
{{ 'enable_currency'|_ }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@@ -24,7 +24,7 @@
|
||||
{{ 'to_get_started'|_ }}
|
||||
</p>
|
||||
{{ ExpandedForm.text('bank_name') }}
|
||||
{{ ExpandedForm.balance('bank_balance') }}
|
||||
{{ ExpandedForm.balanceAll('bank_balance') }}
|
||||
|
||||
<p class="text-success">
|
||||
{{ 'currency_not_present'|_ }}
|
||||
|
@@ -273,6 +273,8 @@ Route::group(
|
||||
Route::get('edit/{currency}', ['uses' => 'CurrencyController@edit', 'as' => 'edit']);
|
||||
Route::get('delete/{currency}', ['uses' => 'CurrencyController@delete', 'as' => 'delete']);
|
||||
Route::get('default/{currency}', ['uses' => 'CurrencyController@defaultCurrency', 'as' => 'default']);
|
||||
Route::get('enable/{currency}', ['uses' => 'CurrencyController@enableCurrency', 'as' => 'enable']);
|
||||
Route::get('disable/{currency}', ['uses' => 'CurrencyController@disableCurrency', 'as' => 'disable']);
|
||||
|
||||
Route::post('store', ['uses' => 'CurrencyController@store', 'as' => 'store']);
|
||||
Route::post('update/{currency}', ['uses' => 'CurrencyController@update', 'as' => 'update']);
|
||||
|
Reference in New Issue
Block a user