diff --git a/app/Api/V2/Controllers/Autocomplete/AccountController.php b/app/Api/V2/Controllers/Autocomplete/AccountController.php index 393c5ce06c..4f0bdc4931 100644 --- a/app/Api/V2/Controllers/Autocomplete/AccountController.php +++ b/app/Api/V2/Controllers/Autocomplete/AccountController.php @@ -65,12 +65,16 @@ class AccountController extends Controller /** * Documentation for this endpoint: - * TODO endpoint is not documented. + * TODO list of checks + * 1. use dates from ParameterBag + * 2. Request validates dates + * 3. Request includes user_group_id as administration_id + * 4. Endpoint is documented. + * 5. Collector uses administration_id * * @param AutocompleteRequest $request * * @return JsonResponse - * @throws JsonException * @throws FireflyException * @throws FireflyException */ @@ -79,7 +83,7 @@ class AccountController extends Controller $data = $request->getData(); $types = $data['types']; $query = $data['query']; - $date = $data['date'] ?? today(config('app.timezone')); + $date = $this->parameters->get('date') ?? today(config('app.timezone')); $this->adminRepository->setAdministrationId($data['administration_id']); $return = []; diff --git a/app/Api/V2/Controllers/Chart/AccountController.php b/app/Api/V2/Controllers/Chart/AccountController.php index dbfd1fa160..62292e1920 100644 --- a/app/Api/V2/Controllers/Chart/AccountController.php +++ b/app/Api/V2/Controllers/Chart/AccountController.php @@ -71,6 +71,8 @@ class AccountController extends Controller * If a transaction has foreign currency = native currency, the foreign amount will be used, no conversion * will take place. * + * TODO validate and set administration_id from request + * * @param DateRequest $request * * @return JsonResponse @@ -80,15 +82,11 @@ class AccountController extends Controller */ public function dashboard(DateRequest $request): JsonResponse { - // parameters for chart: - $dates = $request->getAll(); /** @var Carbon $start */ - $start = $dates['start']; + $start = $this->parameters->get('start'); /** @var Carbon $end */ - $end = $dates['end']; + $end = $this->parameters->get('end'); $end->endOfDay(); - /** @var User $user */ - $user = auth()->user(); // user's preferences $defaultSet = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT])->pluck('id')->toArray(); diff --git a/app/Api/V2/Controllers/Chart/BalanceController.php b/app/Api/V2/Controllers/Chart/BalanceController.php index e70793fd52..0756ffe99c 100644 --- a/app/Api/V2/Controllers/Chart/BalanceController.php +++ b/app/Api/V2/Controllers/Chart/BalanceController.php @@ -69,6 +69,9 @@ class BalanceController extends Controller * If the transaction being processed is already in native currency OR if the * foreign amount is in the native currency, the amount will not be converted. * + * TODO validate and set administration_id + * TODO collector set group, not user + * * @param BalanceChartRequest $request * * @return JsonResponse @@ -78,9 +81,9 @@ class BalanceController extends Controller { $params = $request->getAll(); /** @var Carbon $start */ - $start = $params['start']; + $start = $this->parameters->get('start'); /** @var Carbon $end */ - $end = $params['end']; + $end = $this->parameters->get('end'); $end->endOfDay(); /** @var Collection $accounts */ $accounts = $params['accounts']; diff --git a/app/Api/V2/Controllers/Chart/BudgetController.php b/app/Api/V2/Controllers/Chart/BudgetController.php index 236ccf9de1..83d2d93939 100644 --- a/app/Api/V2/Controllers/Chart/BudgetController.php +++ b/app/Api/V2/Controllers/Chart/BudgetController.php @@ -69,6 +69,8 @@ class BudgetController extends Controller /** * @param DateRequest $request * + * TODO see autocomplete/accountcontroller + * * @return JsonResponse * @throws FireflyException */ diff --git a/app/Api/V2/Controllers/Chart/CategoryController.php b/app/Api/V2/Controllers/Chart/CategoryController.php index 443fad2eab..442f00d4a6 100644 --- a/app/Api/V2/Controllers/Chart/CategoryController.php +++ b/app/Api/V2/Controllers/Chart/CategoryController.php @@ -61,6 +61,7 @@ class CategoryController extends Controller /** * TODO may be worth to move to a handler but the data is simple enough. + * TODO see autoComplete/account controller * * @param DateRequest $request * @@ -69,11 +70,10 @@ class CategoryController extends Controller */ public function dashboard(DateRequest $request): JsonResponse { - $params = $request->getAll(); /** @var Carbon $start */ - $start = $params['start']; + $start = $this->parameters->get('start'); /** @var Carbon $end */ - $end = $params['end']; + $end = $this->parameters->get('end'); $accounts = $this->accountRepos->getAccountsByType([AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::ASSET, AccountType::DEFAULT]); $default = app('amount')->getDefaultCurrency(); $converter = new ExchangeRateConverter(); diff --git a/app/Api/V2/Controllers/Controller.php b/app/Api/V2/Controllers/Controller.php index a4eec48b3f..72c7975473 100644 --- a/app/Api/V2/Controllers/Controller.php +++ b/app/Api/V2/Controllers/Controller.php @@ -93,21 +93,25 @@ class Controller extends BaseController // some date fields: foreach ($dates as $field) { $date = null; + $obj = null; try { $date = request()->query->get($field); } catch (BadRequestException $e) { Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field)); Log::error($e->getMessage()); - $value = null; } - $obj = null; if (null !== $date) { try { - $obj = Carbon::parse($date); + $obj = Carbon::parse($date, config('app.timezone')); } catch (InvalidDateException | InvalidFormatException $e) { // don't care app('log')->warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', substr($date, 0, 20), $e->getMessage())); } + // out of range? set to null. + if (null !== $obj && ($obj->year <= 1900 || $obj->year > 2099)) { + app('log')->warning(sprintf('Refuse to use date "%s" in API v2 controller parameter check: %s', $field, $obj->toAtomString())); + $obj = null; + } } $bag->set($field, $obj); } diff --git a/app/Api/V2/Controllers/Model/Bill/ShowController.php b/app/Api/V2/Controllers/Model/Bill/ShowController.php new file mode 100644 index 0000000000..b9ad71529c --- /dev/null +++ b/app/Api/V2/Controllers/Model/Bill/ShowController.php @@ -0,0 +1,72 @@ +. + */ + +namespace FireflyIII\Api\V2\Controllers\Model\Bill; + +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Repositories\Administration\Bill\BillRepositoryInterface; +use FireflyIII\Transformers\V2\BillTransformer; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; +use Illuminate\Pagination\LengthAwarePaginator; + +/** + * Class ShowController + */ +class ShowController extends Controller +{ + private BillRepositoryInterface $repository; + + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + $this->repository = app(BillRepositoryInterface::class); + $this->repository->setAdministrationId(auth()->user()->user_group_id); + return $next($request); + } + ); + } + + /** + * @param Request $request + * + * TODO see autocomplete/accountcontroller for list. + * + * @return JsonResponse + */ + public function index(Request $request): JsonResponse + { + $this->repository->correctOrder(); + $bills = $this->repository->getBills(); + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $count = $bills->count(); + $bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); + $transformer = new BillTransformer(); + $transformer->setParameters($this->parameters); // give params to transformer + + return response() + ->json($this->jsonApiList('subscriptions', $paginator, $transformer)) + ->header('Content-Type', self::CONTENT_TYPE); + } +} diff --git a/app/Api/V2/Controllers/Model/Bill/SumController.php b/app/Api/V2/Controllers/Model/Bill/SumController.php index 61456329b8..f8288b833d 100644 --- a/app/Api/V2/Controllers/Model/Bill/SumController.php +++ b/app/Api/V2/Controllers/Model/Bill/SumController.php @@ -26,7 +26,7 @@ namespace FireflyIII\Api\V2\Controllers\Model\Bill; use FireflyIII\Api\V2\Controllers\Controller; use FireflyIII\Api\V2\Request\Generic\DateRequest; -use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use FireflyIII\Repositories\Administration\Bill\BillRepositoryInterface; use FireflyIII\Support\Http\Api\ConvertsExchangeRates; use Illuminate\Http\JsonResponse; @@ -35,8 +35,6 @@ use Illuminate\Http\JsonResponse; */ class SumController extends Controller { - use ConvertsExchangeRates; - private BillRepositoryInterface $repository; /** @@ -58,35 +56,37 @@ class SumController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/transactions-sum/getBillsPaidTrSum * + * TODO see autocomplete/accountcontroller for list. + * * @param DateRequest $request * * @return JsonResponse */ public function paid(DateRequest $request): JsonResponse { - $dates = $request->getAll(); - $result = $this->repository->sumPaidInRange($dates['start'], $dates['end']); - $converted = $this->cerSum($result); + $this->repository->setAdministrationId(auth()->user()->user_group_id); + $result = $this->repository->sumPaidInRange($this->parameters->get('start'), $this->parameters->get('end')); // convert to JSON response: - return response()->api($converted); + return response()->api(array_values($result)); } /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/transactions-sum/getBillsUnpaidTrSum * + * TODO see autocomplete/accountcontroller for list. + * * @param DateRequest $request * * @return JsonResponse */ public function unpaid(DateRequest $request): JsonResponse { - $dates = $request->getAll(); - $result = $this->repository->sumUnpaidInRange($dates['start'], $dates['end']); - $converted = $this->cerSum($result); + $this->repository->setAdministrationId(auth()->user()->user_group_id); + $result = $this->repository->sumUnpaidInRange($this->parameters->get('start'), $this->parameters->get('end')); // convert to JSON response: - return response()->api($converted); + return response()->api(array_values($result)); } } diff --git a/app/Api/V2/Controllers/Model/Budget/ListController.php b/app/Api/V2/Controllers/Model/Budget/ListController.php index f2f5645f30..3a3cca394d 100644 --- a/app/Api/V2/Controllers/Model/Budget/ListController.php +++ b/app/Api/V2/Controllers/Model/Budget/ListController.php @@ -60,6 +60,8 @@ class ListController extends Controller */ public function index(Request $request): JsonResponse { + echo 'this needs move to Administration'; + exit; $collection = $this->repository->getActiveBudgets(); $total = $collection->count(); $collection->slice($this->pageSize * $this->parameters->get('page'), $this->pageSize); diff --git a/app/Api/V2/Request/Chart/BalanceChartRequest.php b/app/Api/V2/Request/Chart/BalanceChartRequest.php index 48703b997d..f7003d967e 100644 --- a/app/Api/V2/Request/Chart/BalanceChartRequest.php +++ b/app/Api/V2/Request/Chart/BalanceChartRequest.php @@ -41,8 +41,6 @@ class BalanceChartRequest extends FormRequest public function getAll(): array { return [ - 'start' => $this->getCarbonDate('start'), - 'end' => $this->getCarbonDate('end'), 'accounts' => $this->getAccountList(), 'period' => $this->string('period'), ]; diff --git a/app/Repositories/Administration/Bill/BillRepository.php b/app/Repositories/Administration/Bill/BillRepository.php index c0d8442555..bb123447a3 100644 --- a/app/Repositories/Administration/Bill/BillRepository.php +++ b/app/Repositories/Administration/Bill/BillRepository.php @@ -39,6 +39,32 @@ class BillRepository implements BillRepositoryInterface { use AdministrationTrait; + /** + * Correct order of piggies in case of issues. + */ + public function correctOrder(): void + { + $set = $this->userGroup->bills()->orderBy('order', 'ASC')->get(); + $current = 1; + foreach ($set as $bill) { + if ((int)$bill->order !== $current) { + $bill->order = $current; + $bill->save(); + } + $current++; + } + } + + /** + * @return Collection + */ + public function getBills(): Collection + { + return $this->userGroup->bills() + ->orderBy('bills.name', 'ASC') + ->get(['bills.*']); + } + /** * @inheritDoc */ @@ -109,7 +135,6 @@ class BillRepository implements BillRepositoryInterface ->get(['bills.*']); } - /** * @inheritDoc */ diff --git a/app/Repositories/Administration/Bill/BillRepositoryInterface.php b/app/Repositories/Administration/Bill/BillRepositoryInterface.php index 80ff3b15fa..12327f568c 100644 --- a/app/Repositories/Administration/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Administration/Bill/BillRepositoryInterface.php @@ -32,11 +32,22 @@ use Illuminate\Support\Collection; */ interface BillRepositoryInterface { + /** + * TODO duplicate of other repos + * Add correct order to bills. + */ + public function correctOrder(): void; + /** * @return Collection */ public function getActiveBills(): Collection; + /** + * @return Collection + */ + public function getBills(): Collection; + /** * Between start and end, tells you on which date(s) the bill is expected to hit. * diff --git a/app/Support/Http/Api/ConvertsExchangeRates.php b/app/Support/Http/Api/ConvertsExchangeRates.php index 42fe3119de..b34eecd144 100644 --- a/app/Support/Http/Api/ConvertsExchangeRates.php +++ b/app/Support/Http/Api/ConvertsExchangeRates.php @@ -42,6 +42,7 @@ trait ConvertsExchangeRates * @param array $set * * @return array + * @deprecated */ public function cerChartSet(array $set): array { @@ -80,6 +81,7 @@ trait ConvertsExchangeRates /** * @return void + * @deprecated */ private function getPreference(): void { @@ -90,6 +92,7 @@ trait ConvertsExchangeRates * @param int $currencyId * * @return TransactionCurrency + * @deprecated */ private function getCurrency(int $currencyId): TransactionCurrency { @@ -107,6 +110,8 @@ trait ConvertsExchangeRates * * @return string * @throws FireflyException + * + * @deprecated */ private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string { @@ -140,6 +145,8 @@ trait ConvertsExchangeRates * @param string $date * * @return string|null + * + * @deprecated */ private function getFromDB(int $from, int $to, string $date): ?string { @@ -178,6 +185,8 @@ trait ConvertsExchangeRates * * @return string * @throws FireflyException + * + * @deprecated */ private function getEuroRate(TransactionCurrency $currency, Carbon $date): string { @@ -212,6 +221,8 @@ trait ConvertsExchangeRates /** * @return int * @throws FireflyException + * + * @deprecated */ private function getEuroId(): int { @@ -293,6 +304,8 @@ trait ConvertsExchangeRates * @param Carbon|null $date * * @return string + * + * @deprecated */ private function convertAmount(string $amount, TransactionCurrency $from, TransactionCurrency $to, ?Carbon $date = null): string { diff --git a/app/Transformers/V2/BillTransformer.php b/app/Transformers/V2/BillTransformer.php new file mode 100644 index 0000000000..19bd4cf8ef --- /dev/null +++ b/app/Transformers/V2/BillTransformer.php @@ -0,0 +1,320 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers\V2; + +use Carbon\Carbon; +use Carbon\CarbonInterface; +use FireflyIII\Models\Bill; +use FireflyIII\Models\Note; +use FireflyIII\Models\ObjectGroup; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use Illuminate\Support\Collection; +use Illuminate\Support\Facades\DB; +use Log; + +/** + * Class BillTransformer + */ +class BillTransformer extends AbstractTransformer +{ + private array $currencies; + private TransactionCurrency $default; + private array $groups; + private array $notes; + private array $paidDates; + private BillRepositoryInterface $repository; + + /** + * BillTransformer constructor. + * + + */ + public function __construct() + { + $this->repository = app(BillRepositoryInterface::class); + } + + /** + * @inheritDoc + */ + public function collectMetaData(Collection $objects): void + { + $currencies = []; + $bills = []; + $this->notes = []; + $this->groups = []; + $this->paidDates = []; + + + // start with currencies: + /** @var Bill $object */ + foreach ($objects as $object) { + $id = (int)$object->transaction_currency_id; + $bills[] = (int)$object->id; + $currencies[$id] = $currencies[$id] ?? TransactionCurrency::find($id); + } + $this->currencies = $currencies; + + // continue with notes + $notes = Note::whereNoteableType(Bill::class)->whereIn('noteable_id', array_keys($bills))->get(); + /** @var Note $note */ + foreach ($notes as $note) { + $id = (int)$note->noteable_id; + $this->notes[$id] = $note; + } + // grab object groups: + $set = DB::table('object_groupables') + ->leftJoin('object_groups', 'object_groups.id', '=', 'object_groupables.object_group_id') + ->where('object_groupables.object_groupable_type', Bill::class) + ->get(['object_groupables.*', 'object_groups.title', 'object_groups.order']); + /** @var ObjectGroup $entry */ + foreach ($set as $entry) { + $billId = (int)$entry->object_groupable_id; + $id = (int)$entry->object_group_id; + $order = (int)$entry->order; + $this->groups[$billId] = [ + 'object_group_id' => $id, + 'object_group_title' => $entry->title, + 'object_group_order' => $order, + ]; + + } + $this->default = app('amount')->getDefaultCurrency(); + + // grab all paid dates: + if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { + $journals = TransactionJournal::whereIn('bill_id', $bills) + ->where('date', '>=', $this->parameters->get('start')) + ->where('date', '<=', $this->parameters->get('end')) + ->get(['transaction_journals.id', 'transaction_journals.transaction_group_id', 'transaction_journals.date', 'transaction_journals.bill_id']); + /** @var TransactionJournal $journal */ + foreach ($journals as $journal) { + $billId = (int)$journal->bill_id; + $this->paidDates[$billId][] = [ + 'transaction_group_id' => (string)$journal->id, + 'transaction_journal_id' => (string)$journal->transaction_group_id, + 'date' => $journal->date->toAtomString(), + ]; + } + } + } + + /** + * Transform the bill. + * + * @param Bill $bill + * + * @return array + */ + public function transform(Bill $bill): array + { + $paidData = $this->paidDates[(int)$bill->id] ?? []; + $nextExpectedMatch = $this->nextExpectedMatch($bill, $this->paidDates[(int)$bill->id] ?? []); + $payDates = $this->payDates($bill); + $currency = $this->currencies[(int)$bill->transaction_currency_id]; + $group = $this->groups[(int)$bill->id] ?? null; + $nextExpectedMatchDiff = $this->getNextExpectedMatchDiff($nextExpectedMatch, $payDates); + return [ + 'id' => (int)$bill->id, + 'created_at' => $bill->created_at->toAtomString(), + 'updated_at' => $bill->updated_at->toAtomString(), + 'name' => $bill->name, + 'amount_min' => app('steam')->bcround($bill->amount_min, $currency->decimal_places), + 'amount_max' => app('steam')->bcround($bill->amount_max, $currency->decimal_places), + 'currency_id' => (string)$bill->transaction_currency_id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => (int)$currency->decimal_places, + 'date' => $bill->date->toAtomString(), + 'end_date' => $bill->end_date?->toAtomString(), + 'extension_date' => $bill->extension_date?->toAtomString(), + 'repeat_freq' => $bill->repeat_freq, + 'skip' => (int)$bill->skip, + 'active' => $bill->active, + 'order' => (int)$bill->order, + 'notes' => $this->notes[(int)$bill->id] ?? null, + 'object_group_id' => $group ? $group['object_group_id'] : null, + 'object_group_order' => $group ? $group['object_group_order'] : null, + 'object_group_title' => $group ? $group['object_group_title'] : null, + 'next_expected_match' => $nextExpectedMatch->toAtomString(), + 'next_expected_match_diff' => $nextExpectedMatchDiff, + 'pay_dates' => $payDates, + 'paid_dates' => $paidData, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => sprintf('/bills/%d', $bill->id), + ], + ], + ]; + } + + /** + * Get the data the bill was paid and predict the next expected match. + * + * @param Bill $bill + * @param array $dates + * + * @return Carbon + */ + protected function nextExpectedMatch(Bill $bill, array $dates): Carbon + { + // 2023-07-1 sub one day from the start date to fix a possible bug (see #7704) + // 2023-07-18 this particular date is used to search for the last paid date. + // 2023-07-18 the cloned $searchDate is used to grab the correct transactions. + /** @var Carbon $start */ + $start = clone $this->parameters->get('start'); + $start->subDay(); + + $lastPaidDate = $this->lastPaidDate($dates, $start); + $nextMatch = clone $bill->date; + while ($nextMatch < $lastPaidDate) { + /* + * As long as this date is smaller than the last time the bill was paid, keep jumping ahead. + * For example: 1 jan, 1 feb, etc. + */ + $nextMatch = app('navigation')->addPeriod($nextMatch, $bill->repeat_freq, $bill->skip); + } + if ($nextMatch->isSameDay($lastPaidDate)) { + /* + * Add another period because it's the same day as the last paid date. + */ + $nextMatch = app('navigation')->addPeriod($nextMatch, $bill->repeat_freq, $bill->skip); + } + return $nextMatch; + } + + /** + * Returns the latest date in the set, or start when set is empty. + * + * @param Collection $dates + * @param Carbon $default + * + * @return Carbon + */ + protected function lastPaidDate(array $dates, Carbon $default): Carbon + { + if (0 === count($dates)) { + return $default; + } + $latest = $dates[0]['date']; + /** @var array $row */ + foreach ($dates as $row) { + $carbon = new Carbon($row['date']); + if ($carbon->gte($latest)) { + $latest = $row['date']; + } + } + + return new Carbon($latest); + } + + /** + * @param Bill $bill + * + * @return array + */ + protected function payDates(Bill $bill): array + { + //Log::debug(sprintf('Now in payDates() for bill #%d', $bill->id)); + if (null === $this->parameters->get('start') || null === $this->parameters->get('end')) { + //Log::debug('No start or end date, give empty array.'); + + return []; + } + $set = new Collection(); + $currentStart = clone $this->parameters->get('start'); + // 2023-06-23 subDay to fix 7655 + $currentStart->subDay(); + $loop = 0; + while ($currentStart <= $this->parameters->get('end')) { + $nextExpectedMatch = $this->nextDateMatch($bill, $currentStart); + // If nextExpectedMatch is after end, we continue: + if ($nextExpectedMatch > $this->parameters->get('end')) { + break; + } + // add to set + $set->push(clone $nextExpectedMatch); + $nextExpectedMatch->addDay(); + $currentStart = clone $nextExpectedMatch; + $loop++; + if ($loop > 4) { + break; + } + } + $simple = $set->map( + static function (Carbon $date) { + return $date->toAtomString(); + } + ); + + return $simple->toArray(); + } + + /** + * Given a bill and a date, this method will tell you at which moment this bill expects its next + * transaction. Whether or not it is there already, is not relevant. + * + * @param Bill $bill + * @param Carbon $date + * + * @return Carbon + */ + protected function nextDateMatch(Bill $bill, Carbon $date): Carbon + { + //Log::debug(sprintf('Now in nextDateMatch(%d, %s)', $bill->id, $date->format('Y-m-d'))); + $start = clone $bill->date; + //Log::debug(sprintf('Bill start date is %s', $start->format('Y-m-d'))); + while ($start < $date) { + $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + } + + //Log::debug(sprintf('End of loop, bill start date is now %s', $start->format('Y-m-d'))); + + return $start; + } + + /** + * @param Carbon $next + * @param array $dates + * + * @return string + */ + private function getNextExpectedMatchDiff(Carbon $next, array $dates): string + { + if ($next->isToday()) { + return trans('firefly.today'); + } + $current = $dates[0] ?? null; + if (null === $current) { + return trans('firefly.not_expected_period'); + } + $carbon = new Carbon($current); + return $carbon->diffForHumans(today(config('app.timezone')), CarbonInterface::DIFF_RELATIVE_TO_NOW); + } + + +} diff --git a/routes/api.php b/routes/api.php index b862f6dda7..46a67cb10e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -124,15 +124,16 @@ Route::group( ); /** - * V2 API route for bills. + * V2 API route for subscriptions. */ Route::group( [ 'namespace' => 'FireflyIII\Api\V2\Controllers\Model\Bill', - 'prefix' => 'v2/bills', - 'as' => 'api.v2.bills.', + 'prefix' => 'v2/subscriptions', + 'as' => 'api.v2.subscriptions.', ], static function () { + Route::get('', ['uses' => 'ShowController@index', 'as' => 'index']); Route::get('sum/paid', ['uses' => 'SumController@paid', 'as' => 'sum.paid']); Route::get('sum/unpaid', ['uses' => 'SumController@unpaid', 'as' => 'sum.unpaid']); }