transaction fix
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
package com.sasiedzi.event.domain;
|
package com.sasiedzi.event.domain;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import jakarta.validation.constraints.*;
|
import jakarta.validation.constraints.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -92,6 +94,77 @@ public class Event implements Serializable {
|
|||||||
this.date = date;
|
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() {
|
public Integer getPlayersLimit() {
|
||||||
return this.playersLimit;
|
return this.playersLimit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.sasiedzi.event.domain.enumeration.TransactionType;
|
|||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -80,6 +81,33 @@ public class Transaction implements Serializable {
|
|||||||
return this;
|
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) {
|
public void setType(TransactionType type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.sasiedzi.event.repository;
|
package com.sasiedzi.event.repository;
|
||||||
|
|
||||||
|
import com.sasiedzi.event.domain.Charge;
|
||||||
import com.sasiedzi.event.domain.Event;
|
import com.sasiedzi.event.domain.Event;
|
||||||
|
import java.util.List;
|
||||||
import org.springframework.data.jpa.repository.*;
|
import org.springframework.data.jpa.repository.*;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,4 +12,7 @@ import org.springframework.stereotype.Repository;
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Repository
|
@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);
|
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.
|
* Delete the event by id.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ public class TransactionService {
|
|||||||
setBeneficiary(newTransaction);
|
setBeneficiary(newTransaction);
|
||||||
newTransaction.setEvent(existing.getEvent());
|
newTransaction.setEvent(existing.getEvent());
|
||||||
calculateBalances(existing.getTransactionItems().stream().map(TransactionItem::getUserAccount).toList());
|
calculateBalances(existing.getTransactionItems().stream().map(TransactionItem::getUserAccount).toList());
|
||||||
|
Set<Long> processedAccounts = new HashSet<>();
|
||||||
for (TransactionItem item : existing.getTransactionItems()) {
|
for (TransactionItem item : existing.getTransactionItems()) {
|
||||||
BigDecimal accountBalance = item.getUserAccount().getBalance();
|
BigDecimal accountBalance = item.getUserAccount().getBalance();
|
||||||
if (accountBalance == null) {
|
if (accountBalance == null) {
|
||||||
@@ -125,7 +126,8 @@ public class TransactionService {
|
|||||||
accountBalance.compareTo(BigDecimal.ZERO) < 0 &&
|
accountBalance.compareTo(BigDecimal.ZERO) < 0 &&
|
||||||
!Account.Skarbiec.toString().equals(item.getUserAccount().getName()) &&
|
!Account.Skarbiec.toString().equals(item.getUserAccount().getName()) &&
|
||||||
!Account.Boisko.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();
|
TransactionItem newItem = new TransactionItem();
|
||||||
newItem.setAmount(accountBalance.negate());
|
newItem.setAmount(accountBalance.negate());
|
||||||
@@ -135,6 +137,7 @@ public class TransactionService {
|
|||||||
newItem.setRegistration(item.getRegistration());
|
newItem.setRegistration(item.getRegistration());
|
||||||
newItem.setComment(item.getComment());
|
newItem.setComment(item.getComment());
|
||||||
newTransaction.getTransactionItems().add(newItem);
|
newTransaction.getTransactionItems().add(newItem);
|
||||||
|
processedAccounts.add(item.getUserAccount().getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newTransaction;
|
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)}.
|
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the event, or with status {@code 404 (Not Found)}.
|
||||||
*/
|
*/
|
||||||
@GetMapping("/{id}")
|
@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);
|
LOG.debug("REST request to get Event : {}", id);
|
||||||
Optional<Event> event = eventService.findOne(id);
|
return eventService.getEventForRegistration(id);
|
||||||
return ResponseUtil.wrapOrNotFound(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
:to="{ name: 'RegistrationCreateForEvent', params: { eventId: event.id } }"
|
:to="{ name: 'RegistrationCreateForEvent', params: { eventId: event.id } }"
|
||||||
custom
|
custom
|
||||||
v-slot="{ navigate }"
|
v-slot="{ navigate }"
|
||||||
v-if="isCurrentEvent"
|
v-if="event.active"
|
||||||
>
|
>
|
||||||
<button @click="navigate" class="btn btn-primary">
|
<button @click="navigate" class="btn btn-primary">
|
||||||
<font-awesome-icon icon="plus"></font-awesome-icon> <span>Dołącz do wydarzenia</span>
|
<font-awesome-icon icon="plus"></font-awesome-icon> <span>Dołącz do wydarzenia</span>
|
||||||
@@ -55,28 +55,7 @@
|
|||||||
<!-- <font-awesome-icon icon="plus"></font-awesome-icon> <span>Opłać boisko</span>-->
|
<!-- <font-awesome-icon icon="plus"></font-awesome-icon> <span>Opłać boisko</span>-->
|
||||||
<!-- </button>-->
|
<!-- </button>-->
|
||||||
<!-- </router-link>-->
|
<!-- </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> <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">
|
<div class="table-responsive" v-if="event.registrations && event.registrations.length > 0">
|
||||||
<table class="table table-striped" aria-describedby="event.registrations">
|
<table class="table table-striped" aria-describedby="event.registrations">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -181,6 +160,71 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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> <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> <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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" src="./event-details.component.ts"></script>
|
<script lang="ts" src="./event-details.component.ts"></script>
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
:to="{ name: 'TransactionEdit', params: { transactionId: transaction.id } }"
|
:to="{ name: 'TransactionEdit', params: { transactionId: transaction.id } }"
|
||||||
custom
|
custom
|
||||||
v-slot="{ navigate }"
|
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">
|
<button @click="navigate" class="btn btn-primary btn-sm edit" data-cy="entityEditButton">
|
||||||
<font-awesome-icon icon="pencil-alt"></font-awesome-icon>
|
<font-awesome-icon icon="pencil-alt"></font-awesome-icon>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { IRegistration } from '@/shared/model/registration.model';
|
import type { IRegistration } from '@/shared/model/registration.model';
|
||||||
|
import type { ITransaction } from '@/shared/model/transaction.model';
|
||||||
|
|
||||||
export interface IEvent {
|
export interface IEvent {
|
||||||
id?: number;
|
id?: number;
|
||||||
@@ -8,6 +9,13 @@ export interface IEvent {
|
|||||||
cost?: number | null;
|
cost?: number | null;
|
||||||
comment?: string | null;
|
comment?: string | null;
|
||||||
registrations?: IRegistration[];
|
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 {
|
export class Event implements IEvent {
|
||||||
@@ -19,5 +27,12 @@ export class Event implements IEvent {
|
|||||||
public cost?: number | null,
|
public cost?: number | null,
|
||||||
public comment?: string | null,
|
public comment?: string | null,
|
||||||
public registrations?: IRegistration[],
|
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[] | [];
|
transactionItems?: ITransactionItem[] | [];
|
||||||
items?: ITransactionItem[] | [];
|
items?: ITransactionItem[] | [];
|
||||||
beneficiary?: IUserAccount | null;
|
beneficiary?: IUserAccount | null;
|
||||||
|
editable?: boolean | false;
|
||||||
|
deletable?: boolean | false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Transaction implements ITransaction {
|
export class Transaction implements ITransaction {
|
||||||
@@ -22,6 +24,8 @@ export class Transaction implements ITransaction {
|
|||||||
public event?: IEvent | null,
|
public event?: IEvent | null,
|
||||||
public items?: ITransactionItem[] | [],
|
public items?: ITransactionItem[] | [],
|
||||||
public beneficiary?: IUserAccount | null,
|
public beneficiary?: IUserAccount | null,
|
||||||
|
public editable?: boolean | false,
|
||||||
|
public deletable?: boolean | false,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user