diff --git a/src/main/java/org/hostsharing/hsadminng/domain/Asset.java b/src/main/java/org/hostsharing/hsadminng/domain/Asset.java index 3149e14c..4d9cf04d 100644 --- a/src/main/java/org/hostsharing/hsadminng/domain/Asset.java +++ b/src/main/java/org/hostsharing/hsadminng/domain/Asset.java @@ -21,6 +21,8 @@ import org.hostsharing.hsadminng.domain.enumeration.AssetAction; public class Asset implements Serializable { private static final long serialVersionUID = 1L; + + public static final String ENTITY_NAME = "asset"; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") diff --git a/src/main/java/org/hostsharing/hsadminng/service/AssetService.java b/src/main/java/org/hostsharing/hsadminng/service/AssetService.java index 0b6ab5a9..be332069 100644 --- a/src/main/java/org/hostsharing/hsadminng/service/AssetService.java +++ b/src/main/java/org/hostsharing/hsadminng/service/AssetService.java @@ -26,10 +26,12 @@ public class AssetService { private final AssetRepository assetRepository; private final AssetMapper assetMapper; + private final AssetValidator assetValidator; - public AssetService(AssetRepository assetRepository, AssetMapper assetMapper) { + public AssetService(AssetRepository assetRepository, AssetMapper assetMapper, AssetValidator assetValidator ) { this.assetRepository = assetRepository; this.assetMapper = assetMapper; + this.assetValidator = assetValidator; } /** @@ -40,6 +42,9 @@ public class AssetService { */ public AssetDTO save(AssetDTO assetDTO) { log.debug("Request to save Asset : {}", assetDTO); + + assetValidator.validate(assetDTO); + Asset asset = assetMapper.toEntity(assetDTO); asset = assetRepository.save(asset); return assetMapper.toDto(asset); diff --git a/src/main/java/org/hostsharing/hsadminng/service/AssetValidator.java b/src/main/java/org/hostsharing/hsadminng/service/AssetValidator.java new file mode 100644 index 00000000..01da9875 --- /dev/null +++ b/src/main/java/org/hostsharing/hsadminng/service/AssetValidator.java @@ -0,0 +1,43 @@ +package org.hostsharing.hsadminng.service; + +import org.hostsharing.hsadminng.domain.Asset; +import org.hostsharing.hsadminng.domain.enumeration.AssetAction; +import org.hostsharing.hsadminng.service.dto.AssetDTO; +import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; + +@Service +public class AssetValidator { + public void validate(final AssetDTO assetDTO) { + if (assetDTO.getId() != null) { + throw new BadRequestAlertException("Asset transactions are immutable", Asset.ENTITY_NAME, "assetTransactionImmutable"); + } + + if (assetDTO.getDocumentDate().isAfter(assetDTO.getValueDate())) { + throw new BadRequestAlertException("Document date may not be after value date", Asset.ENTITY_NAME, "documentDateMayNotBeAfterValueDate"); + } + + if ((assetDTO.getAction() == AssetAction.PAYMENT) && (assetDTO.getAmount().compareTo(BigDecimal.valueOf(0)) <= 0)) { + throw new BadRequestAlertException("Asset payments require a positive amount", Asset.ENTITY_NAME, "assetPaymentsPositiveAmount"); + } + if ((assetDTO.getAction() == AssetAction.ADOPTION) && (assetDTO.getAmount().compareTo(BigDecimal.valueOf(0)) <= 0)) { + throw new BadRequestAlertException("Asset adoptions require a positive amount", Asset.ENTITY_NAME, "assetAdoptionsPositiveAmount"); + } + + if ((assetDTO.getAction() == AssetAction.PAYBACK) && (assetDTO.getAmount().compareTo(BigDecimal.valueOf(0)) >= 0)) { + throw new BadRequestAlertException("Asset paybacks require a negative amount", Asset.ENTITY_NAME, "assetPaybacksNegativeAmount"); + } + if ((assetDTO.getAction() == AssetAction.HANDOVER) && (assetDTO.getAmount().compareTo(BigDecimal.valueOf(0)) >= 0)) { + throw new BadRequestAlertException("Asset handovers require a negative amount", Asset.ENTITY_NAME, "assetHandoversNegativeAmount"); + } + if ((assetDTO.getAction() == AssetAction.LOSS) && (assetDTO.getAmount().compareTo(BigDecimal.valueOf(0)) >= 0)) { + throw new BadRequestAlertException("Asset losses require a negative amount", Asset.ENTITY_NAME, "assetLossesNegativeAmount"); + } + if ((assetDTO.getAction() == AssetAction.CLEARING) && (assetDTO.getAmount().compareTo(BigDecimal.valueOf(0)) >= 0)) { + throw new BadRequestAlertException("Asset clearings require a negative amount", Asset.ENTITY_NAME, "assetClearingsNegativeAmount"); + } + + } +} diff --git a/src/main/java/org/hostsharing/hsadminng/service/ShareService.java b/src/main/java/org/hostsharing/hsadminng/service/ShareService.java index 76552c01..98c4979a 100644 --- a/src/main/java/org/hostsharing/hsadminng/service/ShareService.java +++ b/src/main/java/org/hostsharing/hsadminng/service/ShareService.java @@ -28,9 +28,12 @@ public class ShareService { private final ShareMapper shareMapper; - public ShareService(ShareRepository shareRepository, ShareMapper shareMapper) { + private final ShareValidator shareValidator; + + public ShareService(ShareRepository shareRepository, ShareMapper shareMapper, ShareValidator shareValidator) { this.shareRepository = shareRepository; this.shareMapper = shareMapper; + this.shareValidator = shareValidator; } /** @@ -42,16 +45,8 @@ public class ShareService { public ShareDTO save(ShareDTO shareDTO) { log.debug("Request to save Share : {}", shareDTO); - if (shareDTO.getId() != null) { - throw new BadRequestAlertException("Share transactions are immutable", Share.ENTITY_NAME, "shareTransactionImmutable"); - } + shareValidator.validate(shareDTO); - if((shareDTO.getAction() == ShareAction.SUBSCRIPTION) && (shareDTO.getQuantity() <= 0)) { - throw new BadRequestAlertException("Share subscriptions require a positive quantity", Share.ENTITY_NAME, "shareSubscriptionPositivQuantity"); - } - if((shareDTO.getAction() == ShareAction.CANCELLATION) && (shareDTO.getQuantity() >= 0)) { - throw new BadRequestAlertException("Share cancellations require a negative quantity", Share.ENTITY_NAME, "shareCancellationNegativeQuantity"); - } Share share = shareMapper.toEntity(shareDTO); share = shareRepository.save(share); return shareMapper.toDto(share); diff --git a/src/main/java/org/hostsharing/hsadminng/service/ShareValidator.java b/src/main/java/org/hostsharing/hsadminng/service/ShareValidator.java new file mode 100644 index 00000000..44479a86 --- /dev/null +++ b/src/main/java/org/hostsharing/hsadminng/service/ShareValidator.java @@ -0,0 +1,30 @@ +package org.hostsharing.hsadminng.service; + +import org.hostsharing.hsadminng.domain.Share; +import org.hostsharing.hsadminng.domain.enumeration.ShareAction; +import org.hostsharing.hsadminng.service.dto.ShareDTO; +import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException; +import org.springframework.stereotype.Service; + +@Service +public class ShareValidator { + + public void validate(final ShareDTO shareDTO) { + if (shareDTO.getId() != null) { + throw new BadRequestAlertException("Share transactions are immutable", Share.ENTITY_NAME, "shareTransactionImmutable"); + } + + if (shareDTO.getDocumentDate().isAfter(shareDTO.getValueDate())) { + throw new BadRequestAlertException("Document date may not be after value date", Share.ENTITY_NAME, "documentDateMayNotBeAfterValueDate"); + } + + if ((shareDTO.getAction() == ShareAction.SUBSCRIPTION) && (shareDTO.getQuantity() <= 0)) { + throw new BadRequestAlertException("Share subscriptions require a positive quantity", Share.ENTITY_NAME, "shareSubscriptionPositiveQuantity"); + } + + if ((shareDTO.getAction() == ShareAction.CANCELLATION) && (shareDTO.getQuantity() >= 0)) { + throw new BadRequestAlertException("Share cancellations require a negative quantity", Share.ENTITY_NAME, "shareCancellationNegativeQuantity"); + } + + } +} diff --git a/src/main/webapp/i18n/de/asset.json b/src/main/webapp/i18n/de/asset.json index ff6df7e7..dee8fe54 100644 --- a/src/main/webapp/i18n/de/asset.json +++ b/src/main/webapp/i18n/de/asset.json @@ -2,25 +2,25 @@ "hsadminNgApp": { "asset": { "home": { - "title": "Assets", - "createLabel": "Asset erstellen", - "createOrEditLabel": "Asset erstellen oder bearbeiten" + "title": "Geschäftsguthaben-Transaktionen", + "createLabel": "Geschäftsguthaben-Transaktion erfassen", + "createOrEditLabel": "Geschäftsguthaben-Transaktion erfassen oder bearbeiten" }, - "created": "Asset erstellt mit ID {{ param }}", - "updated": "Asset aktualisiert mit ID {{ param }}", - "deleted": "Asset gelöscht mit ID {{ param }}", + "created": "Geschäftsguthaben-Transaktion erfasst mit ID {{ param }}", + "updated": "Geschäftsguthaben-Transaktion aktualisiert mit ID {{ param }}", + "deleted": "Geschäftsguthaben-Transaktion gelöscht mit ID {{ param }}", "delete": { - "question": "Soll Asset {{ id }} wirklich dauerhaft gelöscht werden?" + "question": "Soll die Geschäftsguthaben-Transaktion {{ id }} wirklich dauerhaft gelöscht werden?" }, "detail": { - "title": "Asset" + "title": "Geschäftsguthaben-Transaktion" }, - "documentDate": "Document Date", - "valueDate": "Value Date", - "action": "Action", - "amount": "Amount", - "remark": "Remark", - "membership": "Membership" + "documentDate": "Belegdatum", + "valueDate": "Buchungsdatum", + "action": "Transaktion", + "amount": "Betrag", + "remark": "Bemerkung", + "membership": "zugehörige Mitgliedschaft" } } } diff --git a/src/main/webapp/i18n/de/assetAction.json b/src/main/webapp/i18n/de/assetAction.json index d3f1ca77..e89d58f3 100644 --- a/src/main/webapp/i18n/de/assetAction.json +++ b/src/main/webapp/i18n/de/assetAction.json @@ -2,12 +2,12 @@ "hsadminNgApp": { "AssetAction": { "null": "", - "PAYMENT": "PAYMENT", - "HANDOVER": "HANDOVER", - "ADOPTION": "ADOPTION", - "LOSS": "LOSS", - "CLEARING": "CLEARING", - "PAYBACK": "PAYBACK" + "PAYMENT": "Einzahlung", + "HANDOVER": "Übertragung", + "ADOPTION": "Übernahme", + "LOSS": "Verlust", + "CLEARING": "Verrechnung", + "PAYBACK": "Auszahlung" } } } diff --git a/src/main/webapp/i18n/de/custom-error.json b/src/main/webapp/i18n/de/custom-error.json index 11be4363..08b8fd1c 100644 --- a/src/main/webapp/i18n/de/custom-error.json +++ b/src/main/webapp/i18n/de/custom-error.json @@ -1,10 +1,17 @@ { "error": { - "shareSubscriptionPositivQuantity": "Zeichnungen von Geschäftsanteilen erfordern eine positive Stückzahl", + "shareSubscriptionPositiveQuantity": "Zeichnungen von Geschäftsanteilen erfordern eine positive Stückzahl", "shareCancellationNegativeQuantity": "Kündigungen von Geschäftsanteilen erfordern eine negative Stückzahl", "shareTransactionImmutable": "Transaktionen mit Geschäftsanteilen sind unveränderlich", "membershipNotDeletable": "Mitgliedschaft kann nicht gelöscht werden, setze stattdessen das 'untilDate'", - "untilDateMustBeAfterSinceDate": "Mitgliedshafts-Austrittsdatum muss nach dem Beitrittsdatum liegen", - "anotherUncancelledMembershipExists": "Nur eine einzige ungekündigte Mitgliedschaft pro Kunde ist zulässig" + "untilDateMustBeAfterSinceDate": "Mitgliedshaftsaustrittsdatum muss nach dem Beitrittsdatum liegen", + "documentDateMayNotBeAfterValueDate": "Belegdatum darf nicht vor dem Buchungsdatum liegen", + "anotherUncancelledMembershipExists": "Nur eine einzige ungekündigte Mitgliedschaft pro Kunde ist zulässig", + "assetPaymentsPositiveAmount": "Einzahlungen von Geschäftsguthaben erfordern einen positiven Betrag", + "assetAdoptionsPositiveAmount": "Übernahmen von Geschäftsguthaben erfordern einen positiven Betrag", + "assetPaybacksNegativeAmount": "Auszahlungen von Geschäftsguthaben erfordern einen negativen Betrag", + "assetHandoversNegativeAmount": "Übertragungen von Geschäftsguthaben erfordern einen negativen Betrag", + "assetLossesNegativeAmount": "Verluste von Geschäftsguthaben erfordern einen negativen Betrag", + "assetClearingsNegativeAmount": "Verrechnungen von Geschäftsguthaben erfordern einen negativen Betrag" } } diff --git a/src/main/webapp/i18n/de/share.json b/src/main/webapp/i18n/de/share.json index fdb5dec4..2cadbe83 100644 --- a/src/main/webapp/i18n/de/share.json +++ b/src/main/webapp/i18n/de/share.json @@ -2,25 +2,25 @@ "hsadminNgApp": { "share": { "home": { - "title": "Shares", - "createLabel": "Share erstellen", - "createOrEditLabel": "Share erstellen oder bearbeiten" + "title": "Geschäftsanteil-Transaktionen", + "createLabel": "Geschäftsanteil-Transaktion erfassen", + "createOrEditLabel": "Geschäftsanteil-Transaktion erfassen oder bearbeiten" }, - "created": "Share erstellt mit ID {{ param }}", - "updated": "Share aktualisiert mit ID {{ param }}", - "deleted": "Share gelöscht mit ID {{ param }}", + "created": "Geschäftsanteil-Transaktion erfasst mit ID {{ param }}", + "updated": "Geschäftsanteil-Transaktion aktualisiert mit ID {{ param }}", + "deleted": "Geschäftsanteil-Transaktion gelöscht mit ID {{ param }}", "delete": { - "question": "Soll Share {{ id }} wirklich dauerhaft gelöscht werden?" + "question": "Soll die Geschäftsanteil-Transaktion {{ id }} wirklich dauerhaft gelöscht werden?" }, "detail": { - "title": "Share" + "title": "Geschäftsanteil-Transaktion" }, - "documentDate": "Document Date", - "valueDate": "Value Date", - "action": "Action", - "quantity": "Quantity", - "remark": "Remark", - "membership": "Membership" + "documentDate": "Belegdatum", + "valueDate": "Buchungsdatum", + "action": "Aktion", + "quantity": "Anzahl", + "remark": "Bemerkung", + "membership": "zugehörige Mitgliedschaft" } } } diff --git a/src/main/webapp/i18n/de/shareAction.json b/src/main/webapp/i18n/de/shareAction.json index 2016c4bb..63d4be57 100644 --- a/src/main/webapp/i18n/de/shareAction.json +++ b/src/main/webapp/i18n/de/shareAction.json @@ -2,8 +2,8 @@ "hsadminNgApp": { "ShareAction": { "null": "", - "SUBSCRIPTION": "SUBSCRIPTION", - "CANCELLATION": "CANCELLATION" + "SUBSCRIPTION": "Zeichnung", + "CANCELLATION": "Kündigung" } } } diff --git a/src/main/webapp/i18n/en/asset.json b/src/main/webapp/i18n/en/asset.json index ac290fb7..a380f70f 100644 --- a/src/main/webapp/i18n/en/asset.json +++ b/src/main/webapp/i18n/en/asset.json @@ -2,25 +2,25 @@ "hsadminNgApp": { "asset": { "home": { - "title": "Assets", - "createLabel": "Create a new Asset", - "createOrEditLabel": "Create or edit a Asset" + "title": "Asset Transactions", + "createLabel": "Register a new asset transaction", + "createOrEditLabel": "Register or edit an asset transaction" }, - "created": "A new Asset is created with identifier {{ param }}", - "updated": "A Asset is updated with identifier {{ param }}", - "deleted": "A Asset is deleted with identifier {{ param }}", + "created": "A new asset transaction is registered with identifier {{ param }}", + "updated": "An asset transaction is updated with identifier {{ param }}", + "deleted": "An asset transaction is deleted with identifier {{ param }}", "delete": { - "question": "Are you sure you want to delete Asset {{ id }}?" + "question": "Are you sure you want to delete asset transaction {{ id }}?" }, "detail": { - "title": "Asset" + "title": "Asset transaction" }, - "documentDate": "Document Date", - "valueDate": "Value Date", + "documentDate": "Document date", + "valueDate": "Value date", "action": "Action", "amount": "Amount", "remark": "Remark", - "membership": "Membership" + "membership": "Related membership" } } } diff --git a/src/main/webapp/i18n/en/assetAction.json b/src/main/webapp/i18n/en/assetAction.json index d3f1ca77..e17447ca 100644 --- a/src/main/webapp/i18n/en/assetAction.json +++ b/src/main/webapp/i18n/en/assetAction.json @@ -2,12 +2,12 @@ "hsadminNgApp": { "AssetAction": { "null": "", - "PAYMENT": "PAYMENT", - "HANDOVER": "HANDOVER", - "ADOPTION": "ADOPTION", - "LOSS": "LOSS", - "CLEARING": "CLEARING", - "PAYBACK": "PAYBACK" + "PAYMENT": "Payment", + "HANDOVER": "Handover", + "ADOPTION": "Adoption", + "LOSS": "Loss", + "CLEARING": "Clearing", + "PAYBACK": "Payback" } } } diff --git a/src/main/webapp/i18n/en/custom-error.json b/src/main/webapp/i18n/en/custom-error.json index 145dfcd1..277e3d4d 100644 --- a/src/main/webapp/i18n/en/custom-error.json +++ b/src/main/webapp/i18n/en/custom-error.json @@ -1,10 +1,17 @@ { "error": { - "shareSubscriptionPositivQuantity": "Share subscriptions require a positive quantity", + "shareSubscriptionPositiveQuantity": "Share subscriptions require a positive quantity", "shareCancellationNegativeQuantity": "Share cancellations require a negative quantity", "shareTransactionImmutable": "Share transactions are immutable", "membershipNotDeletable": "Membership cannot be deleted, instead set 'untilDate'", "untilDateMustBeAfterSinceDate": "Membership until date must be after since date", - "anotherUncancelledMembershipExists": "Only a single uncancelled membership allowed per customer" + "documentDateMayNotBeAfterValueDate": "Document date may not be after value date", + "anotherUncancelledMembershipExists": "Only a single uncancelled membership allowed per customer", + "assetPaymentsPositiveAmount": "Asset payments require a positive amount", + "assetAdoptionsPositiveAmount": "Asset adoptions require a positive amount", + "assetPaybacksNegativeAmount": "Asset paybacks require a negative amount", + "assetHandoversNegativeAmount": "Asset handovers require a negative amount", + "assetLossesNegativeAmount": "Asset losses require a negative amount", + "assetClearingsNegativeAmount": "Asset clearings require a negative amount" } } diff --git a/src/main/webapp/i18n/en/share.json b/src/main/webapp/i18n/en/share.json index 5c178744..e103c0ec 100644 --- a/src/main/webapp/i18n/en/share.json +++ b/src/main/webapp/i18n/en/share.json @@ -2,25 +2,25 @@ "hsadminNgApp": { "share": { "home": { - "title": "Shares", - "createLabel": "Create a new Share", - "createOrEditLabel": "Create or edit a Share" + "title": "Share Transactions", + "createLabel": "Register a new share transaction", + "createOrEditLabel": "Register or edit a share transaction" }, - "created": "A new Share is created with identifier {{ param }}", - "updated": "A Share is updated with identifier {{ param }}", - "deleted": "A Share is deleted with identifier {{ param }}", + "created": "A new share transactions is registered with identifier {{ param }}", + "updated": "A share transaction is updated with identifier {{ param }}", + "deleted": "A share transcation is deleted with identifier {{ param }}", "delete": { - "question": "Are you sure you want to delete Share {{ id }}?" + "question": "Are you sure you want to delete share transaction {{ id }}?" }, "detail": { - "title": "Share" + "title": "Share transaction" }, - "documentDate": "Document Date", - "valueDate": "Value Date", + "documentDate": "Document date", + "valueDate": "Value date", "action": "Action", "quantity": "Quantity", "remark": "Remark", - "membership": "Membership" + "membership": "Related membership" } } } diff --git a/src/main/webapp/i18n/en/shareAction.json b/src/main/webapp/i18n/en/shareAction.json index 2016c4bb..b2aed341 100644 --- a/src/main/webapp/i18n/en/shareAction.json +++ b/src/main/webapp/i18n/en/shareAction.json @@ -2,8 +2,8 @@ "hsadminNgApp": { "ShareAction": { "null": "", - "SUBSCRIPTION": "SUBSCRIPTION", - "CANCELLATION": "CANCELLATION" + "SUBSCRIPTION": "Subscription", + "CANCELLATION": "Cancellation" } } } diff --git a/src/test/java/org/hostsharing/hsadminng/service/AssetValidatorUnitTest.java b/src/test/java/org/hostsharing/hsadminng/service/AssetValidatorUnitTest.java new file mode 100644 index 00000000..5009d7a0 --- /dev/null +++ b/src/test/java/org/hostsharing/hsadminng/service/AssetValidatorUnitTest.java @@ -0,0 +1,205 @@ +package org.hostsharing.hsadminng.service; + +import org.assertj.core.api.AbstractThrowableAssert; +import org.hostsharing.hsadminng.domain.enumeration.AssetAction; +import org.hostsharing.hsadminng.service.dto.AssetDTO; +import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException; +import org.junit.Test; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.function.Consumer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowableOfType; + +public class AssetValidatorUnitTest { + + private AssetValidator assetValidator = new AssetValidator(); + + @Test + public void shouldAcceptValidAssetDTO() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.PAYMENT).withAmount("64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isNull(); + } + + @Test + public void shouldAcceptIfDocumentDateEqualsValueDate() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-11") + .withAction(AssetAction.PAYMENT).withAmount("64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isNull(); + } + + @Test + public void shouldRejectIfDocumentDateAfterValueDate() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-13").withValueDate("2019-04-12") + .withAction(AssetAction.PAYMENT).withAmount("64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Document date may not be after value date", "asset", "documentDateMayNotBeAfterValueDate")); + } + + @Test + public void shouldRejectIfPaymentWithNegativeAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.PAYMENT).withAmount("-64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset payments require a positive amount", "asset", "assetPaymentsPositiveAmount")); + } + + @Test + public void shouldRejectIfPaymentWithZeroAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.PAYMENT).withAmount("0.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset payments require a positive amount", "asset", "assetPaymentsPositiveAmount")); + } + + @Test + public void shouldRejectIfAdoptionWithNegativeAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.ADOPTION).withAmount("-64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset adoptions require a positive amount", "asset", "assetAdoptionsPositiveAmount")); + } + + @Test + public void shouldRejectIfAdoptionWithZeroAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.ADOPTION).withAmount("0.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset adoptions require a positive amount", "asset", "assetAdoptionsPositiveAmount")); + } + + @Test + public void shouldRejectIfPaybackWithPositiveAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.PAYBACK).withAmount("64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset paybacks require a negative amount", "asset", "assetPaybacksNegativeAmount")); + } + + @Test + public void shouldRejectIfPaybackWithZeroAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.PAYBACK).withAmount("0.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset paybacks require a negative amount", "asset", "assetPaybacksNegativeAmount")); + } + + @Test + public void shouldRejectIfHandoverWithPositiveAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.HANDOVER).withAmount("64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset handovers require a negative amount", "asset", "assetHandoversNegativeAmount")); + } + + @Test + public void shouldRejectIfHandoverWithZeroAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.HANDOVER).withAmount("0.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset handovers require a negative amount", "asset", "assetHandoversNegativeAmount")); + } + + @Test + public void shouldRejectIfLossWithPositiveAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.LOSS).withAmount("64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset losses require a negative amount", "asset", "assetLossesNegativeAmount")); + } + + @Test + public void shouldRejectIfLossWithZeroAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.LOSS).withAmount("0.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset losses require a negative amount", "asset", "assetLossesNegativeAmount")); + } + + @Test + public void shouldRejectIfClearingWithPositiveAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.CLEARING).withAmount("64.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset clearings require a negative amount", "asset", "assetClearingsNegativeAmount")); + } + + @Test + public void shouldRejectIfClearingWithZeroAmount() { + new GivenAssetValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(AssetAction.CLEARING).withAmount("0.00") + .when((AssetDTO assetDto) -> assetValidator.validate(assetDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Asset clearings require a negative amount", "asset", "assetClearingsNegativeAmount")); + } + + + // -- only test fixture below --- + + private class GivenAssetValidationTestCase { + + private final AssetDTO assetDto = new AssetDTO(); + private BadRequestAlertException actualException; + + GivenAssetValidationTestCase withDocumentDate(String documentDate) { + assetDto.setDocumentDate(LocalDate.parse(documentDate)); + return this; + } + + GivenAssetValidationTestCase withValueDate(String valueDate) { + assetDto.setValueDate(LocalDate.parse(valueDate)); + return this; + } + + GivenAssetValidationTestCase withAction(AssetAction assetAction) { + assetDto.setAction(assetAction); + return this; + } + + GivenAssetValidationTestCase withAmount(String amount) { + assetDto.setAmount(new BigDecimal(amount)); + return this; + } + + GivenAssetValidationTestCase when(final Consumer statement) { + actualException = catchThrowableOfType(() -> assetValidator.validate(assetDto), BadRequestAlertException.class); + return this; + } + + public AbstractThrowableAssert thenActualException() { + return assertThat(actualException); + } + } +} diff --git a/src/test/java/org/hostsharing/hsadminng/service/ShareValidatorUnitTest.java b/src/test/java/org/hostsharing/hsadminng/service/ShareValidatorUnitTest.java new file mode 100644 index 00000000..a950b07c --- /dev/null +++ b/src/test/java/org/hostsharing/hsadminng/service/ShareValidatorUnitTest.java @@ -0,0 +1,126 @@ +package org.hostsharing.hsadminng.service; + +import org.assertj.core.api.AbstractThrowableAssert; +import org.hostsharing.hsadminng.domain.enumeration.ShareAction; +import org.hostsharing.hsadminng.service.dto.ShareDTO; +import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException; +import org.junit.Test; + +import java.time.LocalDate; +import java.util.function.Consumer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowableOfType; + +public class ShareValidatorUnitTest { + + private ShareValidator shareValidator = new ShareValidator(); + + @Test + public void shouldAcceptValidShareDTO() { + new GivenShareValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(ShareAction.SUBSCRIPTION).withQuantity(1) + .when((ShareDTO shareDto) -> shareValidator.validate(shareDto)) + .thenActualException().isNull(); + } + + @Test + public void shouldAcceptIfDocumentDateEqualsValueDate() { + new GivenShareValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-11") + .withAction(ShareAction.SUBSCRIPTION).withQuantity(1) + .when((ShareDTO shareDto) -> shareValidator.validate(shareDto)) + .thenActualException().isNull(); + } + + @Test + public void shouldRejectIfDocumentDateAfterValueDate() { + new GivenShareValidationTestCase() + .withDocumentDate("2019-04-13").withValueDate("2019-04-12") + .withAction(ShareAction.SUBSCRIPTION).withQuantity(1) + .when((ShareDTO shareDto) -> shareValidator.validate(shareDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Document date may not be after value date", "share", "documentDateMayNotBeAfterValueDate")); + } + + @Test + public void shouldRejectIfSubscriptionWithNegativeQuantity() { + new GivenShareValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(ShareAction.SUBSCRIPTION).withQuantity(-1) + .when((ShareDTO shareDto) -> shareValidator.validate(shareDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Share subscriptions require a positive quantity", "share", "shareSubscriptionPositiveQuantity")); + } + + @Test + public void shouldRejectIfSubscriptionWithZeroQuantity() { + new GivenShareValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(ShareAction.SUBSCRIPTION).withQuantity(0) + .when((ShareDTO shareDto) -> shareValidator.validate(shareDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Share subscriptions require a positive quantity", "share", "shareSubscriptionPositiveQuantity")); + } + + @Test + public void shouldRejectIfCancellationWithPositiveQuantity() { + new GivenShareValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(ShareAction.CANCELLATION).withQuantity(1) + .when((ShareDTO shareDto) -> shareValidator.validate(shareDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Share cancellations require a negative quantity", "share", "shareCancellationNegativeQuantity")); + } + + @Test + public void shouldRejectIfCancellationWithZeroQuantity() { + new GivenShareValidationTestCase() + .withDocumentDate("2019-04-11").withValueDate("2019-04-12") + .withAction(ShareAction.CANCELLATION).withQuantity(0) + .when((ShareDTO shareDto) -> shareValidator.validate(shareDto)) + .thenActualException().isEqualToComparingFieldByField(new BadRequestAlertException( + "Share cancellations require a negative quantity", "share", "shareCancellationNegativeQuantity")); + } + + + // -- only test fixture below --- + + private class GivenShareValidationTestCase { + + private final ShareDTO shareDto = new ShareDTO(); + private BadRequestAlertException actualException; + + GivenShareValidationTestCase withDocumentDate(String documentDate) { + shareDto.setDocumentDate(LocalDate.parse(documentDate)); + return this; + } + + GivenShareValidationTestCase withValueDate(String valueDate) { + shareDto.setValueDate(LocalDate.parse(valueDate)); + return this; + } + + GivenShareValidationTestCase withAction(ShareAction shareAction) { + shareDto.setAction(shareAction); + return this; + } + + GivenShareValidationTestCase withQuantity(Integer quantity) { + shareDto.setQuantity(quantity); + return this; + } + + GivenShareValidationTestCase when(final Consumer statement) { + actualException = catchThrowableOfType(() -> shareValidator.validate(shareDto), BadRequestAlertException.class); + return this; + } + + public AbstractThrowableAssert thenActualException() { + return assertThat(actualException); + } + } +} + +