hosting-asset-data-migration (#79)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: #79 Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
parent
c191af2ea1
commit
4d27a98c9a
18
.aliases
18
.aliases
@ -1,4 +1,4 @@
|
|||||||
# For using the alias import-office-tables,
|
# For using the alias gw-importOfficeData or gw-importHostingAssets,
|
||||||
# copy the file .tc-environment to .environment (ignored by git)
|
# copy the file .tc-environment to .environment (ignored by git)
|
||||||
# and amend them according to your external DB.
|
# and amend them according to your external DB.
|
||||||
|
|
||||||
@ -42,7 +42,11 @@ postgresAutodoc () {
|
|||||||
}
|
}
|
||||||
alias postgres-autodoc=postgresAutodoc
|
alias postgres-autodoc=postgresAutodoc
|
||||||
|
|
||||||
function importOfficeData() {
|
function importLegacyData() {
|
||||||
|
export target=$1
|
||||||
|
if [ -z "$target" ]; then
|
||||||
|
echo "importLegacyData needs target argument, but none was given" >&2
|
||||||
|
else
|
||||||
source .tc-environment
|
source .tc-environment
|
||||||
|
|
||||||
if [ -f .environment ]; then
|
if [ -f .environment ]; then
|
||||||
@ -50,11 +54,17 @@ function importOfficeData() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "using environment (with ending ';' for use in IntelliJ IDEA):"
|
echo "using environment (with ending ';' for use in IntelliJ IDEA):"
|
||||||
|
echo "--- BEGIN: ---"
|
||||||
set | grep ^HSADMINNG_ | sed 's/$/;/'
|
set | grep ^HSADMINNG_ | sed 's/$/;/'
|
||||||
|
echo "---- END. ----"
|
||||||
|
echo
|
||||||
|
|
||||||
./gradlew importOfficeData --rerun
|
echo ./gradlew $target --rerun
|
||||||
|
./gradlew $target --rerun
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
alias gw-importOfficeData=importOfficeData
|
alias gw-importOfficeData='importLegacyData importOfficeData'
|
||||||
|
alias gw-importHostingAssets='importLegacyData importHostingAssets'
|
||||||
|
|
||||||
alias podman-start='systemctl --user enable --now podman.socket && systemctl --user status podman.socket && ls -la /run/user/$UID/podman/podman.sock'
|
alias podman-start='systemctl --user enable --now podman.socket && systemctl --user status podman.socket && ls -la /run/user/$UID/podman/podman.sock'
|
||||||
alias podman-stop='systemctl --user disable --now podman.socket && systemctl --user status podman.socket && ls -la /run/user/$UID/podman/podman.sock'
|
alias podman-stop='systemctl --user disable --now podman.socket && systemctl --user status podman.socket && ls -la /run/user/$UID/podman/podman.sock'
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -136,4 +136,9 @@ Desktop.ini
|
|||||||
# ESLint
|
# ESLint
|
||||||
######################
|
######################
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
|
||||||
|
######################
|
||||||
|
# Project Related
|
||||||
|
######################
|
||||||
/.environment*
|
/.environment*
|
||||||
|
/src/test/resources/migration-prod/*
|
||||||
|
12
build.gradle
12
build.gradle
@ -318,7 +318,7 @@ jacocoTestCoverageVerification {
|
|||||||
|
|
||||||
tasks.register('importOfficeData', Test) {
|
tasks.register('importOfficeData', Test) {
|
||||||
useJUnitPlatform {
|
useJUnitPlatform {
|
||||||
includeTags 'import'
|
includeTags 'importOfficeData'
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'verification'
|
group 'verification'
|
||||||
@ -327,6 +327,16 @@ tasks.register('importOfficeData', Test) {
|
|||||||
mustRunAfter spotlessJava
|
mustRunAfter spotlessJava
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.register('importHostingAssets', Test) {
|
||||||
|
useJUnitPlatform {
|
||||||
|
includeTags 'importHostingAssets'
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'verification'
|
||||||
|
description 'run the import jobs as tests'
|
||||||
|
|
||||||
|
mustRunAfter spotlessJava
|
||||||
|
}
|
||||||
|
|
||||||
// pitest mutation testing
|
// pitest mutation testing
|
||||||
pitest {
|
pitest {
|
||||||
|
@ -18,7 +18,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
|||||||
|
|
||||||
// a partial HsOfficeDebitorEntity to reduce the number of SQL queries to load the entity
|
// a partial HsOfficeDebitorEntity to reduce the number of SQL queries to load the entity
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "hs_booking_debitor_rv")
|
@Table(name = "hs_booking_debitor_xv")
|
||||||
@Getter
|
@Getter
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@ -184,7 +184,9 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject, Propertie
|
|||||||
}
|
}
|
||||||
|
|
||||||
public HsBookingProjectEntity getRelatedProject() {
|
public HsBookingProjectEntity getRelatedProject() {
|
||||||
return project != null ? project : parentItem.getRelatedProject();
|
return project != null ? project
|
||||||
|
: parentItem != null ? parentItem.getRelatedProject()
|
||||||
|
: null; // can be the case for technical assets like IP-numbers
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RbacView rbac() {
|
public static RbacView rbac() {
|
||||||
|
@ -22,6 +22,10 @@ public class HsBookingItemEntityValidator extends HsEntityValidator<HsBookingIte
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> validateEntity(final HsBookingItemEntity bookingItem) {
|
public List<String> validateEntity(final HsBookingItemEntity bookingItem) {
|
||||||
|
// TODO.impl: HsBookingItemType could do this similar to HsHostingAssetType
|
||||||
|
if ( bookingItem.getParentItem() == null && bookingItem.getProject() == null) {
|
||||||
|
return List.of(bookingItem + ".'parentItem' or .'project' expected to be set, but both are null");
|
||||||
|
}
|
||||||
return enrich(prefix(bookingItem.toShortString(), "resources"), super.validateProperties(bookingItem));
|
return enrich(prefix(bookingItem.toShortString(), "resources"), super.validateProperties(bookingItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,11 +11,12 @@ class HsCloudServerBookingItemValidator extends HsBookingItemEntityValidator {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
booleanProperty("active") .withDefault(true),
|
booleanProperty("active") .withDefault(true),
|
||||||
|
|
||||||
integerProperty("CPUs") .min( 1) .max( 32) .required(),
|
integerProperty("CPU") .min( 1) .max( 32) .required(),
|
||||||
integerProperty("RAM").unit("GB") .min( 1) .max( 128) .required(),
|
integerProperty("RAM").unit("GB") .min( 1) .max( 8192) .required(),
|
||||||
integerProperty("SSD").unit("GB") .min( 0) .max( 1000) .step(25).required(), // (1)
|
integerProperty("SSD").unit("GB") .min( 25) .max( 1000) .step(25).requiresAtLeastOneOf("SDD", "HDD"),
|
||||||
integerProperty("HDD").unit("GB") .min( 0) .max( 4000) .step(250).withDefault(0),
|
integerProperty("HDD").unit("GB") .min(250) .max( 4000) .step(250).requiresAtLeastOneOf("SSD", "HDD"),
|
||||||
integerProperty("Traffic").unit("GB") .min(250) .max(10000) .step(250).required(),
|
integerProperty("Traffic").unit("GB") .min(250) .max(10000) .step(250).requiresAtMaxOneOf("Bandwidth", "Traffic"),
|
||||||
|
integerProperty("Bandwidth").unit("GB") .min(250) .max(10000) .step(250).requiresAtMaxOneOf("Bandwidth", "Traffic"), // TODO.spec
|
||||||
|
|
||||||
enumerationProperty("SLA-Infrastructure").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional()
|
enumerationProperty("SLA-Infrastructure").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional()
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
@ -10,11 +10,12 @@ class HsManagedServerBookingItemValidator extends HsBookingItemEntityValidator {
|
|||||||
|
|
||||||
HsManagedServerBookingItemValidator() {
|
HsManagedServerBookingItemValidator() {
|
||||||
super(
|
super(
|
||||||
integerProperty("CPUs").min(1).max(32).required(),
|
integerProperty("CPU").min(1).max(32).required(),
|
||||||
integerProperty("RAM").unit("GB").min(1).max(128).required(),
|
integerProperty("RAM").unit("GB").min(1).max(128).required(),
|
||||||
integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required().asTotalLimit().withThreshold(200),
|
integerProperty("SSD").unit("GB").min(25).max(2000).step(25).requiresAtLeastOneOf("SSD", "HDD").asTotalLimit().withThreshold(200),
|
||||||
integerProperty("HDD").unit("GB").min(0).max(4000).step(250).withDefault(0).asTotalLimit().withThreshold(200),
|
integerProperty("HDD").unit("GB").min(250).max(10000).step(250).requiresAtLeastOneOf("SSD", "HDD").asTotalLimit().withThreshold(200),
|
||||||
integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required().asTotalLimit().withThreshold(200),
|
integerProperty("Traffic").unit("GB").min(250).max(64000).step(250).requiresAtMaxOneOf("Bandwidth", "Traffic").asTotalLimit().withThreshold(200),
|
||||||
|
integerProperty("Bandwidth").unit("GB").min(250).max(64000).step(250).requiresAtMaxOneOf("Bandwidth", "Traffic").asTotalLimit().withThreshold(200), // TODO.spec
|
||||||
enumerationProperty("SLA-Platform").values("BASIC", "EXT8H", "EXT4H", "EXT2H").withDefault("BASIC"),
|
enumerationProperty("SLA-Platform").values("BASIC", "EXT8H", "EXT4H", "EXT2H").withDefault("BASIC"),
|
||||||
booleanProperty("SLA-EMail").falseIf("SLA-Platform", "BASIC").withDefault(false),
|
booleanProperty("SLA-EMail").falseIf("SLA-Platform", "BASIC").withDefault(false),
|
||||||
booleanProperty("SLA-Maria").falseIf("SLA-Platform", "BASIC").optional(),
|
booleanProperty("SLA-Maria").falseIf("SLA-Platform", "BASIC").optional(),
|
||||||
|
@ -23,16 +23,17 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
|
|||||||
|
|
||||||
public HsManagedWebspaceBookingItemValidator() {
|
public HsManagedWebspaceBookingItemValidator() {
|
||||||
super(
|
super(
|
||||||
integerProperty("SSD").unit("GB").min(1).max(100).step(1).required(),
|
integerProperty("SSD").unit("GB").min(1).max(2000).step(1).required(),
|
||||||
integerProperty("HDD").unit("GB").min(0).max(250).step(10).optional(),
|
integerProperty("HDD").unit("GB").min(0).max(10000).step(10).optional(),
|
||||||
integerProperty("Traffic").unit("GB").min(10).max(1000).step(10).required(),
|
integerProperty("Traffic").unit("GB").min(10).max(64000).step(10).requiresAtMaxOneOf("Bandwidth", "Traffic"),
|
||||||
|
integerProperty("Bandwidth").unit("GB").min(10).max(1000).step(10).requiresAtMaxOneOf("Bandwidth", "Traffic"), // TODO.spec
|
||||||
integerProperty("Multi").min(1).max(100).step(1).withDefault(1)
|
integerProperty("Multi").min(1).max(100).step(1).withDefault(1)
|
||||||
.eachComprising( 25, unixUsers())
|
.eachComprising( 25, unixUsers())
|
||||||
.eachComprising( 5, databaseUsers())
|
.eachComprising( 5, databaseUsers())
|
||||||
.eachComprising( 5, databases())
|
.eachComprising( 5, databases())
|
||||||
.eachComprising(250, eMailAddresses()),
|
.eachComprising(250, eMailAddresses()),
|
||||||
integerProperty("Daemons").min(0).max(10).withDefault(0),
|
integerProperty("Daemons").min(0).max(16).withDefault(0),
|
||||||
booleanProperty("Online Office Server").optional(),
|
booleanProperty("Online Office Server").optional(), // TODO.impl: shorten to "Office"
|
||||||
enumerationProperty("SLA-Platform").values("BASIC", "EXT24H").withDefault("BASIC")
|
enumerationProperty("SLA-Platform").values("BASIC", "EXT24H").withDefault("BASIC")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,16 @@ class HsPrivateCloudBookingItemValidator extends HsBookingItemEntityValidator {
|
|||||||
HsPrivateCloudBookingItemValidator() {
|
HsPrivateCloudBookingItemValidator() {
|
||||||
super(
|
super(
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
integerProperty("CPUs") .min( 1).max( 128).required().asTotalLimit(),
|
integerProperty("CPU") .min( 1).max( 128).required().asTotalLimit(),
|
||||||
integerProperty("RAM").unit("GB") .min( 1).max( 512).required().asTotalLimit(),
|
integerProperty("RAM").unit("GB") .min( 1).max( 512).required().asTotalLimit(),
|
||||||
integerProperty("SSD").unit("GB") .min( 25).max( 4000).step(25).required().asTotalLimit(),
|
integerProperty("SSD").unit("GB") .min( 25).max( 4000).step(25).requiresAtLeastOneOf("SSD", "HDD").asTotalLimit(),
|
||||||
integerProperty("HDD").unit("GB") .min( 0).max(16000).step(250).withDefault(0).asTotalLimit(),
|
integerProperty("HDD").unit("GB") .min(250).max(16000).step(250).requiresAtLeastOneOf("SSD", "HDD").asTotalLimit(),
|
||||||
integerProperty("Traffic").unit("GB") .min(250).max(40000).step(250).required().asTotalLimit(),
|
integerProperty("Traffic").unit("GB") .min(250).max(64000).step(250).requiresAtMaxOneOf("Bandwidth", "Traffic").asTotalLimit(),
|
||||||
|
integerProperty("Bandwidth").unit("GB") .min(250).max(64000).step(250).requiresAtMaxOneOf("Bandwidth", "Traffic").asTotalLimit(), // TODO.spec
|
||||||
|
|
||||||
// Alternatively we could specify it similarly to "Multi" option but exclusively counting:
|
// Alternatively we could specify it similarly to "Multi" option but exclusively counting:
|
||||||
// integerProperty("Resource-Points") .min(4).max(100).required()
|
// integerProperty("Resource-Points") .min(4).max(100).required()
|
||||||
// .each("CPUs").countsAs(64)
|
// .each("CPU").countsAs(64)
|
||||||
// .each("RAM").countsAs(64)
|
// .each("RAM").countsAs(64)
|
||||||
// .each("SSD").countsAs(18)
|
// .each("SSD").countsAs(18)
|
||||||
// .each("HDD").countsAs(2)
|
// .each("HDD").countsAs(2)
|
||||||
|
@ -8,6 +8,7 @@ import lombok.Getter;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.validation.PropertiesProvider;
|
import net.hostsharing.hsadminng.hs.validation.PropertiesProvider;
|
||||||
import net.hostsharing.hsadminng.mapper.PatchableMapWrapper;
|
import net.hostsharing.hsadminng.mapper.PatchableMapWrapper;
|
||||||
@ -38,6 +39,7 @@ import java.io.IOException;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static java.util.Collections.emptyMap;
|
import static java.util.Collections.emptyMap;
|
||||||
@ -134,6 +136,14 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Properti
|
|||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HsBookingProjectEntity getRelatedProject() {
|
||||||
|
return Optional.ofNullable(bookingItem)
|
||||||
|
.map(HsBookingItemEntity::getRelatedProject)
|
||||||
|
.orElseGet(() -> Optional.ofNullable(parentAsset)
|
||||||
|
.map(HsHostingAssetEntity::getRelatedProject)
|
||||||
|
.orElse(null));
|
||||||
|
}
|
||||||
|
|
||||||
public PatchableMapWrapper<Object> getConfig() {
|
public PatchableMapWrapper<Object> getConfig() {
|
||||||
return PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper;}, config);
|
return PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper;}, config);
|
||||||
}
|
}
|
||||||
@ -163,7 +173,6 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Properti
|
|||||||
return emptyMap();
|
return emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return stringify.apply(this);
|
return stringify.apply(this);
|
||||||
@ -202,7 +211,8 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Properti
|
|||||||
directlyFetchedByDependsOnColumn(),
|
directlyFetchedByDependsOnColumn(),
|
||||||
NULLABLE)
|
NULLABLE)
|
||||||
|
|
||||||
.switchOnColumn("type",
|
.switchOnColumn(
|
||||||
|
"type",
|
||||||
inCaseOf("DOMAIN_SETUP", then -> {
|
inCaseOf("DOMAIN_SETUP", then -> {
|
||||||
then.toRole(GLOBAL, GUEST).grantPermission(INSERT);
|
then.toRole(GLOBAL, GUEST).grantPermission(INSERT);
|
||||||
})
|
})
|
||||||
@ -231,7 +241,14 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Properti
|
|||||||
with.permission(SELECT);
|
with.permission(SELECT);
|
||||||
})
|
})
|
||||||
|
|
||||||
.limitDiagramTo("asset", "bookingItem", "bookingItem.debitorRel", "parentAsset", "assignedToAsset", "alarmContact", "global");
|
.limitDiagramTo(
|
||||||
|
"asset",
|
||||||
|
"bookingItem",
|
||||||
|
"bookingItem.debitorRel",
|
||||||
|
"parentAsset",
|
||||||
|
"assignedToAsset",
|
||||||
|
"alarmContact",
|
||||||
|
"global");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
@ -18,7 +18,7 @@ class HsManagedWebspaceHostingAssetValidator extends HostingAssetEntityValidator
|
|||||||
protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) {
|
protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) {
|
||||||
final var prefixPattern =
|
final var prefixPattern =
|
||||||
!assetEntity.isLoaded()
|
!assetEntity.isLoaded()
|
||||||
? assetEntity.getParentAsset().getBookingItem().getProject().getDebitor().getDefaultPrefix()
|
? assetEntity.getRelatedProject().getDebitor().getDefaultPrefix()
|
||||||
: "[a-z][a-z0-9][a-z0-9]";
|
: "[a-z][a-z0-9][a-z0-9]";
|
||||||
return Pattern.compile("^" + prefixPattern + "[0-9][0-9]$");
|
return Pattern.compile("^" + prefixPattern + "[0-9][0-9]$");
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ public class HsOfficeMembershipEntity implements RbacObject, Stringifyable {
|
|||||||
|
|
||||||
private static Stringify<HsOfficeMembershipEntity> stringify = stringify(HsOfficeMembershipEntity.class)
|
private static Stringify<HsOfficeMembershipEntity> stringify = stringify(HsOfficeMembershipEntity.class)
|
||||||
.withProp(e -> MEMBER_NUMBER_TAG + e.getMemberNumber())
|
.withProp(e -> MEMBER_NUMBER_TAG + e.getMemberNumber())
|
||||||
.withProp(e -> e.getPartner().toShortString())
|
.withProp(HsOfficeMembershipEntity::getPartner)
|
||||||
.withProp(e -> e.getValidity().asString())
|
.withProp(e -> e.getValidity().asString())
|
||||||
.withProp(HsOfficeMembershipEntity::getStatus)
|
.withProp(HsOfficeMembershipEntity::getStatus)
|
||||||
.quotedValues(false);
|
.quotedValues(false);
|
||||||
|
@ -13,10 +13,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static java.lang.Boolean.FALSE;
|
import static java.lang.Boolean.FALSE;
|
||||||
@ -30,7 +32,7 @@ import static org.apache.commons.lang3.ObjectUtils.isArray;
|
|||||||
public abstract class ValidatableProperty<P extends ValidatableProperty<?, ?>, T> {
|
public abstract class ValidatableProperty<P extends ValidatableProperty<?, ?>, T> {
|
||||||
|
|
||||||
protected static final String[] KEY_ORDER_HEAD = Array.of("propertyName");
|
protected static final String[] KEY_ORDER_HEAD = Array.of("propertyName");
|
||||||
protected static final String[] KEY_ORDER_TAIL = Array.of("required", "defaultValue", "readOnly", "writeOnly", "computed", "isTotalsValidator", "thresholdPercentage");
|
protected static final String[] KEY_ORDER_TAIL = Array.of("required", "requiresAtLeastOneOf", "requiresAtMaxOneOf", "defaultValue", "readOnly", "writeOnly", "computed", "isTotalsValidator", "thresholdPercentage");
|
||||||
protected static final String[] KEY_ORDER = Array.join(KEY_ORDER_HEAD, KEY_ORDER_TAIL);
|
protected static final String[] KEY_ORDER = Array.join(KEY_ORDER_HEAD, KEY_ORDER_TAIL);
|
||||||
|
|
||||||
final Class<T> type;
|
final Class<T> type;
|
||||||
@ -40,6 +42,8 @@ public abstract class ValidatableProperty<P extends ValidatableProperty<?, ?>, T
|
|||||||
private final String[] keyOrder;
|
private final String[] keyOrder;
|
||||||
|
|
||||||
private Boolean required;
|
private Boolean required;
|
||||||
|
private Set<String> requiresAtLeastOneOf;
|
||||||
|
private Set<String> requiresAtMaxOneOf;
|
||||||
private T defaultValue;
|
private T defaultValue;
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
@ -100,9 +104,19 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
|
|||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValidatableProperty<P, T> optional() {
|
public P optional() {
|
||||||
required = FALSE;
|
required = FALSE;
|
||||||
return this;
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public P requiresAtLeastOneOf(final String... propNames) {
|
||||||
|
requiresAtLeastOneOf = new LinkedHashSet<>(List.of(propNames));
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public P requiresAtMaxOneOf(final String... propNames) {
|
||||||
|
requiresAtMaxOneOf = new LinkedHashSet<>(List.of(propNames));
|
||||||
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public P withDefault(final T value) {
|
public P withDefault(final T value) {
|
||||||
@ -172,28 +186,57 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
|
|||||||
final var result = new ArrayList<String>();
|
final var result = new ArrayList<String>();
|
||||||
final var props = propsProvider.directProps();
|
final var props = propsProvider.directProps();
|
||||||
final var propValue = props.get(propertyName);
|
final var propValue = props.get(propertyName);
|
||||||
|
|
||||||
if (propValue == null) {
|
if (propValue == null) {
|
||||||
if (required) {
|
if (required == TRUE) {
|
||||||
result.add(propertyName + "' is required but missing");
|
result.add(propertyName + "' is required but missing");
|
||||||
}
|
}
|
||||||
|
validateRequiresAtLeastOneOf(result, propsProvider);
|
||||||
}
|
}
|
||||||
if (propValue != null){
|
if (propValue != null){
|
||||||
|
validateRequiresAtMaxOneOf(result, propsProvider);
|
||||||
|
|
||||||
if ( type.isInstance(propValue)) {
|
if ( type.isInstance(propValue)) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
validate(result, (T) propValue, propsProvider);
|
validate(result, (T) propValue, propsProvider);
|
||||||
} else {
|
} else {
|
||||||
result.add(propertyName + "' is expected to be of type " + type.getSimpleName() + ", " +
|
result.add(propertyName + "' is expected to be of type " + type.getSimpleName() + ", " +
|
||||||
"but is of type " + propValue.getClass().getSimpleName() + "");
|
"but is of type " + propValue.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateRequiresAtLeastOneOf(final ArrayList<String> result, final PropertiesProvider propsProvider) {
|
||||||
|
if (requiresAtLeastOneOf != null ) {
|
||||||
|
final var allPropNames = propsProvider.directProps().keySet();
|
||||||
|
final var entriesWithValue = allPropNames.stream()
|
||||||
|
.filter(name -> requiresAtLeastOneOf.contains(name))
|
||||||
|
.count();
|
||||||
|
if (entriesWithValue == 0) {
|
||||||
|
result.add(propertyName + "' is required once in group " + requiresAtLeastOneOf + " but missing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateRequiresAtMaxOneOf(final ArrayList<String> result, final PropertiesProvider propsProvider) {
|
||||||
|
if (requiresAtMaxOneOf != null) {
|
||||||
|
final var allPropNames = propsProvider.directProps().keySet();
|
||||||
|
final var entriesWithValue = allPropNames.stream()
|
||||||
|
.filter(name -> requiresAtMaxOneOf.contains(name))
|
||||||
|
.count();
|
||||||
|
if (entriesWithValue > 1) {
|
||||||
|
result.add(propertyName + "' is required at max once in group " + requiresAtMaxOneOf
|
||||||
|
+ " but multiple properties are set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void validate(final List<String> result, final T propValue, final PropertiesProvider propProvider);
|
protected abstract void validate(final List<String> result, final T propValue, final PropertiesProvider propProvider);
|
||||||
|
|
||||||
public void verifyConsistency(final Map.Entry<? extends Enum<?>, ?> typeDef) {
|
public void verifyConsistency(final Map.Entry<? extends Enum<?>, ?> typeDef) {
|
||||||
if (required == null ) {
|
if (required == null && requiresAtLeastOneOf == null && requiresAtMaxOneOf == null) {
|
||||||
throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .required() or .optional()" );
|
throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .required(), .optional(), .withDefault(...), .requiresAtLeastOneOf(...) or .requiresAtMaxOneOf(...)" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
--changeset hs-booking-debitor-RESTRICTED-VIEW:1 endDelimiter:--//
|
--changeset hs-booking-debitor-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
create view hs_booking_debitor_rv as
|
create view hs_booking_debitor_xv as
|
||||||
select debitor.uuid,
|
select debitor.uuid,
|
||||||
debitor.version,
|
debitor.version,
|
||||||
(partner.partnerNumber::varchar || debitor.debitorNumberSuffix)::numeric as debitorNumber,
|
(partner.partnerNumber::varchar || debitor.debitorNumberSuffix)::numeric as debitorNumber,
|
||||||
debitor.defaultPrefix
|
debitor.defaultPrefix
|
||||||
from hs_office_debitor_rv debitor
|
from hs_office_debitor debitor
|
||||||
-- RBAC for debitor is sufficient, for faster access we are bypassing RBAC for the join tables
|
-- RBAC for debitor is sufficient, for faster access we are bypassing RBAC for the join tables
|
||||||
join hs_office_relation debitorRel on debitor.debitorReluUid=debitorRel.uuid
|
join hs_office_relation debitorRel on debitor.debitorReluUid=debitorRel.uuid
|
||||||
join hs_office_relation partnerRel on partnerRel.holderUuid=debitorRel.anchorUuid
|
join hs_office_relation partnerRel on partnerRel.holderUuid=debitorRel.anchorUuid
|
||||||
|
@ -33,11 +33,11 @@ begin
|
|||||||
managedServerUuid := uuid_generate_v4();
|
managedServerUuid := uuid_generate_v4();
|
||||||
insert
|
insert
|
||||||
into hs_booking_item (uuid, projectuuid, type, parentitemuuid, caption, validity, resources)
|
into hs_booking_item (uuid, projectuuid, type, parentitemuuid, caption, validity, resources)
|
||||||
values (privateCloudUuid, relatedProject.uuid, 'PRIVATE_CLOUD', null, 'some PrivateCloud', daterange('20240401', null, '[]'), '{ "CPUs": 10, "RAM": 32, "SSD": 4000, "HDD": 10000, "Traffic": 2000 }'::jsonb),
|
values (privateCloudUuid, relatedProject.uuid, 'PRIVATE_CLOUD', null, 'some PrivateCloud', daterange('20240401', null, '[]'), '{ "CPU": 10, "RAM": 32, "SSD": 4000, "HDD": 10000, "Traffic": 2000 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'MANAGED_SERVER', privateCloudUuid, 'some ManagedServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 2, "RAM": 4, "SSD": 500, "Traffic": 500 }'::jsonb),
|
(uuid_generate_v4(), null, 'MANAGED_SERVER', privateCloudUuid, 'some ManagedServer', daterange('20230115', '20240415', '[)'), '{ "CPU": 2, "RAM": 4, "SSD": 500, "Traffic": 500 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'test CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 2, "RAM": 4, "SSD": 750, "Traffic": 500 }'::jsonb),
|
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'test CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPU": 2, "RAM": 4, "SSD": 750, "Traffic": 500 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'prod CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 4, "RAM": 16, "SSD": 1000, "Traffic": 500 }'::jsonb),
|
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'prod CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPU": 4, "RAM": 16, "SSD": 1000, "Traffic": 500 }'::jsonb),
|
||||||
(managedServerUuid, relatedProject.uuid, 'MANAGED_SERVER', null, 'separate ManagedServer', daterange('20221001', null, '[]'), '{ "CPUs": 2, "RAM": 8, "SSD": 500, "Traffic": 500 }'::jsonb),
|
(managedServerUuid, relatedProject.uuid, 'MANAGED_SERVER', null, 'separate ManagedServer', daterange('20221001', null, '[]'), '{ "CPU": 2, "RAM": 8, "SSD": 500, "Traffic": 500 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'MANAGED_WEBSPACE', managedServerUuid, 'some ManagedWebspace', daterange('20221001', null, '[]'), '{ "SSD": 50, "Traffic": 20, "Daemons": 2, "Multi": 4 }'::jsonb),
|
(uuid_generate_v4(), null, 'MANAGED_WEBSPACE', managedServerUuid, 'some ManagedWebspace', daterange('20221001', null, '[]'), '{ "SSD": 50, "Traffic": 20, "Daemons": 2, "Multi": 4 }'::jsonb),
|
||||||
(uuid_generate_v4(), relatedProject.uuid, 'MANAGED_WEBSPACE', null, 'separate ManagedWebspace', daterange('20221001', null, '[]'), '{ "SSD": 100, "Traffic": 50, "Daemons": 0, "Multi": 1 }'::jsonb);
|
(uuid_generate_v4(), relatedProject.uuid, 'MANAGED_WEBSPACE', null, 'separate ManagedWebspace', daterange('20221001', null, '[]'), '{ "SSD": 100, "Traffic": 50, "Daemons": 0, "Multi": 1 }'::jsonb);
|
||||||
end; $$;
|
end; $$;
|
||||||
|
@ -42,7 +42,7 @@ create table if not exists hs_hosting_asset
|
|||||||
alarmContactUuid uuid null references hs_office_contact(uuid) initially deferred,
|
alarmContactUuid uuid null references hs_office_contact(uuid) initially deferred,
|
||||||
|
|
||||||
constraint chk_hs_hosting_asset_has_booking_item_or_parent_asset
|
constraint chk_hs_hosting_asset_has_booking_item_or_parent_asset
|
||||||
check (bookingItemUuid is not null or parentAssetUuid is not null or type='DOMAIN_SETUP')
|
check (bookingItemUuid is not null or parentAssetUuid is not null or type in ('DOMAIN_SETUP', 'IPV4_NUMBER', 'IPV6_NUMBER'))
|
||||||
);
|
);
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.coopshares",
|
"..hs.office.coopshares",
|
||||||
"..hs.office.debitor",
|
"..hs.office.debitor",
|
||||||
"..hs.office.membership",
|
"..hs.office.membership",
|
||||||
"..hs.office.migration",
|
"..hs.migration",
|
||||||
"..hs.office.partner",
|
"..hs.office.partner",
|
||||||
"..hs.office.person",
|
"..hs.office.person",
|
||||||
"..hs.office.relation",
|
"..hs.office.relation",
|
||||||
@ -156,6 +156,7 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.(*)..",
|
"..hs.office.(*)..",
|
||||||
"..hs.booking.(*)..",
|
"..hs.booking.(*)..",
|
||||||
"..hs.hosting.(*)..",
|
"..hs.hosting.(*)..",
|
||||||
|
"..hs.migration",
|
||||||
"..rbac.rbacgrant" // TODO.test: just because of RbacGrantsDiagramServiceIntegrationTest
|
"..rbac.rbacgrant" // TODO.test: just because of RbacGrantsDiagramServiceIntegrationTest
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -167,7 +168,8 @@ public class ArchitectureTest {
|
|||||||
.resideInAnyPackage(
|
.resideInAnyPackage(
|
||||||
"..hs.booking.(*)..",
|
"..hs.booking.(*)..",
|
||||||
"..hs.hosting.(*)..",
|
"..hs.hosting.(*)..",
|
||||||
"..hs.validation" // TODO.impl: Some Validators need to be refactored to booking package.
|
"..hs.validation", // TODO.impl: Some Validators need to be refactored to booking package.
|
||||||
|
"..hs.migration.."
|
||||||
);
|
);
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@ -177,7 +179,8 @@ public class ArchitectureTest {
|
|||||||
.should().onlyBeAccessed().byClassesThat()
|
.should().onlyBeAccessed().byClassesThat()
|
||||||
.resideInAnyPackage(
|
.resideInAnyPackage(
|
||||||
"..hs.hosting.(*)..",
|
"..hs.hosting.(*)..",
|
||||||
"..hs.booking.(*).." // TODO.impl: fix this cyclic dependency
|
"..hs.booking.(*)..", // TODO.impl: fix this cyclic dependency
|
||||||
|
"..hs.migration.."
|
||||||
);
|
);
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@ -189,7 +192,7 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.bankaccount..",
|
"..hs.office.bankaccount..",
|
||||||
"..hs.office.sepamandate..",
|
"..hs.office.sepamandate..",
|
||||||
"..hs.office.debitor..",
|
"..hs.office.debitor..",
|
||||||
"..hs.office.migration..");
|
"..hs.migration..");
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ -199,7 +202,7 @@ public class ArchitectureTest {
|
|||||||
.resideInAnyPackage(
|
.resideInAnyPackage(
|
||||||
"..hs.office.sepamandate..",
|
"..hs.office.sepamandate..",
|
||||||
"..hs.office.debitor..",
|
"..hs.office.debitor..",
|
||||||
"..hs.office.migration..");
|
"..hs.migration..");
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ -212,7 +215,7 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.partner..",
|
"..hs.office.partner..",
|
||||||
"..hs.office.debitor..",
|
"..hs.office.debitor..",
|
||||||
"..hs.office.membership..",
|
"..hs.office.membership..",
|
||||||
"..hs.office.migration..",
|
"..hs.migration..",
|
||||||
"..hs.hosting.asset.."
|
"..hs.hosting.asset.."
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -227,7 +230,7 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.partner..",
|
"..hs.office.partner..",
|
||||||
"..hs.office.debitor..",
|
"..hs.office.debitor..",
|
||||||
"..hs.office.membership..",
|
"..hs.office.membership..",
|
||||||
"..hs.office.migration..")
|
"..hs.migration..")
|
||||||
.orShould().haveNameNotMatching(".*Test$");
|
.orShould().haveNameNotMatching(".*Test$");
|
||||||
|
|
||||||
|
|
||||||
@ -239,7 +242,7 @@ public class ArchitectureTest {
|
|||||||
.resideInAnyPackage(
|
.resideInAnyPackage(
|
||||||
"..hs.office.relation..",
|
"..hs.office.relation..",
|
||||||
"..hs.office.partner..",
|
"..hs.office.partner..",
|
||||||
"..hs.office.migration..")
|
"..hs.migration..")
|
||||||
.orShould().haveNameNotMatching(".*Test$");
|
.orShould().haveNameNotMatching(".*Test$");
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@ -251,7 +254,7 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.partner..",
|
"..hs.office.partner..",
|
||||||
"..hs.office.debitor..",
|
"..hs.office.debitor..",
|
||||||
"..hs.office.membership..",
|
"..hs.office.membership..",
|
||||||
"..hs.office.migration..")
|
"..hs.migration..")
|
||||||
.orShould().haveNameNotMatching(".*Test$");
|
.orShould().haveNameNotMatching(".*Test$");
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@ -263,7 +266,7 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.membership..",
|
"..hs.office.membership..",
|
||||||
"..hs.office.coopassets..",
|
"..hs.office.coopassets..",
|
||||||
"..hs.office.coopshares..",
|
"..hs.office.coopshares..",
|
||||||
"..hs.office.migration..");
|
"..hs.migration..");
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ -272,7 +275,7 @@ public class ArchitectureTest {
|
|||||||
.should().onlyBeAccessed().byClassesThat()
|
.should().onlyBeAccessed().byClassesThat()
|
||||||
.resideInAnyPackage(
|
.resideInAnyPackage(
|
||||||
"..hs.office.coopassets..",
|
"..hs.office.coopassets..",
|
||||||
"..hs.office.migration..");
|
"..hs.migration..");
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ -281,14 +284,14 @@ public class ArchitectureTest {
|
|||||||
.should().onlyBeAccessed().byClassesThat()
|
.should().onlyBeAccessed().byClassesThat()
|
||||||
.resideInAnyPackage(
|
.resideInAnyPackage(
|
||||||
"..hs.office.coopshares..",
|
"..hs.office.coopshares..",
|
||||||
"..hs.office.migration..");
|
"..hs.migration..");
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static final ArchRule hsOfficeMigrationPackageRule = classes()
|
public static final ArchRule hsOfficeMigrationPackageRule = classes()
|
||||||
.that().resideInAPackage("..hs.office.migration..")
|
.that().resideInAPackage("..hs.migration..")
|
||||||
.should().onlyBeAccessed().byClassesThat()
|
.should().onlyBeAccessed().byClassesThat()
|
||||||
.resideInAnyPackage("..hs.office.migration..");
|
.resideInAnyPackage("..hs.migration..");
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@ -101,7 +101,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"resources": {
|
"resources": {
|
||||||
"RAM": 8,
|
"RAM": 8,
|
||||||
"SSD": 500,
|
"SSD": 500,
|
||||||
"CPUs": 2,
|
"CPU": 2,
|
||||||
"Traffic": 500
|
"Traffic": 500
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -114,7 +114,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"HDD": 10000,
|
"HDD": 10000,
|
||||||
"RAM": 32,
|
"RAM": 32,
|
||||||
"SSD": 4000,
|
"SSD": 4000,
|
||||||
"CPUs": 10,
|
"CPU": 10,
|
||||||
"Traffic": 2000
|
"Traffic": 2000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_SERVER",
|
||||||
"caption": "some new booking",
|
"caption": "some new booking",
|
||||||
"validTo": "{validTo}",
|
"validTo": "{validTo}",
|
||||||
"resources": { "CPUs": 12, "RAM": 4, "SSD": 100, "Traffic": 250 }
|
"resources": { "CPU": 12, "RAM": 4, "SSD": 100, "Traffic": 250 }
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.replace("{projectUuid}", givenProject.getUuid().toString())
|
.replace("{projectUuid}", givenProject.getUuid().toString())
|
||||||
@ -166,7 +166,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"caption": "some new booking",
|
"caption": "some new booking",
|
||||||
"validFrom": "{today}",
|
"validFrom": "{today}",
|
||||||
"validTo": "{todayPlus1Month}",
|
"validTo": "{todayPlus1Month}",
|
||||||
"resources": { "CPUs": 12, "SSD": 100, "Traffic": 250 }
|
"resources": { "CPU": 12, "SSD": 100, "Traffic": 250 }
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.replace("{today}", LocalDate.now().toString())
|
.replace("{today}", LocalDate.now().toString())
|
||||||
@ -267,7 +267,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"resources": {
|
"resources": {
|
||||||
"RAM": 8,
|
"RAM": 8,
|
||||||
"SSD": 500,
|
"SSD": 500,
|
||||||
"CPUs": 2,
|
"CPU": 2,
|
||||||
"Traffic": 500
|
"Traffic": 500
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ class HsBookingItemControllerRestTest {
|
|||||||
"caption": "some new booking",
|
"caption": "some new booking",
|
||||||
"validTo": "{validTo}",
|
"validTo": "{validTo}",
|
||||||
"garbage": "should not be accepted",
|
"garbage": "should not be accepted",
|
||||||
"resources": { "CPUs": 12, "RAM": 4, "SSD": 100, "Traffic": 250 }
|
"resources": { "CPU": 12, "RAM": 4, "SSD": 100, "Traffic": 250 }
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.replace("{projectUuid}", givenProjectUuid.toString())
|
.replace("{projectUuid}", givenProjectUuid.toString())
|
||||||
@ -108,7 +108,7 @@ class HsBookingItemControllerRestTest {
|
|||||||
"caption": "some new booking",
|
"caption": "some new booking",
|
||||||
"validFrom": "{today}",
|
"validFrom": "{today}",
|
||||||
"validTo": "{todayPlus1Month}",
|
"validTo": "{todayPlus1Month}",
|
||||||
"resources": { "CPUs": 12, "SSD": 100, "Traffic": 250 }
|
"resources": { "CPU": 12, "SSD": 100, "Traffic": 250 }
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.replace("{today}", LocalDate.now().toString())
|
.replace("{today}", LocalDate.now().toString())
|
||||||
@ -141,7 +141,7 @@ class HsBookingItemControllerRestTest {
|
|||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_SERVER",
|
||||||
"caption": "some new booking",
|
"caption": "some new booking",
|
||||||
"validFrom": "{validFrom}",
|
"validFrom": "{validFrom}",
|
||||||
"resources": { "CPUs": 12, "RAM": 4, "SSD": 100, "Traffic": 250 }
|
"resources": { "CPU": 12, "RAM": 4, "SSD": 100, "Traffic": 250 }
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.replace("{projectUuid}", givenProjectUuid.toString())
|
.replace("{projectUuid}", givenProjectUuid.toString())
|
||||||
@ -159,7 +159,7 @@ class HsBookingItemControllerRestTest {
|
|||||||
"caption": "some new booking",
|
"caption": "some new booking",
|
||||||
"validFrom": "{today}",
|
"validFrom": "{today}",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": { "CPUs": 12, "SSD": 100, "Traffic": 250 }
|
"resources": { "CPU": 12, "SSD": 100, "Traffic": 250 }
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.replace("{today}", LocalDate.now().toString())
|
.replace("{today}", LocalDate.now().toString())
|
||||||
|
@ -25,7 +25,7 @@ class HsBookingItemEntityUnitTest {
|
|||||||
.type(HsBookingItemType.CLOUD_SERVER)
|
.type(HsBookingItemType.CLOUD_SERVER)
|
||||||
.caption("some caption")
|
.caption("some caption")
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("SSD-storage", 512),
|
entry("SSD-storage", 512),
|
||||||
entry("HDD-storage", 2048)))
|
entry("HDD-storage", 2048)))
|
||||||
.validity(toPostgresDateRange(GIVEN_VALID_FROM, GIVEN_VALID_TO))
|
.validity(toPostgresDateRange(GIVEN_VALID_FROM, GIVEN_VALID_TO))
|
||||||
@ -53,7 +53,7 @@ class HsBookingItemEntityUnitTest {
|
|||||||
void toStringContainsAllPropertiesAndResourcesSortedByKey() {
|
void toStringContainsAllPropertiesAndResourcesSortedByKey() {
|
||||||
final var result = givenBookingItem.toString();
|
final var result = givenBookingItem.toString();
|
||||||
|
|
||||||
assertThat(result).isEqualToIgnoringWhitespace("HsBookingItemEntity(D-1234500:test project, CLOUD_SERVER, [2020-01-01,2031-01-01), some caption, { \"CPUs\": 2, \"HDD-storage\": 2048, \"SSD-storage\": 512 })");
|
assertThat(result).isEqualToIgnoringWhitespace("HsBookingItemEntity(D-1234500:test project, CLOUD_SERVER, [2020-01-01,2031-01-01), some caption, { \"CPU\": 2, \"HDD-storage\": 2048, \"SSD-storage\": 512 })");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -171,8 +171,8 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
allTheseBookingItemsAreReturned(
|
allTheseBookingItemsAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_WEBSPACE, [2022-10-01,), separate ManagedWebspace, { Daemons: 0, Multi: 1, SSD: 100, Traffic: 50 } )",
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_WEBSPACE, [2022-10-01,), separate ManagedWebspace, { Daemons: 0, Multi: 1, SSD: 100, Traffic: 50 } )",
|
||||||
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SSD: 500, Traffic: 500 } )",
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPU: 2, RAM: 8, SSD: 500, Traffic: 500 } )",
|
||||||
"HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 } )");
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPU: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 } )");
|
||||||
assertThat(result.stream().filter(bi -> bi.getRelatedHostingAsset()!=null).findAny())
|
assertThat(result.stream().filter(bi -> bi.getRelatedHostingAsset()!=null).findAny())
|
||||||
.as("at least one relatedProject expected, but none found => fetching relatedProject does not work")
|
.as("at least one relatedProject expected, but none found => fetching relatedProject does not work")
|
||||||
.isNotEmpty();
|
.isNotEmpty();
|
||||||
@ -194,8 +194,8 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
exactlyTheseBookingItemsAreReturned(
|
exactlyTheseBookingItemsAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_WEBSPACE, [2022-10-01,), separate ManagedWebspace, { Daemons: 0, Multi: 1, SSD: 100, Traffic: 50 } )",
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_WEBSPACE, [2022-10-01,), separate ManagedWebspace, { Daemons: 0, Multi: 1, SSD: 100, Traffic: 50 } )",
|
||||||
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SSD: 500, Traffic: 500 } )",
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPU: 2, RAM: 8, SSD: 500, Traffic: 500 } )",
|
||||||
"HsBookingItemEntity(D-1000111:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 } )");
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPU: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 } )");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var foundBookingItem = em.find(HsBookingItemEntity.class, givenBookingItemUuid);
|
final var foundBookingItem = em.find(HsBookingItemEntity.class, givenBookingItemUuid);
|
||||||
foundBookingItem.getResources().put("CPUs", 2);
|
foundBookingItem.getResources().put("CPU", 2);
|
||||||
foundBookingItem.getResources().remove("SSD-storage");
|
foundBookingItem.getResources().remove("SSD-storage");
|
||||||
foundBookingItem.getResources().put("HSD-storage", 2048);
|
foundBookingItem.getResources().put("HSD-storage", 2048);
|
||||||
foundBookingItem.setValidity(Range.closedOpen(
|
foundBookingItem.setValidity(Range.closedOpen(
|
||||||
@ -336,7 +336,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
.validity(Range.closedOpen(
|
.validity(Range.closedOpen(
|
||||||
LocalDate.parse("2020-01-01"), LocalDate.parse("2023-01-01")))
|
LocalDate.parse("2020-01-01"), LocalDate.parse("2023-01-01")))
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 1),
|
entry("CPU", 1),
|
||||||
entry("SSD-storage", 256)))
|
entry("SSD-storage", 256)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ public class TestHsBookingItem {
|
|||||||
.type(HsBookingItemType.CLOUD_SERVER)
|
.type(HsBookingItemType.CLOUD_SERVER)
|
||||||
.caption("test cloud server booking item")
|
.caption("test cloud server booking item")
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 4),
|
entry("RAM", 4),
|
||||||
entry("SSD", 50),
|
entry("SSD", 50),
|
||||||
entry("Traffic", 250)
|
entry("Traffic", 250)
|
||||||
@ -30,7 +30,7 @@ public class TestHsBookingItem {
|
|||||||
.type(HsBookingItemType.MANAGED_SERVER)
|
.type(HsBookingItemType.MANAGED_SERVER)
|
||||||
.caption("test project booking item")
|
.caption("test project booking item")
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 4),
|
entry("RAM", 4),
|
||||||
entry("SSD", 50),
|
entry("SSD", 50),
|
||||||
entry("Traffic", 250)
|
entry("Traffic", 250)
|
||||||
|
@ -38,7 +38,7 @@ class HsBookingItemEntityValidatorUnitTest {
|
|||||||
// then
|
// then
|
||||||
assertThat(result).isInstanceOf(ValidationException.class)
|
assertThat(result).isInstanceOf(ValidationException.class)
|
||||||
.hasMessageContaining(
|
.hasMessageContaining(
|
||||||
"'D-12345:test project:Test-Server.resources.CPUs' is required but missing",
|
"'D-12345:test project:Test-Server.resources.CPU' is required but missing",
|
||||||
"'D-12345:test project:Test-Server.resources.RAM' is required but missing",
|
"'D-12345:test project:Test-Server.resources.RAM' is required but missing",
|
||||||
"'D-12345:test project:Test-Server.resources.SSD' is required but missing",
|
"'D-12345:test project:Test-Server.resources.SSD' is required but missing",
|
||||||
"'D-12345:test project:Test-Server.resources.Traffic' is required but missing");
|
"'D-12345:test project:Test-Server.resources.Traffic' is required but missing");
|
||||||
|
@ -33,7 +33,7 @@ class HsCloudServerBookingItemValidatorUnitTest {
|
|||||||
.project(project)
|
.project(project)
|
||||||
.caption("Test-Server")
|
.caption("Test-Server")
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 25),
|
entry("RAM", 25),
|
||||||
entry("SSD", 25),
|
entry("SSD", 25),
|
||||||
entry("Traffic", 250),
|
entry("Traffic", 250),
|
||||||
@ -56,11 +56,12 @@ class HsCloudServerBookingItemValidatorUnitTest {
|
|||||||
// then
|
// then
|
||||||
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
|
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
|
||||||
"{type=boolean, propertyName=active, defaultValue=true}",
|
"{type=boolean, propertyName=active, defaultValue=true}",
|
||||||
"{type=integer, propertyName=CPUs, min=1, max=32, required=true}",
|
"{type=integer, propertyName=CPU, min=1, max=32, required=true}",
|
||||||
"{type=integer, propertyName=RAM, unit=GB, min=1, max=128, required=true}",
|
"{type=integer, propertyName=RAM, unit=GB, min=1, max=8192, required=true}",
|
||||||
"{type=integer, propertyName=SSD, unit=GB, min=0, max=1000, step=25, required=true}",
|
"{type=integer, propertyName=SSD, unit=GB, min=25, max=1000, step=25, requiresAtLeastOneOf=[SDD, HDD]}",
|
||||||
"{type=integer, propertyName=HDD, unit=GB, min=0, max=4000, step=250, defaultValue=0}",
|
"{type=integer, propertyName=HDD, unit=GB, min=250, max=4000, step=250, requiresAtLeastOneOf=[SSD, HDD]}",
|
||||||
"{type=integer, propertyName=Traffic, unit=GB, min=250, max=10000, step=250, required=true}",
|
"{type=integer, propertyName=Traffic, unit=GB, min=250, max=10000, step=250, requiresAtMaxOneOf=[Bandwidth, Traffic]}",
|
||||||
|
"{type=integer, propertyName=Bandwidth, unit=GB, min=250, max=10000, step=250, requiresAtMaxOneOf=[Bandwidth, Traffic]}",
|
||||||
"{type=enumeration, propertyName=SLA-Infrastructure, values=[BASIC, EXT8H, EXT4H, EXT2H]}");
|
"{type=enumeration, propertyName=SLA-Infrastructure, values=[BASIC, EXT8H, EXT4H, EXT2H]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ class HsCloudServerBookingItemValidatorUnitTest {
|
|||||||
.type(CLOUD_SERVER)
|
.type(CLOUD_SERVER)
|
||||||
.caption("Test Cloud-Server")
|
.caption("Test Cloud-Server")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 10),
|
entry("RAM", 10),
|
||||||
entry("SSD", 50),
|
entry("SSD", 50),
|
||||||
entry("Traffic", 2500)
|
entry("Traffic", 2500)
|
||||||
@ -81,7 +82,7 @@ class HsCloudServerBookingItemValidatorUnitTest {
|
|||||||
.type(MANAGED_SERVER)
|
.type(MANAGED_SERVER)
|
||||||
.caption("Test Managed-Server")
|
.caption("Test Managed-Server")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 3),
|
entry("CPU", 3),
|
||||||
entry("RAM", 20),
|
entry("RAM", 20),
|
||||||
entry("SSD", 100),
|
entry("SSD", 100),
|
||||||
entry("Traffic", 3000)
|
entry("Traffic", 3000)
|
||||||
@ -92,7 +93,7 @@ class HsCloudServerBookingItemValidatorUnitTest {
|
|||||||
.project(project)
|
.project(project)
|
||||||
.caption("Test Cloud")
|
.caption("Test Cloud")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 4),
|
entry("CPU", 4),
|
||||||
entry("RAM", 20),
|
entry("RAM", 20),
|
||||||
entry("SSD", 100),
|
entry("SSD", 100),
|
||||||
entry("Traffic", 5000)
|
entry("Traffic", 5000)
|
||||||
@ -110,7 +111,7 @@ class HsCloudServerBookingItemValidatorUnitTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).containsExactlyInAnyOrder(
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
"'D-12345:Test-Project:Test Cloud.resources.CPUs' maximum total is 4, but actual total CPUs is 5",
|
"'D-12345:Test-Project:Test Cloud.resources.CPU' maximum total is 4, but actual total CPU is 5",
|
||||||
"'D-12345:Test-Project:Test Cloud.resources.RAM' maximum total is 20 GB, but actual total RAM is 30 GB",
|
"'D-12345:Test-Project:Test Cloud.resources.RAM' maximum total is 20 GB, but actual total RAM is 30 GB",
|
||||||
"'D-12345:Test-Project:Test Cloud.resources.SSD' maximum total is 100 GB, but actual total SSD is 150 GB",
|
"'D-12345:Test-Project:Test Cloud.resources.SSD' maximum total is 100 GB, but actual total SSD is 150 GB",
|
||||||
"'D-12345:Test-Project:Test Cloud.resources.Traffic' maximum total is 5000 GB, but actual total Traffic is 5500 GB"
|
"'D-12345:Test-Project:Test Cloud.resources.Traffic' maximum total is 5000 GB, but actual total Traffic is 5500 GB"
|
||||||
|
@ -40,7 +40,7 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
.type(MANAGED_SERVER)
|
.type(MANAGED_SERVER)
|
||||||
.project(project)
|
.project(project)
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 25),
|
entry("RAM", 25),
|
||||||
entry("SSD", 25),
|
entry("SSD", 25),
|
||||||
entry("Traffic", 250),
|
entry("Traffic", 250),
|
||||||
@ -63,11 +63,12 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
|
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
|
||||||
"{type=integer, propertyName=CPUs, min=1, max=32, required=true}",
|
"{type=integer, propertyName=CPU, min=1, max=32, required=true}",
|
||||||
"{type=integer, propertyName=RAM, unit=GB, min=1, max=128, required=true}",
|
"{type=integer, propertyName=RAM, unit=GB, min=1, max=128, required=true}",
|
||||||
"{type=integer, propertyName=SSD, unit=GB, min=25, max=1000, step=25, required=true, isTotalsValidator=true, thresholdPercentage=200}",
|
"{type=integer, propertyName=SSD, unit=GB, min=25, max=2000, step=25, requiresAtLeastOneOf=[SSD, HDD], isTotalsValidator=true, thresholdPercentage=200}",
|
||||||
"{type=integer, propertyName=HDD, unit=GB, min=0, max=4000, step=250, defaultValue=0, isTotalsValidator=true, thresholdPercentage=200}",
|
"{type=integer, propertyName=HDD, unit=GB, min=250, max=10000, step=250, requiresAtLeastOneOf=[SSD, HDD], isTotalsValidator=true, thresholdPercentage=200}",
|
||||||
"{type=integer, propertyName=Traffic, unit=GB, min=250, max=10000, step=250, required=true, isTotalsValidator=true, thresholdPercentage=200}",
|
"{type=integer, propertyName=Traffic, unit=GB, min=250, max=64000, step=250, requiresAtMaxOneOf=[Bandwidth, Traffic], isTotalsValidator=true, thresholdPercentage=200}",
|
||||||
|
"{type=integer, propertyName=Bandwidth, unit=GB, min=250, max=64000, step=250, requiresAtMaxOneOf=[Bandwidth, Traffic], isTotalsValidator=true, thresholdPercentage=200}",
|
||||||
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT8H, EXT4H, EXT2H], defaultValue=BASIC}",
|
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT8H, EXT4H, EXT2H], defaultValue=BASIC}",
|
||||||
"{type=boolean, propertyName=SLA-EMail}", // TODO.impl: falseIf-validation is missing in output
|
"{type=boolean, propertyName=SLA-EMail}", // TODO.impl: falseIf-validation is missing in output
|
||||||
"{type=boolean, propertyName=SLA-Maria}",
|
"{type=boolean, propertyName=SLA-Maria}",
|
||||||
@ -82,7 +83,7 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
final var subCloudServerBookingItemEntity = HsBookingItemEntity.builder()
|
final var subCloudServerBookingItemEntity = HsBookingItemEntity.builder()
|
||||||
.type(CLOUD_SERVER)
|
.type(CLOUD_SERVER)
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 10),
|
entry("RAM", 10),
|
||||||
entry("SSD", 50),
|
entry("SSD", 50),
|
||||||
entry("Traffic", 2500)
|
entry("Traffic", 2500)
|
||||||
@ -91,7 +92,7 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
final HsBookingItemEntity subManagedServerBookingItemEntity = HsBookingItemEntity.builder()
|
final HsBookingItemEntity subManagedServerBookingItemEntity = HsBookingItemEntity.builder()
|
||||||
.type(MANAGED_SERVER)
|
.type(MANAGED_SERVER)
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 3),
|
entry("CPU", 3),
|
||||||
entry("RAM", 20),
|
entry("RAM", 20),
|
||||||
entry("SSD", 100),
|
entry("SSD", 100),
|
||||||
entry("Traffic", 3000)
|
entry("Traffic", 3000)
|
||||||
@ -101,7 +102,7 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
.type(PRIVATE_CLOUD)
|
.type(PRIVATE_CLOUD)
|
||||||
.project(project)
|
.project(project)
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 4),
|
entry("CPU", 4),
|
||||||
entry("RAM", 20),
|
entry("RAM", 20),
|
||||||
entry("SSD", 100),
|
entry("SSD", 100),
|
||||||
entry("Traffic", 5000)
|
entry("Traffic", 5000)
|
||||||
@ -120,7 +121,7 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).containsExactlyInAnyOrder(
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
"'D-12345:Test-Project:null.resources.CPUs' maximum total is 4, but actual total CPUs is 5",
|
"'D-12345:Test-Project:null.resources.CPU' maximum total is 4, but actual total CPU is 5",
|
||||||
"'D-12345:Test-Project:null.resources.RAM' maximum total is 20 GB, but actual total RAM is 30 GB",
|
"'D-12345:Test-Project:null.resources.RAM' maximum total is 20 GB, but actual total RAM is 30 GB",
|
||||||
"'D-12345:Test-Project:null.resources.SSD' maximum total is 100 GB, but actual total SSD is 150 GB",
|
"'D-12345:Test-Project:null.resources.SSD' maximum total is 100 GB, but actual total SSD is 150 GB",
|
||||||
"'D-12345:Test-Project:null.resources.Traffic' maximum total is 5000 GB, but actual total Traffic is 5500 GB"
|
"'D-12345:Test-Project:null.resources.Traffic' maximum total is 5000 GB, but actual total Traffic is 5500 GB"
|
||||||
|
@ -29,7 +29,7 @@ class HsManagedWebspaceBookingItemValidatorUnitTest {
|
|||||||
.project(project)
|
.project(project)
|
||||||
.caption("Test Managed-Webspace")
|
.caption("Test Managed-Webspace")
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 25),
|
entry("RAM", 25),
|
||||||
entry("Traffic", 250),
|
entry("Traffic", 250),
|
||||||
entry("SLA-EMail", true)
|
entry("SLA-EMail", true)
|
||||||
@ -41,7 +41,7 @@ class HsManagedWebspaceBookingItemValidatorUnitTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).containsExactlyInAnyOrder(
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
"'D-12345:Test-Project:Test Managed-Webspace.resources.CPUs' is not expected but is set to '2'",
|
"'D-12345:Test-Project:Test Managed-Webspace.resources.CPU' is not expected but is set to '2'",
|
||||||
"'D-12345:Test-Project:Test Managed-Webspace.resources.RAM' is not expected but is set to '25'",
|
"'D-12345:Test-Project:Test Managed-Webspace.resources.RAM' is not expected but is set to '25'",
|
||||||
"'D-12345:Test-Project:Test Managed-Webspace.resources.SSD' is required but missing",
|
"'D-12345:Test-Project:Test Managed-Webspace.resources.SSD' is required but missing",
|
||||||
"'D-12345:Test-Project:Test Managed-Webspace.resources.SLA-EMail' is not expected but is set to 'true'"
|
"'D-12345:Test-Project:Test Managed-Webspace.resources.SLA-EMail' is not expected but is set to 'true'"
|
||||||
@ -55,11 +55,12 @@ class HsManagedWebspaceBookingItemValidatorUnitTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
|
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
|
||||||
"{type=integer, propertyName=SSD, unit=GB, min=1, max=100, step=1, required=true}",
|
"{type=integer, propertyName=SSD, unit=GB, min=1, max=2000, step=1, required=true}",
|
||||||
"{type=integer, propertyName=HDD, unit=GB, min=0, max=250, step=10}",
|
"{type=integer, propertyName=HDD, unit=GB, min=0, max=10000, step=10}",
|
||||||
"{type=integer, propertyName=Traffic, unit=GB, min=10, max=1000, step=10, required=true}",
|
"{type=integer, propertyName=Traffic, unit=GB, min=10, max=64000, step=10, requiresAtMaxOneOf=[Bandwidth, Traffic]}",
|
||||||
|
"{type=integer, propertyName=Bandwidth, unit=GB, min=10, max=1000, step=10, requiresAtMaxOneOf=[Bandwidth, Traffic]}",
|
||||||
"{type=integer, propertyName=Multi, min=1, max=100, step=1, defaultValue=1}",
|
"{type=integer, propertyName=Multi, min=1, max=100, step=1, defaultValue=1}",
|
||||||
"{type=integer, propertyName=Daemons, min=0, max=10, defaultValue=0}",
|
"{type=integer, propertyName=Daemons, min=0, max=16, defaultValue=0}",
|
||||||
"{type=boolean, propertyName=Online Office Server}",
|
"{type=boolean, propertyName=Online Office Server}",
|
||||||
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT24H], defaultValue=BASIC}");
|
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT24H], defaultValue=BASIC}");
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import static java.util.Map.ofEntries;
|
|||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.PRIVATE_CLOUD;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.PRIVATE_CLOUD;
|
||||||
|
import static net.hostsharing.hsadminng.hs.booking.project.TestHsBookingProject.TEST_PROJECT;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
class HsPrivateCloudBookingItemValidatorUnitTest {
|
class HsPrivateCloudBookingItemValidatorUnitTest {
|
||||||
@ -28,9 +29,10 @@ class HsPrivateCloudBookingItemValidatorUnitTest {
|
|||||||
// given
|
// given
|
||||||
final var privateCloudBookingItemEntity = HsBookingItemEntity.builder()
|
final var privateCloudBookingItemEntity = HsBookingItemEntity.builder()
|
||||||
.type(PRIVATE_CLOUD)
|
.type(PRIVATE_CLOUD)
|
||||||
|
.project(TEST_PROJECT)
|
||||||
.caption("myPC")
|
.caption("myPC")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 4),
|
entry("CPU", 4),
|
||||||
entry("RAM", 20),
|
entry("RAM", 20),
|
||||||
entry("SSD", 100),
|
entry("SSD", 100),
|
||||||
entry("Traffic", 5000),
|
entry("Traffic", 5000),
|
||||||
@ -42,7 +44,7 @@ class HsPrivateCloudBookingItemValidatorUnitTest {
|
|||||||
.type(MANAGED_SERVER)
|
.type(MANAGED_SERVER)
|
||||||
.caption("myMS-1")
|
.caption("myMS-1")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 10),
|
entry("RAM", 10),
|
||||||
entry("SSD", 50),
|
entry("SSD", 50),
|
||||||
entry("Traffic", 2500),
|
entry("Traffic", 2500),
|
||||||
@ -54,7 +56,7 @@ class HsPrivateCloudBookingItemValidatorUnitTest {
|
|||||||
.type(CLOUD_SERVER)
|
.type(CLOUD_SERVER)
|
||||||
.caption("myMS-2")
|
.caption("myMS-2")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 10),
|
entry("RAM", 10),
|
||||||
entry("SSD", 50),
|
entry("SSD", 50),
|
||||||
entry("Traffic", 2500),
|
entry("Traffic", 2500),
|
||||||
@ -80,7 +82,7 @@ class HsPrivateCloudBookingItemValidatorUnitTest {
|
|||||||
.type(PRIVATE_CLOUD)
|
.type(PRIVATE_CLOUD)
|
||||||
.caption("myPC")
|
.caption("myPC")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 4),
|
entry("CPU", 4),
|
||||||
entry("RAM", 20),
|
entry("RAM", 20),
|
||||||
entry("SSD", 100),
|
entry("SSD", 100),
|
||||||
entry("Traffic", 5000),
|
entry("Traffic", 5000),
|
||||||
@ -92,7 +94,7 @@ class HsPrivateCloudBookingItemValidatorUnitTest {
|
|||||||
.type(MANAGED_SERVER)
|
.type(MANAGED_SERVER)
|
||||||
.caption("myMS-1")
|
.caption("myMS-1")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 3),
|
entry("CPU", 3),
|
||||||
entry("RAM", 20),
|
entry("RAM", 20),
|
||||||
entry("SSD", 100),
|
entry("SSD", 100),
|
||||||
entry("Traffic", 3000),
|
entry("Traffic", 3000),
|
||||||
@ -104,7 +106,7 @@ class HsPrivateCloudBookingItemValidatorUnitTest {
|
|||||||
.type(CLOUD_SERVER)
|
.type(CLOUD_SERVER)
|
||||||
.caption("myMS-2")
|
.caption("myMS-2")
|
||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 10),
|
entry("RAM", 10),
|
||||||
entry("SSD", 50),
|
entry("SSD", 50),
|
||||||
entry("Traffic", 2500),
|
entry("Traffic", 2500),
|
||||||
@ -124,7 +126,7 @@ class HsPrivateCloudBookingItemValidatorUnitTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).containsExactlyInAnyOrder(
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
"'D-12345:Test-Project:myPC.resources.CPUs' maximum total is 4, but actual total CPUs is 5",
|
"'D-12345:Test-Project:myPC.resources.CPU' maximum total is 4, but actual total CPU is 5",
|
||||||
"'D-12345:Test-Project:myPC.resources.RAM' maximum total is 20 GB, but actual total RAM is 30 GB",
|
"'D-12345:Test-Project:myPC.resources.RAM' maximum total is 20 GB, but actual total RAM is 30 GB",
|
||||||
"'D-12345:Test-Project:myPC.resources.SSD' maximum total is 100 GB, but actual total SSD is 150 GB",
|
"'D-12345:Test-Project:myPC.resources.SSD' maximum total is 100 GB, but actual total SSD is 150 GB",
|
||||||
"'D-12345:Test-Project:myPC.resources.Traffic' maximum total is 5000 GB, but actual total Traffic is 5500 GB",
|
"'D-12345:Test-Project:myPC.resources.Traffic' maximum total is 5000 GB, but actual total Traffic is 5500 GB",
|
||||||
|
@ -702,7 +702,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var project = projectRepo.findByCaption(projectCaption).getFirst();
|
final var project = projectRepo.findByCaption(projectCaption).getFirst();
|
||||||
final var resources = switch (bookingItemType) {
|
final var resources = switch (bookingItemType) {
|
||||||
case MANAGED_SERVER -> Map.<String, Object>ofEntries(entry("CPUs", 1),
|
case MANAGED_SERVER -> Map.<String, Object>ofEntries(entry("CPU", 1),
|
||||||
entry("RAM", 20),
|
entry("RAM", 20),
|
||||||
entry("SSD", 25),
|
entry("SSD", 25),
|
||||||
entry("Traffic", 250));
|
entry("Traffic", 250));
|
||||||
|
@ -16,7 +16,7 @@ class HsHostingAssetEntityUnitTest {
|
|||||||
.identifier("vm1234")
|
.identifier("vm1234")
|
||||||
.caption("some managed asset")
|
.caption("some managed asset")
|
||||||
.config(Map.ofEntries(
|
.config(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("SSD-storage", 512),
|
entry("SSD-storage", 512),
|
||||||
entry("HDD-storage", 2048)))
|
entry("HDD-storage", 2048)))
|
||||||
.build();
|
.build();
|
||||||
@ -27,7 +27,7 @@ class HsHostingAssetEntityUnitTest {
|
|||||||
.identifier("xyz00")
|
.identifier("xyz00")
|
||||||
.caption("some managed webspace")
|
.caption("some managed webspace")
|
||||||
.config(Map.ofEntries(
|
.config(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("SSD-storage", 512),
|
entry("SSD-storage", 512),
|
||||||
entry("HDD-storage", 2048)))
|
entry("HDD-storage", 2048)))
|
||||||
.build();
|
.build();
|
||||||
@ -58,7 +58,7 @@ class HsHostingAssetEntityUnitTest {
|
|||||||
void toStringContainsAllPropertiesAndResourcesSortedByKey() {
|
void toStringContainsAllPropertiesAndResourcesSortedByKey() {
|
||||||
|
|
||||||
assertThat(givenWebspace.toString()).isEqualToIgnoringWhitespace(
|
assertThat(givenWebspace.toString()).isEqualToIgnoringWhitespace(
|
||||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, xyz00, some managed webspace, MANAGED_SERVER:vm1234, D-1234500:test project:test cloud server booking item, { \"CPUs\": 2, \"HDD-storage\": 2048, \"SSD-storage\": 512 })");
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, xyz00, some managed webspace, MANAGED_SERVER:vm1234, D-1234500:test project:test cloud server booking item, { \"CPU\": 2, \"HDD-storage\": 2048, \"SSD-storage\": 512 })");
|
||||||
|
|
||||||
assertThat(givenUnixUser.toString()).isEqualToIgnoringWhitespace(
|
assertThat(givenUnixUser.toString()).isEqualToIgnoringWhitespace(
|
||||||
"HsHostingAssetEntity(UNIX_USER, xyz00-web, some unix-user, MANAGED_WEBSPACE:xyz00, { \"HDD-hard-quota\": 512, \"HDD-soft-quota\": 256, \"SSD-hard-quota\": 256, \"SSD-soft-quota\": 128 })");
|
"HsHostingAssetEntity(UNIX_USER, xyz00-web, some unix-user, MANAGED_WEBSPACE:xyz00, { \"HDD-hard-quota\": 512, \"HDD-soft-quota\": 256, \"SSD-hard-quota\": 256, \"SSD-soft-quota\": 128 })");
|
||||||
|
@ -263,7 +263,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var foundAsset = em.find(HsHostingAssetEntity.class, givenAssetUuid);
|
final var foundAsset = em.find(HsHostingAssetEntity.class, givenAssetUuid);
|
||||||
foundAsset.getConfig().put("CPUs", 2);
|
foundAsset.getConfig().put("CPU", 2);
|
||||||
foundAsset.getConfig().remove("SSD-storage");
|
foundAsset.getConfig().remove("SSD-storage");
|
||||||
foundAsset.getConfig().put("HSD-storage", 2048);
|
foundAsset.getConfig().put("HSD-storage", 2048);
|
||||||
return toCleanup(assetRepo.save(foundAsset));
|
return toCleanup(assetRepo.save(foundAsset));
|
||||||
@ -404,7 +404,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
.identifier(identifier)
|
.identifier(identifier)
|
||||||
.caption("some temp cloud asset")
|
.caption("some temp cloud asset")
|
||||||
.config(Map.ofEntries(
|
.config(Map.ofEntries(
|
||||||
entry("CPUs", 1),
|
entry("CPU", 1),
|
||||||
entry("SSD-storage", 256)))
|
entry("SSD-storage", 256)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class HsHostingAssetTypeUnitTest {
|
|||||||
## HostingAsset Type Structure
|
## HostingAsset Type Structure
|
||||||
|
|
||||||
|
|
||||||
### Webspace+Server
|
### Server+Webspace
|
||||||
|
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
@ -35,6 +35,12 @@ class HsHostingAssetTypeUnitTest {
|
|||||||
entity HA_IPV6_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_CLOUD_SERVER *--> BI_PRIVATE_CLOUD
|
||||||
@ -43,10 +49,16 @@ class HsHostingAssetTypeUnitTest {
|
|||||||
|
|
||||||
HA_CLOUD_SERVER *==> BI_CLOUD_SERVER
|
HA_CLOUD_SERVER *==> BI_CLOUD_SERVER
|
||||||
HA_MANAGED_SERVER *==> BI_MANAGED_SERVER
|
HA_MANAGED_SERVER *==> BI_MANAGED_SERVER
|
||||||
|
HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
|
||||||
|
HA_MANAGED_WEBSPACE o..> HA_MANAGED_SERVER
|
||||||
|
HA_UNIX_USER *==> HA_MANAGED_WEBSPACE
|
||||||
|
HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE
|
||||||
HA_IPV4_NUMBER o..> HA_CLOUD_SERVER
|
HA_IPV4_NUMBER o..> HA_CLOUD_SERVER
|
||||||
HA_IPV4_NUMBER o..> HA_MANAGED_SERVER
|
HA_IPV4_NUMBER o..> HA_MANAGED_SERVER
|
||||||
|
HA_IPV4_NUMBER o..> HA_MANAGED_WEBSPACE
|
||||||
HA_IPV6_NUMBER o..> HA_CLOUD_SERVER
|
HA_IPV6_NUMBER o..> HA_CLOUD_SERVER
|
||||||
HA_IPV6_NUMBER o..> HA_MANAGED_SERVER
|
HA_IPV6_NUMBER o..> HA_MANAGED_SERVER
|
||||||
|
HA_IPV6_NUMBER o..> HA_MANAGED_WEBSPACE
|
||||||
|
|
||||||
package Legend #white {
|
package Legend #white {
|
||||||
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
|
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
|
||||||
|
@ -22,7 +22,7 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest {
|
|||||||
.type(HsBookingItemType.MANAGED_SERVER)
|
.type(HsBookingItemType.MANAGED_SERVER)
|
||||||
.caption("Test Managed-Server")
|
.caption("Test Managed-Server")
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPU", 2),
|
||||||
entry("RAM", 25),
|
entry("RAM", 25),
|
||||||
entry("SSD", 25),
|
entry("SSD", 25),
|
||||||
entry("Traffic", 250),
|
entry("Traffic", 250),
|
||||||
@ -125,6 +125,7 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest {
|
|||||||
.type(MANAGED_WEBSPACE)
|
.type(MANAGED_WEBSPACE)
|
||||||
.bookingItem(HsBookingItemEntity.builder()
|
.bookingItem(HsBookingItemEntity.builder()
|
||||||
.type(HsBookingItemType.MANAGED_WEBSPACE)
|
.type(HsBookingItemType.MANAGED_WEBSPACE)
|
||||||
|
.project(TEST_PROJECT)
|
||||||
.caption("some ManagedWebspace")
|
.caption("some ManagedWebspace")
|
||||||
.resources(Map.ofEntries(entry("SSD", 25), entry("Traffic", 250)))
|
.resources(Map.ofEntries(entry("SSD", 25), entry("Traffic", 250)))
|
||||||
.build())
|
.build())
|
||||||
|
@ -0,0 +1,312 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.migration;
|
||||||
|
|
||||||
|
import com.opencsv.CSVParserBuilder;
|
||||||
|
import com.opencsv.CSVReader;
|
||||||
|
import com.opencsv.CSVReaderBuilder;
|
||||||
|
import net.hostsharing.hsadminng.rbac.context.ContextBasedTest;
|
||||||
|
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
||||||
|
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||||
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
import org.junit.jupiter.api.extension.TestWatcher;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.PersistenceContext;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.lang.Boolean.parseBoolean;
|
||||||
|
import static java.util.Arrays.stream;
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
import static java.util.Optional.ofNullable;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||||
|
|
||||||
|
public class CsvDataImport extends ContextBasedTest {
|
||||||
|
|
||||||
|
public static final String TEST_DATA_MIGRATION_DATA_PATH = "migration";
|
||||||
|
public static final String MIGRATION_DATA_PATH = ofNullable(System.getenv("HSADMINNG_MIGRATION_DATA_PATH"))
|
||||||
|
.orElse(TEST_DATA_MIGRATION_DATA_PATH);
|
||||||
|
|
||||||
|
@Value("${spring.datasource.url}")
|
||||||
|
protected String jdbcUrl;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.username}")
|
||||||
|
protected String postgresAdminUser;
|
||||||
|
|
||||||
|
@Value("${hsadminng.superuser}")
|
||||||
|
protected String rbacSuperuser;
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
EntityManager em;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
TransactionTemplate txTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
JpaAttempt jpaAttempt;
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
HttpServletRequest request;
|
||||||
|
|
||||||
|
private static final List<AssertionError> errors = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<String[]> readAllLines(Reader reader) throws Exception {
|
||||||
|
|
||||||
|
final var parser = new CSVParserBuilder()
|
||||||
|
.withSeparator(';')
|
||||||
|
.withQuoteChar('"')
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final var filteredReader = skippingEmptyAndCommentLines(reader);
|
||||||
|
try (CSVReader csvReader = new CSVReaderBuilder(filteredReader)
|
||||||
|
.withCSVParser(parser)
|
||||||
|
.build()) {
|
||||||
|
return csvReader.readAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Reader skippingEmptyAndCommentLines(Reader reader) throws IOException {
|
||||||
|
try (var bufferedReader = new BufferedReader(reader);
|
||||||
|
StringWriter writer = new StringWriter()) {
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
|
if (!line.isBlank() && !line.startsWith("#")) {
|
||||||
|
writer.write(line);
|
||||||
|
writer.write("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StringReader(writer.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String[] justHeader(final List<String[]> lines) {
|
||||||
|
return stream(lines.getFirst()).map(String::trim).toArray(String[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Reader resourceReader(@NotNull final String resourcePath) {
|
||||||
|
return new InputStreamReader(requireNonNull(getClass().getClassLoader().getResourceAsStream(resourcePath)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String[]> withoutHeader(final List<String[]> records) {
|
||||||
|
return records.subList(1, records.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] trimAll(final String[] record) {
|
||||||
|
for (int i = 0; i < record.length; ++i) {
|
||||||
|
if (record[i] != null) {
|
||||||
|
record[i] = record[i].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends RbacObject> T persist(final Integer id, final T entity) {
|
||||||
|
try {
|
||||||
|
final var asString = entity.toString();
|
||||||
|
if ( asString.contains("'null null, null'") || asString.equals("person()")) {
|
||||||
|
System.err.println("skipping to persist empty record-id " + id + " #" + entity.hashCode() + ": " + entity);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
//System.out.println("persisting #" + entity.hashCode() + ": " + entity);
|
||||||
|
em.persist(entity);
|
||||||
|
// uncomment for debugging purposes
|
||||||
|
// em.flush(); // makes it slow, but produces better error messages
|
||||||
|
// System.out.println("persisted #" + entity.hashCode() + " as " + entity.getUuid());
|
||||||
|
} catch (Exception exc) {
|
||||||
|
System.err.println("failed to persist #" + entity.hashCode() + ": " + entity);
|
||||||
|
System.err.println(exc);
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> String toFormattedString(final Map<Integer, E> map) {
|
||||||
|
if ( map.isEmpty() ) {
|
||||||
|
return "{}";
|
||||||
|
}
|
||||||
|
return "{\n" +
|
||||||
|
map.keySet().stream()
|
||||||
|
.map(id -> " " + id + "=" + map.get(id).toString())
|
||||||
|
.map(e -> e.replaceAll("\n ", " ").replace("\n", ""))
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.joining(",\n")) +
|
||||||
|
"\n}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteTestDataFromHsOfficeTables() {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context(rbacSuperuser);
|
||||||
|
// TODO.perf: could we instead skip creating test-data based on an env var?
|
||||||
|
em.createNativeQuery("delete from hs_hosting_asset where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_booking_item where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_booking_project where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_coopassetstransaction where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_coopassetstransaction_legacy_id where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_coopsharestransaction where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_coopsharestransaction_legacy_id where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_membership where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_sepamandate where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_sepamandate_legacy_id where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_debitor where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_bankaccount where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_partner where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_partner_details where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_relation where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_contact where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from hs_office_person where true").executeUpdate();
|
||||||
|
}).assertSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void resetHsOfficeSequences() {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context(rbacSuperuser);
|
||||||
|
em.createNativeQuery("alter sequence hs_office_contact_legacy_id_seq restart with 1000000000;").executeUpdate();
|
||||||
|
em.createNativeQuery("alter sequence hs_office_coopassetstransaction_legacy_id_seq restart with 1000000000;")
|
||||||
|
.executeUpdate();
|
||||||
|
em.createNativeQuery("alter sequence public.hs_office_coopsharestransaction_legacy_id_seq restart with 1000000000;")
|
||||||
|
.executeUpdate();
|
||||||
|
em.createNativeQuery("alter sequence public.hs_office_partner_legacy_id_seq restart with 1000000000;")
|
||||||
|
.executeUpdate();
|
||||||
|
em.createNativeQuery("alter sequence public.hs_office_sepamandate_legacy_id_seq restart with 1000000000;")
|
||||||
|
.executeUpdate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteFromTestTables() {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context(rbacSuperuser);
|
||||||
|
em.createNativeQuery("delete from test_domain where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from test_package where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from test_customer where true").executeUpdate();
|
||||||
|
}).assertSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteFromRbacTables() {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context(rbacSuperuser);
|
||||||
|
em.createNativeQuery("delete from rbacuser_rv where name not like 'superuser-%'").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from tx_journal where true").executeUpdate();
|
||||||
|
em.createNativeQuery("delete from tx_context where true").executeUpdate();
|
||||||
|
}).assertSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
|
void logError(final Runnable assertion) {
|
||||||
|
try {
|
||||||
|
assertion.run();
|
||||||
|
} catch (final AssertionError exc) {
|
||||||
|
errors.add(exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void logErrors() {
|
||||||
|
assumeThat(errors).isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Columns {
|
||||||
|
|
||||||
|
private final List<String> columnNames;
|
||||||
|
|
||||||
|
public Columns(final String[] header) {
|
||||||
|
columnNames = List.of(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
int indexOf(final String columnName) {
|
||||||
|
int index = columnNames.indexOf(columnName);
|
||||||
|
if (index < 0) {
|
||||||
|
throw new RuntimeException("column name '" + columnName + "' not found in: " + columnNames);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Record {
|
||||||
|
|
||||||
|
private final Columns columns;
|
||||||
|
private final String[] row;
|
||||||
|
|
||||||
|
public Record(final Columns columns, final String[] row) {
|
||||||
|
this.columns = columns;
|
||||||
|
this.row = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getString(final String columnName) {
|
||||||
|
return row[columns.indexOf(columnName)];
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isEmpty(final String columnName) {
|
||||||
|
final String value = getString(columnName);
|
||||||
|
return value == null || value.isBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean getBoolean(final String columnName) {
|
||||||
|
final String value = getString(columnName);
|
||||||
|
return isNotBlank(value) &&
|
||||||
|
( parseBoolean(value.trim()) || value.trim().startsWith("t"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer getInteger(final String columnName) {
|
||||||
|
final String value = getString(columnName);
|
||||||
|
return isNotBlank(value) ? Integer.parseInt(value.trim()) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal getBigDecimal(final String columnName) {
|
||||||
|
final String value = getString(columnName);
|
||||||
|
if (isNotBlank(value)) {
|
||||||
|
return new BigDecimal(value);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate getLocalDate(final String columnName) {
|
||||||
|
final String dateString = getString(columnName);
|
||||||
|
if (isNotBlank(dateString)) {
|
||||||
|
return LocalDate.parse(dateString);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrderedDependedTestsExtension implements TestWatcher, BeforeEachCallback {
|
||||||
|
|
||||||
|
private static boolean previousTestsPassed = true;
|
||||||
|
|
||||||
|
public void testFailed(ExtensionContext context, Throwable cause) {
|
||||||
|
previousTestsPassed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeEach(final ExtensionContext extensionContext) {
|
||||||
|
assumeThat(previousTestsPassed).isTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WriteOnceMap<K, V> extends TreeMap<K, V> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V put(final K k, final V v) {
|
||||||
|
assertThat(containsKey(k)).describedAs("overwriting " + get(k) + " index " + k + " with " + v).isFalse();
|
||||||
|
return super.put(k, v);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,620 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.migration;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.debitor.HsBookingDebitorEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidatorRegistry;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.validators.HostingAssetEntitySaveProcessor;
|
||||||
|
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Tag;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.test.annotation.Commit;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static java.util.Arrays.stream;
|
||||||
|
import static java.util.Optional.ofNullable;
|
||||||
|
import static java.util.stream.Collectors.toMap;
|
||||||
|
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER;
|
||||||
|
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.IPV4_NUMBER;
|
||||||
|
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
|
||||||
|
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE;
|
||||||
|
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This 'test' includes the complete legacy 'office' data import.
|
||||||
|
*
|
||||||
|
* There is no code in 'main' because the import is not needed a normal runtime.
|
||||||
|
* There is some test data in Java resources to verify the data conversion.
|
||||||
|
* For a real import a main method will be added later
|
||||||
|
* which reads CSV files from the file system.
|
||||||
|
*
|
||||||
|
* When run on a Hostsharing database, it needs the following settings (hsh99_... just examples).
|
||||||
|
*
|
||||||
|
* In a real Hostsharing environment, these are created via (the old) hsadmin:
|
||||||
|
|
||||||
|
CREATE USER hsh99_admin WITH PASSWORD 'password';
|
||||||
|
CREATE DATABASE hsh99_hsadminng ENCODING 'UTF8' TEMPLATE template0;
|
||||||
|
REVOKE ALL ON DATABASE hsh99_hsadminng FROM public; -- why does hsadmin do that?
|
||||||
|
ALTER DATABASE hsh99_hsadminng OWNER TO hsh99_admin;
|
||||||
|
|
||||||
|
CREATE USER hsh99_restricted WITH PASSWORD 'password';
|
||||||
|
|
||||||
|
\c hsh99_hsadminng
|
||||||
|
|
||||||
|
GRANT ALL PRIVILEGES ON SCHEMA public to hsh99_admin;
|
||||||
|
|
||||||
|
* Additionally, we need these settings (because the Hostsharing DB-Admin has no CREATE right):
|
||||||
|
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
|
-- maybe something like that is needed for the 2nd user
|
||||||
|
-- GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public to hsh99_restricted;
|
||||||
|
|
||||||
|
* Then copy the file .tc-environment to a file named .environment (excluded from git) and fill in your specific values.
|
||||||
|
|
||||||
|
* To finally import the office data, run:
|
||||||
|
*
|
||||||
|
* gw-importHostingAssets # comes from .aliases file and uses .environment
|
||||||
|
*/
|
||||||
|
@Tag("importHostingAssets")
|
||||||
|
@DataJpaTest(properties = {
|
||||||
|
"spring.datasource.url=${HSADMINNG_POSTGRES_JDBC_URL:jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers}",
|
||||||
|
"spring.datasource.username=${HSADMINNG_POSTGRES_ADMIN_USERNAME:ADMIN}",
|
||||||
|
"spring.datasource.password=${HSADMINNG_POSTGRES_ADMIN_PASSWORD:password}",
|
||||||
|
"hsadminng.superuser=${HSADMINNG_SUPERUSER:superuser-alex@hostsharing.net}"
|
||||||
|
})
|
||||||
|
@DirtiesContext
|
||||||
|
@Import({ Context.class, JpaAttempt.class })
|
||||||
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
|
@ExtendWith(OrderedDependedTestsExtension.class)
|
||||||
|
public class ImportHostingAssets extends ImportOfficeData {
|
||||||
|
|
||||||
|
static final Integer IP_NUMBER_ID_OFFSET = 1000000;
|
||||||
|
static final Integer HIVE_ID_OFFSET = 2000000;
|
||||||
|
static final Integer PACKET_ID_OFFSET = 3000000;
|
||||||
|
|
||||||
|
record Hive(int hive_id, String hive_name, int inet_addr_id, AtomicReference<HsHostingAssetEntity> serverRef) {}
|
||||||
|
|
||||||
|
static Map<Integer, HsBookingProjectEntity> bookingProjects = new WriteOnceMap<>();
|
||||||
|
static Map<Integer, HsBookingItemEntity> bookingItems = new WriteOnceMap<>();
|
||||||
|
static Map<Integer, Hive> hives = new WriteOnceMap<>();
|
||||||
|
static Map<Integer, HsHostingAssetEntity> hostingAssets = new WriteOnceMap<>(); // TODO.impl: separate maps for each type?
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(11010)
|
||||||
|
void createBookingProjects() {
|
||||||
|
debitors.forEach((id, debitor) -> {
|
||||||
|
bookingProjects.put(id, HsBookingProjectEntity.builder()
|
||||||
|
.caption(debitor.getDefaultPrefix() + " default project")
|
||||||
|
.debitor(em.find(HsBookingDebitorEntity.class, debitor.getUuid()))
|
||||||
|
.build());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(12010)
|
||||||
|
void importIpNumbers() {
|
||||||
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/inet_addr.csv")) {
|
||||||
|
final var lines = readAllLines(reader);
|
||||||
|
importIpNumbers(justHeader(lines), withoutHeader(lines));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(12019)
|
||||||
|
void verifyIpNumbers() {
|
||||||
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
|
// no contacts yet => mostly null values
|
||||||
|
assertThat(firstOfEachType(5, IPV4_NUMBER)).isEqualToIgnoringWhitespace("""
|
||||||
|
{
|
||||||
|
1000363=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.34),
|
||||||
|
1000381=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.52),
|
||||||
|
1000402=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.73),
|
||||||
|
1000433=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.104),
|
||||||
|
1000457=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.128)
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(12030)
|
||||||
|
void importHives() {
|
||||||
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/hive.csv")) {
|
||||||
|
final var lines = readAllLines(reader);
|
||||||
|
importHives(justHeader(lines), withoutHeader(lines));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(12039)
|
||||||
|
void verifyHives() {
|
||||||
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
|
// no contacts yet => mostly null values
|
||||||
|
assertThat(toFormattedString(first(5, hives))).isEqualToIgnoringWhitespace("""
|
||||||
|
{
|
||||||
|
2000001=Hive[hive_id=1, hive_name=h00, inet_addr_id=358, serverRef=null],
|
||||||
|
2000002=Hive[hive_id=2, hive_name=h01, inet_addr_id=359, serverRef=null],
|
||||||
|
2000004=Hive[hive_id=4, hive_name=h02, inet_addr_id=360, serverRef=null],
|
||||||
|
2000007=Hive[hive_id=7, hive_name=h03, inet_addr_id=361, serverRef=null],
|
||||||
|
2000013=Hive[hive_id=13, hive_name=h04, inet_addr_id=430, serverRef=null]
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(13000)
|
||||||
|
void importPackets() {
|
||||||
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/packet.csv")) {
|
||||||
|
final var lines = readAllLines(reader);
|
||||||
|
importPackets(justHeader(lines), withoutHeader(lines));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(13009)
|
||||||
|
void verifyPackets() {
|
||||||
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
|
assertThat(firstOfEachType(3, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE)).isEqualToIgnoringWhitespace("""
|
||||||
|
{
|
||||||
|
3000630=HsHostingAssetEntity(MANAGED_WEBSPACE, hsh00, HA hsh00, MANAGED_SERVER:vm1050, D-1000000:hsh default project:BI hsh00),
|
||||||
|
3000968=HsHostingAssetEntity(MANAGED_SERVER, vm1061, HA vm1061, D-1015200:rar default project:BI vm1061),
|
||||||
|
3000978=HsHostingAssetEntity(MANAGED_SERVER, vm1050, HA vm1050, D-1000000:hsh default project:BI vm1050),
|
||||||
|
3001061=HsHostingAssetEntity(MANAGED_SERVER, vm1068, HA vm1068, D-1000300:mim default project:BI vm1068),
|
||||||
|
3001094=HsHostingAssetEntity(MANAGED_WEBSPACE, lug00, HA lug00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI lug00),
|
||||||
|
3001112=HsHostingAssetEntity(MANAGED_WEBSPACE, mim00, HA mim00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI mim00),
|
||||||
|
3023611=HsHostingAssetEntity(CLOUD_SERVER, vm2097, HA vm2097, D-1101800:wws default project:BI vm2097)
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
assertThat(firstOfEachType(
|
||||||
|
3,
|
||||||
|
HsBookingItemType.CLOUD_SERVER,
|
||||||
|
HsBookingItemType.MANAGED_SERVER,
|
||||||
|
HsBookingItemType.MANAGED_WEBSPACE)).isEqualToIgnoringWhitespace("""
|
||||||
|
{
|
||||||
|
3000630=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_WEBSPACE, [2001-06-01,), BI hsh00),
|
||||||
|
3000968=HsBookingItemEntity(D-1015200:rar default project, MANAGED_SERVER, [2013-04-01,), BI vm1061),
|
||||||
|
3000978=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_SERVER, [2013-04-01,), BI vm1050),
|
||||||
|
3001061=HsBookingItemEntity(D-1000300:mim default project, MANAGED_SERVER, [2013-08-19,), BI vm1068),
|
||||||
|
3001094=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-10,), BI lug00),
|
||||||
|
3001112=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-17,), BI mim00),
|
||||||
|
3023611=HsBookingItemEntity(D-1101800:wws default project, CLOUD_SERVER, [2022-08-10,), BI vm2097)
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(13010)
|
||||||
|
void importPacketComponents() {
|
||||||
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/packet_component.csv")) {
|
||||||
|
final var lines = readAllLines(reader);
|
||||||
|
importPacketComponents(justHeader(lines), withoutHeader(lines));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(13019)
|
||||||
|
void verifyPacketComponents() {
|
||||||
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
|
// no contacts yet => mostly null values
|
||||||
|
assertThat(firstOfEachType(5, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE))
|
||||||
|
.isEqualToIgnoringWhitespace("""
|
||||||
|
{
|
||||||
|
3000630=HsHostingAssetEntity(MANAGED_WEBSPACE, hsh00, HA hsh00, MANAGED_SERVER:vm1050, D-1000000:hsh default project:BI hsh00),
|
||||||
|
3000968=HsHostingAssetEntity(MANAGED_SERVER, vm1061, HA vm1061, D-1015200:rar default project:BI vm1061),
|
||||||
|
3000978=HsHostingAssetEntity(MANAGED_SERVER, vm1050, HA vm1050, D-1000000:hsh default project:BI vm1050),
|
||||||
|
3001061=HsHostingAssetEntity(MANAGED_SERVER, vm1068, HA vm1068, D-1000300:mim default project:BI vm1068),
|
||||||
|
3001094=HsHostingAssetEntity(MANAGED_WEBSPACE, lug00, HA lug00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI lug00),
|
||||||
|
3001112=HsHostingAssetEntity(MANAGED_WEBSPACE, mim00, HA mim00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI mim00),
|
||||||
|
3001447=HsHostingAssetEntity(MANAGED_SERVER, vm1093, HA vm1093, D-1000000:hsh default project:BI vm1093),
|
||||||
|
3019959=HsHostingAssetEntity(MANAGED_WEBSPACE, dph00, HA dph00, MANAGED_SERVER:vm1093, D-1101900:dph default project:BI dph00),
|
||||||
|
3023611=HsHostingAssetEntity(CLOUD_SERVER, vm2097, HA vm2097, D-1101800:wws default project:BI vm2097)
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
assertThat(firstOfEachType(
|
||||||
|
5,
|
||||||
|
HsBookingItemType.CLOUD_SERVER,
|
||||||
|
HsBookingItemType.MANAGED_SERVER,
|
||||||
|
HsBookingItemType.MANAGED_WEBSPACE))
|
||||||
|
.isEqualToIgnoringWhitespace("""
|
||||||
|
{
|
||||||
|
3000630=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_WEBSPACE, [2001-06-01,), BI hsh00, { "HDD": 10, "Multi": 25, "SLA-Platform": "EXT24H", "SSD": 16, "Traffic": 50}),
|
||||||
|
3000968=HsBookingItemEntity(D-1015200:rar default project, MANAGED_SERVER, [2013-04-01,), BI vm1061, { "CPU": 6, "HDD": 250, "RAM": 14, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 375, "Traffic": 250}),
|
||||||
|
3000978=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_SERVER, [2013-04-01,), BI vm1050, { "CPU": 4, "HDD": 250, "RAM": 32, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 150, "Traffic": 250}),
|
||||||
|
3001061=HsBookingItemEntity(D-1000300:mim default project, MANAGED_SERVER, [2013-08-19,), BI vm1068, { "CPU": 2, "HDD": 250, "RAM": 4, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT2H", "SLA-Web": true, "Traffic": 250}),
|
||||||
|
3001094=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-10,), BI lug00, { "Multi": 5, "SLA-Platform": "EXT24H", "SSD": 1, "Traffic": 10}),
|
||||||
|
3001112=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-17,), BI mim00, { "Multi": 5, "SLA-Platform": "EXT24H", "SSD": 3, "Traffic": 20}),
|
||||||
|
3001447=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_SERVER, [2014-11-28,), BI vm1093, { "CPU": 6, "HDD": 500, "RAM": 16, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 300, "Traffic": 250}),
|
||||||
|
3019959=HsBookingItemEntity(D-1101900:dph default project, MANAGED_WEBSPACE, [2021-06-02,), BI dph00, { "Multi": 1, "SLA-Platform": "EXT24H", "SSD": 25, "Traffic": 20}),
|
||||||
|
3023611=HsBookingItemEntity(D-1101800:wws default project, CLOUD_SERVER, [2022-08-10,), BI vm2097, { "CPU": 8, "RAM": 12, "SLA-Infrastructure": "EXT4H", "SSD": 25, "Traffic": 250})
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(11400)
|
||||||
|
void validateBookingItems() {
|
||||||
|
bookingItems.forEach((id, bi) -> {
|
||||||
|
try {
|
||||||
|
HsBookingItemEntityValidatorRegistry.validated(bi);
|
||||||
|
} catch (final Exception exc) {
|
||||||
|
System.err.println("validation failed for id:" + id + "( " + bi + "): " + exc.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(11410)
|
||||||
|
void validateHostingAssets() {
|
||||||
|
hostingAssets.forEach((id, ha) -> {
|
||||||
|
try {
|
||||||
|
new HostingAssetEntitySaveProcessor(ha)
|
||||||
|
.preprocessEntity()
|
||||||
|
.validateEntity();
|
||||||
|
} catch (final Exception exc) {
|
||||||
|
System.err.println("validation failed for id:" + id + "( " + ha + "): " + exc.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(19000)
|
||||||
|
@Commit
|
||||||
|
void persistHostingAssetEntities() {
|
||||||
|
|
||||||
|
System.out.println("PERSISTING hosting-assets to database '" + jdbcUrl + "' as user '" + postgresAdminUser + "'");
|
||||||
|
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context(rbacSuperuser);
|
||||||
|
bookingProjects.forEach(this::persist);
|
||||||
|
}).assertSuccessful();
|
||||||
|
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context(rbacSuperuser);
|
||||||
|
bookingItems.forEach(this::persistRecursively);
|
||||||
|
}).assertSuccessful();
|
||||||
|
|
||||||
|
persistHostingAssetsOfType(CLOUD_SERVER);
|
||||||
|
persistHostingAssetsOfType(MANAGED_SERVER);
|
||||||
|
persistHostingAssetsOfType(MANAGED_WEBSPACE);
|
||||||
|
persistHostingAssetsOfType(IPV4_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(99999)
|
||||||
|
void logErrors() {
|
||||||
|
super.logErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistRecursively(final Integer key, final HsBookingItemEntity bi) {
|
||||||
|
if (bi.getParentItem() != null) {
|
||||||
|
persistRecursively(key, HsBookingItemEntityValidatorRegistry.validated(bi.getParentItem()));
|
||||||
|
}
|
||||||
|
persist(key, HsBookingItemEntityValidatorRegistry.validated(bi));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistHostingAssetsOfType(final HsHostingAssetType hsHostingAssetType) {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context(rbacSuperuser);
|
||||||
|
hostingAssets.forEach((key, ha) -> {
|
||||||
|
if (ha.getType() == hsHostingAssetType) {
|
||||||
|
new HostingAssetEntitySaveProcessor(ha)
|
||||||
|
.preprocessEntity()
|
||||||
|
.validateEntity()
|
||||||
|
.prepareForSave()
|
||||||
|
.saveUsing(entity -> persist(key, entity))
|
||||||
|
.validateContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}).assertSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importIpNumbers(final String[] header, final List<String[]> records) {
|
||||||
|
final var columns = new Columns(header);
|
||||||
|
records.stream()
|
||||||
|
.map(this::trimAll)
|
||||||
|
.map(row -> new Record(columns, row))
|
||||||
|
.forEach(rec -> {
|
||||||
|
final var ipNumber = HsHostingAssetEntity.builder()
|
||||||
|
.type(IPV4_NUMBER)
|
||||||
|
.identifier(rec.getString("inet_addr"))
|
||||||
|
.caption(rec.getString("description"))
|
||||||
|
.build();
|
||||||
|
hostingAssets.put(IP_NUMBER_ID_OFFSET + rec.getInteger("inet_addr_id"), ipNumber);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importHives(final String[] header, final List<String[]> records) {
|
||||||
|
final var columns = new Columns(header);
|
||||||
|
records.stream()
|
||||||
|
.map(this::trimAll)
|
||||||
|
.map(row -> new Record(columns, row))
|
||||||
|
.forEach(rec -> {
|
||||||
|
final var hive_id = rec.getInteger("hive_id");
|
||||||
|
final var hive = new Hive(
|
||||||
|
hive_id,
|
||||||
|
rec.getString("hive_name"),
|
||||||
|
rec.getInteger("inet_addr_id"),
|
||||||
|
new AtomicReference<>());
|
||||||
|
hives.put(HIVE_ID_OFFSET + hive_id, hive);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importPackets(final String[] header, final List<String[]> records) {
|
||||||
|
final var columns = new Columns(header);
|
||||||
|
records.stream()
|
||||||
|
.map(this::trimAll)
|
||||||
|
.map(row -> new Record(columns, row))
|
||||||
|
.forEach(rec -> {
|
||||||
|
final var packet_id = rec.getInteger("packet_id");
|
||||||
|
final var basepacket_code = rec.getString("basepacket_code");
|
||||||
|
final var packet_name = rec.getString("packet_name");
|
||||||
|
final var bp_id = rec.getInteger("bp_id");
|
||||||
|
final var hive_id = rec.getInteger("hive_id");
|
||||||
|
final var created = rec.getLocalDate("created");
|
||||||
|
final var cancelled = rec.getLocalDate("cancelled");
|
||||||
|
final var cur_inet_addr_id = rec.getInteger("cur_inet_addr_id");
|
||||||
|
final var old_inet_addr_id = rec.getInteger("old_inet_addr_id");
|
||||||
|
final var free = rec.getBoolean("free");
|
||||||
|
|
||||||
|
assertThat(old_inet_addr_id)
|
||||||
|
.as("packet.old_inet_addr_id not supported, but is not null for " + packet_name)
|
||||||
|
.isNull();
|
||||||
|
|
||||||
|
final var biType = determineBiType(basepacket_code);
|
||||||
|
final var bookingItem = HsBookingItemEntity.builder()
|
||||||
|
.type(biType)
|
||||||
|
.caption("BI " + packet_name)
|
||||||
|
.project(bookingProjects.get(bp_id))
|
||||||
|
.validity(toPostgresDateRange(created, cancelled))
|
||||||
|
.build();
|
||||||
|
bookingItems.put(PACKET_ID_OFFSET + packet_id, bookingItem);
|
||||||
|
final var haType = determineHaType(basepacket_code);
|
||||||
|
|
||||||
|
logError(() -> assertThat(!free || haType == MANAGED_WEBSPACE || bookingItem.getRelatedProject().getDebitor().getDefaultPrefix().equals("hsh"))
|
||||||
|
.as("packet.free only supported for Hostsharing-Assets and ManagedWebspace in customer-ManagedServer, but is set for " + packet_name)
|
||||||
|
.isTrue());
|
||||||
|
|
||||||
|
final var asset = HsHostingAssetEntity.builder()
|
||||||
|
.isLoaded(haType == MANAGED_WEBSPACE) // this turns off identifier validation to accept former default prefixes
|
||||||
|
.type(haType)
|
||||||
|
.identifier(packet_name)
|
||||||
|
.bookingItem(bookingItem)
|
||||||
|
.caption("HA " + packet_name)
|
||||||
|
.build();
|
||||||
|
hostingAssets.put(PACKET_ID_OFFSET + packet_id, asset);
|
||||||
|
if (haType == MANAGED_SERVER) {
|
||||||
|
hive(hive_id).serverRef.set(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur_inet_addr_id != null) {
|
||||||
|
ipNumber(cur_inet_addr_id).setAssignedToAsset(asset);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// once we know all hosting assets, we can set the parentAsset for managed webspaces
|
||||||
|
records.stream()
|
||||||
|
.map(this::trimAll)
|
||||||
|
.map(row -> new Record(columns, row))
|
||||||
|
.forEach(rec -> {
|
||||||
|
final var packet_id = rec.getInteger("packet_id");
|
||||||
|
final var basepacket_code = rec.getString("basepacket_code");
|
||||||
|
final var hive_id = rec.getInteger("hive_id");
|
||||||
|
|
||||||
|
final var haType = determineHaType(basepacket_code);
|
||||||
|
if (haType == MANAGED_WEBSPACE) {
|
||||||
|
final var managedWebspace = pac(packet_id);
|
||||||
|
final var parentAsset = hive(hive_id).serverRef.get();
|
||||||
|
managedWebspace.setParentAsset(parentAsset);
|
||||||
|
managedWebspace.getBookingItem().setParentItem(parentAsset.getBookingItem());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importPacketComponents(final String[] header, final List<String[]> records) {
|
||||||
|
final var columns = new Columns(header);
|
||||||
|
records.stream()
|
||||||
|
.map(this::trimAll)
|
||||||
|
.map(row -> new Record(columns, row))
|
||||||
|
.forEach(rec -> {
|
||||||
|
// final var packet_component_id = rec.getInteger("packet_component_id"); not needed
|
||||||
|
final var packet_id = rec.getInteger("packet_id");
|
||||||
|
final var quantity = rec.getInteger("quantity");
|
||||||
|
final var basecomponent_code = rec.getString("basecomponent_code");
|
||||||
|
// final var created = rec.getLocalDate("created"); TODO.spec: can we do without?
|
||||||
|
// final var cancelled = rec.getLocalDate("cancelled"); TODO.spec: can we do without?
|
||||||
|
Function<Integer, Object> convert = (v -> v);
|
||||||
|
|
||||||
|
final var asset = pac(packet_id);
|
||||||
|
final var name = switch (basecomponent_code) {
|
||||||
|
case "DAEMON" -> "Daemons";
|
||||||
|
case "MULTI" -> "Multi";
|
||||||
|
case "CPU" -> "CPU";
|
||||||
|
case "RAM" -> returning("RAM", convert = v -> v/1024);
|
||||||
|
case "QUOTA" -> returning("SSD", convert = v -> v/1024);
|
||||||
|
case "STORAGE" -> returning("HDD", convert = v -> v/1024);
|
||||||
|
case "TRAFFIC" -> "Traffic";
|
||||||
|
case "OFFICE" -> returning("Online Office Server", convert = v -> v == 1);
|
||||||
|
|
||||||
|
case "SLABASIC" -> switch (asset.getType()) {
|
||||||
|
case CLOUD_SERVER -> "SLA-Infrastructure";
|
||||||
|
case MANAGED_SERVER -> "SLA-Platform";
|
||||||
|
case MANAGED_WEBSPACE -> "SLA-Platform";
|
||||||
|
default -> throw new IllegalArgumentException("SLABASIC not defined for " + asset.getType());
|
||||||
|
};
|
||||||
|
|
||||||
|
case "SLAINFR2H" -> "SLA-Infrastructure";
|
||||||
|
case "SLAINFR4H" -> "SLA-Infrastructure";
|
||||||
|
case "SLAINFR8H" -> "SLA-Infrastructure";
|
||||||
|
|
||||||
|
case "SLAEXT24H" -> "SLA-Platform";
|
||||||
|
|
||||||
|
case "SLAPLAT2H" -> "SLA-Platform";
|
||||||
|
case "SLAPLAT4H" -> "SLA-Platform";
|
||||||
|
case "SLAPLAT8H" -> "SLA-Platform";
|
||||||
|
|
||||||
|
case "SLAWEB2H" -> "SLA-Web";
|
||||||
|
case "SLAWEB4H" -> "SLA-Web";
|
||||||
|
case "SLAWEB8H" -> "SLA-Web";
|
||||||
|
|
||||||
|
case "SLAMAIL2H" -> "SLA-EMail";
|
||||||
|
case "SLAMAIL4H" -> "SLA-EMail";
|
||||||
|
case "SLAMAIL8H" -> "SLA-EMail";
|
||||||
|
|
||||||
|
case "SLAMARIA2H" -> "SLA-Maria";
|
||||||
|
case "SLAMARIA4H" -> "SLA-Maria";
|
||||||
|
case "SLAMARIA8H" -> "SLA-Maria";
|
||||||
|
|
||||||
|
case "SLAPGSQL2H" -> "SLA-PgSQL";
|
||||||
|
case "SLAPGSQL4H" -> "SLA-PgSQL";
|
||||||
|
case "SLAPGSQL8H" -> "SLA-PgSQL";
|
||||||
|
|
||||||
|
case "SLAOFFIC2H" -> "SLA-Office";
|
||||||
|
case "SLAOFFIC4H" -> "SLA-Office";
|
||||||
|
case "SLAOFFIC8H" -> "SLA-Office";
|
||||||
|
|
||||||
|
case "BANDWIDTH" -> "Bandwidth";
|
||||||
|
default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (name.equals("SLA-Infrastructure")) {
|
||||||
|
final var slaValue = switch (basecomponent_code) {
|
||||||
|
case "SLABASIC" -> "BASIC";
|
||||||
|
case "SLAINFR2H" -> "EXT2H";
|
||||||
|
case "SLAINFR4H" -> "EXT4H";
|
||||||
|
case "SLAINFR8H" -> "EXT8H";
|
||||||
|
default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code);
|
||||||
|
};
|
||||||
|
asset.getBookingItem().getResources().put(name, slaValue);
|
||||||
|
} else if (name.equals("SLA-Platform")) {
|
||||||
|
final var slaValue = switch (basecomponent_code) {
|
||||||
|
case "SLABASIC" -> "BASIC";
|
||||||
|
case "SLAEXT24H" -> "EXT24H";
|
||||||
|
case "SLAPLAT2H" -> "EXT2H";
|
||||||
|
case "SLAPLAT4H" -> "EXT4H";
|
||||||
|
case "SLAPLAT8H" -> "EXT8H";
|
||||||
|
default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code);
|
||||||
|
};
|
||||||
|
if ( ofNullable(asset.getBookingItem().getResources().get(name)).map("BASIC"::equals).orElse(true) ) {
|
||||||
|
asset.getBookingItem().getResources().put(name, slaValue);
|
||||||
|
}
|
||||||
|
} else if (name.startsWith("SLA")) {
|
||||||
|
asset.getBookingItem().getResources().put(name, true);
|
||||||
|
} else if (quantity > 0) {
|
||||||
|
asset.getBookingItem().getResources().put(name, convert.apply(quantity));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
<V> V returning(final V value, final Object... assignments) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull HsBookingItemType determineBiType(final String basepacket_code) {
|
||||||
|
return switch (basepacket_code) {
|
||||||
|
case "SRV/CLD" -> HsBookingItemType.CLOUD_SERVER;
|
||||||
|
case "SRV/MGD" -> HsBookingItemType.MANAGED_SERVER;
|
||||||
|
case "PAC/WEB" -> HsBookingItemType.MANAGED_WEBSPACE;
|
||||||
|
default -> throw new IllegalArgumentException(
|
||||||
|
"unknown basepacket_code: " + basepacket_code);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull HsHostingAssetType determineHaType(final String basepacket_code) {
|
||||||
|
return switch (basepacket_code) {
|
||||||
|
case "SRV/CLD" -> CLOUD_SERVER;
|
||||||
|
case "SRV/MGD" -> MANAGED_SERVER;
|
||||||
|
case "PAC/WEB" -> MANAGED_WEBSPACE;
|
||||||
|
default -> throw new IllegalArgumentException(
|
||||||
|
"unknown basepacket_code: " + basepacket_code);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HsHostingAssetEntity ipNumber(final Integer inet_addr_id) {
|
||||||
|
return inet_addr_id != null ? hostingAssets.get(IP_NUMBER_ID_OFFSET + inet_addr_id) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Hive hive(final Integer hive_id) {
|
||||||
|
return hive_id != null ? hives.get(HIVE_ID_OFFSET + hive_id) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HsHostingAssetEntity pac(final Integer packet_id) {
|
||||||
|
return packet_id != null ? hostingAssets.get(PACKET_ID_OFFSET + packet_id) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String firstOfEachType(
|
||||||
|
final int maxCount,
|
||||||
|
final HsHostingAssetType... types) {
|
||||||
|
return toFormattedString(stream(types)
|
||||||
|
.flatMap(t ->
|
||||||
|
hostingAssets.entrySet().stream()
|
||||||
|
.filter(hae -> hae.getValue().getType() == t)
|
||||||
|
.limit(maxCount)
|
||||||
|
)
|
||||||
|
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String firstOfEachType(
|
||||||
|
final int maxCount,
|
||||||
|
final HsBookingItemType... types) {
|
||||||
|
return toFormattedString(stream(types)
|
||||||
|
.flatMap(t ->
|
||||||
|
bookingItems.entrySet().stream()
|
||||||
|
.filter(bie -> bie.getValue().getType() == t)
|
||||||
|
.limit(maxCount)
|
||||||
|
)
|
||||||
|
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Integer, Object> first(
|
||||||
|
final int maxCount,
|
||||||
|
final Map<Integer, ?> entities) {
|
||||||
|
return entities.entrySet().stream()
|
||||||
|
.limit(maxCount)
|
||||||
|
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assumeThatWeAreExplicitlyImportingOfficeData() {
|
||||||
|
assumeThat(false).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean isImportingControlledTestData() {
|
||||||
|
return MIGRATION_DATA_PATH.equals(TEST_DATA_MIGRATION_DATA_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void assumeThatWeAreImportingControlledTestData() {
|
||||||
|
assumeThat(isImportingControlledTestData()).isTrue();
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,6 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.migration;
|
package net.hostsharing.hsadminng.hs.migration;
|
||||||
|
|
||||||
import com.opencsv.CSVParserBuilder;
|
|
||||||
import com.opencsv.CSVReader;
|
|
||||||
import com.opencsv.CSVReaderBuilder;
|
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.rbac.context.ContextBasedTest;
|
|
||||||
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.coopassets.HsOfficeCoopAssetsTransactionEntity;
|
import net.hostsharing.hsadminng.hs.office.coopassets.HsOfficeCoopAssetsTransactionEntity;
|
||||||
@ -26,34 +22,17 @@ import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
|||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
|
||||||
import org.junit.jupiter.api.extension.TestWatcher;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.test.annotation.Commit;
|
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.lang.Boolean.parseBoolean;
|
|
||||||
import static java.util.Arrays.stream;
|
import static java.util.Arrays.stream;
|
||||||
import static java.util.Objects.requireNonNull;
|
|
||||||
import static java.util.Optional.ofNullable;
|
import static java.util.Optional.ofNullable;
|
||||||
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
@ -96,9 +75,9 @@ import static org.assertj.core.api.Fail.fail;
|
|||||||
|
|
||||||
* To finally import the office data, run:
|
* To finally import the office data, run:
|
||||||
*
|
*
|
||||||
* import-office-tables # comes from .aliases file and uses .environment
|
* gw-importOfficeTables # comes from .aliases file and uses .environment
|
||||||
*/
|
*/
|
||||||
@Tag("import")
|
@Tag("importOfficeData")
|
||||||
@DataJpaTest(properties = {
|
@DataJpaTest(properties = {
|
||||||
"spring.datasource.url=${HSADMINNG_POSTGRES_JDBC_URL:jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers}",
|
"spring.datasource.url=${HSADMINNG_POSTGRES_JDBC_URL:jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers}",
|
||||||
"spring.datasource.username=${HSADMINNG_POSTGRES_ADMIN_USERNAME:ADMIN}",
|
"spring.datasource.username=${HSADMINNG_POSTGRES_ADMIN_USERNAME:ADMIN}",
|
||||||
@ -109,7 +88,7 @@ import static org.assertj.core.api.Fail.fail;
|
|||||||
@Import({ Context.class, JpaAttempt.class })
|
@Import({ Context.class, JpaAttempt.class })
|
||||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
@ExtendWith(OrderedDependedTestsExtension.class)
|
@ExtendWith(OrderedDependedTestsExtension.class)
|
||||||
public class ImportOfficeData extends ContextBasedTest {
|
public class ImportOfficeData extends CsvDataImport {
|
||||||
|
|
||||||
private static final String[] SUBSCRIBER_ROLES = new String[] {
|
private static final String[] SUBSCRIBER_ROLES = new String[] {
|
||||||
"subscriber:operations-discussion",
|
"subscriber:operations-discussion",
|
||||||
@ -123,15 +102,16 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
new String[]{"partner", "vip-contact", "ex-partner", "billing", "contractual", "operation"},
|
new String[]{"partner", "vip-contact", "ex-partner", "billing", "contractual", "operation"},
|
||||||
SUBSCRIBER_ROLES);
|
SUBSCRIBER_ROLES);
|
||||||
|
|
||||||
// at least as the number of lines in business-partners.csv from test-data, but less than real data partner count
|
// at least as the number of lines in business_partners.csv from test-data, but less than real data partner count
|
||||||
public static final int MAX_NUMBER_OF_TEST_DATA_PARTNERS = 100;
|
public static final int MAX_NUMBER_OF_TEST_DATA_PARTNERS = 100;
|
||||||
public static final String MIGRATION_DATA_PATH = ofNullable(System.getenv("HSADMINNG_MIGRATION_DATA_PATH")).orElse("migration") + "/";
|
|
||||||
|
|
||||||
static int relationId = 2000000;
|
static int relationId = 2000000;
|
||||||
|
|
||||||
private static final List<Integer> IGNORE_BUSINESS_PARTNERS = Arrays.asList(
|
private static final List<Integer> IGNORE_BUSINESS_PARTNERS = Arrays.asList(
|
||||||
512167, // 11139, partner without contractual contact
|
512167, // 11139, partner without contractual contact
|
||||||
512170, // 11142, partner without contractual contact
|
512170, // 11142, partner without contractual contact
|
||||||
|
511725, // 10764, partner without contractual contact
|
||||||
|
// 512171, // 11143, partner without partner contact -- exc
|
||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -140,44 +120,23 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
|
|
||||||
@Value("${spring.datasource.url}")
|
static Map<Integer, HsOfficeContactEntity> contacts = new WriteOnceMap<>();
|
||||||
private String jdbcUrl;
|
static Map<Integer, HsOfficePersonEntity> persons = new WriteOnceMap<>();
|
||||||
|
static Map<Integer, HsOfficePartnerEntity> partners = new WriteOnceMap<>();
|
||||||
|
static Map<Integer, HsOfficeDebitorEntity> debitors = new WriteOnceMap<>();
|
||||||
|
static Map<Integer, HsOfficeMembershipEntity> memberships = new WriteOnceMap<>();
|
||||||
|
|
||||||
@Value("${spring.datasource.username}")
|
static Map<Integer, HsOfficeRelationEntity> relations = new WriteOnceMap<>();
|
||||||
private String postgresAdminUser;
|
static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new WriteOnceMap<>();
|
||||||
|
static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new WriteOnceMap<>();
|
||||||
@Value("${hsadminng.superuser}")
|
static Map<Integer, HsOfficeCoopSharesTransactionEntity> coopShares = new WriteOnceMap<>();
|
||||||
private String rbacSuperuser;
|
static Map<Integer, HsOfficeCoopAssetsTransactionEntity> coopAssets = new WriteOnceMap<>();
|
||||||
|
|
||||||
private static Map<Integer, HsOfficeContactEntity> contacts = new WriteOnceMap<>();
|
|
||||||
private static Map<Integer, HsOfficePersonEntity> persons = new WriteOnceMap<>();
|
|
||||||
private static Map<Integer, HsOfficePartnerEntity> partners = new WriteOnceMap<>();
|
|
||||||
private static Map<Integer, HsOfficeDebitorEntity> debitors = new WriteOnceMap<>();
|
|
||||||
private static Map<Integer, HsOfficeMembershipEntity> memberships = new WriteOnceMap<>();
|
|
||||||
|
|
||||||
private static Map<Integer, HsOfficeRelationEntity> relations = new WriteOnceMap<>();
|
|
||||||
private static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new WriteOnceMap<>();
|
|
||||||
private static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new WriteOnceMap<>();
|
|
||||||
private static Map<Integer, HsOfficeCoopSharesTransactionEntity> coopShares = new WriteOnceMap<>();
|
|
||||||
private static Map<Integer, HsOfficeCoopAssetsTransactionEntity> coopAssets = new WriteOnceMap<>();
|
|
||||||
|
|
||||||
@PersistenceContext
|
|
||||||
EntityManager em;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
TransactionTemplate txTemplate;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
JpaAttempt jpaAttempt;
|
|
||||||
|
|
||||||
@MockBean
|
|
||||||
HttpServletRequest request;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1010)
|
@Order(1010)
|
||||||
void importBusinessPartners() {
|
void importBusinessPartners() {
|
||||||
|
|
||||||
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "business-partners.csv")) {
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/office/business_partners.csv")) {
|
||||||
final var lines = readAllLines(reader);
|
final var lines = readAllLines(reader);
|
||||||
importBusinessPartners(justHeader(lines), withoutHeader(lines));
|
importBusinessPartners(justHeader(lines), withoutHeader(lines));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -193,28 +152,39 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
// no contacts yet => mostly null values
|
// no contacts yet => mostly null values
|
||||||
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=partner(P-10017: null null, null),
|
100=partner(P-10003: null null, null),
|
||||||
20=partner(P-10020: null null, null),
|
120=partner(P-10020: null null, null),
|
||||||
22=partner(P-11022: null null, null),
|
122=partner(P-11022: null null, null),
|
||||||
90=partner(P-19090: null null, null),
|
132=partner(P-10152: null null, null),
|
||||||
99=partner(P-19999: null null, null)
|
190=partner(P-19090: null null, null),
|
||||||
|
199=partner(P-19999: null null, null),
|
||||||
|
213=partner(P-10000: null null, null),
|
||||||
|
541=partner(P-11018: null null, null),
|
||||||
|
542=partner(P-11019: null null, null)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(contacts)).isEqualTo("{}");
|
assertThat(toFormattedString(contacts)).isEqualTo("{}");
|
||||||
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=debitor(D-1001700: rel(anchor='null null, null', type='DEBITOR'), mih),
|
100=debitor(D-1000300: rel(anchor='null null, null', type='DEBITOR'), mim),
|
||||||
20=debitor(D-1002000: rel(anchor='null null, null', type='DEBITOR'), xyz),
|
120=debitor(D-1002000: rel(anchor='null null, null', type='DEBITOR'), xyz),
|
||||||
22=debitor(D-1102200: rel(anchor='null null, null', type='DEBITOR'), xxx),
|
122=debitor(D-1102200: rel(anchor='null null, null', type='DEBITOR'), xxx),
|
||||||
90=debitor(D-1909000: rel(anchor='null null, null', type='DEBITOR'), yyy),
|
132=debitor(D-1015200: rel(anchor='null null, null', type='DEBITOR'), rar),
|
||||||
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz)
|
190=debitor(D-1909000: rel(anchor='null null, null', type='DEBITOR'), yyy),
|
||||||
|
199=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz),
|
||||||
|
213=debitor(D-1000000: rel(anchor='null null, null', type='DEBITOR'), hsh),
|
||||||
|
541=debitor(D-1101800: rel(anchor='null null, null', type='DEBITOR'), wws),
|
||||||
|
542=debitor(D-1101900: rel(anchor='null null, null', type='DEBITOR'), dph)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=Membership(M-1001700, P-10017, [2000-12-06,), ACTIVE),
|
100=Membership(M-1000300, P-10003, [2000-12-06,), ACTIVE),
|
||||||
20=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
|
120=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
|
||||||
22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE)
|
122=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE),
|
||||||
|
132=Membership(M-1015200, P-10152, [2003-07-12,), ACTIVE),
|
||||||
|
541=Membership(M-1101800, P-11018, [2021-05-17,), ACTIVE),
|
||||||
|
542=Membership(M-1101900, P-11019, [2021-05-25,), ACTIVE)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -222,8 +192,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
@Order(1020)
|
@Order(1020)
|
||||||
void importContacts() {
|
void importContacts() {
|
||||||
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/office/contacts.csv")) {
|
||||||
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "contacts.csv")) {
|
|
||||||
final var lines = readAllLines(reader);
|
final var lines = readAllLines(reader);
|
||||||
importContacts(justHeader(lines), withoutHeader(lines));
|
importContacts(justHeader(lines), withoutHeader(lines));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -238,83 +207,151 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
|
|
||||||
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=partner(P-10017: NP Mellies, Michael, Herr Michael Mellies ),
|
100=partner(P-10003: ?? Michael Mellis, Herr Michael Mellis , Michael Mellis),
|
||||||
20=partner(P-10020: LP JM GmbH, Herr Philip Meyer-Contract , JM GmbH),
|
120=partner(P-10020: LP JM GmbH, Herr Philip Meyer-Contract , JM GmbH),
|
||||||
22=partner(P-11022: ?? Test PS, Petra Schmidt , Test PS),
|
122=partner(P-11022: ?? Test PS, Petra Schmidt , Test PS),
|
||||||
90=partner(P-19090: NP Camus, Cecilia, Frau Cecilia Camus ),
|
132=partner(P-10152: ?? Ragnar IT-Beratung, Herr Ragnar Richter , Ragnar IT-Beratung),
|
||||||
99=partner(P-19999: null null, null)
|
190=partner(P-19090: NP Camus, Cecilia, Frau Cecilia Camus ),
|
||||||
|
199=partner(P-19999: null null, null),
|
||||||
|
213=partner(P-10000: LP Hostsharing e.G., Firma Hostmaster Hostsharing , Hostsharing e.G.),
|
||||||
|
541=partner(P-11018: ?? Wasserwerk Südholstein, Frau Christiane Milberg , Wasserwerk Südholstein),
|
||||||
|
542=partner(P-11019: ?? Das Perfekte Haus, Herr Richard Wiese , Das Perfekte Haus)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(contacts)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(contacts)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
1101=contact(caption='Herr Michael Mellies ', emailAddresses='{ "main": "mih@example.org"}'),
|
100=contact(caption='Herr Michael Mellis , Michael Mellis', emailAddresses='{ "main": "michael@Mellis.example.org"}'),
|
||||||
1200=contact(caption='JM e.K.', emailAddresses='{ "main": "jm-ex-partner@example.org"}'),
|
1200=contact(caption='JM e.K.', emailAddresses='{ "main": "jm-ex-partner@example.org"}'),
|
||||||
1201=contact(caption='Frau Dr. Jenny Meyer-Billing , JM GmbH', emailAddresses='{ "main": "jm-billing@example.org"}'),
|
1201=contact(caption='Frau Dr. Jenny Meyer-Billing , JM GmbH', emailAddresses='{ "main": "jm-billing@example.org"}'),
|
||||||
1202=contact(caption='Herr Andrew Meyer-Operation , JM GmbH', emailAddresses='{ "main": "am-operation@example.org"}'),
|
1202=contact(caption='Herr Andrew Meyer-Operation , JM GmbH', emailAddresses='{ "main": "am-operation@example.org"}'),
|
||||||
1203=contact(caption='Herr Philip Meyer-Contract , JM GmbH', emailAddresses='{ "main": "pm-partner@example.org"}'),
|
1203=contact(caption='Herr Philip Meyer-Contract , JM GmbH', emailAddresses='{ "main": "pm-partner@example.org"}'),
|
||||||
1204=contact(caption='Frau Tammy Meyer-VIP , JM GmbH', emailAddresses='{ "main": "tm-vip@example.org"}'),
|
1204=contact(caption='Frau Tammy Meyer-VIP , JM GmbH', emailAddresses='{ "main": "tm-vip@example.org"}'),
|
||||||
1301=contact(caption='Petra Schmidt , Test PS', emailAddresses='{ "main": "ps@example.com"}'),
|
1301=contact(caption='Petra Schmidt , Test PS', emailAddresses='{ "main": "ps@example.com"}'),
|
||||||
|
132=contact(caption='Herr Ragnar Richter , Ragnar IT-Beratung', emailAddresses='{ "main": "hostsharing@ragnar-richter.de"}'),
|
||||||
1401=contact(caption='Frau Frauke Fanninga ', emailAddresses='{ "main": "ff@example.org"}'),
|
1401=contact(caption='Frau Frauke Fanninga ', emailAddresses='{ "main": "ff@example.org"}'),
|
||||||
1501=contact(caption='Frau Cecilia Camus ', emailAddresses='{ "main": "cc@example.org"}')
|
1501=contact(caption='Frau Cecilia Camus ', emailAddresses='{ "main": "cc@example.org"}'),
|
||||||
|
212=contact(caption='Firma Hostmaster Hostsharing , Hostsharing e.G.', emailAddresses='{ "main": "hostmaster@hostsharing.net"}'),
|
||||||
|
90436=contact(caption='Frau Christiane Milberg , Wasserwerk Südholstein', emailAddresses='{ "main": "rechnung@ww-sholst.example.org"}'),
|
||||||
|
90437=contact(caption='Herr Richard Wiese , Das Perfekte Haus', emailAddresses='{ "main": "admin@das-perfekte-haus.example.org"}'),
|
||||||
|
90438=contact(caption='Herr Karim Metzger , Wasswerwerk Südholstein', emailAddresses='{ "main": "karim.metzger@ww-sholst.example.org"}'),
|
||||||
|
90590=contact(caption='Herr Inhaber R. Wiese , Das Perfekte Haus', emailAddresses='{ "main": "515217@kkemail.example.org"}'),
|
||||||
|
90629=contact(caption='Ragnar Richter ', emailAddresses='{ "main": "mail@ragnar-richter..example.org"}'),
|
||||||
|
90677=contact(caption='Eike Henning ', emailAddresses='{ "main": "hostsharing@eike-henning..example.org"}'),
|
||||||
|
90698=contact(caption='Jan Henning ', emailAddresses='{ "main": "mail@jan-henning.example.org"}')
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(persons)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(persons)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
1=person(personType='LP', tradeName='Hostsharing eG'),
|
100=person(personType='??', tradeName='Michael Mellis', familyName='Mellis', givenName='Michael'),
|
||||||
1101=person(personType='NP', familyName='Mellies', givenName='Michael'),
|
|
||||||
1200=person(personType='LP', tradeName='JM e.K.'),
|
1200=person(personType='LP', tradeName='JM e.K.'),
|
||||||
1201=person(personType='LP', tradeName='JM GmbH', familyName='Meyer-Billing', givenName='Jenny'),
|
1201=person(personType='LP', tradeName='JM GmbH', familyName='Meyer-Billing', givenName='Jenny'),
|
||||||
1202=person(personType='LP', tradeName='JM GmbH', familyName='Meyer-Operation', givenName='Andrew'),
|
1202=person(personType='LP', tradeName='JM GmbH', familyName='Meyer-Operation', givenName='Andrew'),
|
||||||
1203=person(personType='LP', tradeName='JM GmbH', familyName='Meyer-Contract', givenName='Philip'),
|
1203=person(personType='LP', tradeName='JM GmbH', familyName='Meyer-Contract', givenName='Philip'),
|
||||||
1204=person(personType='LP', tradeName='JM GmbH', familyName='Meyer-VIP', givenName='Tammy'),
|
1204=person(personType='LP', tradeName='JM GmbH', familyName='Meyer-VIP', givenName='Tammy'),
|
||||||
1301=person(personType='??', tradeName='Test PS', familyName='Schmidt', givenName='Petra'),
|
1301=person(personType='??', tradeName='Test PS', familyName='Schmidt', givenName='Petra'),
|
||||||
|
132=person(personType='??', tradeName='Ragnar IT-Beratung', familyName='Richter', givenName='Ragnar'),
|
||||||
1401=person(personType='NP', familyName='Fanninga', givenName='Frauke'),
|
1401=person(personType='NP', familyName='Fanninga', givenName='Frauke'),
|
||||||
1501=person(personType='NP', familyName='Camus', givenName='Cecilia')
|
1501=person(personType='NP', familyName='Camus', givenName='Cecilia'),
|
||||||
|
212=person(personType='LP', tradeName='Hostsharing e.G.', familyName='Hostsharing', givenName='Hostmaster'),
|
||||||
|
90436=person(personType='??', tradeName='Wasserwerk Südholstein', familyName='Milberg', givenName='Christiane'),
|
||||||
|
90437=person(personType='??', tradeName='Das Perfekte Haus', familyName='Wiese', givenName='Richard'),
|
||||||
|
90438=person(personType='??', tradeName='Wasswerwerk Südholstein', familyName='Metzger', givenName='Karim'),
|
||||||
|
90590=person(personType='??', tradeName='Das Perfekte Haus', familyName='Wiese', givenName='Inhaber R.'),
|
||||||
|
90629=person(personType='NP', familyName='Richter', givenName='Ragnar'),
|
||||||
|
90677=person(personType='NP', familyName='Henning', givenName='Eike'),
|
||||||
|
90698=person(personType='NP', familyName='Henning', givenName='Jan')
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=debitor(D-1001700: rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael'), mih),
|
100=debitor(D-1000300: rel(anchor='?? Michael Mellis', type='DEBITOR', holder='?? Michael Mellis'), mim),
|
||||||
20=debitor(D-1002000: rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH'), xyz),
|
120=debitor(D-1002000: rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH'), xyz),
|
||||||
22=debitor(D-1102200: rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS'), xxx),
|
122=debitor(D-1102200: rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS'), xxx),
|
||||||
90=debitor(D-1909000: rel(anchor='NP Camus, Cecilia', type='DEBITOR', holder='NP Camus, Cecilia'), yyy),
|
132=debitor(D-1015200: rel(anchor='?? Ragnar IT-Beratung', type='DEBITOR', holder='?? Ragnar IT-Beratung'), rar),
|
||||||
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz)
|
190=debitor(D-1909000: rel(anchor='NP Camus, Cecilia', type='DEBITOR', holder='NP Camus, Cecilia'), yyy),
|
||||||
|
199=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz),
|
||||||
|
213=debitor(D-1000000: rel(anchor='LP Hostsharing e.G.', type='DEBITOR', holder='LP Hostsharing e.G.'), hsh),
|
||||||
|
541=debitor(D-1101800: rel(anchor='?? Wasserwerk Südholstein', type='DEBITOR', holder='?? Wasserwerk Südholstein'), wws),
|
||||||
|
542=debitor(D-1101900: rel(anchor='?? Das Perfekte Haus', type='DEBITOR', holder='?? Das Perfekte Haus'), dph)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=Membership(M-1001700, P-10017, [2000-12-06,), ACTIVE),
|
100=Membership(M-1000300, P-10003, [2000-12-06,), ACTIVE),
|
||||||
20=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
|
120=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
|
||||||
22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE)
|
122=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE),
|
||||||
|
132=Membership(M-1015200, P-10152, [2003-07-12,), ACTIVE),
|
||||||
|
541=Membership(M-1101800, P-11018, [2021-05-17,), ACTIVE),
|
||||||
|
542=Membership(M-1101900, P-11019, [2021-05-25,), ACTIVE)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(relations)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(relations)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
2000000=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000000=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
2000001=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000001=rel(anchor='?? Michael Mellis', type='DEBITOR', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
2000002=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000002=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='?? Ragnar IT-Beratung', contact='Herr Ragnar Richter , Ragnar IT-Beratung'),
|
||||||
2000003=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
|
2000003=rel(anchor='?? Ragnar IT-Beratung', type='DEBITOR', holder='?? Ragnar IT-Beratung', contact='Herr Ragnar Richter , Ragnar IT-Beratung'),
|
||||||
2000004=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000004=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='LP Hostsharing e.G.', contact='Firma Hostmaster Hostsharing , Hostsharing e.G.'),
|
||||||
2000005=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000005=rel(anchor='LP Hostsharing e.G.', type='DEBITOR', holder='LP Hostsharing e.G.', contact='Firma Hostmaster Hostsharing , Hostsharing e.G.'),
|
||||||
2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus '),
|
2000006=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='?? Wasserwerk Südholstein', contact='Frau Christiane Milberg , Wasserwerk Südholstein'),
|
||||||
2000007=rel(anchor='NP Camus, Cecilia', type='DEBITOR', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus '),
|
2000007=rel(anchor='?? Wasserwerk Südholstein', type='DEBITOR', holder='?? Wasserwerk Südholstein', contact='Frau Christiane Milberg , Wasserwerk Südholstein'),
|
||||||
2000008=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'),
|
2000008=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='?? Das Perfekte Haus', contact='Herr Richard Wiese , Das Perfekte Haus'),
|
||||||
2000009=rel(anchor='null null, null', type='DEBITOR'),
|
2000009=rel(anchor='?? Das Perfekte Haus', type='DEBITOR', holder='?? Das Perfekte Haus', contact='Herr Inhaber R. Wiese , Das Perfekte Haus'),
|
||||||
2000010=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000010=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
2000011=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000011=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
|
||||||
2000012=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
|
2000012=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
2000013=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000013=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
2000014=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000014=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus '),
|
||||||
2000015=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000015=rel(anchor='NP Camus, Cecilia', type='DEBITOR', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus '),
|
||||||
2000016=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000016=rel(anchor='LP Hostsharing e.G.', type='PARTNER', holder='null null, null'),
|
||||||
2000017=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000017=rel(anchor='null null, null', type='DEBITOR'),
|
||||||
2000018=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000018=rel(anchor='LP Hostsharing e.G.', type='OPERATIONS', holder='LP Hostsharing e.G.', contact='Firma Hostmaster Hostsharing , Hostsharing e.G.'),
|
||||||
2000019=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
|
2000019=rel(anchor='LP Hostsharing e.G.', type='REPRESENTATIVE', holder='LP Hostsharing e.G.', contact='Firma Hostmaster Hostsharing , Hostsharing e.G.'),
|
||||||
2000020=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000020=rel(anchor='?? Michael Mellis', type='OPERATIONS', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
2000021=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000021=rel(anchor='?? Michael Mellis', type='REPRESENTATIVE', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
2000022=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga '),
|
2000022=rel(anchor='?? Michael Mellis', type='SUBSCRIBER', mark='operations-discussion', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
2000023=rel(anchor='NP Camus, Cecilia', type='OPERATIONS', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus '),
|
2000023=rel(anchor='?? Michael Mellis', type='SUBSCRIBER', mark='operations-announce', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
2000024=rel(anchor='NP Camus, Cecilia', type='REPRESENTATIVE', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus ')
|
2000024=rel(anchor='?? Michael Mellis', type='SUBSCRIBER', mark='generalversammlung', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
|
2000025=rel(anchor='?? Michael Mellis', type='SUBSCRIBER', mark='members-announce', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
|
2000026=rel(anchor='?? Michael Mellis', type='SUBSCRIBER', mark='members-discussion', holder='?? Michael Mellis', contact='Herr Michael Mellis , Michael Mellis'),
|
||||||
|
2000027=rel(anchor='?? Ragnar IT-Beratung', type='OPERATIONS', holder='?? Ragnar IT-Beratung', contact='Herr Ragnar Richter , Ragnar IT-Beratung'),
|
||||||
|
2000028=rel(anchor='?? Ragnar IT-Beratung', type='SUBSCRIBER', mark='operations-discussion', holder='?? Ragnar IT-Beratung', contact='Herr Ragnar Richter , Ragnar IT-Beratung'),
|
||||||
|
2000029=rel(anchor='?? Ragnar IT-Beratung', type='SUBSCRIBER', mark='operations-announce', holder='?? Ragnar IT-Beratung', contact='Herr Ragnar Richter , Ragnar IT-Beratung'),
|
||||||
|
2000030=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
|
||||||
|
2000031=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
|
2000032=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
|
2000033=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
|
2000034=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
|
2000035=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
|
2000036=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
|
2000037=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
|
||||||
|
2000038=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
|
2000039=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
|
2000040=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga '),
|
||||||
|
2000041=rel(anchor='NP Camus, Cecilia', type='OPERATIONS', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus '),
|
||||||
|
2000042=rel(anchor='NP Camus, Cecilia', type='REPRESENTATIVE', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus '),
|
||||||
|
2000043=rel(anchor='?? Wasserwerk Südholstein', type='REPRESENTATIVE', holder='?? Wasserwerk Südholstein', contact='Frau Christiane Milberg , Wasserwerk Südholstein'),
|
||||||
|
2000044=rel(anchor='?? Wasserwerk Südholstein', type='SUBSCRIBER', mark='generalversammlung', holder='?? Wasserwerk Südholstein', contact='Frau Christiane Milberg , Wasserwerk Südholstein'),
|
||||||
|
2000045=rel(anchor='?? Wasserwerk Südholstein', type='SUBSCRIBER', mark='members-announce', holder='?? Wasserwerk Südholstein', contact='Frau Christiane Milberg , Wasserwerk Südholstein'),
|
||||||
|
2000046=rel(anchor='?? Wasserwerk Südholstein', type='SUBSCRIBER', mark='members-discussion', holder='?? Wasserwerk Südholstein', contact='Frau Christiane Milberg , Wasserwerk Südholstein'),
|
||||||
|
2000047=rel(anchor='?? Das Perfekte Haus', type='OPERATIONS', holder='?? Das Perfekte Haus', contact='Herr Richard Wiese , Das Perfekte Haus'),
|
||||||
|
2000048=rel(anchor='?? Das Perfekte Haus', type='REPRESENTATIVE', holder='?? Das Perfekte Haus', contact='Herr Richard Wiese , Das Perfekte Haus'),
|
||||||
|
2000049=rel(anchor='?? Das Perfekte Haus', type='SUBSCRIBER', mark='operations-discussion', holder='?? Das Perfekte Haus', contact='Herr Richard Wiese , Das Perfekte Haus'),
|
||||||
|
2000050=rel(anchor='?? Das Perfekte Haus', type='SUBSCRIBER', mark='operations-announce', holder='?? Das Perfekte Haus', contact='Herr Richard Wiese , Das Perfekte Haus'),
|
||||||
|
2000051=rel(anchor='?? Das Perfekte Haus', type='SUBSCRIBER', mark='generalversammlung', holder='?? Das Perfekte Haus', contact='Herr Richard Wiese , Das Perfekte Haus'),
|
||||||
|
2000052=rel(anchor='?? Das Perfekte Haus', type='SUBSCRIBER', mark='members-announce', holder='?? Das Perfekte Haus', contact='Herr Richard Wiese , Das Perfekte Haus'),
|
||||||
|
2000053=rel(anchor='?? Das Perfekte Haus', type='SUBSCRIBER', mark='members-discussion', holder='?? Das Perfekte Haus', contact='Herr Richard Wiese , Das Perfekte Haus'),
|
||||||
|
2000054=rel(anchor='?? Wasserwerk Südholstein', type='OPERATIONS', holder='?? Wasswerwerk Südholstein', contact='Herr Karim Metzger , Wasswerwerk Südholstein'),
|
||||||
|
2000055=rel(anchor='?? Wasserwerk Südholstein', type='SUBSCRIBER', mark='operations-discussion', holder='?? Wasswerwerk Südholstein', contact='Herr Karim Metzger , Wasswerwerk Südholstein'),
|
||||||
|
2000056=rel(anchor='?? Wasserwerk Südholstein', type='SUBSCRIBER', mark='operations-announce', holder='?? Wasswerwerk Südholstein', contact='Herr Karim Metzger , Wasswerwerk Südholstein'),
|
||||||
|
2000057=rel(anchor='?? Ragnar IT-Beratung', type='REPRESENTATIVE', holder='NP Richter, Ragnar', contact='Ragnar Richter '),
|
||||||
|
2000058=rel(anchor='?? Ragnar IT-Beratung', type='SUBSCRIBER', mark='generalversammlung', holder='NP Richter, Ragnar', contact='Ragnar Richter '),
|
||||||
|
2000059=rel(anchor='?? Ragnar IT-Beratung', type='SUBSCRIBER', mark='members-announce', holder='NP Richter, Ragnar', contact='Ragnar Richter '),
|
||||||
|
2000060=rel(anchor='?? Ragnar IT-Beratung', type='SUBSCRIBER', mark='members-discussion', holder='NP Richter, Ragnar', contact='Ragnar Richter '),
|
||||||
|
2000061=rel(anchor='?? Ragnar IT-Beratung', type='OPERATIONS', holder='NP Henning, Eike', contact='Eike Henning '),
|
||||||
|
2000062=rel(anchor='?? Ragnar IT-Beratung', type='SUBSCRIBER', mark='operations-discussion', holder='NP Henning, Eike', contact='Eike Henning '),
|
||||||
|
2000063=rel(anchor='?? Ragnar IT-Beratung', type='SUBSCRIBER', mark='operations-announce', holder='NP Henning, Eike', contact='Eike Henning '),
|
||||||
|
2000064=rel(anchor='?? Ragnar IT-Beratung', type='OPERATIONS', holder='NP Henning, Jan', contact='Jan Henning ')
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -322,8 +359,9 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
@Order(1030)
|
@Order(1030)
|
||||||
void importSepaMandates() {
|
void importSepaMandates() {
|
||||||
|
assumeThatWeAreExplicitlyImportingOfficeData();
|
||||||
|
|
||||||
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "sepa-mandates.csv")) {
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/office/sepa_mandates.csv")) {
|
||||||
final var lines = readAllLines(reader);
|
final var lines = readAllLines(reader);
|
||||||
importSepaMandates(justHeader(lines), withoutHeader(lines));
|
importSepaMandates(justHeader(lines), withoutHeader(lines));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -334,20 +372,29 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
@Order(1039)
|
@Order(1039)
|
||||||
void verifySepaMandates() {
|
void verifySepaMandates() {
|
||||||
|
assumeThatWeAreExplicitlyImportingOfficeData();
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
assertThat(toFormattedString(bankAccounts)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(bankAccounts)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
234234=bankAccount(DE37500105177419788228: holder='Michael Mellies', bic='INGDDEFFXXX'),
|
132=bankAccount(DE37500105177419788228: holder='Michael Mellis', bic='GENODEF1HH2'),
|
||||||
|
234234=bankAccount(DE37500105177419788228: holder='Michael Mellis', bic='INGDDEFFXXX'),
|
||||||
235600=bankAccount(DE02300209000106531065: holder='JM e.K.', bic='CMCIDEDD'),
|
235600=bankAccount(DE02300209000106531065: holder='JM e.K.', bic='CMCIDEDD'),
|
||||||
235662=bankAccount(DE49500105174516484892: holder='JM GmbH', bic='INGDDEFFXXX')
|
235662=bankAccount(DE49500105174516484892: holder='JM GmbH', bic='INGDDEFFXXX'),
|
||||||
|
30=bankAccount(DE02300209000106531065: holder='Ragnar Richter', bic='GENODEM1GLS'),
|
||||||
|
386=bankAccount(DE49500105174516484892: holder='Wasserwerk Suedholstein', bic='NOLADE21WHO'),
|
||||||
|
387=bankAccount(DE89370400440532013000: holder='Richard Wiese Das Perfekte Haus', bic='COBADEFFXXX')
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(sepaMandates)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(sepaMandates)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
|
132=SEPA-Mandate(DE37500105177419788228, HS-10003-20140801, 2013-12-01, [2013-12-01,)),
|
||||||
234234=SEPA-Mandate(DE37500105177419788228, MH12345, 2004-06-12, [2004-06-15,)),
|
234234=SEPA-Mandate(DE37500105177419788228, MH12345, 2004-06-12, [2004-06-15,)),
|
||||||
235600=SEPA-Mandate(DE02300209000106531065, JM33344, 2004-01-15, [2004-01-20,2005-06-28)),
|
235600=SEPA-Mandate(DE02300209000106531065, JM33344, 2004-01-15, [2004-01-20,2005-06-28)),
|
||||||
235662=SEPA-Mandate(DE49500105174516484892, JM33344, 2005-06-28, [2005-07-01,))
|
235662=SEPA-Mandate(DE49500105174516484892, JM33344, 2005-06-28, [2005-07-01,)),
|
||||||
|
30=SEPA-Mandate(DE02300209000106531065, HS-10152-20140801, 2013-12-01, [2013-12-01,2016-02-16)),
|
||||||
|
386=SEPA-Mandate(DE49500105174516484892, HS-11018-20210512, 2021-05-12, [2021-05-17,)),
|
||||||
|
387=SEPA-Mandate(DE89370400440532013000, HS-11019-20210519, 2021-05-19, [2021-05-25,))
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -355,7 +402,9 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
@Order(1040)
|
@Order(1040)
|
||||||
void importCoopShares() {
|
void importCoopShares() {
|
||||||
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "share-transactions.csv")) {
|
assumeThatWeAreExplicitlyImportingOfficeData();
|
||||||
|
|
||||||
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/office/share_transactions.csv")) {
|
||||||
final var lines = readAllLines(reader);
|
final var lines = readAllLines(reader);
|
||||||
importCoopShares(justHeader(lines), withoutHeader(lines));
|
importCoopShares(justHeader(lines), withoutHeader(lines));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -366,14 +415,22 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
@Order(1041)
|
@Order(1041)
|
||||||
void verifyCoopShares() {
|
void verifyCoopShares() {
|
||||||
|
assumeThatWeAreExplicitlyImportingOfficeData();
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
assertThat(toFormattedString(coopShares)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(coopShares)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
33443=CoopShareTransaction(M-1001700: 2000-12-06, SUBSCRIPTION, 20, 1001700, initial share subscription),
|
241=CoopShareTransaction(M-1000300: 2011-12-05, SUBSCRIPTION, 16, 1000300),
|
||||||
|
279=CoopShareTransaction(M-1015200: 2013-10-21, SUBSCRIPTION, 1, 1015200),
|
||||||
33451=CoopShareTransaction(M-1002000: 2000-12-06, SUBSCRIPTION, 2, 1002000, initial share subscription),
|
33451=CoopShareTransaction(M-1002000: 2000-12-06, SUBSCRIPTION, 2, 1002000, initial share subscription),
|
||||||
33701=CoopShareTransaction(M-1001700: 2005-01-10, SUBSCRIPTION, 40, 1001700, increase),
|
33701=CoopShareTransaction(M-1000300: 2005-01-10, SUBSCRIPTION, 40, 1000300, increase),
|
||||||
33810=CoopShareTransaction(M-1002000: 2016-12-31, CANCELLATION, 22, 1002000, membership ended)
|
33810=CoopShareTransaction(M-1002000: 2016-12-31, CANCELLATION, 22, 1002000, membership ended),
|
||||||
|
3=CoopShareTransaction(M-1000300: 2000-12-06, SUBSCRIPTION, 80, 1000300, initial share subscription),
|
||||||
|
523=CoopShareTransaction(M-1000300: 2020-12-08, SUBSCRIPTION, 96, 1000300, Kapitalerhoehung),
|
||||||
|
562=CoopShareTransaction(M-1101800: 2021-05-17, SUBSCRIPTION, 4, 1101800, Beitritt),
|
||||||
|
563=CoopShareTransaction(M-1101900: 2021-05-25, SUBSCRIPTION, 1, 1101900, Beitritt),
|
||||||
|
721=CoopShareTransaction(M-1000300: 2023-10-10, SUBSCRIPTION, 96, 1000300, Kapitalerhoehung),
|
||||||
|
90=CoopShareTransaction(M-1015200: 2003-07-12, SUBSCRIPTION, 1, 1015200)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -381,8 +438,9 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
@Order(1050)
|
@Order(1050)
|
||||||
void importCoopAssets() {
|
void importCoopAssets() {
|
||||||
|
assumeThatWeAreExplicitlyImportingOfficeData();
|
||||||
|
|
||||||
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "asset-transactions.csv")) {
|
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/office/asset_transactions.csv")) {
|
||||||
final var lines = readAllLines(reader);
|
final var lines = readAllLines(reader);
|
||||||
importCoopAssets(justHeader(lines), withoutHeader(lines));
|
importCoopAssets(justHeader(lines), withoutHeader(lines));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -393,20 +451,29 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
@Order(1059)
|
@Order(1059)
|
||||||
void verifyCoopAssets() {
|
void verifyCoopAssets() {
|
||||||
|
assumeThatWeAreExplicitlyImportingOfficeData();
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
assertThat(toFormattedString(coopAssets)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(coopAssets)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
30000=CoopAssetsTransaction(M-1001700: 2000-12-06, DEPOSIT, 1280.00, 1001700, for subscription A),
|
1093=CoopAssetsTransaction(M-1000300: 2023-10-05, DEPOSIT, 3072, 1000300, Kapitalerhoehung - Ueberweisung),
|
||||||
|
1094=CoopAssetsTransaction(M-1000300: 2023-10-06, DEPOSIT, 3072, 1000300, Kapitalerhoehung - Ueberweisung),
|
||||||
31000=CoopAssetsTransaction(M-1002000: 2000-12-06, DEPOSIT, 128.00, 1002000, for subscription B),
|
31000=CoopAssetsTransaction(M-1002000: 2000-12-06, DEPOSIT, 128.00, 1002000, for subscription B),
|
||||||
32000=CoopAssetsTransaction(M-1001700: 2005-01-10, DEPOSIT, 2560.00, 1001700, for subscription C),
|
32000=CoopAssetsTransaction(M-1000300: 2005-01-10, DEPOSIT, 2560.00, 1000300, for subscription C),
|
||||||
33001=CoopAssetsTransaction(M-1001700: 2005-01-10, TRANSFER, -512.00, 1001700, for transfer to 10),
|
33001=CoopAssetsTransaction(M-1000300: 2005-01-10, TRANSFER, -512.00, 1000300, for transfer to 10),
|
||||||
33002=CoopAssetsTransaction(M-1002000: 2005-01-10, ADOPTION, 512.00, 1002000, for transfer from 7),
|
33002=CoopAssetsTransaction(M-1002000: 2005-01-10, ADOPTION, 512.00, 1002000, for transfer from 7),
|
||||||
34001=CoopAssetsTransaction(M-1002000: 2016-12-31, CLEARING, -8.00, 1002000, for cancellation D),
|
34001=CoopAssetsTransaction(M-1002000: 2016-12-31, CLEARING, -8.00, 1002000, for cancellation D),
|
||||||
34002=CoopAssetsTransaction(M-1002000: 2016-12-31, DISBURSAL, -100.00, 1002000, for cancellation D),
|
34002=CoopAssetsTransaction(M-1002000: 2016-12-31, DISBURSAL, -100.00, 1002000, for cancellation D),
|
||||||
34003=CoopAssetsTransaction(M-1002000: 2016-12-31, LOSS, -20.00, 1002000, for cancellation D),
|
34003=CoopAssetsTransaction(M-1002000: 2016-12-31, LOSS, -20.00, 1002000, for cancellation D),
|
||||||
35001=CoopAssetsTransaction(M-1909000: 2024-01-15, DEPOSIT, 128.00, 1909000, for subscription E),
|
35001=CoopAssetsTransaction(M-1909000: 2024-01-15, DEPOSIT, 128.00, 1909000, for subscription E),
|
||||||
35002=CoopAssetsTransaction(M-1909000: 2024-01-20, ADJUSTMENT, -128.00, 1909000, chargeback for subscription E, M-1909000:DEP:+128.00)
|
35002=CoopAssetsTransaction(M-1909000: 2024-01-20, ADJUSTMENT, -128.00, 1909000, chargeback for subscription E, M-1909000:DEP:+128.00),
|
||||||
|
358=CoopAssetsTransaction(M-1000300: 2000-12-06, DEPOSIT, 5120, 1000300, for subscription A),
|
||||||
|
442=CoopAssetsTransaction(M-1015200: 2003-07-07, DEPOSIT, 64, 1015200),
|
||||||
|
577=CoopAssetsTransaction(M-1000300: 2011-12-12, DEPOSIT, 1024, 1000300),
|
||||||
|
632=CoopAssetsTransaction(M-1015200: 2013-10-21, DEPOSIT, 64, 1015200),
|
||||||
|
885=CoopAssetsTransaction(M-1000300: 2020-12-15, DEPOSIT, 6144, 1000300, Einzahlung),
|
||||||
|
924=CoopAssetsTransaction(M-1101800: 2021-05-21, DEPOSIT, 256, 1101800, Beitritt - Lastschrift),
|
||||||
|
925=CoopAssetsTransaction(M-1101900: 2021-05-31, DEPOSIT, 64, 1101900, Beitritt - Lastschrift)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -414,13 +481,18 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
@Order(1099)
|
@Order(1099)
|
||||||
void verifyMemberships() {
|
void verifyMemberships() {
|
||||||
|
assumeThatWeAreExplicitlyImportingOfficeData();
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=Membership(M-1001700, P-10017, [2000-12-06,), ACTIVE),
|
100=Membership(M-1000300, P-10003, [2000-12-06,), ACTIVE),
|
||||||
20=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
|
120=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
|
||||||
22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE),
|
122=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE),
|
||||||
90=Membership(M-1909000, P-19090, empty, INVALID)
|
132=Membership(M-1015200, P-10152, [2003-07-12,), ACTIVE),
|
||||||
|
190=Membership(M-1909000, P-19090, empty, INVALID),
|
||||||
|
541=Membership(M-1101800, P-11018, [2021-05-17,), ACTIVE),
|
||||||
|
542=Membership(M-1101900, P-11019, [2021-05-25,), ACTIVE)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -431,11 +503,11 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
partners.forEach((id, p) -> {
|
partners.forEach((id, p) -> {
|
||||||
final var partnerRel = p.getPartnerRel();
|
final var partnerRel = p.getPartnerRel();
|
||||||
assertThat(partnerRel).describedAs("partner " + id + " without partnerRel").isNotNull();
|
assertThat(partnerRel).describedAs("partner " + id + " without partnerRel").isNotNull();
|
||||||
if ( id != 99 ) {
|
if ( id != 199 ) {
|
||||||
assertThat(partnerRel.getContact()).describedAs("partner " + id + " without partnerRel.contact").isNotNull();
|
logError( () -> assertThat(partnerRel.getContact()).describedAs("partner " + id + " without partnerRel.contact").isNotNull());
|
||||||
assertThat(partnerRel.getContact().getCaption()).describedAs("partner " + id + " without valid partnerRel.contact").isNotNull();
|
logError( () -> assertThat(partnerRel.getContact().getCaption()).describedAs("partner " + id + " without valid partnerRel.contact").isNotNull());
|
||||||
assertThat(partnerRel.getHolder()).describedAs("partner " + id + " without partnerRel.relHolder").isNotNull();
|
logError( () -> assertThat(partnerRel.getHolder()).describedAs("partner " + id + " without partnerRel.relHolder").isNotNull());
|
||||||
assertThat(partnerRel.getHolder().getPersonType()).describedAs("partner " + id + " without valid partnerRel.relHolder").isNotNull();
|
logError( () -> assertThat(partnerRel.getHolder().getPersonType()).describedAs("partner " + id + " without valid partnerRel.relHolder").isNotNull());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -523,13 +595,29 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(9000)
|
@Order(3005)
|
||||||
@Commit
|
void removeEmptyPersons() {
|
||||||
void persistEntities() {
|
// avoid a error when persisting the deliberately invalid partner entry #99
|
||||||
|
final var idsToRemove = new HashSet<Integer>();
|
||||||
|
persons.forEach( (id, p) -> {
|
||||||
|
if ( p.getPersonType() == null ||
|
||||||
|
(p.getFamilyName() == null && p.getGivenName() == null && p.getTradeName() == null) ) {
|
||||||
|
idsToRemove.add(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
idsToRemove.forEach(id -> persons.remove(id));
|
||||||
|
|
||||||
System.out.println("PERSISTING to database '" + jdbcUrl + "' as user '" + postgresAdminUser + "'");
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
assertThat(idsToRemove.size()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(9000)
|
||||||
|
void persistOfficeEntities() {
|
||||||
|
|
||||||
|
System.out.println("PERSISTING office data to database '" + jdbcUrl + "' as user '" + postgresAdminUser + "'");
|
||||||
deleteTestDataFromHsOfficeTables();
|
deleteTestDataFromHsOfficeTables();
|
||||||
resetFromHsOfficeSequences();
|
resetHsOfficeSequences();
|
||||||
deleteFromTestTables();
|
deleteFromTestTables();
|
||||||
deleteFromRbacTables();
|
deleteFromRbacTables();
|
||||||
|
|
||||||
@ -542,6 +630,8 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
context(rbacSuperuser);
|
context(rbacSuperuser);
|
||||||
persons.forEach(this::persist);
|
persons.forEach(this::persist);
|
||||||
|
relations.forEach( (id, rel) -> this.persist(id, rel.getAnchor()) );
|
||||||
|
relations.forEach( (id, rel) -> this.persist(id, rel.getHolder()) );
|
||||||
}).assertSuccessful();
|
}).assertSuccessful();
|
||||||
|
|
||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
@ -602,18 +692,8 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void persist(final Integer id, final RbacObject entity) {
|
protected void assumeThatWeAreExplicitlyImportingOfficeData() {
|
||||||
try {
|
// not throwing AssumptionException
|
||||||
//System.out.println("persisting #" + entity.hashCode() + ": " + entity);
|
|
||||||
em.persist(entity);
|
|
||||||
// uncomment for debugging purposes
|
|
||||||
// em.flush();
|
|
||||||
// System.out.println("persisted #" + entity.hashCode() + " as " + entity.getUuid());
|
|
||||||
} catch (Exception exc) {
|
|
||||||
System.err.println("failed to persist #" + entity.hashCode() + ": " + entity);
|
|
||||||
System.err.println(exc);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isImportingControlledTestData() {
|
private static boolean isImportingControlledTestData() {
|
||||||
@ -624,62 +704,6 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
assumeThat(partners.size()).isLessThanOrEqualTo(MAX_NUMBER_OF_TEST_DATA_PARTNERS);
|
assumeThat(partners.size()).isLessThanOrEqualTo(MAX_NUMBER_OF_TEST_DATA_PARTNERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteTestDataFromHsOfficeTables() {
|
|
||||||
jpaAttempt.transacted(() -> {
|
|
||||||
context(rbacSuperuser);
|
|
||||||
em.createNativeQuery("delete from hs_hosting_asset where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_booking_item where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_booking_project where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_coopassetstransaction where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_coopassetstransaction_legacy_id where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_coopsharestransaction where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_coopsharestransaction_legacy_id where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_membership where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_sepamandate where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_sepamandate_legacy_id where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_debitor where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_bankaccount where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_partner where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_partner_details where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_relation where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_contact where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from hs_office_person where true").executeUpdate();
|
|
||||||
}).assertSuccessful();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetFromHsOfficeSequences() {
|
|
||||||
jpaAttempt.transacted(() -> {
|
|
||||||
context(rbacSuperuser);
|
|
||||||
em.createNativeQuery("alter sequence hs_office_contact_legacy_id_seq restart with 1000000000;").executeUpdate();
|
|
||||||
em.createNativeQuery("alter sequence hs_office_coopassetstransaction_legacy_id_seq restart with 1000000000;")
|
|
||||||
.executeUpdate();
|
|
||||||
em.createNativeQuery("alter sequence public.hs_office_coopsharestransaction_legacy_id_seq restart with 1000000000;")
|
|
||||||
.executeUpdate();
|
|
||||||
em.createNativeQuery("alter sequence public.hs_office_partner_legacy_id_seq restart with 1000000000;")
|
|
||||||
.executeUpdate();
|
|
||||||
em.createNativeQuery("alter sequence public.hs_office_sepamandate_legacy_id_seq restart with 1000000000;")
|
|
||||||
.executeUpdate();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteFromTestTables() {
|
|
||||||
jpaAttempt.transacted(() -> {
|
|
||||||
context(rbacSuperuser);
|
|
||||||
em.createNativeQuery("delete from test_domain where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from test_package where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from test_customer where true").executeUpdate();
|
|
||||||
}).assertSuccessful();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteFromRbacTables() {
|
|
||||||
jpaAttempt.transacted(() -> {
|
|
||||||
context(rbacSuperuser);
|
|
||||||
em.createNativeQuery("delete from rbacuser_rv where name not like 'superuser-%'").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from tx_journal where true").executeUpdate();
|
|
||||||
em.createNativeQuery("delete from tx_context where true").executeUpdate();
|
|
||||||
}).assertSuccessful();
|
|
||||||
}
|
|
||||||
|
|
||||||
private <E extends RbacObject> void updateLegacyIds(
|
private <E extends RbacObject> void updateLegacyIds(
|
||||||
Map<Integer, E> entities,
|
Map<Integer, E> entities,
|
||||||
final String legacyIdTable,
|
final String legacyIdTable,
|
||||||
@ -698,59 +722,25 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String[]> readAllLines(Reader reader) throws Exception {
|
|
||||||
|
|
||||||
final var parser = new CSVParserBuilder()
|
|
||||||
.withSeparator(';')
|
|
||||||
.withQuoteChar('"')
|
|
||||||
.build();
|
|
||||||
|
|
||||||
final var filteredReader = skippingEmptyAndCommentLines(reader);
|
|
||||||
try (CSVReader csvReader = new CSVReaderBuilder(filteredReader)
|
|
||||||
.withCSVParser(parser)
|
|
||||||
.build()) {
|
|
||||||
return csvReader.readAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Reader skippingEmptyAndCommentLines(Reader reader) throws IOException {
|
|
||||||
try (var bufferedReader = new BufferedReader(reader);
|
|
||||||
StringWriter writer = new StringWriter()) {
|
|
||||||
|
|
||||||
String line;
|
|
||||||
while ((line = bufferedReader.readLine()) != null) {
|
|
||||||
if (!line.isBlank() && !line.startsWith("#")) {
|
|
||||||
writer.write(line);
|
|
||||||
writer.write("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new StringReader(writer.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void importBusinessPartners(final String[] header, final List<String[]> records) {
|
private void importBusinessPartners(final String[] header, final List<String[]> records) {
|
||||||
|
|
||||||
final var columns = new Columns(header);
|
final var columns = new Columns(header);
|
||||||
|
|
||||||
final var mandant = HsOfficePersonEntity.builder()
|
|
||||||
.personType(HsOfficePersonType.LEGAL_PERSON)
|
|
||||||
.tradeName("Hostsharing eG")
|
|
||||||
.build();
|
|
||||||
persons.put(1, mandant);
|
|
||||||
|
|
||||||
records.stream()
|
records.stream()
|
||||||
.map(this::trimAll)
|
.map(this::trimAll)
|
||||||
.map(row -> new Record(columns, row))
|
.map(row -> new Record(columns, row))
|
||||||
.forEach(rec -> {
|
.forEach(rec -> {
|
||||||
if (this.IGNORE_BUSINESS_PARTNERS.contains(rec.getInteger("bp_id"))) {
|
final Integer bpId = rec.getInteger("bp_id");
|
||||||
|
if (IGNORE_BUSINESS_PARTNERS.contains(bpId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final var person = HsOfficePersonEntity.builder().build();
|
final var person = HsOfficePersonEntity.builder().build();
|
||||||
|
|
||||||
final var partnerRel = addRelation(
|
final var partnerRel = addRelation(
|
||||||
HsOfficeRelationType.PARTNER, mandant, person,
|
HsOfficeRelationType.PARTNER,
|
||||||
|
null, // is set after contacts when the person for 'Hostsharing eG' is known
|
||||||
|
person,
|
||||||
null // is set during contacts import depending on assigned roles
|
null // is set during contacts import depending on assigned roles
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -759,7 +749,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||||
.partnerRel(partnerRel)
|
.partnerRel(partnerRel)
|
||||||
.build();
|
.build();
|
||||||
partners.put(rec.getInteger("bp_id"), partner);
|
partners.put(bpId, partner);
|
||||||
|
|
||||||
final var debitorRel = addRelation(
|
final var debitorRel = addRelation(
|
||||||
HsOfficeRelationType.DEBITOR, partnerRel.getHolder(), // partner person
|
HsOfficeRelationType.DEBITOR, partnerRel.getHolder(), // partner person
|
||||||
@ -777,7 +767,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
.vatBusiness("GROSS".equals(rec.getString("indicator_vat"))) // TODO: remove
|
.vatBusiness("GROSS".equals(rec.getString("indicator_vat"))) // TODO: remove
|
||||||
.vatId(rec.getString("uid_vat"))
|
.vatId(rec.getString("uid_vat"))
|
||||||
.build();
|
.build();
|
||||||
debitors.put(rec.getInteger("bp_id"), debitor);
|
debitors.put(bpId, debitor);
|
||||||
|
|
||||||
if (isNotBlank(rec.getString("member_since"))) {
|
if (isNotBlank(rec.getString("member_since"))) {
|
||||||
assertThat(rec.getInteger("member_id")).isEqualTo(partner.getPartnerNumber());
|
assertThat(rec.getInteger("member_id")).isEqualTo(partner.getPartnerNumber());
|
||||||
@ -793,7 +783,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
? HsOfficeMembershipStatus.ACTIVE
|
? HsOfficeMembershipStatus.ACTIVE
|
||||||
: HsOfficeMembershipStatus.UNKNOWN)
|
: HsOfficeMembershipStatus.UNKNOWN)
|
||||||
.build();
|
.build();
|
||||||
memberships.put(rec.getInteger("bp_id"), membership);
|
memberships.put(bpId, membership);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -807,6 +797,10 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
.map(row -> new Record(columns, row))
|
.map(row -> new Record(columns, row))
|
||||||
.forEach(rec -> {
|
.forEach(rec -> {
|
||||||
final var bpId = rec.getInteger("bp_id");
|
final var bpId = rec.getInteger("bp_id");
|
||||||
|
if (IGNORE_BUSINESS_PARTNERS.contains(bpId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final var member = ofNullable(memberships.get(bpId))
|
final var member = ofNullable(memberships.get(bpId))
|
||||||
.orElseGet(() -> createOnDemandMembership(bpId));
|
.orElseGet(() -> createOnDemandMembership(bpId));
|
||||||
|
|
||||||
@ -958,10 +952,10 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
final var contactId = rec.getInteger("contact_id");
|
final var contactId = rec.getInteger("contact_id");
|
||||||
final var bpId = rec.getInteger("bp_id");
|
final var bpId = rec.getInteger("bp_id");
|
||||||
|
|
||||||
if (this.IGNORE_CONTACTS.contains(contactId)) {
|
if (IGNORE_CONTACTS.contains(contactId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.IGNORE_BUSINESS_PARTNERS.contains(bpId)) {
|
if (IGNORE_BUSINESS_PARTNERS.contains(bpId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,6 +1013,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assertNoMissingContractualRelations();
|
assertNoMissingContractualRelations();
|
||||||
|
useHostsharingAsPartnerAnchor();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertNoMissingContractualRelations() {
|
private static void assertNoMissingContractualRelations() {
|
||||||
@ -1038,6 +1033,16 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void useHostsharingAsPartnerAnchor() {
|
||||||
|
final var mandant = persons.values().stream()
|
||||||
|
.filter(p -> p.getTradeName().startsWith("Hostsharing e"))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow();
|
||||||
|
relations.values().stream()
|
||||||
|
.filter(r -> r.getType() == HsOfficeRelationType.PARTNER)
|
||||||
|
.forEach(r -> r.setAnchor(mandant));
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean containsRole(final Record rec, final String role) {
|
private static boolean containsRole(final Record rec, final String role) {
|
||||||
final var roles = rec.getString("roles");
|
final var roles = rec.getString("roles");
|
||||||
return ("," + roles + ",").contains("," + role + ",");
|
return ("," + roles + ",").contains("," + role + ",");
|
||||||
@ -1128,27 +1133,6 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
return contact;
|
return contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <E> String toFormattedString(final Map<Integer, E> map) {
|
|
||||||
if ( map.isEmpty() ) {
|
|
||||||
return "{}";
|
|
||||||
}
|
|
||||||
return "{\n" +
|
|
||||||
map.keySet().stream()
|
|
||||||
.map(id -> " " + id + "=" + map.get(id).toString())
|
|
||||||
.map(e -> e.replaceAll("\n ", " ").replace("\n", ""))
|
|
||||||
.collect(Collectors.joining(",\n")) +
|
|
||||||
"\n}\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] trimAll(final String[] record) {
|
|
||||||
for (int i = 0; i < record.length; ++i) {
|
|
||||||
if (record[i] != null) {
|
|
||||||
record[i] = record[i].trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> toPhoneNumbers(final Record rec) {
|
private Map<String, String> toPhoneNumbers(final Record rec) {
|
||||||
final var phoneNumbers = new LinkedHashMap<String, String>();
|
final var phoneNumbers = new LinkedHashMap<String, String>();
|
||||||
if (isNotBlank(rec.getString("phone_private")))
|
if (isNotBlank(rec.getString("phone_private")))
|
||||||
@ -1218,104 +1202,4 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
private String toName(final String salut, final String title, final String firstname, final String lastname) {
|
private String toName(final String salut, final String title, final String firstname, final String lastname) {
|
||||||
return toCaption(salut, title, firstname, lastname, null);
|
return toCaption(salut, title, firstname, lastname, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Reader resourceReader(@NotNull final String resourcePath) {
|
|
||||||
return new InputStreamReader(requireNonNull(getClass().getClassLoader().getResourceAsStream(resourcePath)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String[] justHeader(final List<String[]> lines) {
|
|
||||||
return stream(lines.getFirst()).map(String::trim).toArray(String[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String[]> withoutHeader(final List<String[]> records) {
|
|
||||||
return records.subList(1, records.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Columns {
|
|
||||||
|
|
||||||
private final List<String> columnNames;
|
|
||||||
|
|
||||||
public Columns(final String[] header) {
|
|
||||||
columnNames = List.of(header);
|
|
||||||
}
|
|
||||||
|
|
||||||
int indexOf(final String columnName) {
|
|
||||||
int index = columnNames.indexOf(columnName);
|
|
||||||
if (index < 0) {
|
|
||||||
throw new RuntimeException("column name '" + columnName + "' not found in: " + columnNames);
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Record {
|
|
||||||
|
|
||||||
private final Columns columns;
|
|
||||||
private final String[] row;
|
|
||||||
|
|
||||||
public Record(final Columns columns, final String[] row) {
|
|
||||||
this.columns = columns;
|
|
||||||
this.row = row;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getString(final String columnName) {
|
|
||||||
return row[columns.indexOf(columnName)];
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isEmpty(final String columnName) {
|
|
||||||
final String value = getString(columnName);
|
|
||||||
return value == null || value.isBlank();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBoolean(final String columnName) {
|
|
||||||
final String value = getString(columnName);
|
|
||||||
return isNotBlank(value) &&
|
|
||||||
( parseBoolean(value.trim()) || value.trim().startsWith("t"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer getInteger(final String columnName) {
|
|
||||||
final String value = getString(columnName);
|
|
||||||
return isNotBlank(value) ? Integer.parseInt(value.trim()) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BigDecimal getBigDecimal(final String columnName) {
|
|
||||||
final String value = getString(columnName);
|
|
||||||
if (isNotBlank(value)) {
|
|
||||||
return new BigDecimal(value);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalDate getLocalDate(final String columnName) {
|
|
||||||
final String dateString = getString(columnName);
|
|
||||||
if (isNotBlank(dateString)) {
|
|
||||||
return LocalDate.parse(dateString);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class OrderedDependedTestsExtension implements TestWatcher, BeforeEachCallback {
|
|
||||||
|
|
||||||
private static boolean previousTestsPassed = true;
|
|
||||||
|
|
||||||
public void testFailed(ExtensionContext context, Throwable cause) {
|
|
||||||
previousTestsPassed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeEach(final ExtensionContext extensionContext) {
|
|
||||||
assumeThat(previousTestsPassed).isTrue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WriteOnceMap<K, V> extends TreeMap<K, V> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V put(final K k, final V v) {
|
|
||||||
assertThat(containsKey(k)).describedAs("overwriting " + get(k) + " index " + k + " with " + v).isFalse();
|
|
||||||
return super.put(k, v);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,11 +0,0 @@
|
|||||||
member_asset_id; bp_id; date; action; amount; comment
|
|
||||||
30000; 17; 2000-12-06; PAYMENT; 1280.00; for subscription A
|
|
||||||
31000; 20; 2000-12-06; PAYMENT; 128.00; for subscription B
|
|
||||||
32000; 17; 2005-01-10; PAYMENT; 2560.00; for subscription C
|
|
||||||
33001; 17; 2005-01-10; HANDOVER; -512.00; for transfer to 10
|
|
||||||
33002; 20; 2005-01-10; ADOPTION; 512.00; for transfer from 7
|
|
||||||
34001; 20; 2016-12-31; CLEARING; -8.00; for cancellation D
|
|
||||||
34002; 20; 2016-12-31; PAYBACK; -100.00; for cancellation D
|
|
||||||
34003; 20; 2016-12-31; LOSS; -20.00; for cancellation D
|
|
||||||
35001; 90; 2024-01-15; PAYMENT; 128.00; for subscription E
|
|
||||||
35002; 90; 2024-01-20; ADJUSTMENT;-128.00; chargeback for subscription E
|
|
|
@ -1,6 +0,0 @@
|
|||||||
bp_id;member_id;member_code;member_since;member_until;member_role;author_contract;nondisc_contract;free;exempt_vat;indicator_vat;uid_vat
|
|
||||||
17;10017;hsh00-mih;2000-12-06;;Aufsichtsrat;2006-10-15;2001-10-15;false;false;NET;DE-VAT-007
|
|
||||||
20;10020;hsh00-xyz;2000-12-06;2015-12-31;;;;false;false;GROSS;
|
|
||||||
22;11022;hsh00-xxx;2021-04-01;;;;;true;true;GROSS;
|
|
||||||
90;19090;hsh00-yyy;;;;;;true;true;GROSS;
|
|
||||||
99;19999;hsh00-zzz;;;;;;false;false;GROSS;
|
|
|
@ -1,20 +0,0 @@
|
|||||||
contact_id; bp_id; salut; first_name; last_name; title; firma; co; street; zipcode;city; country; phone_private; phone_office; phone_mobile; fax; email; roles
|
|
||||||
|
|
||||||
# eine natürliche Person, implizites contractual
|
|
||||||
1101; 17; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; partner,contractual,billing,operation
|
|
||||||
|
|
||||||
# eine juristische Person mit drei separaten Ansprechpartnern, vip-contact und ex-partner
|
|
||||||
1200; 20;; ; ; ; JM e.K.;; Wiesenweg 15; 12335; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; jm-ex-partner@example.org; ex-partner
|
|
||||||
1201; 20; Frau; Jenny; Meyer-Billing; Dr.; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 7777777; +49 30 1111111; ; +49 30 2222222; jm-billing@example.org; billing
|
|
||||||
1202; 20; Herr; Andrew; Meyer-Operation; ; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 3333333; ; +49 30 4444444; am-operation@example.org; operation,vip-contact,subscriber:operations-announce
|
|
||||||
1203; 20; Herr; Philip; Meyer-Contract; ; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; pm-partner@example.org; partner,contractual,subscriber:members-announce,subscriber:customers-announce
|
|
||||||
1204; 20; Frau; Tammy; Meyer-VIP; ; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 999999; +49 30 999999; ; +49 30 6666666; tm-vip@example.org; vip-contact
|
|
||||||
|
|
||||||
# eine juristische Person mit nur einem Ansprechpartner und explizitem contractual
|
|
||||||
1301; 22; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; partner,billing,contractual,operation
|
|
||||||
|
|
||||||
# eine natürliche Person, die nur Subscriber ist
|
|
||||||
1401; 17; Frau; Frauke; Fanninga; ; ; ; Am Walde 1; 29456; Hitzacker; DE; ; ; ;; ff@example.org; subscriber:operations-announce
|
|
||||||
|
|
||||||
# eine natürliche Person als Partner
|
|
||||||
1501; 90; Frau; Cecilia; Camus; ; ; ; Rue d'Avignion 60; 45000; Orléans; FR; ; ; ;; cc@example.org; partner,contractual,billing,operation
|
|
|
@ -20,58 +20,58 @@ dump() {
|
|||||||
dump "select bp_id, member_id, member_code, member_since, member_until, member_role, author_contract, nondisc_contract, free, exempt_vat, indicator_vat, uid_vat
|
dump "select bp_id, member_id, member_code, member_since, member_until, member_role, author_contract, nondisc_contract, free, exempt_vat, indicator_vat, uid_vat
|
||||||
from business_partner
|
from business_partner
|
||||||
order by bp_id" \
|
order by bp_id" \
|
||||||
"business-partners.csv"
|
"office/business_partners.csv"
|
||||||
|
|
||||||
dump "select contact_id, bp_id, salut, first_name, last_name, title, firma, co, street, zipcode, city, country, phone_private, phone_office, phone_mobile, fax, email, array_to_string(array_agg(role), ',') as roles
|
dump "select contact_id, bp_id, salut, first_name, last_name, title, firma, co, street, zipcode, city, country, phone_private, phone_office, phone_mobile, fax, email, array_to_string(array_agg(role), ',') as roles
|
||||||
from contact
|
from contact
|
||||||
left join contactrole_ref using(contact_id)
|
left join contactrole_ref using(contact_id)
|
||||||
group by contact_id
|
group by contact_id
|
||||||
order by contact_id" \
|
order by contact_id" \
|
||||||
"contacts.csv"
|
"office/contacts.csv"
|
||||||
|
|
||||||
dump "select sepa_mandat_id, bp_id, bank_customer, bank_name, bank_iban, bank_bic, mandat_ref, mandat_signed, mandat_since, mandat_until, mandat_used
|
dump "select sepa_mandat_id, bp_id, bank_customer, bank_name, bank_iban, bank_bic, mandat_ref, mandat_signed, mandat_since, mandat_until, mandat_used
|
||||||
from sepa_mandat
|
from sepa_mandat
|
||||||
order by sepa_mandat_id" \
|
order by sepa_mandat_id" \
|
||||||
"sepa-mandates.csv"
|
"office/sepa_mandates.csv"
|
||||||
|
|
||||||
dump "select member_asset_id, bp_id, date, action, amount, comment
|
dump "select member_asset_id, bp_id, date, action, amount, comment
|
||||||
from member_asset
|
from member_asset
|
||||||
WHERE bp_id NOT IN (511912)
|
WHERE bp_id NOT IN (511912)
|
||||||
order by member_asset_id" \
|
order by member_asset_id" \
|
||||||
"asset-transactions.csv"
|
"office/asset_transactions.csv"
|
||||||
|
|
||||||
dump "select member_share_id, bp_id, date, action, quantity, comment
|
dump "select member_share_id, bp_id, date, action, quantity, comment
|
||||||
from member_share
|
from member_share
|
||||||
WHERE bp_id NOT IN (511912)
|
WHERE bp_id NOT IN (511912)
|
||||||
order by member_share_id" \
|
order by member_share_id" \
|
||||||
"share-transactions.csv"
|
"office/share_transactions.csv"
|
||||||
|
|
||||||
dump "select inet_addr_id, inet_addr, description
|
dump "select inet_addr_id, inet_addr, description
|
||||||
from inet_addr
|
from inet_addr
|
||||||
order by inet_addr_id" \
|
order by inet_addr_id" \
|
||||||
"inet_addr.csv"
|
"hosting/inet_addr.csv"
|
||||||
|
|
||||||
dump "select hive_id, hive_name, inet_addr_id, description
|
dump "select hive_id, hive_name, inet_addr_id, description
|
||||||
from hive
|
from hive
|
||||||
order by hive_id" \
|
order by hive_id" \
|
||||||
"hive.csv"
|
"hosting/hive.csv"
|
||||||
|
|
||||||
dump "select packet_id, basepacket_code, packet_name, bp_id, hive_id, created, cancelled, cur_inet_addr_id, old_inet_addr_id, free
|
dump "select packet_id, basepacket_code, packet_name, bp_id, hive_id, created, cancelled, cur_inet_addr_id, old_inet_addr_id, free
|
||||||
from packet
|
from packet
|
||||||
left join basepacket using (basepacket_id)
|
left join basepacket using (basepacket_id)
|
||||||
order by packet_id" \
|
order by packet_id" \
|
||||||
"packet.csv"
|
"hosting/packet.csv"
|
||||||
|
|
||||||
dump "select packet_component_id, packet_id, quantity, basecomponent_code, created, cancelled
|
dump "select packet_component_id, packet_id, quantity, basecomponent_code, created, cancelled
|
||||||
from packet_component
|
from packet_component
|
||||||
left join basecomponent using (basecomponent_id)
|
left join basecomponent using (basecomponent_id)
|
||||||
order by packet_component_id" \
|
order by packet_component_id" \
|
||||||
"packet_component.csv"
|
"hosting/packet_component.csv"
|
||||||
|
|
||||||
dump "select unixuser_id, name, comment, shell, homedir, locked, packet_id, userid, quota_softlimit, quota_hardlimit, storage_softlimit, storage_hardlimit
|
dump "select unixuser_id, name, comment, shell, homedir, locked, packet_id, userid, quota_softlimit, quota_hardlimit, storage_softlimit, storage_hardlimit
|
||||||
from unixuser
|
from unixuser
|
||||||
order by unixuser_id" \
|
order by unixuser_id" \
|
||||||
"unixuser.csv"
|
"hosting/unixuser.csv"
|
||||||
|
|
||||||
# weil das fehlt, muss group by komplett gesetzt werden: alter table domain add constraint PK_domain primary key (domain_id);
|
# weil das fehlt, muss group by komplett gesetzt werden: alter table domain add constraint PK_domain primary key (domain_id);
|
||||||
dump "select domain_id, domain_name, domain_since, domain_dns_master, domain_owner, valid_subdomain_names, passenger_python, passenger_nodejs, passenger_ruby, fcgi_php_bin, array_to_string(array_agg(domain_option_name), ',') as domainoptions
|
dump "select domain_id, domain_name, domain_since, domain_dns_master, domain_owner, valid_subdomain_names, passenger_python, passenger_nodejs, passenger_ruby, fcgi_php_bin, array_to_string(array_agg(domain_option_name), ',') as domainoptions
|
||||||
@ -80,7 +80,7 @@ dump "select domain_id, domain_name, domain_since, domain_dns_master, domain_own
|
|||||||
left join domain_option using (domain_option_id)
|
left join domain_option using (domain_option_id)
|
||||||
group by domain.domain_id, domain.domain_name, domain_since, domain_dns_master, domain_owner, valid_subdomain_names, passenger_python, passenger_nodejs, passenger_ruby, fcgi_php_bin
|
group by domain.domain_id, domain.domain_name, domain_since, domain_dns_master, domain_owner, valid_subdomain_names, passenger_python, passenger_nodejs, passenger_ruby, fcgi_php_bin
|
||||||
order by domain.domain_id" \
|
order by domain.domain_id" \
|
||||||
"domain.csv"
|
"hosting/domain.csv"
|
||||||
|
|
||||||
dump "select emailaddr_id, domain_id, localpart, subdomain, target
|
dump "select emailaddr_id, domain_id, localpart, subdomain, target
|
||||||
from emailaddr
|
from emailaddr
|
||||||
@ -90,14 +90,14 @@ dump "select emailaddr_id, domain_id, localpart, subdomain, target
|
|||||||
dump "select emailalias_id, pac_id, name, target
|
dump "select emailalias_id, pac_id, name, target
|
||||||
from emailalias
|
from emailalias
|
||||||
order by emailalias_id" \
|
order by emailalias_id" \
|
||||||
"emailalias.csv"
|
"hosting/emailalias.csv"
|
||||||
|
|
||||||
dump "select dbuser_id, engine, packet_id, name
|
dump "select dbuser_id, engine, packet_id, name
|
||||||
from database_user
|
from database_user
|
||||||
order by dbuser_id" \
|
order by dbuser_id" \
|
||||||
"database_user.csv"
|
"hosting/database_user.csv"
|
||||||
|
|
||||||
dump "select database_id, engine, packet_id, name, owner, encoding
|
dump "select database_id, engine, packet_id, name, owner, encoding
|
||||||
from database
|
from database
|
||||||
order by database_id" \
|
order by database_id" \
|
||||||
"database.csv"
|
"hosting/database.csv"
|
||||||
|
26
src/test/resources/migration/hosting/hive.csv
Normal file
26
src/test/resources/migration/hosting/hive.csv
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
hive_id;hive_name;inet_addr_id;description
|
||||||
|
1;h00;358;
|
||||||
|
2;h01;359;
|
||||||
|
4;h02;360;
|
||||||
|
7;h03;361;
|
||||||
|
13;h04;430;
|
||||||
|
14;h50;433;
|
||||||
|
20;h05;354;
|
||||||
|
21;h06;355;
|
||||||
|
22;h07;357;
|
||||||
|
28;h60;363;
|
||||||
|
31;h63;431;
|
||||||
|
37;h67;381;
|
||||||
|
38;h97;537;
|
||||||
|
39;h96;536;
|
||||||
|
45;h74;485;
|
||||||
|
50;h82;514;
|
||||||
|
128;h19;565;
|
||||||
|
148;h50;522;
|
||||||
|
163;h92;457;
|
||||||
|
173;h25;1759;
|
||||||
|
192;h93;1778;
|
||||||
|
193;h95;1779;
|
||||||
|
205;vm1107;1861;
|
||||||
|
208;vm1110;1864;
|
||||||
|
210;vm1112;1833;
|
|
10
src/test/resources/migration/hosting/inet_addr.csv
Normal file
10
src/test/resources/migration/hosting/inet_addr.csv
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
inet_addr_id;inet_addr;description
|
||||||
|
363;83.223.95.34;
|
||||||
|
381;83.223.95.52;
|
||||||
|
402;83.223.95.73;
|
||||||
|
433;83.223.95.104;
|
||||||
|
457;83.223.95.128;
|
||||||
|
473;83.223.95.144;
|
||||||
|
574;83.223.95.245;
|
||||||
|
1168;83.223.79.72;
|
||||||
|
1790;83.223.94.179;
|
|
10
src/test/resources/migration/hosting/packet.csv
Normal file
10
src/test/resources/migration/hosting/packet.csv
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
packet_id;basepacket_code;packet_name;bp_id;hive_id;created;cancelled;cur_inet_addr_id;old_inet_addr_id;free
|
||||||
|
630;PAC/WEB;hsh00;213;14;2001-06-01;;473;;1
|
||||||
|
968;SRV/MGD;vm1061;132;28;2013-04-01;;363;;0
|
||||||
|
978;SRV/MGD;vm1050;213;14;2013-04-01;;433;;1
|
||||||
|
1061;SRV/MGD;vm1068;100;37;2013-08-19;;381;;f
|
||||||
|
1094;PAC/WEB;lug00;100;37;2013-09-10;;1168;;1
|
||||||
|
1112;PAC/WEB;mim00;100;37;2013-09-17;;402;;1
|
||||||
|
1447;SRV/MGD;vm1093;213;163;2014-11-28;;457;;t
|
||||||
|
19959;PAC/WEB;dph00;542;163;2021-06-02;;574;;0
|
||||||
|
23611;SRV/CLD;vm2097;541;;2022-08-10;;1790;;0
|
|
143
src/test/resources/migration/hosting/packet_component.csv
Normal file
143
src/test/resources/migration/hosting/packet_component.csv
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
packet_component_id;packet_id;quantity;basecomponent_code;created;cancelled
|
||||||
|
46105;1094;10;TRAFFIC;2017-03-27;
|
||||||
|
46109;1094;5;MULTI;2017-03-27;
|
||||||
|
46111;1094;0;DAEMON;2017-03-27;
|
||||||
|
46113;1094;1024;QUOTA;2017-03-27;
|
||||||
|
46117;1112;0;DAEMON;2017-03-27;
|
||||||
|
46121;1112;20;TRAFFIC;2017-03-27;
|
||||||
|
46122;1112;5;MULTI;2017-03-27;
|
||||||
|
46123;1112;3072;QUOTA;2017-03-27;
|
||||||
|
143133;1094;1;SLABASIC;2017-09-01;
|
||||||
|
143483;1112;1;SLABASIC;2017-09-01;
|
||||||
|
757383;1112;0;SLAEXT24H;;
|
||||||
|
770533;1094;0;SLAEXT24H;;
|
||||||
|
784283;1112;0;OFFICE;;
|
||||||
|
797433;1094;0;OFFICE;;
|
||||||
|
1228033;1112;0;STORAGE;;
|
||||||
|
1241433;1094;0;STORAGE;;
|
||||||
|
1266451;978;0;SLAPLAT4H;2021-10-05;
|
||||||
|
1266452;978;250;TRAFFIC;2021-10-05;
|
||||||
|
1266453;978;0;SLAPLAT8H;2021-10-05;
|
||||||
|
1266454;978;0;SLAMAIL4H;2021-10-05;
|
||||||
|
1266455;978;0;SLAMARIA8H;2021-10-05;
|
||||||
|
1266456;978;0;SLAPGSQL4H;2021-10-05;
|
||||||
|
1266457;978;0;SLAWEB4H;2021-10-05;
|
||||||
|
1266458;978;0;SLAMARIA4H;2021-10-05;
|
||||||
|
1266459;978;0;SLAPGSQL8H;2021-10-05;
|
||||||
|
1266460;978;0;SLAOFFIC8H;2021-10-05;
|
||||||
|
1266461;978;0;SLAWEB8H;2021-10-05;
|
||||||
|
1266462;978;256000;STORAGE;2021-10-05;
|
||||||
|
1266463;978;153600;QUOTA;2021-10-05;
|
||||||
|
1266464;978;0;SLAOFFIC4H;2021-10-05;
|
||||||
|
1266465;978;32768;RAM;2021-10-05;
|
||||||
|
1266466;978;4;CPU;2021-10-05;
|
||||||
|
1266467;978;1;SLABASIC;2021-10-05;
|
||||||
|
1266468;978;0;SLAMAIL8H;2021-10-05;
|
||||||
|
1275583;978;0;SLAPLAT2H;2022-04-20;
|
||||||
|
1280533;978;0;SLAWEB2H;2022-04-20;
|
||||||
|
1285483;978;0;SLAMARIA2H;2022-04-20;
|
||||||
|
1290433;978;0;SLAPGSQL2H;2022-04-20;
|
||||||
|
1295383;978;0;SLAMAIL2H;2022-04-20;
|
||||||
|
1300333;978;0;SLAOFFIC2H;2022-04-20;
|
||||||
|
1305933;1447;0;SLAWEB2H;2022-05-02;
|
||||||
|
1305934;1447;0;SLAPLAT4H;2022-05-02;
|
||||||
|
1305935;1447;0;SLAWEB8H;2022-05-02;
|
||||||
|
1305936;1447;0;SLAOFFIC4H;2022-05-02;
|
||||||
|
1305937;1447;0;SLAMARIA4H;2022-05-02;
|
||||||
|
1305938;1447;0;SLAOFFIC8H;2022-05-02;
|
||||||
|
1305939;1447;1;SLABASIC;2022-05-02;
|
||||||
|
1305940;1447;0;SLAMAIL8H;2022-05-02;
|
||||||
|
1305941;1447;0;SLAPGSQL4H;2022-05-02;
|
||||||
|
1305942;1447;6;CPU;2022-05-02;
|
||||||
|
1305943;1447;250;TRAFFIC;2022-05-02;
|
||||||
|
1305944;1447;0;SLAOFFIC2H;2022-05-02;
|
||||||
|
1305945;1447;0;SLAMAIL4H;2022-05-02;
|
||||||
|
1305946;1447;0;SLAPGSQL2H;2022-05-02;
|
||||||
|
1305947;1447;0;SLAMARIA2H;2022-05-02;
|
||||||
|
1305948;1447;0;SLAMARIA8H;2022-05-02;
|
||||||
|
1305949;1447;0;SLAWEB4H;2022-05-02;
|
||||||
|
1305950;1447;16384;RAM;2022-05-02;
|
||||||
|
1305951;1447;0;SLAPGSQL8H;2022-05-02;
|
||||||
|
1305952;1447;512000;STORAGE;2022-05-02;
|
||||||
|
1305953;1447;0;SLAMAIL2H;2022-05-02;
|
||||||
|
1305954;1447;0;SLAPLAT2H;2022-05-02;
|
||||||
|
1305955;1447;0;SLAPLAT8H;2022-05-02;
|
||||||
|
1305956;1447;307200;QUOTA;2022-05-02;
|
||||||
|
1312013;23611;1;SLABASIC;2022-08-10;
|
||||||
|
1312014;23611;0;BANDWIDTH;2022-08-10;
|
||||||
|
1312015;23611;12288;RAM;2022-08-10;
|
||||||
|
1312016;23611;25600;QUOTA;2022-08-10;
|
||||||
|
1312017;23611;0;SLAINFR8H;2022-08-10;
|
||||||
|
1312018;23611;0;STORAGE;2022-08-10;
|
||||||
|
1312019;23611;0;SLAINFR2H;2022-08-10;
|
||||||
|
1312020;23611;8;CPU;2022-08-10;
|
||||||
|
1312021;23611;250;TRAFFIC;2022-08-10;
|
||||||
|
1312022;23611;0;SLAINFR4H;2022-08-10;
|
||||||
|
1313883;978;0;BANDWIDTH;;
|
||||||
|
1316583;1447;0;BANDWIDTH;;
|
||||||
|
1338074;968;0;SLAMARIA2H;2023-09-05;
|
||||||
|
1338075;968;384000;QUOTA;2023-09-05;
|
||||||
|
1338076;968;1;SLAMAIL8H;2023-09-05;
|
||||||
|
1338077;968;0;BANDWIDTH;2023-09-05;
|
||||||
|
1338078;968;0;SLAWEB2H;2023-09-05;
|
||||||
|
1338079;968;0;SLAOFFIC4H;2023-09-05;
|
||||||
|
1338080;968;256000;STORAGE;2023-09-05;
|
||||||
|
1338081;968;0;SLAPLAT4H;2023-09-05;
|
||||||
|
1338082;968;0;SLAPGSQL2H;2023-09-05;
|
||||||
|
1338083;968;0;SLAPLAT2H;2023-09-05;
|
||||||
|
1338084;968;250;TRAFFIC;2023-09-05;
|
||||||
|
1338085;968;1;SLAMARIA8H;2023-09-05;
|
||||||
|
1338086;968;0;SLAPGSQL4H;2023-09-05;
|
||||||
|
1338087;968;0;SLAMAIL2H;2023-09-05;
|
||||||
|
1338088;968;1;SLAPLAT8H;2023-09-05;
|
||||||
|
1338089;968;0;SLAWEB4H;2023-09-05;
|
||||||
|
1338090;968;6;CPU;2023-09-05;
|
||||||
|
1338091;968;1;SLAPGSQL8H;2023-09-05;
|
||||||
|
1338092;968;0;SLAMARIA4H;2023-09-05;
|
||||||
|
1338093;968;0;SLAMAIL4H;2023-09-05;
|
||||||
|
1338094;968;14336;RAM;2023-09-05;
|
||||||
|
1338095;968;0;SLAOFFIC2H;2023-09-05;
|
||||||
|
1338096;968;0;SLAOFFIC8H;2023-09-05;
|
||||||
|
1338097;968;1;SLABASIC;2023-09-05;
|
||||||
|
1338098;968;1;SLAWEB8H;2023-09-05;
|
||||||
|
1339228;19959;20;TRAFFIC;2023-10-27;
|
||||||
|
1339229;19959;1;SLABASIC;2023-10-27;
|
||||||
|
1339230;19959;0;DAEMON;2023-10-27;
|
||||||
|
1339231;19959;25600;QUOTA;2023-10-27;
|
||||||
|
1339232;19959;0;STORAGE;2023-10-27;
|
||||||
|
1339233;19959;0;SLAEXT24H;2023-10-27;
|
||||||
|
1339234;19959;0;OFFICE;2023-10-27;
|
||||||
|
1339235;19959;1;MULTI;2023-10-27;
|
||||||
|
1341088;1061;0;SLAOFFIC2H;2023-12-14;
|
||||||
|
1341089;1061;0;SLAOFFIC8H;2023-12-14;
|
||||||
|
1341090;1061;256000;STORAGE;2023-12-14;
|
||||||
|
1341091;1061;0;SLAMAIL4H;2023-12-14;
|
||||||
|
1341092;1061;0;SLAMAIL2H;2023-12-14;
|
||||||
|
1341093;1061;0;SLAPLAT2H;2023-12-14;
|
||||||
|
1341094;1061;4096;RAM;2023-12-14;
|
||||||
|
1341095;1061;0;SLAPLAT4H;2023-12-14;
|
||||||
|
1341096;1061;1;SLAPGSQL8H;2023-12-14;
|
||||||
|
1341097;1061;2;CPU;2023-12-14;
|
||||||
|
1341098;1061;0;QUOTA;2023-12-14;
|
||||||
|
1341099;1061;0;SLAMAIL8H;2023-12-14;
|
||||||
|
1341100;1061;1;SLABASIC;2023-12-14;
|
||||||
|
1341101;1061;1;SLAMARIA8H;2023-12-14;
|
||||||
|
1341102;1061;0;SLAPGSQL4H;2023-12-14;
|
||||||
|
1341103;1061;0;SLAPGSQL2H;2023-12-14;
|
||||||
|
1341104;1061;0;SLAMARIA4H;2023-12-14;
|
||||||
|
1341105;1061;0;SLAOFFIC4H;2023-12-14;
|
||||||
|
1341106;1061;1;SLAPLAT8H;2023-12-14;
|
||||||
|
1341107;1061;0;BANDWIDTH;2023-12-14;
|
||||||
|
1341108;1061;1;SLAWEB8H;2023-12-14;
|
||||||
|
1341109;1061;0;SLAWEB2H;2023-12-14;
|
||||||
|
1341110;1061;0;SLAMARIA2H;2023-12-14;
|
||||||
|
1341111;1061;250;TRAFFIC;2023-12-14;
|
||||||
|
1341112;1061;0;SLAWEB4H;2023-12-14;
|
||||||
|
1346628;630;0;SLAEXT24H;2024-03-19;
|
||||||
|
1346629;630;0;OFFICE;2024-03-19;
|
||||||
|
1346630;630;16384;QUOTA;2024-03-19;
|
||||||
|
1346631;630;0;DAEMON;2024-03-19;
|
||||||
|
1346632;630;10240;STORAGE;2024-03-19;
|
||||||
|
1346633;630;1;SLABASIC;2024-03-19;
|
||||||
|
1346634;630;50;TRAFFIC;2024-03-19;
|
||||||
|
1346635;630;25;MULTI;2024-03-19;
|
|
19
src/test/resources/migration/office/asset_transactions.csv
Normal file
19
src/test/resources/migration/office/asset_transactions.csv
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
member_asset_id; bp_id; date; action; amount; comment
|
||||||
|
358; 100; 2000-12-06; PAYMENT; 5120; for subscription A
|
||||||
|
442; 132; 2003-07-07; PAYMENT; 64;
|
||||||
|
577; 100; 2011-12-12; PAYMENT; 1024;
|
||||||
|
632; 132; 2013-10-21; PAYMENT; 64;
|
||||||
|
885; 100; 2020-12-15; PAYMENT; 6144; Einzahlung
|
||||||
|
924; 541; 2021-05-21; PAYMENT; 256; Beitritt - Lastschrift
|
||||||
|
925; 542; 2021-05-31; PAYMENT; 64; Beitritt - Lastschrift
|
||||||
|
1093; 100; 2023-10-05; PAYMENT; 3072; Kapitalerhoehung - Ueberweisung
|
||||||
|
1094; 100; 2023-10-06; PAYMENT; 3072; Kapitalerhoehung - Ueberweisung
|
||||||
|
31000; 120; 2000-12-06; PAYMENT; 128.00; for subscription B
|
||||||
|
32000; 100; 2005-01-10; PAYMENT; 2560.00; for subscription C
|
||||||
|
33001; 100; 2005-01-10; HANDOVER; -512.00; for transfer to 10
|
||||||
|
33002; 120; 2005-01-10; ADOPTION; 512.00; for transfer from 7
|
||||||
|
34001; 120; 2016-12-31; CLEARING; -8.00; for cancellation D
|
||||||
|
34002; 120; 2016-12-31; PAYBACK; -100.00; for cancellation D
|
||||||
|
34003; 120; 2016-12-31; LOSS; -20.00; for cancellation D
|
||||||
|
35001; 190; 2024-01-15; PAYMENT; 128.00; for subscription E
|
||||||
|
35002; 190; 2024-01-20; ADJUSTMENT;-128.00; chargeback for subscription E
|
|
10
src/test/resources/migration/office/business_partners.csv
Normal file
10
src/test/resources/migration/office/business_partners.csv
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
bp_id;member_id;member_code;member_since;member_until;member_role;author_contract;nondisc_contract;free;exempt_vat;indicator_vat;uid_vat
|
||||||
|
100;10003;hsh00-mim;2000-12-06;;Aufsichtsrat;;2001-04-24;0;0;GROSS;DE217249198
|
||||||
|
132;10152;hsh00-rar;2003-07-12;;;;;0;0;GROSS;DE 236 109 136
|
||||||
|
213;10000;hsh00-hsh;;;Hostsharing eG;;;1;0;GROSS;
|
||||||
|
541;11018;hsh00-wws;2021-05-17;;;;;0;0;GROSS;
|
||||||
|
542;11019;hsh00-dph;2021-05-25;;;;;0;0;GROSS;
|
||||||
|
120;10020;hsh00-xyz;2000-12-06;2015-12-31;;;;false;false;GROSS;
|
||||||
|
122;11022;hsh00-xxx;2021-04-01;;;;;true;true;GROSS;
|
||||||
|
190;19090;hsh00-yyy;;;;;;true;true;GROSS;
|
||||||
|
199;19999;hsh00-zzz;;;;;;false;false;GROSS;
|
|
35
src/test/resources/migration/office/contacts.csv
Normal file
35
src/test/resources/migration/office/contacts.csv
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
contact_id; bp_id; salut; first_name; last_name; title; firma; co; street; zipcode; city; country; phone_private; phone_office; phone_mobile; fax; email; roles
|
||||||
|
|
||||||
|
# Hostsharing, the mandate itself
|
||||||
|
212; 213; Firma; Hostmaster; Hostsharing; ; Hostsharing e.G.; ; ; ; ; Germany; ; ; ; ; hostmaster@hostsharing.net; billing,operation,contractual,partner
|
||||||
|
|
||||||
|
# some natural persons
|
||||||
|
100; 100; Herr; Michael; Mellis; ; Michael Mellis; ; Dr. Bolte Str. 50; 26524; Hage; Germany; ; +49 4931/1234567; +49/1522123455; +49 40 912345-9; michael@Mellis.example.org; billing,operation,contractual,partner,subscriber:members-announce,subscriber:operations-announce,subscriber:operations-discussion,subscriber:members-discussion,subscriber:generalversammlung
|
||||||
|
132; 132; Herr; Ragnar; Richter; ; Ragnar IT-Beratung; ; Vioktoriastraße 114; 70197; Stuttgart; Germany; +49 711 987654-1; +49 711 987654-2; ; +49 711 87654-3; hostsharing@ragnar-richter.de; billing,operation,partner,subscriber:operations-announce,subscriber:operations-discussion
|
||||||
|
|
||||||
|
# eine juristische Person mit drei separaten Ansprechpartnern, vip-contact und ex-partner
|
||||||
|
1200; 120; ; ; ; ; JM e.K.; ; Wiesenweg 15; 12335; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; jm-ex-partner@example.org; ex-partner
|
||||||
|
1201; 120; Frau; Jenny; Meyer-Billing; Dr.; JM GmbH; ; Waldweg 5; 11001; Berlin; DE; +49 30 7777777; +49 30 1111111; ; +49 30 2222222; jm-billing@example.org; billing
|
||||||
|
1202; 120; Herr; Andrew; Meyer-Operation; ; JM GmbH; ; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 3333333; ; +49 30 4444444; am-operation@example.org; operation,vip-contact,subscriber:operations-announce
|
||||||
|
1203; 120; Herr; Philip; Meyer-Contract; ; JM GmbH; ; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; pm-partner@example.org; partner,contractual,subscriber:members-announce,subscriber:customers-announce
|
||||||
|
1204; 120; Frau; Tammy; Meyer-VIP; ; JM GmbH; ; Waldweg 5; 11001; Berlin; DE; +49 30 999999; +49 30 999999; ; +49 30 6666666; tm-vip@example.org; vip-contact
|
||||||
|
|
||||||
|
# eine juristische Person mit nur einem Ansprechpartner und explizitem contractual
|
||||||
|
1301; 122; ; Petra; Schmidt; ; Test PS; ; ; ; ; ; ; ; ; ; ps@example.com; partner,billing,contractual,operation
|
||||||
|
|
||||||
|
# eine natürliche Person, die nur Subscriber ist
|
||||||
|
1401; 120; Frau; Frauke; Fanninga; ; ; ; Am Walde 1; 29456; Hitzacker; DE; ; ; ; ; ff@example.org; subscriber:operations-announce
|
||||||
|
|
||||||
|
# eine natürliche Person als Partner
|
||||||
|
1501; 190; Frau; Cecilia; Camus; ; ; ; Rue d'Avignion 60; 45000; Orléans; FR; ; ; ; ; cc@example.org; partner,contractual,billing,operation
|
||||||
|
|
||||||
|
# some more contacts of realistic business partners
|
||||||
|
|
||||||
|
90436; 541; Frau; Christiane; Milberg; ; Wasserwerk Südholstein; ; Am Wasserwerk 1-3; 25491; Hetlingen; Germany; ; ; +49 4103 12345-1; ; rechnung@ww-sholst.example.org; billing,partner,subscriber:members-discussion,contractual,subscriber:members-announce,subscriber:generalversammlung
|
||||||
|
90437; 542; Herr; Richard; Wiese; ; Das Perfekte Haus; ; Kennedyplatz 11; 45279; Essen; Germany; ; ; +49-172-12345; ; admin@das-perfekte-haus.example.org; operation,partner,subscriber:members-discussion,contractual,subscriber:operations-announce,subscriber:operations-discussion,subscriber:members-announce,subscriber:generalversammlung
|
||||||
|
90438; 541; Herr; Karim; Metzger; ; Wasswerwerk Südholstein; ; Am Wasserwerk 1-3; 25491; Hetlingen; Germany; ; +49 4103 12345-2; ; ; karim.metzger@ww-sholst.example.org; operation,subscriber:operations-announce,subscriber:operations-discussion
|
||||||
|
90590; 542; Herr; Inhaber R.; Wiese; ; Das Perfekte Haus; Client-ID 515217; Essen, Kastanienallee 81; 30127; Hannover; Germany; ; ; ; ; 515217@kkemail.example.org; billing
|
||||||
|
90629; 132; ; Ragnar; Richter; ; ; ; ; ; ; ; ; ; ; ; mail@ragnar-richter..example.org; contractual,subscriber:members-announce,subscriber:members-discussion,subscriber:generalversammlung
|
||||||
|
90677; 132; ; Eike; Henning; ; ; ; ; ; ; ; ; ; ; ; hostsharing@eike-henning..example.org; operation,subscriber:operations-announce,subscriber:operations-discussion
|
||||||
|
90698; 132; ; Jan; Henning; ; ; ; ; ; ; ; ; 01577 12345678; ; ; mail@jan-henning.example.org; operation
|
||||||
|
|
|
8
src/test/resources/migration/office/sepa_mandates.csv
Normal file
8
src/test/resources/migration/office/sepa_mandates.csv
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
sepa_mandat_id;bp_id;bank_customer;bank_name;bank_iban;bank_bic;mandat_ref;mandat_signed;mandat_since;mandat_until;mandat_used
|
||||||
|
30;132;Ragnar Richter;GLS Gemeinschaftsbank eG;DE02300209000106531065;GENODEM1GLS;HS-10152-20140801;2013-12-01;2013-12-01;2016-02-15;2014-01-20
|
||||||
|
132;100;Michael Mellis;Hamburger Volksbank;DE37500105177419788228;GENODEF1HH2;HS-10003-20140801;2013-12-01;2013-12-01;;2022-12-31
|
||||||
|
386;541;Wasserwerk Suedholstein;Sparkasse Westholstein;DE49500105174516484892;NOLADE21WHO;HS-11018-20210512;2021-05-12;2021-05-17;;2022-12-31
|
||||||
|
387;542;Richard Wiese Das Perfekte Haus;Commerzbank Wuppertal;DE89370400440532013000;COBADEFFXXX;HS-11019-20210519;2021-05-19;2021-05-25;;2022-12-31
|
||||||
|
234234;100;Michael Mellis;ING Bank AG;DE37500105177419788228;INGDDEFFXXX;MH12345;2004-06-12;2004-06-15;;2022-10-20
|
||||||
|
235600;120;JM e.K.;Targobank AG;DE02300209000106531065;CMCIDEDD;JM33344;2004-01-15;2004-01-20;2005-06-27 ;2016-01-18
|
||||||
|
235662;120;JM GmbH;ING Bank AG;DE49500105174516484892;INGDDEFFXXX;JM33344;2005-06-28;2005-07-01;;2016-01-18
|
|
12
src/test/resources/migration/office/share_transactions.csv
Normal file
12
src/test/resources/migration/office/share_transactions.csv
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
member_share_id;bp_id;date;action;quantity;comment
|
||||||
|
3;100;2000-12-06;SUBSCRIPTION;80;initial share subscription
|
||||||
|
90;132;2003-07-12;SUBSCRIPTION;1;
|
||||||
|
241;100;2011-12-05;SUBSCRIPTION;16;
|
||||||
|
279;132;2013-10-21;SUBSCRIPTION;1;
|
||||||
|
523;100;2020-12-08;SUBSCRIPTION;96;Kapitalerhoehung
|
||||||
|
562;541;2021-05-17;SUBSCRIPTION;4;Beitritt
|
||||||
|
563;542;2021-05-25;SUBSCRIPTION;1;Beitritt
|
||||||
|
721;100;2023-10-10;SUBSCRIPTION;96;Kapitalerhoehung
|
||||||
|
33451;120;2000-12-06;SUBSCRIPTION;2;initial share subscription
|
||||||
|
33701;100;2005-01-10;SUBSCRIPTION;40;increase
|
||||||
|
33810;120;2016-12-31;UNSUBSCRIPTION;22;membership ended
|
|
@ -1,4 +0,0 @@
|
|||||||
sepa_mandat_id; bp_id; bank_customer; bank_name; bank_iban; bank_bic; mandat_ref; mandat_signed; mandat_since; mandat_until; mandat_used
|
|
||||||
234234; 17; Michael Mellies; ING Bank AG; DE37500105177419788228; INGDDEFFXXX; MH12345; 2004-06-12; 2004-06-15; ; 2022-10-20
|
|
||||||
235600; 20; JM e.K.; Targobank AG; DE02300209000106531065; CMCIDEDD; JM33344; 2004-01-15; 2004-01-20;2005-06-27 ;2016-01-18
|
|
||||||
235662; 20; JM GmbH; ING Bank AG; DE49500105174516484892; INGDDEFFXXX; JM33344; 2005-06-28; 2005-07-01; ; 2016-01-18
|
|
|
@ -1,5 +0,0 @@
|
|||||||
member_share_id;bp_id; date; action; quantity; comment
|
|
||||||
33443; 17; 2000-12-06; SUBSCRIPTION; 20; initial share subscription
|
|
||||||
33451; 20; 2000-12-06; SUBSCRIPTION; 2; initial share subscription
|
|
||||||
33701; 17; 2005-01-10; SUBSCRIPTION; 40; increase
|
|
||||||
33810; 20; 2016-12-31; UNSUBSCRIPTION; 22; membership ended
|
|
|
Loading…
Reference in New Issue
Block a user