feat(MemberOrder, MemberOrderHistory, MemberOrderService, OrdersPanel): add paidConfirmed field and update related logic
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 42s

- Introduced a new boolean field `paidConfirmed` in MemberOrder and MemberOrderHistory models to track payment confirmation status.
- Updated serialization functions in MemberOrderService to include `paidConfirmed` in order and history entries.
- Enhanced OrdersPanel component to allow users to set and display the `paidConfirmed` status for orders.
- Added localization support for the new `paidConfirmed` label in German.
- Adjusted related logic to ensure proper handling of the `paidConfirmed` state throughout the application.
This commit is contained in:
Torsten Schulz (local)
2026-05-06 09:05:28 +02:00
parent 4bef76d6dd
commit 95bfbf86a4
6 changed files with 70 additions and 12 deletions

View File

@@ -53,6 +53,10 @@
<span>{{ $t('orders.budget') }}</span>
<input v-model="newOrder.budget" type="number" min="0" step="0.01">
</label>
<label class="orders-checkbox-label">
<span>{{ $t('orders.paidConfirmed') }}</span>
<input v-model="newOrder.paidConfirmed" type="checkbox">
</label>
<label>
<span>{{ $t('orders.status') }}</span>
<select v-model="newOrder.status">
@@ -88,6 +92,7 @@
<th>{{ $t('orders.statusDate') }}</th>
<th>{{ $t('orders.cost') }}</th>
<th>{{ $t('orders.paid') }}</th>
<th>{{ $t('orders.paidConfirmed') }}</th>
<th>{{ $t('orders.budget') }}</th>
<th>{{ $t('orders.open') }}</th>
<th>{{ $t('orders.history') }}</th>
@@ -116,6 +121,9 @@
<td>
<input v-model="order.draftPaidAmount" type="number" min="0" step="0.01" class="orders-inline-input orders-inline-input-number">
</td>
<td class="orders-cell-center">
<input v-model="order.draftPaidConfirmed" type="checkbox">
</td>
<td>
<input v-model="order.draftBudget" type="number" min="0" step="0.01" class="orders-inline-input orders-inline-input-number">
</td>
@@ -127,7 +135,7 @@
<div v-for="entry in order.historyEntries || []" :key="entry.id" class="orders-history-entry">
<strong>{{ statusLabel(entry.status) }}</strong>
<span>{{ formatDateTime(entry.changedAt) }}</span>
<span>{{ formatCurrency(entry.cost) }} / {{ formatCurrency(entry.paidAmount) }} / {{ formatCurrency(entry.budget) }}</span>
<span>{{ formatCurrency(entry.cost) }} / {{ formatCurrency(entry.paidAmount) }} / {{ entry.paidConfirmed ? 'bezahlt' : 'offen' }} / {{ formatCurrency(entry.budget) }}</span>
</div>
</div>
</details>
@@ -209,7 +217,8 @@ export default {
status: 'requested',
cost: '',
paidAmount: '',
budget: ''
budget: '',
paidConfirmed: false
}
};
},
@@ -237,12 +246,9 @@ export default {
if (this.clubFilter && String(order.clubId) !== String(this.clubFilter)) {
return false;
}
const cost = normalizeAmount(order.cost);
const paidAmount = normalizeAmount(order.paidAmount);
const openAmount = Math.max(0, Number((cost - paidAmount).toFixed(2)));
const isPaid = cost > 0 && openAmount <= 0;
const isPaid = Boolean(order.paidConfirmed);
const isHandedOver = order.status === 'handed_over';
const isCompleted = isPaid || isHandedOver;
const isCompleted = isPaid && isHandedOver;
if (!this.showCompleted && isCompleted) {
return false;
}
@@ -296,6 +302,7 @@ export default {
draftStatus: order.status || 'requested',
draftCost: String(normalizeAmount(order.cost)),
draftPaidAmount: String(normalizeAmount(order.paidAmount)),
draftPaidConfirmed: Boolean(order.paidConfirmed),
draftBudget: String(normalizeAmount(order.budget))
};
},
@@ -331,7 +338,8 @@ export default {
status: this.newOrder.status,
cost: normalizeAmount(this.newOrder.cost),
paidAmount: normalizeAmount(this.newOrder.paidAmount),
budget: normalizeAmount(this.newOrder.budget)
budget: normalizeAmount(this.newOrder.budget),
paidConfirmed: Boolean(this.newOrder.paidConfirmed)
});
if (response.data?.order) {
this.orders.unshift(this.hydrateOrder(response.data.order));
@@ -340,7 +348,8 @@ export default {
status: 'requested',
cost: '',
paidAmount: '',
budget: ''
budget: '',
paidConfirmed: false
};
}
} catch (error) {
@@ -354,6 +363,7 @@ export default {
|| order.draftStatus !== order.status
|| normalizeAmount(order.draftCost) !== normalizeAmount(order.cost)
|| normalizeAmount(order.draftPaidAmount) !== normalizeAmount(order.paidAmount)
|| Boolean(order.draftPaidConfirmed) !== Boolean(order.paidConfirmed)
|| normalizeAmount(order.draftBudget) !== normalizeAmount(order.budget);
},
async saveOrder(order) {
@@ -365,7 +375,8 @@ export default {
status: order.draftStatus,
cost: normalizeAmount(order.draftCost),
paidAmount: normalizeAmount(order.draftPaidAmount),
budget: normalizeAmount(order.draftBudget)
budget: normalizeAmount(order.draftBudget),
paidConfirmed: Boolean(order.draftPaidConfirmed)
});
if (response.data?.order) {
const updated = this.hydrateOrder(response.data.order);
@@ -434,6 +445,23 @@ export default {
color: var(--text-color);
}
.orders-checkbox-label {
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: 0.35rem;
}
.orders-checkbox-label input[type='checkbox'],
.orders-cell-center input[type='checkbox'] {
width: 1.05rem;
height: 1.05rem;
}
.orders-cell-center {
text-align: center;
}
.orders-filters {
justify-content: flex-start;
flex: 1;

View File

@@ -462,6 +462,7 @@
"statusHandedOver": "Artikel ausgehändigt",
"cost": "Kosten",
"paid": "Bezahlt",
"paidConfirmed": "Hat bezahlt",
"budget": "Budget",
"open": "Noch offen",
"history": "Verlauf",