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/.yo-rc.json b/.yo-rc.json index d83b33c..c6fd6c0 100644 --- a/.yo-rc.json +++ b/.yo-rc.json @@ -15,7 +15,7 @@ "enableHibernateCache": null, "enableSwaggerCodegen": false, "enableTranslation": false, - "entities": ["Charge", "Event", "Registration"], + "entities": ["Charge", "Event", "Registration", "Transaction"], "feignClient": null, "jhipsterVersion": "8.7.2", "lastLiquibaseTimestamp": 1730797803000, 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 2a6083d..5556c4b 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 = { "user", "event" }, allowSetters = true) private Set registrations = new HashSet<>(); + @OneToMany(fetch = FetchType.LAZY, mappedBy = "event") + @JsonIgnoreProperties(value = { "event" }, 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 70aa207..a75be2f 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..7e61fc5 --- /dev/null +++ b/src/main/java/com/sasiedzi/event/domain/Transaction.java @@ -0,0 +1,135 @@ +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; + + // 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; + } + + // 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/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/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/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/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..a176e96 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20241113134007_added_entity_Transaction.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..edaca56 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20241113134007_added_entity_constraints_Transaction.xml @@ -0,0 +1,20 @@ + + + + + + + + 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/master.xml b/src/main/resources/config/liquibase/master.xml index 512c6fb..bb8f9ce 100644 --- a/src/main/resources/config/liquibase/master.xml +++ b/src/main/resources/config/liquibase/master.xml @@ -14,9 +14,11 @@ + + 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..da3ac67 100644 --- a/src/main/webapp/app/entities/entities-menu.vue +++ b/src/main/webapp/app/entities/entities-menu.vue @@ -12,6 +12,10 @@ Registration + + + Transaction + diff --git a/src/main/webapp/app/entities/entities.component.ts b/src/main/webapp/app/entities/entities.component.ts index 8593ff2..e9a1453 100644 --- a/src/main/webapp/app/entities/entities.component.ts +++ b/src/main/webapp/app/entities/entities.component.ts @@ -3,6 +3,7 @@ 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 UserService from '@/entities/user/user.service'; // jhipster-needle-add-entity-service-to-entities-component-import - JHipster will import entities services here @@ -14,6 +15,7 @@ export default defineComponent({ provide('chargeService', () => new ChargeService()); provide('eventService', () => new EventService()); provide('registrationService', () => new RegistrationService()); + provide('transactionService', () => new TransactionService()); // 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..68cc773 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 = { 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..8d5932a --- /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 = { type: 'BBBBBB', date: dayjs(currentDate).format(DATE_FORMAT), ...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/router/entities.ts b/src/main/webapp/app/router/entities.ts index 7bc13ad..3c05bfd 100644 --- a/src/main/webapp/app/router/entities.ts +++ b/src/main/webapp/app/router/entities.ts @@ -15,6 +15,10 @@ 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'); + // jhipster-needle-add-entity-to-router-import - JHipster will import entities to the router here export default { @@ -93,6 +97,30 @@ 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] }, + }, // 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/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..29d6c5c --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/TransactionAsserts.java @@ -0,0 +1,66 @@ +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())); + } +} 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..26c20da --- /dev/null +++ b/src/test/java/com/sasiedzi/event/domain/TransactionTest.java @@ -0,0 +1,37 @@ +package com.sasiedzi.event.domain; + +import static com.sasiedzi.event.domain.EventTestSamples.*; +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(); + } +} 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/web/rest/ChargeResourceIT.java b/src/test/java/com/sasiedzi/event/web/rest/ChargeResourceIT.java index c7398f5..9553082 100644 --- a/src/test/java/com/sasiedzi/event/web/rest/ChargeResourceIT.java +++ b/src/test/java/com/sasiedzi/event/web/rest/ChargeResourceIT.java @@ -358,7 +358,7 @@ class ChargeResourceIT { Charge partialUpdatedCharge = new Charge(); partialUpdatedCharge.setId(charge.getId()); - partialUpdatedCharge.chargeDate(UPDATED_CHARGE_DATE).amount(UPDATED_AMOUNT); + partialUpdatedCharge.amount(UPDATED_AMOUNT); restChargeMockMvc .perform( 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..79713e2 100644 --- a/src/test/java/com/sasiedzi/event/web/rest/EventResourceIT.java +++ b/src/test/java/com/sasiedzi/event/web/rest/EventResourceIT.java @@ -328,8 +328,6 @@ class EventResourceIT { Event partialUpdatedEvent = new Event(); partialUpdatedEvent.setId(event.getId()); - partialUpdatedEvent.name(UPDATED_NAME).date(UPDATED_DATE).playersLimit(UPDATED_PLAYERS_LIMIT); - restEventMockMvc .perform( patch(ENTITY_API_URL_ID, partialUpdatedEvent.getId()) 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..b240a74 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.dateTime(UPDATED_DATE_TIME).playerName(UPDATED_PLAYER_NAME); restRegistrationMockMvc .perform( 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..e88d59a --- /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.type(UPDATED_TYPE).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)); + } +}