hosting-asset-data-migration #79

Merged
hsh-michaelhoennig merged 22 commits from hosting-asset-data-migration into master 2024-07-22 11:30:34 +02:00
28 changed files with 668 additions and 315 deletions
Showing only changes of commit 45c13244bf - Show all commits

View File

@ -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

View File

@ -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() {

View File

@ -13,7 +13,7 @@ class HsCloudServerBookingItemValidator extends HsBookingItemEntityValidator {
integerProperty("CPU") .min( 1) .max( 32) .required(), integerProperty("CPU") .min( 1) .max( 32) .required(),
integerProperty("RAM").unit("GB") .min( 1) .max( 8192) .required(), integerProperty("RAM").unit("GB") .min( 1) .max( 8192) .required(),
integerProperty("SSD").unit("GB") .min( 0) .max( 1000) .step(25).optional(), // (1) // FIXME: required()vvv integerProperty("SSD").unit("GB") .min( 0) .max( 1000) .step(25).optional(), // (1) // FIXME: required()
integerProperty("HDD").unit("GB") .min( 0) .max( 4000) .step(250).withDefault(0), integerProperty("HDD").unit("GB") .min( 0) .max( 4000) .step(250).withDefault(0),
integerProperty("Traffic").unit("GB") .min(250) .max(10000) .step(250).optional(), // FIXME: required() integerProperty("Traffic").unit("GB") .min(250) .max(10000) .step(250).optional(), // FIXME: required()
integerProperty("Bandwidth").unit("GB") .min(250) .max(10000) .step(250).optional(), // TODO.spec integerProperty("Bandwidth").unit("GB") .min(250) .max(10000) .step(250).optional(), // TODO.spec

View File

@ -33,7 +33,7 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
.eachComprising( 5, databases()) .eachComprising( 5, databases())
.eachComprising(250, eMailAddresses()), .eachComprising(250, eMailAddresses()),
integerProperty("Daemons").min(0).max(16).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")
); );
} }

View File

@ -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;
@ -108,7 +110,7 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Properti
private HsOfficeContactEntity alarmContact; private HsOfficeContactEntity alarmContact;
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true, fetch = FetchType.LAZY) @OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true, fetch = FetchType.LAZY)
@JoinColumn(name="parentassetuuid", referencedColumnName="uuid") @JoinColumn(name = "parentassetuuid", referencedColumnName = "uuid")
private List<HsHostingAssetEntity> subHostingAssets; private List<HsHostingAssetEntity> subHostingAssets;
@Column(name = "identifier") @Column(name = "identifier")
@ -134,12 +136,20 @@ 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);
} }
public void putConfig(Map<String, Object> newConfig) { public void putConfig(Map<String, Object> newConfig) {
PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper; }, config).assign(newConfig); PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper;}, config).assign(newConfig);
} }
@Override @Override
@ -150,20 +160,19 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Properti
@Override @Override
public Object getContextValue(final String propName) { public Object getContextValue(final String propName) {
final var v = config.get(propName); final var v = config.get(propName);
if (v!= null) { if (v != null) {
return v; return v;
} }
if (bookingItem!=null) { if (bookingItem != null) {
return bookingItem.getResources().get(propName); return bookingItem.getResources().get(propName);
} }
if (parentAsset!=null && parentAsset.getBookingItem()!=null) { if (parentAsset != null && parentAsset.getBookingItem() != null) {
return parentAsset.getBookingItem().getResources().get(propName); return parentAsset.getBookingItem().getResources().get(propName);
} }
return emptyMap(); return emptyMap();
} }
@Override @Override
public String toString() { public String toString() {
return stringify.apply(this); return stringify.apply(this);
@ -182,9 +191,9 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Properti
.toRole(GLOBAL, ADMIN).grantPermission(INSERT) // TODO.impl: Why is this necessary to insert test data? .toRole(GLOBAL, ADMIN).grantPermission(INSERT) // TODO.impl: Why is this necessary to insert test data?
.importEntityAlias("bookingItem", HsBookingItemEntity.class, usingDefaultCase(), .importEntityAlias("bookingItem", HsBookingItemEntity.class, usingDefaultCase(),
dependsOnColumn("bookingItemUuid"), dependsOnColumn("bookingItemUuid"),
directlyFetchedByDependsOnColumn(), directlyFetchedByDependsOnColumn(),
NULLABLE) NULLABLE)
.importEntityAlias("parentAsset", HsHostingAssetEntity.class, usingDefaultCase(), .importEntityAlias("parentAsset", HsHostingAssetEntity.class, usingDefaultCase(),
dependsOnColumn("parentAssetUuid"), dependsOnColumn("parentAssetUuid"),
@ -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 {

View File

@ -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]$");
} }

View File

@ -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

View File

@ -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'))
); );
--// --//

View File

@ -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")

View File

@ -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 })");

View File

