General cleanup and new (incomplete) tests.

This commit is contained in:
James Cole 2015-04-06 09:15:59 +02:00
parent 1035f0e139
commit c907cb4cf1
9 changed files with 385 additions and 171 deletions

View File

@ -17,11 +17,11 @@ use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Navigation;
use Preferences;
@ -46,9 +46,8 @@ class GoogleChartController extends Controller
*/
public function accountBalanceChart(Account $account, GChart $chart)
{
$accountName = iconv('UTF-8', 'ASCII//TRANSLIT', $account->name);
$chart->addColumn('Day of month', 'date');
$chart->addColumn('Balance for ' . $accountName, 'number');
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty(1);
$start = Session::get('start', Carbon::now()->startOfMonth());
@ -73,19 +72,15 @@ class GoogleChartController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allAccountsBalanceChart(GChart $chart)
public function allAccountsBalanceChart(GChart $chart, AccountRepositoryInterface $repository)
{
$chart->addColumn('Day of the month', 'date');
$frontPage = Preferences::get('frontPageAccounts', []);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$accounts = $repository->getFrontpageAccounts($frontPage);
if ($frontPage->data == []) {
$accounts = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
} else {
$accounts = Auth::user()->accounts()->whereIn('id', $frontPage->data)->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
}
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
@ -108,7 +103,7 @@ class GoogleChartController extends Controller
$current->addDay();
}
$chart->generate();
//header('Content-Type: application/json; charset=utf-8');
return Response::json($chart->getData());
}
@ -120,22 +115,16 @@ class GoogleChartController extends Controller
*/
public function allBudgetsAndSpending($year, GChart $chart, BudgetRepositoryInterface $repository)
{
try {
new Carbon('01-01-' . $year);
} catch (Exception $e) {
return view('error')->with('message', 'Invalid year.');
}
$budgets = Auth::user()->budgets()->get();
$budgets->sortBy('name');
$budgets = $repository->getBudgets();
$chart->addColumn('Month', 'date');
foreach ($budgets as $budget) {
$chart->addColumn($budget->name, 'number');
}
$start = Carbon::createFromDate(intval($year), 1, 1);
$end = clone $start;
$end->endOfYear();
while ($start <= $end) {
$row = [clone $start];
foreach ($budgets as $budget) {
@ -146,7 +135,6 @@ class GoogleChartController extends Controller
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
@ -158,73 +146,44 @@ class GoogleChartController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allBudgetsHomeChart(GChart $chart)
public function allBudgetsHomeChart(GChart $chart, BudgetRepositoryInterface $repository)
{
$chart->addColumn('Budget', 'string');
$chart->addColumn('Budgeted', 'number');
$chart->addColumn('Spent', 'number');
$budgets = Auth::user()->budgets()->orderBy('name', 'DESC')->get();
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$budgets = $repository->getBudgets();
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$allEntries = new Collection;
/** @var Budget $budget */
foreach ($budgets as $budget) {
/** @var Collection $repetitions */
$repetitions = LimitRepetition::
leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00'))
->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00'))
->where('budget_limits.budget_id', $budget->id)
->get(['limit_repetitions.*']);
// no results? search entire range for expenses and list those.
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
if ($repetitions->count() == 0) {
$expenses = floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1;
if ($expenses > 0) {
$chart->addRow($budget->name, 0, $expenses);
}
} else {
// add with foreach:
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
$expenses
=
floatval($budget->transactionjournals()->before($repetition->enddate)->after($repetition->startdate)->lessThan(0)->sum('amount')) * -1;
if ($expenses > 0) {
$chart->addRow($budget->name . ' (' . $repetition->startdate->format('j M Y') . ')', floatval($repetition->amount), $expenses);
}
}
$expenses = $repository->sumBudgetExpensesInPeriod($budget, $start, $end);
$allEntries->push([$budget->name, 0, $expenses]);
continue;
}
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
$expenses = $repository->sumBudgetExpensesInPeriod($budget, $repetition->startdate, $repetition->enddate);
$allEntries->push([$budget->name . ' (' . $repetition->startdate->format('j M Y') . ')', floatval($repetition->amount), $expenses]);
}
}
$noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end);
$allEntries->push(['(no budget)', 0, $noBudgetExpenses]);
foreach ($allEntries as $entry) {
if ($entry[2] > 0) {
$chart->addRow($entry[0], $entry[1], $entry[2]);
}
}
$noBudgetSet = Auth::user()
->transactionjournals()
->whereNotIn(
'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) {
$query
->select('transaction_journals.id')
->from('transaction_journals')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00'))
->whereNotNull('budget_transaction_journal.budget_id');
}
)
->before($end)
->after($start)
->lessThan(0)
->transactionTypes(['Withdrawal'])
->get();
$sum = $noBudgetSet->sum('amount') * -1;
$chart->addRow('No budget', 0, $sum);
$chart->generate();
return Response::json($chart->getData());
}
/**
@ -232,34 +191,14 @@ class GoogleChartController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allCategoriesHomeChart(GChart $chart)
public function allCategoriesHomeChart(GChart $chart, CategoryRepositoryInterface $repository)
{
$chart->addColumn('Category', 'string');
$chart->addColumn('Spent', 'number');
// query!
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$set = TransactionJournal::
where('transaction_journals.user_id', Auth::user()->id)
->leftJoin(
'transactions',
function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0);
}
)
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->before($end)
->where('categories.user_id', Auth::user()->id)
->after($start)
->where('transaction_types.type', 'Withdrawal')
->groupBy('categories.id')
->orderBy('sum', 'DESC')
->get(['categories.id', 'categories.encrypted', 'categories.name', \DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
$set = $repository->getCategoriesAndExpenses($start, $end);
foreach ($set as $entry) {
$isEncrypted = intval($entry->encrypted) == 1 ? true : false;
@ -275,11 +214,12 @@ class GoogleChartController extends Controller
}
/**
* @param Bill $bill
* @param Bill $bill
* @param GChart $chart
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function billOverview(Bill $bill, GChart $chart)
public function billOverview(Bill $bill, GChart $chart, BillRepositoryInterface $repository)
{
$chart->addColumn('Date', 'date');
@ -288,24 +228,10 @@ class GoogleChartController extends Controller
$chart->addColumn('Recorded bill entry', 'number');
// get first transaction or today for start:
$first = $bill->transactionjournals()->orderBy('date', 'ASC')->first();
if ($first) {
$start = $first->date;
} else {
$start = new Carbon;
}
$results = $bill->transactionjournals()->after($start)->get();
$results = $repository->getJournals($bill);
/** @var TransactionJournal $result */
foreach ($results as $result) {
$amount = 0;
/** @var Transaction $tr */
foreach ($result->transactions()->get() as $tr) {
if (floatval($tr->amount) > 0) {
$amount = floatval($tr->amount);
}
}
$chart->addRow(clone $result->date, $bill->amount_max, $bill->amount_min, $amount);
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
@ -330,7 +256,7 @@ class GoogleChartController extends Controller
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$bills = Auth::user()->bills()->where('active', 1)->get();
$bills = $repository->getActiveBills();
/** @var Bill $bill */
foreach ($bills as $bill) {

View File

@ -170,7 +170,6 @@ Route::group(
Route::get('/bills/add/{bill}', ['uses' => 'BillController@add', 'as' => 'bills.add']);
Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']);
Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.show']);
Route::post('/bills/store', ['uses' => 'BillController@store', 'as' => 'bills.store']);
Route::post('/bills/update/{bill}', ['uses' => 'BillController@update', 'as' => 'bills.update']);
Route::post('/bills/destroy/{bill}', ['uses' => 'BillController@destroy', 'as' => 'bills.destroy']);
@ -226,7 +225,7 @@ Route::group(
Route::get('/chart/home/bills', ['uses' => 'GoogleChartController@billsOverview']);
Route::get('/chart/account/{account}/{view?}', ['uses' => 'GoogleChartController@accountBalanceChart']);
Route::get('/chart/budget/{budget}/spending/{year?}', ['uses' => 'GoogleChartController@budgetsAndSpending']);
Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending']);
Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending'])->where(['year' => '[0-9]+']);
Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']);
Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']);
Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']);

View File

@ -7,6 +7,7 @@ use Carbon\Carbon;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Log;
use Navigation;
@ -33,7 +34,15 @@ class BillRepository implements BillRepositoryInterface
*/
public function getBills()
{
return Auth::user()->bills()->orderBy('name', 'ASC')->get();
/** @var Collection $set */
$set = Auth::user()->bills()->orderBy('name', 'ASC')->get();
$set->sort(
function (Bill $bill) {
return $bill->name;
}
);
return $set;
}
/**
@ -44,10 +53,16 @@ class BillRepository implements BillRepositoryInterface
public function getJournals(Bill $bill)
{
return $bill->transactionjournals()->withRelevantData()
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.amount', '>', 0);
}
)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->get();
->get(['transaction_journals.*', 'transactions.amount']);
}
/**
@ -307,4 +322,20 @@ class BillRepository implements BillRepositoryInterface
return $bill;
}
/**
* @return Collection
*/
public function getActiveBills()
{
/** @var Collection $set */
$set = Auth::user()->bills()->orderBy('name', 'ASC')->where('active', 1)->get();
$set->sort(
function (Bill $bill) {
return $bill->name;
}
);
return $set;
}
}

View File

@ -22,6 +22,11 @@ interface BillRepositoryInterface
*/
public function destroy(Bill $bill);
/**
* @return Collection
*/
public function getActiveBills();
/**
* @return Collection
*/
@ -32,14 +37,14 @@ interface BillRepositoryInterface
*
* @return Collection
*/
public function getPossiblyRelatedJournals(Bill $bill);
public function getJournals(Bill $bill);
/**
* @param Bill $bill
*
* @return Collection
*/
public function getJournals(Bill $bill);
public function getPossiblyRelatedJournals(Bill $bill);
/**
* Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself)

View File

@ -9,6 +9,7 @@ use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\LimitRepetition;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Database\Query\Builder as QueryBuilder;
/**
* Class BudgetRepository
@ -60,7 +61,49 @@ class BudgetRepository implements BudgetRepositoryInterface
*/
public function getActiveBudgets()
{
return Auth::user()->budgets()->where('active', 1)->get();
$budgets = Auth::user()->budgets()->where('active', 1)->get();
$budgets->sortBy('name');
return $budgets;
}
/**
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end)
{
/** @var Collection $repetitions */
return LimitRepetition::
leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00'))
->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00'))
->where('budget_limits.budget_id', $budget->id)
->get(['limit_repetitions.*']);
}
/**
* @param Budget $budget
*
* @return Collection
*/
public function getBudgetLimits(Budget $budget)
{
return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get();
}
/**
* @return Collection
*/
public function getBudgets()
{
$budgets = Auth::user()->budgets()->get();
$budgets->sortBy('name');
return $budgets;
}
/**
@ -135,6 +178,35 @@ class BudgetRepository implements BudgetRepositoryInterface
->get(['transaction_journals.*']);
}
/**
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function getWithoutBudgetSum(Carbon $start, Carbon $end)
{
$noBudgetSet = Auth::user()
->transactionjournals()
->whereNotIn(
'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) {
$query
->select('transaction_journals.id')
->from('transaction_journals')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00'))
->whereNotNull('budget_transaction_journal.budget_id');
}
)
->before($end)
->after($start)
->lessThan(0)
->transactionTypes(['Withdrawal'])
->get();
return floatval($noBudgetSet->sum('amount')) * -1;
}
/**
* @param Budget $budget
* @param Carbon $date
@ -169,6 +241,18 @@ class BudgetRepository implements BudgetRepositoryInterface
return $newBudget;
}
/**
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function sumBudgetExpensesInPeriod(Budget $budget, $start, $end)
{
return floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1;
}
/**
* @param Budget $budget
* @param array $data
@ -224,14 +308,4 @@ class BudgetRepository implements BudgetRepositoryInterface
}
/**
* @param Budget $budget
*
* @return Collection
*/
public function getBudgetLimits(Budget $budget)
{
return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get();
}
}

View File

@ -14,6 +14,11 @@ use Illuminate\Support\Collection;
*/
interface BudgetRepositoryInterface
{
/**
* @return void
*/
public function cleanupBudgets();
/**
* @param Budget $budget
*
@ -26,31 +31,14 @@ interface BudgetRepositoryInterface
*/
public function getActiveBudgets();
/**
* @return Collection
*/
public function getInactiveBudgets();
/**
* @return void
*/
public function cleanupBudgets();
/**
* @param Budget $budget
* @param Carbon $date
*
* @return float
*/
public function spentInMonth(Budget $budget, Carbon $date);
/**
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getWithoutBudget(Carbon $start, Carbon $end);
public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end);
/**
* @param Budget $budget
@ -59,6 +47,11 @@ interface BudgetRepositoryInterface
*/
public function getBudgetLimits(Budget $budget);
/**
* @return Collection
*/
public function getBudgets();
/**
* @param Budget $budget
* @param Carbon $date
@ -68,28 +61,9 @@ interface BudgetRepositoryInterface
public function getCurrentRepetition(Budget $budget, Carbon $date);
/**
* @param Budget $budget
* @param Carbon $date
* @param $amount
*
* @return mixed
* @return Collection
*/
public function updateLimitAmount(Budget $budget, Carbon $date, $amount);
/**
* @param array $data
*
* @return Budget
*/
public function store(array $data);
/**
* @param Budget $budget
* @param array $data
*
* @return Budget
*/
public function update(Budget $budget, array $data);
public function getInactiveBudgets();
/**
* Returns all the transaction journals for a limit, possibly limited by a limit repetition.
@ -102,4 +76,61 @@ interface BudgetRepositoryInterface
*/
public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50);
/**
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getWithoutBudget(Carbon $start, Carbon $end);
/**
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function getWithoutBudgetSum(Carbon $start, Carbon $end);
/**
* @param Budget $budget
* @param Carbon $date
*
* @return float
*/
public function spentInMonth(Budget $budget, Carbon $date);
/**
* @param array $data
*
* @return Budget
*/
public function store(array $data);
/**
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function sumBudgetExpensesInPeriod(Budget $budget, $start, $end);
/**
* @param Budget $budget
* @param array $data
*
* @return Budget
*/
public function update(Budget $budget, array $data);
/**
* @param Budget $budget
* @param Carbon $date
* @param $amount
*
* @return mixed
*/
public function updateLimitAmount(Budget $budget, Carbon $date, $amount);
}

