introduce-booking-module #41
@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@ -122,7 +123,9 @@ public class HsBookingItemController implements HsBookingItemsApi {
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final BiConsumer<HsBookingItemInsertResource, HsBookingItemEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
||||
entity.setValidity(toPostgresDateRange(resource.getValidFrom(), resource.getValidTo()));
|
||||
entity.putResources((Map<String, Object>) resource.getResources());
|
||||
};
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
@ -122,6 +121,9 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject {
|
||||
}
|
||||
|
||||
public void putResources(Map<String, Object> entries) {
|
||||
if ( resourcesWrapper == null ) {
|
||||
resourcesWrapper = new PatchableMapWrapper(resources);
|
||||
}
|
||||
resourcesWrapper.assign(entries);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.hostsharing.hsadminng.hs.booking.item;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.ArbitraryBookingResourcesJsonResource;
|
||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingItemPatchResource;
|
||||
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
||||
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
||||
@ -25,7 +24,7 @@ public class HsBookingItemEntityPatcher implements EntityPatcher<HsBookingItemPa
|
||||
OptionalFromJson.of(resource.getCaption())
|
||||
.ifPresent(entity::setCaption);
|
||||
Optional.ofNullable(resource.getResources())
|
||||
.ifPresent(r -> entity.putResources(objectToMap(resource.getResources())));
|
||||
.ifPresent(r -> entity.getResources().patch(objectToMap(resource.getResources())));
|
||||
OptionalFromJson.of(resource.getValidFrom())
|
||||
.ifPresent(entity::setValidFrom);
|
||||
OptionalFromJson.of(resource.getValidTo())
|
||||
@ -33,6 +32,9 @@ public class HsBookingItemEntityPatcher implements EntityPatcher<HsBookingItemPa
|
||||
}
|
||||
|
||||
static Map<String, Object> objectToMap(final Object obj) {
|
||||
if (obj instanceof Map<?, ?>) {
|
||||
return toKeyValueMap(obj);
|
||||
}
|
||||
return stream(obj.getClass().getDeclaredFields())
|
||||
.map(field -> {
|
||||
try {
|
||||
@ -53,4 +55,9 @@ public class HsBookingItemEntityPatcher implements EntityPatcher<HsBookingItemPa
|
||||
return map1;
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Map<String, Object> toKeyValueMap(final Object obj) {
|
||||
return (Map<String, Object>) obj;
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ public class PatchMap extends TreeMap<String, Object> {
|
||||
stream(entries).forEach(r -> put(r.getKey(), r.getValue()));
|
||||
}
|
||||
|
||||
// @SafeVarargs
|
||||
// public static Map<String, Object> patchMap(final ImmutablePair<String, Object>... entries) {
|
||||
// return new PatchMap(entries);
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// public static ImmutablePair<String, Object> entry(final String key, final Object value) {
|
||||
// return new ImmutablePair<>(key, value);
|
||||
// }
|
||||
@SafeVarargs
|
||||
public static Map<String, Object> patchMap(final ImmutablePair<String, Object>... entries) {
|
||||
return new PatchMap(entries);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ImmutablePair<String, Object> entry(final String key, final Object value) {
|
||||
return new ImmutablePair<>(key, value);
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,9 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
/** This class wraps another (usually persistent) map and
|
||||
@ -33,6 +30,16 @@ public class PatchableMapWrapper implements Map<String, Object> {
|
||||
delegate.putAll(entries);
|
||||
}
|
||||
|
||||
public void patch(final Map<String, Object> patch) {
|
||||
patch.forEach((key, value) -> {
|
||||
if (value == null) {
|
||||
remove(key);
|
||||
} else {
|
||||
put(key, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "{ "
|
||||
+ (
|
||||
|
@ -18,7 +18,7 @@ components:
|
||||
type: string
|
||||
format: date
|
||||
resources:
|
||||
$ref: '#/components/schemas/ArbitraryBookingResourcesJson'
|
||||
$ref: '#/components/schemas/BookingResources'
|
||||
required:
|
||||
- uuid
|
||||
- debitor
|
||||
@ -41,7 +41,7 @@ components:
|
||||
format: date
|
||||
nullable: true
|
||||
resources:
|
||||
$ref: '#/components/schemas/ArbitraryBookingResourcesJson'
|
||||
$ref: '#/components/schemas/BookingResources'
|
||||
|
||||
HsBookingItemInsert:
|
||||
type: object
|
||||
@ -64,7 +64,7 @@ components:
|
||||
format: date
|
||||
nullable: true
|
||||
resources:
|
||||
$ref: '#/components/schemas/ArbitraryBookingResourcesJson'
|
||||
$ref: '#/components/schemas/BookingResources'
|
||||
required:
|
||||
- caption
|
||||
- debitorUuid
|
||||
@ -72,7 +72,53 @@ components:
|
||||
- resources
|
||||
additionalProperties: false
|
||||
|
||||
ArbitraryBookingResourcesJson:
|
||||
BookingResourcesDoesNotWork:
|
||||
type: object
|
||||
description: An object containing arbitrary JSON
|
||||
additionalProperties: true
|
||||
x-javaType: 'java.util.Map<String, Object>'
|
||||
additionalProperties:
|
||||
type: object
|
||||
|
||||
BookingResources:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/ManagedServerBookingResources'
|
||||
- $ref: '#/components/schemas/ManagedWebspaceBookingResources'
|
||||
|
||||
ManagedServerBookingResources:
|
||||
type: object
|
||||
properties:
|
||||
caption:
|
||||
type: string
|
||||
minLength: 3
|
||||
maxLength:
|
||||
nullable: false
|
||||
CPU:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 16
|
||||
SSD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
HDD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
additionalProperties: false
|
||||
|
||||
ManagedWebspaceBookingResources:
|
||||
type: object
|
||||
properties:
|
||||
disk:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 16
|
||||
SSD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
HDD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
additionalProperties: false
|
||||
|
||||
|
@ -4,8 +4,8 @@ get:
|
||||
description: 'Fetch a single booking item its uuid, if visible for the current subject.'
|
||||
operationId: getBookingItemByUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
required: true
|
||||
@ -19,12 +19,12 @@ get:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
patch:
|
||||
tags:
|
||||
@ -32,8 +32,8 @@ patch:
|
||||
description: 'Updates a single booking item identified by its uuid, if permitted for the current subject.'
|
||||
operationId: patchBookingItem
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
required: true
|
||||
@ -44,18 +44,18 @@ patch:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-booking-item-schemas.yaml#/components/schemas/HsBookingItemPatch'
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItemPatch'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
delete:
|
||||
tags:
|
||||
@ -63,8 +63,8 @@ delete:
|
||||
description: 'Delete a single booking item identified by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteBookingIemByUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
required: true
|
||||
@ -76,8 +76,8 @@ delete:
|
||||
"204":
|
||||
description: No Content
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
"404":
|
||||
$ref: './error-responses.yaml#/components/responses/NotFound'
|
||||
$ref: 'error-responses.yaml#/components/responses/NotFound'
|
||||
|
@ -5,8 +5,8 @@ get:
|
||||
- hs-booking-items
|
||||
operationId: listBookingItemsByDebitorUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUuid
|
||||
in: query
|
||||
required: true
|
||||
@ -22,11 +22,11 @@ get:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: './hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
post:
|
||||
summary: Adds a new booking item.
|
||||
@ -34,25 +34,25 @@ post:
|
||||
- hs-booking-items
|
||||
operationId: addBookingItem
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new booking item.
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '/hs-booking-item-schemas.yaml#/components/schemas/HsBookingItemInsert'
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItemInsert'
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
"409":
|
||||
$ref: './error-responses.yaml#/components/responses/Conflict'
|
||||
$ref: 'error-responses.yaml#/components/responses/Conflict'
|
||||
|
@ -11,7 +11,7 @@ paths:
|
||||
# Items
|
||||
|
||||
/api/hs/booking/items:
|
||||
$ref: "./hs-booking-items.yaml"
|
||||
$ref: "hs-booking-items.yaml"
|
||||
|
||||
/api/hs/booking/items/{bookingItemUuid}:
|
||||
$ref: "./hs-booking-items-with-uuid.yaml"
|
||||
$ref: "hs-booking-items-with-uuid.yaml"
|
||||
|
@ -32,9 +32,9 @@ begin
|
||||
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
|
||||
insert
|
||||
into hs_booking_item (uuid, debitoruuid, caption, validity, resources)
|
||||
values (uuid_generate_v4(), relatedDebitor.uuid, 'some ManagedServer', daterange('20221001', null, '[]'), '{ "CPUs": 2, "SDD-storage": 512 }'::jsonb),
|
||||
(uuid_generate_v4(), relatedDebitor.uuid, 'some CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 2, "HDD-storage": 1024 }'::jsonb),
|
||||
(uuid_generate_v4(), relatedDebitor.uuid, 'some Whatever', daterange('20240401', null, '[]'), '{ "CPUs": 1, "SDD-storage": 512, "HDD-storage": 2048 }'::jsonb);
|
||||
values (uuid_generate_v4(), relatedDebitor.uuid, 'some ManagedServer', daterange('20221001', null, '[]'), '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb),
|
||||
(uuid_generate_v4(), relatedDebitor.uuid, 'some CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb),
|
||||
(uuid_generate_v4(), relatedDebitor.uuid, 'some Whatever', daterange('20240401', null, '[]'), '{ "CPU": 1, "SDD": 512, "HDD": 2048, "extra": 42 }'::jsonb);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
@ -72,19 +72,32 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
"caption": "some ManagedServer",
|
||||
"validFrom": "2022-10-01",
|
||||
"validTo": null,
|
||||
"resources": { CPUs: 2, SDD-storage: 512 }
|
||||
"resources": {
|
||||
"CPU": 2,
|
||||
"SDD": 512,
|
||||
"extra": 42
|
||||
}
|
||||
},
|
||||
{
|
||||
"caption": "some CloudServer",
|
||||
"validFrom": "2023-01-15",
|
||||
"validTo": "2024-04-14",
|
||||
"resources": { CPUs: 2, HDD-storage: 1024 }
|
||||
"resources": {
|
||||
"CPU": 2,
|
||||
"HDD": 1024,
|
||||
"extra": 42
|
||||
}
|
||||
},
|
||||
{
|
||||
"caption": "some Whatever",
|
||||
"validFrom": "2024-04-01",
|
||||
"validTo": null,
|
||||
"resources": { CPUs: 1, HDD-storage: 2048, SDD-storage: 512 }
|
||||
"resources": {
|
||||
"CPU": 1,
|
||||
"HDD": 2048,
|
||||
"SDD": 512,
|
||||
"extra": 42
|
||||
}
|
||||
}
|
||||
]
|
||||
"""));
|
||||
@ -109,7 +122,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
{
|
||||
"debitorUuid": "%s",
|
||||
"caption": "some new booking",
|
||||
"resources": { "something": 12 },
|
||||
"resources": { "CPU": 12, "extra": 42 },
|
||||
"validFrom": "2022-10-13"
|
||||
}
|
||||
""".formatted(givenDebitor.getUuid()))
|
||||
@ -124,7 +137,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
"caption": "some new booking",
|
||||
"validFrom": "2022-10-13",
|
||||
"validTo": null,
|
||||
"resources": { "something": 12 }
|
||||
"resources": { "CPU": 12 }
|
||||
}
|
||||
"""))
|
||||
.header("Location", startsWith("http://localhost"))
|
||||
@ -162,7 +175,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
"caption": "some CloudServer",
|
||||
"validFrom": "2023-01-15",
|
||||
"validTo": "2024-04-14",
|
||||
"resources": { CPUs: 2, HDD-storage: 1024 }
|
||||
"resources": { CPU: 2, HDD: 1024 }
|
||||
}
|
||||
""")); // @formatter:on
|
||||
}
|
||||
@ -207,7 +220,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
"caption": "some CloudServer",
|
||||
"validFrom": "2023-01-15",
|
||||
"validTo": "2024-04-14",
|
||||
"resources": { CPUs: 2, HDD-storage: 1024 }
|
||||
"resources": { CPU: 2, HDD: 1024 }
|
||||
}
|
||||
""")); // @formatter:on
|
||||
}
|
||||
@ -219,7 +232,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
@Test
|
||||
void globalAdmin_canPatchAllUpdatablePropertiesOfBookingItem() {
|
||||
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111);
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111, entry("something", 1));
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
@ -230,9 +243,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
"validFrom": "2020-06-05",
|
||||
"validTo": "2022-12-31",
|
||||
"resources": {
|
||||
"CPUs": "4",
|
||||
"HDD_storage": null,
|
||||
"SSD-storage": "4096"
|
||||
"CPU": "4",
|
||||
"HDD": null,
|
||||
"SSD": "4096"
|
||||
}
|
||||
}
|
||||
""")
|
||||
@ -248,8 +261,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
"validFrom": "2020-06-05",
|
||||
"validTo": "2022-12-31",
|
||||
"resources": {
|
||||
"CPUs": "2",
|
||||
"SSD-storage": "2048"
|
||||
"CPU": "4",
|
||||
"SSD": "4096",
|
||||
"something": 1
|
||||
}
|
||||
}
|
||||
""")); // @formatter:on
|
||||
@ -269,9 +283,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
void globalAdmin_canPatchJustValidToOfArbitraryBookingItem() {
|
||||
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111);
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111, entry("something", 1));
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("current-user", "superuser-alex@hostsharing.net")
|
||||
.contentType(ContentType.JSON)
|
||||
@ -292,7 +306,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
"validFrom": "2022-11-01",
|
||||
"validTo": "2022-12-31",
|
||||
"resources": {
|
||||
"CPUs": 5
|
||||
"something": 1
|
||||
}
|
||||
}
|
||||
""")); // @formatter:on
|
||||
@ -310,7 +324,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
void globalAdmin_canNotPatchReferenceOfArbitraryBookingItem() {
|
||||
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111);
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111, entry("something", 1));
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
@ -344,7 +358,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
@Test
|
||||
void globalAdmin_canDeleteArbitraryBookingItem() {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111);
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111, entry("something", 1));
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
@ -362,7 +376,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
@Test
|
||||
void normalUser_canNotDeleteUnrelatedBookingItem() {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111);
|
||||
final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111, entry("something", 1));
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
@ -378,7 +392,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
}
|
||||
}
|
||||
|
||||
private HsBookingItemEntity givenSomeTemporaryBookingItemForDebitorNumber(final int debitorNumber) {
|
||||
private HsBookingItemEntity givenSomeTemporaryBookingItemForDebitorNumber(final int debitorNumber,
|
||||
final Map.Entry<String, Integer> resources) {
|
||||
return jpaAttempt.transacted(() -> {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenDebitor = debitorRepo.findDebitorByDebitorNumber(debitorNumber).get(0);
|
||||
@ -386,7 +401,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
.uuid(UUID.randomUUID())
|
||||
.debitor(givenDebitor)
|
||||
.caption("some test-booking")
|
||||
.resources(Map.ofEntries(entry("something", 1)))
|
||||
.resources(Map.ofEntries(resources))
|
||||
.validity(Range.closedOpen(
|
||||
LocalDate.parse("2022-11-01"), LocalDate.parse("2023-03-31")))
|
||||
.build();
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.hostsharing.hsadminng.hs.booking.item;
|
||||
|
||||
import io.hypersistence.utils.hibernate.type.range.Range;
|
||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.ArbitraryBookingResourcesJsonResource;
|
||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingItemPatchResource;
|
||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
||||
import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase;
|
||||
@ -13,11 +12,14 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntityPatcher.objectToMap;
|
||||
import static net.hostsharing.hsadminng.hs.office.debitor.TestHsOfficeDebitor.TEST_DEBITOR;
|
||||
import static net.hostsharing.hsadminng.mapper.PatchMap.entry;
|
||||
import static net.hostsharing.hsadminng.mapper.PatchMap.patchMap;
|
||||
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@ -35,15 +37,22 @@ class HsBookingItemEntityPatcherUnitTest extends PatchUnitTestBase<
|
||||
private static final LocalDate PATCHED_VALID_FROM = LocalDate.parse("2022-10-30");
|
||||
private static final LocalDate PATCHED_VALID_TO = LocalDate.parse("2022-12-31");
|
||||
|
||||
private static final ArbitraryBookingResourcesJsonResource INITIAL_RESOURCES = new ArbitraryBookingResourcesJsonResource() {
|
||||
Integer cpus = 1;
|
||||
Integer hddStorage = 1024;
|
||||
};
|
||||
private static final ArbitraryBookingResourcesJsonResource PATCHED_RESOURCES = new ArbitraryBookingResourcesJsonResource() {
|
||||
Integer cpus = 2;
|
||||
Integer sddStorage = 256;
|
||||
Integer hddStorage = null;
|
||||
};
|
||||
private static final Map<String, Object> INITIAL_RESOURCES = patchMap(
|
||||
entry("CPU", 1),
|
||||
entry("HDD", 1024),
|
||||
entry("MEM", 64)
|
||||
);
|
||||
private static final Map<String, Object> PATCH_RESOURCES = patchMap(
|
||||
entry("CPU", 2),
|
||||
entry("HDD", null),
|
||||
entry("SDD", 256)
|
||||
);
|
||||
private static final Map<String, Object> PATCHED_RESOURCES = patchMap(
|
||||
entry("CPU", 2),
|
||||
entry("SDD", 256),
|
||||
entry("MEM", 64)
|
||||
);
|
||||
|
||||
private static final String INITIAL_CAPTION = "initial caption";
|
||||
private static final String PATCHED_CAPTION = "patched caption";
|
||||
|
||||
@ -90,9 +99,9 @@ class HsBookingItemEntityPatcherUnitTest extends PatchUnitTestBase<
|
||||
new SimpleProperty<>(
|
||||
"resources",
|
||||
HsBookingItemPatchResource::setResources,
|
||||
PATCHED_RESOURCES,
|
||||
PATCH_RESOURCES,
|
||||
HsBookingItemEntity::putResources,
|
||||
objectToMap(PATCHED_RESOURCES))
|
||||
PATCHED_RESOURCES)
|
||||
.notNullable(),
|
||||
new JsonNullableProperty<>(
|
||||
"validfrom",
|
||||
|
@ -157,9 +157,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
||||
// then
|
||||
allTheseBookingItemsAreReturned(
|
||||
result,
|
||||
"HsBookingItemEntity(D-1000212, [2022-10-01,), some ManagedServer, { CPUs: 2, SDD-storage: 512 })",
|
||||
"HsBookingItemEntity(D-1000212, [2023-01-15,2024-04-15), some CloudServer, { CPUs: 2, HDD-storage: 1024 })",
|
||||
"HsBookingItemEntity(D-1000212, [2024-04-01,), some Whatever, { CPUs: 1, HDD-storage: 2048, SDD-storage: 512 })");
|
||||
"HsBookingItemEntity(D-1000212, [2022-10-01,), some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })",
|
||||
"HsBookingItemEntity(D-1000212, [2023-01-15,2024-04-15), some CloudServer, { CPU: 2, HDD: 1024, extra: 42 })",
|
||||
"HsBookingItemEntity(D-1000212, [2024-04-01,), some Whatever, { CPU: 1, HDD: 2048, SDD: 512, extra: 42 })");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -174,9 +174,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
||||
// then:
|
||||
exactlyTheseBookingItemsAreReturned(
|
||||
result,
|
||||
"HsBookingItemEntity(D-1000111, [2022-10-01,), some ManagedServer, { CPUs: 2, SDD-storage: 512 })",
|
||||
"HsBookingItemEntity(D-1000111, [2023-01-15,2024-04-15), some CloudServer, { CPUs: 2, HDD-storage: 1024 })",
|
||||
"HsBookingItemEntity(D-1000111, [2024-04-01,), some Whatever, { CPUs: 1, HDD-storage: 2048, SDD-storage: 512 })");
|
||||
"HsBookingItemEntity(D-1000111, [2022-10-01,), some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })",
|
||||
"HsBookingItemEntity(D-1000111, [2023-01-15,2024-04-15), some CloudServer, { CPU: 2, HDD: 1024, extra: 42 })",
|
||||
"HsBookingItemEntity(D-1000111, [2024-04-01,), some Whatever, { CPU: 1, HDD: 2048, SDD: 512, extra: 42 })");
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user