mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-19 10:53:37 +00:00
Expand API with budget limits
This commit is contained in:
@@ -97,7 +97,7 @@ class AvailableBudgetController extends Controller
|
|||||||
// types to get, page size:
|
// types to get, page size:
|
||||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
// get list of accounts. Count it and split it.
|
// get list of available budgets. Count it and split it.
|
||||||
$collection = $this->repository->getAvailableBudgets();
|
$collection = $this->repository->getAvailableBudgets();
|
||||||
$count = $collection->count();
|
$count = $collection->count();
|
||||||
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
230
app/Api/V1/Controllers/BudgetLimitController.php
Normal file
230
app/Api/V1/Controllers/BudgetLimitController.php
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* BudgetLimitController.php
|
||||||
|
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III.
|
||||||
|
*
|
||||||
|
* Firefly III is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Firefly III is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Api\V1\Requests\AvailableBudgetRequest;
|
||||||
|
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use League\Fractal\Manager;
|
||||||
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
|
use League\Fractal\Resource\Item;
|
||||||
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BudgetLimitController
|
||||||
|
*/
|
||||||
|
class BudgetLimitController extends Controller
|
||||||
|
{
|
||||||
|
///** @var CurrencyRepositoryInterface */
|
||||||
|
//private $currencyRepository;
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AccountController constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
/** @var User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
|
//$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||||
|
$this->repository->setUser($user);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function delete(BudgetLimit $budgetLimit): JsonResponse
|
||||||
|
{
|
||||||
|
$this->repository->destroyBudgetLimit($budgetLimit);
|
||||||
|
|
||||||
|
return response()->json([], 204);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function index(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
// read budget from request
|
||||||
|
$budgetId = (int)($request->get('budget_id') ?? 0);
|
||||||
|
$budget = null;
|
||||||
|
if ($budgetId > 0) {
|
||||||
|
$budget = $this->repository->findNull($budgetId);
|
||||||
|
}
|
||||||
|
// read start date from request
|
||||||
|
$start = null;
|
||||||
|
try {
|
||||||
|
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
|
||||||
|
$this->parameters->set('start', $start->format('Y-m-d'));
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
Log::debug(sprintf('Could not parse start date "%s": %s', $request->get('start'), $e->getMessage()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// read end date from request
|
||||||
|
$end = null;
|
||||||
|
try {
|
||||||
|
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
|
||||||
|
$this->parameters->set('end', $end->format('Y-m-d'));
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
Log::debug(sprintf('Could not parse end date "%s": %s', $request->get('end'), $e->getMessage()));
|
||||||
|
}
|
||||||
|
$this->parameters->set('budget_id', $budgetId);
|
||||||
|
|
||||||
|
// types to get, page size:
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of budget limits. Count it and split it.
|
||||||
|
$collection = new Collection;
|
||||||
|
if (null === $budget) {
|
||||||
|
$collection = $this->repository->getAllBudgetLimits($start, $end);
|
||||||
|
}
|
||||||
|
if (null !== $budget) {
|
||||||
|
$collection = $this->repository->getBudgetLimits($budget, $start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = $collection->count();
|
||||||
|
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
|
// make paginator:
|
||||||
|
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
$resource = new FractalCollection($budgetLimits, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse
|
||||||
|
{
|
||||||
|
$manager = new Manager;
|
||||||
|
|
||||||
|
// add include parameter:
|
||||||
|
$include = $request->get('include') ?? '';
|
||||||
|
$manager->parseIncludes($include);
|
||||||
|
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param BudgetLimitRequest $request
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function store(BudgetLimitRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$data = $request->getAll();
|
||||||
|
$budget = $this->repository->findNull($data['budget_id']);
|
||||||
|
if (null === $budget) {
|
||||||
|
throw new FireflyException('Unknown budget.');
|
||||||
|
}
|
||||||
|
$data['budget'] = $budget;
|
||||||
|
$budgetLimit = $this->repository->storeBudgetLimit($data);
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param AvailableBudgetRequest $request
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse
|
||||||
|
{
|
||||||
|
$data = $request->getAll();
|
||||||
|
$budget = $this->repository->findNull($data['budget_id']);
|
||||||
|
if (null === $budget) {
|
||||||
|
$budget = $budgetLimit->budget;
|
||||||
|
}
|
||||||
|
$data['budget'] = $budget;
|
||||||
|
$budgetLimit = $this->repository->updateBudgetLimit($budgetLimit, $data);
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
77
app/Api/V1/Requests/BudgetLimitRequest.php
Normal file
77
app/Api/V1/Requests/BudgetLimitRequest.php
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* BudgetLimitRequest.php
|
||||||
|
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III.
|
||||||
|
*
|
||||||
|
* Firefly III is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Firefly III is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BudgetLimitRequest
|
||||||
|
*/
|
||||||
|
class BudgetLimitRequest extends Request
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
// Only allow authenticated users
|
||||||
|
return auth()->check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAll(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'budget_id' => $this->integer('budget_id'),
|
||||||
|
'start_date' => $this->date('start_date'),
|
||||||
|
'end_date' => $this->date('end_date'),
|
||||||
|
'amount' => $this->string('amount'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
|
||||||
|
'start_date' => 'required|before:end_date|date',
|
||||||
|
'end_date' => 'required|after:start_date|date',
|
||||||
|
'amount' => 'required|more:0',
|
||||||
|
];
|
||||||
|
switch ($this->method()) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case 'PUT':
|
||||||
|
case 'PATCH':
|
||||||
|
$rules['budget_id'] = 'required|exists:budgets,id|belongsToUser:budgets,id';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -58,8 +58,8 @@ class BillFactory
|
|||||||
'date' => $data['date'],
|
'date' => $data['date'],
|
||||||
'repeat_freq' => $data['repeat_freq'],
|
'repeat_freq' => $data['repeat_freq'],
|
||||||
'skip' => $data['skip'],
|
'skip' => $data['skip'],
|
||||||
'automatch' => true,
|
'automatch' => $data['automatch'] ?? true,
|
||||||
'active' => $data['active'],
|
'active' => $data['active'] ?? true,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -49,7 +49,6 @@ class BillFormRequest extends Request
|
|||||||
'date' => $this->date('date'),
|
'date' => $this->date('date'),
|
||||||
'repeat_freq' => $this->string('repeat_freq'),
|
'repeat_freq' => $this->string('repeat_freq'),
|
||||||
'skip' => $this->integer('skip'),
|
'skip' => $this->integer('skip'),
|
||||||
'active' => $this->boolean('active'),
|
|
||||||
'notes' => $this->string('notes'),
|
'notes' => $this->string('notes'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -73,8 +72,6 @@ class BillFormRequest extends Request
|
|||||||
'date' => 'required|date',
|
'date' => 'required|date',
|
||||||
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
||||||
'skip' => 'required|between:0,31',
|
'skip' => 'required|between:0,31',
|
||||||
'automatch' => 'in:1',
|
|
||||||
'active' => 'in:1',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
@@ -22,11 +22,21 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetLimit.
|
* Class BudgetLimit.
|
||||||
|
*
|
||||||
|
* @property Budget $budget
|
||||||
|
* @property int $id
|
||||||
|
* @property Carbon $created_at
|
||||||
|
* @property Carbon $updated_at
|
||||||
|
* @property Carbon $start_date
|
||||||
|
* @property Carbon $end_date
|
||||||
|
* @property string $amount
|
||||||
*/
|
*/
|
||||||
class BudgetLimit extends Model
|
class BudgetLimit extends Model
|
||||||
{
|
{
|
||||||
@@ -67,20 +77,10 @@ class BudgetLimit extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
* @return BelongsTo
|
||||||
*/
|
*/
|
||||||
public function budget()
|
public function budget(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Budget::class);
|
return $this->belongsTo(Budget::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*
|
|
||||||
* @param $value
|
|
||||||
*/
|
|
||||||
public function setAmountAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['amount'] = (string)round($value, 12);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -154,6 +154,20 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a budget limit.
|
||||||
|
*
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*/
|
||||||
|
public function deleteBudgetLimit(BudgetLimit $budgetLimit): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$budgetLimit->delete();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error(sprintf('Could not delete budget limit: %s', $e->getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
@@ -315,8 +329,35 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getAllBudgetLimits(Carbon $start, Carbon $end): Collection
|
public function getAllBudgetLimits(Carbon $start = null, Carbon $end = null): Collection
|
||||||
{
|
{
|
||||||
|
// both are NULL:
|
||||||
|
if (null === $start && null === $end) {
|
||||||
|
$set = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||||
|
->with(['budget'])
|
||||||
|
->where('budgets.user_id', $this->user->id)
|
||||||
|
->get(['budget_limits.*']);
|
||||||
|
|
||||||
|
return $set;
|
||||||
|
}
|
||||||
|
// one of the two is NULL.
|
||||||
|
if (null === $start xor null === $end) {
|
||||||
|
$query = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||||
|
->with(['budget'])
|
||||||
|
->where('budgets.user_id', $this->user->id);
|
||||||
|
if (null !== $end) {
|
||||||
|
// end date must be before $end.
|
||||||
|
$query->where('end_date', '<=', $end->format('Y-m-d 00:00:00'));
|
||||||
|
}
|
||||||
|
if (null !== $start) {
|
||||||
|
// start date must be after $start.
|
||||||
|
$query->where('start_date', '>=', $start->format('Y-m-d 00:00:00'));
|
||||||
|
}
|
||||||
|
$set = $query->get(['budget_limits.*']);
|
||||||
|
|
||||||
|
return $set;
|
||||||
|
}
|
||||||
|
// neither are NULL:
|
||||||
$set = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
$set = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||||
->with(['budget'])
|
->with(['budget'])
|
||||||
->where('budgets.user_id', $this->user->id)
|
->where('budgets.user_id', $this->user->id)
|
||||||
@@ -389,8 +430,28 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getBudgetLimits(Budget $budget, Carbon $start, Carbon $end): Collection
|
public function getBudgetLimits(Budget $budget, Carbon $start = null, Carbon $end = null): Collection
|
||||||
{
|
{
|
||||||
|
if (null === $end && null === $start) {
|
||||||
|
return $budget->budgetlimits()->orderBy('budget_limits.start_date', 'DESC')->get(['budget_limits.*']);
|
||||||
|
}
|
||||||
|
if (null === $end xor null === $start) {
|
||||||
|
$query = $budget->budgetlimits()->orderBy('budget_limits.start_date', 'DESC');
|
||||||
|
// one of the two is null
|
||||||
|
if (null !== $end) {
|
||||||
|
// end date must be before $end.
|
||||||
|
$query->where('end_date', '<=', $end->format('Y-m-d 00:00:00'));
|
||||||
|
}
|
||||||
|
if (null !== $start) {
|
||||||
|
// start date must be after $start.
|
||||||
|
$query->where('start_date', '>=', $start->format('Y-m-d 00:00:00'));
|
||||||
|
}
|
||||||
|
$set = $query->get(['budget_limits.*']);
|
||||||
|
|
||||||
|
return $set;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when both dates are set:
|
||||||
$set = $budget->budgetlimits()
|
$set = $budget->budgetlimits()
|
||||||
->where(
|
->where(
|
||||||
function (Builder $q5) use ($start, $end) {
|
function (Builder $q5) use ($start, $end) {
|
||||||
@@ -663,6 +724,42 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
return $newBudget;
|
return $newBudget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @throws FireflyException
|
||||||
|
* @return BudgetLimit
|
||||||
|
*/
|
||||||
|
public function storeBudgetLimit(array $data): BudgetLimit
|
||||||
|
{
|
||||||
|
$this->cleanupBudgets();
|
||||||
|
/** @var Budget $budget */
|
||||||
|
$budget = $data['budget'];
|
||||||
|
|
||||||
|
// find limit with same date range.
|
||||||
|
// if it exists, throw error.
|
||||||
|
$limits = $budget->budgetlimits()
|
||||||
|
->where('budget_limits.start_date', $data['start_date']->format('Y-m-d 00:00:00'))
|
||||||
|
->where('budget_limits.end_date', $data['end_date']->format('Y-m-d 00:00:00'))
|
||||||
|
->get(['budget_limits.*'])->count();
|
||||||
|
Log::debug(sprintf('Found %d budget limits.', $limits));
|
||||||
|
if ($limits > 0) {
|
||||||
|
throw new FireflyException('A budget limit for this budget, and this date range already exists. You must update the existing one.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug('No existing budget limit, create a new one');
|
||||||
|
// or create one and return it.
|
||||||
|
$limit = new BudgetLimit;
|
||||||
|
$limit->budget()->associate($budget);
|
||||||
|
$limit->start_date = $data['start_date']->format('Y-m-d 00:00:00');
|
||||||
|
$limit->end_date = $data['end_date']->format('Y-m-d 00:00:00');
|
||||||
|
$limit->amount = $data['amount'];
|
||||||
|
$limit->save();
|
||||||
|
Log::debug(sprintf('Created new budget limit with ID #%d and amount %s', $limit->id, $data['amount']));
|
||||||
|
|
||||||
|
return $limit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param array $data
|
* @param array $data
|
||||||
@@ -708,6 +805,29 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return BudgetLimit
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function updateBudgetLimit(BudgetLimit $budgetLimit, array $data): BudgetLimit
|
||||||
|
{
|
||||||
|
$this->cleanupBudgets();
|
||||||
|
/** @var Budget $budget */
|
||||||
|
$budget = $data['budget'];
|
||||||
|
|
||||||
|
$budgetLimit->budget()->associate($budget);
|
||||||
|
$budgetLimit->start_date = $data['start_date']->format('Y-m-d 00:00:00');
|
||||||
|
$budgetLimit->end_date = $data['end_date']->format('Y-m-d 00:00:00');
|
||||||
|
$budgetLimit->amount = $data['amount'];
|
||||||
|
$budgetLimit->save();
|
||||||
|
Log::debug(sprintf('Updated budget limit with ID #%d and amount %s', $budgetLimit->id, $data['amount']));
|
||||||
|
|
||||||
|
return $budgetLimit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
|
@@ -63,6 +63,13 @@ interface BudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function collectBudgetInformation(Collection $budgets, Carbon $start, Carbon $end): array;
|
public function collectBudgetInformation(Collection $budgets, Carbon $start, Carbon $end): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a budget limit.
|
||||||
|
*
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*/
|
||||||
|
public function deleteBudgetLimit(BudgetLimit $budgetLimit): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
@@ -136,7 +143,7 @@ interface BudgetRepositoryInterface
|
|||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getAllBudgetLimits(Carbon $start, Carbon $end): Collection;
|
public function getAllBudgetLimits(Carbon $start = null, Carbon $end = null): Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TransactionCurrency $currency
|
* @param TransactionCurrency $currency
|
||||||
@@ -161,7 +168,7 @@ interface BudgetRepositoryInterface
|
|||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getBudgetLimits(Budget $budget, Carbon $start, Carbon $end): Collection;
|
public function getBudgetLimits(Budget $budget, Carbon $start = null, Carbon $end = null): Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $budgets
|
* @param Collection $budgets
|
||||||
@@ -259,6 +266,21 @@ interface BudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function updateAvailableBudget(AvailableBudget $availableBudget, array $data): AvailableBudget;
|
public function updateAvailableBudget(AvailableBudget $availableBudget, array $data): AvailableBudget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return BudgetLimit
|
||||||
|
*/
|
||||||
|
public function updateBudgetLimit(BudgetLimit $budgetLimit, array $data): BudgetLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return BudgetLimit
|
||||||
|
*/
|
||||||
|
public function storeBudgetLimit(array $data): BudgetLimit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
|
@@ -29,6 +29,9 @@ use League\Fractal\Resource\Item;
|
|||||||
use League\Fractal\TransformerAbstract;
|
use League\Fractal\TransformerAbstract;
|
||||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AvailableBudgetTransformer
|
||||||
|
*/
|
||||||
class AvailableBudgetTransformer extends TransformerAbstract
|
class AvailableBudgetTransformer extends TransformerAbstract
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
103
app/Transformers/BudgetLimitTransformer.php
Normal file
103
app/Transformers/BudgetLimitTransformer.php
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* BudgetLimitTransformer.php
|
||||||
|
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III.
|
||||||
|
*
|
||||||
|
* Firefly III is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Firefly III is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Transformers;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
use League\Fractal\Resource\Item;
|
||||||
|
use League\Fractal\TransformerAbstract;
|
||||||
|
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BudgetLimitTransformer
|
||||||
|
*/
|
||||||
|
class BudgetLimitTransformer extends TransformerAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* List of resources possible to include
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $availableIncludes = ['budget'];
|
||||||
|
/**
|
||||||
|
* List of resources to automatically include
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $defaultIncludes = ['budget'];
|
||||||
|
|
||||||
|
/** @var ParameterBag */
|
||||||
|
protected $parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CurrencyTransformer constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @param ParameterBag $parameters
|
||||||
|
*/
|
||||||
|
public function __construct(ParameterBag $parameters)
|
||||||
|
{
|
||||||
|
$this->parameters = $parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach the budget.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*
|
||||||
|
* @return Item
|
||||||
|
*/
|
||||||
|
public function includeBudget(BudgetLimit $budgetLimit): Item
|
||||||
|
{
|
||||||
|
return $this->item($budgetLimit->budget, new BudgetTransformer($this->parameters), 'budgets');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the note.
|
||||||
|
*
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform(BudgetLimit $budgetLimit): array
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'id' => (int)$budgetLimit->id,
|
||||||
|
'updated_at' => $budgetLimit->updated_at->toAtomString(),
|
||||||
|
'created_at' => $budgetLimit->created_at->toAtomString(),
|
||||||
|
'start_date' => $budgetLimit->start_date->format('Y-m-d'),
|
||||||
|
'end_date' => $budgetLimit->end_date->format('Y-m-d'),
|
||||||
|
'amount' => $budgetLimit->amount,
|
||||||
|
'links' => [
|
||||||
|
[
|
||||||
|
'rel' => 'self',
|
||||||
|
'uri' => '/budget_limits/' . $budgetLimit->id,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
@@ -35,8 +35,6 @@
|
|||||||
{{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }}
|
{{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }}
|
||||||
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
|
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
|
||||||
{{ ExpandedForm.integer('skip',0) }}
|
{{ ExpandedForm.integer('skip',0) }}
|
||||||
{# only correct way to do active checkbox #}
|
|
||||||
{{ ExpandedForm.checkbox('active', 1) }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -66,13 +66,24 @@ Route::group(
|
|||||||
Route::get('', ['uses' => 'AvailableBudgetController@index', 'as' => 'index']);
|
Route::get('', ['uses' => 'AvailableBudgetController@index', 'as' => 'index']);
|
||||||
Route::post('', ['uses' => 'AvailableBudgetController@store', 'as' => 'store']);
|
Route::post('', ['uses' => 'AvailableBudgetController@store', 'as' => 'store']);
|
||||||
Route::get('{availableBudget}', ['uses' => 'AvailableBudgetController@show', 'as' => 'show']);
|
Route::get('{availableBudget}', ['uses' => 'AvailableBudgetController@show', 'as' => 'show']);
|
||||||
Route::get('{availableBudget}/download', ['uses' => 'AvailableBudgetController@download', 'as' => 'download']);
|
|
||||||
Route::post('{availableBudget}/upload', ['uses' => 'AvailableBudgetController@upload', 'as' => 'upload']);
|
|
||||||
Route::put('{availableBudget}', ['uses' => 'AvailableBudgetController@update', 'as' => 'update']);
|
Route::put('{availableBudget}', ['uses' => 'AvailableBudgetController@update', 'as' => 'update']);
|
||||||
Route::delete('{availableBudget}', ['uses' => 'AvailableBudgetController@delete', 'as' => 'delete']);
|
Route::delete('{availableBudget}', ['uses' => 'AvailableBudgetController@delete', 'as' => 'delete']);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Route::group(
|
||||||
|
['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'budget_limits', 'as' => 'api.v1.budget_limits.'],
|
||||||
|
function () {
|
||||||
|
|
||||||
|
// Budget Limit API routes:
|
||||||
|
Route::get('', ['uses' => 'BudgetLimitController@index', 'as' => 'index']);
|
||||||
|
Route::post('', ['uses' => 'BudgetLimitController@store', 'as' => 'store']);
|
||||||
|
Route::get('{budgetLimit}', ['uses' => 'BudgetLimitController@show', 'as' => 'show']);
|
||||||
|
Route::put('{budgetLimit}', ['uses' => 'BudgetLimitController@update', 'as' => 'update']);
|
||||||
|
Route::delete('{budgetLimit}', ['uses' => 'BudgetLimitController@delete', 'as' => 'delete']);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'bills', 'as' => 'api.v1.bills.'], function () {
|
['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'bills', 'as' => 'api.v1.bills.'], function () {
|
||||||
|
Reference in New Issue
Block a user