ceate bookingitems for domain-setup hostingassets (#95)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: #95
Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
Michael Hoennig 2024-09-04 11:15:37 +02:00
parent e57f4bf0c8
commit fbd17a21e2
12 changed files with 159 additions and 63 deletions

View File

@ -12,6 +12,7 @@ package Booking #feb28c {
entity BI_CLOUD_SERVER
entity BI_MANAGED_SERVER
entity BI_MANAGED_WEBSPACE
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
@ -67,6 +68,7 @@ package Booking #feb28c {
entity BI_CLOUD_SERVER
entity BI_MANAGED_SERVER
entity BI_MANAGED_WEBSPACE
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
@ -94,6 +96,7 @@ BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER
HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
HA_UNIX_USER *==> HA_MANAGED_WEBSPACE
HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE
HA_DOMAIN_SETUP *==> BI_DOMAIN_SETUP
HA_DOMAIN_SETUP o..> HA_DOMAIN_SETUP
HA_DOMAIN_DNS_SETUP *==> HA_DOMAIN_SETUP
HA_DOMAIN_DNS_SETUP o--> HA_MANAGED_WEBSPACE
@ -125,6 +128,7 @@ package Booking #feb28c {
entity BI_CLOUD_SERVER
entity BI_MANAGED_SERVER
entity BI_MANAGED_WEBSPACE
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
@ -173,6 +177,7 @@ package Booking #feb28c {
entity BI_CLOUD_SERVER
entity BI_MANAGED_SERVER
entity BI_MANAGED_WEBSPACE
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{

View File

@ -9,7 +9,8 @@ public enum HsBookingItemType implements Node {
PRIVATE_CLOUD,
CLOUD_SERVER(PRIVATE_CLOUD),
MANAGED_SERVER(PRIVATE_CLOUD),
MANAGED_WEBSPACE(MANAGED_SERVER);
MANAGED_WEBSPACE(MANAGED_SERVER),
DOMAIN_SETUP;
private final HsBookingItemType parentItemType;

View File

@ -13,6 +13,7 @@ import java.util.Set;
import static java.util.Arrays.stream;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.DOMAIN_SETUP;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.PRIVATE_CLOUD;
@ -25,6 +26,7 @@ public class HsBookingItemEntityValidatorRegistry {
register(CLOUD_SERVER, new HsCloudServerBookingItemValidator());
register(MANAGED_SERVER, new HsManagedServerBookingItemValidator());
register(MANAGED_WEBSPACE, new HsManagedWebspaceBookingItemValidator());
register(DOMAIN_SETUP, new HsDomainSetupBookingItemValidator());
}
private static void register(final Enum<HsBookingItemType> type, final HsEntityValidator<HsBookingItem> validator) {

View File

@ -0,0 +1,10 @@
package net.hostsharing.hsadminng.hs.booking.item.validators;
class HsDomainSetupBookingItemValidator extends HsBookingItemEntityValidator {
HsDomainSetupBookingItemValidator() {
super(
// no properties yet. maybe later, the setup code goes here?
);
}
}

View File

@ -24,8 +24,10 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.EntityTypeRelation.opti
import static net.hostsharing.hsadminng.hs.hosting.asset.EntityTypeRelation.optionallyAssignedTo;
import static net.hostsharing.hsadminng.hs.hosting.asset.EntityTypeRelation.requiredParent;
import static net.hostsharing.hsadminng.hs.hosting.asset.EntityTypeRelation.requires;
import static net.hostsharing.hsadminng.hs.hosting.asset.EntityTypeRelation.terminatory;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationPolicy.OPTIONAL;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationPolicy.REQUIRED;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationPolicy.TERMINATORY;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationType.ASSIGNED_TO_ASSET;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationType.BOOKING_ITEM;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationType.PARENT_ASSET;
@ -57,6 +59,7 @@ public enum HsHostingAssetType implements Node {
DOMAIN_SETUP( // named e.g. example.org
inGroup("Domain"),
terminatory(HsBookingItemType.DOMAIN_SETUP),
optionalParent(SAME_TYPE)
),
@ -339,7 +342,7 @@ public enum HsHostingAssetType implements Node {
}
public enum RelationPolicy {
FORBIDDEN, OPTIONAL, REQUIRED
FORBIDDEN, OPTIONAL, TERMINATORY, REQUIRED
}
public enum RelationType {
@ -376,6 +379,15 @@ class EntityTypeRelation<E, T extends Node> {
return (Set<R>) result;
}
static EntityTypeRelation<HsBookingItem, HsBookingItemType> terminatory(final HsBookingItemType bookingItemType) {
return new EntityTypeRelation<>(
TERMINATORY,
BOOKING_ITEM,
HsHostingAssetRbacEntity::getBookingItem,
bookingItemType,
" *..> ");
}
static EntityTypeRelation<HsBookingItem, HsBookingItemType> requires(final HsBookingItemType bookingItemType) {
return new EntityTypeRelation<>(
REQUIRED,

View File

@ -182,26 +182,36 @@ public abstract class HostingAssetEntityValidator extends HsEntityValidator<HsHo
List<String> validate(final HsHostingAsset assetEntity, final String referenceFieldName) {
final var actualEntity = referencedEntityGetter.apply(assetEntity);
final var actualEntityType = actualEntity != null ? referencedEntityTypeGetter.apply(actualEntity) : null;
final var referencedEntity = referencedEntityGetter.apply(assetEntity);
final var referencedEntityType = referencedEntity != null ? referencedEntityTypeGetter.apply(referencedEntity) : null;
switch (policy) {
case REQUIRED:
if (!referencedEntityTypes.contains(actualEntityType)) {
return List.of(actualEntityType == null
if (!referencedEntityTypes.contains(referencedEntityType)) {
return List.of(referencedEntityType == null
? referenceFieldName + "' must be of type " + toDisplay(referencedEntityTypes) + " but is null"
: referenceFieldName + "' must be of type " + toDisplay(referencedEntityTypes) + " but is of type " + actualEntityType);
: referenceFieldName + "' must be of type " + toDisplay(referencedEntityTypes) + " but is of type " + referencedEntityType);
}
break;
case TERMINATORY:
if (assetEntity.getParentAsset() != null && assetEntity.getBookingItem() != null) {
return List.of(referenceFieldName + "' or parentItem must be null but is of type " + referencedEntityType);
}
if (assetEntity.getParentAsset() == null && !referencedEntityTypes.contains(referencedEntityType)) {
return List.of(referencedEntityType == null
? referenceFieldName + "' must be of type " + toDisplay(referencedEntityTypes) + " but is null"
: referenceFieldName + "' must be of type " + toDisplay(referencedEntityTypes) + " but is of type " + referencedEntityType);
}
break;
case OPTIONAL:
if (actualEntityType != null && !referencedEntityTypes.contains(actualEntityType)) {
if (referencedEntityType != null && !referencedEntityTypes.contains(referencedEntityType)) {
return List.of(referenceFieldName + "' must be null or of type " + toDisplay(referencedEntityTypes) + " but is of type "
+ actualEntityType);
+ referencedEntityType);
}
break;
case FORBIDDEN:
if (actualEntityType != null) {
return List.of(referenceFieldName + "' must be null but is of type " + actualEntityType);
if (referencedEntityType != null) {
return List.of(referenceFieldName + "' must be null but is of type " + referencedEntityType);
}
break;
}

View File

@ -8,7 +8,8 @@ create type HsBookingItemType as enum (
'PRIVATE_CLOUD',
'CLOUD_SERVER',
'MANAGED_SERVER',
'MANAGED_WEBSPACE'
'MANAGED_WEBSPACE',
'DOMAIN_SETUP'
);
CREATE CAST (character varying as HsBookingItemType) WITH INOUT AS IMPLICIT;

View File

@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test;
import jakarta.persistence.EntityManager;
import jakarta.validation.ValidationException;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.DOMAIN_SETUP;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.PRIVATE_CLOUD;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
@ -53,6 +54,6 @@ class HsBookingItemEntityValidatorUnitTest {
final var result = HsBookingItemEntityValidatorRegistry.types();
// then
assertThat(result).containsExactlyInAnyOrder(PRIVATE_CLOUD, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE);
assertThat(result).containsExactlyInAnyOrder(PRIVATE_CLOUD, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE, DOMAIN_SETUP);
}
}

View File

@ -249,6 +249,15 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
void globalAdmin_canAddTopLevelAsset() {
context.define("superuser-alex@hostsharing.net");
final var givenProject = realProjectRepo.findByCaption("D-1000111 default project").stream()
.findAny().orElseThrow();
final var bookingItem = givenSomeTemporaryBookingItem(() ->
HsBookingItemRealEntity.builder()
.project(givenProject)
.type(HsBookingItemType.DOMAIN_SETUP)
.caption("some temp domain setup booking item")
.build()
);
final var location = RestAssured // @formatter:off
.given()
@ -256,12 +265,13 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
.contentType(ContentType.JSON)
.body("""
{
"bookingItemUuid": "%s",
"type": "DOMAIN_SETUP",
"identifier": "example.com",
"caption": "some unrelated domain-setup",
"config": {}
}
""")
""".formatted(bookingItem.getUuid()))
.port(port)
.when()
.post("http://localhost/api/hs/hosting/assets")
@ -729,6 +739,13 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
}).assertSuccessful().returnedValue();
}
private HsBookingItemRealEntity givenSomeTemporaryBookingItem(final Supplier<HsBookingItemRealEntity> newBookingItem) {
return jpaAttempt.transacted(() -> {
context.define("superuser-alex@hostsharing.net"); // needed to determine creator
return toCleanup(realBookingItemRepo.save(newBookingItem.get()));
}).assertSuccessful().returnedValue();
}
HsHostingAssetRealEntity givenParentAsset(final HsHostingAssetType assetType, final String assetIdentifier) {
final var givenAsset = realAssetRepo.findByIdentifier(assetIdentifier).stream()
.filter(a -> a.getType() == assetType)

View File

@ -15,18 +15,19 @@ class HsHostingAssetTypeUnitTest {
### Server+Webspace
```plantuml
@startuml
left to right direction
package Booking #feb28c {
entity BI_PRIVATE_CLOUD
entity BI_CLOUD_SERVER
entity BI_MANAGED_SERVER
entity BI_MANAGED_WEBSPACE
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
package Server #99bcdb {
entity HA_CLOUD_SERVER
@ -34,19 +35,19 @@ class HsHostingAssetTypeUnitTest {
entity HA_IPV4_NUMBER
entity HA_IPV6_NUMBER
}
package Webspace #99bcdb {
entity HA_MANAGED_WEBSPACE
entity HA_UNIX_USER
entity HA_EMAIL_ALIAS
}
}
BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD
BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD
BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER
HA_CLOUD_SERVER *==> BI_CLOUD_SERVER
HA_MANAGED_SERVER *==> BI_MANAGED_SERVER
HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
@ -59,7 +60,7 @@ class HsHostingAssetTypeUnitTest {
HA_IPV6_NUMBER o..> HA_CLOUD_SERVER
HA_IPV6_NUMBER o..> HA_MANAGED_SERVER
HA_IPV6_NUMBER o..> HA_MANAGED_WEBSPACE
package Legend #white {
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY
@ -68,20 +69,21 @@ class HsHostingAssetTypeUnitTest {
}
Booking -down[hidden]->Legend
```
### Domain
```plantuml
@startuml
left to right direction
package Booking #feb28c {
entity BI_PRIVATE_CLOUD
entity BI_CLOUD_SERVER
entity BI_MANAGED_SERVER
entity BI_MANAGED_WEBSPACE
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
package Domain #99bcdb {
entity HA_DOMAIN_SETUP
@ -91,22 +93,23 @@ class HsHostingAssetTypeUnitTest {
entity HA_DOMAIN_MBOX_SETUP
entity HA_EMAIL_ADDRESS
}
package Webspace #99bcdb {
entity HA_MANAGED_WEBSPACE
entity HA_UNIX_USER
entity HA_EMAIL_ALIAS
}
}
BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD
BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD
BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER
HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
HA_UNIX_USER *==> HA_MANAGED_WEBSPACE
HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE
HA_DOMAIN_SETUP *..> BI_DOMAIN_SETUP
HA_DOMAIN_SETUP o..> HA_DOMAIN_SETUP
HA_DOMAIN_DNS_SETUP *==> HA_DOMAIN_SETUP
HA_DOMAIN_DNS_SETUP o--> HA_MANAGED_WEBSPACE
@ -117,7 +120,7 @@ class HsHostingAssetTypeUnitTest {
HA_DOMAIN_MBOX_SETUP *==> HA_DOMAIN_SETUP
HA_DOMAIN_MBOX_SETUP o--> HA_MANAGED_WEBSPACE
HA_EMAIL_ADDRESS *==> HA_DOMAIN_MBOX_SETUP
package Legend #white {
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY
@ -126,46 +129,47 @@ class HsHostingAssetTypeUnitTest {
}
Booking -down[hidden]->Legend
```
### MariaDB
```plantuml
@startuml
left to right direction
package Booking #feb28c {
entity BI_PRIVATE_CLOUD
entity BI_CLOUD_SERVER
entity BI_MANAGED_SERVER
entity BI_MANAGED_WEBSPACE
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
package MariaDB #99bcdb {
entity HA_MARIADB_INSTANCE
entity HA_MARIADB_USER
entity HA_MARIADB_DATABASE
}
package Webspace #99bcdb {
entity HA_MANAGED_WEBSPACE
entity HA_UNIX_USER
entity HA_EMAIL_ALIAS
}
}
BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD
BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD
BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER
HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
HA_UNIX_USER *==> HA_MANAGED_WEBSPACE
HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE
HA_MARIADB_USER *==> HA_MANAGED_WEBSPACE
HA_MARIADB_USER o--> HA_MARIADB_INSTANCE
HA_MARIADB_DATABASE *==> HA_MARIADB_USER
package Legend #white {
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY
@ -174,46 +178,47 @@ class HsHostingAssetTypeUnitTest {
}
Booking -down[hidden]->Legend
```
### PostgreSQL
```plantuml
@startuml
left to right direction
package Booking #feb28c {
entity BI_PRIVATE_CLOUD
entity BI_CLOUD_SERVER
entity BI_MANAGED_SERVER
entity BI_MANAGED_WEBSPACE
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
package PostgreSQL #99bcdb {
entity HA_PGSQL_INSTANCE
entity HA_PGSQL_USER
entity HA_PGSQL_DATABASE
}
package Webspace #99bcdb {
entity HA_MANAGED_WEBSPACE
entity HA_UNIX_USER
entity HA_EMAIL_ALIAS
}
}
BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD
BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD
BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER
HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
HA_UNIX_USER *==> HA_MANAGED_WEBSPACE
HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE
HA_PGSQL_USER *==> HA_MANAGED_WEBSPACE
HA_PGSQL_USER o--> HA_PGSQL_INSTANCE
HA_PGSQL_DATABASE *==> HA_PGSQL_USER
package Legend #white {
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY
@ -222,7 +227,7 @@ class HsHostingAssetTypeUnitTest {
}
Booking -down[hidden]->Legend
```
This code generated was by HsHostingAssetType.main, do not amend manually.
""");
}

View File

@ -20,6 +20,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder<?, ?> validEntityBuilder() {
return HsHostingAssetRbacEntity.builder()
.type(DOMAIN_SETUP)
.bookingItem(HsBookingItemRealEntity.builder().type(HsBookingItemType.DOMAIN_SETUP).build())
.identifier("example.org");
}
@ -93,20 +94,33 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
@Test
void validatesReferencedEntities() {
// given
final var mangedServerHostingAssetEntity = validEntityBuilder()
final var domainSetupHostingAssetEntity = validEntityBuilder()
.parentAsset(HsHostingAssetRealEntity.builder().type(CLOUD_SERVER).build())
.assignedToAsset(HsHostingAssetRealEntity.builder().type(MANAGED_SERVER).build())
.bookingItem(HsBookingItemRealEntity.builder().type(HsBookingItemType.CLOUD_SERVER).build())
.build();
final var validator = HostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType());
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
// when
final var result = validator.validateEntity(mangedServerHostingAssetEntity);
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
// then
assertThat(result).containsExactlyInAnyOrder(
"'DOMAIN_SETUP:example.org.bookingItem' must be null but is of type CLOUD_SERVER",
"'DOMAIN_SETUP:example.org.bookingItem' or parentItem must be null but is of type CLOUD_SERVER",
"'DOMAIN_SETUP:example.org.parentAsset' must be null or of type DOMAIN_SETUP but is of type CLOUD_SERVER",
"'DOMAIN_SETUP:example.org.assignedToAsset' must be null but is of type MANAGED_SERVER");
}
@Test
void expectsEitherParentAssetOrBookingItem() {
// given
final var domainSetupHostingAssetEntity = validEntityBuilder().build();
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
// when
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
// then
assertThat(result).isEmpty();
}
}

View File

@ -513,15 +513,15 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
assertThat(firstOfEach(12, domainSetupAssets)).isEqualToIgnoringWhitespace("""
{
4531=HsHostingAsset(DOMAIN_SETUP, l-u-g.org, l-u-g.org),
4532=HsHostingAsset(DOMAIN_SETUP, linuxfanboysngirls.de, linuxfanboysngirls.de),
4534=HsHostingAsset(DOMAIN_SETUP, lug-mars.de, lug-mars.de),
4581=HsHostingAsset(DOMAIN_SETUP, 1981.ist-im-netz.de, 1981.ist-im-netz.de, DOMAIN_SETUP:ist-im-netz.de),
4587=HsHostingAsset(DOMAIN_SETUP, mellis.de, mellis.de),
4589=HsHostingAsset(DOMAIN_SETUP, ist-im-netz.de, ist-im-netz.de),
4600=HsHostingAsset(DOMAIN_SETUP, waera.de, waera.de),
4604=HsHostingAsset(DOMAIN_SETUP, xn--wra-qla.de, wära.de),
7662=HsHostingAsset(DOMAIN_SETUP, dph-netzwerk.de, dph-netzwerk.de)
4531=HsHostingAsset(DOMAIN_SETUP, l-u-g.org, l-u-g.org, D-1000300:mim default project:BI l-u-g.org),
4532=HsHostingAsset(DOMAIN_SETUP, linuxfanboysngirls.de, linuxfanboysngirls.de, D-1000300:mim default project:BI linuxfanboysngirls.de),
4534=HsHostingAsset(DOMAIN_SETUP, lug-mars.de, lug-mars.de, D-1000300:mim default project:BI lug-mars.de),
4581=HsHostingAsset(DOMAIN_SETUP, 1981.ist-im-netz.de, 1981.ist-im-netz.de, DOMAIN_SETUP:ist-im-netz.de),
4587=HsHostingAsset(DOMAIN_SETUP, mellis.de, mellis.de, D-1000300:mim default project:BI mellis.de),
4589=HsHostingAsset(DOMAIN_SETUP, ist-im-netz.de, ist-im-netz.de, D-1000300:mim default project:BI ist-im-netz.de),
4600=HsHostingAsset(DOMAIN_SETUP, waera.de, waera.de, D-1000300:mim default project:BI waera.de),
4604=HsHostingAsset(DOMAIN_SETUP, xn--wra-qla.de, wära.de, D-1000300:mim default project:BI xn--wra-qla.de),
7662=HsHostingAsset(DOMAIN_SETUP, dph-netzwerk.de, dph-netzwerk.de, D-1101900:dph default project:BI dph-netzwerk.de)
}
""");
@ -1441,6 +1441,7 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
// Domain Setup
final var domainSetupAsset = HsHostingAssetRealEntity.builder()
// .bookingItem(bookingItem) are set once we've collected all domains
.type(DOMAIN_SETUP)
// .parentAsset(parentDomainSetupAsset) are set once we've collected all of them
.identifier(domain_name)
@ -1542,10 +1543,27 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
final var parentDomainSetup = domainSetupsByName.get(parentDomainName);
if (parentDomainSetup != null) {
domainSetup.setParentAsset(parentDomainSetup);
} else {
final var relatedProject = domainSetup.getSubHostingAssets().stream()
.map(ha -> ha.getAssignedToAsset() != null ? ha.getAssignedToAsset().getRelatedProject() : null)
.findAny().orElseThrow();
final var bookingItem = HsBookingItemRealEntity.builder()
.type(HsBookingItemType.DOMAIN_SETUP)
.caption("BI " + domainSetup.getIdentifier())
.project((HsBookingProjectRealEntity) relatedProject)
//.validity(toPostgresDateRange(created, cancelled))
.build();
domainSetup.setBookingItem(bookingItem);
bookingItems.put(nextAvailableBookingItemId(), bookingItem);
}
});
}
private static @NotNull Integer nextAvailableBookingItemId() {
return bookingItems.keySet().stream().max(Long::compare).map(id -> id + 1).orElseThrow();
}
private String withDefault(final String givenValue, final Object defaultValue) {
if (defaultValue instanceof String defaultStringValue) {
return givenValue != null && !givenValue.isBlank() ? givenValue : defaultStringValue;