Skip to content

Commit

Permalink
Merge pull request #182 from deanblackborough/v2.11.0
Browse files Browse the repository at this point in the history
v2.11.0
  • Loading branch information
deanblackborough authored Jun 6, 2020
2 parents dd1bd7b + efe6ca3 commit 4b8ea19
Show file tree
Hide file tree
Showing 99 changed files with 881 additions and 340 deletions.
2 changes: 1 addition & 1 deletion .docker/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM php:7.3-apache
FROM php:7.4-apache

COPY . /var/www/html
COPY .docker/api/vhost.conf /etc/apache2/sites-available/000-default.conf
Expand Down
6 changes: 3 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
APP_NAME=costs-to-expect
APP_NAME=cte-api
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://api.local
APP_REGISTRATIONS=false
APP_URL=http://localhost:8080
APP_REGISTRATIONS=true

APP_HASH_MIN_LENGTH=
APP_HASH_SALT_CATEGORY=
Expand Down
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,38 @@

The complete changelog for the Costs to Expect REST API, our changelog follows the format defined at https://keepachangelog.com/en/1.0.0/

## [v2.11.0] - 2020-06-06
### Added
- We have added search to the categories summary endpoint.
- We have added search to the subcategories summary endpoint.
- We have added search to the resources summary endpoint.
- We have added search to the resource-types summary endpoint.
- We have updated the transfers collection; you can filter the results by an `item` ID.
- We have updated the partial transfers collection; you can filter the results by an `item` ID.
- We have added additional filtering options for collections. We have added `total` and `actualised_total` range filtering for the `allocated-expense` item type and `total` range filtering for the `simple-expense` item type.

### Changed
- We have added the documentation URI to the README and API; the documentation for the API is work in progress; it is almost complete.
- We have added a version query parameter to the CSS include.
- We have removed a unique index on the `item_transfer` table; the index was limiting the ability to transfer an item multiple times.
- We have altered the format of the category and subcategory object for item relationships; the returned object is now a closer match to a category object.
- We have updated the URIs for item category and subcategory assignments; the URI was singular for a collection.
- We have updated the item delete endpoint; we did not return a conflict error before removing relationships.
- We have tweaked the `type` for expense fields; we highlight that the supplied value should be a decimal string.

### Fixed
- The `name` field now displays as a required field in the items collection OPTIONS request.
- The `filterable` array shows in the OPTIONS response for resource type items.
- We have updated the namespace in a model.
- We have corrected the case of a model name.
- We have added the migrations for the original item-types, missing from the import.
- We have added a database migration to update the `friendly_name` and `examples` data for `item-types`.
- We have updated the delete item request; we delete the transfer log entries for the item.
- We have updated two `item-type` summary endpoints to show they are sortable by `name`.

### Removed
- We have removed the category and subcategory item assigned URIs and replaced them with correctly named URIs for collections.

## [v2.10.4] - 2020-05-23
### Fixed
- We have adjusted the lottery value to reduce session clears.
Expand Down
48 changes: 27 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@

Costs to Expect is a service which focuses on tracking and forecasting expenses.
The Costs to Expect API is the backbone of the service and is not going to be
limited to expenses; however, we figured that is was an excellent place to start.
limited to expenses; however, we figured that it was an excellent place to start.

## Docs

We are working hard to get the documentation ready, the App will not enter beta
until the API documentation is ready, the documentation can be found at
[postman.costs-to-expect.com](https://postman.costs-to-expect.com?version=latest)

### The App
The [alpha](https://app.costs-to-expect.com) for the service is online, we are
hoping to release the public alpha at the start of April 2020. Please check
the [app.costs-to-expect.com/roadmap](https://app.costs-to-expect.com/roadmap)
and changelog to see how we are getting on
[app.costs-to-expect.com/changelog](https://app.costs-to-expect.com/changelog)
hoping to release the public beta soon(tm). Please check
our [app.costs-to-expect.com/roadmap](https://app.costs-to-expect.com/roadmap)
and [app.costs-to-expect.com/changelog](https://app.costs-to-expect.com/changelog)
to see how we are progressing.

### The Website
A small part of the service is tracking the costs to raise a child in the UK,
Expand Down Expand Up @@ -53,10 +59,10 @@ and then running any migrations and install Passport.
* `docker-compose exec api php artisan key:generate`
* `docker-compose exec api php artisan migrate`
* `docker-compose exec api php artisan passport:install`
* Run an OPTIONS request on `http://[your.domail.local]/v2/resource_types`, you should see a nice OPTIONS request,
alternatively a GET request to `http://[your.domail.local]/v1` will show all the routes.
* You can add a development user by POSTing to `http://[your.domail.local]/v2/auth/register` and then get a bearer by
POSTing to `http://[your.domail.local]/v2/auth/login` - you will need a bearer for all the routes that require authentication.
* Run an OPTIONS request on `http://[your.domail.local:8080]/v2/resource_types`, you should see a nice OPTIONS request,
alternatively a GET request to `http://[your.domail.local:8080]/v1` will show all the routes.
* You can add a development user by POSTing to `http://[your.domail.local:8080]/v2/auth/register` and then get a bearer by
POSTing to `http://[your.domail.local:8080]/v2/auth/login` - you will need a bearer for all the routes that require authentication.
* The API is setup to use Mailgun by default, populate `MAILGUN_DOMAIN` and `MAILGUN_SECRET` with values from your account,
you will also need to set `MAIL_FROM_ADDRESS` and `MAIL_TO_ADDRESS`. You may need to set `Authorized Recipients` in Mailgun.

Expand Down Expand Up @@ -153,18 +159,18 @@ additionally, the same is true if you are assigned to a resource type.
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id} |
| PATCH | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id} |
| DELETE | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id} |
| GET/HEAD | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category |
| POST | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category |
| GET/HEAD | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id} |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id} |
| DELETE | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id} |
| GET/HEAD | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id}/subcategory |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id}/subcategory |
| POST | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id}/sub_category |
| GET/HEAD | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id}/subcategory/{item_subcategory_id} |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id}/subcategory/{item_subcategory_id} |
| DELETE | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/category/{item_category_id}/sub_category/{item_subcategory_id} |
| GET/HEAD | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories |
| POST | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories |
| GET/HEAD | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id} |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id} |
| DELETE | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id} |
| GET/HEAD | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id}/subcategories |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id}/subcategories |
| POST | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id}/subcategories |
| GET/HEAD | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id}/subcategories/{item_subcategory_id} |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id}/subcategories/{item_subcategory_id} |
| DELETE | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/categories/{item_category_id}/subcategories/{item_subcategory_id} |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/partial-transfer |
| POST | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/partial-transfer |
| OPTIONS | v2/resource-types/{resource_type_id}/resources/{resource_id}/items/{item_id}/transfer |
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/CategoryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function index($resource_type_id): JsonResponse
);

$search_parameters = SearchParameters::fetch(
Config::get('api.category.searchable')
array_keys(Config::get('api.category.searchable'))
);

$total = (new Category())->total(
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Controllers/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public function index(Request $request)
'prefix' => $config['prefix'],
'release_date' => $config['release_date'],
'changelog' => $config['changelog'],
'readme' => $config['readme']
'readme' => $config['readme'],
'documentation' => $config['documentation']
],
'routes' => $routes_to_display
],
Expand Down
7 changes: 7 additions & 0 deletions app/Http/Controllers/ItemController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Controllers;

use App\Item\Factory;
use App\Models\ItemTransfer;
use App\Option\Delete;
use App\Option\Get;
use App\Option\Patch;
Expand Down Expand Up @@ -451,7 +452,13 @@ public function delete(
UtilityResponse::notFound(trans('entities.item'));
}

