transaction edit

This commit is contained in:
2024-11-19 11:49:37 +01:00
parent c56a7e6dc4
commit 5e75b53d11
10 changed files with 165 additions and 12 deletions
@@ -39,7 +39,7 @@ public class Transaction implements Serializable {
private Event event; private Event event;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "transaction", cascade = CascadeType.ALL, orphanRemoval = true) @OneToMany(fetch = FetchType.LAZY, mappedBy = "transaction", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIgnoreProperties(value = { "userAccount", "transaction", "event", "registration" }, allowSetters = true) @JsonIgnoreProperties(value = { "transaction", "event", "registration" }, allowSetters = true)
private Set<TransactionItem> transactionItems = new HashSet<>(); private Set<TransactionItem> transactionItems = new HashSet<>();
// jhipster-needle-entity-add-field - JHipster will add fields here // jhipster-needle-entity-add-field - JHipster will add fields here
@@ -30,7 +30,7 @@ public class TransactionItem implements Serializable {
@Column(name = "locked") @Column(name = "locked")
private Boolean locked; private Boolean locked;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.EAGER)
@JsonIgnoreProperties(value = { "users", "transactionItems" }, allowSetters = true) @JsonIgnoreProperties(value = { "users", "transactionItems" }, allowSetters = true)
private UserAccount userAccount; private UserAccount userAccount;
@@ -35,7 +35,9 @@ public interface TransactionRepository extends JpaRepository<Transaction, Long>
@Query("select transaction from Transaction transaction left join fetch transaction.event") @Query("select transaction from Transaction transaction left join fetch transaction.event")
List<Transaction> findAllWithToOneRelationships(); List<Transaction> findAllWithToOneRelationships();
@Query("select transaction from Transaction transaction left join fetch transaction.event where transaction.id =:id") @Query(
"select transaction from Transaction transaction left join fetch transaction.event left join fetch transaction.transactionItems where transaction.id =:id"
)
Optional<Transaction> findOneWithToOneRelationships(@Param("id") Long id); Optional<Transaction> findOneWithToOneRelationships(@Param("id") Long id);
@Query( @Query(
@@ -272,6 +272,10 @@ public class TransactionResource {
public ResponseEntity<Transaction> getTransaction(@PathVariable("id") Long id) { public ResponseEntity<Transaction> getTransaction(@PathVariable("id") Long id) {
LOG.debug("REST request to get Transaction : {}", id); LOG.debug("REST request to get Transaction : {}", id);
Optional<Transaction> transaction = transactionRepository.findOneWithEagerRelationships(id); Optional<Transaction> transaction = transactionRepository.findOneWithEagerRelationships(id);
// if (transaction.isPresent()) {
// transaction.get().getTransactionItems().stream().sorted();
// transaction.get().getTransactionItems().sort(Comparator.comparing(item -> item.getUserAccount().getName()));
// }
return ResponseUtil.wrapOrNotFound(transaction); return ResponseUtil.wrapOrNotFound(transaction);
} }
@@ -11,7 +11,8 @@ export default defineComponent({
setup() { setup() {
const transactionService = inject('transactionService', () => new TransactionService()); const transactionService = inject('transactionService', () => new TransactionService());
const alertService = inject('alertService', () => useAlertService(), true); const alertService = inject('alertService', () => useAlertService(), true);
const hasAnyAuthorityValues: Ref<any> = ref({});
const accountService = inject<AccountService>('accountService');
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
@@ -34,8 +35,19 @@ export default defineComponent({
return { return {
alertService, alertService,
transaction, transaction,
accountService,
hasAnyAuthorityValues,
previousState, previousState,
}; };
}, },
methods: {
hasAnyAuthority(authorities: any): boolean {
this.accountService.hasAnyAuthorityAndCheckAuth(authorities).then(value => {
if (this.hasAnyAuthorityValues[authorities] !== value) {
this.hasAnyAuthorityValues = { ...this.hasAnyAuthorityValues, [authorities]: value };
}
});
return this.hasAnyAuthorityValues[authorities] ?? false;
},
},
}); });
@@ -1,6 +1,6 @@
<template> <template>
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-8"> <div class="col-12">
<div v-if="transaction"> <div v-if="transaction">
<h2 class="jh-entity-heading" data-cy="transactionDetailsHeading"><span>Transaction</span> {{ transaction.id }}</h2> <h2 class="jh-entity-heading" data-cy="transactionDetailsHeading"><span>Transaction</span> {{ transaction.id }}</h2>
<dl class="row jh-entity-details"> <dl class="row jh-entity-details">
@@ -40,11 +40,41 @@
custom custom
v-slot="{ navigate }" v-slot="{ navigate }"
> >
<button @click="navigate" class="btn btn-primary"> <button @click="navigate" class="btn btn-primary" v-if="hasAnyAuthority('ROLE_ADMIN')">
<font-awesome-icon icon="pencil-alt"></font-awesome-icon>&nbsp;<span>Edit</span> <font-awesome-icon icon="pencil-alt"></font-awesome-icon>&nbsp;<span>Edit</span>
</button> </button>
</router-link> </router-link>
</div> </div>
<div class="form-group">
<div class="table-responsive">
<table class="table table-striped" aria-describedby="event.registrations">
<thead>
<tr>
<th scope="col"><span>#</span></th>
<th scope="col"><span>Account</span></th>
<th scope="col"><span>Amount</span></th>
<th scope="col"><span>Comment</span></th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in transaction.transactionItems" :key="index" class="transaction-item">
<td>
{{ index }}
</td>
<td>
{{ item.userAccount?.name }}
</td>
<td>
{{ item.amount }}
</td>
<td>
{{ item.comment }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -10,6 +10,8 @@ import EventService from '@/entities/event/event.service';
import { type IEvent } from '@/shared/model/event.model'; import { type IEvent } from '@/shared/model/event.model';
import { type ITransaction, Transaction } from '@/shared/model/transaction.model'; import { type ITransaction, Transaction } from '@/shared/model/transaction.model';
import { TransactionType } from '@/shared/model/enumerations/transaction-type.model'; import { TransactionType } from '@/shared/model/enumerations/transaction-type.model';
import { type IUserAccount } from '@/shared/model/user-account.model';
import UserAccountService from '@/entities/user-account/user-account.service';
export default defineComponent({ export default defineComponent({
compatConfig: { MODE: 3 }, compatConfig: { MODE: 3 },
@@ -20,7 +22,11 @@ export default defineComponent({
const transaction: Ref<ITransaction> = ref(new Transaction()); const transaction: Ref<ITransaction> = ref(new Transaction());
transaction.value.transactionItems = [];
const dictUserAccounts = ref([]) as Ref<IUserAccount[]>;
const eventService = inject('eventService', () => new EventService()); const eventService = inject('eventService', () => new EventService());
const userAccountService = inject('userAccountService', () => new UserAccountService());
const events: Ref<IEvent[]> = ref([]); const events: Ref<IEvent[]> = ref([]);
const transactionTypeValues: Ref<string[]> = ref(Object.keys(TransactionType)); const transactionTypeValues: Ref<string[]> = ref(Object.keys(TransactionType));
@@ -34,13 +40,37 @@ export default defineComponent({
const retrieveTransaction = async transactionId => { const retrieveTransaction = async transactionId => {
try { try {
const res2 = await userAccountService().retrieve();
console.log('got accounts' + res2);
dictUserAccounts.value = res2.data;
const res = await transactionService().find(transactionId); const res = await transactionService().find(transactionId);
transaction.value = res; transaction.value = res;
// console.log('len'+transaction.value.transactionItems?.length);
// console.log('len'+dictUserAccounts.value.length);
// console.log('id'+transaction.value.transactionItems[0].userAccount.id);
// console.log('id'+(dictUserAccounts.value.find(account => account.id === transaction.value.transactionItems[0].userAccount.id) || null));
// transaction.value.transactionItems[0].userAccount = dictUserAccounts.value.find(account => account.id === transaction.value.transactionItems[0].userAccount.id) || null;
transaction.value.transactionItems.forEach((item, index) => {
const matchingAccount = dictUserAccounts.value.find(account => account.id === item.userAccount.id);
transaction.value.transactionItems[index].userAccount = matchingAccount || null;
});
} catch (error) { } catch (error) {
alertService.showHttpError(error.response); alertService.showHttpError(error.response);
} }
}; };
// const retrieveUserAccounts = async () => {
// try {
// const res = await userAccountService().retrieve();
// console.log('got accounts'+ res);
// dictUserAccounts.value = res.data;
// } catch (error) {
// alertService.showHttpError(error.response);
// }
// };
//
// retrieveUserAccounts();
if (route.params?.transactionId) { if (route.params?.transactionId) {
retrieveTransaction(route.params.transactionId); retrieveTransaction(route.params.transactionId);
} }
@@ -61,10 +91,36 @@ export default defineComponent({
date: {}, date: {},
comment: {}, comment: {},
event: {}, event: {},
// transactionItems: {
// $each: {
// amount: { required: validations.required, minValue: validations.minValue(0.01) },
// comment: {},
// locked: {},
// userAccount: {},
// },
// },
}; };
const v$ = useVuelidate(validationRules, transaction as any); const v$ = useVuelidate(validationRules, transaction as any);
v$.value.$validate(); v$.value.$validate();
const addTransactionItem = () => {
transaction.value.transactionItems.push({
amount: 0,
comment: '',
locked: false,
userAccount: null,
});
};
const removeTransactionItem = (index: number) => {
transaction.value.transactionItems.splice(index, 1);
};
const calculateUnsettledBalance = (): string => {
const balance = transaction.value.transactionItems.reduce((sum, item) => sum + item.amount, 0);
return balance.toFixed(2);
};
return { return {
transactionService, transactionService,
alertService, alertService,
@@ -75,9 +131,12 @@ export default defineComponent({
currentLanguage, currentLanguage,
events, events,
v$, v$,
dictUserAccounts,
addTransactionItem,
removeTransactionItem,
calculateUnsettledBalance,
}; };
}, },
created(): void {},
methods: { methods: {
save(): void { save(): void {
this.isSaving = true; this.isSaving = true;
@@ -76,6 +76,52 @@
</option> </option>
</select> </select>
</div> </div>
<div class="form-group">
<button type="button" @click="addTransactionItem" class="btn btn-success">Add Transaction Item</button>
<div class="table-responsive">
<table class="table table-striped" aria-describedby="event.registrations">
<thead>
<tr>
<th scope="col"><span></span></th>
<th scope="col"><span>Locked</span></th>
<th scope="col"><span>Account</span></th>
<th scope="col"><span>Amount</span></th>
<th scope="col"><span>Comment</span></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in transaction.transactionItems" :key="index" class="transaction-item">
<td>
{{ item.id }}
</td>
<td>
<input type="checkbox" v-model="item.locked" class="form-check-input" />
</td>
<td>
<select v-model="item.userAccount" class="form-control" v-if="dictUserAccounts.length">
<option v-for="account in dictUserAccounts" :key="account.id" :value="account">{{ account.name }}</option>
</select>
</td>
<td>
<input type="number" v-model="item.amount" step="0.01" class="form-control" />
</td>
<td>
<input type="text" v-model="item.comment" class="form-control" placeholder="Comment" />
</td>
<td>
<button type="button" @click="removeTransactionItem(index)" class="btn btn-danger">Remove</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="form-group">
<label>Unsettled Balance:</label>
<input type="text" class="form-control" :value="calculateUnsettledBalance()" readonly />
</div>
</div> </div>
<div> <div>
<button type="button" id="cancel-save" data-cy="entityCreateCancelButton" class="btn btn-secondary" @click="previousState()"> <button type="button" id="cancel-save" data-cy="entityCreateCancelButton" class="btn btn-secondary" @click="previousState()">
@@ -33,7 +33,7 @@
<th scope="row"><span>Comment</span></th> <th scope="row"><span>Comment</span></th>
<th scope="row"><span>Event</span></th> <th scope="row"><span>Event</span></th>
<th scope="row" v-for="item in transactions[0].items"> <th scope="row" v-for="item in transactions[0].transactionItems">
<span>{{ item.userAccount?.name }}</span> <span>{{ item.userAccount?.name }}</span>
</th> </th>
<th scope="row"></th> <th scope="row"></th>
@@ -54,7 +54,7 @@
}}</router-link> }}</router-link>
</div> </div>
</td> </td>
<td v-for="item in transaction.items">{{ item.amount }}</td> <td v-for="item in transaction.transactionItems">{{ item.amount }}</td>
<td class="text-right"> <td class="text-right">
<div class="btn-group"> <div class="btn-group">
<router-link :to="{ name: 'TransactionView', params: { transactionId: transaction.id } }" custom v-slot="{ navigate }"> <router-link :to="{ name: 'TransactionView', params: { transactionId: transaction.id } }" custom v-slot="{ navigate }">
@@ -8,7 +8,7 @@ export interface ITransaction {
date?: Date | null; date?: Date | null;
comment?: string | null; comment?: string | null;
event?: IEvent | null; event?: IEvent | null;
items?: ITransactionItem[] | []; transactionItems?: ITransactionItem[] | [];
} }
export class Transaction implements ITransaction { export class Transaction implements ITransaction {
@@ -18,7 +18,7 @@ export class Transaction implements ITransaction {
public date?: Date | null, public date?: Date | null,
public comment?: string | null, public comment?: string | null,
public event?: IEvent | null, public event?: IEvent | null,
public items?: ITransactionItem[] | [], public transactionItems?: ITransactionItem[] | [],
) {} ) {}
} }