@ -12,9 +12,9 @@ class HsHostingAssetTypeUnitTest {
assertThat(result).isEqualTo(""" assertThat(result).isEqualTo("""
## 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

View File

@ -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())

View File

@ -1,4 +1,4 @@
package net.hostsharing.hsadminng.hs.office.migration; package net.hostsharing.hsadminng.hs.migration;
import com.opencsv.CSVParserBuilder; import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader; import com.opencsv.CSVReader;
@ -42,7 +42,9 @@ import static org.assertj.core.api.Assumptions.assumeThat;
public class CsvDataImport extends ContextBasedTest { public class CsvDataImport extends ContextBasedTest {
public static final String MIGRATION_DATA_PATH = ofNullable(System.getenv("HSADMINNG_MIGRATION_DATA_PATH")).orElse("migration") + "/"; 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}") @Value("${spring.datasource.url}")
protected String jdbcUrl; protected String jdbcUrl;
@ -117,22 +119,23 @@ public class CsvDataImport extends ContextBasedTest {
return record; return record;
} }
protected void persist(final Integer id, final RbacObject entity) { public <T extends RbacObject> T persist(final Integer id, final T entity) {
try { try {
final var asString = entity.toString(); final var asString = entity.toString();
if ( asString.contains("'null null, null'") || asString.equals("person()")) { if ( asString.contains("'null null, null'") || asString.equals("person()")) {
return; System.err.println("skipping to persist empty record-id " + id + " #" + entity.hashCode() + ": " + entity);
return entity;
} }
//System.out.println("persisting #" + entity.hashCode() + ": " + entity); //System.out.println("persisting #" + entity.hashCode() + ": " + entity);
em.persist(entity); em.persist(entity);
// uncomment for debugging purposes // uncomment for debugging purposes
em.flush(); em.flush(); // makes it slow, but produces better error messages
// System.out.println("persisted #" + entity.hashCode() + " as " + entity.getUuid()); // System.out.println("persisted #" + entity.hashCode() + " as " + entity.getUuid());
} catch (Exception exc) { } catch (Exception exc) {
System.err.println("failed to persist #" + entity.hashCode() + ": " + entity); System.err.println("failed to persist #" + entity.hashCode() + ": " + entity);
System.err.println(exc); System.err.println(exc);
} }
return entity;
} }
protected <E> String toFormattedString(final Map<Integer, E> map) { protected <E> String toFormattedString(final Map<Integer, E> map) {
@ -151,6 +154,7 @@ public class CsvDataImport extends ContextBasedTest {
protected void deleteTestDataFromHsOfficeTables() { protected void deleteTestDataFromHsOfficeTables() {
jpaAttempt.transacted(() -> { jpaAttempt.transacted(() -> {
context(rbacSuperuser); 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_hosting_asset where true").executeUpdate();
em.createNativeQuery("delete from hs_booking_item 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_booking_project where true").executeUpdate();

View File

@ -1,13 +1,14 @@
package net.hostsharing.hsadminng.hs.office.migration; package net.hostsharing.hsadminng.hs.migration;
import net.hostsharing.hsadminng.context.Context; 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.HsBookingItemEntity;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
import net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidatorRegistry; 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.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
import net.hostsharing.hsadminng.hs.hosting.asset.validators.HostingAssetEntitySaveProcessor; import net.hostsharing.hsadminng.hs.hosting.asset.validators.HostingAssetEntitySaveProcessor;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.MethodOrderer;
@ -87,20 +88,32 @@ import static org.assertj.core.api.Assumptions.assumeThat;
@ExtendWith(OrderedDependedTestsExtension.class) @ExtendWith(OrderedDependedTestsExtension.class)
public class ImportHostingAssets extends ImportOfficeData { public class ImportHostingAssets extends ImportOfficeData {
private static final Integer IP_NUMBER_ID_OFFSET = 1000000; static final Integer IP_NUMBER_ID_OFFSET = 1000000;
private static final Integer HIVE_ID_OFFSET = 2000000; static final Integer HIVE_ID_OFFSET = 2000000;
private static final Integer PACKET_ID_OFFSET = 3000000; static final Integer PACKET_ID_OFFSET = 3000000;
record Hive(int hive_id, String hive_name, int inet_addr_id, AtomicReference<HsHostingAssetEntity> serverRef) {} record Hive(int hive_id, String hive_name, int inet_addr_id, AtomicReference<HsHostingAssetEntity> serverRef) {}
private static Map<Integer, HsBookingItemEntity> bookingItems = new WriteOnceMap<>(); static Map<Integer, HsBookingProjectEntity> bookingProjects = new WriteOnceMap<>();
private static Map<Integer, Hive> hives = new WriteOnceMap<>(); static Map<Integer, HsBookingItemEntity> bookingItems = new WriteOnceMap<>();
private static Map<Integer, HsHostingAssetEntity> hostingAssets = new WriteOnceMap<>(); static Map<Integer, Hive> hives = new WriteOnceMap<>();
static Map<Integer, HsHostingAssetEntity> hostingAssets = new WriteOnceMap<>(); // FIXME: separate maps for each type?
@Test @Test
@Order(2010) @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() { void importIpNumbers() {
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "inet_addr.csv")) { try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/inet_addr.csv")) {
final var lines = readAllLines(reader); final var lines = readAllLines(reader);
importIpNumbers(justHeader(lines), withoutHeader(lines)); importIpNumbers(justHeader(lines), withoutHeader(lines));
} catch (Exception e) { } catch (Exception e) {
@ -109,26 +122,26 @@ public class ImportHostingAssets extends ImportOfficeData {
} }
@Test @Test
@Order(2019) @Order(12019)
void verifyIpNumbers() { void verifyIpNumbers() {
assumeThatWeAreImportingControlledTestData(); assumeThatWeAreImportingControlledTestData();
// no contacts yet => mostly null values // no contacts yet => mostly null values
assertThat(firstOfEachType(5, IPV4_NUMBER)).isEqualToIgnoringWhitespace(""" assertThat(firstOfEachType(5, IPV4_NUMBER)).isEqualToIgnoringWhitespace("""
{ {
1000329=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.0), 1000363=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.34),
1000330=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.1), 1000402=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.73),
1000331=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.2), 1000433=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.104),
1000332=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.3), 1000473=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.144),
1000333=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.4) 1000574=HsHostingAssetEntity(IPV4_NUMBER, 83.223.95.245)
} }
"""); """);
} }
@Test @Test
@Order(2030) @Order(12030)
void importHives() { void importHives() {
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "hive.csv")) { try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/hive.csv")) {
final var lines = readAllLines(reader); final var lines = readAllLines(reader);
importHives(justHeader(lines), withoutHeader(lines)); importHives(justHeader(lines), withoutHeader(lines));
} catch (Exception e) { } catch (Exception e) {
@ -137,26 +150,26 @@ public class ImportHostingAssets extends ImportOfficeData {
} }
@Test @Test
@Order(2039) @Order(12039)
void verifyHives() { void verifyHives() {
assumeThatWeAreImportingControlledTestData(); assumeThatWeAreImportingControlledTestData();
// no contacts yet => mostly null values // no contacts yet => mostly null values
assertThat(toFormattedString(first(5, hives))).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(first(5, hives))).isEqualToIgnoringWhitespace("""
{ {
2000001=Hive[hive_id=1, hive_name=h01, inet_addr_id=358, serverRef=null], 2000001=Hive[hive_id=1, hive_name=h00, inet_addr_id=358, serverRef=null],
2000002=Hive[hive_id=2, hive_name=h02, inet_addr_id=359, serverRef=null], 2000002=Hive[hive_id=2, hive_name=h01, inet_addr_id=359, serverRef=null],
2000004=Hive[hive_id=4, hive_name=h03, inet_addr_id=360, serverRef=null], 2000004=Hive[hive_id=4, hive_name=h02, inet_addr_id=360, serverRef=null],
2000007=Hive[hive_id=7, hive_name=h04, inet_addr_id=361, serverRef=null], 2000007=Hive[hive_id=7, hive_name=h03, inet_addr_id=361, serverRef=null],
2000013=Hive[hive_id=13, hive_name=h05, inet_addr_id=430, serverRef=null] 2000013=Hive[hive_id=13, hive_name=h04, inet_addr_id=430, serverRef=null]
} }
"""); """);
} }
@Test @Test
@Order(3000) @Order(13000)
void importPackets() { void importPackets() {
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "packet.csv")) { try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/packet.csv")) {
final var lines = readAllLines(reader); final var lines = readAllLines(reader);
importPackets(justHeader(lines), withoutHeader(lines)); importPackets(justHeader(lines), withoutHeader(lines));
} catch (Exception e) { } catch (Exception e) {
@ -165,21 +178,19 @@ public class ImportHostingAssets extends ImportOfficeData {
} }
@Test @Test
@Order(3009) @Order(13009)
void verifyPackets() { void verifyPackets() {
assumeThatWeAreImportingControlledTestData(); assumeThatWeAreImportingControlledTestData();
assertThat(firstOfEachType(3, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE)).isEqualToIgnoringWhitespace(""" assertThat(firstOfEachType(3, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE)).isEqualToIgnoringWhitespace("""
{ {
3000003=HsHostingAssetEntity(MANAGED_WEBSPACE, agu00, HA agu00, MANAGED_SERVER:vm1001, D-???????-?:BI agu00), 3000630=HsHostingAssetEntity(MANAGED_WEBSPACE, hsh00, HA hsh00, MANAGED_SERVER:vm1050, D-1000000:hsh default project:BI hsh00),
3000007=HsHostingAssetEntity(MANAGED_WEBSPACE, ahr00, HA ahr00, MANAGED_SERVER:vm1005, D-???????-?:BI ahr00), 3000968=HsHostingAssetEntity(MANAGED_SERVER, vm1061, HA vm1061, D-1015200:rar default project:BI vm1061),
3000008=HsHostingAssetEntity(MANAGED_WEBSPACE, ahr01, HA ahr01, MANAGED_SERVER:vm1003, D-???????-?:BI ahr01), 3000978=HsHostingAssetEntity(MANAGED_SERVER, vm1050, HA vm1050, D-1000000:hsh default project:BI vm1050),
3000964=HsHostingAssetEntity(MANAGED_SERVER, vm1064, HA vm1064, D-???????-?:BI vm1064), 3001061=HsHostingAssetEntity(MANAGED_SERVER, vm1068, HA vm1068, D-1000300:mim default project:BI vm1068),
3000966=HsHostingAssetEntity(MANAGED_SERVER, vm1063, HA vm1063, D-???????-?:BI vm1063), 3001094=HsHostingAssetEntity(MANAGED_WEBSPACE, lug00, HA lug00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI lug00),
3000967=HsHostingAssetEntity(MANAGED_SERVER, vm1062, HA vm1062, D-???????-?:BI vm1062), 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-???????-?:BI vm2097), 3023611=HsHostingAssetEntity(CLOUD_SERVER, vm2097, HA vm2097, D-1101800:wws default project:BI vm2097)
3023612=HsHostingAssetEntity(CLOUD_SERVER, vm2062, HA vm2062, D-???????-?:BI vm2062),
3023613=HsHostingAssetEntity(CLOUD_SERVER, vm2058, HA vm2058, D-???????-?:BI vm2058)
} }
"""); """);
assertThat(firstOfEachType( assertThat(firstOfEachType(
@ -188,23 +199,21 @@ public class ImportHostingAssets extends ImportOfficeData {
HsBookingItemType.MANAGED_SERVER, HsBookingItemType.MANAGED_SERVER,
HsBookingItemType.MANAGED_WEBSPACE)).isEqualToIgnoringWhitespace(""" HsBookingItemType.MANAGED_WEBSPACE)).isEqualToIgnoringWhitespace("""
{ {
3000003=HsBookingItemEntity(MANAGED_WEBSPACE, [2003-07-07,), BI agu00), 3000630=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_WEBSPACE, [2001-06-01,), BI hsh00),
3000007=HsBookingItemEntity(MANAGED_WEBSPACE, [2001-12-17,), BI ahr00), 3000968=HsBookingItemEntity(D-1015200:rar default project, MANAGED_SERVER, [2013-04-01,), BI vm1061),
3000008=HsBookingItemEntity(MANAGED_WEBSPACE, [2003-03-12,), BI ahr01), 3000978=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_SERVER, [2013-04-01,), BI vm1050),
3000964=HsBookingItemEntity(MANAGED_SERVER, [2013-04-01,), BI vm1064), 3001061=HsBookingItemEntity(D-1000300:mim default project, MANAGED_SERVER, [2013-08-19,), BI vm1068),
3000966=HsBookingItemEntity(MANAGED_SERVER, [2013-04-01,), BI vm1063), 3001094=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-10,), BI lug00),
3000967=HsBookingItemEntity(MANAGED_SERVER, [2013-04-01,), BI vm1062), 3001112=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-17,), BI mim00),
3023611=HsBookingItemEntity(CLOUD_SERVER, [2022-08-10,), BI vm2097), 3023611=HsBookingItemEntity(D-1101800:wws default project, CLOUD_SERVER, [2022-08-10,), BI vm2097)
3023612=HsBookingItemEntity(CLOUD_SERVER, [2022-08-10,), BI vm2062),
3023613=HsBookingItemEntity(CLOUD_SERVER, [2022-08-10,), BI vm2058)
} }
"""); """);
} }
@Test @Test
@Order(3010) @Order(13010)
void importPacketComponents() { void importPacketComponents() {
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "packet_component.csv")) { try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/packet_component.csv")) {
final var lines = readAllLines(reader); final var lines = readAllLines(reader);
importPacketComponents(justHeader(lines), withoutHeader(lines)); importPacketComponents(justHeader(lines), withoutHeader(lines));
} catch (Exception e) { } catch (Exception e) {
@ -213,7 +222,7 @@ public class ImportHostingAssets extends ImportOfficeData {
} }
@Test @Test
@Order(3019) @Order(13019)
void verifyPacketComponents() { void verifyPacketComponents() {
assumeThatWeAreImportingControlledTestData(); assumeThatWeAreImportingControlledTestData();
@ -221,21 +230,15 @@ public class ImportHostingAssets extends ImportOfficeData {
assertThat(firstOfEachType(5, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE)) assertThat(firstOfEachType(5, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE))
.isEqualToIgnoringWhitespace(""" .isEqualToIgnoringWhitespace("""
{ {
3000003=HsHostingAssetEntity(MANAGED_WEBSPACE, agu00, HA agu00, MANAGED_SERVER:vm1001, D-???????-?:BI agu00), 3000630=HsHostingAssetEntity(MANAGED_WEBSPACE, hsh00, HA hsh00, MANAGED_SERVER:vm1050, D-1000000:hsh default project:BI hsh00),
3000007=HsHostingAssetEntity(MANAGED_WEBSPACE, ahr00, HA ahr00, MANAGED_SERVER:vm1005, D-???????-?:BI ahr00), 3000968=HsHostingAssetEntity(MANAGED_SERVER, vm1061, HA vm1061, D-1015200:rar default project:BI vm1061),
3000008=HsHostingAssetEntity(MANAGED_WEBSPACE, ahr01, HA ahr01, MANAGED_SERVER:vm1003, D-???????-?:BI ahr01), 3000978=HsHostingAssetEntity(MANAGED_SERVER, vm1050, HA vm1050, D-1000000:hsh default project:BI vm1050),
3000009=HsHostingAssetEntity(MANAGED_WEBSPACE, aih00, HA aih00, MANAGED_SERVER:vm1001, D-???????-?:BI aih00), 3001061=HsHostingAssetEntity(MANAGED_SERVER, vm1068, HA vm1068, D-1000300:mim default project:BI vm1068),
3000012=HsHostingAssetEntity(MANAGED_WEBSPACE, al000, HA al000, MANAGED_SERVER:vm1001, D-???????-?:BI al000), 3001094=HsHostingAssetEntity(MANAGED_WEBSPACE, lug00, HA lug00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI lug00),
3000964=HsHostingAssetEntity(MANAGED_SERVER, vm1064, HA vm1064, D-???????-?:BI vm1064), 3001112=HsHostingAssetEntity(MANAGED_WEBSPACE, mim00, HA mim00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI mim00),
3000966=HsHostingAssetEntity(MANAGED_SERVER, vm1063, HA vm1063, D-???????-?:BI vm1063), 3001447=HsHostingAssetEntity(MANAGED_SERVER, vm1093, HA vm1093, D-1000000:hsh default project:BI vm1093),
3000967=HsHostingAssetEntity(MANAGED_SERVER, vm1062, HA vm1062, D-???????-?:BI vm1062), 3019959=HsHostingAssetEntity(MANAGED_WEBSPACE, dph00, HA dph00, MANAGED_SERVER:vm1093, D-1101900:dph default project:BI dph00),
3000968=HsHostingAssetEntity(MANAGED_SERVER, vm1061, HA vm1061, D-???????-?:BI vm1061), 3023611=HsHostingAssetEntity(CLOUD_SERVER, vm2097, HA vm2097, D-1101800:wws default project:BI vm2097)
3000969=HsHostingAssetEntity(MANAGED_SERVER, vm1060, HA vm1060, D-???????-?:BI vm1060),
3023611=HsHostingAssetEntity(CLOUD_SERVER, vm2097, HA vm2097, D-???????-?:BI vm2097),
3023612=HsHostingAssetEntity(CLOUD_SERVER, vm2062, HA vm2062, D-???????-?:BI vm2062),
3023613=HsHostingAssetEntity(CLOUD_SERVER, vm2058, HA vm2058, D-???????-?:BI vm2058),
3023614=HsHostingAssetEntity(CLOUD_SERVER, vm2055, HA vm2055, D-???????-?:BI vm2055),
3023615=HsHostingAssetEntity(CLOUD_SERVER, vm2010, HA vm2010, D-???????-?:BI vm2010)
} }
"""); """);
assertThat(firstOfEachType( assertThat(firstOfEachType(
@ -245,53 +248,62 @@ public class ImportHostingAssets extends ImportOfficeData {
HsBookingItemType.MANAGED_WEBSPACE)) HsBookingItemType.MANAGED_WEBSPACE))
.isEqualToIgnoringWhitespace(""" .isEqualToIgnoringWhitespace("""
{ {
3000003=HsBookingItemEntity(MANAGED_WEBSPACE, [2003-07-07,), BI agu00, { "Multi": 3, "SLA-Platform": "EXT24H", "SSD": 8, "Traffic": 20}), 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}),
3000007=HsBookingItemEntity(MANAGED_WEBSPACE, [2001-12-17,), BI ahr00, { "Multi": 6, "SLA-Platform": "EXT24H", "SSD": 25, "Traffic": 10}), 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}),
3000008=HsBookingItemEntity(MANAGED_WEBSPACE, [2003-03-12,), BI ahr01, { "Multi": 3, "SLA-Platform": "EXT24H", "SSD": 5, "Traffic": 10}), 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}),
3000009=HsBookingItemEntity(MANAGED_WEBSPACE, [2002-07-03,), BI aih00, { "HDD": 20, "Multi": 2, "SLA-Platform": "EXT24H", "SSD": 3, "Traffic": 10}), 3001061=HsBookingItemEntity(D-1000300:mim default project, MANAGED_SERVER, [2013-08-19,), BI vm1068, { "CPU": 2, "RAM": 4, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT2H", "SLA-Web": true, "SSD": 75, "Traffic": 250}),
3000012=HsBookingItemEntity(MANAGED_WEBSPACE, [2003-10-17,), BI al000, { "HDD": 10, "Multi": 3, "SLA-Platform": "EXT24H", "SSD": 6, "Traffic": 40}), 3001094=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-10,), BI lug00, { "Multi": 5, "SLA-Platform": "EXT24H", "SSD": 1, "Traffic": 10}),
3000964=HsBookingItemEntity(MANAGED_SERVER, [2013-04-01,), BI vm1064, { "CPU": 2, "RAM": 4, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT2H", "SLA-Web": true, "SSD": 75, "Traffic": 500}), 3001112=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-17,), BI mim00, { "Multi": 5, "SLA-Platform": "EXT24H", "SSD": 3, "Traffic": 20}),
3000966=HsBookingItemEntity(MANAGED_SERVER, [2013-04-01,), BI vm1063, { "CPU": 2, "HDD": 250, "RAM": 8, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT8H", "SLA-Web": true, "SSD": 50, "Traffic": 250}), 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}),
3000967=HsBookingItemEntity(MANAGED_SERVER, [2013-04-01,), BI vm1062, { "CPU": 2, "HDD": 250, "RAM": 12, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 100, "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}),
3000968=HsBookingItemEntity(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}), 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})
3000969=HsBookingItemEntity(MANAGED_SERVER, [2013-04-01,), BI vm1060, { "CPU": 2, "RAM": 4, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT8H", "SLA-Web": true, "SSD": 75, "Traffic": 250}),
3023611=HsBookingItemEntity(CLOUD_SERVER, [2022-08-10,), BI vm2097, { "CPU": 8, "RAM": 12, "SLA-Infrastructure": "EXT4H", "SSD": 25, "Traffic": 250}),
3023612=HsBookingItemEntity(CLOUD_SERVER, [2022-08-10,), BI vm2062, { "CPU": 10, "RAM": 64, "SLA-Infrastructure": "EXT8H", "SSD": 25, "Traffic": 250}),
3023613=HsBookingItemEntity(CLOUD_SERVER, [2022-08-10,), BI vm2058, { "CPU": 1, "RAM": 8, "SLA-Infrastructure": "EXT4H", "SSD": 25, "Traffic": 250}),
3023614=HsBookingItemEntity(CLOUD_SERVER, [2022-08-10,), BI vm2055, { "CPU": 8, "HDD": 250, "RAM": 16, "SLA-Infrastructure": "EXT4H", "SSD": 25, "Traffic": 250}),
3023615=HsBookingItemEntity(CLOUD_SERVER, [2022-08-10,), BI vm2010, { "CPU": 2, "RAM": 2, "SLA-Infrastructure": "EXT4H", "SSD": 50, "Traffic": 250})
} }
"""); """);
} }
@Test @Test
@Order(9000) @Order(19000)
@Commit @Commit
void persistEntities() { void persistHostingAssetEntities() {
System.out.println("PERSISTING to database '" + jdbcUrl + "' as user '" + postgresAdminUser + "'"); System.out.println("PERSISTING hosting-assets to database '" + jdbcUrl + "' as user '" + postgresAdminUser + "'");
deleteTestDataFromHsOfficeTables();
resetHsOfficeSequences();
deleteFromTestTables();
deleteFromRbacTables();
jpaAttempt.transacted(() -> { jpaAttempt.transacted(() -> {
context(rbacSuperuser); context(rbacSuperuser);
bookingItems.forEach( bookingProjects.forEach(this::persist);
(key, bi) -> HsBookingItemEntityValidatorRegistry.validated(bi)
);
}).assertSuccessful(); }).assertSuccessful();
jpaAttempt.transacted(() -> { jpaAttempt.transacted(() -> {
context(rbacSuperuser); context(rbacSuperuser);
hostingAssets.forEach((key, ha) -> bookingItems.forEach(this::persistRecursively);
new HostingAssetEntitySaveProcessor(ha) }).assertSuccessful();
.preprocessEntity()
.validateEntity() persistHostingAssetsOfType(IPV4_NUMBER);
.prepareForSave() persistHostingAssetsOfType(CLOUD_SERVER);
// .saveUsing(assetRepo::save) persistHostingAssetsOfType(MANAGED_SERVER);
// .validateContext() persistHostingAssetsOfType(MANAGED_WEBSPACE);
}
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() FIXME
}
}
); );
}).assertSuccessful(); }).assertSuccessful();
} }
@ -348,12 +360,14 @@ public class ImportHostingAssets extends ImportOfficeData {
final var bookingItem = HsBookingItemEntity.builder() final var bookingItem = HsBookingItemEntity.builder()
.type(biType) .type(biType)
.caption("BI " + packet_name) .caption("BI " + packet_name)
.project(bookingProjects.get(bp_id))
.validity(toPostgresDateRange(created, cancelled)) .validity(toPostgresDateRange(created, cancelled))
.build(); .build();
bookingItems.put(PACKET_ID_OFFSET + packet_id, bookingItem); bookingItems.put(PACKET_ID_OFFSET + packet_id, bookingItem);
final var haType = determineHaType(basepacket_code); final var haType = determineHaType(basepacket_code);
final var asset = HsHostingAssetEntity.builder() final var asset = HsHostingAssetEntity.builder()
.isLoaded(haType == MANAGED_WEBSPACE) // this turns off identifier validation to accept former default prefixes
.type(haType) .type(haType)
.identifier(packet_name) .identifier(packet_name)
.bookingItem(bookingItem) .bookingItem(bookingItem)
@ -456,17 +470,16 @@ public class ImportHostingAssets extends ImportOfficeData {
case "SLAINFR2H" -> "EXT2H"; case "SLAINFR2H" -> "EXT2H";
case "SLAINFR4H" -> "EXT4H"; case "SLAINFR4H" -> "EXT4H";
case "SLAINFR8H" -> "EXT8H"; case "SLAINFR8H" -> "EXT8H";
case "SLAINFR24H" -> "EXT24H";
default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code); default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code);
}; };
asset.getBookingItem().getResources().put(name, slaValue); asset.getBookingItem().getResources().put(name, slaValue);
} else if (name.equals("SLA-Platform")) { } else if (name.equals("SLA-Platform")) {
final var slaValue = switch (basecomponent_code) { final var slaValue = switch (basecomponent_code) {
case "SLABASIC" -> "BASIC"; case "SLABASIC" -> "BASIC";
case "SLAEXT24H" -> "EXT24H";
case "SLAPLAT2H" -> "EXT2H"; case "SLAPLAT2H" -> "EXT2H";
case "SLAPLAT4H" -> "EXT4H"; case "SLAPLAT4H" -> "EXT4H";
case "SLAPLAT8H" -> "EXT8H"; case "SLAPLAT8H" -> "EXT8H";
case "SLAEXT24H" -> "EXT24H";
default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code); default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code);
}; };
if ( ofNullable(asset.getBookingItem().getResources().get(name)).map("BASIC"::equals).orElse(true) ) { if ( ofNullable(asset.getBookingItem().getResources().get(name)).map("BASIC"::equals).orElse(true) ) {
@ -554,10 +567,10 @@ public class ImportHostingAssets extends ImportOfficeData {
} }
protected static boolean isImportingControlledTestData() { protected static boolean isImportingControlledTestData() {
return MIGRATION_DATA_PATH.equals("migration"); return MIGRATION_DATA_PATH.equals(TEST_DATA_MIGRATION_DATA_PATH);
} }
protected static void assumeThatWeAreImportingControlledTestData() { protected static void assumeThatWeAreImportingControlledTestData() {
// assumeThat(isImportingControlledTestData()).isTrue(); FIXME assumeThat(isImportingControlledTestData()).isTrue();
} }
} }

View File

@ -1,4 +1,4 @@
package net.hostsharing.hsadminng.hs.office.migration; package net.hostsharing.hsadminng.hs.migration;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
@ -25,7 +25,6 @@ import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
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 java.io.*; import java.io.*;
@ -103,7 +102,7 @@ public class ImportOfficeData extends CsvDataImport {
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;
static int relationId = 2000000; static int relationId = 2000000;
@ -120,23 +119,23 @@ public class ImportOfficeData extends CsvDataImport {
-1 -1
); );
private static Map<Integer, HsOfficeContactEntity> contacts = new WriteOnceMap<>(); static Map<Integer, HsOfficeContactEntity> contacts = new WriteOnceMap<>();
private static Map<Integer, HsOfficePersonEntity> persons = new WriteOnceMap<>(); static Map<Integer, HsOfficePersonEntity> persons = new WriteOnceMap<>();
private static Map<Integer, HsOfficePartnerEntity> partners = new WriteOnceMap<>(); static Map<Integer, HsOfficePartnerEntity> partners = new WriteOnceMap<>();
private static Map<Integer, HsOfficeDebitorEntity> debitors = new WriteOnceMap<>(); static Map<Integer, HsOfficeDebitorEntity> debitors = new WriteOnceMap<>();
private static Map<Integer, HsOfficeMembershipEntity> memberships = new WriteOnceMap<>(); static Map<Integer, HsOfficeMembershipEntity> memberships = new WriteOnceMap<>();
private static Map<Integer, HsOfficeRelationEntity> relations = new WriteOnceMap<>(); static Map<Integer, HsOfficeRelationEntity> relations = new WriteOnceMap<>();
private static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new WriteOnceMap<>(); static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new WriteOnceMap<>();
private static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new WriteOnceMap<>(); static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new WriteOnceMap<>();
private static Map<Integer, HsOfficeCoopSharesTransactionEntity> coopShares = new WriteOnceMap<>(); static Map<Integer, HsOfficeCoopSharesTransactionEntity> coopShares = new WriteOnceMap<>();
private static Map<Integer, HsOfficeCoopAssetsTransactionEntity> coopAssets = new WriteOnceMap<>(); static Map<Integer, HsOfficeCoopAssetsTransactionEntity> coopAssets = new WriteOnceMap<>();
@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) {
@ -152,28 +151,39 @@ public class ImportOfficeData extends CsvDataImport {
// 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), 132=partner(P-10152: null null, null),
22=partner(P-11022: null null, null), 20=partner(P-10020: null null, null),
90=partner(P-19090: null null, null), 213=partner(P-10000: null null, null),
99=partner(P-19999: null null, null) 22=partner(P-11022: null null, null),
512041=partner(P-11018: null null, null),
512042=partner(P-11019: null null, null),
90=partner(P-19090: null null, null),
99=partner(P-19999: 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), 132=debitor(D-1015200: rel(anchor='null null, null', type='DEBITOR'), rar),
22=debitor(D-1102200: rel(anchor='null null, null', type='DEBITOR'), xxx), 20=debitor(D-1002000: rel(anchor='null null, null', type='DEBITOR'), xyz),
90=debitor(D-1909000: rel(anchor='null null, null', type='DEBITOR'), yyy), 213=debitor(D-1000000: rel(anchor='null null, null', type='DEBITOR'), hsh),
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz) 22=debitor(D-1102200: rel(anchor='null null, null', type='DEBITOR'), xxx),
512041=debitor(D-1101800: rel(anchor='null null, null', type='DEBITOR'), wws),
512042=debitor(D-1101900: rel(anchor='null null, null', type='DEBITOR'), dph),
90=debitor(D-1909000: rel(anchor='null null, null', type='DEBITOR'), yyy),
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz)
} }
"""); """);
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), 132=Membership(M-1015200, P-10152, [2003-07-12,), ACTIVE),
22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE) 20=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE),
512041=Membership(M-1101800, P-11018, [2021-05-17,), ACTIVE),
512042=Membership(M-1101900, P-11019, [2021-05-25,), ACTIVE)
} }
"""); """);
} }
@ -181,8 +191,7 @@ public class ImportOfficeData extends CsvDataImport {
@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) {
@ -197,83 +206,151 @@ public class ImportOfficeData extends CsvDataImport {
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
{ {
17=partner(P-10017: NP Mellies, Michael, Herr Michael Mellies ), 100=partner(P-10003: ?? Michael Mellies, Herr Michael Mellies , Michael Mellies),
20=partner(P-10020: LP JM GmbH, Herr Philip Meyer-Contract , JM GmbH), 132=partner(P-10152: ?? Ragnar IT-Beratung, Herr Ragnar Richter , Ragnar IT-Beratung),
22=partner(P-11022: ?? Test PS, Petra Schmidt , Test PS), 20=partner(P-10020: LP JM GmbH, Herr Philip Meyer-Contract , JM GmbH),
90=partner(P-19090: NP Camus, Cecilia, Frau Cecilia Camus ), 213=partner(P-10000: LP Hostsharing e.G., Firma Hostmaster Hostsharing , Hostsharing e.G.),
99=partner(P-19999: null null, null) 22=partner(P-11022: ?? Test PS, Petra Schmidt , Test PS),
512041=partner(P-11018: ?? Wasserwerk Südholstein, Frau Christiane Milberg , Wasserwerk Südholstein),
512042=partner(P-11019: ?? Das Perfekte Haus, Herr Richard Wiese , Das Perfekte Haus),
90=partner(P-19090: NP Camus, Cecilia, Frau Cecilia Camus ),
99=partner(P-19999: null null, null)
} }
"""); """);
assertThat(toFormattedString(contacts)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(contacts)).isEqualToIgnoringWhitespace("""
{ {
1101=contact(caption='Herr Michael Mellies ', emailAddresses='{ "main": "mih@example.org"}'), 100=contact(caption='Herr Michael Mellies , Michael Mellies', emailAddresses='{ "main": "michael@mellies.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"}'),
1401=contact(caption='Frau Frauke Fanninga ', emailAddresses='{ "main": "ff@example.org"}'), 132=contact(caption='Herr Ragnar Richter , Ragnar IT-Beratung', emailAddresses='{ "main": "hostsharing@ragnar-richter.de"}'),
1501=contact(caption='Frau Cecilia Camus ', emailAddresses='{ "main": "cc@example.org"}') 1401=contact(caption='Frau Frauke Fanninga ', emailAddresses='{ "main": "ff@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 Mellies', familyName='Mellies', 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 Mellies', type='DEBITOR', holder='?? Michael Mellies'), mim),
20=debitor(D-1002000: rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH'), xyz), 132=debitor(D-1015200: rel(anchor='?? Ragnar IT-Beratung', type='DEBITOR', holder='?? Ragnar IT-Beratung'), rar),
22=debitor(D-1102200: rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS'), xxx), 20=debitor(D-1002000: rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH'), xyz),
90=debitor(D-1909000: rel(anchor='NP Camus, Cecilia', type='DEBITOR', holder='NP Camus, Cecilia'), yyy), 213=debitor(D-1000000: rel(anchor='LP Hostsharing e.G.', type='DEBITOR', holder='LP Hostsharing e.G.'), hsh),
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz) 22=debitor(D-1102200: rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS'), xxx),
512041=debitor(D-1101800: rel(anchor='?? Wasserwerk Südholstein', type='DEBITOR', holder='?? Wasserwerk Südholstein'), wws),
512042=debitor(D-1101900: rel(anchor='?? Das Perfekte Haus', type='DEBITOR', holder='?? Das Perfekte Haus'), dph),
90=debitor(D-1909000: rel(anchor='NP Camus, Cecilia', type='DEBITOR', holder='NP Camus, Cecilia'), yyy),
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz)
} }
"""); """);
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), 132=Membership(M-1015200, P-10152, [2003-07-12,), ACTIVE),
22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE) 20=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE),
512041=Membership(M-1101800, P-11018, [2021-05-17,), ACTIVE),
512042=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 Mellies', contact='Herr Michael Mellies , Michael Mellies'),
2000001=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), 2000001=rel(anchor='?? Michael Mellies', type='DEBITOR', holder='?? Michael Mellies', contact='Herr Michael Mellies , Michael Mellies'),
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 Mellies', type='OPERATIONS', holder='?? Michael Mellies', contact='Herr Michael Mellies , Michael Mellies'),
2000021=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'), 2000021=rel(anchor='?? Michael Mellies', type='REPRESENTATIVE', holder='?? Michael Mellies', contact='Herr Michael Mellies , Michael Mellies'),
2000022=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga '), 2000022=rel(anchor='?? Michael Mellies', type='SUBSCRIBER', mark='operations-discussion', holder='?? Michael Mellies', contact='Herr Michael Mellies , Michael Mellies'),
2000023=rel(anchor='NP Camus, Cecilia', type='OPERATIONS', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus '), 2000023=rel(anchor='?? Michael Mellies', type='SUBSCRIBER', mark='operations-announce', holder='?? Michael Mellies', contact='Herr Michael Mellies , Michael Mellies'),
2000024=rel(anchor='NP Camus, Cecilia', type='REPRESENTATIVE', holder='NP Camus, Cecilia', contact='Frau Cecilia Camus ') 2000024=rel(anchor='?? Michael Mellies', type='SUBSCRIBER', mark='generalversammlung', holder='?? Michael Mellies', contact='Herr Michael Mellies , Michael Mellies'),
2000025=rel(anchor='?? Michael Mellies', type='SUBSCRIBER', mark='members-announce', holder='?? Michael Mellies', contact='Herr Michael Mellies , Michael Mellies'),
2000026=rel(anchor='?? Michael Mellies', type='SUBSCRIBER', mark='members-discussion', holder='?? Michael Mellies', contact='Herr Michael Mellies , Michael Mellies'),
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 ')
} }
"""); """);
} }
@ -281,8 +358,9 @@ public class ImportOfficeData extends CsvDataImport {
@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) {
@ -293,20 +371,23 @@ public class ImportOfficeData extends CsvDataImport {
@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'),
235600=bankAccount(DE02300209000106531065: holder='JM e.K.', bic='CMCIDEDD'), 30=bankAccount(DE02300209000106531065: holder='Ragnar Richter', bic='GENODEM1GLS'),
235662=bankAccount(DE49500105174516484892: holder='JM GmbH', bic='INGDDEFFXXX') 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("""
{ {
234234=SEPA-Mandate(DE37500105177419788228, MH12345, 2004-06-12, [2004-06-15,)), 132=SEPA-Mandate(DE37500105177419788228, HS-10003-20140801, 2013-12-01, [2013-12-01,)),
235600=SEPA-Mandate(DE02300209000106531065, JM33344, 2004-01-15, [2004-01-20,2005-06-28)), 30=SEPA-Mandate(DE02300209000106531065, HS-10152-20140801, 2013-12-01, [2013-12-01,2016-02-16)),
235662=SEPA-Mandate(DE49500105174516484892, JM33344, 2005-06-28, [2005-07-01,)) 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,))
} }
"""); """);
} }
@ -316,7 +397,7 @@ public class ImportOfficeData extends CsvDataImport {
void importCoopShares() { void importCoopShares() {
assumeThatWeAreExplicitlyImportingOfficeData(); assumeThatWeAreExplicitlyImportingOfficeData();
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "share-transactions.csv")) { 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) {
@ -332,11 +413,15 @@ public class ImportOfficeData extends CsvDataImport {
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),
33451=CoopShareTransaction(M-1002000: 2000-12-06, SUBSCRIPTION, 2, 1002000, initial share subscription), 279=CoopShareTransaction(M-1015200: 2013-10-21, SUBSCRIPTION, 1, 1015200),
33701=CoopShareTransaction(M-1001700: 2005-01-10, SUBSCRIPTION, 40, 1001700, increase), 3=CoopShareTransaction(M-1000300: 2000-12-06, SUBSCRIPTION, 80, 1000300),
33810=CoopShareTransaction(M-1002000: 2016-12-31, CANCELLATION, 22, 1002000, membership ended) 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)
}
"""); """);
} }
@ -345,7 +430,7 @@ public class ImportOfficeData extends CsvDataImport {
void importCoopAssets() { void importCoopAssets() {
assumeThatWeAreExplicitlyImportingOfficeData(); 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) {
@ -361,16 +446,15 @@ public class ImportOfficeData extends CsvDataImport {
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),
31000=CoopAssetsTransaction(M-1002000: 2000-12-06, DEPOSIT, 128.00, 1002000, for subscription B), 1094=CoopAssetsTransaction(M-1000300: 2023-10-06, DEPOSIT, 3072, 1000300, Kapitalerhoehung - Ueberweisung),
32000=CoopAssetsTransaction(M-1001700: 2005-01-10, DEPOSIT, 2560.00, 1001700, for subscription C), 358=CoopAssetsTransaction(M-1000300: 2000-12-06, DEPOSIT, 5120, 1000300),
33001=CoopAssetsTransaction(M-1001700: 2005-01-10, TRANSFER, -512.00, 1001700, for transfer to 10), 442=CoopAssetsTransaction(M-1015200: 2003-07-07, DEPOSIT, 64, 1015200),
33002=CoopAssetsTransaction(M-1002000: 2005-01-10, ADOPTION, 512.00, 1002000, for transfer from 7), 577=CoopAssetsTransaction(M-1000300: 2011-12-12, DEPOSIT, 1024, 1000300),
34001=CoopAssetsTransaction(M-1002000: 2016-12-31, CLEARING, -8.00, 1002000, for cancellation D), 632=CoopAssetsTransaction(M-1015200: 2013-10-21, DEPOSIT, 64, 1015200),
34002=CoopAssetsTransaction(M-1002000: 2016-12-31, DISBURSAL, -100.00, 1002000, for cancellation D), 885=CoopAssetsTransaction(M-1000300: 2020-12-15, DEPOSIT, 6144, 1000300, Einzahlung),
34003=CoopAssetsTransaction(M-1002000: 2016-12-31, LOSS, -20.00, 1002000, for cancellation D), 924=CoopAssetsTransaction(M-1101800: 2021-05-21, DEPOSIT, 256, 1101800, Beitritt - Lastschrift),
35001=CoopAssetsTransaction(M-1909000: 2024-01-15, DEPOSIT, 128.00, 1909000, for subscription E), 925=CoopAssetsTransaction(M-1101900: 2021-05-31, DEPOSIT, 64, 1101900, Beitritt - Lastschrift)
35002=CoopAssetsTransaction(M-1909000: 2024-01-20, ADJUSTMENT, -128.00, 1909000, chargeback for subscription E, M-1909000:DEP:+128.00)
} }
"""); """);
} }
@ -383,10 +467,12 @@ public class ImportOfficeData extends CsvDataImport {
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), 132=Membership(M-1015200, P-10152, [2003-07-12,), ACTIVE),
22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE), 20=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
90=Membership(M-1909000, P-19090, empty, INVALID) 22=Membership(M-1102200, P-11022, [2021-04-01,), ACTIVE),
512041=Membership(M-1101800, P-11018, [2021-05-17,), ACTIVE),
512042=Membership(M-1101900, P-11019, [2021-05-25,), ACTIVE)
} }
"""); """);
} }
@ -394,8 +480,6 @@ public class ImportOfficeData extends CsvDataImport {
@Test @Test
@Order(2000) @Order(2000)
void verifyAllPartnersHavePersons() { void verifyAllPartnersHavePersons() {
assumeThatWeAreExplicitlyImportingOfficeData();
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();
@ -509,10 +593,9 @@ public class ImportOfficeData extends CsvDataImport {
@Test @Test
@Order(9000) @Order(9000)
@Commit void persistOfficeEntities() {
void persistEntities() {
System.out.println("PERSISTING to database '" + jdbcUrl + "' as user '" + postgresAdminUser + "'"); System.out.println("PERSISTING office data to database '" + jdbcUrl + "' as user '" + postgresAdminUser + "'");
deleteTestDataFromHsOfficeTables(); deleteTestDataFromHsOfficeTables();
resetHsOfficeSequences(); resetHsOfficeSequences();
deleteFromTestTables(); deleteFromTestTables();
@ -590,7 +673,7 @@ public class ImportOfficeData extends CsvDataImport {
} }
protected void assumeThatWeAreExplicitlyImportingOfficeData() { protected void assumeThatWeAreExplicitlyImportingOfficeData() {
assumeThat(true).isFalse(); // not throwing AssumptionException
} }
private static boolean isImportingControlledTestData() { private static boolean isImportingControlledTestData() {
@ -623,24 +706,20 @@ public class ImportOfficeData extends CsvDataImport {
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"))) { if (IGNORE_BUSINESS_PARTNERS.contains(rec.getInteger("bp_id"))) {
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
); );
@ -848,10 +927,10 @@ public class ImportOfficeData extends CsvDataImport {
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;
} }
@ -909,6 +988,7 @@ public class ImportOfficeData extends CsvDataImport {
}); });
assertNoMissingContractualRelations(); assertNoMissingContractualRelations();
useHostsharingAsPartnerAnchor();
} }
private static void assertNoMissingContractualRelations() { private static void assertNoMissingContractualRelations() {
@ -928,6 +1008,16 @@ public class ImportOfficeData extends CsvDataImport {
} }
} }
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 + ",");

View File

@ -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"

View 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;
1 hive_id hive_name inet_addr_id description
2 1 h00 358
3 2 h01 359
4 4 h02 360
5 7 h03 361
6 13 h04 430
7 14 h50 433
8 20 h05 354
9 21 h06 355
10 22 h07 357
11 28 h60 363
12 31 h63 431
13 37 h67 381
14 38 h97 537
15 39 h96 536
16 45 h74 485
17 50 h82 514
18 128 h19 565
19 148 h50 522
20 163 h92 457
21 173 h25 1759
22 192 h93 1778
23 193 h95 1779
24 205 vm1107 1861
25 208 vm1110 1864
26 210 vm1112 1833

View File

@ -0,0 +1,8 @@
inet_addr_id;inet_addr;description
363;83.223.95.34;
402;83.223.95.73;
433;83.223.95.104;
473;83.223.95.144;
574;83.223.95.245;
1168;83.223.79.72;
1790;83.223.94.179;
1 inet_addr_id inet_addr description
2 363 83.223.95.34
3 402 83.223.95.73
4 433 83.223.95.104
5 473 83.223.95.144
6 574 83.223.95.245
7 1168 83.223.79.72
8 1790 83.223.94.179

View File

@ -0,0 +1,11 @@
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
#1163;SRV/MGD;vm1083;37;50;2014-01-24;;514;;f
1447;SRV/MGD;vm1093;213;163;2014-11-28;;457;;t
19959;PAC/WEB;dph00;512042;163;2021-06-02;;574;;0
23611;SRV/CLD;vm2097;512041;;2022-08-10;;1790;;0
1 packet_id basepacket_code packet_name bp_id hive_id created cancelled cur_inet_addr_id old_inet_addr_id free
2 630 PAC/WEB hsh00 213 14 2001-06-01 473 1
3 968 SRV/MGD vm1061 132 28 2013-04-01 363 0
4 978 SRV/MGD vm1050 213 14 2013-04-01 433 1
5 1061 SRV/MGD vm1068 100 37 2013-08-19 381 f
6 1094 PAC/WEB lug00 100 37 2013-09-10 1168 1
7 1112 PAC/WEB mim00 100 37 2013-09-17 402 1
8 #1163 SRV/MGD vm1083 37 50 2014-01-24 514 f
9 1447 SRV/MGD vm1093 213 163 2014-11-28 457 t
10 19959 PAC/WEB dph00 512042 163 2021-06-02 574 0
11 23611 SRV/CLD vm2097 512041 2022-08-10 1790 0

View 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;0;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;76800;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;
1 packet_component_id packet_id quantity basecomponent_code created cancelled
2 46105 1094 10 TRAFFIC 2017-03-27
3 46109 1094 5 MULTI 2017-03-27
4 46111 1094 0 DAEMON 2017-03-27
5 46113 1094 1024 QUOTA 2017-03-27
6 46117 1112 0 DAEMON 2017-03-27
7 46121 1112 20 TRAFFIC 2017-03-27
8 46122 1112 5 MULTI 2017-03-27
9 46123 1112 3072 QUOTA 2017-03-27
10 143133 1094 1 SLABASIC 2017-09-01
11 143483 1112 1 SLABASIC 2017-09-01
12 757383 1112 0 SLAEXT24H
13 770533 1094 0 SLAEXT24H
14 784283 1112 0 OFFICE
15 797433 1094 0 OFFICE
16 1228033 1112 0 STORAGE
17 1241433 1094 0 STORAGE
18 1266451 978 0 SLAPLAT4H 2021-10-05
19 1266452 978 250 TRAFFIC 2021-10-05
20 1266453 978 0 SLAPLAT8H 2021-10-05
21 1266454 978 0 SLAMAIL4H 2021-10-05
22 1266455 978 0 SLAMARIA8H 2021-10-05
23 1266456 978 0 SLAPGSQL4H 2021-10-05
24 1266457 978 0 SLAWEB4H 2021-10-05
25 1266458 978 0 SLAMARIA4H 2021-10-05
26 1266459 978 0 SLAPGSQL8H 2021-10-05
27 1266460 978 0 SLAOFFIC8H 2021-10-05
28 1266461 978 0 SLAWEB8H 2021-10-05
29 1266462 978 256000 STORAGE 2021-10-05
30 1266463 978 153600 QUOTA 2021-10-05
31 1266464 978 0 SLAOFFIC4H 2021-10-05
32 1266465 978 32768 RAM 2021-10-05
33 1266466 978 4 CPU 2021-10-05
34 1266467 978 1 SLABASIC 2021-10-05
35 1266468 978 0 SLAMAIL8H 2021-10-05
36 1275583 978 0 SLAPLAT2H 2022-04-20
37 1280533 978 0 SLAWEB2H 2022-04-20
38 1285483 978 0 SLAMARIA2H 2022-04-20
39 1290433 978 0 SLAPGSQL2H 2022-04-20
40 1295383 978 0 SLAMAIL2H 2022-04-20
41 1300333 978 0 SLAOFFIC2H 2022-04-20
42 1305933 1447 0 SLAWEB2H 2022-05-02
43 1305934 1447 0 SLAPLAT4H 2022-05-02
44 1305935 1447 0 SLAWEB8H 2022-05-02
45 1305936 1447 0 SLAOFFIC4H 2022-05-02
46 1305937 1447 0 SLAMARIA4H 2022-05-02
47 1305938 1447 0 SLAOFFIC8H 2022-05-02
48 1305939 1447 1 SLABASIC 2022-05-02
49 1305940 1447 0 SLAMAIL8H 2022-05-02
50 1305941 1447 0 SLAPGSQL4H 2022-05-02
51 1305942 1447 6 CPU 2022-05-02
52 1305943 1447 250 TRAFFIC 2022-05-02
53 1305944 1447 0 SLAOFFIC2H 2022-05-02
54 1305945 1447 0 SLAMAIL4H 2022-05-02
55 1305946 1447 0 SLAPGSQL2H 2022-05-02
56 1305947 1447 0 SLAMARIA2H 2022-05-02
57 1305948 1447 0 SLAMARIA8H 2022-05-02
58 1305949 1447 0 SLAWEB4H 2022-05-02
59 1305950 1447 16384 RAM 2022-05-02
60 1305951 1447 0 SLAPGSQL8H 2022-05-02
61 1305952 1447 512000 STORAGE 2022-05-02
62 1305953 1447 0 SLAMAIL2H 2022-05-02
63 1305954 1447 0 SLAPLAT2H 2022-05-02
64 1305955 1447 0 SLAPLAT8H 2022-05-02
65 1305956 1447 307200 QUOTA 2022-05-02
66 1312013 23611 1 SLABASIC 2022-08-10
67 1312014 23611 0 BANDWIDTH 2022-08-10
68 1312015 23611 12288 RAM 2022-08-10
69 1312016 23611 25600 QUOTA 2022-08-10
70 1312017 23611 0 SLAINFR8H 2022-08-10
71 1312018 23611 0 STORAGE 2022-08-10
72 1312019 23611 0 SLAINFR2H 2022-08-10
73 1312020 23611 8 CPU 2022-08-10
74 1312021 23611 250 TRAFFIC 2022-08-10
75 1312022 23611 0 SLAINFR4H 2022-08-10
76 1313883 978 0 BANDWIDTH
77 1316583 1447 0 BANDWIDTH
78 1338074 968 0 SLAMARIA2H 2023-09-05
79 1338075 968 384000 QUOTA 2023-09-05
80 1338076 968 1 SLAMAIL8H 2023-09-05
81 1338077 968 0 BANDWIDTH 2023-09-05
82 1338078 968 0 SLAWEB2H 2023-09-05
83 1338079 968 0 SLAOFFIC4H 2023-09-05
84 1338080 968 256000 STORAGE 2023-09-05
85 1338081 968 0 SLAPLAT4H 2023-09-05
86 1338082 968 0 SLAPGSQL2H 2023-09-05
87 1338083 968 0 SLAPLAT2H 2023-09-05
88 1338084 968 250 TRAFFIC 2023-09-05
89 1338085 968 1 SLAMARIA8H 2023-09-05
90 1338086 968 0 SLAPGSQL4H 2023-09-05
91 1338087 968 0 SLAMAIL2H 2023-09-05
92 1338088 968 1 SLAPLAT8H 2023-09-05
93 1338089 968 0 SLAWEB4H 2023-09-05
94 1338090 968 6 CPU 2023-09-05
95 1338091 968 1 SLAPGSQL8H 2023-09-05
96 1338092 968 0 SLAMARIA4H 2023-09-05
97 1338093 968 0 SLAMAIL4H 2023-09-05
98 1338094 968 14336 RAM 2023-09-05
99 1338095 968 0 SLAOFFIC2H 2023-09-05
100 1338096 968 0 SLAOFFIC8H 2023-09-05
101 1338097 968 1 SLABASIC 2023-09-05
102 1338098 968 1 SLAWEB8H 2023-09-05
103 1339228 19959 20 TRAFFIC 2023-10-27
104 1339229 19959 1 SLABASIC 2023-10-27
105 1339230 19959 0 DAEMON 2023-10-27
106 1339231 19959 25600 QUOTA 2023-10-27
107 1339232 19959 0 STORAGE 2023-10-27
108 1339233 19959 0 SLAEXT24H 2023-10-27
109 1339234 19959 0 OFFICE 2023-10-27
110 1339235 19959 1 MULTI 2023-10-27
111 1341088 1061 0 SLAOFFIC2H 2023-12-14
112 1341089 1061 0 SLAOFFIC8H 2023-12-14
113 1341090 1061 0 STORAGE 2023-12-14
114 1341091 1061 0 SLAMAIL4H 2023-12-14
115 1341092 1061 0 SLAMAIL2H 2023-12-14
116 1341093 1061 0 SLAPLAT2H 2023-12-14
117 1341094 1061 4096 RAM 2023-12-14
118 1341095 1061 0 SLAPLAT4H 2023-12-14
119 1341096 1061 1 SLAPGSQL8H 2023-12-14
120 1341097 1061 2 CPU 2023-12-14
121 1341098 1061 76800 QUOTA 2023-12-14
122 1341099 1061 0 SLAMAIL8H 2023-12-14
123 1341100 1061 1 SLABASIC 2023-12-14
124 1341101 1061 1 SLAMARIA8H 2023-12-14
125 1341102 1061 0 SLAPGSQL4H 2023-12-14
126 1341103 1061 0 SLAPGSQL2H 2023-12-14
127 1341104 1061 0 SLAMARIA4H 2023-12-14
128 1341105 1061 0 SLAOFFIC4H 2023-12-14
129 1341106 1061 1 SLAPLAT8H 2023-12-14
130 1341107 1061 0 BANDWIDTH 2023-12-14
131 1341108 1061 1 SLAWEB8H 2023-12-14
132 1341109 1061 0 SLAWEB2H 2023-12-14
133 1341110 1061 0 SLAMARIA2H 2023-12-14
134 1341111 1061 250 TRAFFIC 2023-12-14
135 1341112 1061 0 SLAWEB4H 2023-12-14
136 1346628 630 0 SLAEXT24H 2024-03-19
137 1346629 630 0 OFFICE 2024-03-19
138 1346630 630 16384 QUOTA 2024-03-19
139 1346631 630 0 DAEMON 2024-03-19
140 1346632 630 10240 STORAGE 2024-03-19
141 1346633 630 1 SLABASIC 2024-03-19
142 1346634 630 50 TRAFFIC 2024-03-19
143 1346635 630 25 MULTI 2024-03-19

View File

@ -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
Internal Server Error - Gitea: Git with a cup of tea

Internal Server Error

Gitea Version: 1.22.3