if (in_array($item_interface->type(), ['allocated-expense', 'simple-expense']) &&
$item_model->hasCategoryAssignments($item_id) === true) {
UtilityResponse::foreignKeyConstraintError();
}

try {
(new ItemTransfer())->deleteTransfers($item_id);
$item_type->delete();
$item->delete();

Expand Down
13 changes: 11 additions & 2 deletions app/Http/Controllers/ItemPartialTransferController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
use App\Utilities\Response as UtilityResponse;
use App\Utilities\RoutePermission;
use App\Validators\Fields\ItemPartialTransfer as ItemPartialTransferValidator;
use App\Validators\Parameters;
use App\Validators\Route;
use Exception;
use Illuminate\Database\QueryException;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Monolog\Utils;

/**
Expand All @@ -44,10 +46,15 @@ public function index($resource_type_id): JsonResponse
$this->permitted_resource_types
);

$parameters = Parameters::fetch(
array_keys(Config::get('api.item-transfer.parameters.collection'))
);

$total = (new ItemPartialTransfer())->total(
(int) $resource_type_id,
$this->permitted_resource_types,
$this->include_public
$this->include_public,
$parameters
);

$pagination = UtilityPagination::init(
Expand All @@ -63,7 +70,8 @@ public function index($resource_type_id): JsonResponse
$this->permitted_resource_types,
$this->include_public,
$pagination['offset'],
$pagination['limit']
$pagination['limit'],
$parameters
);

$headers = new Header();
Expand Down Expand Up @@ -232,6 +240,7 @@ public function optionsIndex($resource_type_id): JsonResponse
);

$get = Get::init()->
setParameters('api.item-partial-transfer.parameters.collection')->
setPagination(true)->
setAuthenticationStatus($permissions['view'])->
setDescription('route-descriptions.item_partial_transfer_GET_index')->
Expand Down
13 changes: 11 additions & 2 deletions app/Http/Controllers/ItemTransferController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
use App\Utilities\Response as UtilityResponse;
use App\Utilities\RoutePermission;
use App\Validators\Fields\ItemTransfer as ItemTransferValidator;
use App\Validators\Parameters;
use App\Validators\Route;
use Exception;
use Illuminate\Database\QueryException;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;

/**
* Transfer items
Expand All @@ -43,10 +45,15 @@ public function index($resource_type_id): JsonResponse
$this->permitted_resource_types
);

$parameters = Parameters::fetch(
array_keys(Config::get('api.item-transfer.parameters.collection'))
);

$total = (new ItemTransfer())->total(
(int) $resource_type_id,
$this->permitted_resource_types,
$this->include_public
$this->include_public,
$parameters
);

$pagination = UtilityPagination::init(
Expand All @@ -62,7 +69,8 @@ public function index($resource_type_id): JsonResponse
$this->permitted_resource_types,
$this->include_public,
$pagination['offset'],
$pagination['limit']
$pagination['limit'],
$parameters
);

$headers = new Header();
Expand Down Expand Up @@ -100,6 +108,7 @@ public function optionsIndex($resource_type_id): JsonResponse
);

$get = Get::init()->
setParameters('api.item-transfer.parameters.collection')->
setPagination(true)->
setAuthenticationStatus($permissions['view'])->
setDescription('route-descriptions.item_transfer_GET_index')->
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Controllers/ItemTypeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class ItemTypeController extends Controller
public function index(): JsonResponse
{
$search_parameters = SearchParameters::fetch(
Config::get('api.item-type.searchable')
array_keys(Config::get('api.item-type.searchable'))
);

$total = (new ItemType())->totalCount($search_parameters);
Expand All @@ -52,6 +52,7 @@ public function index(): JsonResponse
setSortParameters($sort_parameters)->
paging();


$item_types = (new ItemType())->paginatedCollection(
$pagination['offset'],
$pagination['limit'],
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/PermittedUserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function index(string $resource_type_id): JsonResponse
);

$search_parameters = SearchParameters::fetch(
Config::get('api.permitted-user.searchable')
array_keys(Config::get('api.permitted-user.searchable'))
);

$total = (new PermittedUser())->totalCount(
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/ResourceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function index(string $resource_type_id): JsonResponse
);

$search_parameters = SearchParameters::fetch(
Config::get('api.resource.searchable')
array_keys(Config::get('api.resource.searchable'))
);

$total = (new Resource())->totalCount(
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/ResourceTypeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ResourceTypeController extends Controller
public function index(): JsonResponse
{
$search_parameters = SearchParameters::fetch(
Config::get('api.resource-type.searchable')
array_keys(Config::get('api.resource-type.searchable'))
);

$total = (new ResourceType())->totalCount(
Expand Down
1 change: 1 addition & 0 deletions app/Http/Controllers/ResourceTypeItemController.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public function optionsIndex(string $resource_type_id): JsonResponse
$get = Get::init()->
setSortable($item_interface->sortParametersConfig())->
setSearchable($item_interface->searchParametersConfig())->
setFilterable($item_interface->filterParametersConfig())->
setPagination(true)->
setParameters($item_interface->collectionParametersConfig())->
setParametersData($parameters_data)->
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/SubcategoryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function index($resource_type_id, $category_id): JsonResponse
);

$search_parameters = SearchParameters::fetch(
Config::get('api.subcategory.searchable')
array_keys(Config::get('api.subcategory.searchable'))
);

$total = (new Subcategory())->totalCount(
Expand Down
10 changes: 9 additions & 1 deletion app/Http/Controllers/Summary/CategoryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use App\Utilities\Header;
use App\Utilities\RoutePermission;
use App\Validators\Route;
use App\Validators\SearchParameters;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Config;

/**
* Summary controller for the categories routes
Expand All @@ -33,10 +35,15 @@ public function index($resource_type_id): JsonResponse
$this->permitted_resource_types
);

$search_parameters = SearchParameters::fetch(
array_keys(Config::get('api.category.summary-searchable'))
);

$summary = (new Category())->total(
$resource_type_id,
$this->permitted_resource_types,
$this->include_public
$this->include_public,
$search_parameters
);

$headers = new Header();
Expand Down Expand Up @@ -75,6 +82,7 @@ public function optionsIndex($resource_type_id): JsonResponse
$get = Get::init()->
setDescription('route-descriptions.summary_category_GET_index')->
setAuthenticationStatus($permissions['view'])->
setSearchable('api.category.summary-searchable')->
option();

return $this->optionsResponse($get, 200);
Expand Down
10 changes: 9 additions & 1 deletion app/Http/Controllers/Summary/ResourceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use App\Utilities\RoutePermission;
use App\Validators\Route;
use App\Models\Summary\Resource;
use App\Validators\SearchParameters;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Config;

/**
* Summary controller for the resource routes
Expand All @@ -33,10 +35,15 @@ public function index(string $resource_type_id): JsonResponse
$this->permitted_resource_types
);

$search_parameters = SearchParameters::fetch(
array_keys(Config::get('api.resource.summary-searchable'))
);

$summary = (new Resource())->totalCount(
$resource_type_id,
$this->permitted_resource_types,
$this->include_public
$this->include_public,
$search_parameters
);

$headers = new Header();
Expand Down Expand Up @@ -76,6 +83,7 @@ public function optionsIndex(string $resource_type_id): JsonResponse
setParameters('api.resource.summary-parameters')->
setDescription('route-descriptions.summary-resource-GET-index')->
setAuthenticationStatus($permissions['view'])->
setSearchable('api.resource.summary-searchable')->
option();

return $this->optionsResponse($get, 200);
Expand Down
Loading

0 comments on commit 4b8ea19

Please sign in to comment.