introduce-booking-module #41

Merged
hsh-michaelhoennig merged 21 commits from introduce-booking-module into master 2024-04-16 11:21:35 +02:00
13 changed files with 118 additions and 87 deletions
Showing only changes of commit 75c759bed3 - Show all commits

View File

@ -1,11 +1,11 @@
package net.hostsharing.hsadminng.hs.booking.item; package net.hostsharing.hsadminng.hs.booking.item;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.api.HsBookingItemsApi; import net.hostsharing.hsadminng.hs.booking.generated.api.v1.api.HsBookingItemsApi;
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingItemInsertResource; import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingItemInsertResource;
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingItemPatchResource; import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingItemPatchResource;
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingItemResource; import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingItemResource;
import net.hostsharing.hsadminng.mapper.Mapper; import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.context.Context;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -76,10 +76,10 @@ public class HsBookingItemController implements HsBookingItemsApi {
context.define(currentUser, assumedRoles); context.define(currentUser, assumedRoles);
final var result = bookingItemRepo.findByUuid(bookingItemUuid); final var result = bookingItemRepo.findByUuid(bookingItemUuid);
if (result.isEmpty()) { return result
return ResponseEntity.notFound().build(); .map(bookingItemEntity -> ResponseEntity.ok(
} mapper.map(bookingItemEntity, HsBookingItemResource.class, ENTITY_TO_RESOURCE_POSTMAPPER)))
return ResponseEntity.ok(mapper.map(result.get(), HsBookingItemResource.class, ENTITY_TO_RESOURCE_POSTMAPPER)); .orElseGet(() -> ResponseEntity.notFound().build());
} }
@Override @Override
@ -91,11 +91,9 @@ public class HsBookingItemController implements HsBookingItemsApi {
context.define(currentUser, assumedRoles); context.define(currentUser, assumedRoles);
final var result = bookingItemRepo.deleteByUuid(bookingItemUuid); final var result = bookingItemRepo.deleteByUuid(bookingItemUuid);
if (result == 0) { return result == 0
return ResponseEntity.notFound().build(); ? ResponseEntity.notFound().build()
} : ResponseEntity.noContent().build();
return ResponseEntity.noContent().build();
} }
@Override @Override
@ -122,7 +120,6 @@ public class HsBookingItemController implements HsBookingItemsApi {
if (entity.getValidity().hasUpperBound()) { if (entity.getValidity().hasUpperBound()) {
resource.setValidTo(entity.getValidity().upper().minusDays(1)); resource.setValidTo(entity.getValidity().upper().minusDays(1));
} }
resource.getDebitor().setDebitorNumber(entity.getDebitor().getDebitorNumber());
}; };
final BiConsumer<HsBookingItemInsertResource, HsBookingItemEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { final BiConsumer<HsBookingItemInsertResource, HsBookingItemEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {

View File

@ -118,6 +118,7 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject {
public static RbacView rbac() { public static RbacView rbac() {
return rbacViewFor("bookingItem", HsBookingItemEntity.class) return rbacViewFor("bookingItem", HsBookingItemEntity.class)
.withIdentityView(SQL.projection("caption")) // FIXME: use memberNumber:caption .withIdentityView(SQL.projection("caption")) // FIXME: use memberNumber:caption
.withRestrictedViewOrderBy(SQL.expression("validity"))
.withUpdatableColumns("version", "validity", "resources") .withUpdatableColumns("version", "validity", "resources")
.importEntityAlias("debitor", HsOfficeDebitorEntity.class, .importEntityAlias("debitor", HsOfficeDebitorEntity.class,

View File

@ -74,11 +74,11 @@ public class HsOfficeBankAccountController implements HsOfficeBankAccountsApi {
public ResponseEntity<HsOfficeBankAccountResource> getBankAccountByUuid( public ResponseEntity<HsOfficeBankAccountResource> getBankAccountByUuid(
final String currentUser, final String currentUser,
final String assumedRoles, final String assumedRoles,
final UUID BankAccountUuid) { final UUID bankAccountUuid) {
context.define(currentUser, assumedRoles); context.define(currentUser, assumedRoles);
final var result = bankAccountRepo.findByUuid(BankAccountUuid); final var result = bankAccountRepo.findByUuid(bankAccountUuid);
if (result.isEmpty()) { if (result.isEmpty()) {
return ResponseEntity.notFound().build(); return ResponseEntity.notFound().build();
} }

View File

@ -14,5 +14,5 @@ map:
- type: string:format => java.lang.String - type: string:format => java.lang.String
paths: paths:
/api/hs/booking/items/{itemUUID}: /api/hs/booking/items/{bookingItemUuid}:
null: org.openapitools.jackson.nullable.JsonNullable null: org.openapitools.jackson.nullable.JsonNullable

View File

@ -9,8 +9,6 @@ components:
uuid: uuid:
type: string type: string
format: uuid format: uuid
debitor:
$ref: '../hs-office/hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitor'
caption: caption:
type: string type: string
validFrom: validFrom:
@ -44,7 +42,6 @@ components:
nullable: true nullable: true
resources: resources:
$ref: '#/components/schemas/ArbitraryBookingResourcesJson' $ref: '#/components/schemas/ArbitraryBookingResourcesJson'
additionalProperties: false
HsBookingItemInsert: HsBookingItemInsert:
type: object type: object

View File

@ -6,7 +6,7 @@ get:
parameters: parameters:
- $ref: './auth.yaml#/components/parameters/currentUser' - $ref: './auth.yaml#/components/parameters/currentUser'
- $ref: './auth.yaml#/components/parameters/assumedRoles' - $ref: './auth.yaml#/components/parameters/assumedRoles'
- name: bookingItemUUID - name: bookingItemUuid
in: path in: path
required: true required: true
schema: schema:
@ -34,7 +34,7 @@ patch:
parameters: parameters:
- $ref: './auth.yaml#/components/parameters/currentUser' - $ref: './auth.yaml#/components/parameters/currentUser'
- $ref: './auth.yaml#/components/parameters/assumedRoles' - $ref: './auth.yaml#/components/parameters/assumedRoles'
- name: bookingItemUUID - name: bookingItemUuid
in: path in: path
required: true required: true
schema: schema:
@ -65,7 +65,7 @@ delete:
parameters: parameters:
- $ref: './auth.yaml#/components/parameters/currentUser' - $ref: './auth.yaml#/components/parameters/currentUser'
- $ref: './auth.yaml#/components/parameters/assumedRoles' - $ref: './auth.yaml#/components/parameters/assumedRoles'
- name: bookingItemUUID - name: bookingItemUuid
in: path in: path
required: true required: true
schema: schema:

View File

@ -1,6 +1,6 @@
get: get:
summary: Returns a list of (optionally filtered) booking items. summary: Returns a list of all booking items for a specified debitor.
description: Returns the list of (optionally filtered) booking items which are visible to the current user or any of it's assumed roles. description: Returns the list of all booking items for a specified debitor which are visible to the current user or any of it's assumed roles.
tags: tags:
- hs-booking-items - hs-booking-items
operationId: listBookingItemsByDebitorUuid operationId: listBookingItemsByDebitorUuid
@ -9,7 +9,7 @@ get:
- $ref: './auth.yaml#/components/parameters/assumedRoles' - $ref: './auth.yaml#/components/parameters/assumedRoles'
- name: debitorUuid - name: debitorUuid
in: query in: query
required: false required: true
schema: schema:
type: string type: string
format: uuid format: uuid

View File

@ -13,5 +13,5 @@ paths:
/api/hs/booking/items: /api/hs/booking/items:
$ref: "./hs-booking-items.yaml" $ref: "./hs-booking-items.yaml"
/api/hs/booking/items/{itemUUID}: /api/hs/booking/items/{bookingItemUuid}:
$ref: "./hs-booking-items-with-uuid.yaml" $ref: "./hs-booking-items-with-uuid.yaml"

View File

@ -10,8 +10,7 @@
*/ */
create or replace procedure createHsBookingItemTransactionTestData( create or replace procedure createHsBookingItemTransactionTestData(
givenPartnerNumber numeric, givenPartnerNumber numeric,
givenDebitorSuffix char(2), givenDebitorSuffix char(2)
givenCaption varchar
) )
language plpgsql as $$ language plpgsql as $$
declare declare
@ -33,7 +32,9 @@ begin
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor; raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
insert insert
into hs_booking_item (uuid, debitoruuid, caption, validity, resources) into hs_booking_item (uuid, debitoruuid, caption, validity, resources)
values (uuid_generate_v4(), relatedDebitor.uuid, givenCaption, daterange('20221001' , null, '[]'), '{ "CPUs": 2, "HDD-storage": 512 }'::jsonb); 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);
end; $$; end; $$;
--// --//
@ -44,8 +45,8 @@ end; $$;
do language plpgsql $$ do language plpgsql $$
begin begin
call createHsBookingItemTransactionTestData(10001, '11', 'some booking 1'); call createHsBookingItemTransactionTestData(10001, '11');
call createHsBookingItemTransactionTestData(10002, '12', 'some booking 2'); call createHsBookingItemTransactionTestData(10002, '12');
call createHsBookingItemTransactionTestData(10003, '13', 'some booking 3'); call createHsBookingItemTransactionTestData(10003, '13');
end; end;
$$; $$;

View File

@ -50,6 +50,7 @@ public class ArchitectureTest {
"..hs.office.person", "..hs.office.person",
"..hs.office.relation", "..hs.office.relation",
"..hs.office.sepamandate", "..hs.office.sepamandate",
"..hs.booking.item",
"..errors", "..errors",
"..mapper", "..mapper",
"..ping", "..ping",
@ -123,11 +124,22 @@ public class ArchitectureTest {
@ArchTest @ArchTest
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static final ArchRule hsAdminPackagesRule = classes() public static final ArchRule hsOfficePackageAccessRule = classes()
.that().resideInAPackage("..hs.office.(*)..") .that().resideInAPackage("..hs.office.(*)..")
.should().onlyBeAccessed().byClassesThat() .should().onlyBeAccessed().byClassesThat()
.resideInAnyPackage( .resideInAnyPackage(
"..hs.office.(*)..", "..hs.office.(*)..",
"..hs.booking.(*)..",
"..rbac.rbacgrant" // TODO.test: just because of RbacGrantsDiagramServiceIntegrationTest
);
@ArchTest
@SuppressWarnings("unused")
public static final ArchRule hsBookingPackageAccessRule = classes()
.that().resideInAPackage("..hs.booking.(*)..")
.should().onlyBeAccessed().byClassesThat()
.resideInAnyPackage(
"..hs.booking.(*)..",
"..rbac.rbacgrant" // TODO.test: just because of RbacGrantsDiagramServiceIntegrationTest "..rbac.rbacgrant" // TODO.test: just because of RbacGrantsDiagramServiceIntegrationTest
); );

View File

@ -19,8 +19,10 @@ import org.springframework.transaction.annotation.Transactional;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import static java.util.Map.entry;
import static net.hostsharing.test.JsonMatcher.lenientlyEquals; import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.startsWith;
@ -62,7 +64,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
.header("current-user", "superuser-alex@hostsharing.net") .header("current-user", "superuser-alex@hostsharing.net")
.port(port) .port(port)
.when() .when()
.get("http://localhost/api/hs/booking/items?debitorUuid" + givenDebitor.getUuid()) .get("http://localhost/api/hs/booking/items?debitorUuid=" + givenDebitor.getUuid())
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(200) .statusCode(200)
.contentType("application/json") .contentType("application/json")
@ -70,19 +72,22 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
.body("", lenientlyEquals(""" .body("", lenientlyEquals("""
[ [
{ {
"debitor": { "debitorNumber": 1000111 }, "caption": "some ManagedServer",
"validFrom": "2022-10-01", "validFrom": "2022-10-01",
"validTo": "2026-12-31" "validTo": null,
"resources": null
}, },
{ {
"debitor": { "debitorNumber": 1000212 }, "caption": "some CloudServer",
"validFrom": "2022-10-01", "validFrom": "2023-01-15",
"validTo": "2026-12-31" "validTo": "2024-04-14",
"resources": null
}, },
{ {
"debitor": { "debitorNumber": 1000313 }, "caption": "some Whatever",
"validFrom": "2022-10-01", "validFrom": "2024-04-01",
"validTo": "2026-12-31" "validTo": null,
"resources": null
} }
] ]
""")); """));
@ -97,7 +102,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
void globalAdmin_canAddBookingItem() { void globalAdmin_canAddBookingItem() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenDebitor = debitorRepo.findDebitorByOptionalNameLike("Third").get(0); final var givenDebitor = debitorRepo.findDebitorByDebitorNumber(1000111).get(0);
final var location = RestAssured // @formatter:off final var location = RestAssured // @formatter:off
.given() .given()
@ -106,20 +111,25 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
.body(""" .body("""
{ {
"debitorUuid": "%s", "debitorUuid": "%s",
"caption": "some new booking",
"resources": {
"something": 12
},
"validFrom": "2022-10-13" "validFrom": "2022-10-13"
} }
""".formatted(givenDebitor.getUuid())) """.formatted(givenDebitor.getUuid()))
.port(port) .port(port)
.when() .when()
.post("http://localhost/api/hs/office/BookingItems") .post("http://localhost/api/hs/booking/items")
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(201) .statusCode(201)
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body("", lenientlyEquals(""" .body("", lenientlyEquals("""
{ {
"debitor": { "debitorNumber": 1000111 }, "caption": "some new booking",
"validFrom": "2022-10-01", "validFrom": "2022-10-13",
"validTo": "2026-12-31" "validTo": null,
"resources": null
} }
""")) """))
.header("Location", startsWith("http://localhost")) .header("Location", startsWith("http://localhost"))
@ -139,7 +149,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
void globalAdmin_canGetArbitraryBookingItem() { void globalAdmin_canGetArbitraryBookingItem() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenBookingItemUuid = bookingItemRepo.findAll().stream() final var givenBookingItemUuid = bookingItemRepo.findAll().stream()
.filter(bi -> bi.getDebitor().getDebitorNumber() == 1000101) .filter(bi -> bi.getDebitor().getDebitorNumber() == 1000111)
.findAny().orElseThrow().getUuid(); .findAny().orElseThrow().getUuid();
RestAssured // @formatter:off RestAssured // @formatter:off
@ -148,14 +158,15 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
.port(port) .port(port)
.when() .when()
.get("http://localhost/api/hs/booking/items/" + givenBookingItemUuid) .get("http://localhost/api/hs/booking/items/" + givenBookingItemUuid)
.then().log().body().assertThat() .then().log().all().assertThat()
.statusCode(200) .statusCode(200)
.contentType("application/json") .contentType("application/json")
.body("", lenientlyEquals(""" .body("", lenientlyEquals("""
{ {
"debitor": { "debitorNumber": 1000111 }, "caption": "some CloudServer",
"validFrom": "2022-10-01", "validFrom": "2023-01-15",
"validTo": "2026-12-31" "validTo": "2024-04-14",
"resources": null
} }
""")); // @formatter:on """)); // @formatter:on
} }
@ -164,8 +175,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
void normalUser_canNotGetUnrelatedBookingItem() { void normalUser_canNotGetUnrelatedBookingItem() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenBookingItemUuid = bookingItemRepo.findAll().stream() final var givenBookingItemUuid = bookingItemRepo.findAll().stream()
.filter(bi -> bi.getDebitor().getDebitorNumber() == 1000101) .filter(bi -> bi.getDebitor().getDebitorNumber() == 1000212)
.findAny().orElseThrow().getUuid(); .map(HsBookingItemEntity::getUuid)
.findAny().orElseThrow();
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
@ -181,23 +193,25 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
void debitorAgentUser_canGetRelatedBookingItem() { void debitorAgentUser_canGetRelatedBookingItem() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenBookingItemUuid = bookingItemRepo.findAll().stream() final var givenBookingItemUuid = bookingItemRepo.findAll().stream()
.filter(bi -> bi.getDebitor().getDebitorNumber() == 1000101) .filter(bi -> bi.getDebitor().getDebitorNumber() == 1000313)
.findAny().orElseThrow().getUuid(); .findAny().orElseThrow().getUuid();
generateRbacDiagramForObjectPermission(givenBookingItemUuid, "SELECT", "booking-item-of-debitor-1000313");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
.header("current-user", "person-FirbySusan@example.com") .header("current-user", "person-TuckerJack@example.com")
.port(port) .port(port)
.when() .when()
.get("http://localhost/api/hs/booking/items/" + givenBookingItemUuid) .get("http://localhost/api/hs/booking/items/" + givenBookingItemUuid)
.then().log().body().assertThat() .then().log().all().assertThat()
.statusCode(200) .statusCode(200)
.contentType("application/json") .contentType("application/json")
.body("", lenientlyEquals(""" .body("", lenientlyEquals("""
{ {
"debitor": { "debitorNumber": 1000111 }, "caption": "some CloudServer",
"validFrom": "2022-10-01", "validFrom": "2023-01-15",
"validTo": "2026-12-31" "validTo": "2024-04-14",
"resources": null
} }
""")); // @formatter:on """)); // @formatter:on
} }
@ -227,15 +241,16 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
""") """)
.port(port) .port(port)
.when() .when()
.patch("http://localhost/api/hs/office/BookingItems/" + givenBookingItem.getUuid()) .patch("http://localhost/api/hs/booking/items/" + givenBookingItem.getUuid())
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(200) .statusCode(200)
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body("", lenientlyEquals(""" .body("", lenientlyEquals("""
{ {
"debitor": { "debitorNumber": 1000111 }, "caption": "some test-booking",
"validFrom": "2022-10-01", "validFrom": "2020-06-05",
"validTo": "2026-12-31" "validTo": "2022-12-31",
"resources": null
} }
""")); // @formatter:on """)); // @formatter:on
@ -267,15 +282,16 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
""") """)
.port(port) .port(port)
.when() .when()
.patch("http://localhost/api/hs/office/BookingItems/" + givenBookingItem.getUuid()) .patch("http://localhost/api/hs/booking/items/" + givenBookingItem.getUuid())
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(200) .statusCode(200)
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body("", lenientlyEquals(""" .body("", lenientlyEquals("""
{ {
"debitor": { "debitorNumber": 1000111 }, "caption": "some test-booking",
"validFrom": "2022-10-01", "validFrom": "2022-11-01",
"validTo": "2026-12-31" "validTo": "2022-12-31",
"resources": null
} }
""")); // @formatter:on """)); // @formatter:on
@ -305,7 +321,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
""") """)
.port(port) .port(port)
.when() .when()
.patch("http://localhost/api/hs/office/BookingItems/" + givenBookingItem.getUuid()) .patch("http://localhost/api/hs/booking/items/" + givenBookingItem.getUuid())
.then().assertThat() .then().assertThat()
// TODO.impl: I'd prefer a 400, // TODO.impl: I'd prefer a 400,
// but OpenApi Spring Code Gen does not convert additonalProperties=false into a validation // but OpenApi Spring Code Gen does not convert additonalProperties=false into a validation
@ -333,7 +349,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
.header("current-user", "superuser-alex@hostsharing.net") .header("current-user", "superuser-alex@hostsharing.net")
.port(port) .port(port)
.when() .when()
.delete("http://localhost/api/hs/office/BookingItems/" + givenBookingItem.getUuid()) .delete("http://localhost/api/hs/booking/items/" + givenBookingItem.getUuid())
.then().log().body().assertThat() .then().log().body().assertThat()
.statusCode(204); // @formatter:on .statusCode(204); // @formatter:on
@ -351,7 +367,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
.header("current-user", "bankaccount-admin@FirstGmbH.example.com") .header("current-user", "bankaccount-admin@FirstGmbH.example.com")
.port(port) .port(port)
.when() .when()
.delete("http://localhost/api/hs/office/BookingItems/" + givenBookingItem.getUuid()) .delete("http://localhost/api/hs/booking/items/" + givenBookingItem.getUuid())
.then().log().body().assertThat() .then().log().body().assertThat()
.statusCode(403); // @formatter:on .statusCode(403); // @formatter:on
@ -370,7 +386,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
.header("current-user", "selfregistered-user-drew@hostsharing.org") .header("current-user", "selfregistered-user-drew@hostsharing.org")
.port(port) .port(port)
.when() .when()
.delete("http://localhost/api/hs/office/BookingItems/" + givenBookingItem.getUuid()) .delete("http://localhost/api/hs/booking/items/" + givenBookingItem.getUuid())
.then().log().body().assertThat() .then().log().body().assertThat()
.statusCode(404); // @formatter:on .statusCode(404); // @formatter:on
@ -386,6 +402,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
final var newBookingItem = HsBookingItemEntity.builder() final var newBookingItem = HsBookingItemEntity.builder()
.uuid(UUID.randomUUID()) .uuid(UUID.randomUUID())
.debitor(givenDebitor) .debitor(givenDebitor)
.caption("some test-booking")
.resources(Map.ofEntries(entry("something", 1)))
.validity(Range.closedOpen( .validity(Range.closedOpen(
LocalDate.parse("2022-11-01"), LocalDate.parse("2023-03-31"))) LocalDate.parse("2022-11-01"), LocalDate.parse("2023-03-31")))
.build(); .build();

View File

@ -148,7 +148,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
public void globalAdmin_withoutAssumedRole_canViewAllBookingItemsOfArbitraryDebitor() { public void globalAdmin_withoutAssumedRole_canViewAllBookingItemsOfArbitraryDebitor() {
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var debitorUuid = debitorRepo.findDebitorByDebitorNumber(1000111).stream().findAny().orElseThrow().getUuid(); final var debitorUuid = debitorRepo.findDebitorByDebitorNumber(1000212).stream().findAny().orElseThrow().getUuid();
// when // when
final var result = bookingItemRepo.findAllByDebitorUuid(debitorUuid); final var result = bookingItemRepo.findAllByDebitorUuid(debitorUuid);
@ -156,7 +156,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
// then // then
allTheseBookingItemsAreReturned( allTheseBookingItemsAreReturned(
result, result,
"HsBookingItemEntity(D-1000111, some booking 1, [2022-10-01,), {CPUs=2, HDD-storage=512})"); "HsBookingItemEntity(D-1000212, some CloudServer, [2023-01-15,2024-04-15), {CPUs=2, HDD-storage=1024})",
"HsBookingItemEntity(D-1000212, some ManagedServer, [2022-10-01,), {CPUs=2, SDD-storage=512})",
"HsBookingItemEntity(D-1000212, some Whatever, [2024-04-01,), {CPUs=1, HDD-storage=2048, SDD-storage=512})");
} }
@Test @Test
@ -171,7 +173,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
// then: // then:
exactlyTheseBookingItemsAreReturned( exactlyTheseBookingItemsAreReturned(
result, result,
"HsBookingItemEntity(D-1000111, some booking 1, [2022-10-01,), {CPUs=2, HDD-storage=512})"); "HsBookingItemEntity(D-1000111, some CloudServer, [2023-01-15,2024-04-15), {CPUs=2, HDD-storage=1024})",
"HsBookingItemEntity(D-1000111, some ManagedServer, [2022-10-01,), {CPUs=2, SDD-storage=512})",
"HsBookingItemEntity(D-1000111, some Whatever, [2024-04-01,), {CPUs=1, HDD-storage=2048, SDD-storage=512})");
} }
} }

View File

@ -181,6 +181,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
.containsExactlyInAnyOrder(Array.fromFormatted( .containsExactlyInAnyOrder(Array.fromFormatted(
initialGrantNames, initialGrantNames,
"{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:INSERT>sepamandate to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }", "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:INSERT>sepamandate to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
"{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:INSERT>hs_booking_item to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
// owner // owner
"{ grant perm:debitor#D-1000122:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }", "{ grant perm:debitor#D-1000122:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }",