Merge branch 'master' of ssh://dev.hostsharing.net:29418/hsadmin/hsadmin-ng

This commit is contained in:
Michael Hierweck 2019-04-27 15:46:55 +02:00
commit 2fdb914f6d
46 changed files with 811 additions and 195 deletions

View File

@ -42,9 +42,6 @@ public class HsadminNgApp {
@PostConstruct @PostConstruct
public void initApplication() { public void initApplication() {
// TODO: remove this hack once proper user roles are implemented
SecurityUtils.addUserRole(null, null, Role.HOSTMASTER);
Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles()); Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) { if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
log.error("You have misconfigured your application! It should not run " + log.error("You have misconfigured your application! It should not run " +
@ -54,6 +51,14 @@ public class HsadminNgApp {
log.error("You have misconfigured your application! It should not " + log.error("You have misconfigured your application! It should not " +
"run with both the 'dev' and 'cloud' profiles at the same time."); "run with both the 'dev' and 'cloud' profiles at the same time.");
} }
// TODO: remove this hack once proper user roles are implemented
if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
// For some strange reasons, HsadminNgApp is created in locally running tests,
// but not on Jenkins, therefore the login user had no rights and many tests
// failed.
SecurityUtils.addUserRole(null, null, Role.HOSTMASTER);
}
} }
/** /**

View File

@ -22,7 +22,7 @@ public class Asset implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final String ENTITY_NAME = "asset"; public static final String ENTITY_NAME = "asset";
@Id @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator") @SequenceGenerator(name = "sequenceGenerator")
@ -59,6 +59,11 @@ public class Asset implements Serializable {
return id; return id;
} }
public Asset id(Long id) {
this.id = id;
return this;
}
public void setId(Long id) { public void setId(Long id) {
this.id = id; this.id = id;
} }

View File

@ -1,6 +1,8 @@
package org.hostsharing.hsadminng.security; package org.hostsharing.hsadminng.security;
import org.hostsharing.hsadminng.service.accessfilter.Role; import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
@ -14,6 +16,8 @@ import java.util.Optional;
*/ */
public final class SecurityUtils { public final class SecurityUtils {
private static final Logger log = LoggerFactory.getLogger(SecurityUtils.class);
private static List<UserRoleAssignment> userRoleAssignments = new ArrayList<>(); private static List<UserRoleAssignment> userRoleAssignments = new ArrayList<>();
private SecurityUtils() { private SecurityUtils() {
@ -86,16 +90,18 @@ public final class SecurityUtils {
? ura.role ? ura.role
: Role.ANYBODY). : Role.ANYBODY).
reduce(Role.ANYBODY, (r1, r2) -> r1.covers(r2) ? r1 : r2); reduce(Role.ANYBODY, (r1, r2) -> r1.covers(r2) ? r1 : r2);
log.debug("getLoginUserRoleFor({}, {}) returned {}", onDtoClass, onId, highestRole);
return highestRole; return highestRole;
} }
private static boolean matches(Class<?> onDtoClass, Long onId, UserRoleAssignment ura) { private static boolean matches(Class<?> onDtoClass, Long onId, UserRoleAssignment ura) {
final boolean matches = (ura.onClass == null || onDtoClass == ura.onClass) && (ura.onId == null || ura.onId.equals(onId)); final boolean matches = (ura.onClass == null || onDtoClass == ura.onClass) && (ura.onId == null || ura.onId.equals(onId));
return matches; return matches;
} }
// TODO: depends on https://plan.hostsharing.net/project/hsadmin/us/67?milestone=34 // TODO: depends on https://plan.hostsharing.net/project/hsadmin/us/67?milestone=34
public static void addUserRole(final Class<?> onClass, final Long onId, final Role role) { public static void addUserRole(final Class<?> onClass, final Long onId, final Role role) {
log.info("addUserRole({}, {}, {})", onClass, onId, role);
userRoleAssignments.add(new UserRoleAssignment(onClass, onId, role)); userRoleAssignments.add(new UserRoleAssignment(onClass, onId, role));
} }

View File

@ -4,6 +4,7 @@ import org.hostsharing.hsadminng.domain.Asset;
import org.hostsharing.hsadminng.repository.AssetRepository; import org.hostsharing.hsadminng.repository.AssetRepository;
import org.hostsharing.hsadminng.service.dto.AssetDTO; import org.hostsharing.hsadminng.service.dto.AssetDTO;
import org.hostsharing.hsadminng.service.mapper.AssetMapper; import org.hostsharing.hsadminng.service.mapper.AssetMapper;
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@ -11,6 +12,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import java.util.Optional; import java.util.Optional;
/** /**
@ -18,16 +20,19 @@ import java.util.Optional;
*/ */
@Service @Service
@Transactional @Transactional
public class AssetService { public class AssetService implements IdToDtoResolver<AssetDTO> {
private final Logger log = LoggerFactory.getLogger(AssetService.class); private final Logger log = LoggerFactory.getLogger(AssetService.class);
private final EntityManager em;
private final AssetRepository assetRepository; private final AssetRepository assetRepository;
private final AssetMapper assetMapper; private final AssetMapper assetMapper;
private final AssetValidator assetValidator; private final AssetValidator assetValidator;
public AssetService(AssetRepository assetRepository, AssetMapper assetMapper, AssetValidator assetValidator ) { public AssetService(final EntityManager em, final AssetRepository assetRepository, final AssetMapper assetMapper, final AssetValidator assetValidator) {
this.em = em;
this.assetRepository = assetRepository; this.assetRepository = assetRepository;
this.assetMapper = assetMapper; this.assetMapper = assetMapper;
this.assetValidator = assetValidator; this.assetValidator = assetValidator;
@ -44,6 +49,8 @@ public class AssetService {
assetValidator.validate(assetDTO); assetValidator.validate(assetDTO);
Asset asset = assetMapper.toEntity(assetDTO); Asset asset = assetMapper.toEntity(assetDTO);
asset = assetRepository.save(asset); asset = assetRepository.save(asset);
em.flush();
em.refresh(asset);
return assetMapper.toDto(asset); return assetMapper.toDto(asset);
} }
@ -81,6 +88,7 @@ public class AssetService {
*/ */
public void delete(Long id) { public void delete(Long id) {
log.debug("Request to delete Asset : {}", id); log.debug("Request to delete Asset : {}", id);
assetRepository.deleteById(id);
throw new BadRequestAlertException("Asset transactions are immutable", Asset.ENTITY_NAME, "assetTransactionImmutable");
} }
} }

View File

@ -12,6 +12,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import java.util.Optional; import java.util.Optional;
/** /**
@ -23,15 +24,19 @@ public class MembershipService implements IdToDtoResolver<MembershipDTO> {
private final Logger log = LoggerFactory.getLogger(MembershipService.class); private final Logger log = LoggerFactory.getLogger(MembershipService.class);
private final EntityManager em;
private final MembershipValidator membershipValidator; private final MembershipValidator membershipValidator;
private final MembershipRepository membershipRepository; private final MembershipRepository membershipRepository;
private final MembershipMapper membershipMapper; private final MembershipMapper membershipMapper;
public MembershipService(final MembershipValidator membershipValidator, public MembershipService(final EntityManager em,
final MembershipValidator membershipValidator,
final MembershipRepository membershipRepository, final MembershipRepository membershipRepository,
final MembershipMapper membershipMapper) { final MembershipMapper membershipMapper) {
this.em = em;
this.membershipValidator = membershipValidator; this.membershipValidator = membershipValidator;
this.membershipRepository = membershipRepository; this.membershipRepository = membershipRepository;
this.membershipMapper = membershipMapper; this.membershipMapper = membershipMapper;
@ -50,6 +55,8 @@ public class MembershipService implements IdToDtoResolver<MembershipDTO> {
Membership membership = membershipMapper.toEntity(membershipDTO); Membership membership = membershipMapper.toEntity(membershipDTO);
membership = membershipRepository.save(membership); membership = membershipRepository.save(membership);
em.flush();
em.refresh(membership);
return membershipMapper.toDto(membership); return membershipMapper.toDto(membership);
} }

View File

@ -12,6 +12,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import java.util.Optional; import java.util.Optional;
/** /**
@ -23,13 +24,16 @@ public class ShareService implements IdToDtoResolver<ShareDTO> {
private final Logger log = LoggerFactory.getLogger(ShareService.class); private final Logger log = LoggerFactory.getLogger(ShareService.class);
private final EntityManager em;
private final ShareRepository shareRepository; private final ShareRepository shareRepository;
private final ShareMapper shareMapper; private final ShareMapper shareMapper;
private final ShareValidator shareValidator; private final ShareValidator shareValidator;
public ShareService(ShareRepository shareRepository, ShareMapper shareMapper, ShareValidator shareValidator) { public ShareService(final EntityManager em, final ShareRepository shareRepository, final ShareMapper shareMapper, final ShareValidator shareValidator) {
this.em = em;
this.shareRepository = shareRepository; this.shareRepository = shareRepository;
this.shareMapper = shareMapper; this.shareMapper = shareMapper;
this.shareValidator = shareValidator; this.shareValidator = shareValidator;
@ -48,6 +52,8 @@ public class ShareService implements IdToDtoResolver<ShareDTO> {
Share share = shareMapper.toEntity(shareDTO); Share share = shareMapper.toEntity(shareDTO);
share = shareRepository.save(share); share = shareRepository.save(share);
em.flush();
em.refresh(share);
return shareMapper.toDto(share); return shareMapper.toDto(share);
} }

View File

@ -1,6 +1,11 @@
package org.hostsharing.hsadminng.service.dto; package org.hostsharing.hsadminng.service.dto;
import org.hostsharing.hsadminng.domain.enumeration.AssetAction; import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
import org.hostsharing.hsadminng.service.AssetService;
import org.hostsharing.hsadminng.service.MembershipService;
import org.hostsharing.hsadminng.service.accessfilter.*;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.ApplicationContext;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
@ -12,29 +17,40 @@ import java.util.Objects;
/** /**
* A DTO for the Asset entity. * A DTO for the Asset entity.
*/ */
public class AssetDTO implements Serializable { public class AssetDTO implements Serializable, AccessMappings {
@SelfId(resolver = AssetService.class)
@AccessFor(read = Role.ANY_CUSTOMER_USER)
private Long id; private Long id;
@NotNull @NotNull
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private LocalDate documentDate; private LocalDate documentDate;
@NotNull @NotNull
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private LocalDate valueDate; private LocalDate valueDate;
@NotNull @NotNull
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private AssetAction action; private AssetAction action;
@NotNull @NotNull
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private BigDecimal amount; private BigDecimal amount;
@Size(max = 160) @Size(max = 160)
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = Role.SUPPORTER)
private String remark; private String remark;
@ParentId(resolver = MembershipService.class)
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private Long membershipId; private Long membershipId;
private String membershipDisplayReference; // TODO: these init/update rights actually mean "ignore", we might want to express this in a better way
// background: there is no converter for any display label in DTOs to entity field values anyway
@AccessFor(init=Role.ANYBODY, update = Role.ANYBODY, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private String membershipDisplayLabel;
public Long getId() { public Long getId() {
return id; return id;
@ -92,12 +108,12 @@ public class AssetDTO implements Serializable {
this.membershipId = membershipId; this.membershipId = membershipId;
} }
public String getMembershipDisplayReference() { public String getMembershipDisplayLabel() {
return membershipDisplayReference; return membershipDisplayLabel;
} }
public void setMembershipDisplayReference(String membershipDisplayReference) { public void setMembershipDisplayLabel(String membershipDisplayLabel) {
this.membershipDisplayReference = membershipDisplayReference; this.membershipDisplayLabel = membershipDisplayLabel;
} }
@Override @Override
@ -131,7 +147,23 @@ public class AssetDTO implements Serializable {
", amount=" + getAmount() + ", amount=" + getAmount() +
", remark='" + getRemark() + "'" + ", remark='" + getRemark() + "'" +
", membership=" + getMembershipId() + ", membership=" + getMembershipId() +
", membership='" + getMembershipDisplayReference() + "'" + ", membership='" + getMembershipDisplayLabel() + "'" +
"}"; "}";
} }
@JsonComponent
public static class AssetJsonSerializer extends JsonSerializerWithAccessFilter<AssetDTO> {
public AssetJsonSerializer(final ApplicationContext ctx) {
super(ctx);
}
}
@JsonComponent
public static class AssetJsonDeserializer extends JsonDeserializerWithAccessFilter<AssetDTO> {
public AssetJsonDeserializer(final ApplicationContext ctx) {
super(ctx);
}
}
} }

View File

@ -85,6 +85,9 @@ public class CustomerDTO extends FluentBuilder<CustomerDTO> implements AccessMap
@AccessFor(init = Role.ADMIN, update = Role.SUPPORTER, read = Role.SUPPORTER) @AccessFor(init = Role.ADMIN, update = Role.SUPPORTER, read = Role.SUPPORTER)
private String remark; private String remark;
@AccessFor(init=Role.ANYBODY, update=Role.ANYBODY, read = Role.ANY_CUSTOMER_USER)
private String displayLabel;
public Long getId() { public Long getId() {
return id; return id;
} }
@ -213,6 +216,14 @@ public class CustomerDTO extends FluentBuilder<CustomerDTO> implements AccessMap
this.remark = remark; this.remark = remark;
} }
public String getDisplayLabel() {
return displayLabel;
}
public void setDisplayLabel(final String displayLabel) {
this.displayLabel = displayLabel;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {

View File

@ -2,10 +2,9 @@ package org.hostsharing.hsadminng.service.dto;
import org.hostsharing.hsadminng.service.CustomerService; import org.hostsharing.hsadminng.service.CustomerService;
import org.hostsharing.hsadminng.service.MembershipService; import org.hostsharing.hsadminng.service.MembershipService;
import org.hostsharing.hsadminng.service.accessfilter.AccessFor; import org.hostsharing.hsadminng.service.accessfilter.*;
import org.hostsharing.hsadminng.service.accessfilter.ParentId; import org.springframework.boot.jackson.JsonComponent;
import org.hostsharing.hsadminng.service.accessfilter.Role; import org.springframework.context.ApplicationContext;
import org.hostsharing.hsadminng.service.accessfilter.SelfId;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
@ -16,7 +15,7 @@ import java.util.Objects;
/** /**
* A DTO for the Membership entity. * A DTO for the Membership entity.
*/ */
public class MembershipDTO extends FluentBuilder<MembershipDTO> implements Serializable { public class MembershipDTO extends FluentBuilder<MembershipDTO> implements Serializable, AccessMappings {
@SelfId(resolver = MembershipService.class) @SelfId(resolver = MembershipService.class)
@AccessFor(read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
@ -26,18 +25,18 @@ public class MembershipDTO extends FluentBuilder<MembershipDTO> implements Seria
@AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private LocalDate admissionDocumentDate; private LocalDate admissionDocumentDate;
@AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private LocalDate cancellationDocumentDate; private LocalDate cancellationDocumentDate;
@NotNull @NotNull
@AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private LocalDate memberFromDate; private LocalDate memberFromDate;
@AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private LocalDate memberUntilDate; private LocalDate memberUntilDate;
@Size(max = 160) @Size(max = 160)
@AccessFor(init = Role.ADMIN, read = Role.SUPPORTER) @AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = Role.SUPPORTER)
private String remark; private String remark;
@ParentId(resolver = CustomerService.class) @ParentId(resolver = CustomerService.class)
@ -47,6 +46,12 @@ public class MembershipDTO extends FluentBuilder<MembershipDTO> implements Seria
@AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private String customerPrefix; private String customerPrefix;
@AccessFor(init = Role.ANYBODY, update = Role.ANYBODY, read = Role.FINANCIAL_CONTACT)
private String displayLabel;
@AccessFor(init = Role.ANYBODY, update = Role.ANYBODY, read = Role.FINANCIAL_CONTACT)
private String customerDisplayLabel;
public Long getId() { public Long getId() {
return id; return id;
} }
@ -111,6 +116,22 @@ public class MembershipDTO extends FluentBuilder<MembershipDTO> implements Seria
this.customerPrefix = customerPrefix; this.customerPrefix = customerPrefix;
} }
public String getDisplayLabel() {
return displayLabel;
}
public void setDisplayLabel(final String displayLabel) {
this.displayLabel = displayLabel;
}
public String getCustomerDisplayLabel() {
return customerDisplayLabel;
}
public void setCustomerDisplayLabel(final String customerDisplayLabel) {
this.customerDisplayLabel = customerDisplayLabel;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {
@ -145,4 +166,20 @@ public class MembershipDTO extends FluentBuilder<MembershipDTO> implements Seria
", customer='" + getCustomerPrefix() + "'" + ", customer='" + getCustomerPrefix() + "'" +
"}"; "}";
} }
@JsonComponent
public static class MembershipJsonSerializer extends JsonSerializerWithAccessFilter<MembershipDTO> {
public MembershipJsonSerializer(final ApplicationContext ctx) {
super(ctx);
}
}
@JsonComponent
public static class MembershipJsonDeserializer extends JsonDeserializerWithAccessFilter<MembershipDTO> {
public MembershipJsonDeserializer(final ApplicationContext ctx) {
super(ctx);
}
}
} }

View File

@ -48,7 +48,7 @@ public class ShareDTO implements Serializable {
private Long membershipId; private Long membershipId;
@AccessFor(read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private String membershipDisplayReference; private String membershipDisplayLabel;
public Long getId() { public Long getId() {
return id; return id;
@ -106,12 +106,12 @@ public class ShareDTO implements Serializable {
this.membershipId = membershipId; this.membershipId = membershipId;
} }
public String getMembershipDisplayReference() { public String getMembershipDisplayLabel() {
return membershipDisplayReference; return membershipDisplayLabel;
} }
public void setMembershipDisplayReference(String membershipDisplayReference) { public void setMembershipDisplayLabel(String membershipDisplayLabel) {
this.membershipDisplayReference = membershipDisplayReference; this.membershipDisplayLabel = membershipDisplayLabel;
} }
@Override @Override
@ -145,7 +145,7 @@ public class ShareDTO implements Serializable {
", quantity=" + getQuantity() + ", quantity=" + getQuantity() +
", remark='" + getRemark() + "'" + ", remark='" + getRemark() + "'" +
", membership=" + getMembershipId() + ", membership=" + getMembershipId() +
", membership='" + getMembershipDisplayReference() + "'" + ", membership='" + getMembershipDisplayLabel() + "'" +
"}"; "}";
} }
} }

View File

@ -2,8 +2,10 @@ package org.hostsharing.hsadminng.service.mapper;
import org.hostsharing.hsadminng.domain.Asset; import org.hostsharing.hsadminng.domain.Asset;
import org.hostsharing.hsadminng.service.dto.AssetDTO; import org.hostsharing.hsadminng.service.dto.AssetDTO;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
/** /**
* Mapper for the entity Asset and its DTO AssetDTO. * Mapper for the entity Asset and its DTO AssetDTO.
@ -12,9 +14,14 @@ import org.mapstruct.Mapping;
public interface AssetMapper extends EntityMapper<AssetDTO, Asset> { public interface AssetMapper extends EntityMapper<AssetDTO, Asset> {
@Mapping(source = "membership.id", target = "membershipId") @Mapping(source = "membership.id", target = "membershipId")
@Mapping(source = "membership.admissionDocumentDate", target = "membershipDisplayReference") @Mapping(target = "membershipDisplayLabel", ignore = true)
AssetDTO toDto(Asset asset); AssetDTO toDto(Asset asset);
@AfterMapping
default void setMembershipDisplayLabel(final @MappingTarget AssetDTO dto, final Asset entity) {
dto.setMembershipDisplayLabel(MembershipMapper.displayLabel(entity.getMembership()));
}
@Mapping(source = "membershipId", target = "membership") @Mapping(source = "membershipId", target = "membership")
Asset toEntity(AssetDTO assetDTO); Asset toEntity(AssetDTO assetDTO);

View File

@ -1,9 +1,11 @@
package org.hostsharing.hsadminng.service.mapper; package org.hostsharing.hsadminng.service.mapper;
import org.hostsharing.hsadminng.domain.*; import org.hostsharing.hsadminng.domain.Customer;
import org.hostsharing.hsadminng.service.dto.CustomerDTO; import org.hostsharing.hsadminng.service.dto.CustomerDTO;
import org.mapstruct.AfterMapping;
import org.mapstruct.*; import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
/** /**
* Mapper for the entity Customer and its DTO CustomerDTO. * Mapper for the entity Customer and its DTO CustomerDTO.
@ -11,6 +13,18 @@ import org.mapstruct.*;
@Mapper(componentModel = "spring", uses = {}) @Mapper(componentModel = "spring", uses = {})
public interface CustomerMapper extends EntityMapper<CustomerDTO, Customer> { public interface CustomerMapper extends EntityMapper<CustomerDTO, Customer> {
static String displayLabel(Customer customer) {
return customer.getName()
+ " [" + customer.getReference() + ":" + customer.getPrefix() +"]";
}
@Mapping(target = "displayLabel", ignore = true)
CustomerDTO toDto(Customer customer);
@AfterMapping
default void setDisplayLabel(final @MappingTarget CustomerDTO dto, final Customer entity) {
dto.setDisplayLabel(displayLabel(entity));
}
@Mapping(target = "memberships", ignore = true) @Mapping(target = "memberships", ignore = true)
@Mapping(target = "sepamandates", ignore = true) @Mapping(target = "sepamandates", ignore = true)

View File

@ -1,9 +1,14 @@
package org.hostsharing.hsadminng.service.mapper; package org.hostsharing.hsadminng.service.mapper;
import org.hostsharing.hsadminng.domain.*; import org.hostsharing.hsadminng.domain.Customer;
import org.hostsharing.hsadminng.domain.Membership;
import org.hostsharing.hsadminng.service.dto.MembershipDTO; import org.hostsharing.hsadminng.service.dto.MembershipDTO;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.*; import java.util.Objects;
/** /**
* Mapper for the entity Membership and its DTO MembershipDTO. * Mapper for the entity Membership and its DTO MembershipDTO.
@ -11,10 +16,27 @@ import org.mapstruct.*;
@Mapper(componentModel = "spring", uses = {CustomerMapper.class}) @Mapper(componentModel = "spring", uses = {CustomerMapper.class})
public interface MembershipMapper extends EntityMapper<MembershipDTO, Membership> { public interface MembershipMapper extends EntityMapper<MembershipDTO, Membership> {
static String displayLabel(final Membership entity) {
final Customer customer = entity.getCustomer();
return CustomerMapper.displayLabel(customer) + " "
+ Objects.toString(entity.getMemberFromDate(), "") + " - "
+ Objects.toString(entity.getMemberUntilDate(), "...");
}
@Mapping(source = "customer.id", target = "customerId") @Mapping(source = "customer.id", target = "customerId")
@Mapping(source = "customer.prefix", target = "customerPrefix") @Mapping(source = "customer.prefix", target = "customerPrefix")
@Mapping(target = "displayLabel", ignore = true)
@Mapping(target = "customerDisplayLabel", ignore = true)
MembershipDTO toDto(Membership membership); MembershipDTO toDto(Membership membership);
// TODO BLOG HOWTO: multi-field display reference for selection lists
// also change the filed in the option list in *-update.html
@AfterMapping
default void setMembershipDisplayLabel(final @MappingTarget MembershipDTO dto, final Membership entity) {
dto.setDisplayLabel(displayLabel(entity));
dto.setCustomerDisplayLabel(CustomerMapper.displayLabel(entity.getCustomer()));
}
@Mapping(target = "shares", ignore = true) @Mapping(target = "shares", ignore = true)
@Mapping(target = "assets", ignore = true) @Mapping(target = "assets", ignore = true)
@Mapping(source = "customerId", target = "customer") @Mapping(source = "customerId", target = "customer")

View File

@ -2,8 +2,10 @@ package org.hostsharing.hsadminng.service.mapper;
import org.hostsharing.hsadminng.domain.Share; import org.hostsharing.hsadminng.domain.Share;
import org.hostsharing.hsadminng.service.dto.ShareDTO; import org.hostsharing.hsadminng.service.dto.ShareDTO;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
/** /**
* Mapper for the entity Share and its DTO ShareDTO. * Mapper for the entity Share and its DTO ShareDTO.
@ -12,9 +14,14 @@ import org.mapstruct.Mapping;
public interface ShareMapper extends EntityMapper<ShareDTO, Share> { public interface ShareMapper extends EntityMapper<ShareDTO, Share> {
@Mapping(source = "membership.id", target = "membershipId") @Mapping(source = "membership.id", target = "membershipId")
@Mapping(source = "membership.admissionDocumentDate", target = "membershipDisplayReference") @Mapping(target = "membershipDisplayLabel", ignore = true)
ShareDTO toDto(Share share); ShareDTO toDto(Share share);
@AfterMapping
default void setMembershipDisplayLabel(final @MappingTarget ShareDTO dto, final Share entity) {
dto.setMembershipDisplayLabel(MembershipMapper.displayLabel(entity.getMembership()));
}
@Mapping(source = "membershipId", target = "membership") @Mapping(source = "membershipId", target = "membership")
Share toEntity(ShareDTO shareDTO); Share toEntity(ShareDTO shareDTO);

View File

@ -131,7 +131,7 @@ public class CustomerResource {
@DeleteMapping("/customers/{id}") @DeleteMapping("/customers/{id}")
public ResponseEntity<Void> deleteCustomer(@PathVariable Long id) { public ResponseEntity<Void> deleteCustomer(@PathVariable Long id) {
log.debug("REST request to delete Customer : {}", id); log.debug("REST request to delete Customer : {}", id);
customerService.delete(id); // TODO mhoennig: Rather completely remove the endpoint?
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build(); throw new BadRequestAlertException("Customres can't be deleted", ENTITY_NAME, "customerNotDeletable");
} }
} }

View File

@ -1,25 +1,24 @@
package org.hostsharing.hsadminng.web.rest; package org.hostsharing.hsadminng.web.rest;
import io.github.jhipster.web.util.ResponseUtil;
import org.hostsharing.hsadminng.service.MembershipQueryService;
import org.hostsharing.hsadminng.service.MembershipService; import org.hostsharing.hsadminng.service.MembershipService;
import org.hostsharing.hsadminng.service.dto.MembershipCriteria;
import org.hostsharing.hsadminng.service.dto.MembershipDTO;
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException; import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
import org.hostsharing.hsadminng.web.rest.util.HeaderUtil; import org.hostsharing.hsadminng.web.rest.util.HeaderUtil;
import org.hostsharing.hsadminng.web.rest.util.PaginationUtil; import org.hostsharing.hsadminng.web.rest.util.PaginationUtil;
import org.hostsharing.hsadminng.service.dto.MembershipDTO;
import org.hostsharing.hsadminng.service.dto.MembershipCriteria;
import org.hostsharing.hsadminng.service.MembershipQueryService;
import io.github.jhipster.web.util.ResponseUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -132,7 +131,7 @@ public class MembershipResource {
@DeleteMapping("/memberships/{id}") @DeleteMapping("/memberships/{id}")
public ResponseEntity<Void> deleteMembership(@PathVariable Long id) { public ResponseEntity<Void> deleteMembership(@PathVariable Long id) {
log.debug("REST request to delete Membership : {}", id); log.debug("REST request to delete Membership : {}", id);
membershipService.delete(id); // TODO mhoennig: Rather completely remove the endpoint?
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build(); throw new BadRequestAlertException("Memberships can't be deleted", ENTITY_NAME, "membershipNotDeletable");
} }
} }

View File

@ -37,7 +37,10 @@ spring:
indent-output: true indent-output: true
datasource: datasource:
type: com.zaxxer.hikari.HikariDataSource type: com.zaxxer.hikari.HikariDataSource
# H2 in memory:
url: jdbc:h2:mem:hsadminng;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE url: jdbc:h2:mem:hsadminng;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
# H2 in file:
# url: jdbc:h2:~/.hsadminng.h2db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: hsadminNg username: hsadminNg
password: password:
hikari: hikari:

View File

@ -26,6 +26,7 @@
<appender-ref ref="ASYNC"/> <appender-ref ref="ASYNC"/>
</root> </root>
--> -->
<logger name="org.hostsharing.hsadminng" level="INFO"/>
<logger name="javax.activation" level="WARN"/> <logger name="javax.activation" level="WARN"/>
<logger name="javax.mail" level="WARN"/> <logger name="javax.mail" level="WARN"/>

View File

@ -1,7 +1,7 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-8"> <div class="col-8">
<div *ngIf="asset"> <div *ngIf="asset">
<h2><span jhiTranslate="hsadminNgApp.asset.detail.title">Asset</span> {{asset.id}}</h2> <h2><span jhiTranslate="hsadminNgApp.asset.detail.title">Asset</span>: #{{asset.id}} - {{asset.membershipDisplayLabel}}</h2>
<hr> <hr>
<jhi-alert-error></jhi-alert-error> <jhi-alert-error></jhi-alert-error>
<dl class="row-md jh-entity-details"> <dl class="row-md jh-entity-details">
@ -28,7 +28,7 @@
<dt><span jhiTranslate="hsadminNgApp.asset.membership">Membership</span></dt> <dt><span jhiTranslate="hsadminNgApp.asset.membership">Membership</span></dt>
<dd> <dd>
<div *ngIf="asset.membershipId"> <div *ngIf="asset.membershipId">
<a [routerLink]="['/membership', asset.membershipId, 'view']">{{asset.membershipDisplayReference}}</a> <a [routerLink]="['/membership', asset.membershipId, 'view']">{{asset.membershipDisplayLabel}}</a>
</div> </div>
</dd> </dd>
</dl> </dl>

View File

@ -89,7 +89,7 @@
<label class="form-control-label" jhiTranslate="hsadminNgApp.asset.membership" for="field_membership">Membership</label> <label class="form-control-label" jhiTranslate="hsadminNgApp.asset.membership" for="field_membership">Membership</label>
<select class="form-control" id="field_membership" name="membership" [(ngModel)]="asset.membershipId" required> <select class="form-control" id="field_membership" name="membership" [(ngModel)]="asset.membershipId" required>
<option *ngIf="!editForm.value.membership" [ngValue]="null" selected></option> <option *ngIf="!editForm.value.membership" [ngValue]="null" selected></option>
<option [ngValue]="membershipOption.id" *ngFor="let membershipOption of memberships; trackBy: trackMembershipById">{{membershipOption.admissionDocumentDate}}</option> <option [ngValue]="membershipOption.id" *ngFor="let membershipOption of memberships; trackBy: trackMembershipById">{{membershipOption.displayLabel}}</option>
</select> </select>
</div> </div>
<div [hidden]="!(editForm.controls.membership?.dirty && editForm.controls.membership?.invalid)"> <div [hidden]="!(editForm.controls.membership?.dirty && editForm.controls.membership?.invalid)">

View File

@ -19,8 +19,7 @@
<th jhiSortBy="valueDate"><span jhiTranslate="hsadminNgApp.asset.valueDate">Value Date</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="valueDate"><span jhiTranslate="hsadminNgApp.asset.valueDate">Value Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="action"><span jhiTranslate="hsadminNgApp.asset.action">Action</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="action"><span jhiTranslate="hsadminNgApp.asset.action">Action</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="amount"><span jhiTranslate="hsadminNgApp.asset.amount">Amount</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="amount"><span jhiTranslate="hsadminNgApp.asset.amount">Amount</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="remark"><span jhiTranslate="hsadminNgApp.asset.remark">Remark</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="membershipDisplayLabel"><span jhiTranslate="hsadminNgApp.asset.membership">Membership</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="membershipDisplayReference"><span jhiTranslate="hsadminNgApp.asset.membership">Membership</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -31,10 +30,9 @@
<td>{{asset.valueDate | date:'mediumDate'}}</td> <td>{{asset.valueDate | date:'mediumDate'}}</td>
<td jhiTranslate="{{'hsadminNgApp.AssetAction.' + asset.action}}">{{asset.action}}</td> <td jhiTranslate="{{'hsadminNgApp.AssetAction.' + asset.action}}">{{asset.action}}</td>
<td>{{asset.amount}}</td> <td>{{asset.amount}}</td>
<td>{{asset.remark}}</td>
<td> <td>
<div *ngIf="asset.membershipId"> <div *ngIf="asset.membershipId">
<a [routerLink]="['../membership', asset.membershipId , 'view' ]" >{{asset.membershipDisplayReference}}</a> <a [routerLink]="['../membership', asset.membershipId , 'view' ]" >{{asset.membershipDisplayLabel}}</a>
</div> </div>
</td> </td>
<td class="text-right"> <td class="text-right">

View File

@ -1,7 +1,7 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-8"> <div class="col-8">
<div *ngIf="customer"> <div *ngIf="customer">
<h2><span jhiTranslate="hsadminNgApp.customer.detail.title">Customer</span> {{customer.id}}</h2> <h2><span jhiTranslate="hsadminNgApp.customer.detail.title">Customer</span>: {{customer.displayLabel}}</h2>
<hr> <hr>
<jhi-alert-error></jhi-alert-error> <jhi-alert-error></jhi-alert-error>
<dl class="row-md jh-entity-details"> <dl class="row-md jh-entity-details">

View File

@ -18,18 +18,7 @@
<th jhiSortBy="reference"><span jhiTranslate="hsadminNgApp.customer.reference">Reference</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="reference"><span jhiTranslate="hsadminNgApp.customer.reference">Reference</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="prefix"><span jhiTranslate="hsadminNgApp.customer.prefix">Prefix</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="prefix"><span jhiTranslate="hsadminNgApp.customer.prefix">Prefix</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="name"><span jhiTranslate="hsadminNgApp.customer.name">Name</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="name"><span jhiTranslate="hsadminNgApp.customer.name">Name</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="kind"><span jhiTranslate="hsadminNgApp.customer.kind">Kind</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="kind"><span jhiTranslate="hsadminNgApp.customer.kind">Kind</span> <fa-icon [icon]="'sort'"></fa-icon></thn></th>
<th jhiSortBy="birthDate"><span jhiTranslate="hsadminNgApp.customer.birthDate">Birth Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="birthPlace"><span jhiTranslate="hsadminNgApp.customer.birthPlace">Birth Place</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="registrationCourt"><span jhiTranslate="hsadminNgApp.customer.registrationCourt">Registration Court</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="registrationNumber"><span jhiTranslate="hsadminNgApp.customer.registrationNumber">Registration Number</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="vatRegion"><span jhiTranslate="hsadminNgApp.customer.vatRegion">Vat Region</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="vatNumber"><span jhiTranslate="hsadminNgApp.customer.vatNumber">Vat Number</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="contractualSalutation"><span jhiTranslate="hsadminNgApp.customer.contractualSalutation">Contractual Salutation</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="contractualAddress"><span jhiTranslate="hsadminNgApp.customer.contractualAddress">Contractual Address</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="billingSalutation"><span jhiTranslate="hsadminNgApp.customer.billingSalutation">Billing Salutation</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="billingAddress"><span jhiTranslate="hsadminNgApp.customer.billingAddress">Billing Address</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="remark"><span jhiTranslate="hsadminNgApp.customer.remark">Remark</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -40,17 +29,6 @@
<td>{{customer.prefix}}</td> <td>{{customer.prefix}}</td>
<td>{{customer.name}}</td> <td>{{customer.name}}</td>
<td jhiTranslate="{{'hsadminNgApp.CustomerKind.' + customer.kind}}">{{customer.kind}}</td> <td jhiTranslate="{{'hsadminNgApp.CustomerKind.' + customer.kind}}">{{customer.kind}}</td>
<td>{{customer.birthDate | date:'mediumDate'}}</td>
<td>{{customer.birthPlace}}</td>
<td>{{customer.registrationCourt}}</td>
<td>{{customer.registrationNumber}}</td>
<td jhiTranslate="{{'hsadminNgApp.VatRegion.' + customer.vatRegion}}">{{customer.vatRegion}}</td>
<td>{{customer.vatNumber}}</td>
<td>{{customer.contractualSalutation}}</td>
<td>{{customer.contractualAddress}}</td>
<td>{{customer.billingSalutation}}</td>
<td>{{customer.billingAddress}}</td>
<td>{{customer.remark}}</td>
<td class="text-right"> <td class="text-right">
<div class="btn-group flex-btn-group-container"> <div class="btn-group flex-btn-group-container">
<button type="submit" <button type="submit"

View File

@ -1,7 +1,7 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-8"> <div class="col-8">
<div *ngIf="membership"> <div *ngIf="membership">
<h2><span jhiTranslate="hsadminNgApp.membership.detail.title">Membership</span> {{membership.id}}</h2> <h2><span jhiTranslate="hsadminNgApp.membership.detail.title">Membership</span>: {{membership.displayLabel}}</h2>
<hr> <hr>
<jhi-alert-error></jhi-alert-error> <jhi-alert-error></jhi-alert-error>
<dl class="row-md jh-entity-details"> <dl class="row-md jh-entity-details">
@ -28,7 +28,7 @@
<dt><span jhiTranslate="hsadminNgApp.membership.customer">Customer</span></dt> <dt><span jhiTranslate="hsadminNgApp.membership.customer">Customer</span></dt>
<dd> <dd>
<div *ngIf="membership.customerId"> <div *ngIf="membership.customerId">
<a [routerLink]="['/customer', membership.customerId, 'view']">{{membership.customerPrefix}}</a> <a [routerLink]="['/customer', membership.customerId, 'view']">{{membership.customerDisplayLabel}}</a>
</div> </div>
</dd> </dd>
</dl> </dl>

View File

@ -77,7 +77,7 @@
<label class="form-control-label" jhiTranslate="hsadminNgApp.membership.customer" for="field_customer">Customer</label> <label class="form-control-label" jhiTranslate="hsadminNgApp.membership.customer" for="field_customer">Customer</label>
<select class="form-control" id="field_customer" name="customer" [(ngModel)]="membership.customerId" required> <select class="form-control" id="field_customer" name="customer" [(ngModel)]="membership.customerId" required>
<option *ngIf="!editForm.value.customer" [ngValue]="null" selected></option> <option *ngIf="!editForm.value.customer" [ngValue]="null" selected></option>
<option [ngValue]="customerOption.id" *ngFor="let customerOption of customers; trackBy: trackCustomerById">{{customerOption.prefix}}</option> <option [ngValue]="customerOption.id" *ngFor="let customerOption of customers; trackBy: trackCustomerById">{{customerOption.displayLabel}}</option>
</select> </select>
</div> </div>
<div [hidden]="!(editForm.controls.customer?.dirty && editForm.controls.customer?.invalid)"> <div [hidden]="!(editForm.controls.customer?.dirty && editForm.controls.customer?.invalid)">

View File

@ -19,7 +19,6 @@
<th jhiSortBy="cancellationDocumentDate"><span jhiTranslate="hsadminNgApp.membership.cancellationDocumentDate">Cancellation Document Date</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="cancellationDocumentDate"><span jhiTranslate="hsadminNgApp.membership.cancellationDocumentDate">Cancellation Document Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="memberFromDate"><span jhiTranslate="hsadminNgApp.membership.memberFromDate">Member From Date</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="memberFromDate"><span jhiTranslate="hsadminNgApp.membership.memberFromDate">Member From Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="memberUntilDate"><span jhiTranslate="hsadminNgApp.membership.memberUntilDate">Member Until Date</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="memberUntilDate"><span jhiTranslate="hsadminNgApp.membership.memberUntilDate">Member Until Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="remark"><span jhiTranslate="hsadminNgApp.membership.remark">Remark</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="customerPrefix"><span jhiTranslate="hsadminNgApp.membership.customer">Customer</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="customerPrefix"><span jhiTranslate="hsadminNgApp.membership.customer">Customer</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th></th> <th></th>
</tr> </tr>
@ -28,13 +27,12 @@
<tr *ngFor="let membership of memberships ;trackBy: trackId"> <tr *ngFor="let membership of memberships ;trackBy: trackId">
<td><a [routerLink]="['/membership', membership.id, 'view' ]">{{membership.id}}</a></td> <td><a [routerLink]="['/membership', membership.id, 'view' ]">{{membership.id}}</a></td>
<td>{{membership.admissionDocumentDate | date:'mediumDate'}}</td> <td>{{membership.admissionDocumentDate | date:'mediumDate'}}</td>
<td>{{membership.cancellationDocumentDate | date:'mediumDate'}}</td> <td>{{membership.cancellationDocumentDate | date:'mediumDsate'}}</td>
<td>{{membership.memberFromDate | date:'mediumDate'}}</td> <td>{{membership.memberFromDate | date:'mediumDate'}}</td>
<td>{{membership.memberUntilDate | date:'mediumDate'}}</td> <td>{{membership.memberUntilDate | date:'mediumDate'}}</td>
<td>{{membership.remark}}</td>
<td> <td>
<div *ngIf="membership.customerId"> <div *ngIf="membership.customerId">
<a [routerLink]="['../customer', membership.customerId , 'view' ]" >{{membership.customerPrefix}}</a> <a [routerLink]="['../customer', membership.customerId , 'view' ]" >{{membership.customerDisplayLabel}}</a>
</div> </div>
</td> </td>
<td class="text-right"> <td class="text-right">

View File

@ -1,7 +1,7 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-8"> <div class="col-8">
<div *ngIf="share"> <div *ngIf="share">
<h2><span jhiTranslate="hsadminNgApp.share.detail.title">Share</span> {{share.id}}</h2> <h2><span jhiTranslate="hsadminNgApp.share.detail.title">Share</span>: #{{share.id}} - {{share.membershipDisplayLabel}}</h2>
<hr> <hr>
<jhi-alert-error></jhi-alert-error> <jhi-alert-error></jhi-alert-error>
<dl class="row-md jh-entity-details"> <dl class="row-md jh-entity-details">
@ -28,7 +28,7 @@
<dt><span jhiTranslate="hsadminNgApp.share.membership">Membership</span></dt> <dt><span jhiTranslate="hsadminNgApp.share.membership">Membership</span></dt>
<dd> <dd>
<div *ngIf="share.membershipId"> <div *ngIf="share.membershipId">
<a [routerLink]="['/membership', share.membershipId, 'view']">{{share.membershipDisplayReference}}</a> <a [routerLink]="['/membership', share.membershipId, 'view']">{{share.membershipDisplayLabel}}</a>
</div> </div>
</dd> </dd>
</dl> </dl>

View File

@ -85,7 +85,7 @@
<label class="form-control-label" jhiTranslate="hsadminNgApp.share.membership" for="field_membership">Membership</label> <label class="form-control-label" jhiTranslate="hsadminNgApp.share.membership" for="field_membership">Membership</label>
<select class="form-control" id="field_membership" name="membership" [(ngModel)]="share.membershipId" required> <select class="form-control" id="field_membership" name="membership" [(ngModel)]="share.membershipId" required>
<option *ngIf="!editForm.value.membership" [ngValue]="null" selected></option> <option *ngIf="!editForm.value.membership" [ngValue]="null" selected></option>
<option [ngValue]="membershipOption.id" *ngFor="let membershipOption of memberships; trackBy: trackMembershipById">{{membershipOption.admissionDocumentDate}}</option> <option [ngValue]="membershipOption.id" *ngFor="let membershipOption of memberships; trackBy: trackMembershipById">{{membershipOption.displayLabel}}</option>
</select> </select>
</div> </div>
<div [hidden]="!(editForm.controls.membership?.dirty && editForm.controls.membership?.invalid)"> <div [hidden]="!(editForm.controls.membership?.dirty && editForm.controls.membership?.invalid)">

View File

@ -19,8 +19,7 @@
<th jhiSortBy="valueDate"><span jhiTranslate="hsadminNgApp.share.valueDate">Value Date</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="valueDate"><span jhiTranslate="hsadminNgApp.share.valueDate">Value Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="action"><span jhiTranslate="hsadminNgApp.share.action">Action</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="action"><span jhiTranslate="hsadminNgApp.share.action">Action</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="quantity"><span jhiTranslate="hsadminNgApp.share.quantity">Quantity</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="quantity"><span jhiTranslate="hsadminNgApp.share.quantity">Quantity</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="remark"><span jhiTranslate="hsadminNgApp.share.remark">Remark</span> <fa-icon [icon]="'sort'"></fa-icon></th> <th jhiSortBy="membershipDisplayLabel"><span jhiTranslate="hsadminNgApp.share.membership">Membership</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="membershipDisplayReference"><span jhiTranslate="hsadminNgApp.share.membership">Membership</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -31,10 +30,9 @@
<td>{{share.valueDate | date:'mediumDate'}}</td> <td>{{share.valueDate | date:'mediumDate'}}</td>
<td jhiTranslate="{{'hsadminNgApp.ShareAction.' + share.action}}">{{share.action}}</td> <td jhiTranslate="{{'hsadminNgApp.ShareAction.' + share.action}}">{{share.action}}</td>
<td>{{share.quantity}}</td> <td>{{share.quantity}}</td>
<td>{{share.remark}}</td>
<td> <td>
<div *ngIf="share.membershipId"> <div *ngIf="share.membershipId">
<a [routerLink]="['../membership', share.membershipId , 'view' ]" >{{share.membershipDisplayReference}}</a> <a [routerLink]="['../membership', share.membershipId , 'view' ]" >{{share.membershipDisplayLabel}}</a>
</div> </div>
</td> </td>
<td class="text-right"> <td class="text-right">

View File

@ -16,8 +16,8 @@ export interface IAsset {
action?: AssetAction; action?: AssetAction;
amount?: number; amount?: number;
remark?: string; remark?: string;
membershipDisplayReference?: string;
membershipId?: number; membershipId?: number;
membershipDisplayLabel?: string;
} }
export class Asset implements IAsset { export class Asset implements IAsset {
@ -28,7 +28,7 @@ export class Asset implements IAsset {
public action?: AssetAction, public action?: AssetAction,
public amount?: number, public amount?: number,
public remark?: string, public remark?: string,
public membershipDisplayReference?: string, public membershipId?: number,
public membershipId?: number public membershipDisplayLabel?: string
) {} ) {}
} }

View File

@ -32,6 +32,7 @@ export interface ICustomer {
remark?: string; remark?: string;
memberships?: IMembership[]; memberships?: IMembership[];
sepamandates?: ISepaMandate[]; sepamandates?: ISepaMandate[];
displayLabel?: string;
} }
export class Customer implements ICustomer { export class Customer implements ICustomer {
@ -53,6 +54,7 @@ export class Customer implements ICustomer {
public billingAddress?: string, public billingAddress?: string,
public remark?: string, public remark?: string,
public memberships?: IMembership[], public memberships?: IMembership[],
public sepamandates?: ISepaMandate[] public sepamandates?: ISepaMandate[],
public displayLabel?: string
) {} ) {}
} }

View File

@ -13,6 +13,8 @@ export interface IMembership {
assets?: IAsset[]; assets?: IAsset[];
customerPrefix?: string; customerPrefix?: string;
customerId?: number; customerId?: number;
customerDisplayLabel?: string;
displayLabel?: string;
} }
export class Membership implements IMembership { export class Membership implements IMembership {
@ -26,6 +28,8 @@ export class Membership implements IMembership {
public shares?: IShare[], public shares?: IShare[],
public assets?: IAsset[], public assets?: IAsset[],
public customerPrefix?: string, public customerPrefix?: string,
public customerId?: number public customerId?: number,
public customerDisplayLabel?: string,
public displayLabel?: string
) {} ) {}
} }

View File

@ -12,7 +12,7 @@ export interface IShare {
action?: ShareAction; action?: ShareAction;
quantity?: number; quantity?: number;
remark?: string; remark?: string;
membershipDisplayReference?: string; membershipDisplayLabel?: string;
membershipId?: number; membershipId?: number;
} }
@ -24,7 +24,7 @@ export class Share implements IShare {
public action?: ShareAction, public action?: ShareAction,
public quantity?: number, public quantity?: number,
public remark?: string, public remark?: string,
public membershipDisplayReference?: string, public membershipDisplayLabel?: string,
public membershipId?: number public membershipId?: number
) {} ) {}
} }

View File

@ -5,6 +5,7 @@
"shareCancellationNegativeQuantity": "Kündigungen von Geschäftsanteilen erfordern eine negative Stückzahl", "shareCancellationNegativeQuantity": "Kündigungen von Geschäftsanteilen erfordern eine negative Stückzahl",
"shareTransactionImmutable": "Transaktionen mit Geschäftsanteilen sind unveränderlich", "shareTransactionImmutable": "Transaktionen mit Geschäftsanteilen sind unveränderlich",
"membershipNotDeletable": "Mitgliedschaft kann nicht gelöscht werden, setze stattdessen das 'untilDate'", "membershipNotDeletable": "Mitgliedschaft kann nicht gelöscht werden, setze stattdessen das 'untilDate'",
"customerNotDeletable": "Kunden können nicht explizit gelöscht werden'",
"untilDateMustBeAfterSinceDate": "Mitgliedshafts-Austrittsdatum muss nach dem Beitrittsdatum liegen", "untilDateMustBeAfterSinceDate": "Mitgliedshafts-Austrittsdatum muss nach dem Beitrittsdatum liegen",
"anotherUncancelledMembershipExists": "Nur eine einzige ungekündigte Mitgliedschaft pro Kunde ist zulässig", "anotherUncancelledMembershipExists": "Nur eine einzige ungekündigte Mitgliedschaft pro Kunde ist zulässig",
"initializationProhibited": "Initialisierung des Feldes unzulässig", "initializationProhibited": "Initialisierung des Feldes unzulässig",

View File

@ -5,6 +5,7 @@
"shareCancellationNegativeQuantity": "Share cancellations require a negative quantity", "shareCancellationNegativeQuantity": "Share cancellations require a negative quantity",
"shareTransactionImmutable": "Share transactions are immutable", "shareTransactionImmutable": "Share transactions are immutable",
"membershipNotDeletable": "Membership cannot be deleted, instead set 'untilDate'", "membershipNotDeletable": "Membership cannot be deleted, instead set 'untilDate'",
"customerNotDeletable": "Customer cannot be deleted explicitly'",
"untilDateMustBeAfterSinceDate": "Membership until date must be after since date", "untilDateMustBeAfterSinceDate": "Membership until date must be after since date",
"anotherUncancelledMembershipExists": "Only a single uncancelled membership allowed per customer", "anotherUncancelledMembershipExists": "Only a single uncancelled membership allowed per customer",
"initializationProhibited": "Initialization of the field prohibited", "initializationProhibited": "Initialization of the field prohibited",

View File

@ -0,0 +1,167 @@
package org.hostsharing.hsadminng.service;
import org.apache.commons.lang3.RandomUtils;
import org.hostsharing.hsadminng.domain.Asset;
import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
import org.hostsharing.hsadminng.repository.AssetRepository;
import org.hostsharing.hsadminng.service.dto.AssetDTO;
import org.hostsharing.hsadminng.service.mapper.AssetMapper;
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import javax.persistence.EntityManager;
import java.math.BigDecimal;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowableOfType;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;
// HINT: In IntelliJ IDEA such unit test classes can be created with Shift-Ctrl-T.
// Do not forget to amend the class name (.e.g. ...UnitTest / ...IntTest)!
public class AssetServiceUnitTest {
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock
private EntityManager em;
@Mock
private AssetRepository assetRepository;
@Mock
private AssetValidator assetValidator; // needed for @InjectMocks assetService
@Mock
private AssetMapper assetMapper;
@InjectMocks
private AssetService assetService;
// HINT: Click outside of any test method (e.g. here) and use Ctrl-Shift-F10
// to run all tests from this test class. Use Ctrl-F5 to run the last execution again;
// 'execution' here can also apply to running the application, whatever ran last.
// HINT: In IntelliJ IDEA such test methods can be created with Alt-Insert.
@Test
public void deleteIsRejectedForAssetTransactions() {
// when
final Throwable throwException = catchThrowableOfType(() -> assetService.delete(RandomUtils.nextLong()), BadRequestAlertException.class);
// then
// HINT: When using auto-import for assertions (e.g. via Alt-Enter in IntelliJ IDEA),
// beware to use the correct candidate from org.assertj.core.api.Assertions.
assertThat(throwException).isEqualToComparingFieldByField(
new BadRequestAlertException("Asset transactions are immutable", "asset", "assetTransactionImmutable"));
}
@Test
public void saveShouldPersistValidTransactions() {
// given
final AssetDTO givenAssetDTO = givenAssetDTO(null, AssetAction.PAYMENT, anyPositiveAmout());
// HINT: given(...)...will...() can't be used for void methods, in that case use Mockito's do...() methods
doNothing().when(assetValidator).validate(givenAssetDTO);
// when
final AssetDTO returnedAssetDto = assetService.save(givenAssetDTO);
// then
verify(em).flush();
verify(em).refresh(any(Asset.class));
assertThat(returnedAssetDto).isEqualToIgnoringGivenFields(givenAssetDTO, "id");
}
@Test
public void saveShouldNotPersistInvalidTransactions() {
// given
final AssetDTO givenAssetDTO = givenAssetDTO(null, AssetAction.PAYMENT, anyNegativeAmount());
doThrow(new BadRequestAlertException("Some Dummy Test Violation", "asset", "assetInvalidTestDummy")).when(assetValidator).validate(givenAssetDTO);
// when
final Throwable throwException = catchThrowableOfType(() -> assetService.save(givenAssetDTO), BadRequestAlertException.class);
// then
assertThat(throwException).isEqualToComparingFieldByField(
new BadRequestAlertException("Some Dummy Test Violation", "asset", "assetInvalidTestDummy"));
}
@Test
public void saveShouldUpdateValidTransactions() {
// given
final AssetDTO givenAssetDTO = givenAssetDTO(anyNonNullId(), AssetAction.PAYMENT, anyPositiveAmout());
doNothing().when(assetValidator).validate(givenAssetDTO);
// when
final AssetDTO returnedAssetDto = assetService.save(givenAssetDTO);
// then
verify(em).flush();
verify(em).refresh(any(Asset.class));
assertThat(returnedAssetDto).isEqualToIgnoringGivenFields(givenAssetDTO, "id");
}
@Test
public void saveShouldNotUpdateInvalidTransactions() {
// given
final AssetDTO givenAssetDTO = givenAssetDTO(anyNonNullId(), AssetAction.PAYMENT, anyNegativeAmount());
// HINT: given(...) can't be used for void methods, in that case use Mockito's do...() methods
doThrow(new BadRequestAlertException("Some Dummy Test Violation", "asset", "assetInvalidTestDummy")).when(assetValidator).validate(givenAssetDTO);
// when
final Throwable throwException = catchThrowableOfType(() -> assetService.save(givenAssetDTO), BadRequestAlertException.class);
// then
assertThat(throwException).isEqualToComparingFieldByField(
new BadRequestAlertException("Some Dummy Test Violation", "asset", "assetInvalidTestDummy"));
}
// --- only test fixture code below ---
private long anyNonNullId() {
return RandomUtils.nextInt();
}
// HINT: This rather complicated setup indicates that the method AssetService::save breaks the single responsibility principle.
private AssetDTO givenAssetDTO(final Long id, final AssetAction givenAction, final BigDecimal givenQuantity) {
final AssetDTO givenAssetDTO = createAssetDTO(id, givenAction, givenQuantity);
// dto -> entity
final Asset givenAssetEntity = Mockito.mock(Asset.class);
given(assetMapper.toEntity(same(givenAssetDTO))).willReturn(givenAssetEntity);
// assetRepository.save(entity);
final Asset persistedAssetEntity = Mockito.mock(Asset.class);
given(assetRepository.save(same(givenAssetEntity))).willReturn(persistedAssetEntity);
// entity -> dto
AssetDTO persistedAssetDTO = createAssetDTO(id == null ? RandomUtils.nextLong() : id, givenAction, givenQuantity);
given(assetMapper.toDto(same(persistedAssetEntity))).willReturn(persistedAssetDTO);
return givenAssetDTO;
}
private AssetDTO createAssetDTO(Long id, AssetAction givenAction, BigDecimal givenAmount) {
final AssetDTO givenAssetDTO = new AssetDTO();
givenAssetDTO.setId(id);
givenAssetDTO.setAction(givenAction);
givenAssetDTO.setAmount(givenAmount);
return givenAssetDTO;
}
private BigDecimal anyPositiveAmout() {
return BigDecimal.valueOf(RandomUtils.nextInt()).add(new BigDecimal("0.1"));
}
private BigDecimal anyNegativeAmount() {
return anyPositiveAmout().negate();
}
}

View File

@ -15,12 +15,13 @@ import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import javax.persistence.EntityManager;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowableOfType; import static org.assertj.core.api.Assertions.catchThrowableOfType;
import static org.mockito.ArgumentMatchers.same; import static org.mockito.ArgumentMatchers.same;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.*;
import static org.mockito.Mockito.doThrow;
// HINT: In IntelliJ IDEA such unit test classes can be created with Shift-Ctrl-T. // HINT: In IntelliJ IDEA such unit test classes can be created with Shift-Ctrl-T.
@ -30,6 +31,9 @@ public class ShareServiceUnitTest {
@Rule @Rule
public MockitoRule mockitoRule = MockitoJUnit.rule(); public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock
private EntityManager em;
@Mock @Mock
private ShareRepository shareRepository; private ShareRepository shareRepository;
@ -70,6 +74,8 @@ public class ShareServiceUnitTest {
final ShareDTO returnedShareDto = shareService.save(givenShareDTO); final ShareDTO returnedShareDto = shareService.save(givenShareDTO);
// then // then
verify(em).flush();
verify(em).refresh(any(Share.class));
assertThat(returnedShareDto).isEqualToIgnoringGivenFields(givenShareDTO, "id"); assertThat(returnedShareDto).isEqualToIgnoringGivenFields(givenShareDTO, "id");
} }
@ -97,6 +103,8 @@ public class ShareServiceUnitTest {
final ShareDTO returnedShareDto = shareService.save(givenShareDTO); final ShareDTO returnedShareDto = shareService.save(givenShareDTO);
// then // then
verify(em).flush();
verify(em).refresh(any(Share.class));
assertThat(returnedShareDto).isEqualToIgnoringGivenFields(givenShareDTO, "id"); assertThat(returnedShareDto).isEqualToIgnoringGivenFields(givenShareDTO, "id");
} }

View File

@ -1,11 +1,14 @@
package org.hostsharing.hsadminng.service.accessfilter; package org.hostsharing.hsadminng.service.accessfilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.List; import java.util.List;
public class JSonBuilder { public class JSonBuilder {
private StringBuilder json = new StringBuilder();
@SafeVarargs @SafeVarargs
public static String asJSon(final ImmutablePair<String, Object>... properties) { public static String asJSon(final ImmutablePair<String, Object>... properties) {
final StringBuilder json = new StringBuilder(); final StringBuilder json = new StringBuilder();
@ -14,15 +17,8 @@ public class JSonBuilder {
json.append(": "); json.append(": ");
if (prop.right instanceof Number) { if (prop.right instanceof Number) {
json.append(prop.right); json.append(prop.right);
} else if (prop.right instanceof List) { } else if (prop.right instanceof List) {
json.append("["); json.append(toJSonArray(prop.right));
for ( int n = 0; n < ((List<Integer>)prop.right).size(); ++n ) {
if ( n > 0 ) {
json.append(",");
}
json.append(((List<Integer>)prop.right).get(n));
}
json.append("]");
} else { } else {
json.append(inQuotes(prop.right)); json.append(inQuotes(prop.right));
} }
@ -31,6 +27,50 @@ public class JSonBuilder {
return "{\n" + json.substring(0, json.length() - 2) + "\n}"; return "{\n" + json.substring(0, json.length() - 2) + "\n}";
} }
public JSonBuilder withFieldValue(String name, String value) {
json.append(inQuotes(name) + ":" + (value != null ? inQuotes(value) : "null") + ",");
return this;
}
public JSonBuilder withFieldValue(String name, Number value) {
json.append(inQuotes(name) + ":" + (value != null ? value : "null") + ",");
return this;
}
public JSonBuilder toJSonNullFieldDefinition(String name) {
json.append(inQuotes(name) + ":null,");
return this;
}
public JSonBuilder withFieldValueIfPresent(String name, String value) {
json.append(value != null ? inQuotes(name) + ":" + inQuotes(value) + "," : "");
return this;
}
public JSonBuilder withFieldValueIfPresent(String name, Number value) {
json.append(value != null ? inQuotes(name) + ":" + value + "," : "");
return this;
}
@Override
public String toString() {
return "{" + StringUtils.removeEnd(json.toString(), ",") + "}";
}
@SuppressWarnings("unchecked")
// currently just for the case of date values represented as arrays of integer
private static String toJSonArray(final Object value) {
final StringBuilder jsonArray = new StringBuilder("[");
for (int n = 0; n < ((List<Integer>) value).size(); ++n) {
if (n > 0) {
jsonArray.append(",");
}
jsonArray.append(((List<Integer>) value).get(n));
}
return jsonArray.toString() + "]";
}
private static String inQuotes(Object value) { private static String inQuotes(Object value) {
return value != null ? "\"" + value.toString() + "\"" : "null"; return value != null ? "\"" + value.toString() + "\"" : "null";
} }

View File

@ -20,7 +20,7 @@ public class MockSecurityContext {
public static void givenUserHavingRole(final Class<?> onClass, final Long onId, final Role role) { public static void givenUserHavingRole(final Class<?> onClass, final Long onId, final Role role) {
if ((onClass == null || onId == null) && !role.isIndependent()) { if ((onClass == null || onId == null) && !role.isIndependent()) {
throw new IllegalArgumentException("dependent roles like " + role + " missing DtoClass and ID"); throw new IllegalArgumentException("dependent role " + role + " needs DtoClass and ID");
} }
SecurityUtils.addUserRole(onClass, onId, role); SecurityUtils.addUserRole(onClass, onId, role);
} }

View File

@ -0,0 +1,214 @@
package org.hostsharing.hsadminng.service.dto;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.RandomUtils;
import org.hostsharing.hsadminng.domain.Asset;
import org.hostsharing.hsadminng.domain.Customer;
import org.hostsharing.hsadminng.domain.Membership;
import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
import org.hostsharing.hsadminng.repository.AssetRepository;
import org.hostsharing.hsadminng.repository.CustomerRepository;
import org.hostsharing.hsadminng.repository.MembershipRepository;
import org.hostsharing.hsadminng.service.AssetService;
import org.hostsharing.hsadminng.service.AssetValidator;
import org.hostsharing.hsadminng.service.MembershipValidator;
import org.hostsharing.hsadminng.service.accessfilter.JSonBuilder;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.mapper.AssetMapper;
import org.hostsharing.hsadminng.service.mapper.AssetMapperImpl;
import org.hostsharing.hsadminng.service.mapper.CustomerMapperImpl;
import org.hostsharing.hsadminng.service.mapper.MembershipMapperImpl;
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import javax.persistence.EntityManager;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenAuthenticatedUser;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
@JsonTest
@SpringBootTest(classes = {
AssetMapperImpl.class,
AssetDTO.AssetJsonSerializer.class,
AssetDTO.AssetJsonDeserializer.class,
MembershipMapperImpl.class,
CustomerMapperImpl.class
})
@RunWith(SpringRunner.class)
public class AssetDTOUnitTest {
private static final Long SOME_CUSTOMER_ID = RandomUtils.nextLong(100, 199);
private static final Integer SOME_CUSTOMER_REFERENCE = 10001;
private static final String SOME_CUSTOMER_PREFIX = "abc";
private static final String SOME_CUSTOMER_NAME = "Some Customer Name";
private static final Customer SOME_CUSTOMER = new Customer().id(SOME_CUSTOMER_ID).reference(SOME_CUSTOMER_REFERENCE).prefix(SOME_CUSTOMER_PREFIX).name(SOME_CUSTOMER_NAME);
private static final Long SOME_MEMBERSHIP_ID = RandomUtils.nextLong(200, 299);
private static final LocalDate SOME_MEMBER_FROM_DATE = LocalDate.parse("2000-12-06") ;
private static final Membership SOME_MEMBERSHIP = new Membership().id(SOME_MEMBERSHIP_ID).customer(SOME_CUSTOMER).memberFromDate(SOME_MEMBER_FROM_DATE);
public static final String SOME_MEMBERSHIP_DISPLAY_LABEL = "Some Customer Name [10001:abc] 2000-12-06 - ...";
private static final Long SOME_ASSET_ID = RandomUtils.nextLong(300, 399);
private static final Asset SOME_ASSET = new Asset().id(SOME_ASSET_ID).membership(SOME_MEMBERSHIP);
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
@Autowired
private ObjectMapper objectMapper;
@Autowired
private AssetMapper assetMapper;
@MockBean
private AssetRepository assetRepository;
@MockBean
private AssetValidator assetValidator;
@MockBean
private CustomerRepository customerRepository;
@MockBean
private MembershipRepository membershipRepository;
@MockBean
private MembershipValidator membershipValidator;
@MockBean
private AssetService assetService;
@MockBean
private EntityManager em;
@Before
public void init() {
given(customerRepository.findById(SOME_CUSTOMER_ID)).willReturn(Optional.of(SOME_CUSTOMER));
given(membershipRepository.findById(SOME_MEMBERSHIP_ID)).willReturn(Optional.of(SOME_MEMBERSHIP));
given(assetRepository.findById(SOME_ASSET_ID)).willReturn((Optional.of(SOME_ASSET)));
}
@Test
public void shouldSerializePartiallyForFinancialCustomerContact() throws JsonProcessingException {
// given
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, SOME_CUSTOMER_ID, Role.FINANCIAL_CONTACT);
final AssetDTO given = createSomeAssetDTO(SOME_ASSET_ID);
// when
final String actual = objectMapper.writeValueAsString(given);
// then
given.setRemark(null);
assertEquals(createExpectedJSon(given), actual);
}
@Test
public void shouldSerializeCompletelyForSupporter() throws JsonProcessingException {
// given
givenAuthenticatedUser();
givenUserHavingRole(Role.SUPPORTER);
final AssetDTO given = createSomeAssetDTO(SOME_ASSET_ID);
// when
final String actual = objectMapper.writeValueAsString(given);
// then
assertEquals(createExpectedJSon(given), actual);
}
@Test
public void shouldNotDeserializeForContractualCustomerContact() {
// given
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, SOME_CUSTOMER_ID, Role.CONTRACTUAL_CONTACT);
final String json = new JSonBuilder()
.withFieldValue("id", SOME_ASSET_ID)
.withFieldValue("remark", "Updated Remark")
.toString();
// when
final Throwable actual = catchThrowable(() -> objectMapper.readValue(json, AssetDTO.class));
// then
assertThat(actual).isInstanceOfSatisfying(BadRequestAlertException.class, bre ->
assertThat(bre.getMessage()).isEqualTo("Update of field AssetDTO.remark prohibited for current user role CONTRACTUAL_CONTACT")
);
}
@Test
public void shouldDeserializeForAdminIfRemarkIsChanged() throws IOException {
// given
givenAuthenticatedUser();
givenUserHavingRole(Role.ADMIN);
final String json = new JSonBuilder()
.withFieldValue("id", SOME_ASSET_ID)
.withFieldValue("remark", "Updated Remark")
.toString();
// when
final AssetDTO actual = objectMapper.readValue(json, AssetDTO.class);
// then
final AssetDTO expected = new AssetDTO();
expected.setId(SOME_ASSET_ID);
expected.setMembershipId(SOME_MEMBERSHIP_ID);
expected.setRemark("Updated Remark");
expected.setMembershipDisplayLabel(SOME_MEMBERSHIP_DISPLAY_LABEL);
assertThat(actual).isEqualToIgnoringGivenFields(expected, "displayLabel");
}
// --- only test fixture below ---
private String createExpectedJSon(AssetDTO dto) {
return new JSonBuilder()
.withFieldValueIfPresent("id", dto.getId())
.withFieldValueIfPresent("documentDate", dto.getDocumentDate().toString())
.withFieldValueIfPresent("valueDate", dto.getValueDate().toString())
.withFieldValueIfPresent("action", dto.getAction().name())
.withFieldValueIfPresent("amount", dto.getAmount().doubleValue())
.withFieldValueIfPresent("remark", dto.getRemark())
.withFieldValueIfPresent("membershipId", dto.getMembershipId())
.withFieldValue("membershipDisplayLabel", dto.getMembershipDisplayLabel())
.toString();
}
private AssetDTO createSomeAssetDTO(final long id) {
final AssetDTO given = new AssetDTO();
given.setId(id);
given.setAction(AssetAction.PAYMENT);
given.setAmount(new BigDecimal("512.01"));
given.setDocumentDate(LocalDate.parse("2019-04-27"));
given.setValueDate(LocalDate.parse("2019-04-28"));
given.setMembershipId(SOME_MEMBERSHIP_ID);
given.setRemark("Some Remark");
given.setMembershipDisplayLabel("Display Label for Membership #" + SOME_MEMBERSHIP_ID);
return given;
}
}

View File

@ -7,6 +7,7 @@ import org.hostsharing.hsadminng.domain.enumeration.CustomerKind;
import org.hostsharing.hsadminng.domain.enumeration.VatRegion; import org.hostsharing.hsadminng.domain.enumeration.VatRegion;
import org.hostsharing.hsadminng.repository.CustomerRepository; import org.hostsharing.hsadminng.repository.CustomerRepository;
import org.hostsharing.hsadminng.service.CustomerService; import org.hostsharing.hsadminng.service.CustomerService;
import org.hostsharing.hsadminng.service.accessfilter.JSonBuilder;
import org.hostsharing.hsadminng.service.accessfilter.Role; import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.mapper.CustomerMapper; import org.hostsharing.hsadminng.service.mapper.CustomerMapper;
import org.hostsharing.hsadminng.service.mapper.CustomerMapperImpl; import org.hostsharing.hsadminng.service.mapper.CustomerMapperImpl;
@ -78,12 +79,12 @@ public class CustomerDTOUnitTest {
String actual = objectMapper.writeValueAsString(given); String actual = objectMapper.writeValueAsString(given);
// then // then
final String expectedJSon = "{" + final String expectedJSon = new JSonBuilder()
toJSonFieldDefinition("id", given.getId()) + "," + .withFieldValue("id", given.getId())
toJSonFieldDefinition("reference", given.getReference()) + "," + .withFieldValue("reference", given.getReference())
toJSonFieldDefinition("prefix", given.getPrefix()) + "," + .withFieldValue("prefix", given.getPrefix())
toJSonFieldDefinition("name", given.getName()) + .withFieldValue("name", given.getName())
"}"; .withFieldValue("displayLabel", given.getDisplayLabel()).toString();
assertEquals(expectedJSon, actual); assertEquals(expectedJSon, actual);
} }
@ -118,56 +119,30 @@ public class CustomerDTOUnitTest {
expected.setId(1234L); expected.setId(1234L);
expected.setContractualSalutation("Hallo Updated"); expected.setContractualSalutation("Hallo Updated");
expected.setBillingSalutation("Moin Updated"); expected.setBillingSalutation("Moin Updated");
assertThat(actual).isEqualToComparingFieldByField(expected); assertThat(actual).isEqualToIgnoringGivenFields(expected, "displayLabel");
} }
// --- only test fixture below --- // --- only test fixture below ---
private String createExpectedJSon(CustomerDTO dto) { private String createExpectedJSon(CustomerDTO dto) {
String json = // the fields in alphanumeric order: return new JSonBuilder()
toJSonFieldDefinitionIfPresent("id", dto.getId()) + .withFieldValueIfPresent("id", dto.getId())
toJSonFieldDefinitionIfPresent("reference", dto.getReference()) + .withFieldValueIfPresent("reference", dto.getReference())
toJSonFieldDefinitionIfPresent("prefix", dto.getPrefix()) + .withFieldValueIfPresent("prefix", dto.getPrefix())
toJSonFieldDefinitionIfPresent("name", dto.getName()) + .withFieldValueIfPresent("name", dto.getName())
toJSonFieldDefinitionIfPresent("kind", "LEGAL") + .withFieldValueIfPresent("kind", "LEGAL")
toJSonNullFieldDefinition("birthDate") + .toJSonNullFieldDefinition("birthDate")
toJSonNullFieldDefinition("birthPlace") + .toJSonNullFieldDefinition("birthPlace")
toJSonFieldDefinitionIfPresent("registrationCourt", "Registergericht") + .withFieldValueIfPresent("registrationCourt", "Registergericht")
toJSonFieldDefinitionIfPresent("registrationNumber", "Registernummer") + .withFieldValueIfPresent("registrationNumber", "Registernummer")
toJSonFieldDefinitionIfPresent("vatRegion", "DOMESTIC") + .withFieldValueIfPresent("vatRegion", "DOMESTIC")
toJSonFieldDefinitionIfPresent("vatNumber", "DE1234") + .withFieldValueIfPresent("vatNumber", "DE1234")
toJSonFieldDefinitionIfPresent("contractualSalutation", dto.getContractualSalutation()) + .withFieldValueIfPresent("contractualSalutation", dto.getContractualSalutation())
toJSonFieldDefinitionIfPresent("contractualAddress", dto.getContractualAddress()) + .withFieldValueIfPresent("contractualAddress", dto.getContractualAddress())
toJSonFieldDefinitionIfPresent("billingSalutation", dto.getBillingSalutation()) + .withFieldValueIfPresent("billingSalutation", dto.getBillingSalutation())
toJSonFieldDefinitionIfPresent("billingAddress", dto.getBillingAddress()) + .withFieldValueIfPresent("billingAddress", dto.getBillingAddress())
toJSonFieldDefinitionIfPresent("remark", dto.getRemark()); .withFieldValueIfPresent("remark", dto.getRemark())
return "{" + json.substring(0, json.length() - 1) + "}"; .withFieldValueIfPresent("displayLabel", dto.getDisplayLabel()).toString();
}
private String toJSonFieldDefinition(String name, String value) {
return inQuotes(name) + ":" + (value != null ? inQuotes(value) : "null");
}
private String toJSonFieldDefinition(String name, Number value) {
return inQuotes(name) + ":" + (value != null ? value : "null");
}
private String toJSonNullFieldDefinition(String name) {
return inQuotes(name) + ":null,";
}
private String toJSonFieldDefinitionIfPresent(String name, String value) {
return value != null ? inQuotes(name) + ":" + inQuotes(value) + "," : "";
}
private String toJSonFieldDefinitionIfPresent(String name, Number value) {
return value != null ? inQuotes(name) + ":" + value + "," : "";
}
private String inQuotes(Object value) {
return "\"" + value.toString() + "\"";
} }
private CustomerDTO createSomeCustomerDTO(final long id) { private CustomerDTO createSomeCustomerDTO(final long id) {
@ -186,6 +161,7 @@ public class CustomerDTOUnitTest {
given.setBillingAddress("Noch eine Adresse"); given.setBillingAddress("Noch eine Adresse");
given.setBillingSalutation("Moin"); given.setBillingSalutation("Moin");
given.setRemark("Eine Bemerkung"); given.setRemark("Eine Bemerkung");
given.setDisplayLabel("Display Label");
return given; return given;
} }
} }

View File

@ -154,7 +154,7 @@ public class ShareDTOUnitTest {
givenDTO.setAction(ShareAction.SUBSCRIPTION); givenDTO.setAction(ShareAction.SUBSCRIPTION);
givenDTO.setQuantity(3); givenDTO.setQuantity(3);
givenDTO.setDocumentDate(LocalDate.parse("2019-04-22")); givenDTO.setDocumentDate(LocalDate.parse("2019-04-22"));
givenDTO.setMembershipDisplayReference("2019-04-21"); // TODO: why is this not a LocalDate? givenDTO.setMembershipDisplayLabel("2019-04-21"); // TODO: why is this not a LocalDate?
givenDTO.setValueDate(LocalDate.parse("2019-04-30")); givenDTO.setValueDate(LocalDate.parse("2019-04-30"));
givenDTO.setRemark("Some Remark"); givenDTO.setRemark("Some Remark");
return givenDTO; return givenDTO;

View File

@ -7,6 +7,8 @@ import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
import org.hostsharing.hsadminng.repository.AssetRepository; import org.hostsharing.hsadminng.repository.AssetRepository;
import org.hostsharing.hsadminng.service.AssetQueryService; import org.hostsharing.hsadminng.service.AssetQueryService;
import org.hostsharing.hsadminng.service.AssetService; import org.hostsharing.hsadminng.service.AssetService;
import org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.dto.AssetDTO; import org.hostsharing.hsadminng.service.dto.AssetDTO;
import org.hostsharing.hsadminng.service.mapper.AssetMapper; import org.hostsharing.hsadminng.service.mapper.AssetMapper;
import org.hostsharing.hsadminng.web.rest.errors.ExceptionTranslator; import org.hostsharing.hsadminng.web.rest.errors.ExceptionTranslator;
@ -27,6 +29,7 @@ import org.springframework.validation.Validator;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.List; import java.util.List;
@ -54,8 +57,8 @@ public class AssetResourceIntTest {
private static final AssetAction DEFAULT_ACTION = AssetAction.PAYMENT; private static final AssetAction DEFAULT_ACTION = AssetAction.PAYMENT;
private static final AssetAction UPDATED_ACTION = AssetAction.HANDOVER; private static final AssetAction UPDATED_ACTION = AssetAction.HANDOVER;
private static final BigDecimal DEFAULT_AMOUNT = new BigDecimal(1); private static final BigDecimal DEFAULT_AMOUNT = new BigDecimal("1");
private static final BigDecimal UPDATED_AMOUNT = new BigDecimal(2); private static final BigDecimal UPDATED_AMOUNT = new BigDecimal("2");
private static final String DEFAULT_REMARK = "AAAAAAAAAA"; private static final String DEFAULT_REMARK = "AAAAAAAAAA";
private static final String UPDATED_REMARK = "BBBBBBBBBB"; private static final String UPDATED_REMARK = "BBBBBBBBBB";
@ -93,6 +96,9 @@ public class AssetResourceIntTest {
@Before @Before
public void setup() { public void setup() {
MockSecurityContext.givenAuthenticatedUser();
MockSecurityContext.givenUserHavingRole(Role.ADMIN);
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
final AssetResource assetResource = new AssetResource(assetService, assetQueryService); final AssetResource assetResource = new AssetResource(assetService, assetQueryService);
this.restAssetMockMvc = MockMvcBuilders.standaloneSetup(assetResource) this.restAssetMockMvc = MockMvcBuilders.standaloneSetup(assetResource)
@ -168,16 +174,16 @@ public class AssetResourceIntTest {
assertThat(testAsset.getDocumentDate()).isEqualTo(DEFAULT_DOCUMENT_DATE); assertThat(testAsset.getDocumentDate()).isEqualTo(DEFAULT_DOCUMENT_DATE);
assertThat(testAsset.getValueDate()).isEqualTo(DEFAULT_VALUE_DATE); assertThat(testAsset.getValueDate()).isEqualTo(DEFAULT_VALUE_DATE);
assertThat(testAsset.getAction()).isEqualTo(DEFAULT_ACTION); assertThat(testAsset.getAction()).isEqualTo(DEFAULT_ACTION);
assertThat(testAsset.getAmount()).isEqualTo(DEFAULT_AMOUNT); assertThat(testAsset.getAmount()).isEqualTo(DEFAULT_AMOUNT.setScale(2, RoundingMode.HALF_DOWN));
assertThat(testAsset.getRemark()).isEqualTo(DEFAULT_REMARK); assertThat(testAsset.getRemark()).isEqualTo(DEFAULT_REMARK);
} }
@Test @Test
@Transactional @Transactional
public void createAssetWithExistingId() throws Exception { public void createAssetWithIdForNonExistingEntity() throws Exception {
int databaseSizeBeforeCreate = assetRepository.findAll().size(); int databaseSizeBeforeCreate = assetRepository.findAll().size();
// Create the Asset with an existing ID // Create the Asset with an ID
asset.setId(1L); asset.setId(1L);
AssetDTO assetDTO = assetMapper.toDto(asset); AssetDTO assetDTO = assetMapper.toDto(asset);
@ -192,6 +198,27 @@ public class AssetResourceIntTest {
assertThat(assetList).hasSize(databaseSizeBeforeCreate); assertThat(assetList).hasSize(databaseSizeBeforeCreate);
} }
@Test
@Transactional
public void createAssetWithExistingExistingEntity() throws Exception {
// Initialize the database
assetRepository.saveAndFlush(asset);
int databaseSizeBeforeCreate = assetRepository.findAll().size();
// Create the Asset with the ID of an existing ID
AssetDTO assetDTO = assetMapper.toDto(asset);
// An entity with an existing ID cannot be created, so this API call must fail
restAssetMockMvc.perform(post("/api/assets")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(assetDTO)))
.andExpect(status().isBadRequest());
// Validate the Asset in the database
List<Asset> assetList = assetRepository.findAll();
assertThat(assetList).hasSize(databaseSizeBeforeCreate);
}
@Test @Test
@Transactional @Transactional
public void checkDocumentDateIsRequired() throws Exception { public void checkDocumentDateIsRequired() throws Exception {
@ -283,7 +310,7 @@ public class AssetResourceIntTest {
.andExpect(jsonPath("$.[*].valueDate").value(hasItem(DEFAULT_VALUE_DATE.toString()))) .andExpect(jsonPath("$.[*].valueDate").value(hasItem(DEFAULT_VALUE_DATE.toString())))
.andExpect(jsonPath("$.[*].action").value(hasItem(DEFAULT_ACTION.toString()))) .andExpect(jsonPath("$.[*].action").value(hasItem(DEFAULT_ACTION.toString())))
.andExpect(jsonPath("$.[*].amount").value(hasItem(DEFAULT_AMOUNT.intValue()))) .andExpect(jsonPath("$.[*].amount").value(hasItem(DEFAULT_AMOUNT.intValue())))
.andExpect(jsonPath("$.[*].remark").value(hasItem(DEFAULT_REMARK.toString()))); .andExpect(jsonPath("$.[*].remark").value(hasItem(DEFAULT_REMARK)));
} }
@Test @Test
@ -301,7 +328,7 @@ public class AssetResourceIntTest {
.andExpect(jsonPath("$.valueDate").value(DEFAULT_VALUE_DATE.toString())) .andExpect(jsonPath("$.valueDate").value(DEFAULT_VALUE_DATE.toString()))
.andExpect(jsonPath("$.action").value(DEFAULT_ACTION.toString())) .andExpect(jsonPath("$.action").value(DEFAULT_ACTION.toString()))
.andExpect(jsonPath("$.amount").value(DEFAULT_AMOUNT.intValue())) .andExpect(jsonPath("$.amount").value(DEFAULT_AMOUNT.intValue()))
.andExpect(jsonPath("$.remark").value(DEFAULT_REMARK.toString())); .andExpect(jsonPath("$.remark").value(DEFAULT_REMARK));
} }
@Test @Test

View File

@ -9,6 +9,7 @@ import org.hostsharing.hsadminng.domain.enumeration.VatRegion;
import org.hostsharing.hsadminng.repository.CustomerRepository; import org.hostsharing.hsadminng.repository.CustomerRepository;
import org.hostsharing.hsadminng.service.CustomerQueryService; import org.hostsharing.hsadminng.service.CustomerQueryService;
import org.hostsharing.hsadminng.service.CustomerService; import org.hostsharing.hsadminng.service.CustomerService;
import org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext;
import org.hostsharing.hsadminng.service.accessfilter.Role; import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.dto.CustomerDTO; import org.hostsharing.hsadminng.service.dto.CustomerDTO;
import org.hostsharing.hsadminng.service.mapper.CustomerMapper; import org.hostsharing.hsadminng.service.mapper.CustomerMapper;
@ -136,6 +137,9 @@ public class CustomerResourceIntTest {
@Before @Before
public void setup() { public void setup() {
MockSecurityContext.givenAuthenticatedUser();
MockSecurityContext.givenUserHavingRole(Role.ADMIN);
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
givenAuthenticatedUser(); givenAuthenticatedUser();
@ -261,7 +265,7 @@ public class CustomerResourceIntTest {
public void createCustomerWithNonExistingIdIsRejected() throws Exception { public void createCustomerWithNonExistingIdIsRejected() throws Exception {
int databaseSizeBeforeCreate = customerRepository.findAll().size(); int databaseSizeBeforeCreate = customerRepository.findAll().size();
// Create the Customer with an existing ID // Create the Customer with an ID for which no entity exists
customer.setId(1L); customer.setId(1L);
CustomerDTO customerDTO = customerMapper.toDto(customer); CustomerDTO customerDTO = customerMapper.toDto(customer);
@ -430,20 +434,20 @@ public class CustomerResourceIntTest {
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$.id").value(customer.getId().intValue())) .andExpect(jsonPath("$.id").value(customer.getId().intValue()))
.andExpect(jsonPath("$.reference").value(DEFAULT_REFERENCE)) .andExpect(jsonPath("$.reference").value(DEFAULT_REFERENCE))
.andExpect(jsonPath("$.prefix").value(DEFAULT_PREFIX.toString())) .andExpect(jsonPath("$.prefix").value(DEFAULT_PREFIX))
.andExpect(jsonPath("$.name").value(DEFAULT_NAME.toString())) .andExpect(jsonPath("$.name").value(DEFAULT_NAME))
.andExpect(jsonPath("$.kind").value(DEFAULT_KIND.toString())) .andExpect(jsonPath("$.kind").value(DEFAULT_KIND.toString()))
.andExpect(jsonPath("$.birthDate").value(DEFAULT_BIRTH_DATE.toString())) .andExpect(jsonPath("$.birthDate").value(DEFAULT_BIRTH_DATE.toString()))
.andExpect(jsonPath("$.birthPlace").value(DEFAULT_BIRTH_PLACE.toString())) .andExpect(jsonPath("$.birthPlace").value(DEFAULT_BIRTH_PLACE))
.andExpect(jsonPath("$.registrationCourt").value(DEFAULT_REGISTRATION_COURT.toString())) .andExpect(jsonPath("$.registrationCourt").value(DEFAULT_REGISTRATION_COURT))
.andExpect(jsonPath("$.registrationNumber").value(DEFAULT_REGISTRATION_NUMBER.toString())) .andExpect(jsonPath("$.registrationNumber").value(DEFAULT_REGISTRATION_NUMBER))
.andExpect(jsonPath("$.vatRegion").value(DEFAULT_VAT_REGION.toString())) .andExpect(jsonPath("$.vatRegion").value(DEFAULT_VAT_REGION.toString()))
.andExpect(jsonPath("$.vatNumber").value(DEFAULT_VAT_NUMBER.toString())) .andExpect(jsonPath("$.vatNumber").value(DEFAULT_VAT_NUMBER))
.andExpect(jsonPath("$.contractualSalutation").value(DEFAULT_CONTRACTUAL_SALUTATION.toString())) .andExpect(jsonPath("$.contractualSalutation").value(DEFAULT_CONTRACTUAL_SALUTATION))
.andExpect(jsonPath("$.contractualAddress").value(DEFAULT_CONTRACTUAL_ADDRESS.toString())) .andExpect(jsonPath("$.contractualAddress").value(DEFAULT_CONTRACTUAL_ADDRESS))
.andExpect(jsonPath("$.billingSalutation").value(DEFAULT_BILLING_SALUTATION.toString())) .andExpect(jsonPath("$.billingSalutation").value(DEFAULT_BILLING_SALUTATION))
.andExpect(jsonPath("$.billingAddress").value(DEFAULT_BILLING_ADDRESS.toString())) .andExpect(jsonPath("$.billingAddress").value(DEFAULT_BILLING_ADDRESS))
.andExpect(jsonPath("$.remark").value(DEFAULT_REMARK.toString())); .andExpect(jsonPath("$.remark").value(DEFAULT_REMARK));
} }
@Test @Test
@ -1265,11 +1269,11 @@ public class CustomerResourceIntTest {
// Delete the customer // Delete the customer
restCustomerMockMvc.perform(delete("/api/customers/{id}", customer.getId()) restCustomerMockMvc.perform(delete("/api/customers/{id}", customer.getId())
.accept(TestUtil.APPLICATION_JSON_UTF8)) .accept(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(status().isOk()); .andExpect(status().isBadRequest());
// Validate the database is empty // Validate the database is unchanged
List<Customer> customerList = customerRepository.findAll(); List<Customer> customerList = customerRepository.findAll();
assertThat(customerList).hasSize(databaseSizeBeforeDelete - 1); assertThat(customerList).hasSize(databaseSizeBeforeDelete);
} }
@Test @Test

View File

@ -8,6 +8,8 @@ import org.hostsharing.hsadminng.domain.Share;
import org.hostsharing.hsadminng.repository.MembershipRepository; import org.hostsharing.hsadminng.repository.MembershipRepository;
import org.hostsharing.hsadminng.service.MembershipQueryService; import org.hostsharing.hsadminng.service.MembershipQueryService;
import org.hostsharing.hsadminng.service.MembershipService; import org.hostsharing.hsadminng.service.MembershipService;
import org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.dto.MembershipDTO; import org.hostsharing.hsadminng.service.dto.MembershipDTO;
import org.hostsharing.hsadminng.service.mapper.MembershipMapper; import org.hostsharing.hsadminng.service.mapper.MembershipMapper;
import org.hostsharing.hsadminng.web.rest.errors.ExceptionTranslator; import org.hostsharing.hsadminng.web.rest.errors.ExceptionTranslator;
@ -97,6 +99,9 @@ public class MembershipResourceIntTest {
@Before @Before
public void setup() { public void setup() {
MockSecurityContext.givenAuthenticatedUser();
MockSecurityContext.givenUserHavingRole(Role.ADMIN);
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
final MembershipResource membershipResource = new MembershipResource(membershipService, membershipQueryService); final MembershipResource membershipResource = new MembershipResource(membershipService, membershipQueryService);
this.restMembershipMockMvc = MockMvcBuilders.standaloneSetup(membershipResource) this.restMembershipMockMvc = MockMvcBuilders.standaloneSetup(membershipResource)
@ -177,10 +182,32 @@ public class MembershipResourceIntTest {
@Test @Test
@Transactional @Transactional
public void createMembershipWithExistingId() throws Exception { public void createCustomerWithExistingIdIsRejected() throws Exception {
// Initialize the database
final long existingCustomerId = membershipRepository.saveAndFlush(membership).getId();
int databaseSizeBeforeCreate = membershipRepository.findAll().size(); int databaseSizeBeforeCreate = membershipRepository.findAll().size();
// Create the Membership with an existing ID // Create the Customer with an existing ID
membership.setId(existingCustomerId);
MembershipDTO membershipDTO = membershipMapper.toDto(membership);
// An entity with an existing ID cannot be created, so this API call must fail
restMembershipMockMvc.perform(post("/api/memberships")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(membershipDTO)))
.andExpect(status().isBadRequest());
// Validate the Customer in the database
List<Membership> membershipList = membershipRepository.findAll();
assertThat(membershipList).hasSize(databaseSizeBeforeCreate);
}
@Test
@Transactional
public void createCustomerWithNonExistingIdIsRejected() throws Exception {
int databaseSizeBeforeCreate = membershipRepository.findAll().size();
// Create the Membership with an ID for which no entity exists
membership.setId(1L); membership.setId(1L);
MembershipDTO membershipDTO = membershipMapper.toDto(membership); MembershipDTO membershipDTO = membershipMapper.toDto(membership);
@ -248,7 +275,7 @@ public class MembershipResourceIntTest {
.andExpect(jsonPath("$.[*].cancellationDocumentDate").value(hasItem(DEFAULT_CANCELLATION_DOCUMENT_DATE.toString()))) .andExpect(jsonPath("$.[*].cancellationDocumentDate").value(hasItem(DEFAULT_CANCELLATION_DOCUMENT_DATE.toString())))
.andExpect(jsonPath("$.[*].memberFromDate").value(hasItem(DEFAULT_MEMBER_FROM_DATE.toString()))) .andExpect(jsonPath("$.[*].memberFromDate").value(hasItem(DEFAULT_MEMBER_FROM_DATE.toString())))
.andExpect(jsonPath("$.[*].memberUntilDate").value(hasItem(DEFAULT_MEMBER_UNTIL_DATE.toString()))) .andExpect(jsonPath("$.[*].memberUntilDate").value(hasItem(DEFAULT_MEMBER_UNTIL_DATE.toString())))
.andExpect(jsonPath("$.[*].remark").value(hasItem(DEFAULT_REMARK.toString()))); .andExpect(jsonPath("$.[*].remark").value(hasItem(DEFAULT_REMARK)));
} }
@Test @Test
@ -266,7 +293,7 @@ public class MembershipResourceIntTest {
.andExpect(jsonPath("$.cancellationDocumentDate").value(DEFAULT_CANCELLATION_DOCUMENT_DATE.toString())) .andExpect(jsonPath("$.cancellationDocumentDate").value(DEFAULT_CANCELLATION_DOCUMENT_DATE.toString()))
.andExpect(jsonPath("$.memberFromDate").value(DEFAULT_MEMBER_FROM_DATE.toString())) .andExpect(jsonPath("$.memberFromDate").value(DEFAULT_MEMBER_FROM_DATE.toString()))
.andExpect(jsonPath("$.memberUntilDate").value(DEFAULT_MEMBER_UNTIL_DATE.toString())) .andExpect(jsonPath("$.memberUntilDate").value(DEFAULT_MEMBER_UNTIL_DATE.toString()))
.andExpect(jsonPath("$.remark").value(DEFAULT_REMARK.toString())); .andExpect(jsonPath("$.remark").value(DEFAULT_REMARK));
} }
@Test @Test
@ -682,9 +709,7 @@ public class MembershipResourceIntTest {
// Disconnect from session so that the updates on updatedMembership are not directly saved in db // Disconnect from session so that the updates on updatedMembership are not directly saved in db
em.detach(updatedMembership); em.detach(updatedMembership);
updatedMembership updatedMembership
.admissionDocumentDate(UPDATED_ADMISSION_DOCUMENT_DATE)
.cancellationDocumentDate(UPDATED_CANCELLATION_DOCUMENT_DATE) .cancellationDocumentDate(UPDATED_CANCELLATION_DOCUMENT_DATE)
.memberFromDate(UPDATED_MEMBER_FROM_DATE)
.memberUntilDate(UPDATED_MEMBER_UNTIL_DATE) .memberUntilDate(UPDATED_MEMBER_UNTIL_DATE)
.remark(UPDATED_REMARK); .remark(UPDATED_REMARK);
MembershipDTO membershipDTO = membershipMapper.toDto(updatedMembership); MembershipDTO membershipDTO = membershipMapper.toDto(updatedMembership);
@ -698,9 +723,9 @@ public class MembershipResourceIntTest {
List<Membership> membershipList = membershipRepository.findAll(); List<Membership> membershipList = membershipRepository.findAll();
assertThat(membershipList).hasSize(databaseSizeBeforeUpdate); assertThat(membershipList).hasSize(databaseSizeBeforeUpdate);
Membership testMembership = membershipList.get(membershipList.size() - 1); Membership testMembership = membershipList.get(membershipList.size() - 1);
assertThat(testMembership.getAdmissionDocumentDate()).isEqualTo(UPDATED_ADMISSION_DOCUMENT_DATE); assertThat(testMembership.getAdmissionDocumentDate()).isEqualTo(DEFAULT_ADMISSION_DOCUMENT_DATE);
assertThat(testMembership.getCancellationDocumentDate()).isEqualTo(UPDATED_CANCELLATION_DOCUMENT_DATE); assertThat(testMembership.getCancellationDocumentDate()).isEqualTo(UPDATED_CANCELLATION_DOCUMENT_DATE);
assertThat(testMembership.getMemberFromDate()).isEqualTo(UPDATED_MEMBER_FROM_DATE); assertThat(testMembership.getMemberFromDate()).isEqualTo(DEFAULT_MEMBER_FROM_DATE);
assertThat(testMembership.getMemberUntilDate()).isEqualTo(UPDATED_MEMBER_UNTIL_DATE); assertThat(testMembership.getMemberUntilDate()).isEqualTo(UPDATED_MEMBER_UNTIL_DATE);
assertThat(testMembership.getRemark()).isEqualTo(UPDATED_REMARK); assertThat(testMembership.getRemark()).isEqualTo(UPDATED_REMARK);
} }

View File

@ -7,6 +7,8 @@ import org.hostsharing.hsadminng.domain.enumeration.ShareAction;
import org.hostsharing.hsadminng.repository.ShareRepository; import org.hostsharing.hsadminng.repository.ShareRepository;
import org.hostsharing.hsadminng.service.ShareQueryService; import org.hostsharing.hsadminng.service.ShareQueryService;
import org.hostsharing.hsadminng.service.ShareService; import org.hostsharing.hsadminng.service.ShareService;
import org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.dto.ShareDTO; import org.hostsharing.hsadminng.service.dto.ShareDTO;
import org.hostsharing.hsadminng.service.mapper.ShareMapper; import org.hostsharing.hsadminng.service.mapper.ShareMapper;
import org.hostsharing.hsadminng.web.rest.errors.ExceptionTranslator; import org.hostsharing.hsadminng.web.rest.errors.ExceptionTranslator;
@ -92,6 +94,9 @@ public class ShareResourceIntTest {
@Before @Before
public void setup() { public void setup() {
MockSecurityContext.givenAuthenticatedUser();
MockSecurityContext.givenUserHavingRole(Role.ADMIN);
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
final ShareResource shareResource = new ShareResource(shareService, shareQueryService); final ShareResource shareResource = new ShareResource(shareService, shareQueryService);
this.restShareMockMvc = MockMvcBuilders.standaloneSetup(shareResource) this.restShareMockMvc = MockMvcBuilders.standaloneSetup(shareResource)