Implemented Event Budget
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
<script setup>
|
||||
import Modal from "../../../Views/Components/Modal.vue";
|
||||
import {reactive, ref} from "vue";
|
||||
import AmountInput from "../../../Views/Components/AmountInput.vue";
|
||||
import {toast} from "vue3-toastify";
|
||||
import {useAjax} from "../../../../resources/js/components/ajaxHandler.js";
|
||||
|
||||
const { request } = useAjax()
|
||||
|
||||
const props = defineProps({
|
||||
showAddEstimate: Boolean,
|
||||
type: String,
|
||||
title: String,
|
||||
costUnitId: Number,
|
||||
amount: Number,
|
||||
amount_type: String,
|
||||
estimateId: Number,
|
||||
description: String,
|
||||
})
|
||||
|
||||
console.log(props)
|
||||
|
||||
const form = reactive({
|
||||
amount_type: props.amount_type,
|
||||
amount: props.amount,
|
||||
description: props.description,
|
||||
|
||||
})
|
||||
|
||||
async function save() {
|
||||
const data = await request('/api/v1/budget/' + props.costUnitId + '/save-estimate', {
|
||||
method: "POST",
|
||||
body: {
|
||||
estimateId: props.estimateId,
|
||||
amount_type: form.amount_type,
|
||||
amount: form.amount,
|
||||
description: form.description,
|
||||
estimateType: props.type,
|
||||
}
|
||||
});
|
||||
|
||||
if (data.status === 'success') {
|
||||
toast.success(data.message);
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
}
|
||||
|
||||
emit('closeAddEstimate')
|
||||
}
|
||||
|
||||
const emit = defineEmits(['closeAddEstimate'])
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal
|
||||
:show="showAddEstimate"
|
||||
@close="emit('closeAddEstimate')"
|
||||
title="Ausgabenschätzung hinzufügen"
|
||||
width="600px"
|
||||
>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Kostenstelle</th>
|
||||
<td>{{title}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Verwendungszweck</th>
|
||||
<td><input type="text" v-model="form.description" style="width: 250px;" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Betrag</th>
|
||||
<td><AmountInput v-model="form.amount" style="width: 100px;" /> Euro</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Kostentyp</th>
|
||||
<td style="vertical-align: top;">
|
||||
<input type="radio" v-model="form.amount_type" value="flat"
|
||||
id="amount_type_flat" />
|
||||
<label for="amount_type_flat">Pauschal</label><br />
|
||||
|
||||
<input type="radio" v-model="form.amount_type" value="per_person" id="amount_type_per_person" />
|
||||
<label for="amount_type_per_person">Pro Person</label><br />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input type="button" value="Speichern" class="button" @click="save" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -3,189 +3,115 @@ import {createApp, ref} from 'vue'
|
||||
import LoadingModal from "../../../Views/Components/LoadingModal.vue";
|
||||
import { useAjax } from "../../../../resources/js/components/ajaxHandler.js";
|
||||
import {toast} from "vue3-toastify";
|
||||
import AddOrUpdateEstimate from "./AddOrUpdateEstimate.vue";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: [Array, Object],
|
||||
default: () => []
|
||||
},
|
||||
|
||||
deep_jump_id: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
|
||||
deep_jump_id_sub: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
})
|
||||
|
||||
const showInvoiceList = ref(false)
|
||||
const invoices = ref(null)
|
||||
const current_cost_unit = ref(null)
|
||||
const showLoading = ref(false)
|
||||
const show_invoice = ref(false)
|
||||
const invoice = ref(null)
|
||||
const localData = ref(props.data)
|
||||
|
||||
const show_cost_unit = ref(false)
|
||||
const showTreasurers = ref(false)
|
||||
const costUnit = ref(null)
|
||||
const showAddEstimate = ref(false)
|
||||
const estimateId = ref(null)
|
||||
const description = ref(null)
|
||||
const amount = ref(null)
|
||||
const amountType = ref(null)
|
||||
|
||||
const { data, loading, error, request, download } = useAjax()
|
||||
|
||||
async function costUnitDetails(costUnitId) {
|
||||
const data = await request('/api/v1/cost-unit/' + costUnitId + '/details', {
|
||||
method: "GET",
|
||||
});
|
||||
async function reload() {
|
||||
const url = "/api/v1/budget/" + props.data.costUnitId + "/list/" + props.data.estimateType
|
||||
try {
|
||||
const response = await fetch(url, { method: 'GET' })
|
||||
if (!response.ok) throw new Error('Fehler beim Laden')
|
||||
|
||||
showLoading.value = false;
|
||||
|
||||
if (data.status === 'success') {
|
||||
costUnit.value = data.costUnit
|
||||
show_cost_unit.value = true
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
const result = await response.json()
|
||||
localData.value = result
|
||||
} catch (err) {
|
||||
console.error('Error fetching estimates:', err)
|
||||
}
|
||||
}
|
||||
|
||||
async function editTreasurers(costUnitId) {
|
||||
const data = await request('/api/v1/cost-unit/' + costUnitId + '/treasurers', {
|
||||
async function openAddEstimate() {
|
||||
estimateId.value = 0
|
||||
amount.value = 0.00
|
||||
amountType.value = 'flat'
|
||||
description.value = ''
|
||||
showAddEstimate.value = true
|
||||
}
|
||||
|
||||
async function openEditEstimate(localEstimateId, localDescription, localAmount, localAmountType, localEstimateType) {
|
||||
estimateId.value = localEstimateId
|
||||
description.value = localDescription
|
||||
amount.value = localAmount
|
||||
amountType.value = localAmountType
|
||||
console.log(localEstimateId, localDescription, localAmount, localAmountType, localEstimateType)
|
||||
console.log(estimateId.value, description.value, amount.value, amountType.value, localEstimateType)
|
||||
showAddEstimate.value = true
|
||||
}
|
||||
|
||||
async function deleteEstimate(currentEstimateId) {
|
||||
const data = await request('/api/v1/budget/' + props.data.costUnitId + '/' + currentEstimateId + '/delete', {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
showLoading.value = false;
|
||||
|
||||
if (data.status === 'success') {
|
||||
costUnit.value = data.costUnit
|
||||
showTreasurers.value = true
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
function loadInvoices(cost_unit_id) {
|
||||
window.location.href = '/cost-unit/' + cost_unit_id;
|
||||
}
|
||||
|
||||
async function denyNewRequests(costUnitId) {
|
||||
changeCostUnitState(costUnitId, 'close');
|
||||
}
|
||||
|
||||
|
||||
async function archiveCostUnit(costUnitId) {
|
||||
changeCostUnitState(costUnitId, 'archive');
|
||||
}
|
||||
|
||||
|
||||
async function allowNewRequests(costUnitId) {
|
||||
changeCostUnitState(costUnitId, 'open');
|
||||
}
|
||||
|
||||
|
||||
async function changeCostUnitState(costUnitId, endPoint) {
|
||||
showLoading.value = true;
|
||||
const data = await request('/api/v1/cost-unit/' + costUnitId + '/' + endPoint, {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
showLoading.value = false;
|
||||
if (data.status === 'success') {
|
||||
toast.success(data.message);
|
||||
document.getElementById('costUnitBox_' + costUnitId).style.display = 'none';
|
||||
reload()
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function exportPayouts(costUnitId) {
|
||||
showLoading.value = true;
|
||||
|
||||
|
||||
const response = await fetch('/api/v1/core/retrieve-global-data');
|
||||
const data = await response.json();
|
||||
const exportUrl = '/api/v1/cost-unit/' + costUnitId + '/export-payouts';
|
||||
|
||||
try {
|
||||
if (data.tenant.download_exports) {
|
||||
const response = await fetch(exportUrl, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Fehler beim Export (ZIP)');
|
||||
|
||||
const blob = await response.blob();
|
||||
const downloadUrl = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.style.display = "none";
|
||||
a.href = downloadUrl;
|
||||
a.download = "Abrechnungen-Sippenstunden.zip";
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
setTimeout(() => {
|
||||
window.URL.revokeObjectURL(downloadUrl);
|
||||
document.body.removeChild(a);
|
||||
}, 100);
|
||||
} else {
|
||||
const response = await request(exportUrl, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
toast.success(response.message);
|
||||
}
|
||||
showLoading.value = false;
|
||||
|
||||
} catch (err) {
|
||||
showLoading.value = false;
|
||||
toast.error('Beim Export der Abrechnungen ist ein Fehler aufgetreten.');
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="props.data.estimates && props.data.estimates.length > 0">
|
||||
<div v-if="localData.estimates && localData.estimates.length > 0">
|
||||
<h2>{{ props.data.title }}</h2>
|
||||
<span v-for="estimate in props.data.estimates">
|
||||
<table style="width: 100%">
|
||||
|
||||
<h3>Gesamtkosten: {{ localData.totalAmountString }}</h3>
|
||||
<span v-for="estimate in localData.estimates">
|
||||
<table style="width: 100%;">
|
||||
<tr><th style="width: 200px;">
|
||||
{{ estimate.title }}
|
||||
</th>
|
||||
<td>{{ estimate.totalAmountString }}</td>
|
||||
<td>{{ estimate.singleAmountString }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
Bearbeiten
|
||||
Löschen
|
||||
<td style="padding-bottom: 30px">
|
||||
<label class="link" style="font-size: 10pt; margin-right: 20px;" @click="openEditEstimate(estimate.id, estimate.title, estimate.amountValue, estimate.amountType, props.data.estimateType)">Bearbeiten</label>
|
||||
<label class="link" style="font-size: 10pt; margin-right: 20px; color: #ff0000;" @click="deleteEstimate(estimate.id)">Löschen</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</span>
|
||||
|
||||
<CostUnitDetails :data="costUnit" :showCostUnit="show_cost_unit" v-if="show_cost_unit" @close="show_cost_unit = false" />
|
||||
<Treasurers :data="costUnit" :showTreasurers="showTreasurers" v-if="showTreasurers" @closeTreasurers="showTreasurers = false" />
|
||||
</div>
|
||||
|
||||
<div v-else-if="showInvoiceList">
|
||||
<invoices :data="invoices" :load_invoice_id="props.deep_jump_id_sub" :cost_unit_id="current_cost_unit" />
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<strong style="width: 100%; text-align: center; display: block; margin-top: 20px;">
|
||||
Noch keine geschätzten Ausgaben vorhanden
|
||||
</strong>
|
||||
</div>
|
||||
<label class="link">
|
||||
<label class="link" @click="openAddEstimate()">
|
||||
Hinzufügen
|
||||
</label>
|
||||
<LoadingModal :show="showLoading" />
|
||||
<AddOrUpdateEstimate
|
||||
:amount="amount"
|
||||
:amount_type="amountType"
|
||||
:description="description"
|
||||
:estimateId="estimateId"
|
||||
:costUnitId="props.data.costUnitId"
|
||||
:title="props.data.title"
|
||||
:type="props.data.estimateType"
|
||||
:showAddEstimate="showAddEstimate"
|
||||
|
||||
v-if="showAddEstimate"
|
||||
@closeAddEstimate="showAddEstimate = false; reload()" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user