feat(MemberOrder): add budget field to MemberOrder and MemberOrderHistory models
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 41s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 41s
- Introduced a new budget field in both MemberOrder and MemberOrderHistory models to track budget amounts. - Updated memberOrderService to handle budget in serialization and normalization processes. - Enhanced OrdersPanel component to include budget input and display in the UI. - Added German localization for the new budget term to ensure consistency across languages.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE `member_orders`
|
||||
ADD COLUMN `budget` DECIMAL(10,2) NOT NULL DEFAULT 0.00 AFTER `paid_amount`;
|
||||
|
||||
ALTER TABLE `member_order_history`
|
||||
ADD COLUMN `budget` DECIMAL(10,2) NOT NULL DEFAULT 0.00 AFTER `paid_amount`;
|
||||
@@ -49,6 +49,11 @@ const MemberOrder = sequelize.define('MemberOrder', {
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
field: 'paid_amount'
|
||||
},
|
||||
budget: {
|
||||
type: DataTypes.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
}
|
||||
}, {
|
||||
underscored: true,
|
||||
|
||||
@@ -47,6 +47,11 @@ const MemberOrderHistory = sequelize.define('MemberOrderHistory', {
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
field: 'paid_amount'
|
||||
},
|
||||
budget: {
|
||||
type: DataTypes.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
}
|
||||
}, {
|
||||
underscored: true,
|
||||
|
||||
@@ -20,10 +20,12 @@ const serializeOrder = (order) => {
|
||||
const plain = typeof order.toJSON === 'function' ? order.toJSON() : { ...order };
|
||||
const cost = normalizeAmount(plain.cost);
|
||||
const paidAmount = normalizeAmount(plain.paidAmount);
|
||||
const budget = normalizeAmount(plain.budget);
|
||||
return {
|
||||
...plain,
|
||||
cost,
|
||||
paidAmount,
|
||||
budget,
|
||||
openAmount: Math.max(0, Number((cost - paidAmount).toFixed(2)))
|
||||
};
|
||||
};
|
||||
@@ -32,10 +34,12 @@ const serializeHistoryEntry = (entry) => {
|
||||
const plain = typeof entry.toJSON === 'function' ? entry.toJSON() : { ...entry };
|
||||
const cost = normalizeAmount(plain.cost);
|
||||
const paidAmount = normalizeAmount(plain.paidAmount);
|
||||
const budget = normalizeAmount(plain.budget);
|
||||
return {
|
||||
...plain,
|
||||
cost,
|
||||
paidAmount,
|
||||
budget,
|
||||
openAmount: Math.max(0, Number((cost - paidAmount).toFixed(2)))
|
||||
};
|
||||
};
|
||||
@@ -64,7 +68,8 @@ class MemberOrderService {
|
||||
status: order.status,
|
||||
changedAt: new Date(),
|
||||
cost: normalizeAmount(order.cost),
|
||||
paidAmount: normalizeAmount(order.paidAmount)
|
||||
paidAmount: normalizeAmount(order.paidAmount),
|
||||
budget: normalizeAmount(order.budget)
|
||||
}, transaction ? { transaction } : undefined);
|
||||
}
|
||||
|
||||
@@ -105,6 +110,7 @@ class MemberOrderService {
|
||||
const status = ORDER_STATUSES.includes(payload?.status) ? payload.status : 'requested';
|
||||
const cost = normalizeAmount(payload?.cost);
|
||||
const paidAmount = normalizeAmount(payload?.paidAmount);
|
||||
const budget = normalizeAmount(payload?.budget);
|
||||
|
||||
if (!item) {
|
||||
return {
|
||||
@@ -121,7 +127,8 @@ class MemberOrderService {
|
||||
orderDate: new Date(),
|
||||
statusDate: new Date(),
|
||||
cost,
|
||||
paidAmount
|
||||
paidAmount,
|
||||
budget
|
||||
});
|
||||
|
||||
await this._createHistorySnapshot(order);
|
||||
@@ -171,6 +178,7 @@ class MemberOrderService {
|
||||
const nextStatus = payload?.status && ORDER_STATUSES.includes(payload.status) ? payload.status : order.status;
|
||||
const nextCost = payload?.cost != null ? normalizeAmount(payload.cost) : normalizeAmount(order.cost);
|
||||
const nextPaidAmount = payload?.paidAmount != null ? normalizeAmount(payload.paidAmount) : normalizeAmount(order.paidAmount);
|
||||
const nextBudget = payload?.budget != null ? normalizeAmount(payload.budget) : normalizeAmount(order.budget);
|
||||
|
||||
if (nextItem && nextItem !== order.item) {
|
||||
order.item = nextItem;
|
||||
@@ -189,6 +197,10 @@ class MemberOrderService {
|
||||
order.paidAmount = nextPaidAmount;
|
||||
changed = true;
|
||||
}
|
||||
if (nextBudget !== normalizeAmount(order.budget)) {
|
||||
order.budget = nextBudget;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
const existing = await this.getMemberOrders(userToken, clubId, memberId);
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
<span>{{ $t('orders.paid') }}</span>
|
||||
<input v-model="newOrder.paidAmount" type="number" min="0" step="0.01">
|
||||
</label>
|
||||
<label>
|
||||
<span>{{ $t('orders.budget') }}</span>
|
||||
<input v-model="newOrder.budget" type="number" min="0" step="0.01">
|
||||
</label>
|
||||
<label>
|
||||
<span>{{ $t('orders.status') }}</span>
|
||||
<select v-model="newOrder.status">
|
||||
@@ -75,6 +79,7 @@
|
||||
<th>{{ $t('orders.statusDate') }}</th>
|
||||
<th>{{ $t('orders.cost') }}</th>
|
||||
<th>{{ $t('orders.paid') }}</th>
|
||||
<th>{{ $t('orders.budget') }}</th>
|
||||
<th>{{ $t('orders.open') }}</th>
|
||||
<th>{{ $t('orders.history') }}</th>
|
||||
<th>{{ $t('common.save') }}</th>
|
||||
@@ -102,6 +107,9 @@
|
||||
<td>
|
||||
<input v-model="order.draftPaidAmount" type="number" min="0" step="0.01" class="orders-inline-input orders-inline-input-number">
|
||||
</td>
|
||||
<td>
|
||||
<input v-model="order.draftBudget" type="number" min="0" step="0.01" class="orders-inline-input orders-inline-input-number">
|
||||
</td>
|
||||
<td>{{ formatCurrency(calculateOpenAmount(order)) }}</td>
|
||||
<td>
|
||||
<details class="orders-history-details">
|
||||
@@ -110,7 +118,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) }}</span>
|
||||
<span>{{ formatCurrency(entry.cost) }} / {{ formatCurrency(entry.paidAmount) }} / {{ formatCurrency(entry.budget) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
@@ -181,7 +189,8 @@ export default {
|
||||
item: '',
|
||||
status: 'requested',
|
||||
cost: '',
|
||||
paidAmount: ''
|
||||
paidAmount: '',
|
||||
budget: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -251,7 +260,8 @@ export default {
|
||||
draftItem: order.item || '',
|
||||
draftStatus: order.status || 'requested',
|
||||
draftCost: String(normalizeAmount(order.cost)),
|
||||
draftPaidAmount: String(normalizeAmount(order.paidAmount))
|
||||
draftPaidAmount: String(normalizeAmount(order.paidAmount)),
|
||||
draftBudget: String(normalizeAmount(order.budget))
|
||||
};
|
||||
},
|
||||
async loadOrders() {
|
||||
@@ -285,7 +295,8 @@ export default {
|
||||
item: this.newOrder.item.trim(),
|
||||
status: this.newOrder.status,
|
||||
cost: normalizeAmount(this.newOrder.cost),
|
||||
paidAmount: normalizeAmount(this.newOrder.paidAmount)
|
||||
paidAmount: normalizeAmount(this.newOrder.paidAmount),
|
||||
budget: normalizeAmount(this.newOrder.budget)
|
||||
});
|
||||
if (response.data?.order) {
|
||||
this.orders.unshift(this.hydrateOrder(response.data.order));
|
||||
@@ -293,7 +304,8 @@ export default {
|
||||
item: '',
|
||||
status: 'requested',
|
||||
cost: '',
|
||||
paidAmount: ''
|
||||
paidAmount: '',
|
||||
budget: ''
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -306,7 +318,8 @@ export default {
|
||||
return order.draftItem !== (order.item || '')
|
||||
|| order.draftStatus !== order.status
|
||||
|| normalizeAmount(order.draftCost) !== normalizeAmount(order.cost)
|
||||
|| normalizeAmount(order.draftPaidAmount) !== normalizeAmount(order.paidAmount);
|
||||
|| normalizeAmount(order.draftPaidAmount) !== normalizeAmount(order.paidAmount)
|
||||
|| normalizeAmount(order.draftBudget) !== normalizeAmount(order.budget);
|
||||
},
|
||||
async saveOrder(order) {
|
||||
this.savingOrderIds.push(order.id);
|
||||
@@ -316,7 +329,8 @@ export default {
|
||||
item: order.draftItem,
|
||||
status: order.draftStatus,
|
||||
cost: normalizeAmount(order.draftCost),
|
||||
paidAmount: normalizeAmount(order.draftPaidAmount)
|
||||
paidAmount: normalizeAmount(order.draftPaidAmount),
|
||||
budget: normalizeAmount(order.draftBudget)
|
||||
});
|
||||
if (response.data?.order) {
|
||||
const updated = this.hydrateOrder(response.data.order);
|
||||
|
||||
@@ -457,6 +457,7 @@
|
||||
"statusHandedOver": "Artikel ausgehändigt",
|
||||
"cost": "Kosten",
|
||||
"paid": "Bezahlt",
|
||||
"budget": "Budget",
|
||||
"open": "Noch offen",
|
||||
"history": "Verlauf",
|
||||
"orderDate": "Erfasst am",
|
||||
|
||||
Reference in New Issue
Block a user