transaction fix

This commit is contained in:
2024-12-02 19:20:03 +01:00
parent 4819d318b8
commit 88c4c2ce70
10 changed files with 219 additions and 29 deletions
@@ -1,11 +1,13 @@
package com.sasiedzi.event.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.Set;
@@ -92,6 +94,77 @@ public class Event implements Serializable {
this.date = date;
}
// @Transient
// private Boolean editable;
@JsonProperty("editable")
public Boolean getEditable() {
if (date == null) return false;
LocalDate currentDate = LocalDate.now();
long daysBetween = ChronoUnit.DAYS.between(this.date, currentDate);
return daysBetween <= 7;
}
@Transient
private Long chargeTransactionId;
@JsonProperty("chargeTransactionId")
public Long getChargeTransactionId() {
return chargeTransactionId;
}
public void setChargeTransactionId(Long chargeTransactionId) {
this.chargeTransactionId = chargeTransactionId;
}
// public void setEditable(Boolean editable) {
// this.editable = editable;
// }
@Transient
private Boolean charged;
@JsonProperty("charged")
public Boolean getCharged() {
return charged;
}
public void setCharged(Boolean charged) {
this.charged = charged;
}
@Transient
private Boolean current;
@JsonProperty("current")
public Boolean getCurrent() {
return current;
}
public void setCurrent(Boolean current) {
this.current = current;
}
@JsonProperty("active")
public Boolean getActive() {
if (date == null) return false;
LocalDate currentDate = LocalDate.now();
long daysBetween = ChronoUnit.DAYS.between(this.date, currentDate);
return daysBetween <= 0;
}
// @Transient
// private Boolean deletable;
@JsonProperty("deletable")
public Boolean getDeletable() {
return getEditable();
}
// public void setDeletable(Boolean deletable) {
// this.deletable = deletable;
// }
public Integer getPlayersLimit() {
return this.playersLimit;
}
@@ -6,6 +6,7 @@ import com.sasiedzi.event.domain.enumeration.TransactionType;
import jakarta.persistence.*;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.Set;
@@ -80,6 +81,33 @@ public class Transaction implements Serializable {
return this;
}
// @Transient
// private Boolean editable;
@JsonProperty("editable")
public Boolean getEditable() {
if (date == null) return false;
LocalDate currentDate = LocalDate.now();
long daysBetween = ChronoUnit.DAYS.between(this.date, currentDate);
return daysBetween <= 7;
}
// public void setEditable(Boolean editable) {
// this.editable = editable;
// }
// @Transient
// private Boolean deletable;
@JsonProperty("deletable")
public Boolean getDeletable() {
return getEditable();
}
// public void setDeletable(Boolean deletable) {
// this.deletable = deletable;
// }
public void setType(TransactionType type) {
this.type = type;
}
@@ -1,7 +1,10 @@
package com.sasiedzi.event.repository;
import com.sasiedzi.event.domain.Charge;
import com.sasiedzi.event.domain.Event;
import java.util.List;
import org.springframework.data.jpa.repository.*;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
/**
@@ -9,4 +12,7 @@ import org.springframework.stereotype.Repository;
*/
@SuppressWarnings("unused")
@Repository
public interface EventRepository extends JpaRepository<Event, Long> {}
public interface EventRepository extends JpaRepository<Event, Long> {
@Query("select event from Event event left join fetch event.transactions where event.id =:id")
Event findByIdWithTransactions(@Param("id") Long id);
}
@@ -126,6 +126,24 @@ public class EventService {
return eventRepository.findById(id);
}
@Transactional(readOnly = true)
public Event getEventForRegistration(Long id) {
LOG.debug("Request to get Event : {}", id);
Event event = eventRepository.findByIdWithTransactions(id);
event.setCurrent(id.equals(getCurrentEventId()));
event.setCharged(event.getTransactions().stream().anyMatch(t -> TransactionType.FIELDPAYMENT.equals(t.getType())));
event.setChargeTransactionId(
event
.getTransactions()
.stream()
.filter(t -> TransactionType.MATCH.equals(t.getType()))
.map(Transaction::getId)
.findFirst()
.orElse(null)
);
return event;
}
/**
* Delete the event by id.
*
@@ -116,6 +116,7 @@ public class TransactionService {
setBeneficiary(newTransaction);
newTransaction.setEvent(existing.getEvent());
calculateBalances(existing.getTransactionItems().stream().map(TransactionItem::getUserAccount).toList());
Set<Long> processedAccounts = new HashSet<>();
for (TransactionItem item : existing.getTransactionItems()) {
BigDecimal accountBalance = item.getUserAccount().getBalance();
if (accountBalance == null) {
@@ -125,7 +126,8 @@ public class TransactionService {
accountBalance.compareTo(BigDecimal.ZERO) < 0 &&
!Account.Skarbiec.toString().equals(item.getUserAccount().getName()) &&
!Account.Boisko.toString().equals(item.getUserAccount().getName()) &&
!Account.Counter.toString().equals(item.getUserAccount().getName())
!Account.Counter.toString().equals(item.getUserAccount().getName()) &&
!processedAccounts.contains(item.getUserAccount().getId())
) {
TransactionItem newItem = new TransactionItem();
newItem.setAmount(accountBalance.negate());
@@ -135,6 +137,7 @@ public class TransactionService {
newItem.setRegistration(item.getRegistration());
newItem.setComment(item.getComment());
newTransaction.getTransactionItems().add(newItem);
processedAccounts.add(item.getUserAccount().getId());
}
}
return newTransaction;
@@ -160,10 +160,9 @@ public class EventResource {
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the event, or with status {@code 404 (Not Found)}.
*/
@GetMapping("/{id}")
public ResponseEntity<Event> getEvent(@PathVariable("id") Long id) {
public Event getEvent(@PathVariable("id") Long id) {
LOG.debug("REST request to get Event : {}", id);
Optional<Event> event = eventService.findOne(id);
return ResponseUtil.wrapOrNotFound(event);
return eventService.getEventForRegistration(id);
}
/**
@@ -39,7 +39,7 @@
:to="{ name: 'RegistrationCreateForEvent', params: { eventId: event.id } }"
custom
v-slot="{ navigate }"
v-if="isCurrentEvent"
v-if="event.active"
>
<button @click="navigate" class="btn btn-primary">
<font-awesome-icon icon="plus"></font-awesome-icon>&nbsp;<span>Dołącz do wydarzenia</span>
@@ -55,28 +55,7 @@
<!-- <font-awesome-icon icon="plus"></font-awesome-icon>&nbsp;<span>Opłać boisko</span>-->
<!-- </button>-->
<!-- </router-link>-->
<router-link
v-if="event.id"
:to="{ name: 'TransactionFieldPayment', params: { paymentForFieldByEventId: event.id } }"
custom
v-slot="{ navigate }"
><!-- <router-link
v-if="transaction.id"
:to="{ name: 'TransactionCreateOpposite', params: { opposingTransactionId: transaction.id } }"
custom
v-slot="{ navigate }"
>-->
<button @click="navigate" class="btn btn-primary" v-if="hasAnyAuthority(['ROLE_ADMIN', 'ROLE_COUNTER'])">
<font-awesome-icon icon="pencil-alt"></font-awesome-icon>&nbsp;<span>Dodaj płatność za boisko</span>
</button>
</router-link>
<button
class="btn btn-primary float-right"
v-if="isCurrentEvent && hasAnyAuthority(['ROLE_ADMIN', 'ROLE_COUNTER'])"
@click="settle()"
>
<font-awesome-icon icon="sync"></font-awesome-icon> <span>Rozlicz wydarzenie</span>
</button>
<div class="table-responsive" v-if="event.registrations && event.registrations.length > 0">
<table class="table table-striped" aria-describedby="event.registrations">
<thead>
@@ -181,6 +160,71 @@
</div>
</div>
</div>
<button
class="btn btn-primary float-right"
v-if="(event.editable && hasAnyAuthority(['ROLE_COUNTER'])) || hasAnyAuthority(['ROLE_ADMIN'])"
@click="settle()"
>
<font-awesome-icon icon="sync"></font-awesome-icon> <span>Rozlicz wydarzenie</span>
</button>
<router-link
v-if="event.id && event.charged == false"
:to="{ name: 'TransactionFieldPayment', params: { paymentForFieldByEventId: event.id } }"
custom
v-slot="{ navigate }"
><!-- <router-link
v-if="transaction.id"
:to="{ name: 'TransactionCreateOpposite', params: { opposingTransactionId: transaction.id } }"
custom
v-slot="{ navigate }"
>-->
<button @click="navigate" class="btn btn-primary" v-if="hasAnyAuthority(['ROLE_ADMIN', 'ROLE_COUNTER'])">
<font-awesome-icon icon="pencil-alt"></font-awesome-icon>&nbsp;<span>Dodaj płatność za boisko</span>
</button>
</router-link>
<router-link
v-if="event.transactions?.length > 0 && event.editable"
:to="{ name: 'TransactionPaymentsForTransaction', params: { paymentsForTransactionId: event.chargeTransactionId } }"
custom
v-slot="{ navigate }"
><!-- <router-link
v-if="transaction.id"
:to="{ name: 'TransactionCreateOpposite', params: { opposingTransactionId: transaction.id } }"
custom
v-slot="{ navigate }"
>-->
<button @click="navigate" class="btn btn-primary" v-if="hasAnyAuthority(['ROLE_ADMIN', 'ROLE_COUNTER'])">
<font-awesome-icon icon="pencil-alt"></font-awesome-icon>&nbsp;<span>Dodaj wpłaty na konto</span>
</button>
</router-link>
<div class="table-responsive" v-if="event.transactions && event.transactions.length > 0">
Rozliczenie:
<table class="table table-striped" aria-describedby="transactions">
<thead>
<tr>
<!-- <th/>-->
<!-- <th/>-->
<!-- <th/>-->
<th />
</tr>
</thead>
<tbody>
<tr v-for="transaction in event.transactions" :key="transaction.id" data-cy="entityTable">
<td>
<router-link :to="{ name: 'TransactionView', params: { transactionId: transaction.id } }"
>{{ transaction.date }} {{ transaction.type }}
</router-link>
<div v-if="transaction.comment">{{ transaction.comment }}</div>
</td>
<!-- <td>{{ transaction.type }}</td>-->
<!-- <td>{{ transaction.date }}</td>-->
<!-- <td>{{ transaction.comment }}</td>-->
</tr>
</tbody>
</table>
</div>
</template>
<script lang="ts" src="./event-details.component.ts"></script>
@@ -94,7 +94,7 @@
:to="{ name: 'TransactionEdit', params: { transactionId: transaction.id } }"
custom
v-slot="{ navigate }"
v-if="hasAnyAuthority(['ROLE_ADMIN', 'ROLE_COUNTER'])"
v-if="(transaction.editable && hasAnyAuthority(['ROLE_COUNTER'])) || hasAnyAuthority(['ROLE_ADMIN'])"
>
<button @click="navigate" class="btn btn-primary btn-sm edit" data-cy="entityEditButton">
<font-awesome-icon icon="pencil-alt"></font-awesome-icon>
@@ -1,4 +1,5 @@
import type { IRegistration } from '@/shared/model/registration.model';
import type { ITransaction } from '@/shared/model/transaction.model';
export interface IEvent {
id?: number;
@@ -8,6 +9,13 @@ export interface IEvent {
cost?: number | null;
comment?: string | null;
registrations?: IRegistration[];
transactions?: ITransaction[];
editable?: boolean | false;
deletable?: boolean | false;
charged?: boolean | false;
active?: boolean | false;
current?: boolean | false;
chargeTransactionId?: number | null;
}
export class Event implements IEvent {
@@ -19,5 +27,12 @@ export class Event implements IEvent {
public cost?: number | null,
public comment?: string | null,
public registrations?: IRegistration[],
public transactions?: ITransaction[],
public editable?: boolean | false,
public deletable?: boolean | false,
public charged?: boolean | false,
public active?: boolean | false,
public current?: boolean | false,
public chargeTransactionId?: number | null,
) {}
}
@@ -11,6 +11,8 @@ export interface ITransaction {
transactionItems?: ITransactionItem[] | [];
items?: ITransactionItem[] | [];
beneficiary?: IUserAccount | null;
editable?: boolean | false;
deletable?: boolean | false;
}
export class Transaction implements ITransaction {
@@ -22,6 +24,8 @@ export class Transaction implements ITransaction {
public event?: IEvent | null,
public items?: ITransactionItem[] | [],
public beneficiary?: IUserAccount | null,
public editable?: boolean | false,
public deletable?: boolean | false,
) {}
}