diff --git a/.jhipster/Transaction.json b/.jhipster/Transaction.json new file mode 100644 index 0000000..145a8cd --- /dev/null +++ b/.jhipster/Transaction.json @@ -0,0 +1,35 @@ +{ + "annotations": { + "changelogDate": "20241113134007" + }, + "fields": [ + { + "fieldName": "type", + "fieldType": "TransactionType", + "fieldValues": "PURCHASE,MATCH,FIELDPAYMENT,INTERNALTRANSFER" + }, + { + "fieldName": "date", + "fieldType": "LocalDate" + }, + { + "fieldName": "comment", + "fieldType": "String" + } + ], + "name": "Transaction", + "pagination": "no", + "readOnly": false, + "relationships": [ + { + "otherEntityField": "name", + "otherEntityName": "event", + "otherEntityRelationshipName": "transaction", + "relationshipName": "event", + "relationshipSide": "left", + "relationshipType": "many-to-one" + } + ], + "searchEngine": "no", + "service": "no" +} diff --git a/.jhipster/TransactionItem.json b/.jhipster/TransactionItem.json new file mode 100644 index 0000000..3627e1d --- /dev/null +++ b/.jhipster/TransactionItem.json @@ -0,0 +1,42 @@ +{ + "annotations": { + "changelogDate": "20241113135446" + }, + "fields": [ + { + "fieldName": "amount", + "fieldType": "BigDecimal" + }, + { + "fieldName": "date", + "fieldType": "LocalDate" + }, + { + "fieldName": "comment", + "fieldType": "String" + } + ], + "name": "TransactionItem", + "pagination": "no", + "readOnly": false, + "relationships": [ + { + "otherEntityField": "name", + "otherEntityName": "userAccount", + "otherEntityRelationshipName": "transactionItem", + "relationshipName": "userAccount", + "relationshipSide": "left", + "relationshipType": "many-to-many" + }, + { + "otherEntityField": "id", + "otherEntityName": "transaction", + "otherEntityRelationshipName": "transactionItem", + "relationshipName": "transaction", + "relationshipSide": "left", + "relationshipType": "one-to-many" + } + ], + "searchEngine": "no", + "service": "no" +} diff --git a/.jhipster/UserAccount.json b/.jhipster/UserAccount.json new file mode 100644 index 0000000..c3d89c7 --- /dev/null +++ b/.jhipster/UserAccount.json @@ -0,0 +1,26 @@ +{ + "annotations": { + "changelogDate": "20241113135042" + }, + "fields": [ + { + "fieldName": "name", + "fieldType": "String" + } + ], + "name": "UserAccount", + "pagination": "no", + "readOnly": false, + "relationships": [ + { + "otherEntityField": "login", + "otherEntityName": "user", + "otherEntityRelationshipName": "userAccount", + "relationshipName": "user", + "relationshipSide": "left", + "relationshipType": "many-to-many" + } + ], + "searchEngine": "no", + "service": "no" +} diff --git a/.yo-rc.json b/.yo-rc.json index d83b33c..26d7f45 100644 --- a/.yo-rc.json +++ b/.yo-rc.json @@ -15,10 +15,10 @@ "enableHibernateCache": null, "enableSwaggerCodegen": false, "enableTranslation": false, - "entities": ["Charge", "Event", "Registration"], + "entities": ["Charge", "Event", "Registration", "Transaction", "UserAccount", "TransactionItem"], "feignClient": null, "jhipsterVersion": "8.7.2", - "lastLiquibaseTimestamp": 1730797803000, + "lastLiquibaseTimestamp": 1731506086000, "messageBroker": false, "microfrontend": null, "microfrontends": [], diff --git a/src/main/java/com/sasiedzi/event/domain/Charge.java b/src/main/java/com/sasiedzi/event/domain/Charge.java index 74cc1de..5016913 100644 --- a/src/main/java/com/sasiedzi/event/domain/Charge.java +++ b/src/main/java/com/sasiedzi/event/domain/Charge.java @@ -38,7 +38,7 @@ public class Charge implements Serializable { private BigDecimal amount; @ManyToOne(fetch = FetchType.LAZY) - @JsonIgnoreProperties(value = { "registrations" }, allowSetters = true) + @JsonIgnoreProperties(value = { "registrations", "transactions" }, allowSetters = true) private Event event; @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/java/com/sasiedzi/event/domain/Event.java b/src/main/java/com/sasiedzi/event/domain/Event.java index f166a7b..d387af2 100644 --- a/src/main/java/com/sasiedzi/event/domain/Event.java +++ b/src/main/java/com/sasiedzi/event/domain/Event.java @@ -47,6 +47,10 @@ public class Event implements Serializable { @JsonIgnoreProperties(value = { "event" }, allowSetters = true) private Set registrations = new HashSet<>(); + @OneToMany(fetch = FetchType.LAZY, mappedBy = "event") + @JsonIgnoreProperties(value = { "event", "transactionItem" }, allowSetters = true) + private Set transactions = new HashSet<>(); + // jhipster-needle-entity-add-field - JHipster will add fields here public Long getId() { @@ -158,6 +162,37 @@ public class Event implements Serializable { return this; } + public Set getTransactions() { + return this.transactions; + } + + public void setTransactions(Set transactions) { + if (this.transactions != null) { + this.transactions.forEach(i -> i.setEvent(null)); + } + if (transactions != null) { + transactions.forEach(i -> i.setEvent(this)); + } + this.transactions = transactions; + } + + public Event transactions(Set transactions) { + this.setTransactions(transactions); + return this; + } + + public Event addTransaction(Transaction transaction) { + this.transactions.add(transaction); + transaction.setEvent(this); + return this; + } + + public Event removeTransaction(Transaction transaction) { + this.transactions.remove(transaction); + transaction.setEvent(null); + return this; + } + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here @Override diff --git a/src/main/java/com/sasiedzi/event/domain/Registration.java b/src/main/java/com/sasiedzi/event/domain/Registration.java index 03b228c..9be5b96 100644 --- a/src/main/java/com/sasiedzi/event/domain/Registration.java +++ b/src/main/java/com/sasiedzi/event/domain/Registration.java @@ -41,7 +41,7 @@ public class Registration implements Serializable { private User user; @ManyToOne(fetch = FetchType.LAZY) - @JsonIgnoreProperties(value = { "registrations" }, allowSetters = true) + @JsonIgnoreProperties(value = { "registrations", "transactions" }, allowSetters = true) private Event event; // jhipster-needle-entity-add-field - JHipster will add fields here diff --git a/src/main/java/com/sasiedzi/event/domain/Transaction.java b/src/main/java/com/sasiedzi/event/domain/Transaction.java new file mode 100644 index 0000000..fb3de48 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/domain/Transaction.java @@ -0,0 +1,152 @@ +package com.sasiedzi.event.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.sasiedzi.event.domain.enumeration.TransactionType; +import jakarta.persistence.*; +import java.io.Serializable; +import java.time.LocalDate; + +/** + * A Transaction. + */ +@Entity +@Table(name = "transaction") +@SuppressWarnings("common-java:DuplicatedBlocks") +public class Transaction implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") + @SequenceGenerator(name = "sequenceGenerator") + @Column(name = "id") + private Long id; + + @Enumerated(EnumType.STRING) + @Column(name = "type") + private TransactionType type; + + @Column(name = "date") + private LocalDate date; + + @Column(name = "comment") + private String comment; + + @ManyToOne(fetch = FetchType.LAZY) + @JsonIgnoreProperties(value = { "registrations", "transactions" }, allowSetters = true) + private Event event; + + @ManyToOne(fetch = FetchType.LAZY) + @JsonIgnoreProperties(value = { "userAccounts", "transactions" }, allowSetters = true) + private TransactionItem transactionItem; + + // jhipster-needle-entity-add-field - JHipster will add fields here + + public Long getId() { + return this.id; + } + + public Transaction id(Long id) { + this.setId(id); + return this; + } + + public void setId(Long id) { + this.id = id; + } + + public TransactionType getType() { + return this.type; + } + + public Transaction type(TransactionType type) { + this.setType(type); + return this; + } + + public void setType(TransactionType type) { + this.type = type; + } + + public LocalDate getDate() { + return this.date; + } + + public Transaction date(LocalDate date) { + this.setDate(date); + return this; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public String getComment() { + return this.comment; + } + + public Transaction comment(String comment) { + this.setComment(comment); + return this; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public Event getEvent() { + return this.event; + } + + public void setEvent(Event event) { + this.event = event; + } + + public Transaction event(Event event) { + this.setEvent(event); + return this; + } + + public TransactionItem getTransactionItem() { + return this.transactionItem; + } + + public void setTransactionItem(TransactionItem transactionItem) { + this.transactionItem = transactionItem; + } + + public Transaction transactionItem(TransactionItem transactionItem) { + this.setTransactionItem(transactionItem); + return this; + } + + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Transaction)) { + return false; + } + return getId() != null && getId().equals(((Transaction) o).getId()); + } + + @Override + public int hashCode() { + // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ + return getClass().hashCode(); + } + + // prettier-ignore + @Override + public String toString() { + return "Transaction{" + + "id=" + getId() + + ", type='" + getType() + "'" + + ", date='" + getDate() + "'" + + ", comment='" + getComment() + "'" + + "}"; + } +} diff --git a/src/main/java/com/sasiedzi/event/domain/TransactionItem.java b/src/main/java/com/sasiedzi/event/domain/TransactionItem.java new file mode 100644 index 0000000..f1448e4 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/domain/TransactionItem.java @@ -0,0 +1,186 @@ +package com.sasiedzi.event.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; + +/** + * A TransactionItem. + */ +@Entity +@Table(name = "transaction_item") +@SuppressWarnings("common-java:DuplicatedBlocks") +public class TransactionItem implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") + @SequenceGenerator(name = "sequenceGenerator") + @Column(name = "id") + private Long id; + + @Column(name = "amount", precision = 21, scale = 2) + private BigDecimal amount; + + @Column(name = "date") + private LocalDate date; + + @Column(name = "comment") + private String comment; + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable( + name = "rel_transaction_item__user_account", + joinColumns = @JoinColumn(name = "transaction_item_id"), + inverseJoinColumns = @JoinColumn(name = "user_account_id") + ) + @JsonIgnoreProperties(value = { "users", "transactionItems" }, allowSetters = true) + private Set userAccounts = new HashSet<>(); + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "transactionItem") + @JsonIgnoreProperties(value = { "event", "transactionItem" }, allowSetters = true) + private Set transactions = new HashSet<>(); + + // jhipster-needle-entity-add-field - JHipster will add fields here + + public Long getId() { + return this.id; + } + + public TransactionItem id(Long id) { + this.setId(id); + return this; + } + + public void setId(Long id) { + this.id = id; + } + + public BigDecimal getAmount() { + return this.amount; + } + + public TransactionItem amount(BigDecimal amount) { + this.setAmount(amount); + return this; + } + + public void setAmount(BigDecimal amount) { + this.amount = amount; + } + + public LocalDate getDate() { + return this.date; + } + + public TransactionItem date(LocalDate date) { + this.setDate(date); + return this; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public String getComment() { + return this.comment; + } + + public TransactionItem comment(String comment) { + this.setComment(comment); + return this; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public Set getUserAccounts() { + return this.userAccounts; + } + + public void setUserAccounts(Set userAccounts) { + this.userAccounts = userAccounts; + } + + public TransactionItem userAccounts(Set userAccounts) { + this.setUserAccounts(userAccounts); + return this; + } + + public TransactionItem addUserAccount(UserAccount userAccount) { + this.userAccounts.add(userAccount); + return this; + } + + public TransactionItem removeUserAccount(UserAccount userAccount) { + this.userAccounts.remove(userAccount); + return this; + } + + public Set getTransactions() { + return this.transactions; + } + + public void setTransactions(Set transactions) { + if (this.transactions != null) { + this.transactions.forEach(i -> i.setTransactionItem(null)); + } + if (transactions != null) { + transactions.forEach(i -> i.setTransactionItem(this)); + } + this.transactions = transactions; + } + + public TransactionItem transactions(Set transactions) { + this.setTransactions(transactions); + return this; + } + + public TransactionItem addTransaction(Transaction transaction) { + this.transactions.add(transaction); + transaction.setTransactionItem(this); + return this; + } + + public TransactionItem removeTransaction(Transaction transaction) { + this.transactions.remove(transaction); + transaction.setTransactionItem(null); + return this; + } + + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TransactionItem)) { + return false; + } + return getId() != null && getId().equals(((TransactionItem) o).getId()); + } + + @Override + public int hashCode() { + // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ + return getClass().hashCode(); + } + + // prettier-ignore + @Override + public String toString() { + return "TransactionItem{" + + "id=" + getId() + + ", amount=" + getAmount() + + ", date='" + getDate() + "'" + + ", comment='" + getComment() + "'" + + "}"; + } +} diff --git a/src/main/java/com/sasiedzi/event/domain/UserAccount.java b/src/main/java/com/sasiedzi/event/domain/UserAccount.java new file mode 100644 index 0000000..384d2f9 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/domain/UserAccount.java @@ -0,0 +1,149 @@ +package com.sasiedzi.event.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +/** + * A UserAccount. + */ +@Entity +@Table(name = "user_account") +@SuppressWarnings("common-java:DuplicatedBlocks") +public class UserAccount implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") + @SequenceGenerator(name = "sequenceGenerator") + @Column(name = "id") + private Long id; + + @Column(name = "name") + private String name; + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable( + name = "rel_user_account__user", + joinColumns = @JoinColumn(name = "user_account_id"), + inverseJoinColumns = @JoinColumn(name = "user_id") + ) + private Set users = new HashSet<>(); + + @ManyToMany(fetch = FetchType.LAZY, mappedBy = "userAccounts") + @JsonIgnoreProperties(value = { "userAccounts", "transactions" }, allowSetters = true) + private Set transactionItems = new HashSet<>(); + + // jhipster-needle-entity-add-field - JHipster will add fields here + + public Long getId() { + return this.id; + } + + public UserAccount id(Long id) { + this.setId(id); + return this; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public UserAccount name(String name) { + this.setName(name); + return this; + } + + public void setName(String name) { + this.name = name; + } + + public Set getUsers() { + return this.users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public UserAccount users(Set users) { + this.setUsers(users); + return this; + } + + public UserAccount addUser(User user) { + this.users.add(user); + return this; + } + + public UserAccount removeUser(User user) { + this.users.remove(user); + return this; + } + + public Set getTransactionItems() { + return this.transactionItems; + } + + public void setTransactionItems(Set transactionItems) { + if (this.transactionItems != null) { + this.transactionItems.forEach(i -> i.removeUserAccount(this)); + } + if (transactionItems != null) { + transactionItems.forEach(i -> i.addUserAccount(this)); + } + this.transactionItems = transactionItems; + } + + public UserAccount transactionItems(Set transactionItems) { + this.setTransactionItems(transactionItems); + return this; + } + + public UserAccount addTransactionItem(TransactionItem transactionItem) { + this.transactionItems.add(transactionItem); + transactionItem.getUserAccounts().add(this); + return this; + } + + public UserAccount removeTransactionItem(TransactionItem transactionItem) { + this.transactionItems.remove(transactionItem); + transactionItem.getUserAccounts().remove(this); + return this; + } + + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof UserAccount)) { + return false; + } + return getId() != null && getId().equals(((UserAccount) o).getId()); + } + + @Override + public int hashCode() { + // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ + return getClass().hashCode(); + } + + // prettier-ignore + @Override + public String toString() { + return "UserAccount{" + + "id=" + getId() + + ", name='" + getName() + "'" + + "}"; + } +} diff --git a/src/main/java/com/sasiedzi/event/domain/enumeration/TransactionType.java b/src/main/java/com/sasiedzi/event/domain/enumeration/TransactionType.java new file mode 100644 index 0000000..ee61eb5 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/domain/enumeration/TransactionType.java @@ -0,0 +1,11 @@ +package com.sasiedzi.event.domain.enumeration; + +/** + * The TransactionType enumeration. + */ +public enum TransactionType { + PURCHASE, + MATCH, + FIELDPAYMENT, + INTERNALTRANSFER, +} diff --git a/src/main/java/com/sasiedzi/event/repository/TransactionItemRepository.java b/src/main/java/com/sasiedzi/event/repository/TransactionItemRepository.java new file mode 100644 index 0000000..9a3ab7c --- /dev/null +++ b/src/main/java/com/sasiedzi/event/repository/TransactionItemRepository.java @@ -0,0 +1,30 @@ +package com.sasiedzi.event.repository; + +import com.sasiedzi.event.domain.TransactionItem; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.*; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the TransactionItem entity. + * + * When extending this class, extend TransactionItemRepositoryWithBagRelationships too. + * For more information refer to https://github.com/jhipster/generator-jhipster/issues/17990. + */ +@Repository +public interface TransactionItemRepository extends TransactionItemRepositoryWithBagRelationships, JpaRepository { + default Optional findOneWithEagerRelationships(Long id) { + return this.fetchBagRelationships(this.findById(id)); + } + + default List findAllWithEagerRelationships() { + return this.fetchBagRelationships(this.findAll()); + } + + default Page findAllWithEagerRelationships(Pageable pageable) { + return this.fetchBagRelationships(this.findAll(pageable)); + } +} diff --git a/src/main/java/com/sasiedzi/event/repository/TransactionItemRepositoryWithBagRelationships.java b/src/main/java/com/sasiedzi/event/repository/TransactionItemRepositoryWithBagRelationships.java new file mode 100644 index 0000000..4fbf0d7 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/repository/TransactionItemRepositoryWithBagRelationships.java @@ -0,0 +1,14 @@ +package com.sasiedzi.event.repository; + +import com.sasiedzi.event.domain.TransactionItem; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Page; + +public interface TransactionItemRepositoryWithBagRelationships { + Optional fetchBagRelationships(Optional transactionItem); + + List fetchBagRelationships(List transactionItems); + + Page fetchBagRelationships(Page transactionItems); +} diff --git a/src/main/java/com/sasiedzi/event/repository/TransactionItemRepositoryWithBagRelationshipsImpl.java b/src/main/java/com/sasiedzi/event/repository/TransactionItemRepositoryWithBagRelationshipsImpl.java new file mode 100644 index 0000000..feeebed --- /dev/null +++ b/src/main/java/com/sasiedzi/event/repository/TransactionItemRepositoryWithBagRelationshipsImpl.java @@ -0,0 +1,67 @@ +package com.sasiedzi.event.repository; + +import com.sasiedzi.event.domain.TransactionItem; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.stream.IntStream; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; + +/** + * Utility repository to load bag relationships based on https://vladmihalcea.com/hibernate-multiplebagfetchexception/ + */ +public class TransactionItemRepositoryWithBagRelationshipsImpl implements TransactionItemRepositoryWithBagRelationships { + + private static final String ID_PARAMETER = "id"; + private static final String TRANSACTIONITEMS_PARAMETER = "transactionItems"; + + @PersistenceContext + private EntityManager entityManager; + + @Override + public Optional fetchBagRelationships(Optional transactionItem) { + return transactionItem.map(this::fetchUserAccounts); + } + + @Override + public Page fetchBagRelationships(Page transactionItems) { + return new PageImpl<>( + fetchBagRelationships(transactionItems.getContent()), + transactionItems.getPageable(), + transactionItems.getTotalElements() + ); + } + + @Override + public List fetchBagRelationships(List transactionItems) { + return Optional.of(transactionItems).map(this::fetchUserAccounts).orElse(Collections.emptyList()); + } + + TransactionItem fetchUserAccounts(TransactionItem result) { + return entityManager + .createQuery( + "select transactionItem from TransactionItem transactionItem left join fetch transactionItem.userAccounts where transactionItem.id = :id", + TransactionItem.class + ) + .setParameter(ID_PARAMETER, result.getId()) + .getSingleResult(); + } + + List fetchUserAccounts(List transactionItems) { + HashMap order = new HashMap<>(); + IntStream.range(0, transactionItems.size()).forEach(index -> order.put(transactionItems.get(index).getId(), index)); + List result = entityManager + .createQuery( + "select transactionItem from TransactionItem transactionItem left join fetch transactionItem.userAccounts where transactionItem in :transactionItems", + TransactionItem.class + ) + .setParameter(TRANSACTIONITEMS_PARAMETER, transactionItems) + .getResultList(); + Collections.sort(result, (o1, o2) -> Integer.compare(order.get(o1.getId()), order.get(o2.getId()))); + return result; + } +} diff --git a/src/main/java/com/sasiedzi/event/repository/TransactionRepository.java b/src/main/java/com/sasiedzi/event/repository/TransactionRepository.java new file mode 100644 index 0000000..a0d9d5f --- /dev/null +++ b/src/main/java/com/sasiedzi/event/repository/TransactionRepository.java @@ -0,0 +1,40 @@ +package com.sasiedzi.event.repository; + +import com.sasiedzi.event.domain.Transaction; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.*; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the Transaction entity. + */ +@Repository +public interface TransactionRepository extends JpaRepository { + default Optional findOneWithEagerRelationships(Long id) { + return this.findOneWithToOneRelationships(id); + } + + default List findAllWithEagerRelationships() { + return this.findAllWithToOneRelationships(); + } + + default Page findAllWithEagerRelationships(Pageable pageable) { + return this.findAllWithToOneRelationships(pageable); + } + + @Query( + value = "select transaction from Transaction transaction left join fetch transaction.event", + countQuery = "select count(transaction) from Transaction transaction" + ) + Page findAllWithToOneRelationships(Pageable pageable); + + @Query("select transaction from Transaction transaction left join fetch transaction.event") + List findAllWithToOneRelationships(); + + @Query("select transaction from Transaction transaction left join fetch transaction.event where transaction.id =:id") + Optional findOneWithToOneRelationships(@Param("id") Long id); +} diff --git a/src/main/java/com/sasiedzi/event/repository/UserAccountRepository.java b/src/main/java/com/sasiedzi/event/repository/UserAccountRepository.java new file mode 100644 index 0000000..14114b1 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/repository/UserAccountRepository.java @@ -0,0 +1,30 @@ +package com.sasiedzi.event.repository; + +import com.sasiedzi.event.domain.UserAccount; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.*; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the UserAccount entity. + * + * When extending this class, extend UserAccountRepositoryWithBagRelationships too. + * For more information refer to https://github.com/jhipster/generator-jhipster/issues/17990. + */ +@Repository +public interface UserAccountRepository extends UserAccountRepositoryWithBagRelationships, JpaRepository { + default Optional findOneWithEagerRelationships(Long id) { + return this.fetchBagRelationships(this.findById(id)); + } + + default List findAllWithEagerRelationships() { + return this.fetchBagRelationships(this.findAll()); + } + + default Page findAllWithEagerRelationships(Pageable pageable) { + return this.fetchBagRelationships(this.findAll(pageable)); + } +} diff --git a/src/main/java/com/sasiedzi/event/repository/UserAccountRepositoryWithBagRelationships.java b/src/main/java/com/sasiedzi/event/repository/UserAccountRepositoryWithBagRelationships.java new file mode 100644 index 0000000..9c0c61b --- /dev/null +++ b/src/main/java/com/sasiedzi/event/repository/UserAccountRepositoryWithBagRelationships.java @@ -0,0 +1,14 @@ +package com.sasiedzi.event.repository; + +import com.sasiedzi.event.domain.UserAccount; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Page; + +public interface UserAccountRepositoryWithBagRelationships { + Optional fetchBagRelationships(Optional userAccount); + + List fetchBagRelationships(List userAccounts); + + Page fetchBagRelationships(Page userAccounts); +} diff --git a/src/main/java/com/sasiedzi/event/repository/UserAccountRepositoryWithBagRelationshipsImpl.java b/src/main/java/com/sasiedzi/event/repository/UserAccountRepositoryWithBagRelationshipsImpl.java new file mode 100644 index 0000000..6365794 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/repository/UserAccountRepositoryWithBagRelationshipsImpl.java @@ -0,0 +1,67 @@ +package com.sasiedzi.event.repository; + +import com.sasiedzi.event.domain.UserAccount; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.stream.IntStream; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; + +/** + * Utility repository to load bag relationships based on https://vladmihalcea.com/hibernate-multiplebagfetchexception/ + */ +public class UserAccountRepositoryWithBagRelationshipsImpl implements UserAccountRepositoryWithBagRelationships { + + private static final String ID_PARAMETER = "id"; + private static final String USERACCOUNTS_PARAMETER = "userAccounts"; + + @PersistenceContext + private EntityManager entityManager; + + @Override + public Optional fetchBagRelationships(Optional userAccount) { + return userAccount.map(this::fetchUsers); + } + + @Override + public Page fetchBagRelationships(Page userAccounts) { + return new PageImpl<>( + fetchBagRelationships(userAccounts.getContent()), + userAccounts.getPageable(), + userAccounts.getTotalElements() + ); + } + + @Override + public List fetchBagRelationships(List userAccounts) { + return Optional.of(userAccounts).map(this::fetchUsers).orElse(Collections.emptyList()); + } + + UserAccount fetchUsers(UserAccount result) { + return entityManager + .createQuery( + "select userAccount from UserAccount userAccount left join fetch userAccount.users where userAccount.id = :id", + UserAccount.class + ) + .setParameter(ID_PARAMETER, result.getId()) + .getSingleResult(); + } + + List fetchUsers(List userAccounts) { + HashMap order = new HashMap<>(); + IntStream.range(0, userAccounts.size()).forEach(index -> order.put(userAccounts.get(index).getId(), index)); + List result = entityManager + .createQuery( + "select userAccount from UserAccount userAccount left join fetch userAccount.users where userAccount in :userAccounts", + UserAccount.class + ) + .setParameter(USERACCOUNTS_PARAMETER, userAccounts) + .getResultList(); + Collections.sort(result, (o1, o2) -> Integer.compare(order.get(o1.getId()), order.get(o2.getId()))); + return result; + } +} diff --git a/src/main/java/com/sasiedzi/event/web/rest/TransactionItemResource.java b/src/main/java/com/sasiedzi/event/web/rest/TransactionItemResource.java new file mode 100644 index 0000000..adcedb9 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/web/rest/TransactionItemResource.java @@ -0,0 +1,189 @@ +package com.sasiedzi.event.web.rest; + +import com.sasiedzi.event.domain.TransactionItem; +import com.sasiedzi.event.repository.TransactionItemRepository; +import com.sasiedzi.event.web.rest.errors.BadRequestAlertException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; +import tech.jhipster.web.util.HeaderUtil; +import tech.jhipster.web.util.ResponseUtil; + +/** + * REST controller for managing {@link com.sasiedzi.event.domain.TransactionItem}. + */ +@RestController +@RequestMapping("/api/transaction-items") +@Transactional +public class TransactionItemResource { + + private static final Logger LOG = LoggerFactory.getLogger(TransactionItemResource.class); + + private static final String ENTITY_NAME = "transactionItem"; + + @Value("${jhipster.clientApp.name}") + private String applicationName; + + private final TransactionItemRepository transactionItemRepository; + + public TransactionItemResource(TransactionItemRepository transactionItemRepository) { + this.transactionItemRepository = transactionItemRepository; + } + + /** + * {@code POST /transaction-items} : Create a new transactionItem. + * + * @param transactionItem the transactionItem to create. + * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new transactionItem, or with status {@code 400 (Bad Request)} if the transactionItem has already an ID. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PostMapping("") + public ResponseEntity createTransactionItem(@RequestBody TransactionItem transactionItem) throws URISyntaxException { + LOG.debug("REST request to save TransactionItem : {}", transactionItem); + if (transactionItem.getId() != null) { + throw new BadRequestAlertException("A new transactionItem cannot already have an ID", ENTITY_NAME, "idexists"); + } + transactionItem = transactionItemRepository.save(transactionItem); + return ResponseEntity.created(new URI("/api/transaction-items/" + transactionItem.getId())) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, false, ENTITY_NAME, transactionItem.getId().toString())) + .body(transactionItem); + } + + /** + * {@code PUT /transaction-items/:id} : Updates an existing transactionItem. + * + * @param id the id of the transactionItem to save. + * @param transactionItem the transactionItem to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated transactionItem, + * or with status {@code 400 (Bad Request)} if the transactionItem is not valid, + * or with status {@code 500 (Internal Server Error)} if the transactionItem couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PutMapping("/{id}") + public ResponseEntity updateTransactionItem( + @PathVariable(value = "id", required = false) final Long id, + @RequestBody TransactionItem transactionItem + ) throws URISyntaxException { + LOG.debug("REST request to update TransactionItem : {}, {}", id, transactionItem); + if (transactionItem.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, transactionItem.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!transactionItemRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + transactionItem = transactionItemRepository.save(transactionItem); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, false, ENTITY_NAME, transactionItem.getId().toString())) + .body(transactionItem); + } + + /** + * {@code PATCH /transaction-items/:id} : Partial updates given fields of an existing transactionItem, field will ignore if it is null + * + * @param id the id of the transactionItem to save. + * @param transactionItem the transactionItem to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated transactionItem, + * or with status {@code 400 (Bad Request)} if the transactionItem is not valid, + * or with status {@code 404 (Not Found)} if the transactionItem is not found, + * or with status {@code 500 (Internal Server Error)} if the transactionItem couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = "/{id}", consumes = { "application/json", "application/merge-patch+json" }) + public ResponseEntity partialUpdateTransactionItem( + @PathVariable(value = "id", required = false) final Long id, + @RequestBody TransactionItem transactionItem + ) throws URISyntaxException { + LOG.debug("REST request to partial update TransactionItem partially : {}, {}", id, transactionItem); + if (transactionItem.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, transactionItem.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!transactionItemRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + Optional result = transactionItemRepository + .findById(transactionItem.getId()) + .map(existingTransactionItem -> { + if (transactionItem.getAmount() != null) { + existingTransactionItem.setAmount(transactionItem.getAmount()); + } + if (transactionItem.getDate() != null) { + existingTransactionItem.setDate(transactionItem.getDate()); + } + if (transactionItem.getComment() != null) { + existingTransactionItem.setComment(transactionItem.getComment()); + } + + return existingTransactionItem; + }) + .map(transactionItemRepository::save); + + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, false, ENTITY_NAME, transactionItem.getId().toString()) + ); + } + + /** + * {@code GET /transaction-items} : get all the transactionItems. + * + * @param eagerload flag to eager load entities from relationships (This is applicable for many-to-many). + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of transactionItems in body. + */ + @GetMapping("") + public List getAllTransactionItems( + @RequestParam(name = "eagerload", required = false, defaultValue = "true") boolean eagerload + ) { + LOG.debug("REST request to get all TransactionItems"); + if (eagerload) { + return transactionItemRepository.findAllWithEagerRelationships(); + } else { + return transactionItemRepository.findAll(); + } + } + + /** + * {@code GET /transaction-items/:id} : get the "id" transactionItem. + * + * @param id the id of the transactionItem to retrieve. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the transactionItem, or with status {@code 404 (Not Found)}. + */ + @GetMapping("/{id}") + public ResponseEntity getTransactionItem(@PathVariable("id") Long id) { + LOG.debug("REST request to get TransactionItem : {}", id); + Optional transactionItem = transactionItemRepository.findOneWithEagerRelationships(id); + return ResponseUtil.wrapOrNotFound(transactionItem); + } + + /** + * {@code DELETE /transaction-items/:id} : delete the "id" transactionItem. + * + * @param id the id of the transactionItem to delete. + * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteTransactionItem(@PathVariable("id") Long id) { + LOG.debug("REST request to delete TransactionItem : {}", id); + transactionItemRepository.deleteById(id); + return ResponseEntity.noContent() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, false, ENTITY_NAME, id.toString())) + .build(); + } +} diff --git a/src/main/java/com/sasiedzi/event/web/rest/TransactionResource.java b/src/main/java/com/sasiedzi/event/web/rest/TransactionResource.java new file mode 100644 index 0000000..f32e9e3 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/web/rest/TransactionResource.java @@ -0,0 +1,189 @@ +package com.sasiedzi.event.web.rest; + +import com.sasiedzi.event.domain.Transaction; +import com.sasiedzi.event.repository.TransactionRepository; +import com.sasiedzi.event.web.rest.errors.BadRequestAlertException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; +import tech.jhipster.web.util.HeaderUtil; +import tech.jhipster.web.util.ResponseUtil; + +/** + * REST controller for managing {@link com.sasiedzi.event.domain.Transaction}. + */ +@RestController +@RequestMapping("/api/transactions") +@Transactional +public class TransactionResource { + + private static final Logger LOG = LoggerFactory.getLogger(TransactionResource.class); + + private static final String ENTITY_NAME = "transaction"; + + @Value("${jhipster.clientApp.name}") + private String applicationName; + + private final TransactionRepository transactionRepository; + + public TransactionResource(TransactionRepository transactionRepository) { + this.transactionRepository = transactionRepository; + } + + /** + * {@code POST /transactions} : Create a new transaction. + * + * @param transaction the transaction to create. + * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new transaction, or with status {@code 400 (Bad Request)} if the transaction has already an ID. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PostMapping("") + public ResponseEntity createTransaction(@RequestBody Transaction transaction) throws URISyntaxException { + LOG.debug("REST request to save Transaction : {}", transaction); + if (transaction.getId() != null) { + throw new BadRequestAlertException("A new transaction cannot already have an ID", ENTITY_NAME, "idexists"); + } + transaction = transactionRepository.save(transaction); + return ResponseEntity.created(new URI("/api/transactions/" + transaction.getId())) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, false, ENTITY_NAME, transaction.getId().toString())) + .body(transaction); + } + + /** + * {@code PUT /transactions/:id} : Updates an existing transaction. + * + * @param id the id of the transaction to save. + * @param transaction the transaction to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated transaction, + * or with status {@code 400 (Bad Request)} if the transaction is not valid, + * or with status {@code 500 (Internal Server Error)} if the transaction couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PutMapping("/{id}") + public ResponseEntity updateTransaction( + @PathVariable(value = "id", required = false) final Long id, + @RequestBody Transaction transaction + ) throws URISyntaxException { + LOG.debug("REST request to update Transaction : {}, {}", id, transaction); + if (transaction.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, transaction.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!transactionRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + transaction = transactionRepository.save(transaction); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, false, ENTITY_NAME, transaction.getId().toString())) + .body(transaction); + } + + /** + * {@code PATCH /transactions/:id} : Partial updates given fields of an existing transaction, field will ignore if it is null + * + * @param id the id of the transaction to save. + * @param transaction the transaction to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated transaction, + * or with status {@code 400 (Bad Request)} if the transaction is not valid, + * or with status {@code 404 (Not Found)} if the transaction is not found, + * or with status {@code 500 (Internal Server Error)} if the transaction couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = "/{id}", consumes = { "application/json", "application/merge-patch+json" }) + public ResponseEntity partialUpdateTransaction( + @PathVariable(value = "id", required = false) final Long id, + @RequestBody Transaction transaction + ) throws URISyntaxException { + LOG.debug("REST request to partial update Transaction partially : {}, {}", id, transaction); + if (transaction.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, transaction.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!transactionRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + Optional result = transactionRepository + .findById(transaction.getId()) + .map(existingTransaction -> { + if (transaction.getType() != null) { + existingTransaction.setType(transaction.getType()); + } + if (transaction.getDate() != null) { + existingTransaction.setDate(transaction.getDate()); + } + if (transaction.getComment() != null) { + existingTransaction.setComment(transaction.getComment()); + } + + return existingTransaction; + }) + .map(transactionRepository::save); + + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, false, ENTITY_NAME, transaction.getId().toString()) + ); + } + + /** + * {@code GET /transactions} : get all the transactions. + * + * @param eagerload flag to eager load entities from relationships (This is applicable for many-to-many). + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of transactions in body. + */ + @GetMapping("") + public List getAllTransactions( + @RequestParam(name = "eagerload", required = false, defaultValue = "true") boolean eagerload + ) { + LOG.debug("REST request to get all Transactions"); + if (eagerload) { + return transactionRepository.findAllWithEagerRelationships(); + } else { + return transactionRepository.findAll(); + } + } + + /** + * {@code GET /transactions/:id} : get the "id" transaction. + * + * @param id the id of the transaction to retrieve. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the transaction, or with status {@code 404 (Not Found)}. + */ + @GetMapping("/{id}") + public ResponseEntity getTransaction(@PathVariable("id") Long id) { + LOG.debug("REST request to get Transaction : {}", id); + Optional transaction = transactionRepository.findOneWithEagerRelationships(id); + return ResponseUtil.wrapOrNotFound(transaction); + } + + /** + * {@code DELETE /transactions/:id} : delete the "id" transaction. + * + * @param id the id of the transaction to delete. + * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteTransaction(@PathVariable("id") Long id) { + LOG.debug("REST request to delete Transaction : {}", id); + transactionRepository.deleteById(id); + return ResponseEntity.noContent() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, false, ENTITY_NAME, id.toString())) + .build(); + } +} diff --git a/src/main/java/com/sasiedzi/event/web/rest/UserAccountResource.java b/src/main/java/com/sasiedzi/event/web/rest/UserAccountResource.java new file mode 100644 index 0000000..4ae9472 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/web/rest/UserAccountResource.java @@ -0,0 +1,183 @@ +package com.sasiedzi.event.web.rest; + +import com.sasiedzi.event.domain.UserAccount; +import com.sasiedzi.event.repository.UserAccountRepository; +import com.sasiedzi.event.web.rest.errors.BadRequestAlertException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; +import tech.jhipster.web.util.HeaderUtil; +import tech.jhipster.web.util.ResponseUtil; + +/** + * REST controller for managing {@link com.sasiedzi.event.domain.UserAccount}. + */ +@RestController +@RequestMapping("/api/user-accounts") +@Transactional +public class UserAccountResource { + + private static final Logger LOG = LoggerFactory.getLogger(UserAccountResource.class); + + private static final String ENTITY_NAME = "userAccount"; + + @Value("${jhipster.clientApp.name}") + private String applicationName; + + private final UserAccountRepository userAccountRepository; + + public UserAccountResource(UserAccountRepository userAccountRepository) { + this.userAccountRepository = userAccountRepository; + } + + /** + * {@code POST /user-accounts} : Create a new userAccount. + * + * @param userAccount the userAccount to create. + * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new userAccount, or with status {@code 400 (Bad Request)} if the userAccount has already an ID. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PostMapping("") + public ResponseEntity createUserAccount(@RequestBody UserAccount userAccount) throws URISyntaxException { + LOG.debug("REST request to save UserAccount : {}", userAccount); + if (userAccount.getId() != null) { + throw new BadRequestAlertException("A new userAccount cannot already have an ID", ENTITY_NAME, "idexists"); + } + userAccount = userAccountRepository.save(userAccount); + return ResponseEntity.created(new URI("/api/user-accounts/" + userAccount.getId())) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, false, ENTITY_NAME, userAccount.getId().toString())) + .body(userAccount); + } + + /** + * {@code PUT /user-accounts/:id} : Updates an existing userAccount. + * + * @param id the id of the userAccount to save. + * @param userAccount the userAccount to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated userAccount, + * or with status {@code 400 (Bad Request)} if the userAccount is not valid, + * or with status {@code 500 (Internal Server Error)} if the userAccount couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PutMapping("/{id}") + public ResponseEntity updateUserAccount( + @PathVariable(value = "id", required = false) final Long id, + @RequestBody UserAccount userAccount + ) throws URISyntaxException { + LOG.debug("REST request to update UserAccount : {}, {}", id, userAccount); + if (userAccount.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, userAccount.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!userAccountRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + userAccount = userAccountRepository.save(userAccount); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, false, ENTITY_NAME, userAccount.getId().toString())) + .body(userAccount); + } + + /** + * {@code PATCH /user-accounts/:id} : Partial updates given fields of an existing userAccount, field will ignore if it is null + * + * @param id the id of the userAccount to save. + * @param userAccount the userAccount to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated userAccount, + * or with status {@code 400 (Bad Request)} if the userAccount is not valid, + * or with status {@code 404 (Not Found)} if the userAccount is not found, + * or with status {@code 500 (Internal Server Error)} if the userAccount couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = "/{id}", consumes = { "application/json", "application/merge-patch+json" }) + public ResponseEntity partialUpdateUserAccount( + @PathVariable(value = "id", required = false) final Long id, + @RequestBody UserAccount userAccount + ) throws URISyntaxException { + LOG.debug("REST request to partial update UserAccount partially : {}, {}", id, userAccount); + if (userAccount.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, userAccount.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!userAccountRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + Optional result = userAccountRepository + .findById(userAccount.getId()) + .map(existingUserAccount -> { + if (userAccount.getName() != null) { + existingUserAccount.setName(userAccount.getName()); + } + + return existingUserAccount; + }) + .map(userAccountRepository::save); + + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, false, ENTITY_NAME, userAccount.getId().toString()) + ); + } + + /** + * {@code GET /user-accounts} : get all the userAccounts. + * + * @param eagerload flag to eager load entities from relationships (This is applicable for many-to-many). + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of userAccounts in body. + */ + @GetMapping("") + public List getAllUserAccounts( + @RequestParam(name = "eagerload", required = false, defaultValue = "true") boolean eagerload + ) { + LOG.debug("REST request to get all UserAccounts"); + if (eagerload) { + return userAccountRepository.findAllWithEagerRelationships(); + } else { + return userAccountRepository.findAll(); + } + } + + /** + * {@code GET /user-accounts/:id} : get the "id" userAccount. + * + * @param id the id of the userAccount to retrieve. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the userAccount, or with status {@code 404 (Not Found)}. + */ + @GetMapping("/{id}") + public ResponseEntity getUserAccount(@PathVariable("id") Long id) { + LOG.debug("REST request to get UserAccount : {}", id); + Optional userAccount = userAccountRepository.findOneWithEagerRelationships(id); + return ResponseUtil.wrapOrNotFound(userAccount); + } + + /** + * {@code DELETE /user-accounts/:id} : delete the "id" userAccount. + * + * @param id the id of the userAccount to delete. + * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteUserAccount(@PathVariable("id") Long id) { + LOG.debug("REST request to delete UserAccount : {}", id); + userAccountRepository.deleteById(id); + return ResponseEntity.noContent() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, false, ENTITY_NAME, id.toString())) + .build(); + } +} diff --git a/src/main/resources/config/liquibase/changelog/20241113134007_added_entity_Transaction.xml b/src/main/resources/config/liquibase/changelog/20241113134007_added_entity_Transaction.xml new file mode 100644 index 0000000..c48f42c --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20241113134007_added_entity_Transaction.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20241113134007_added_entity_constraints_Transaction.xml b/src/main/resources/config/liquibase/changelog/20241113134007_added_entity_constraints_Transaction.xml new file mode 100644 index 0000000..9d1a100 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20241113134007_added_entity_constraints_Transaction.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20241113135042_added_entity_UserAccount.xml b/src/main/resources/config/liquibase/changelog/20241113135042_added_entity_UserAccount.xml new file mode 100644 index 0000000..074de61 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20241113135042_added_entity_UserAccount.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20241113135042_added_entity_constraints_UserAccount.xml b/src/main/resources/config/liquibase/changelog/20241113135042_added_entity_constraints_UserAccount.xml new file mode 100644 index 0000000..391fe61 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20241113135042_added_entity_constraints_UserAccount.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20241113135446_added_entity_TransactionItem.xml b/src/main/resources/config/liquibase/changelog/20241113135446_added_entity_TransactionItem.xml new file mode 100644 index 0000000..53fdc61 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20241113135446_added_entity_TransactionItem.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20241113135446_added_entity_constraints_TransactionItem.xml b/src/main/resources/config/liquibase/changelog/20241113135446_added_entity_constraints_TransactionItem.xml new file mode 100644 index 0000000..b61aff3 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20241113135446_added_entity_constraints_TransactionItem.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/fake-data/transaction.csv b/src/main/resources/config/liquibase/fake-data/transaction.csv new file mode 100644 index 0000000..2c7fbf2 --- /dev/null +++ b/src/main/resources/config/liquibase/fake-data/transaction.csv @@ -0,0 +1,11 @@ +id;type;date;comment +1;MATCH;2024-11-12;hope gad outside +2;FIELDPAYMENT;2024-11-12;fibre +3;INTERNALTRANSFER;2024-11-12;finger +4;MATCH;2024-11-12;fair victorious sniff +5;MATCH;2024-11-12;yuck +6;PURCHASE;2024-11-13;correctly +7;INTERNALTRANSFER;2024-11-12;behind gladly alongside +8;FIELDPAYMENT;2024-11-13;negative +9;FIELDPAYMENT;2024-11-13;unlucky +10;FIELDPAYMENT;2024-11-12;see scorpion diff --git a/src/main/resources/config/liquibase/fake-data/transaction_item.csv b/src/main/resources/config/liquibase/fake-data/transaction_item.csv new file mode 100644 index 0000000..3a39abf --- /dev/null +++ b/src/main/resources/config/liquibase/fake-data/transaction_item.csv @@ -0,0 +1,11 @@ +id;amount;date;comment +1;11521.38;2024-11-13;until knowingly antagonize +2;25335.92;2024-11-13;paintwork +3;18782.46;2024-11-13;whoever +4;31380.57;2024-11-13;saturate snow vestment +5;16957.5;2024-11-13;desecrate +6;21000.66;2024-11-13;card +7;21849.26;2024-11-13;as hourly ha +8;11729.78;2024-11-13;on fledgling +9;17672.41;2024-11-13;sarcastic or +10;22248.04;2024-11-12;where gadzooks out diff --git a/src/main/resources/config/liquibase/fake-data/user_account.csv b/src/main/resources/config/liquibase/fake-data/user_account.csv new file mode 100644 index 0000000..817d47f --- /dev/null +++ b/src/main/resources/config/liquibase/fake-data/user_account.csv @@ -0,0 +1,11 @@ +id;name +1;since +2;pfft what jam-packed +3;internalise +4;yum indeed for +5;minion gee +6;likewise impressive concerning +7;notwithstanding +8;furthermore +9;diligently kindly +10;buck diff --git a/src/main/resources/config/liquibase/master.xml b/src/main/resources/config/liquibase/master.xml index 512c6fb..3f0bb26 100644 --- a/src/main/resources/config/liquibase/master.xml +++ b/src/main/resources/config/liquibase/master.xml @@ -14,9 +14,15 @@ + + + + + + diff --git a/src/main/webapp/app/entities/charge/charge.service.spec.ts b/src/main/webapp/app/entities/charge/charge.service.spec.ts index 8a812a7..99612da 100644 --- a/src/main/webapp/app/entities/charge/charge.service.spec.ts +++ b/src/main/webapp/app/entities/charge/charge.service.spec.ts @@ -100,7 +100,7 @@ describe('Service Tests', () => { }); it('should partial update a Charge', async () => { - const patchObject = { chargeDate: dayjs(currentDate).format(DATE_FORMAT), type: 'BBBBBB', ...new Charge() }; + const patchObject = { amount: 1, ...new Charge() }; const returnedFromService = Object.assign(patchObject, elemDefault); const expected = { chargeDate: currentDate, ...returnedFromService }; diff --git a/src/main/webapp/app/entities/entities-menu.vue b/src/main/webapp/app/entities/entities-menu.vue index 242733a..0b6c386 100644 --- a/src/main/webapp/app/entities/entities-menu.vue +++ b/src/main/webapp/app/entities/entities-menu.vue @@ -12,6 +12,14 @@ Registration + + + Transaction + + + + User Account + diff --git a/src/main/webapp/app/entities/entities.component.ts b/src/main/webapp/app/entities/entities.component.ts index 8593ff2..e8b84ff 100644 --- a/src/main/webapp/app/entities/entities.component.ts +++ b/src/main/webapp/app/entities/entities.component.ts @@ -3,6 +3,8 @@ import { defineComponent, provide } from 'vue'; import ChargeService from './charge/charge.service'; import EventService from './event/event.service'; import RegistrationService from './registration/registration.service'; +import TransactionService from './transaction/transaction.service'; +import UserAccountService from './user-account/user-account.service'; import UserService from '@/entities/user/user.service'; // jhipster-needle-add-entity-service-to-entities-component-import - JHipster will import entities services here @@ -14,6 +16,8 @@ export default defineComponent({ provide('chargeService', () => new ChargeService()); provide('eventService', () => new EventService()); provide('registrationService', () => new RegistrationService()); + provide('transactionService', () => new TransactionService()); + provide('userAccountService', () => new UserAccountService()); // jhipster-needle-add-entity-service-to-entities-component - JHipster will import entities services here }, }); diff --git a/src/main/webapp/app/entities/event/event.service.spec.ts b/src/main/webapp/app/entities/event/event.service.spec.ts index 5857942..37e69d2 100644 --- a/src/main/webapp/app/entities/event/event.service.spec.ts +++ b/src/main/webapp/app/entities/event/event.service.spec.ts @@ -107,7 +107,7 @@ describe('Service Tests', () => { }); it('should partial update a Event', async () => { - const patchObject = { name: 'BBBBBB', date: dayjs(currentDate).format(DATE_FORMAT), cost: 1, ...new Event() }; + const patchObject = { name: 'BBBBBB', playersLimit: 1, cost: 1, ...new Event() }; const returnedFromService = Object.assign(patchObject, elemDefault); const expected = { date: currentDate, ...returnedFromService }; diff --git a/src/main/webapp/app/entities/registration/registration.service.spec.ts b/src/main/webapp/app/entities/registration/registration.service.spec.ts index d5aa072..173724a 100644 --- a/src/main/webapp/app/entities/registration/registration.service.spec.ts +++ b/src/main/webapp/app/entities/registration/registration.service.spec.ts @@ -106,7 +106,7 @@ describe('Service Tests', () => { }); it('should partial update a Registration', async () => { - const patchObject = { comment: 'BBBBBB', ...new Registration() }; + const patchObject = { playerName: 'BBBBBB', comment: 'BBBBBB', ...new Registration() }; const returnedFromService = Object.assign(patchObject, elemDefault); const expected = { dateTime: currentDate, ...returnedFromService }; diff --git a/src/main/webapp/app/entities/transaction/transaction-details.component.spec.ts b/src/main/webapp/app/entities/transaction/transaction-details.component.spec.ts new file mode 100644 index 0000000..5706b5a --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction-details.component.spec.ts @@ -0,0 +1,89 @@ +/* tslint:disable max-line-length */ +import { vitest } from 'vitest'; +import { type MountingOptions, shallowMount } from '@vue/test-utils'; +import sinon, { type SinonStubbedInstance } from 'sinon'; +import { type RouteLocation } from 'vue-router'; + +import TransactionDetails from './transaction-details.vue'; +import TransactionService from './transaction.service'; +import AlertService from '@/shared/alert/alert.service'; + +type TransactionDetailsComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vitest.fn(); + +vitest.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const transactionSample = { id: 123 }; + +describe('Component Tests', () => { + let alertService: AlertService; + + afterEach(() => { + vitest.resetAllMocks(); + }); + + describe('Transaction Management Detail Component', () => { + let transactionServiceStub: SinonStubbedInstance; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + route = {}; + transactionServiceStub = sinon.createStubInstance(TransactionService); + + alertService = new AlertService({ + bvToast: { + toast: vitest.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'router-link': true, + }, + provide: { + alertService, + transactionService: () => transactionServiceStub, + }, + }; + }); + + describe('Navigate to details', () => { + it('Should call load all on init', async () => { + // GIVEN + transactionServiceStub.find.resolves(transactionSample); + route = { + params: { + transactionId: `${123}`, + }, + }; + const wrapper = shallowMount(TransactionDetails, { global: mountOptions }); + const comp = wrapper.vm; + // WHEN + await comp.$nextTick(); + + // THEN + expect(comp.transaction).toMatchObject(transactionSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + transactionServiceStub.find.resolves(transactionSample); + const wrapper = shallowMount(TransactionDetails, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/transaction/transaction-details.component.ts b/src/main/webapp/app/entities/transaction/transaction-details.component.ts new file mode 100644 index 0000000..458cbcd --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction-details.component.ts @@ -0,0 +1,41 @@ +import { type Ref, defineComponent, inject, ref } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; + +import TransactionService from './transaction.service'; +import { type ITransaction } from '@/shared/model/transaction.model'; +import { useAlertService } from '@/shared/alert/alert.service'; + +export default defineComponent({ + compatConfig: { MODE: 3 }, + name: 'TransactionDetails', + setup() { + const transactionService = inject('transactionService', () => new TransactionService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + const transaction: Ref = ref({}); + + const retrieveTransaction = async transactionId => { + try { + const res = await transactionService().find(transactionId); + transaction.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.transactionId) { + retrieveTransaction(route.params.transactionId); + } + + return { + alertService, + transaction, + + previousState, + }; + }, +}); diff --git a/src/main/webapp/app/entities/transaction/transaction-details.vue b/src/main/webapp/app/entities/transaction/transaction-details.vue new file mode 100644 index 0000000..9dfc257 --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction-details.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/main/webapp/app/entities/transaction/transaction-update.component.spec.ts b/src/main/webapp/app/entities/transaction/transaction-update.component.spec.ts new file mode 100644 index 0000000..2edb780 --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction-update.component.spec.ts @@ -0,0 +1,137 @@ +/* tslint:disable max-line-length */ +import { vitest } from 'vitest'; +import { type MountingOptions, shallowMount } from '@vue/test-utils'; +import sinon, { type SinonStubbedInstance } from 'sinon'; +import { type RouteLocation } from 'vue-router'; + +import TransactionUpdate from './transaction-update.vue'; +import TransactionService from './transaction.service'; +import AlertService from '@/shared/alert/alert.service'; + +import EventService from '@/entities/event/event.service'; + +type TransactionUpdateComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vitest.fn(); + +vitest.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const transactionSample = { id: 123 }; + +describe('Component Tests', () => { + let mountOptions: MountingOptions['global']; + let alertService: AlertService; + + describe('Transaction Management Update Component', () => { + let comp: TransactionUpdateComponentType; + let transactionServiceStub: SinonStubbedInstance; + + beforeEach(() => { + route = {}; + transactionServiceStub = sinon.createStubInstance(TransactionService); + transactionServiceStub.retrieve.onFirstCall().resolves(Promise.resolve([])); + + alertService = new AlertService({ + bvToast: { + toast: vitest.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'b-input-group': true, + 'b-input-group-prepend': true, + 'b-form-datepicker': true, + 'b-form-input': true, + }, + provide: { + alertService, + transactionService: () => transactionServiceStub, + eventService: () => + sinon.createStubInstance(EventService, { + retrieve: sinon.stub().resolves({}), + } as any), + }, + }; + }); + + afterEach(() => { + vitest.resetAllMocks(); + }); + + describe('save', () => { + it('Should call update service on save for existing entity', async () => { + // GIVEN + const wrapper = shallowMount(TransactionUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.transaction = transactionSample; + transactionServiceStub.update.resolves(transactionSample); + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(transactionServiceStub.update.calledWith(transactionSample)).toBeTruthy(); + expect(comp.isSaving).toEqual(false); + }); + + it('Should call create service on save for new entity', async () => { + // GIVEN + const entity = {}; + transactionServiceStub.create.resolves(entity); + const wrapper = shallowMount(TransactionUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.transaction = entity; + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(transactionServiceStub.create.calledWith(entity)).toBeTruthy(); + expect(comp.isSaving).toEqual(false); + }); + }); + + describe('Before route enter', () => { + it('Should retrieve data', async () => { + // GIVEN + transactionServiceStub.find.resolves(transactionSample); + transactionServiceStub.retrieve.resolves([transactionSample]); + + // WHEN + route = { + params: { + transactionId: `${transactionSample.id}`, + }, + }; + const wrapper = shallowMount(TransactionUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(comp.transaction).toMatchObject(transactionSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + transactionServiceStub.find.resolves(transactionSample); + const wrapper = shallowMount(TransactionUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/transaction/transaction-update.component.ts b/src/main/webapp/app/entities/transaction/transaction-update.component.ts new file mode 100644 index 0000000..8952716 --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction-update.component.ts @@ -0,0 +1,111 @@ +import { type Ref, computed, defineComponent, inject, ref } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; +import { useVuelidate } from '@vuelidate/core'; + +import TransactionService from './transaction.service'; +import { useValidation } from '@/shared/composables'; +import { useAlertService } from '@/shared/alert/alert.service'; + +import EventService from '@/entities/event/event.service'; +import { type IEvent } from '@/shared/model/event.model'; +import { type ITransaction, Transaction } from '@/shared/model/transaction.model'; +import { TransactionType } from '@/shared/model/enumerations/transaction-type.model'; + +export default defineComponent({ + compatConfig: { MODE: 3 }, + name: 'TransactionUpdate', + setup() { + const transactionService = inject('transactionService', () => new TransactionService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const transaction: Ref = ref(new Transaction()); + + const eventService = inject('eventService', () => new EventService()); + + const events: Ref = ref([]); + const transactionTypeValues: Ref = ref(Object.keys(TransactionType)); + const isSaving = ref(false); + const currentLanguage = inject('currentLanguage', () => computed(() => navigator.language ?? 'en'), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + + const retrieveTransaction = async transactionId => { + try { + const res = await transactionService().find(transactionId); + transaction.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.transactionId) { + retrieveTransaction(route.params.transactionId); + } + + const initRelationships = () => { + eventService() + .retrieve() + .then(res => { + events.value = res.data; + }); + }; + + initRelationships(); + + const validations = useValidation(); + const validationRules = { + type: {}, + date: {}, + comment: {}, + event: {}, + }; + const v$ = useVuelidate(validationRules, transaction as any); + v$.value.$validate(); + + return { + transactionService, + alertService, + transaction, + previousState, + transactionTypeValues, + isSaving, + currentLanguage, + events, + v$, + }; + }, + created(): void {}, + methods: { + save(): void { + this.isSaving = true; + if (this.transaction.id) { + this.transactionService() + .update(this.transaction) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showInfo(`A Transaction is updated with identifier ${param.id}`); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } else { + this.transactionService() + .create(this.transaction) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showSuccess(`A Transaction is created with identifier ${param.id}`); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } + }, + }, +}); diff --git a/src/main/webapp/app/entities/transaction/transaction-update.vue b/src/main/webapp/app/entities/transaction/transaction-update.vue new file mode 100644 index 0000000..234546d --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction-update.vue @@ -0,0 +1,98 @@ + + diff --git a/src/main/webapp/app/entities/transaction/transaction.component.spec.ts b/src/main/webapp/app/entities/transaction/transaction.component.spec.ts new file mode 100644 index 0000000..64182bf --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction.component.spec.ts @@ -0,0 +1,100 @@ +/* tslint:disable max-line-length */ +import { vitest } from 'vitest'; +import { type MountingOptions, shallowMount } from '@vue/test-utils'; +import sinon, { type SinonStubbedInstance } from 'sinon'; + +import Transaction from './transaction.vue'; +import TransactionService from './transaction.service'; +import AlertService from '@/shared/alert/alert.service'; + +type TransactionComponentType = InstanceType; + +const bModalStub = { + render: () => {}, + methods: { + hide: () => {}, + show: () => {}, + }, +}; + +describe('Component Tests', () => { + let alertService: AlertService; + + describe('Transaction Management Component', () => { + let transactionServiceStub: SinonStubbedInstance; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + transactionServiceStub = sinon.createStubInstance(TransactionService); + transactionServiceStub.retrieve.resolves({ headers: {} }); + + alertService = new AlertService({ + bvToast: { + toast: vitest.fn(), + } as any, + }); + + mountOptions = { + stubs: { + bModal: bModalStub as any, + 'font-awesome-icon': true, + 'b-badge': true, + 'b-button': true, + 'router-link': true, + }, + directives: { + 'b-modal': {}, + }, + provide: { + alertService, + transactionService: () => transactionServiceStub, + }, + }; + }); + + describe('Mount', () => { + it('Should call load all on init', async () => { + // GIVEN + transactionServiceStub.retrieve.resolves({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + const wrapper = shallowMount(Transaction, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(transactionServiceStub.retrieve.calledOnce).toBeTruthy(); + expect(comp.transactions[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + }); + describe('Handles', () => { + let comp: TransactionComponentType; + + beforeEach(async () => { + const wrapper = shallowMount(Transaction, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + transactionServiceStub.retrieve.reset(); + transactionServiceStub.retrieve.resolves({ headers: {}, data: [] }); + }); + + it('Should call delete service on confirmDelete', async () => { + // GIVEN + transactionServiceStub.delete.resolves({}); + + // WHEN + comp.prepareRemove({ id: 123 }); + + comp.removeTransaction(); + await comp.$nextTick(); // clear components + + // THEN + expect(transactionServiceStub.delete.called).toBeTruthy(); + + // THEN + await comp.$nextTick(); // handle component clear watch + expect(transactionServiceStub.retrieve.callCount).toEqual(1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/transaction/transaction.component.ts b/src/main/webapp/app/entities/transaction/transaction.component.ts new file mode 100644 index 0000000..4d9ca7d --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction.component.ts @@ -0,0 +1,75 @@ +import { type Ref, defineComponent, inject, onMounted, ref } from 'vue'; + +import TransactionService from './transaction.service'; +import { type ITransaction } from '@/shared/model/transaction.model'; +import { useAlertService } from '@/shared/alert/alert.service'; + +export default defineComponent({ + compatConfig: { MODE: 3 }, + name: 'Transaction', + setup() { + const transactionService = inject('transactionService', () => new TransactionService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const transactions: Ref = ref([]); + + const isFetching = ref(false); + + const clear = () => {}; + + const retrieveTransactions = async () => { + isFetching.value = true; + try { + const res = await transactionService().retrieve(); + transactions.value = res.data; + } catch (err) { + alertService.showHttpError(err.response); + } finally { + isFetching.value = false; + } + }; + + const handleSyncList = () => { + retrieveTransactions(); + }; + + onMounted(async () => { + await retrieveTransactions(); + }); + + const removeId: Ref = ref(null); + const removeEntity = ref(null); + const prepareRemove = (instance: ITransaction) => { + removeId.value = instance.id; + removeEntity.value.show(); + }; + const closeDialog = () => { + removeEntity.value.hide(); + }; + const removeTransaction = async () => { + try { + await transactionService().delete(removeId.value); + const message = `A Transaction is deleted with identifier ${removeId.value}`; + alertService.showInfo(message, { variant: 'danger' }); + removeId.value = null; + retrieveTransactions(); + closeDialog(); + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + return { + transactions, + handleSyncList, + isFetching, + retrieveTransactions, + clear, + removeId, + removeEntity, + prepareRemove, + closeDialog, + removeTransaction, + }; + }, +}); diff --git a/src/main/webapp/app/entities/transaction/transaction.service.spec.ts b/src/main/webapp/app/entities/transaction/transaction.service.spec.ts new file mode 100644 index 0000000..ec9a0a6 --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction.service.spec.ts @@ -0,0 +1,164 @@ +/* tslint:disable max-line-length */ +import axios from 'axios'; +import sinon from 'sinon'; +import dayjs from 'dayjs'; + +import TransactionService from './transaction.service'; +import { DATE_FORMAT } from '@/shared/composables/date-format'; +import { Transaction } from '@/shared/model/transaction.model'; + +const error = { + response: { + status: null, + data: { + type: null, + }, + }, +}; + +const axiosStub = { + get: sinon.stub(axios, 'get'), + post: sinon.stub(axios, 'post'), + put: sinon.stub(axios, 'put'), + patch: sinon.stub(axios, 'patch'), + delete: sinon.stub(axios, 'delete'), +}; + +describe('Service Tests', () => { + describe('Transaction Service', () => { + let service: TransactionService; + let elemDefault; + let currentDate: Date; + + beforeEach(() => { + service = new TransactionService(); + currentDate = new Date(); + elemDefault = new Transaction(123, 'PURCHASE', currentDate, 'AAAAAAA'); + }); + + describe('Service methods', () => { + it('should find an element', async () => { + const returnedFromService = { date: dayjs(currentDate).format(DATE_FORMAT), ...elemDefault }; + axiosStub.get.resolves({ data: returnedFromService }); + + return service.find(123).then(res => { + expect(res).toMatchObject(elemDefault); + }); + }); + + it('should not find an element', async () => { + axiosStub.get.rejects(error); + return service + .find(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should create a Transaction', async () => { + const returnedFromService = { id: 123, date: dayjs(currentDate).format(DATE_FORMAT), ...elemDefault }; + const expected = { date: currentDate, ...returnedFromService }; + + axiosStub.post.resolves({ data: returnedFromService }); + return service.create({}).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not create a Transaction', async () => { + axiosStub.post.rejects(error); + + return service + .create({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should update a Transaction', async () => { + const returnedFromService = { type: 'BBBBBB', date: dayjs(currentDate).format(DATE_FORMAT), comment: 'BBBBBB', ...elemDefault }; + + const expected = { date: currentDate, ...returnedFromService }; + axiosStub.put.resolves({ data: returnedFromService }); + + return service.update(expected).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not update a Transaction', async () => { + axiosStub.put.rejects(error); + + return service + .update({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should partial update a Transaction', async () => { + const patchObject = { ...new Transaction() }; + const returnedFromService = Object.assign(patchObject, elemDefault); + + const expected = { date: currentDate, ...returnedFromService }; + axiosStub.patch.resolves({ data: returnedFromService }); + + return service.partialUpdate(patchObject).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not partial update a Transaction', async () => { + axiosStub.patch.rejects(error); + + return service + .partialUpdate({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should return a list of Transaction', async () => { + const returnedFromService = { type: 'BBBBBB', date: dayjs(currentDate).format(DATE_FORMAT), comment: 'BBBBBB', ...elemDefault }; + const expected = { date: currentDate, ...returnedFromService }; + axiosStub.get.resolves([returnedFromService]); + return service.retrieve().then(res => { + expect(res).toContainEqual(expected); + }); + }); + + it('should not return a list of Transaction', async () => { + axiosStub.get.rejects(error); + + return service + .retrieve() + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should delete a Transaction', async () => { + axiosStub.delete.resolves({ ok: true }); + return service.delete(123).then(res => { + expect(res.ok).toBeTruthy(); + }); + }); + + it('should not delete a Transaction', async () => { + axiosStub.delete.rejects(error); + + return service + .delete(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/transaction/transaction.service.ts b/src/main/webapp/app/entities/transaction/transaction.service.ts new file mode 100644 index 0000000..9616427 --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction.service.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; + +import { type ITransaction } from '@/shared/model/transaction.model'; + +const baseApiUrl = 'api/transactions'; + +export default class TransactionService { + public find(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + public retrieve(): Promise { + return new Promise((resolve, reject) => { + axios + .get(baseApiUrl) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + public delete(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .delete(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + public create(entity: ITransaction): Promise { + return new Promise((resolve, reject) => { + axios + .post(`${baseApiUrl}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + public update(entity: ITransaction): Promise { + return new Promise((resolve, reject) => { + axios + .put(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + public partialUpdate(entity: ITransaction): Promise { + return new Promise((resolve, reject) => { + axios + .patch(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } +} diff --git a/src/main/webapp/app/entities/transaction/transaction.vue b/src/main/webapp/app/entities/transaction/transaction.vue new file mode 100644 index 0000000..ef26313 --- /dev/null +++ b/src/main/webapp/app/entities/transaction/transaction.vue @@ -0,0 +1,108 @@ + + + diff --git a/src/main/webapp/app/entities/user-account/user-account-details.component.spec.ts b/src/main/webapp/app/entities/user-account/user-account-details.component.spec.ts new file mode 100644 index 0000000..35837c1 --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account-details.component.spec.ts @@ -0,0 +1,89 @@ +/* tslint:disable max-line-length */ +import { vitest } from 'vitest'; +import { type MountingOptions, shallowMount } from '@vue/test-utils'; +import sinon, { type SinonStubbedInstance } from 'sinon'; +import { type RouteLocation } from 'vue-router'; + +import UserAccountDetails from './user-account-details.vue'; +import UserAccountService from './user-account.service'; +import AlertService from '@/shared/alert/alert.service'; + +type UserAccountDetailsComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vitest.fn(); + +vitest.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const userAccountSample = { id: 123 }; + +describe('Component Tests', () => { + let alertService: AlertService; + + afterEach(() => { + vitest.resetAllMocks(); + }); + + describe('UserAccount Management Detail Component', () => { + let userAccountServiceStub: SinonStubbedInstance; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + route = {}; + userAccountServiceStub = sinon.createStubInstance(UserAccountService); + + alertService = new AlertService({ + bvToast: { + toast: vitest.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'router-link': true, + }, + provide: { + alertService, + userAccountService: () => userAccountServiceStub, + }, + }; + }); + + describe('Navigate to details', () => { + it('Should call load all on init', async () => { + // GIVEN + userAccountServiceStub.find.resolves(userAccountSample); + route = { + params: { + userAccountId: `${123}`, + }, + }; + const wrapper = shallowMount(UserAccountDetails, { global: mountOptions }); + const comp = wrapper.vm; + // WHEN + await comp.$nextTick(); + + // THEN + expect(comp.userAccount).toMatchObject(userAccountSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + userAccountServiceStub.find.resolves(userAccountSample); + const wrapper = shallowMount(UserAccountDetails, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/user-account/user-account-details.component.ts b/src/main/webapp/app/entities/user-account/user-account-details.component.ts new file mode 100644 index 0000000..68529b6 --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account-details.component.ts @@ -0,0 +1,41 @@ +import { type Ref, defineComponent, inject, ref } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; + +import UserAccountService from './user-account.service'; +import { type IUserAccount } from '@/shared/model/user-account.model'; +import { useAlertService } from '@/shared/alert/alert.service'; + +export default defineComponent({ + compatConfig: { MODE: 3 }, + name: 'UserAccountDetails', + setup() { + const userAccountService = inject('userAccountService', () => new UserAccountService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + const userAccount: Ref = ref({}); + + const retrieveUserAccount = async userAccountId => { + try { + const res = await userAccountService().find(userAccountId); + userAccount.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.userAccountId) { + retrieveUserAccount(route.params.userAccountId); + } + + return { + alertService, + userAccount, + + previousState, + }; + }, +}); diff --git a/src/main/webapp/app/entities/user-account/user-account-details.vue b/src/main/webapp/app/entities/user-account/user-account-details.vue new file mode 100644 index 0000000..6e3c0fb --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account-details.vue @@ -0,0 +1,41 @@ + + + diff --git a/src/main/webapp/app/entities/user-account/user-account-update.component.spec.ts b/src/main/webapp/app/entities/user-account/user-account-update.component.spec.ts new file mode 100644 index 0000000..56adc17 --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account-update.component.spec.ts @@ -0,0 +1,138 @@ +/* tslint:disable max-line-length */ +import { vitest } from 'vitest'; +import { type MountingOptions, shallowMount } from '@vue/test-utils'; +import sinon, { type SinonStubbedInstance } from 'sinon'; +import { type RouteLocation } from 'vue-router'; + +import UserAccountUpdate from './user-account-update.vue'; +import UserAccountService from './user-account.service'; +import AlertService from '@/shared/alert/alert.service'; + +import UserService from '@/entities/user/user.service'; + +type UserAccountUpdateComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vitest.fn(); + +vitest.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const userAccountSample = { id: 123 }; + +describe('Component Tests', () => { + let mountOptions: MountingOptions['global']; + let alertService: AlertService; + + describe('UserAccount Management Update Component', () => { + let comp: UserAccountUpdateComponentType; + let userAccountServiceStub: SinonStubbedInstance; + + beforeEach(() => { + route = {}; + userAccountServiceStub = sinon.createStubInstance(UserAccountService); + userAccountServiceStub.retrieve.onFirstCall().resolves(Promise.resolve([])); + + alertService = new AlertService({ + bvToast: { + toast: vitest.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'b-input-group': true, + 'b-input-group-prepend': true, + 'b-form-datepicker': true, + 'b-form-input': true, + }, + provide: { + alertService, + userAccountService: () => userAccountServiceStub, + + userService: () => + sinon.createStubInstance(UserService, { + retrieve: sinon.stub().resolves({}), + } as any), + }, + }; + }); + + afterEach(() => { + vitest.resetAllMocks(); + }); + + describe('save', () => { + it('Should call update service on save for existing entity', async () => { + // GIVEN + const wrapper = shallowMount(UserAccountUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.userAccount = userAccountSample; + userAccountServiceStub.update.resolves(userAccountSample); + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(userAccountServiceStub.update.calledWith(userAccountSample)).toBeTruthy(); + expect(comp.isSaving).toEqual(false); + }); + + it('Should call create service on save for new entity', async () => { + // GIVEN + const entity = {}; + userAccountServiceStub.create.resolves(entity); + const wrapper = shallowMount(UserAccountUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.userAccount = entity; + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(userAccountServiceStub.create.calledWith(entity)).toBeTruthy(); + expect(comp.isSaving).toEqual(false); + }); + }); + + describe('Before route enter', () => { + it('Should retrieve data', async () => { + // GIVEN + userAccountServiceStub.find.resolves(userAccountSample); + userAccountServiceStub.retrieve.resolves([userAccountSample]); + + // WHEN + route = { + params: { + userAccountId: `${userAccountSample.id}`, + }, + }; + const wrapper = shallowMount(UserAccountUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(comp.userAccount).toMatchObject(userAccountSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + userAccountServiceStub.find.resolves(userAccountSample); + const wrapper = shallowMount(UserAccountUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/user-account/user-account-update.component.ts b/src/main/webapp/app/entities/user-account/user-account-update.component.ts new file mode 100644 index 0000000..fc7b4c1 --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account-update.component.ts @@ -0,0 +1,112 @@ +import { type Ref, computed, defineComponent, inject, ref } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; +import { useVuelidate } from '@vuelidate/core'; + +import UserAccountService from './user-account.service'; +import { useValidation } from '@/shared/composables'; +import { useAlertService } from '@/shared/alert/alert.service'; + +import UserService from '@/entities/user/user.service'; +import { type IUserAccount, UserAccount } from '@/shared/model/user-account.model'; + +export default defineComponent({ + compatConfig: { MODE: 3 }, + name: 'UserAccountUpdate', + setup() { + const userAccountService = inject('userAccountService', () => new UserAccountService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const userAccount: Ref = ref(new UserAccount()); + const userService = inject('userService', () => new UserService()); + const users: Ref> = ref([]); + const isSaving = ref(false); + const currentLanguage = inject('currentLanguage', () => computed(() => navigator.language ?? 'en'), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + + const retrieveUserAccount = async userAccountId => { + try { + const res = await userAccountService().find(userAccountId); + userAccount.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.userAccountId) { + retrieveUserAccount(route.params.userAccountId); + } + + const initRelationships = () => { + userService() + .retrieve() + .then(res => { + users.value = res.data; + }); + }; + + initRelationships(); + + const validations = useValidation(); + const validationRules = { + name: {}, + users: {}, + }; + const v$ = useVuelidate(validationRules, userAccount as any); + v$.value.$validate(); + + return { + userAccountService, + alertService, + userAccount, + previousState, + isSaving, + currentLanguage, + users, + v$, + }; + }, + created(): void { + this.userAccount.users = []; + }, + methods: { + save(): void { + this.isSaving = true; + if (this.userAccount.id) { + this.userAccountService() + .update(this.userAccount) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showInfo(`A UserAccount is updated with identifier ${param.id}`); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } else { + this.userAccountService() + .create(this.userAccount) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showSuccess(`A UserAccount is created with identifier ${param.id}`); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } + }, + + getSelected(selectedVals, option, pkField = 'id'): any { + if (selectedVals) { + return selectedVals.find(value => option[pkField] === value[pkField]) ?? option; + } + return option; + }, + }, +}); diff --git a/src/main/webapp/app/entities/user-account/user-account-update.vue b/src/main/webapp/app/entities/user-account/user-account-update.vue new file mode 100644 index 0000000..4b85e59 --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account-update.vue @@ -0,0 +1,58 @@ + + diff --git a/src/main/webapp/app/entities/user-account/user-account.component.spec.ts b/src/main/webapp/app/entities/user-account/user-account.component.spec.ts new file mode 100644 index 0000000..8dd5bfa --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account.component.spec.ts @@ -0,0 +1,100 @@ +/* tslint:disable max-line-length */ +import { vitest } from 'vitest'; +import { type MountingOptions, shallowMount } from '@vue/test-utils'; +import sinon, { type SinonStubbedInstance } from 'sinon'; + +import UserAccount from './user-account.vue'; +import UserAccountService from './user-account.service'; +import AlertService from '@/shared/alert/alert.service'; + +type UserAccountComponentType = InstanceType; + +const bModalStub = { + render: () => {}, + methods: { + hide: () => {}, + show: () => {}, + }, +}; + +describe('Component Tests', () => { + let alertService: AlertService; + + describe('UserAccount Management Component', () => { + let userAccountServiceStub: SinonStubbedInstance; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + userAccountServiceStub = sinon.createStubInstance(UserAccountService); + userAccountServiceStub.retrieve.resolves({ headers: {} }); + + alertService = new AlertService({ + bvToast: { + toast: vitest.fn(), + } as any, + }); + + mountOptions = { + stubs: { + bModal: bModalStub as any, + 'font-awesome-icon': true, + 'b-badge': true, + 'b-button': true, + 'router-link': true, + }, + directives: { + 'b-modal': {}, + }, + provide: { + alertService, + userAccountService: () => userAccountServiceStub, + }, + }; + }); + + describe('Mount', () => { + it('Should call load all on init', async () => { + // GIVEN + userAccountServiceStub.retrieve.resolves({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + const wrapper = shallowMount(UserAccount, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(userAccountServiceStub.retrieve.calledOnce).toBeTruthy(); + expect(comp.userAccounts[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + }); + describe('Handles', () => { + let comp: UserAccountComponentType; + + beforeEach(async () => { + const wrapper = shallowMount(UserAccount, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + userAccountServiceStub.retrieve.reset(); + userAccountServiceStub.retrieve.resolves({ headers: {}, data: [] }); + }); + + it('Should call delete service on confirmDelete', async () => { + // GIVEN + userAccountServiceStub.delete.resolves({}); + + // WHEN + comp.prepareRemove({ id: 123 }); + + comp.removeUserAccount(); + await comp.$nextTick(); // clear components + + // THEN + expect(userAccountServiceStub.delete.called).toBeTruthy(); + + // THEN + await comp.$nextTick(); // handle component clear watch + expect(userAccountServiceStub.retrieve.callCount).toEqual(1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/user-account/user-account.component.ts b/src/main/webapp/app/entities/user-account/user-account.component.ts new file mode 100644 index 0000000..b49e578 --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account.component.ts @@ -0,0 +1,75 @@ +import { type Ref, defineComponent, inject, onMounted, ref } from 'vue'; + +import UserAccountService from './user-account.service'; +import { type IUserAccount } from '@/shared/model/user-account.model'; +import { useAlertService } from '@/shared/alert/alert.service'; + +export default defineComponent({ + compatConfig: { MODE: 3 }, + name: 'UserAccount', + setup() { + const userAccountService = inject('userAccountService', () => new UserAccountService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const userAccounts: Ref = ref([]); + + const isFetching = ref(false); + + const clear = () => {}; + + const retrieveUserAccounts = async () => { + isFetching.value = true; + try { + const res = await userAccountService().retrieve(); + userAccounts.value = res.data; + } catch (err) { + alertService.showHttpError(err.response); + } finally { + isFetching.value = false; + } + }; + + const handleSyncList = () => { + retrieveUserAccounts(); + }; + + onMounted(async () => { + await retrieveUserAccounts(); + }); + + const removeId: Ref = ref(null); + const removeEntity = ref(null); + const prepareRemove = (instance: IUserAccount) => { + removeId.value = instance.id; + removeEntity.value.show(); + }; + const closeDialog = () => { + removeEntity.value.hide(); + }; + const removeUserAccount = async () => { + try { + await userAccountService().delete(removeId.value); + const message = `A UserAccount is deleted with identifier ${removeId.value}`; + alertService.showInfo(message, { variant: 'danger' }); + removeId.value = null; + retrieveUserAccounts(); + closeDialog(); + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + return { + userAccounts, + handleSyncList, + isFetching, + retrieveUserAccounts, + clear, + removeId, + removeEntity, + prepareRemove, + closeDialog, + removeUserAccount, + }; + }, +}); diff --git a/src/main/webapp/app/entities/user-account/user-account.service.spec.ts b/src/main/webapp/app/entities/user-account/user-account.service.spec.ts new file mode 100644 index 0000000..900d8ef --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account.service.spec.ts @@ -0,0 +1,160 @@ +/* tslint:disable max-line-length */ +import axios from 'axios'; +import sinon from 'sinon'; + +import UserAccountService from './user-account.service'; +import { UserAccount } from '@/shared/model/user-account.model'; + +const error = { + response: { + status: null, + data: { + type: null, + }, + }, +}; + +const axiosStub = { + get: sinon.stub(axios, 'get'), + post: sinon.stub(axios, 'post'), + put: sinon.stub(axios, 'put'), + patch: sinon.stub(axios, 'patch'), + delete: sinon.stub(axios, 'delete'), +}; + +describe('Service Tests', () => { + describe('UserAccount Service', () => { + let service: UserAccountService; + let elemDefault; + + beforeEach(() => { + service = new UserAccountService(); + elemDefault = new UserAccount(123, 'AAAAAAA'); + }); + + describe('Service methods', () => { + it('should find an element', async () => { + const returnedFromService = { ...elemDefault }; + axiosStub.get.resolves({ data: returnedFromService }); + + return service.find(123).then(res => { + expect(res).toMatchObject(elemDefault); + }); + }); + + it('should not find an element', async () => { + axiosStub.get.rejects(error); + return service + .find(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should create a UserAccount', async () => { + const returnedFromService = { id: 123, ...elemDefault }; + const expected = { ...returnedFromService }; + + axiosStub.post.resolves({ data: returnedFromService }); + return service.create({}).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not create a UserAccount', async () => { + axiosStub.post.rejects(error); + + return service + .create({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should update a UserAccount', async () => { + const returnedFromService = { name: 'BBBBBB', ...elemDefault }; + + const expected = { ...returnedFromService }; + axiosStub.put.resolves({ data: returnedFromService }); + + return service.update(expected).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not update a UserAccount', async () => { + axiosStub.put.rejects(error); + + return service + .update({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should partial update a UserAccount', async () => { + const patchObject = { name: 'BBBBBB', ...new UserAccount() }; + const returnedFromService = Object.assign(patchObject, elemDefault); + + const expected = { ...returnedFromService }; + axiosStub.patch.resolves({ data: returnedFromService }); + + return service.partialUpdate(patchObject).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not partial update a UserAccount', async () => { + axiosStub.patch.rejects(error); + + return service + .partialUpdate({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should return a list of UserAccount', async () => { + const returnedFromService = { name: 'BBBBBB', ...elemDefault }; + const expected = { ...returnedFromService }; + axiosStub.get.resolves([returnedFromService]); + return service.retrieve().then(res => { + expect(res).toContainEqual(expected); + }); + }); + + it('should not return a list of UserAccount', async () => { + axiosStub.get.rejects(error); + + return service + .retrieve() + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should delete a UserAccount', async () => { + axiosStub.delete.resolves({ ok: true }); + return service.delete(123).then(res => { + expect(res.ok).toBeTruthy(); + }); + }); + + it('should not delete a UserAccount', async () => { + axiosStub.delete.rejects(error); + + return service + .delete(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/user-account/user-account.service.ts b/src/main/webapp/app/entities/user-account/user-account.service.ts new file mode 100644 index 0000000..5b8ffbd --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account.service.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; + +import { type IUserAccount } from '@/shared/model/user-account.model'; + +const baseApiUrl = 'api/user-accounts'; + +export default class UserAccountService { + public find(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + public retrieve(): Promise { + return new Promise((resolve, reject) => { + axios + .get(baseApiUrl) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + public delete(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .delete(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + public create(entity: IUserAccount): Promise { + return new Promise((resolve, reject) => { + axios + .post(`${baseApiUrl}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + public update(entity: IUserAccount): Promise { + return new Promise((resolve, reject) => { + axios + .put(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + public partialUpdate(entity: IUserAccount): Promise { + return new Promise((resolve, reject) => { + axios + .patch(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } +} diff --git a/src/main/webapp/app/entities/user-account/user-account.vue b/src/main/webapp/app/entities/user-account/user-account.vue new file mode 100644 index 0000000..56191c0 --- /dev/null +++ b/src/main/webapp/app/entities/user-account/user-account.vue @@ -0,0 +1,103 @@ + + + diff --git a/src/main/webapp/app/router/entities.ts b/src/main/webapp/app/router/entities.ts index 7853df9..f1902e0 100644 --- a/src/main/webapp/app/router/entities.ts +++ b/src/main/webapp/app/router/entities.ts @@ -15,6 +15,14 @@ const Registration = () => import('@/entities/registration/registration.vue'); const RegistrationUpdate = () => import('@/entities/registration/registration-update.vue'); const RegistrationDetails = () => import('@/entities/registration/registration-details.vue'); +const Transaction = () => import('@/entities/transaction/transaction.vue'); +const TransactionUpdate = () => import('@/entities/transaction/transaction-update.vue'); +const TransactionDetails = () => import('@/entities/transaction/transaction-details.vue'); + +const UserAccount = () => import('@/entities/user-account/user-account.vue'); +const UserAccountUpdate = () => import('@/entities/user-account/user-account-update.vue'); +const UserAccountDetails = () => import('@/entities/user-account/user-account-details.vue'); + // jhipster-needle-add-entity-to-router-import - JHipster will import entities to the router here export default { @@ -94,6 +102,54 @@ export default { component: RegistrationDetails, meta: { authorities: [Authority.USER] }, }, + { + path: 'transaction', + name: 'Transaction', + component: Transaction, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'transaction/new', + name: 'TransactionCreate', + component: TransactionUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'transaction/:transactionId/edit', + name: 'TransactionEdit', + component: TransactionUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'transaction/:transactionId/view', + name: 'TransactionView', + component: TransactionDetails, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'user-account', + name: 'UserAccount', + component: UserAccount, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'user-account/new', + name: 'UserAccountCreate', + component: UserAccountUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'user-account/:userAccountId/edit', + name: 'UserAccountEdit', + component: UserAccountUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'user-account/:userAccountId/view', + name: 'UserAccountView', + component: UserAccountDetails, + meta: { authorities: [Authority.USER] }, + }, // jhipster-needle-add-entity-to-router - JHipster will add entities to the router here ], }; diff --git a/src/main/webapp/app/shared/model/enumerations/transaction-type.model.ts b/src/main/webapp/app/shared/model/enumerations/transaction-type.model.ts new file mode 100644 index 0000000..5352299 --- /dev/null +++ b/src/main/webapp/app/shared/model/enumerations/transaction-type.model.ts @@ -0,0 +1,9 @@ +export enum TransactionType { + PURCHASE = 'PURCHASE', + + MATCH = 'MATCH', + + FIELDPAYMENT = 'FIELDPAYMENT', + + INTERNALTRANSFER = 'INTERNALTRANSFER', +} diff --git a/src/main/webapp/app/shared/model/transaction.model.ts b/src/main/webapp/app/shared/model/transaction.model.ts new file mode 100644 index 0000000..23240cb --- /dev/null +++ b/src/main/webapp/app/shared/model/transaction.model.ts @@ -0,0 +1,20 @@ +import { type IEvent } from '@/shared/model/event.model'; + +import { type TransactionType } from '@/shared/model/enumerations/transaction-type.model'; +export interface ITransaction { + id?: number; + type?: keyof typeof TransactionType | null; + date?: Date | null; + comment?: string | null; + event?: IEvent | null; +} + +export class Transaction implements ITransaction { + constructor( + public id?: number, + public type?: keyof typeof TransactionType | null, + public date?: Date | null, + public comment?: string | null, + public event?: IEvent | null, + ) {} +} diff --git a/src/main/webapp/app/shared/model/user-account.model.ts b/src/main/webapp/app/shared/model/user-account.model.ts new file mode 100644 index 0000000..330fffe --- /dev/null +++ b/src/main/webapp/app/shared/model/user-account.model.ts @@ -0,0 +1,15 @@ +import { type IUser } from '@/shared/model/user.model'; + +export interface IUserAccount { + id?: number; + name?: string | null; + users?: IUser[] | null; +} + +export class UserAccount implements IUserAccount { + constructor( + public id?: number, + public name?: string | null, + public users?: IUser[] | null, + ) {} +} diff --git a/src/test/java/com/sasiedzi/event/domain/EventTest.java b/src/test/java/com/sasiedzi/event/domain/EventTest.java index 6fdc0fb..ca8292f 100644 --- a/src/test/java/com/sasiedzi/event/domain/EventTest.java +++ b/src/test/java/com/sasiedzi/event/domain/EventTest.java @@ -2,6 +2,7 @@ package com.sasiedzi.event.domain; import static com.sasiedzi.event.domain.EventTestSamples.*; import static com.sasiedzi.event.domain.RegistrationTestSamples.*; +import static com.sasiedzi.event.domain.TransactionTestSamples.*; import static org.assertj.core.api.Assertions.assertThat; import com.sasiedzi.event.web.rest.TestUtil; @@ -46,4 +47,26 @@ class EventTest { assertThat(event.getRegistrations()).doesNotContain(registrationBack); assertThat(registrationBack.getEvent()).isNull(); } + + @Test + void transactionTest() { + Event event = getEventRandomSampleGenerator(); + Transaction transactionBack = getTransactionRandomSampleGenerator(); + + event.addTransaction(transactionBack); + assertThat(event.getTransactions()).containsOnly(transactionBack); + assertThat(transactionBack.getEvent()).isEqualTo(event); + + event.removeTransaction(transactionBack); + assertThat(event.getTransactions()).doesNotContain(transactionBack); + assertThat(transactionBack.getEvent()).isNull(); + + event.transactions(new HashSet<>(Set.of(transactionBack))); + assertThat(event.getTransactions()).containsOnly(transactionBack); + assertThat(transactionBack.getEvent()).isEqualTo(event); + + event.setTransactions(new HashSet<>()); + assertThat(event.getTransactions()).doesNotContain(transactionBack); + assertThat(transactionBack.getEvent()).isNull(); + } } diff --git a/src/test/java/com/sasiedzi/event/domain/TransactionAsserts.java b/src/test/java/com/sasiedzi/event/domain/TransactionAsserts.java new file mode 100644 index 0000000..6909593 --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/TransactionAsserts.java @@ -0,0 +1,67 @@ +package com.sasiedzi.event.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TransactionAsserts { + + /** + * Asserts that the entity has all properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionAllPropertiesEquals(Transaction expected, Transaction actual) { + assertTransactionAutoGeneratedPropertiesEquals(expected, actual); + assertTransactionAllUpdatablePropertiesEquals(expected, actual); + } + + /** + * Asserts that the entity has all updatable properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionAllUpdatablePropertiesEquals(Transaction expected, Transaction actual) { + assertTransactionUpdatableFieldsEquals(expected, actual); + assertTransactionUpdatableRelationshipsEquals(expected, actual); + } + + /** + * Asserts that the entity has all the auto generated properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionAutoGeneratedPropertiesEquals(Transaction expected, Transaction actual) { + assertThat(expected) + .as("Verify Transaction auto generated properties") + .satisfies(e -> assertThat(e.getId()).as("check id").isEqualTo(actual.getId())); + } + + /** + * Asserts that the entity has all the updatable fields set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionUpdatableFieldsEquals(Transaction expected, Transaction actual) { + assertThat(expected) + .as("Verify Transaction relevant properties") + .satisfies(e -> assertThat(e.getType()).as("check type").isEqualTo(actual.getType())) + .satisfies(e -> assertThat(e.getDate()).as("check date").isEqualTo(actual.getDate())) + .satisfies(e -> assertThat(e.getComment()).as("check comment").isEqualTo(actual.getComment())); + } + + /** + * Asserts that the entity has all the updatable relationships set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionUpdatableRelationshipsEquals(Transaction expected, Transaction actual) { + assertThat(expected) + .as("Verify Transaction relationships") + .satisfies(e -> assertThat(e.getEvent()).as("check event").isEqualTo(actual.getEvent())) + .satisfies(e -> assertThat(e.getTransactionItem()).as("check transactionItem").isEqualTo(actual.getTransactionItem())); + } +} diff --git a/src/test/java/com/sasiedzi/event/domain/TransactionItemAsserts.java b/src/test/java/com/sasiedzi/event/domain/TransactionItemAsserts.java new file mode 100644 index 0000000..85575de --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/TransactionItemAsserts.java @@ -0,0 +1,67 @@ +package com.sasiedzi.event.domain; + +import static com.sasiedzi.event.domain.AssertUtils.bigDecimalCompareTo; +import static org.assertj.core.api.Assertions.assertThat; + +public class TransactionItemAsserts { + + /** + * Asserts that the entity has all properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionItemAllPropertiesEquals(TransactionItem expected, TransactionItem actual) { + assertTransactionItemAutoGeneratedPropertiesEquals(expected, actual); + assertTransactionItemAllUpdatablePropertiesEquals(expected, actual); + } + + /** + * Asserts that the entity has all updatable properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionItemAllUpdatablePropertiesEquals(TransactionItem expected, TransactionItem actual) { + assertTransactionItemUpdatableFieldsEquals(expected, actual); + assertTransactionItemUpdatableRelationshipsEquals(expected, actual); + } + + /** + * Asserts that the entity has all the auto generated properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionItemAutoGeneratedPropertiesEquals(TransactionItem expected, TransactionItem actual) { + assertThat(expected) + .as("Verify TransactionItem auto generated properties") + .satisfies(e -> assertThat(e.getId()).as("check id").isEqualTo(actual.getId())); + } + + /** + * Asserts that the entity has all the updatable fields set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionItemUpdatableFieldsEquals(TransactionItem expected, TransactionItem actual) { + assertThat(expected) + .as("Verify TransactionItem relevant properties") + .satisfies(e -> assertThat(e.getAmount()).as("check amount").usingComparator(bigDecimalCompareTo).isEqualTo(actual.getAmount())) + .satisfies(e -> assertThat(e.getDate()).as("check date").isEqualTo(actual.getDate())) + .satisfies(e -> assertThat(e.getComment()).as("check comment").isEqualTo(actual.getComment())); + } + + /** + * Asserts that the entity has all the updatable relationships set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertTransactionItemUpdatableRelationshipsEquals(TransactionItem expected, TransactionItem actual) { + assertThat(expected) + .as("Verify TransactionItem relationships") + .satisfies(e -> assertThat(e.getUserAccounts()).as("check userAccounts").isEqualTo(actual.getUserAccounts())); + } +} diff --git a/src/test/java/com/sasiedzi/event/domain/TransactionItemTest.java b/src/test/java/com/sasiedzi/event/domain/TransactionItemTest.java new file mode 100644 index 0000000..f3892bb --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/TransactionItemTest.java @@ -0,0 +1,68 @@ +package com.sasiedzi.event.domain; + +import static com.sasiedzi.event.domain.TransactionItemTestSamples.*; +import static com.sasiedzi.event.domain.TransactionTestSamples.*; +import static com.sasiedzi.event.domain.UserAccountTestSamples.*; +import static org.assertj.core.api.Assertions.assertThat; + +import com.sasiedzi.event.web.rest.TestUtil; +import java.util.HashSet; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class TransactionItemTest { + + @Test + void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(TransactionItem.class); + TransactionItem transactionItem1 = getTransactionItemSample1(); + TransactionItem transactionItem2 = new TransactionItem(); + assertThat(transactionItem1).isNotEqualTo(transactionItem2); + + transactionItem2.setId(transactionItem1.getId()); + assertThat(transactionItem1).isEqualTo(transactionItem2); + + transactionItem2 = getTransactionItemSample2(); + assertThat(transactionItem1).isNotEqualTo(transactionItem2); + } + + @Test + void userAccountTest() { + TransactionItem transactionItem = getTransactionItemRandomSampleGenerator(); + UserAccount userAccountBack = getUserAccountRandomSampleGenerator(); + + transactionItem.addUserAccount(userAccountBack); + assertThat(transactionItem.getUserAccounts()).containsOnly(userAccountBack); + + transactionItem.removeUserAccount(userAccountBack); + assertThat(transactionItem.getUserAccounts()).doesNotContain(userAccountBack); + + transactionItem.userAccounts(new HashSet<>(Set.of(userAccountBack))); + assertThat(transactionItem.getUserAccounts()).containsOnly(userAccountBack); + + transactionItem.setUserAccounts(new HashSet<>()); + assertThat(transactionItem.getUserAccounts()).doesNotContain(userAccountBack); + } + + @Test + void transactionTest() { + TransactionItem transactionItem = getTransactionItemRandomSampleGenerator(); + Transaction transactionBack = getTransactionRandomSampleGenerator(); + + transactionItem.addTransaction(transactionBack); + assertThat(transactionItem.getTransactions()).containsOnly(transactionBack); + assertThat(transactionBack.getTransactionItem()).isEqualTo(transactionItem); + + transactionItem.removeTransaction(transactionBack); + assertThat(transactionItem.getTransactions()).doesNotContain(transactionBack); + assertThat(transactionBack.getTransactionItem()).isNull(); + + transactionItem.transactions(new HashSet<>(Set.of(transactionBack))); + assertThat(transactionItem.getTransactions()).containsOnly(transactionBack); + assertThat(transactionBack.getTransactionItem()).isEqualTo(transactionItem); + + transactionItem.setTransactions(new HashSet<>()); + assertThat(transactionItem.getTransactions()).doesNotContain(transactionBack); + assertThat(transactionBack.getTransactionItem()).isNull(); + } +} diff --git a/src/test/java/com/sasiedzi/event/domain/TransactionItemTestSamples.java b/src/test/java/com/sasiedzi/event/domain/TransactionItemTestSamples.java new file mode 100644 index 0000000..6697cba --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/TransactionItemTestSamples.java @@ -0,0 +1,23 @@ +package com.sasiedzi.event.domain; + +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; + +public class TransactionItemTestSamples { + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + (2 * Integer.MAX_VALUE)); + + public static TransactionItem getTransactionItemSample1() { + return new TransactionItem().id(1L).comment("comment1"); + } + + public static TransactionItem getTransactionItemSample2() { + return new TransactionItem().id(2L).comment("comment2"); + } + + public static TransactionItem getTransactionItemRandomSampleGenerator() { + return new TransactionItem().id(longCount.incrementAndGet()).comment(UUID.randomUUID().toString()); + } +} diff --git a/src/test/java/com/sasiedzi/event/domain/TransactionTest.java b/src/test/java/com/sasiedzi/event/domain/TransactionTest.java new file mode 100644 index 0000000..d145950 --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/TransactionTest.java @@ -0,0 +1,50 @@ +package com.sasiedzi.event.domain; + +import static com.sasiedzi.event.domain.EventTestSamples.*; +import static com.sasiedzi.event.domain.TransactionItemTestSamples.*; +import static com.sasiedzi.event.domain.TransactionTestSamples.*; +import static org.assertj.core.api.Assertions.assertThat; + +import com.sasiedzi.event.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class TransactionTest { + + @Test + void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(Transaction.class); + Transaction transaction1 = getTransactionSample1(); + Transaction transaction2 = new Transaction(); + assertThat(transaction1).isNotEqualTo(transaction2); + + transaction2.setId(transaction1.getId()); + assertThat(transaction1).isEqualTo(transaction2); + + transaction2 = getTransactionSample2(); + assertThat(transaction1).isNotEqualTo(transaction2); + } + + @Test + void eventTest() { + Transaction transaction = getTransactionRandomSampleGenerator(); + Event eventBack = getEventRandomSampleGenerator(); + + transaction.setEvent(eventBack); + assertThat(transaction.getEvent()).isEqualTo(eventBack); + + transaction.event(null); + assertThat(transaction.getEvent()).isNull(); + } + + @Test + void transactionItemTest() { + Transaction transaction = getTransactionRandomSampleGenerator(); + TransactionItem transactionItemBack = getTransactionItemRandomSampleGenerator(); + + transaction.setTransactionItem(transactionItemBack); + assertThat(transaction.getTransactionItem()).isEqualTo(transactionItemBack); + + transaction.transactionItem(null); + assertThat(transaction.getTransactionItem()).isNull(); + } +} diff --git a/src/test/java/com/sasiedzi/event/domain/TransactionTestSamples.java b/src/test/java/com/sasiedzi/event/domain/TransactionTestSamples.java new file mode 100644 index 0000000..a8c6ba4 --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/TransactionTestSamples.java @@ -0,0 +1,23 @@ +package com.sasiedzi.event.domain; + +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; + +public class TransactionTestSamples { + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + (2 * Integer.MAX_VALUE)); + + public static Transaction getTransactionSample1() { + return new Transaction().id(1L).comment("comment1"); + } + + public static Transaction getTransactionSample2() { + return new Transaction().id(2L).comment("comment2"); + } + + public static Transaction getTransactionRandomSampleGenerator() { + return new Transaction().id(longCount.incrementAndGet()).comment(UUID.randomUUID().toString()); + } +} diff --git a/src/test/java/com/sasiedzi/event/domain/UserAccountAsserts.java b/src/test/java/com/sasiedzi/event/domain/UserAccountAsserts.java new file mode 100644 index 0000000..e71e661 --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/UserAccountAsserts.java @@ -0,0 +1,64 @@ +package com.sasiedzi.event.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UserAccountAsserts { + + /** + * Asserts that the entity has all properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertUserAccountAllPropertiesEquals(UserAccount expected, UserAccount actual) { + assertUserAccountAutoGeneratedPropertiesEquals(expected, actual); + assertUserAccountAllUpdatablePropertiesEquals(expected, actual); + } + + /** + * Asserts that the entity has all updatable properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertUserAccountAllUpdatablePropertiesEquals(UserAccount expected, UserAccount actual) { + assertUserAccountUpdatableFieldsEquals(expected, actual); + assertUserAccountUpdatableRelationshipsEquals(expected, actual); + } + + /** + * Asserts that the entity has all the auto generated properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertUserAccountAutoGeneratedPropertiesEquals(UserAccount expected, UserAccount actual) { + assertThat(expected) + .as("Verify UserAccount auto generated properties") + .satisfies(e -> assertThat(e.getId()).as("check id").isEqualTo(actual.getId())); + } + + /** + * Asserts that the entity has all the updatable fields set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertUserAccountUpdatableFieldsEquals(UserAccount expected, UserAccount actual) { + assertThat(expected) + .as("Verify UserAccount relevant properties") + .satisfies(e -> assertThat(e.getName()).as("check name").isEqualTo(actual.getName())); + } + + /** + * Asserts that the entity has all the updatable relationships set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertUserAccountUpdatableRelationshipsEquals(UserAccount expected, UserAccount actual) { + assertThat(expected) + .as("Verify UserAccount relationships") + .satisfies(e -> assertThat(e.getTransactionItems()).as("check transactionItems").isEqualTo(actual.getTransactionItems())); + } +} diff --git a/src/test/java/com/sasiedzi/event/domain/UserAccountTest.java b/src/test/java/com/sasiedzi/event/domain/UserAccountTest.java new file mode 100644 index 0000000..fb7631c --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/UserAccountTest.java @@ -0,0 +1,49 @@ +package com.sasiedzi.event.domain; + +import static com.sasiedzi.event.domain.TransactionItemTestSamples.*; +import static com.sasiedzi.event.domain.UserAccountTestSamples.*; +import static org.assertj.core.api.Assertions.assertThat; + +import com.sasiedzi.event.web.rest.TestUtil; +import java.util.HashSet; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class UserAccountTest { + + @Test + void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(UserAccount.class); + UserAccount userAccount1 = getUserAccountSample1(); + UserAccount userAccount2 = new UserAccount(); + assertThat(userAccount1).isNotEqualTo(userAccount2); + + userAccount2.setId(userAccount1.getId()); + assertThat(userAccount1).isEqualTo(userAccount2); + + userAccount2 = getUserAccountSample2(); + assertThat(userAccount1).isNotEqualTo(userAccount2); + } + + @Test + void transactionItemTest() { + UserAccount userAccount = getUserAccountRandomSampleGenerator(); + TransactionItem transactionItemBack = getTransactionItemRandomSampleGenerator(); + + userAccount.addTransactionItem(transactionItemBack); + assertThat(userAccount.getTransactionItems()).containsOnly(transactionItemBack); + assertThat(transactionItemBack.getUserAccounts()).containsOnly(userAccount); + + userAccount.removeTransactionItem(transactionItemBack); + assertThat(userAccount.getTransactionItems()).doesNotContain(transactionItemBack); + assertThat(transactionItemBack.getUserAccounts()).doesNotContain(userAccount); + + userAccount.transactionItems(new HashSet<>(Set.of(transactionItemBack))); + assertThat(userAccount.getTransactionItems()).containsOnly(transactionItemBack); + assertThat(transactionItemBack.getUserAccounts()).containsOnly(userAccount); + + userAccount.setTransactionItems(new HashSet<>()); + assertThat(userAccount.getTransactionItems()).doesNotContain(transactionItemBack); + assertThat(transactionItemBack.getUserAccounts()).doesNotContain(userAccount); + } +} diff --git a/src/test/java/com/sasiedzi/event/domain/UserAccountTestSamples.java b/src/test/java/com/sasiedzi/event/domain/UserAccountTestSamples.java new file mode 100644 index 0000000..73a0e03 --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/UserAccountTestSamples.java @@ -0,0 +1,23 @@ +package com.sasiedzi.event.domain; + +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; + +public class UserAccountTestSamples { + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + (2 * Integer.MAX_VALUE)); + + public static UserAccount getUserAccountSample1() { + return new UserAccount().id(1L).name("name1"); + } + + public static UserAccount getUserAccountSample2() { + return new UserAccount().id(2L).name("name2"); + } + + public static UserAccount getUserAccountRandomSampleGenerator() { + return new UserAccount().id(longCount.incrementAndGet()).name(UUID.randomUUID().toString()); + } +} diff --git a/src/test/java/com/sasiedzi/event/web/rest/ChargeResourceIT.java b/src/test/java/com/sasiedzi/event/web/rest/ChargeResourceIT.java index c7398f5..7120c4b 100644 --- a/src/test/java/com/sasiedzi/event/web/rest/ChargeResourceIT.java +++ b/src/test/java/com/sasiedzi/event/web/rest/ChargeResourceIT.java @@ -358,8 +358,6 @@ class ChargeResourceIT { Charge partialUpdatedCharge = new Charge(); partialUpdatedCharge.setId(charge.getId()); - partialUpdatedCharge.chargeDate(UPDATED_CHARGE_DATE).amount(UPDATED_AMOUNT); - restChargeMockMvc .perform( patch(ENTITY_API_URL_ID, partialUpdatedCharge.getId()) diff --git a/src/test/java/com/sasiedzi/event/web/rest/EventResourceIT.java b/src/test/java/com/sasiedzi/event/web/rest/EventResourceIT.java index c103d38..e004b8a 100644 --- a/src/test/java/com/sasiedzi/event/web/rest/EventResourceIT.java +++ b/src/test/java/com/sasiedzi/event/web/rest/EventResourceIT.java @@ -328,7 +328,7 @@ class EventResourceIT { Event partialUpdatedEvent = new Event(); partialUpdatedEvent.setId(event.getId()); - partialUpdatedEvent.name(UPDATED_NAME).date(UPDATED_DATE).playersLimit(UPDATED_PLAYERS_LIMIT); + partialUpdatedEvent.name(UPDATED_NAME).cost(UPDATED_COST).comment(UPDATED_COMMENT); restEventMockMvc .perform( diff --git a/src/test/java/com/sasiedzi/event/web/rest/RegistrationResourceIT.java b/src/test/java/com/sasiedzi/event/web/rest/RegistrationResourceIT.java index bf0c95a..a400f13 100644 --- a/src/test/java/com/sasiedzi/event/web/rest/RegistrationResourceIT.java +++ b/src/test/java/com/sasiedzi/event/web/rest/RegistrationResourceIT.java @@ -357,7 +357,7 @@ class RegistrationResourceIT { Registration partialUpdatedRegistration = new Registration(); partialUpdatedRegistration.setId(registration.getId()); - partialUpdatedRegistration.active(UPDATED_ACTIVE).comment(UPDATED_COMMENT); + partialUpdatedRegistration.active(UPDATED_ACTIVE); restRegistrationMockMvc .perform( diff --git a/src/test/java/com/sasiedzi/event/web/rest/TransactionItemResourceIT.java b/src/test/java/com/sasiedzi/event/web/rest/TransactionItemResourceIT.java new file mode 100644 index 0000000..ee3fb2c --- /dev/null +++ b/src/test/java/com/sasiedzi/event/web/rest/TransactionItemResourceIT.java @@ -0,0 +1,469 @@ +package com.sasiedzi.event.web.rest; + +import static com.sasiedzi.event.domain.TransactionItemAsserts.*; +import static com.sasiedzi.event.web.rest.TestUtil.createUpdateProxyForBean; +import static com.sasiedzi.event.web.rest.TestUtil.sameNumber; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sasiedzi.event.IntegrationTest; +import com.sasiedzi.event.domain.TransactionItem; +import com.sasiedzi.event.repository.TransactionItemRepository; +import jakarta.persistence.EntityManager; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +/** + * Integration tests for the {@link TransactionItemResource} REST controller. + */ +@IntegrationTest +@ExtendWith(MockitoExtension.class) +@AutoConfigureMockMvc +@WithMockUser +class TransactionItemResourceIT { + + private static final BigDecimal DEFAULT_AMOUNT = new BigDecimal(1); + private static final BigDecimal UPDATED_AMOUNT = new BigDecimal(2); + + private static final LocalDate DEFAULT_DATE = LocalDate.ofEpochDay(0L); + private static final LocalDate UPDATED_DATE = LocalDate.now(ZoneId.systemDefault()); + + private static final String DEFAULT_COMMENT = "AAAAAAAAAA"; + private static final String UPDATED_COMMENT = "BBBBBBBBBB"; + + private static final String ENTITY_API_URL = "/api/transaction-items"; + private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{id}"; + + private static Random random = new Random(); + private static AtomicLong longCount = new AtomicLong(random.nextInt() + (2 * Integer.MAX_VALUE)); + + @Autowired + private ObjectMapper om; + + @Autowired + private TransactionItemRepository transactionItemRepository; + + @Mock + private TransactionItemRepository transactionItemRepositoryMock; + + @Autowired + private EntityManager em; + + @Autowired + private MockMvc restTransactionItemMockMvc; + + private TransactionItem transactionItem; + + private TransactionItem insertedTransactionItem; + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static TransactionItem createEntity() { + return new TransactionItem().amount(DEFAULT_AMOUNT).date(DEFAULT_DATE).comment(DEFAULT_COMMENT); + } + + /** + * Create an updated entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static TransactionItem createUpdatedEntity() { + return new TransactionItem().amount(UPDATED_AMOUNT).date(UPDATED_DATE).comment(UPDATED_COMMENT); + } + + @BeforeEach + public void initTest() { + transactionItem = createEntity(); + } + + @AfterEach + public void cleanup() { + if (insertedTransactionItem != null) { + transactionItemRepository.delete(insertedTransactionItem); + insertedTransactionItem = null; + } + } + + @Test + @Transactional + void createTransactionItem() throws Exception { + long databaseSizeBeforeCreate = getRepositoryCount(); + // Create the TransactionItem + var returnedTransactionItem = om.readValue( + restTransactionItemMockMvc + .perform( + post(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(transactionItem)) + ) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getContentAsString(), + TransactionItem.class + ); + + // Validate the TransactionItem in the database + assertIncrementedRepositoryCount(databaseSizeBeforeCreate); + assertTransactionItemUpdatableFieldsEquals(returnedTransactionItem, getPersistedTransactionItem(returnedTransactionItem)); + + insertedTransactionItem = returnedTransactionItem; + } + + @Test + @Transactional + void createTransactionItemWithExistingId() throws Exception { + // Create the TransactionItem with an existing ID + transactionItem.setId(1L); + + long databaseSizeBeforeCreate = getRepositoryCount(); + + // An entity with an existing ID cannot be created, so this API call must fail + restTransactionItemMockMvc + .perform( + post(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(transactionItem)) + ) + .andExpect(status().isBadRequest()); + + // Validate the TransactionItem in the database + assertSameRepositoryCount(databaseSizeBeforeCreate); + } + + @Test + @Transactional + void getAllTransactionItems() throws Exception { + // Initialize the database + insertedTransactionItem = transactionItemRepository.saveAndFlush(transactionItem); + + // Get all the transactionItemList + restTransactionItemMockMvc + .perform(get(ENTITY_API_URL + "?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(transactionItem.getId().intValue()))) + .andExpect(jsonPath("$.[*].amount").value(hasItem(sameNumber(DEFAULT_AMOUNT)))) + .andExpect(jsonPath("$.[*].date").value(hasItem(DEFAULT_DATE.toString()))) + .andExpect(jsonPath("$.[*].comment").value(hasItem(DEFAULT_COMMENT))); + } + + @SuppressWarnings({ "unchecked" }) + void getAllTransactionItemsWithEagerRelationshipsIsEnabled() throws Exception { + when(transactionItemRepositoryMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restTransactionItemMockMvc.perform(get(ENTITY_API_URL + "?eagerload=true")).andExpect(status().isOk()); + + verify(transactionItemRepositoryMock, times(1)).findAllWithEagerRelationships(any()); + } + + @SuppressWarnings({ "unchecked" }) + void getAllTransactionItemsWithEagerRelationshipsIsNotEnabled() throws Exception { + when(transactionItemRepositoryMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restTransactionItemMockMvc.perform(get(ENTITY_API_URL + "?eagerload=false")).andExpect(status().isOk()); + verify(transactionItemRepositoryMock, times(1)).findAll(any(Pageable.class)); + } + + @Test + @Transactional + void getTransactionItem() throws Exception { + // Initialize the database + insertedTransactionItem = transactionItemRepository.saveAndFlush(transactionItem); + + // Get the transactionItem + restTransactionItemMockMvc + .perform(get(ENTITY_API_URL_ID, transactionItem.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.id").value(transactionItem.getId().intValue())) + .andExpect(jsonPath("$.amount").value(sameNumber(DEFAULT_AMOUNT))) + .andExpect(jsonPath("$.date").value(DEFAULT_DATE.toString())) + .andExpect(jsonPath("$.comment").value(DEFAULT_COMMENT)); + } + + @Test + @Transactional + void getNonExistingTransactionItem() throws Exception { + // Get the transactionItem + restTransactionItemMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound()); + } + + @Test + @Transactional + void putExistingTransactionItem() throws Exception { + // Initialize the database + insertedTransactionItem = transactionItemRepository.saveAndFlush(transactionItem); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the transactionItem + TransactionItem updatedTransactionItem = transactionItemRepository.findById(transactionItem.getId()).orElseThrow(); + // Disconnect from session so that the updates on updatedTransactionItem are not directly saved in db + em.detach(updatedTransactionItem); + updatedTransactionItem.amount(UPDATED_AMOUNT).date(UPDATED_DATE).comment(UPDATED_COMMENT); + + restTransactionItemMockMvc + .perform( + put(ENTITY_API_URL_ID, updatedTransactionItem.getId()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(updatedTransactionItem)) + ) + .andExpect(status().isOk()); + + // Validate the TransactionItem in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertPersistedTransactionItemToMatchAllProperties(updatedTransactionItem); + } + + @Test + @Transactional + void putNonExistingTransactionItem() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transactionItem.setId(longCount.incrementAndGet()); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restTransactionItemMockMvc + .perform( + put(ENTITY_API_URL_ID, transactionItem.getId()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(transactionItem)) + ) + .andExpect(status().isBadRequest()); + + // Validate the TransactionItem in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithIdMismatchTransactionItem() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transactionItem.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restTransactionItemMockMvc + .perform( + put(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(transactionItem)) + ) + .andExpect(status().isBadRequest()); + + // Validate the TransactionItem in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithMissingIdPathParamTransactionItem() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transactionItem.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restTransactionItemMockMvc + .perform( + put(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(transactionItem)) + ) + .andExpect(status().isMethodNotAllowed()); + + // Validate the TransactionItem in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void partialUpdateTransactionItemWithPatch() throws Exception { + // Initialize the database + insertedTransactionItem = transactionItemRepository.saveAndFlush(transactionItem); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the transactionItem using partial update + TransactionItem partialUpdatedTransactionItem = new TransactionItem(); + partialUpdatedTransactionItem.setId(transactionItem.getId()); + + partialUpdatedTransactionItem.amount(UPDATED_AMOUNT).date(UPDATED_DATE); + + restTransactionItemMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedTransactionItem.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedTransactionItem)) + ) + .andExpect(status().isOk()); + + // Validate the TransactionItem in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertTransactionItemUpdatableFieldsEquals( + createUpdateProxyForBean(partialUpdatedTransactionItem, transactionItem), + getPersistedTransactionItem(transactionItem) + ); + } + + @Test + @Transactional + void fullUpdateTransactionItemWithPatch() throws Exception { + // Initialize the database + insertedTransactionItem = transactionItemRepository.saveAndFlush(transactionItem); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the transactionItem using partial update + TransactionItem partialUpdatedTransactionItem = new TransactionItem(); + partialUpdatedTransactionItem.setId(transactionItem.getId()); + + partialUpdatedTransactionItem.amount(UPDATED_AMOUNT).date(UPDATED_DATE).comment(UPDATED_COMMENT); + + restTransactionItemMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedTransactionItem.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedTransactionItem)) + ) + .andExpect(status().isOk()); + + // Validate the TransactionItem in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertTransactionItemUpdatableFieldsEquals( + partialUpdatedTransactionItem, + getPersistedTransactionItem(partialUpdatedTransactionItem) + ); + } + + @Test + @Transactional + void patchNonExistingTransactionItem() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transactionItem.setId(longCount.incrementAndGet()); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restTransactionItemMockMvc + .perform( + patch(ENTITY_API_URL_ID, transactionItem.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(transactionItem)) + ) + .andExpect(status().isBadRequest()); + + // Validate the TransactionItem in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithIdMismatchTransactionItem() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transactionItem.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restTransactionItemMockMvc + .perform( + patch(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(transactionItem)) + ) + .andExpect(status().isBadRequest()); + + // Validate the TransactionItem in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithMissingIdPathParamTransactionItem() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transactionItem.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restTransactionItemMockMvc + .perform( + patch(ENTITY_API_URL) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(transactionItem)) + ) + .andExpect(status().isMethodNotAllowed()); + + // Validate the TransactionItem in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void deleteTransactionItem() throws Exception { + // Initialize the database + insertedTransactionItem = transactionItemRepository.saveAndFlush(transactionItem); + + long databaseSizeBeforeDelete = getRepositoryCount(); + + // Delete the transactionItem + restTransactionItemMockMvc + .perform(delete(ENTITY_API_URL_ID, transactionItem.getId()).with(csrf()).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + // Validate the database contains one less item + assertDecrementedRepositoryCount(databaseSizeBeforeDelete); + } + + protected long getRepositoryCount() { + return transactionItemRepository.count(); + } + + protected void assertIncrementedRepositoryCount(long countBefore) { + assertThat(countBefore + 1).isEqualTo(getRepositoryCount()); + } + + protected void assertDecrementedRepositoryCount(long countBefore) { + assertThat(countBefore - 1).isEqualTo(getRepositoryCount()); + } + + protected void assertSameRepositoryCount(long countBefore) { + assertThat(countBefore).isEqualTo(getRepositoryCount()); + } + + protected TransactionItem getPersistedTransactionItem(TransactionItem transactionItem) { + return transactionItemRepository.findById(transactionItem.getId()).orElseThrow(); + } + + protected void assertPersistedTransactionItemToMatchAllProperties(TransactionItem expectedTransactionItem) { + assertTransactionItemAllPropertiesEquals(expectedTransactionItem, getPersistedTransactionItem(expectedTransactionItem)); + } + + protected void assertPersistedTransactionItemToMatchUpdatableProperties(TransactionItem expectedTransactionItem) { + assertTransactionItemAllUpdatablePropertiesEquals(expectedTransactionItem, getPersistedTransactionItem(expectedTransactionItem)); + } +} diff --git a/src/test/java/com/sasiedzi/event/web/rest/TransactionResourceIT.java b/src/test/java/com/sasiedzi/event/web/rest/TransactionResourceIT.java new file mode 100644 index 0000000..b34aeba --- /dev/null +++ b/src/test/java/com/sasiedzi/event/web/rest/TransactionResourceIT.java @@ -0,0 +1,458 @@ +package com.sasiedzi.event.web.rest; + +import static com.sasiedzi.event.domain.TransactionAsserts.*; +import static com.sasiedzi.event.web.rest.TestUtil.createUpdateProxyForBean; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sasiedzi.event.IntegrationTest; +import com.sasiedzi.event.domain.Transaction; +import com.sasiedzi.event.domain.enumeration.TransactionType; +import com.sasiedzi.event.repository.TransactionRepository; +import jakarta.persistence.EntityManager; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +/** + * Integration tests for the {@link TransactionResource} REST controller. + */ +@IntegrationTest +@ExtendWith(MockitoExtension.class) +@AutoConfigureMockMvc +@WithMockUser +class TransactionResourceIT { + + private static final TransactionType DEFAULT_TYPE = TransactionType.PURCHASE; + private static final TransactionType UPDATED_TYPE = TransactionType.MATCH; + + private static final LocalDate DEFAULT_DATE = LocalDate.ofEpochDay(0L); + private static final LocalDate UPDATED_DATE = LocalDate.now(ZoneId.systemDefault()); + + private static final String DEFAULT_COMMENT = "AAAAAAAAAA"; + private static final String UPDATED_COMMENT = "BBBBBBBBBB"; + + private static final String ENTITY_API_URL = "/api/transactions"; + private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{id}"; + + private static Random random = new Random(); + private static AtomicLong longCount = new AtomicLong(random.nextInt() + (2 * Integer.MAX_VALUE)); + + @Autowired + private ObjectMapper om; + + @Autowired + private TransactionRepository transactionRepository; + + @Mock + private TransactionRepository transactionRepositoryMock; + + @Autowired + private EntityManager em; + + @Autowired + private MockMvc restTransactionMockMvc; + + private Transaction transaction; + + private Transaction insertedTransaction; + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Transaction createEntity() { + return new Transaction().type(DEFAULT_TYPE).date(DEFAULT_DATE).comment(DEFAULT_COMMENT); + } + + /** + * Create an updated entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Transaction createUpdatedEntity() { + return new Transaction().type(UPDATED_TYPE).date(UPDATED_DATE).comment(UPDATED_COMMENT); + } + + @BeforeEach + public void initTest() { + transaction = createEntity(); + } + + @AfterEach + public void cleanup() { + if (insertedTransaction != null) { + transactionRepository.delete(insertedTransaction); + insertedTransaction = null; + } + } + + @Test + @Transactional + void createTransaction() throws Exception { + long databaseSizeBeforeCreate = getRepositoryCount(); + // Create the Transaction + var returnedTransaction = om.readValue( + restTransactionMockMvc + .perform( + post(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(transaction)) + ) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getContentAsString(), + Transaction.class + ); + + // Validate the Transaction in the database + assertIncrementedRepositoryCount(databaseSizeBeforeCreate); + assertTransactionUpdatableFieldsEquals(returnedTransaction, getPersistedTransaction(returnedTransaction)); + + insertedTransaction = returnedTransaction; + } + + @Test + @Transactional + void createTransactionWithExistingId() throws Exception { + // Create the Transaction with an existing ID + transaction.setId(1L); + + long databaseSizeBeforeCreate = getRepositoryCount(); + + // An entity with an existing ID cannot be created, so this API call must fail + restTransactionMockMvc + .perform(post(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(transaction))) + .andExpect(status().isBadRequest()); + + // Validate the Transaction in the database + assertSameRepositoryCount(databaseSizeBeforeCreate); + } + + @Test + @Transactional + void getAllTransactions() throws Exception { + // Initialize the database + insertedTransaction = transactionRepository.saveAndFlush(transaction); + + // Get all the transactionList + restTransactionMockMvc + .perform(get(ENTITY_API_URL + "?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(transaction.getId().intValue()))) + .andExpect(jsonPath("$.[*].type").value(hasItem(DEFAULT_TYPE.toString()))) + .andExpect(jsonPath("$.[*].date").value(hasItem(DEFAULT_DATE.toString()))) + .andExpect(jsonPath("$.[*].comment").value(hasItem(DEFAULT_COMMENT))); + } + + @SuppressWarnings({ "unchecked" }) + void getAllTransactionsWithEagerRelationshipsIsEnabled() throws Exception { + when(transactionRepositoryMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restTransactionMockMvc.perform(get(ENTITY_API_URL + "?eagerload=true")).andExpect(status().isOk()); + + verify(transactionRepositoryMock, times(1)).findAllWithEagerRelationships(any()); + } + + @SuppressWarnings({ "unchecked" }) + void getAllTransactionsWithEagerRelationshipsIsNotEnabled() throws Exception { + when(transactionRepositoryMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restTransactionMockMvc.perform(get(ENTITY_API_URL + "?eagerload=false")).andExpect(status().isOk()); + verify(transactionRepositoryMock, times(1)).findAll(any(Pageable.class)); + } + + @Test + @Transactional + void getTransaction() throws Exception { + // Initialize the database + insertedTransaction = transactionRepository.saveAndFlush(transaction); + + // Get the transaction + restTransactionMockMvc + .perform(get(ENTITY_API_URL_ID, transaction.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.id").value(transaction.getId().intValue())) + .andExpect(jsonPath("$.type").value(DEFAULT_TYPE.toString())) + .andExpect(jsonPath("$.date").value(DEFAULT_DATE.toString())) + .andExpect(jsonPath("$.comment").value(DEFAULT_COMMENT)); + } + + @Test + @Transactional + void getNonExistingTransaction() throws Exception { + // Get the transaction + restTransactionMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound()); + } + + @Test + @Transactional + void putExistingTransaction() throws Exception { + // Initialize the database + insertedTransaction = transactionRepository.saveAndFlush(transaction); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the transaction + Transaction updatedTransaction = transactionRepository.findById(transaction.getId()).orElseThrow(); + // Disconnect from session so that the updates on updatedTransaction are not directly saved in db + em.detach(updatedTransaction); + updatedTransaction.type(UPDATED_TYPE).date(UPDATED_DATE).comment(UPDATED_COMMENT); + + restTransactionMockMvc + .perform( + put(ENTITY_API_URL_ID, updatedTransaction.getId()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(updatedTransaction)) + ) + .andExpect(status().isOk()); + + // Validate the Transaction in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertPersistedTransactionToMatchAllProperties(updatedTransaction); + } + + @Test + @Transactional + void putNonExistingTransaction() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transaction.setId(longCount.incrementAndGet()); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restTransactionMockMvc + .perform( + put(ENTITY_API_URL_ID, transaction.getId()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(transaction)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Transaction in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithIdMismatchTransaction() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transaction.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restTransactionMockMvc + .perform( + put(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(transaction)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Transaction in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithMissingIdPathParamTransaction() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transaction.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restTransactionMockMvc + .perform(put(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(transaction))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the Transaction in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void partialUpdateTransactionWithPatch() throws Exception { + // Initialize the database + insertedTransaction = transactionRepository.saveAndFlush(transaction); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the transaction using partial update + Transaction partialUpdatedTransaction = new Transaction(); + partialUpdatedTransaction.setId(transaction.getId()); + + partialUpdatedTransaction.comment(UPDATED_COMMENT); + + restTransactionMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedTransaction.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedTransaction)) + ) + .andExpect(status().isOk()); + + // Validate the Transaction in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertTransactionUpdatableFieldsEquals( + createUpdateProxyForBean(partialUpdatedTransaction, transaction), + getPersistedTransaction(transaction) + ); + } + + @Test + @Transactional + void fullUpdateTransactionWithPatch() throws Exception { + // Initialize the database + insertedTransaction = transactionRepository.saveAndFlush(transaction); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the transaction using partial update + Transaction partialUpdatedTransaction = new Transaction(); + partialUpdatedTransaction.setId(transaction.getId()); + + partialUpdatedTransaction.type(UPDATED_TYPE).date(UPDATED_DATE).comment(UPDATED_COMMENT); + + restTransactionMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedTransaction.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedTransaction)) + ) + .andExpect(status().isOk()); + + // Validate the Transaction in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertTransactionUpdatableFieldsEquals(partialUpdatedTransaction, getPersistedTransaction(partialUpdatedTransaction)); + } + + @Test + @Transactional + void patchNonExistingTransaction() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transaction.setId(longCount.incrementAndGet()); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restTransactionMockMvc + .perform( + patch(ENTITY_API_URL_ID, transaction.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(transaction)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Transaction in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithIdMismatchTransaction() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transaction.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restTransactionMockMvc + .perform( + patch(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(transaction)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Transaction in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithMissingIdPathParamTransaction() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + transaction.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restTransactionMockMvc + .perform( + patch(ENTITY_API_URL).with(csrf()).contentType("application/merge-patch+json").content(om.writeValueAsBytes(transaction)) + ) + .andExpect(status().isMethodNotAllowed()); + + // Validate the Transaction in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void deleteTransaction() throws Exception { + // Initialize the database + insertedTransaction = transactionRepository.saveAndFlush(transaction); + + long databaseSizeBeforeDelete = getRepositoryCount(); + + // Delete the transaction + restTransactionMockMvc + .perform(delete(ENTITY_API_URL_ID, transaction.getId()).with(csrf()).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + // Validate the database contains one less item + assertDecrementedRepositoryCount(databaseSizeBeforeDelete); + } + + protected long getRepositoryCount() { + return transactionRepository.count(); + } + + protected void assertIncrementedRepositoryCount(long countBefore) { + assertThat(countBefore + 1).isEqualTo(getRepositoryCount()); + } + + protected void assertDecrementedRepositoryCount(long countBefore) { + assertThat(countBefore - 1).isEqualTo(getRepositoryCount()); + } + + protected void assertSameRepositoryCount(long countBefore) { + assertThat(countBefore).isEqualTo(getRepositoryCount()); + } + + protected Transaction getPersistedTransaction(Transaction transaction) { + return transactionRepository.findById(transaction.getId()).orElseThrow(); + } + + protected void assertPersistedTransactionToMatchAllProperties(Transaction expectedTransaction) { + assertTransactionAllPropertiesEquals(expectedTransaction, getPersistedTransaction(expectedTransaction)); + } + + protected void assertPersistedTransactionToMatchUpdatableProperties(Transaction expectedTransaction) { + assertTransactionAllUpdatablePropertiesEquals(expectedTransaction, getPersistedTransaction(expectedTransaction)); + } +} diff --git a/src/test/java/com/sasiedzi/event/web/rest/UserAccountResourceIT.java b/src/test/java/com/sasiedzi/event/web/rest/UserAccountResourceIT.java new file mode 100644 index 0000000..e02d354 --- /dev/null +++ b/src/test/java/com/sasiedzi/event/web/rest/UserAccountResourceIT.java @@ -0,0 +1,450 @@ +package com.sasiedzi.event.web.rest; + +import static com.sasiedzi.event.domain.UserAccountAsserts.*; +import static com.sasiedzi.event.web.rest.TestUtil.createUpdateProxyForBean; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sasiedzi.event.IntegrationTest; +import com.sasiedzi.event.domain.UserAccount; +import com.sasiedzi.event.repository.UserAccountRepository; +import com.sasiedzi.event.repository.UserRepository; +import jakarta.persistence.EntityManager; +import java.util.ArrayList; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +/** + * Integration tests for the {@link UserAccountResource} REST controller. + */ +@IntegrationTest +@ExtendWith(MockitoExtension.class) +@AutoConfigureMockMvc +@WithMockUser +class UserAccountResourceIT { + + private static final String DEFAULT_NAME = "AAAAAAAAAA"; + private static final String UPDATED_NAME = "BBBBBBBBBB"; + + private static final String ENTITY_API_URL = "/api/user-accounts"; + private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{id}"; + + private static Random random = new Random(); + private static AtomicLong longCount = new AtomicLong(random.nextInt() + (2 * Integer.MAX_VALUE)); + + @Autowired + private ObjectMapper om; + + @Autowired + private UserAccountRepository userAccountRepository; + + @Autowired + private UserRepository userRepository; + + @Mock + private UserAccountRepository userAccountRepositoryMock; + + @Autowired + private EntityManager em; + + @Autowired + private MockMvc restUserAccountMockMvc; + + private UserAccount userAccount; + + private UserAccount insertedUserAccount; + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static UserAccount createEntity() { + return new UserAccount().name(DEFAULT_NAME); + } + + /** + * Create an updated entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static UserAccount createUpdatedEntity() { + return new UserAccount().name(UPDATED_NAME); + } + + @BeforeEach + public void initTest() { + userAccount = createEntity(); + } + + @AfterEach + public void cleanup() { + if (insertedUserAccount != null) { + userAccountRepository.delete(insertedUserAccount); + insertedUserAccount = null; + } + userRepository.deleteAll(); + } + + @Test + @Transactional + void createUserAccount() throws Exception { + long databaseSizeBeforeCreate = getRepositoryCount(); + // Create the UserAccount + var returnedUserAccount = om.readValue( + restUserAccountMockMvc + .perform( + post(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userAccount)) + ) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getContentAsString(), + UserAccount.class + ); + + // Validate the UserAccount in the database + assertIncrementedRepositoryCount(databaseSizeBeforeCreate); + assertUserAccountUpdatableFieldsEquals(returnedUserAccount, getPersistedUserAccount(returnedUserAccount)); + + insertedUserAccount = returnedUserAccount; + } + + @Test + @Transactional + void createUserAccountWithExistingId() throws Exception { + // Create the UserAccount with an existing ID + userAccount.setId(1L); + + long databaseSizeBeforeCreate = getRepositoryCount(); + + // An entity with an existing ID cannot be created, so this API call must fail + restUserAccountMockMvc + .perform(post(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userAccount))) + .andExpect(status().isBadRequest()); + + // Validate the UserAccount in the database + assertSameRepositoryCount(databaseSizeBeforeCreate); + } + + @Test + @Transactional + void getAllUserAccounts() throws Exception { + // Initialize the database + insertedUserAccount = userAccountRepository.saveAndFlush(userAccount); + + // Get all the userAccountList + restUserAccountMockMvc + .perform(get(ENTITY_API_URL + "?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(userAccount.getId().intValue()))) + .andExpect(jsonPath("$.[*].name").value(hasItem(DEFAULT_NAME))); + } + + @SuppressWarnings({ "unchecked" }) + void getAllUserAccountsWithEagerRelationshipsIsEnabled() throws Exception { + when(userAccountRepositoryMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restUserAccountMockMvc.perform(get(ENTITY_API_URL + "?eagerload=true")).andExpect(status().isOk()); + + verify(userAccountRepositoryMock, times(1)).findAllWithEagerRelationships(any()); + } + + @SuppressWarnings({ "unchecked" }) + void getAllUserAccountsWithEagerRelationshipsIsNotEnabled() throws Exception { + when(userAccountRepositoryMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restUserAccountMockMvc.perform(get(ENTITY_API_URL + "?eagerload=false")).andExpect(status().isOk()); + verify(userAccountRepositoryMock, times(1)).findAll(any(Pageable.class)); + } + + @Test + @Transactional + void getUserAccount() throws Exception { + // Initialize the database + insertedUserAccount = userAccountRepository.saveAndFlush(userAccount); + + // Get the userAccount + restUserAccountMockMvc + .perform(get(ENTITY_API_URL_ID, userAccount.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.id").value(userAccount.getId().intValue())) + .andExpect(jsonPath("$.name").value(DEFAULT_NAME)); + } + + @Test + @Transactional + void getNonExistingUserAccount() throws Exception { + // Get the userAccount + restUserAccountMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound()); + } + + @Test + @Transactional + void putExistingUserAccount() throws Exception { + // Initialize the database + insertedUserAccount = userAccountRepository.saveAndFlush(userAccount); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the userAccount + UserAccount updatedUserAccount = userAccountRepository.findById(userAccount.getId()).orElseThrow(); + // Disconnect from session so that the updates on updatedUserAccount are not directly saved in db + em.detach(updatedUserAccount); + updatedUserAccount.name(UPDATED_NAME); + + restUserAccountMockMvc + .perform( + put(ENTITY_API_URL_ID, updatedUserAccount.getId()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(updatedUserAccount)) + ) + .andExpect(status().isOk()); + + // Validate the UserAccount in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertPersistedUserAccountToMatchAllProperties(updatedUserAccount); + } + + @Test + @Transactional + void putNonExistingUserAccount() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + userAccount.setId(longCount.incrementAndGet()); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restUserAccountMockMvc + .perform( + put(ENTITY_API_URL_ID, userAccount.getId()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(userAccount)) + ) + .andExpect(status().isBadRequest()); + + // Validate the UserAccount in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithIdMismatchUserAccount() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + userAccount.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restUserAccountMockMvc + .perform( + put(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(userAccount)) + ) + .andExpect(status().isBadRequest()); + + // Validate the UserAccount in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithMissingIdPathParamUserAccount() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + userAccount.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restUserAccountMockMvc + .perform(put(ENTITY_API_URL).with(csrf()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userAccount))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the UserAccount in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void partialUpdateUserAccountWithPatch() throws Exception { + // Initialize the database + insertedUserAccount = userAccountRepository.saveAndFlush(userAccount); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the userAccount using partial update + UserAccount partialUpdatedUserAccount = new UserAccount(); + partialUpdatedUserAccount.setId(userAccount.getId()); + + partialUpdatedUserAccount.name(UPDATED_NAME); + + restUserAccountMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedUserAccount.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedUserAccount)) + ) + .andExpect(status().isOk()); + + // Validate the UserAccount in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertUserAccountUpdatableFieldsEquals( + createUpdateProxyForBean(partialUpdatedUserAccount, userAccount), + getPersistedUserAccount(userAccount) + ); + } + + @Test + @Transactional + void fullUpdateUserAccountWithPatch() throws Exception { + // Initialize the database + insertedUserAccount = userAccountRepository.saveAndFlush(userAccount); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the userAccount using partial update + UserAccount partialUpdatedUserAccount = new UserAccount(); + partialUpdatedUserAccount.setId(userAccount.getId()); + + partialUpdatedUserAccount.name(UPDATED_NAME); + + restUserAccountMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedUserAccount.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedUserAccount)) + ) + .andExpect(status().isOk()); + + // Validate the UserAccount in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertUserAccountUpdatableFieldsEquals(partialUpdatedUserAccount, getPersistedUserAccount(partialUpdatedUserAccount)); + } + + @Test + @Transactional + void patchNonExistingUserAccount() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + userAccount.setId(longCount.incrementAndGet()); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restUserAccountMockMvc + .perform( + patch(ENTITY_API_URL_ID, userAccount.getId()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(userAccount)) + ) + .andExpect(status().isBadRequest()); + + // Validate the UserAccount in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithIdMismatchUserAccount() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + userAccount.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restUserAccountMockMvc + .perform( + patch(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .with(csrf()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(userAccount)) + ) + .andExpect(status().isBadRequest()); + + // Validate the UserAccount in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithMissingIdPathParamUserAccount() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + userAccount.setId(longCount.incrementAndGet()); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restUserAccountMockMvc + .perform( + patch(ENTITY_API_URL).with(csrf()).contentType("application/merge-patch+json").content(om.writeValueAsBytes(userAccount)) + ) + .andExpect(status().isMethodNotAllowed()); + + // Validate the UserAccount in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void deleteUserAccount() throws Exception { + // Initialize the database + insertedUserAccount = userAccountRepository.saveAndFlush(userAccount); + + long databaseSizeBeforeDelete = getRepositoryCount(); + + // Delete the userAccount + restUserAccountMockMvc + .perform(delete(ENTITY_API_URL_ID, userAccount.getId()).with(csrf()).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + // Validate the database contains one less item + assertDecrementedRepositoryCount(databaseSizeBeforeDelete); + } + + protected long getRepositoryCount() { + return userAccountRepository.count(); + } + + protected void assertIncrementedRepositoryCount(long countBefore) { + assertThat(countBefore + 1).isEqualTo(getRepositoryCount()); + } + + protected void assertDecrementedRepositoryCount(long countBefore) { + assertThat(countBefore - 1).isEqualTo(getRepositoryCount()); + } + + protected void assertSameRepositoryCount(long countBefore) { + assertThat(countBefore).isEqualTo(getRepositoryCount()); + } + + protected UserAccount getPersistedUserAccount(UserAccount userAccount) { + return userAccountRepository.findById(userAccount.getId()).orElseThrow(); + } + + protected void assertPersistedUserAccountToMatchAllProperties(UserAccount expectedUserAccount) { + assertUserAccountAllPropertiesEquals(expectedUserAccount, getPersistedUserAccount(expectedUserAccount)); + } + + protected void assertPersistedUserAccountToMatchUpdatableProperties(UserAccount expectedUserAccount) { + assertUserAccountAllUpdatablePropertiesEquals(expectedUserAccount, getPersistedUserAccount(expectedUserAccount)); + } +}