diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetTranslations.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsCoopAssetTranslations.java similarity index 92% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetTranslations.java rename to src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsCoopAssetTranslations.java index 7d7abf29..d61f59ed 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetTranslations.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsCoopAssetTranslations.java @@ -1,4 +1,4 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; +package net.hostsharing.hsadminng.hs.office.coopassets; import net.hostsharing.hsadminng.config.MessageTranslator; import net.hostsharing.hsadminng.config.RetroactiveTranslator; @@ -8,7 +8,7 @@ import org.springframework.stereotype.Service; // HOWTO translate messages which got created without i18n support, in this case in a PostgreSQL constraint trigger @Service -public class HsHostingAssetTranslations implements RetroactiveTranslator { +public class HsCoopAssetTranslations implements RetroactiveTranslator { public static final String ERROR_400_PREFIX = "ERROR: [400] "; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsCoopShareTranslations.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsCoopShareTranslations.java new file mode 100644 index 00000000..67665441 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsCoopShareTranslations.java @@ -0,0 +1,26 @@ +package net.hostsharing.hsadminng.hs.office.coopshares; + +import net.hostsharing.hsadminng.config.MessageTranslator; +import net.hostsharing.hsadminng.config.RetroactiveTranslator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +// HOWTO translate messages which got created without i18n support, in this case in a PostgreSQL constraint trigger +@Service +public class HsCoopShareTranslations implements RetroactiveTranslator { + + public static final String ERROR_400_PREFIX = "ERROR: [400] "; + + @Autowired + private MessageTranslator messageTranslator; + + @Override + public boolean canTranslate(final String message) { + return message.equals("ERROR: [400] coop shares transaction would result in a negative number of shares"); + } + + @Override + public String translate(final String message) { + return ERROR_400_PREFIX + messageTranslator.translate(message.substring(ERROR_400_PREFIX.length())); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java index 718ff1ee..2bacca2b 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java @@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.hs.office.coopshares; import io.micrometer.core.annotation.Timed; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import net.hostsharing.hsadminng.config.MessageTranslator; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.errors.MultiValidationException; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeCoopSharesApi; @@ -37,6 +38,9 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar @Autowired private StrictMapper mapper; + @Autowired + private MessageTranslator messageTranslator; + @Autowired private HsOfficeCoopSharesTransactionRepository coopSharesTransactionRepo; @@ -118,32 +122,31 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar MultiValidationException.throwIfNotEmpty(violations); } - private static void validateSubscriptionTransaction( + private void validateSubscriptionTransaction( final HsOfficeCoopSharesTransactionInsertResource requestBody, final ArrayList violations) { if (requestBody.getTransactionType() == SUBSCRIPTION && requestBody.getShareCount() < 0) { - violations.add("for %s, shareCount must be positive but is \"%d\"".formatted( + violations.add(messageTranslator.translate("for transactionType={0}, shareCount must be positive but is {1}", requestBody.getTransactionType(), requestBody.getShareCount())); } } - private static void validateCancellationTransaction( + private void validateCancellationTransaction( final HsOfficeCoopSharesTransactionInsertResource requestBody, final ArrayList violations) { if (requestBody.getTransactionType() == CANCELLATION && requestBody.getShareCount() > 0) { - violations.add("for %s, shareCount must be negative but is \"%d\"".formatted( + violations.add(messageTranslator.translate("for transactionType={0}, shareCount must be negative but is {1}", requestBody.getTransactionType(), requestBody.getShareCount())); } } - private static void validateshareCount( + private void validateshareCount( final HsOfficeCoopSharesTransactionInsertResource requestBody, final ArrayList violations) { if (requestBody.getShareCount() == 0) { - violations.add("shareCount must not be 0 but is \"%d\"".formatted( - requestBody.getShareCount())); + violations.add(messageTranslator.translate("shareCount must not be 0")); } } diff --git a/src/main/resources/i18n/messages_de.properties b/src/main/resources/i18n/messages_de.properties index 14a49800..01da06ad 100644 --- a/src/main/resources/i18n/messages_de.properties +++ b/src/main/resources/i18n/messages_de.properties @@ -12,6 +12,12 @@ unknown\ authorization\ ticket=unbekanntes Autorisierungs-Ticket {0}\ "{1}"\ not\ found\ or\ not\ accessible={0} "{1}" nicht gefunden oder nicht zugänglich but\ is=ist aber +# office.coop-shares +for\ transactionType\={0},\ shareCount\ must\ be\ positive\ but\ is\ {1}=für transactionType={0}, muss shareCount positiv sein, ist aber {1} +for\ transactionType\={0},\ shareCount\ must\ be\ negative\ but\ is\ {1}=für transactionType={0}, muss shareCount negativ sein, ist aber {1} +shareCount\ must\ not\ be\ 0=shareCount darf nicht 0 sein +coop\ shares\ transaction\ would\ result\ in\ a\ negative\ number\ of\ shares=Geschäftsanteile-Transaktion würde zu negativen Geschäftsanteilen führen + # office.coop-assets either\ {0}\ or\ {1}\ must\ be\ given=entweder {0} oder {1} muss angegeben werden either\ {0}\ or\ {1}\ must\ be\ given,\ not\ both=entweder {0} oder {1} muss angegeben werden, nicht beide diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerAcceptanceTest.java index f09093d4..934bcb89 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerAcceptanceTest.java @@ -3,6 +3,7 @@ package net.hostsharing.hsadminng.hs.office.coopshares; import io.restassured.RestAssured; import io.restassured.http.ContentType; import net.hostsharing.hsadminng.HsadminNgApplication; +import net.hostsharing.hsadminng.config.MessageTranslator; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipRepository; import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup; @@ -32,7 +33,7 @@ import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.startsWith; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = {HsadminNgApplication.class, DisableSecurityConfig.class, JpaAttempt.class}) + classes = {HsadminNgApplication.class, DisableSecurityConfig.class, MessageTranslator.class, JpaAttempt.class}) @ActiveProfiles("test") @Transactional @Tag("officeIntegrationTest") @@ -180,7 +181,7 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased } @Nested - class AddCoopSharesTransaction { + class PostNewCoopSharesTransaction { @Test void globalAdmin_canAddCoopSharesTransaction() { @@ -191,6 +192,7 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased final var location = RestAssured // @formatter:off .given() .header("Authorization", "Bearer superuser-alex@hostsharing.net") + .header("Accept-Language", "de") .contentType(ContentType.JSON).body(""" { "membership.uuid": "%s", @@ -306,6 +308,7 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased RestAssured // @formatter:off .given() .header("Authorization", "Bearer superuser-alex@hostsharing.net") + .header("Accept-Language", "de") .contentType(ContentType.JSON) .body(""" { @@ -329,7 +332,7 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased { "statusCode": 400, "statusPhrase": "Bad Request", - "message": "ERROR: [400] coop shares transaction would result in a negative number of shares" + "message": "ERROR: [400] Geschäftsanteile-Transaktion würde zu negativen Geschäftsanteilen führen" } """)); // @formatter:on } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java index e3306853..54f41ca3 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java @@ -1,6 +1,7 @@ package net.hostsharing.hsadminng.hs.office.coopshares; import net.hostsharing.hsadminng.config.MessageTranslator; +import net.hostsharing.hsadminng.config.MessagesResourceConfig; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipRepository; import net.hostsharing.hsadminng.mapper.StrictMapper; @@ -27,7 +28,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(HsOfficeCoopSharesTransactionController.class) -@Import({DisableSecurityConfig.class, MessageTranslator.class}) +@Import({DisableSecurityConfig.class, + MessagesResourceConfig.class, + MessageTranslator.class}) @ActiveProfiles("test") class HsOfficeCoopSharesTransactionControllerRestTest { @@ -61,45 +64,45 @@ class HsOfficeCoopSharesTransactionControllerRestTest { enum BadRequestTestCases { MEMBERSHIP_UUID_MISSING( requestBody -> requestBody.without("membership.uuid"), - "membershipUuid must not be null"), + "membershipUuid darf nicht null sein ist aber null"), TRANSACTION_TYPE_MISSING( requestBody -> requestBody.without("transactionType"), - "transactionType must not be null"), + "transactionType darf nicht null sein ist aber null"), VALUE_DATE_MISSING( requestBody -> requestBody.without("valueDate"), - "valueDate must not be null"), + "valueDate darf nicht null sein ist aber null"), SHARES_COUNT_FOR_SUBSCRIPTION_MUST_BE_POSITIVE( requestBody -> requestBody .with("transactionType", "SUBSCRIPTION") .with("shareCount", -1), - "for SUBSCRIPTION, shareCount must be positive but is \"-1\""), + "für transactionType=SUBSCRIPTION, muss shareCount positiv sein, ist aber -1"), SHARES_COUNT_FOR_CANCELLATION_MUST_BE_NEGATIVE( requestBody -> requestBody .with("transactionType", "CANCELLATION") .with("shareCount", 1), - "for CANCELLATION, shareCount must be negative but is \"1\""), + "für transactionType=CANCELLATION, muss shareCount negativ sein, ist aber 1"), SHARES_COUNT_MUST_NOT_BE_NULL( requestBody -> requestBody .with("transactionType", "REVERSAL") .with("shareCount", 0), - "shareCount must not be 0 but is \"0\""), + "shareCount darf nicht 0 sein"), REFERENCE_MISSING( requestBody -> requestBody.without("reference"), - "reference must not be null"), + "reference darf nicht null sein ist aber null"), REFERENCE_TOO_SHORT( requestBody -> requestBody.with("reference", "12345"), - "reference size must be between 6 and 48 but is \"12345\""), + "reference Größe muss zwischen 6 und 48 sein ist aber \"12345\""), REFERENCE_TOO_LONG( requestBody -> requestBody.with("reference", "0123456789012345678901234567890123456789012345678"), - "reference size must be between 6 and 48 but is \"0123456789012345678901234567890123456789012345678\""); + "reference Größe muss zwischen 6 und 48 sein ist aber \"0123456789012345678901234567890123456789012345678\""); private final Function givenBodyTransformation; private final String expectedErrorMessage; @@ -124,6 +127,7 @@ class HsOfficeCoopSharesTransactionControllerRestTest { mockMvc.perform(MockMvcRequestBuilders .post("/api/hs/office/coopsharestransactions") .header("Authorization", "Bearer superuser-alex@hostsharing.net") + .header("Accept-Language", "de") .contentType(MediaType.APPLICATION_JSON) .content(testCase.givenRequestBody()) .accept(MediaType.APPLICATION_JSON))