View File

@ -4,7 +4,10 @@ namespace FireflyIII\Repositories\Category;
use Auth;
use Carbon\Carbon;
use DB;
use FireflyIII\Models\Category;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
/**
@ -46,6 +49,36 @@ class CategoryRepository implements CategoryRepositoryInterface
return Auth::user()->categories()->orderBy('name', 'ASC')->get();
}
/**
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getCategoriesAndExpenses($start, $end)
{
return TransactionJournal::
where('transaction_journals.user_id', Auth::user()->id)
->leftJoin(
'transactions',
function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0);
}
)
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->before($end)
->where('categories.user_id', Auth::user()->id)
->after($start)
->where('transaction_types.type', 'Withdrawal')
->groupBy('categories.id')
->orderBy('sum', 'DESC')
->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
}
/**
* @param Category $category
* @param int $page

View File

@ -32,6 +32,14 @@ interface CategoryRepositoryInterface
*/
public function getCategories();
/**
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getCategoriesAndExpenses($start, $end);
/**
* @param Category $category
* @param int $page

View File

@ -0,0 +1,107 @@
<?php
/**
* Class GoogleChartControllerTest
*/
class GoogleChartControllerTest extends TestCase
{
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
public function setUp()
{
parent::setUp();
}
/**
* This method is called before the first test of this test class is run.
*
* @since Method available since Release 3.4.0
*/
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
}
/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*/
public function tearDown()
{
parent::tearDown();
}
public function testAccountBalanceChart()
{
$this->markTestIncomplete();
}
public function testAllAccountsBalanceChart()
{
$this->markTestIncomplete();
}
public function testAllBudgetsAndSpending()
{
$this->markTestIncomplete();
}
public function testAllBudgetsHomeChart()
{
$this->markTestIncomplete();
}
public function testAllCategoriesHomeChart()
{
$this->markTestIncomplete();
}
public function testBillOverview()
{
$this->markTestIncomplete();
}
public function testBillsOverview()
{
$this->markTestIncomplete();
}
public function testBudgetLimitSpending()
{
$this->markTestIncomplete();
}
public function testBudgetsAndSpending()
{
$this->markTestIncomplete();
}
public function testCategoryOverviewChart()
{
$this->markTestIncomplete();
}
public function testCategoryPeriodChart()
{
$this->markTestIncomplete();
}
public function testPiggyBankHistory()
{
$this->markTestIncomplete();
}
public function testYearInExp()
{
$this->markTestIncomplete();
}
public function testYearInExpSum()
{
$this->markTestIncomplete();
}
}