API: Rename rooms to locations and start/end to starts_at/ends_at
This commit is contained in:
parent
2e38b55167
commit
497c1772f7
|
@ -121,8 +121,8 @@ $route->addGroup(
|
||||||
|
|
||||||
$route->get('/angeltypes', 'Api\AngelTypeController@index');
|
$route->get('/angeltypes', 'Api\AngelTypeController@index');
|
||||||
$route->get('/news', 'Api\NewsController@index');
|
$route->get('/news', 'Api\NewsController@index');
|
||||||
$route->get('/rooms', 'Api\RoomsController@index');
|
$route->get('/locations', 'Api\LocationsController@index');
|
||||||
$route->get('/rooms/{room_id:\d+}/shifts', 'Api\ShiftsController@entriesByRoom');
|
$route->get('/locations/{location_id:\d+}/shifts', 'Api\ShiftsController@entriesByLocation');
|
||||||
|
|
||||||
$route->addRoute(
|
$route->addRoute(
|
||||||
['POST', 'PUT', 'DELETE', 'PATCH'],
|
['POST', 'PUT', 'DELETE', 'PATCH'],
|
||||||
|
|
|
@ -140,7 +140,7 @@ components:
|
||||||
- created_at
|
- created_at
|
||||||
- updated_at
|
- updated_at
|
||||||
- url
|
- url
|
||||||
Room:
|
Location:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
|
@ -151,8 +151,8 @@ components:
|
||||||
example: Heaven
|
example: Heaven
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
example: https://example.com/rooms/42
|
example: https://example.com/location/42
|
||||||
description: Link of the room start page
|
description: Link of the location page
|
||||||
required:
|
required:
|
||||||
- id
|
- id
|
||||||
- name
|
- name
|
||||||
|
@ -172,18 +172,18 @@ components:
|
||||||
description: |
|
description: |
|
||||||
Shift description, should be added to the shift type description as it might be empty.
|
Shift description, should be added to the shift type description as it might be empty.
|
||||||
Normally contains additional information for a specific shift / task.
|
Normally contains additional information for a specific shift / task.
|
||||||
start:
|
starts_at:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
description: DateTime in ISO-8601 format
|
description: DateTime in ISO-8601 format
|
||||||
example: 2023-05-13T14:00:00.000000Z
|
example: 2023-05-13T14:00:00.000000Z
|
||||||
end:
|
ends_at:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
description: DateTime in ISO-8601 format
|
description: DateTime in ISO-8601 format
|
||||||
example: 2023-05-13T16:00:00.000000Z23
|
example: 2023-05-13T16:00:00.000000Z23
|
||||||
room:
|
location:
|
||||||
$ref: '#/components/schemas/Room'
|
$ref: '#/components/schemas/Location'
|
||||||
shift_type:
|
shift_type:
|
||||||
$ref: '#/components/schemas/ShiftType'
|
$ref: '#/components/schemas/ShiftType'
|
||||||
created_at:
|
created_at:
|
||||||
|
@ -211,9 +211,9 @@ components:
|
||||||
- id
|
- id
|
||||||
- title
|
- title
|
||||||
- description
|
- description
|
||||||
- start
|
- starts_at
|
||||||
- end
|
- ends_at
|
||||||
- room
|
- location
|
||||||
- shift_type
|
- shift_type
|
||||||
- created_at
|
- created_at
|
||||||
- updated_at
|
- updated_at
|
||||||
|
@ -349,11 +349,11 @@ paths:
|
||||||
'403':
|
'403':
|
||||||
$ref: '#/components/responses/ForbiddenError'
|
$ref: '#/components/responses/ForbiddenError'
|
||||||
|
|
||||||
/rooms:
|
/locations:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- shift
|
- shift
|
||||||
summary: Get a list of rooms
|
summary: Get a list of locations
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Ok
|
description: Ok
|
||||||
|
@ -365,25 +365,25 @@ paths:
|
||||||
data:
|
data:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/Room'
|
$ref: '#/components/schemas/Location'
|
||||||
'401':
|
'401':
|
||||||
$ref: '#/components/responses/UnauthorizedError'
|
$ref: '#/components/responses/UnauthorizedError'
|
||||||
'403':
|
'403':
|
||||||
$ref: '#/components/responses/ForbiddenError'
|
$ref: '#/components/responses/ForbiddenError'
|
||||||
|
|
||||||
/rooms/{id}/shifts:
|
/locations/{id}/shifts:
|
||||||
parameters:
|
parameters:
|
||||||
- name: id
|
- name: id
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: The rooms identifier
|
description: The locations identifier
|
||||||
example: 42
|
example: 42
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- shift
|
- shift
|
||||||
summary: Get all shifts in the requested room
|
summary: Get all shifts in the requested location
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Ok
|
description: Ok
|
||||||
|
|
|
@ -5,18 +5,18 @@ declare(strict_types=1);
|
||||||
namespace Engelsystem\Controllers\Api;
|
namespace Engelsystem\Controllers\Api;
|
||||||
|
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
|
|
||||||
class RoomsController extends ApiController
|
class LocationsController extends ApiController
|
||||||
{
|
{
|
||||||
public function index(): Response
|
public function index(): Response
|
||||||
{
|
{
|
||||||
$models = Room::query()
|
$models = Location::query()
|
||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->get(['id', 'name']);
|
->get(['id', 'name']);
|
||||||
|
|
||||||
$models->map(function (Room $model): void {
|
$models->map(function (Location $model): void {
|
||||||
$model->url = $this->url->to('/rooms', ['action' => 'view', 'room_id' => $model->id]);
|
$model->url = $this->url->to('/locations', ['action' => 'view', 'location_id' => $model->id]);
|
||||||
});
|
});
|
||||||
|
|
||||||
$data = ['data' => $models];
|
$data = ['data' => $models];
|
|
@ -6,23 +6,23 @@ namespace Engelsystem\Controllers\Api;
|
||||||
|
|
||||||
use Engelsystem\Http\Request;
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class ShiftsController extends ApiController
|
class ShiftsController extends ApiController
|
||||||
{
|
{
|
||||||
public function entriesByRoom(Request $request): Response
|
public function entriesByLocation(Request $request): Response
|
||||||
{
|
{
|
||||||
$roomId = (int) $request->getAttribute('room_id');
|
$locationId = (int) $request->getAttribute('location_id');
|
||||||
/** @var Room $room */
|
/** @var Location $location */
|
||||||
$room = Room::findOrFail($roomId);
|
$location = Location::findOrFail($locationId);
|
||||||
/** @var Shift[]|Collection $shifts */
|
/** @var Shift[]|Collection $shifts */
|
||||||
$shifts = $room->shifts()
|
$shifts = $location->shifts()
|
||||||
->with([
|
->with([
|
||||||
'neededAngelTypes.angelType',
|
'neededAngelTypes.angelType',
|
||||||
'room',
|
'location.neededAngelTypes.angelType',
|
||||||
'shiftEntries.angelType',
|
'shiftEntries.angelType',
|
||||||
'shiftEntries.user.contact',
|
'shiftEntries.user.contact',
|
||||||
'shiftEntries.user.personalData',
|
'shiftEntries.user.personalData',
|
||||||
|
@ -70,16 +70,16 @@ class ShiftsController extends ApiController
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$roomData = $room->only(['id', 'name']);
|
$locationData = $location->only(['id', 'name']);
|
||||||
$roomData['url'] = $this->url->to('/rooms', ['action' => 'view', 'room_id' => $room->id]);
|
$locationData['url'] = $this->url->to('/locations', ['action' => 'view', 'location_id' => $location->id]);
|
||||||
|
|
||||||
$shiftEntries[] = [
|
$shiftEntries[] = [
|
||||||
'id' => $shift->id,
|
'id' => $shift->id,
|
||||||
'title' => $shift->title,
|
'title' => $shift->title,
|
||||||
'description' => $shift->description,
|
'description' => $shift->description,
|
||||||
'start' => $shift->start,
|
'starts_at' => $shift->start,
|
||||||
'end' => $shift->end,
|
'ends_at' => $shift->end,
|
||||||
'room' => $roomData,
|
'location' => $locationData,
|
||||||
'shift_type' => $shift->shiftType->only(['id', 'name', 'description']),
|
'shift_type' => $shift->shiftType->only(['id', 'name', 'description']),
|
||||||
'created_at' => $shift->created_at,
|
'created_at' => $shift->created_at,
|
||||||
'updated_at' => $shift->updated_at,
|
'updated_at' => $shift->updated_at,
|
||||||
|
@ -101,8 +101,8 @@ class ShiftsController extends ApiController
|
||||||
// From shift
|
// From shift
|
||||||
$neededAngelTypes = $shift->neededAngelTypes;
|
$neededAngelTypes = $shift->neededAngelTypes;
|
||||||
|
|
||||||
// Add from room
|
// Add from location
|
||||||
foreach ($shift->room->neededAngelTypes as $neededAngelType) {
|
foreach ($shift->location->neededAngelTypes as $neededAngelType) {
|
||||||
/** @var NeededAngelType $existingNeededAngelType */
|
/** @var NeededAngelType $existingNeededAngelType */
|
||||||
$existingNeededAngelType = $neededAngelTypes
|
$existingNeededAngelType = $neededAngelTypes
|
||||||
->where('angel_type_id', $neededAngelType->angel_type_id)
|
->where('angel_type_id', $neededAngelType->angel_type_id)
|
||||||
|
@ -112,7 +112,7 @@ class ShiftsController extends ApiController
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$existingNeededAngelType->room_id = $shift->room->id;
|
$existingNeededAngelType->location_id = $shift->location->id;
|
||||||
$existingNeededAngelType->count += $neededAngelType->count;
|
$existingNeededAngelType->count += $neededAngelType->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,24 +4,23 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Engelsystem\Test\Unit\Controllers\Api;
|
namespace Engelsystem\Test\Unit\Controllers\Api;
|
||||||
|
|
||||||
use Engelsystem\Controllers\Api\RoomsController;
|
use Engelsystem\Controllers\Api\LocationsController;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
|
|
||||||
class RoomsControllerTest extends ApiBaseControllerTest
|
class LocationsControllerTest extends ApiBaseControllerTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Api\RoomsController::index
|
* @covers \Engelsystem\Controllers\Api\LocationsController::index
|
||||||
*/
|
*/
|
||||||
public function testIndex(): void
|
public function testIndex(): void
|
||||||
{
|
{
|
||||||
$this->initDatabase();
|
$items = Location::factory(3)->create();
|
||||||
$items = Room::factory(3)->create();
|
|
||||||
|
|
||||||
$controller = new RoomsController(new Response(), $this->url);
|
$controller = new LocationsController(new Response(), $this->url);
|
||||||
|
|
||||||
$response = $controller->index();
|
$response = $controller->index();
|
||||||
$this->validateApiResponse('/rooms', 'get', $response);
|
$this->validateApiResponse('/locations', 'get', $response);
|
||||||
|
|
||||||
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
|
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
|
||||||
$this->assertJson($response->getContent());
|
$this->assertJson($response->getContent());
|
|
@ -8,7 +8,7 @@ use Engelsystem\Controllers\Api\ShiftsController;
|
||||||
use Engelsystem\Helpers\Carbon;
|
use Engelsystem\Helpers\Carbon;
|
||||||
use Engelsystem\Http\Request;
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
|
@ -19,55 +19,58 @@ use Engelsystem\Models\User\User;
|
||||||
class ShiftsControllerTest extends ApiBaseControllerTest
|
class ShiftsControllerTest extends ApiBaseControllerTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Api\ShiftsController::entriesByRoom
|
* @covers \Engelsystem\Controllers\Api\ShiftsController::entriesByLocation
|
||||||
* @covers \Engelsystem\Controllers\Api\ShiftsController::getNeededAngelTypes
|
* @covers \Engelsystem\Controllers\Api\ShiftsController::getNeededAngelTypes
|
||||||
*/
|
*/
|
||||||
public function testEntriesByRoom(): void
|
public function testEntriesByLocation(): void
|
||||||
{
|
{
|
||||||
$this->initDatabase();
|
$this->initDatabase();
|
||||||
|
|
||||||
/** @var Room $room */
|
/** @var Location $location */
|
||||||
$room = Room::factory()->create();
|
$location = Location::factory()->create();
|
||||||
|
|
||||||
// Shifts
|
// Shifts
|
||||||
/** @var Shift $shiftA */
|
/** @var Shift $shiftA */
|
||||||
$shiftA = Shift::factory(1)
|
$shiftA = Shift::factory(1)
|
||||||
->create(['room_id' => $room->id, 'start' => Carbon::now()->subHour()])
|
->create(['location_id' => $location->id, 'start' => Carbon::now()->subHour()])
|
||||||
->first();
|
->first();
|
||||||
/** @var Shift $shiftB */
|
/** @var Shift $shiftB */
|
||||||
$shiftB = Shift::factory(1)
|
$shiftB = Shift::factory(1)
|
||||||
->create(['room_id' => $room->id, 'start' => Carbon::now()->addHour()])
|
->create(['location_id' => $location->id, 'start' => Carbon::now()->addHour()])
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
// "Empty" entry to be skipped
|
// "Empty" entry to be skipped
|
||||||
NeededAngelType::factory(1)->create(['room_id' => null, 'shift_id' => $shiftA->id, 'count' => 0]);
|
NeededAngelType::factory(1)->create(['location_id' => null, 'shift_id' => $shiftA->id, 'count' => 0]);
|
||||||
|
|
||||||
// Needed entry by shift
|
// Needed entry by shift
|
||||||
/** @var NeededAngelType $byShift */
|
/** @var NeededAngelType $byShift */
|
||||||
$byShift = NeededAngelType::factory(2)
|
$byShift = NeededAngelType::factory(2)
|
||||||
->create(['room_id' => null, 'shift_id' => $shiftA->id, 'count' => 2])
|
->create(['location_id' => null, 'shift_id' => $shiftA->id, 'count' => 2])
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
// Needed entry by room
|
// Needed entry by location
|
||||||
/** @var NeededAngelType $byRoom */
|
/** @var NeededAngelType $byLocation */
|
||||||
$byRoom = NeededAngelType::factory(1)
|
$byLocation = NeededAngelType::factory(1)
|
||||||
->create(['room_id' => $room->id, 'shift_id' => null, 'count' => 3])
|
->create(['location_id' => $location->id, 'shift_id' => null, 'count' => 3])
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
// Added by both
|
// Added by both
|
||||||
NeededAngelType::factory(1)
|
NeededAngelType::factory(1)
|
||||||
->create([
|
->create([
|
||||||
'room_id' => $room->id, 'shift_id' => null, 'angel_type_id' => $byShift->angel_type_id, 'count' => 3,
|
'location_id' => $location->id,
|
||||||
|
'shift_id' => null,
|
||||||
|
'angel_type_id' => $byShift->angel_type_id,
|
||||||
|
'count' => 3,
|
||||||
])
|
])
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
// By shift
|
// By shift
|
||||||
ShiftEntry::factory(2)->create(['shift_id' => $shiftA->id, 'angel_type_id' => $byShift->angel_type_id]);
|
ShiftEntry::factory(2)->create(['shift_id' => $shiftA->id, 'angel_type_id' => $byShift->angel_type_id]);
|
||||||
|
|
||||||
// By room
|
// By location
|
||||||
ShiftEntry::factory(1)->create(['shift_id' => $shiftA->id, 'angel_type_id' => $byRoom->angel_type_id]);
|
ShiftEntry::factory(1)->create(['shift_id' => $shiftA->id, 'angel_type_id' => $byLocation->angel_type_id]);
|
||||||
|
|
||||||
// Additional (not required by shift nor room)
|
// Additional (not required by shift nor location)
|
||||||
ShiftEntry::factory(1)->create(['shift_id' => $shiftA->id]);
|
ShiftEntry::factory(1)->create(['shift_id' => $shiftA->id]);
|
||||||
|
|
||||||
foreach (User::all() as $user) {
|
foreach (User::all() as $user) {
|
||||||
|
@ -78,12 +81,12 @@ class ShiftsControllerTest extends ApiBaseControllerTest
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = new Request();
|
$request = new Request();
|
||||||
$request = $request->withAttribute('room_id', $room->id);
|
$request = $request->withAttribute('location_id', $location->id);
|
||||||
|
|
||||||
$controller = new ShiftsController(new Response(), $this->url);
|
$controller = new ShiftsController(new Response(), $this->url);
|
||||||
|
|
||||||
$response = $controller->entriesByRoom($request);
|
$response = $controller->entriesByLocation($request);
|
||||||
$this->validateApiResponse('/rooms/{id}/shifts', 'get', $response);
|
$this->validateApiResponse('/locations/{id}/shifts', 'get', $response);
|
||||||
|
|
||||||
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
|
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
|
||||||
$this->assertJson($response->getContent());
|
$this->assertJson($response->getContent());
|
||||||
|
@ -95,7 +98,7 @@ class ShiftsControllerTest extends ApiBaseControllerTest
|
||||||
// First shift
|
// First shift
|
||||||
$shiftAData = $data['data'][0];
|
$shiftAData = $data['data'][0];
|
||||||
$this->assertEquals($shiftA->title, $shiftAData['title'], 'Title is equal');
|
$this->assertEquals($shiftA->title, $shiftAData['title'], 'Title is equal');
|
||||||
$this->assertEquals($room->id, $shiftAData['room']['id'], 'Same room');
|
$this->assertEquals($location->id, $shiftAData['location']['id'], 'Same location');
|
||||||
$this->assertEquals($shiftA->shiftType->id, $shiftAData['shift_type']['id'], 'Shift type equals');
|
$this->assertEquals($shiftA->shiftType->id, $shiftAData['shift_type']['id'], 'Shift type equals');
|
||||||
$this->assertCount(4, $shiftAData['entries']);
|
$this->assertCount(4, $shiftAData['entries']);
|
||||||
// Has users
|
// Has users
|
||||||
|
@ -112,7 +115,7 @@ class ShiftsControllerTest extends ApiBaseControllerTest
|
||||||
// Second (empty) shift
|
// Second (empty) shift
|
||||||
$shiftBData = $data['data'][1];
|
$shiftBData = $data['data'][1];
|
||||||
$this->assertEquals($shiftB->title, $shiftBData['title'], 'Title is equal');
|
$this->assertEquals($shiftB->title, $shiftBData['title'], 'Title is equal');
|
||||||
$this->assertEquals($room->id, $shiftBData['room']['id'], 'Same room');
|
$this->assertEquals($location->id, $shiftBData['location']['id'], 'Same location');
|
||||||
$this->assertEquals($shiftB->shiftType->id, $shiftBData['shift_type']['id'], 'Shift type equals');
|
$this->assertEquals($shiftB->shiftType->id, $shiftBData['shift_type']['id'], 'Shift type equals');
|
||||||
$this->assertCount(2, $shiftBData['entries']);
|
$this->assertCount(2, $shiftBData['entries']);
|
||||||
// No users
|
// No users
|
||||||
|
|
Loading…
Reference in New Issue