HsOfficeCoopSharesTransactionController.java
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.rbac.context.Context;
import net.hostsharing.hsadminng.errors.MultiValidationException;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeCoopSharesApi;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionInsertResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionResource;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipRepository;
import net.hostsharing.hsadminng.mapper.StrictMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionTypeResource.CANCELLATION;
import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionTypeResource.SUBSCRIPTION;
import static net.hostsharing.hsadminng.hs.validation.UuidResolver.resolve;
@RestController
@PreAuthorize("isAuthenticated()")
@SecurityRequirement(name = "bearerAuth")
public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopSharesApi {
@Autowired
private Context context;
@Autowired
private StrictMapper mapper;
@Autowired
private MessageTranslator messageTranslator;
@Autowired
private HsOfficeCoopSharesTransactionRepository coopSharesTransactionRepo;
@Autowired
private HsOfficeMembershipRepository membershipRepo;
@Override
@Transactional(readOnly = true)
@Timed("app.office.coopShares.api.getListOfCoopShares")
public ResponseEntity<List<HsOfficeCoopSharesTransactionResource>> getListOfCoopShares(
final String assumedRoles,
final UUID membershipUuid,
final @DateTimeFormat(iso = ISO.DATE) LocalDate fromValueDate,
final @DateTimeFormat(iso = ISO.DATE) LocalDate toValueDate) {
context.assumeRoles(assumedRoles);
final var entities = coopSharesTransactionRepo.findCoopSharesTransactionByOptionalMembershipUuidAndDateRange(
membershipUuid,
fromValueDate,
toValueDate);
final var resources = mapper.mapList(
entities,
HsOfficeCoopSharesTransactionResource.class,
ENTITY_TO_RESOURCE_POSTMAPPER);
return ResponseEntity.ok(resources);
}
@Override
@Transactional
@Timed("app.office.coopShares.repo.postNewCoopSharesTransaction")
public ResponseEntity<HsOfficeCoopSharesTransactionResource> postNewCoopSharesTransaction(
final String assumedRoles,
final HsOfficeCoopSharesTransactionInsertResource requestBody) {
context.assumeRoles(assumedRoles);
validate(requestBody);
final var entityToSave = mapper.map(
requestBody,
HsOfficeCoopSharesTransactionEntity.class,
RESOURCE_TO_ENTITY_POSTMAPPER);
final var saved = coopSharesTransactionRepo.save(entityToSave);
final var uri =
MvcUriComponentsBuilder.fromController(getClass())
.path("/api/hs/office/coopsharestransactions/{id}")
.buildAndExpand(saved.getUuid())
.toUri();
final var mapped = mapper.map(saved, HsOfficeCoopSharesTransactionResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
return ResponseEntity.created(uri).body(mapped);
}
@Override
@Transactional(readOnly = true)
@Timed("app.office.coopShares.repo.getSingleCoopShareTransactionByUuid")
public ResponseEntity<HsOfficeCoopSharesTransactionResource> getSingleCoopShareTransactionByUuid(
final String assumedRoles, final UUID shareTransactionUuid) {
context.assumeRoles(assumedRoles);
final var result = coopSharesTransactionRepo.findByUuid(shareTransactionUuid);
if (result.isEmpty()) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(mapper.map(
result.get(),
HsOfficeCoopSharesTransactionResource.class,
ENTITY_TO_RESOURCE_POSTMAPPER));
}
private void validate(final HsOfficeCoopSharesTransactionInsertResource requestBody) {
final var violations = new ArrayList<String>();
validateSubscriptionTransaction(requestBody, violations);
validateCancellationTransaction(requestBody, violations);
validateshareCount(requestBody, violations);
MultiValidationException.throwIfNotEmpty(violations);
}
private void validateSubscriptionTransaction(
final HsOfficeCoopSharesTransactionInsertResource requestBody,
final ArrayList<String> violations) {
if (requestBody.getTransactionType() == SUBSCRIPTION
&& requestBody.getShareCount() < 0) {
violations.add(messageTranslator.translate(
"office.coop-shares.for-transactiontype-{0}-sharecount-must-be-positive-but-is-{1}",
requestBody.getTransactionType(), requestBody.getShareCount()));
}
}
private void validateCancellationTransaction(
final HsOfficeCoopSharesTransactionInsertResource requestBody,
final ArrayList<String> violations) {
if (requestBody.getTransactionType() == CANCELLATION
&& requestBody.getShareCount() > 0) {
violations.add(messageTranslator.translate(
"office.coop-shares.for-transactiontype-{0}-sharecount-must-be-negative-but-is-{1}",
requestBody.getTransactionType(), requestBody.getShareCount()));
}
}
private void validateshareCount(
final HsOfficeCoopSharesTransactionInsertResource requestBody,
final ArrayList<String> violations) {
if (requestBody.getShareCount() == 0) {
violations.add(messageTranslator.translate("office.coop-shares.sharecount-must-not-be-0"));
}
}
final BiConsumer<HsOfficeCoopSharesTransactionInsertResource, HsOfficeCoopSharesTransactionEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
entity.setMembership(resolve("membership.uuid", resource.getMembershipUuid(), membershipRepo::findByUuid));
if (resource.getRevertedShareTxUuid() != null) {
entity.setRevertedShareTx(resolve(
"revertedShareTx.uuid",
resource.getRevertedShareTxUuid(),
coopSharesTransactionRepo::findByUuid));
}
};
final BiConsumer<HsOfficeCoopSharesTransactionEntity, HsOfficeCoopSharesTransactionResource> ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
resource.setMembershipUuid(entity.getMembership().getUuid());
};
}