add coop assets+shares scenario tests
This commit is contained in:
parent
5f454a2ebe
commit
9a9e3e2e73
@ -0,0 +1,28 @@
|
|||||||
|
package net.hostsharing.hsadminng.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class FormattedBigDecimalDeserializer extends JsonDeserializer<BigDecimal> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||||
|
final var numberStr = p.getText();
|
||||||
|
try {
|
||||||
|
final var format = NumberFormat.getInstance(Locale.GERMANY);
|
||||||
|
if (format instanceof DecimalFormat) {
|
||||||
|
((DecimalFormat) format).setParseBigDecimal(true);
|
||||||
|
}
|
||||||
|
return (BigDecimal) format.parse(numberStr);
|
||||||
|
} catch (final ParseException e) {
|
||||||
|
throw new IOException("Failed to parse BigDecimal from string: " + numberStr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.config;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import org.openapitools.jackson.nullable.JsonNullableModule;
|
import org.openapitools.jackson.nullable.JsonNullableModule;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -9,15 +10,25 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class JsonObjectMapperConfiguration {
|
public class JsonObjectMapperConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Primary
|
@Primary
|
||||||
public Jackson2ObjectMapperBuilder customObjectMapper() {
|
public Jackson2ObjectMapperBuilder customObjectMapper() {
|
||||||
|
// HOWTO: add JSON converters and specify other JSON mapping configurations
|
||||||
return new Jackson2ObjectMapperBuilder()
|
return new Jackson2ObjectMapperBuilder()
|
||||||
|
.modulesToInstall(formattedBigDecimalModule())
|
||||||
.modules(new JsonNullableModule(), new JavaTimeModule())
|
.modules(new JsonNullableModule(), new JavaTimeModule())
|
||||||
.featuresToEnable(JsonParser.Feature.ALLOW_COMMENTS, JsonParser.Feature.ALLOW_COMMENTS)
|
.featuresToEnable(JsonParser.Feature.ALLOW_COMMENTS, JsonParser.Feature.ALLOW_COMMENTS)
|
||||||
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SimpleModule formattedBigDecimalModule() {
|
||||||
|
final var module = new SimpleModule();
|
||||||
|
module.addDeserializer(BigDecimal.class, new FormattedBigDecimalDeserializer());
|
||||||
|
return module;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import jakarta.persistence.AttributeConverter;
|
|||||||
import jakarta.persistence.Converter;
|
import jakarta.persistence.Converter;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
// HOWTO: convert data types for exchange between PostgreSQL and Java/Hibernate/JPA-Entities
|
||||||
@Converter(autoApply = true)
|
@Converter(autoApply = true)
|
||||||
public class HsOfficePersonTypeConverter implements AttributeConverter<HsOfficePersonType, String> {
|
public class HsOfficePersonTypeConverter implements AttributeConverter<HsOfficePersonType, String> {
|
||||||
|
|
||||||
|
@ -12,10 +12,13 @@ import net.hostsharing.hsadminng.hs.office.scenarios.debitor.FinallyDeleteSepaMa
|
|||||||
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.DontDeleteDefaultDebitor;
|
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.DontDeleteDefaultDebitor;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.InvalidateSepaMandateForDebitor;
|
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.InvalidateSepaMandateForDebitor;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CancelMembership;
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CancelMembership;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CreateCoopSharesCancellationTransaction;
|
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CreateCoopSharesRevertTransaction;
|
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CreateCoopSharesSubscriptionTransaction;
|
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CreateMembership;
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CreateMembership;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets.CreateCoopAssetsDepositTransaction;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets.CreateCoopAssetsDisbursalTransaction;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets.CreateCoopAssetsRevertTransaction;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares.CreateCoopSharesCancellationTransaction;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares.CreateCoopSharesRevertTransaction;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares.CreateCoopSharesSubscriptionTransaction;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.partner.AddOperationsContactToPartner;
|
import net.hostsharing.hsadminng.hs.office.scenarios.partner.AddOperationsContactToPartner;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.partner.CreatePartner;
|
import net.hostsharing.hsadminng.hs.office.scenarios.partner.CreatePartner;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.DeleteDebitor;
|
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.DeleteDebitor;
|
||||||
@ -348,7 +351,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
void shouldRevertCoopSharesSubscription() {
|
void shouldRevertCoopSharesSubscription() {
|
||||||
new CreateCoopSharesRevertTransaction(this)
|
new CreateCoopSharesRevertTransaction(this)
|
||||||
.given("memberNumber", "3101000")
|
.given("memberNumber", "3101000")
|
||||||
.given("comment", "reverting some incorrect subscription")
|
.given("comment", "reverting some incorrect transaction")
|
||||||
.given("dateOfIncorrectTransaction", "2024-02-15")
|
.given("dateOfIncorrectTransaction", "2024-02-15")
|
||||||
.doRun();
|
.doRun();
|
||||||
}
|
}
|
||||||
@ -367,6 +370,45 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
.doRun();
|
.doRun();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4301)
|
||||||
|
@Requires("Membership: M-3101000 - Test AG")
|
||||||
|
@Produces("Coop-Assets DEPOSIT Transaction")
|
||||||
|
void shouldSubscribeCoopAssets() {
|
||||||
|
new CreateCoopAssetsDepositTransaction(this)
|
||||||
|
.given("memberNumber", "3101000")
|
||||||
|
.given("reference", "sign 2024-01-15")
|
||||||
|
.given("assetValue", 100*64)
|
||||||
|
.given("comment", "disposal for initial shares")
|
||||||
|
.given("transactionDate", "2024-01-15")
|
||||||
|
.doRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4302)
|
||||||
|
@Requires("Membership: M-3101000 - Test AG")
|
||||||
|
void shouldRevertCoopAssetsSubscription() {
|
||||||
|
new CreateCoopAssetsRevertTransaction(this)
|
||||||
|
.given("memberNumber", "3101000")
|
||||||
|
.given("comment", "reverting some incorrect transaction")
|
||||||
|
.given("dateOfIncorrectTransaction", "2024-02-15")
|
||||||
|
.doRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4302)
|
||||||
|
@Requires("Coop-Assets DEPOSIT Transaction")
|
||||||
|
@Produces("Coop-Assets DISBURSAL Transaction")
|
||||||
|
void shouldDisburseCoopAssets() {
|
||||||
|
new CreateCoopAssetsDisbursalTransaction(this)
|
||||||
|
.given("memberNumber", "3101000")
|
||||||
|
.given("reference", "cancel 2024-01-15")
|
||||||
|
.given("valueToDisburse", 8*64)
|
||||||
|
.given("comment", "disbursal according to shares cancellation")
|
||||||
|
.given("transactionDate", "2024-02-15")
|
||||||
|
.doRun();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(4900)
|
@Order(4900)
|
||||||
@Requires("Membership: M-3101000 - Test AG")
|
@Requires("Membership: M-3101000 - Test AG")
|
||||||
|
@ -19,7 +19,7 @@ public class PathAssertion {
|
|||||||
public Consumer<UseCase.HttpResponse> contains(final String resolvableValue) {
|
public Consumer<UseCase.HttpResponse> contains(final String resolvableValue) {
|
||||||
return response -> {
|
return response -> {
|
||||||
try {
|
try {
|
||||||
response.path(path).map(Object::toString).contains(ScenarioTest.resolve(resolvableValue, DROP_COMMENTS));
|
response.path(path).map(this::asString).contains(ScenarioTest.resolve(resolvableValue, DROP_COMMENTS));
|
||||||
} catch (final AssertionError e) {
|
} catch (final AssertionError e) {
|
||||||
// without this, the error message is often lacking important context
|
// without this, the error message is often lacking important context
|
||||||
fail(e.getMessage() + " in `path(\"" + path + "\").contains(\"" + resolvableValue + "\")`" );
|
fail(e.getMessage() + " in `path(\"" + path + "\").contains(\"" + resolvableValue + "\")`" );
|
||||||
@ -37,4 +37,15 @@ public class PathAssertion {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String asString(final Object value) {
|
||||||
|
if (value instanceof Double doubleValue) {
|
||||||
|
if (doubleValue % 1 == 0) {
|
||||||
|
return String.valueOf(doubleValue.intValue()); // avoid trailing ".0"
|
||||||
|
} else {
|
||||||
|
return doubleValue.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
||||||
|
|
||||||
|
public class CreateCoopAssetsDepositTransaction extends CreateCoopAssetsTransaction {
|
||||||
|
|
||||||
|
public CreateCoopAssetsDepositTransaction(final ScenarioTest testSuite) {
|
||||||
|
super(testSuite);
|
||||||
|
|
||||||
|
given("transactionType", "DEPOSIT");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
||||||
|
|
||||||
|
public class CreateCoopAssetsDisbursalTransaction extends CreateCoopAssetsTransaction {
|
||||||
|
|
||||||
|
public CreateCoopAssetsDisbursalTransaction(final ScenarioTest testSuite) {
|
||||||
|
super(testSuite);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpResponse run() {
|
||||||
|
given("transactionType", "DISBURSAL");
|
||||||
|
given("assetValue", "-%{valueToDisburse}");
|
||||||
|
return super.run();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
||||||
|
|
||||||
|
public class CreateCoopAssetsRevertTransaction extends CreateCoopAssetsTransaction {
|
||||||
|
|
||||||
|
public CreateCoopAssetsRevertTransaction(final ScenarioTest testSuite) {
|
||||||
|
super(testSuite);
|
||||||
|
|
||||||
|
requires("CoopAssets-Transaction with incorrect assetValue", alias ->
|
||||||
|
new CreateCoopAssetsDepositTransaction(testSuite)
|
||||||
|
.given("memberNumber", "3101000")
|
||||||
|
.given("reference", "sign %{dateOfIncorrectTransaction}") // same as revertedAssetTx
|
||||||
|
.given("assetValue", 10)
|
||||||
|
.given("comment", "coop-assets deposit transaction with wrong asset value")
|
||||||
|
.given("transactionDate", "%{dateOfIncorrectTransaction}")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpResponse run() {
|
||||||
|
given("transactionType", "REVERSAL");
|
||||||
|
given("assetValue", -100);
|
||||||
|
given("revertedAssetTx", uuid("CoopAssets-Transaction with incorrect assetValue"));
|
||||||
|
return super.run();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets;
|
||||||
|
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.UseCase;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
import static io.restassured.http.ContentType.JSON;
|
||||||
|
import static org.springframework.http.HttpStatus.OK;
|
||||||
|
|
||||||
|
public abstract class CreateCoopAssetsTransaction extends UseCase<CreateCoopAssetsTransaction> {
|
||||||
|
|
||||||
|
public CreateCoopAssetsTransaction(final ScenarioTest testSuite) {
|
||||||
|
super(testSuite);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpResponse run() {
|
||||||
|
|
||||||
|
obtain("#{Find }membershipUuid", () ->
|
||||||
|
httpGet("/api/hs/office/memberships?memberNumber=&{memberNumber}")
|
||||||
|
.expecting(OK).expecting(JSON).expectArrayElements(1),
|
||||||
|
response -> response.getFromBody("$[0].uuid")
|
||||||
|
);
|
||||||
|
|
||||||
|
return withTitle("Create the Coop-Assets-%{transactionType} Transaction", () ->
|
||||||
|
httpPost("/api/hs/office/coopassetstransactions", usingJsonBody("""
|
||||||
|
{
|
||||||
|
"membership.uuid": ${membershipUuid},
|
||||||
|
"transactionType": ${transactionType},
|
||||||
|
"reference": ${reference},
|
||||||
|
"assetValue": ${assetValue},
|
||||||
|
"comment": ${comment},
|
||||||
|
"valueDate": ${transactionDate},
|
||||||
|
"revertedAssetTx.uuid": ${revertedAssetTx???}
|
||||||
|
}
|
||||||
|
"""))
|
||||||
|
.expecting(HttpStatus.CREATED).expecting(ContentType.JSON)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void verify(final HttpResponse response) {
|
||||||
|
verify("Verify Coop-Assets %{transactionType}-Transaction",
|
||||||
|
() -> httpGet("/api/hs/office/coopassetstransactions/" + response.getLocationUuid())
|
||||||
|
.expecting(HttpStatus.OK).expecting(ContentType.JSON),
|
||||||
|
path("transactionType").contains("%{transactionType}"),
|
||||||
|
path("assetValue").contains("%{assetValue}"),
|
||||||
|
path("comment").contains("%{comment}"),
|
||||||
|
path("valueDate").contains("%{transactionDate}")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.scenarios.membership;
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.scenarios.membership;
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ public class CreateCoopSharesRevertTransaction extends CreateCoopSharesTransacti
|
|||||||
.given("memberNumber", "3101000")
|
.given("memberNumber", "3101000")
|
||||||
.given("reference", "sign %{dateOfIncorrectTransaction}") // same as revertedShareTx
|
.given("reference", "sign %{dateOfIncorrectTransaction}") // same as revertedShareTx
|
||||||
.given("shareCount", 100)
|
.given("shareCount", 100)
|
||||||
.given("comment", "reverting subscription transaction with wrong share count")
|
.given("comment", "coop-shares subscription transaction with wrong share count")
|
||||||
.given("transactionDate", "%{dateOfIncorrectTransaction}")
|
.given("transactionDate", "%{dateOfIncorrectTransaction}")
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.scenarios.membership;
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.scenarios.membership;
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares;
|
||||||
|
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.UseCase;
|
import net.hostsharing.hsadminng.hs.office.scenarios.UseCase;
|
||||||
@ -23,7 +23,7 @@ public abstract class CreateCoopSharesTransaction extends UseCase<CreateCoopShar
|
|||||||
response -> response.getFromBody("$[0].uuid")
|
response -> response.getFromBody("$[0].uuid")
|
||||||
);
|
);
|
||||||
|
|
||||||
return withTitle("Create the CoopShares-%{transactionType} Transaction", () ->
|
return withTitle("Create the Coop-Shares-%{transactionType} Transaction", () ->
|
||||||
httpPost("/api/hs/office/coopsharestransactions", usingJsonBody("""
|
httpPost("/api/hs/office/coopsharestransactions", usingJsonBody("""
|
||||||
{
|
{
|
||||||
"membership.uuid": ${membershipUuid},
|
"membership.uuid": ${membershipUuid},
|
Loading…
Reference in New Issue
Block a user