diff --git a/app/Domains/Budget/Actions/CreateEstimate/CreateEstimateAction.php b/app/Domains/Budget/Actions/CreateEstimate/CreateEstimateAction.php new file mode 100644 index 0000000..0f0cf21 --- /dev/null +++ b/app/Domains/Budget/Actions/CreateEstimate/CreateEstimateAction.php @@ -0,0 +1,50 @@ +response = new CreateEstimateResponse(); + + $amount = []; + switch ($this->request->amountType) { + case 'flat': + $amount['flat_amount'] = $this->request->amount; + break; + case 'per_person': + $amount['amount_by_user'] = $this->request->amount; + break; + } + + if ($this->request->estimateId === 0) { + $estimate = CostUnitEstimate::create(array_merge([ + 'tenant' => app('tenant')->slug, + 'cost_unit_id' => $this->request->costUnit->id, + 'type' => $this->request->estimateType, + 'description' => $this->request->description, + ], $amount)); + } else { + $estimate = CostUnitEstimate::find($this->request->estimateId); + $estimate->update(array_merge([ + 'tenant' => app('tenant')->slug, + 'cost_unit_id' => $this->request->costUnit->id, + 'type' => $this->request->estimateType, + 'description' => $this->request->description, + ], $amount)); + } + + if ($estimate !== null) { + $this->response->estimateId = $estimate->id; + $this->response->success = true; + } + + return $this->response; + } +} diff --git a/app/Domains/Budget/Actions/CreateEstimate/CreateEstimateRequest.php b/app/Domains/Budget/Actions/CreateEstimate/CreateEstimateRequest.php new file mode 100644 index 0000000..c34d618 --- /dev/null +++ b/app/Domains/Budget/Actions/CreateEstimate/CreateEstimateRequest.php @@ -0,0 +1,19 @@ +success = false; + $this->estimateId = null; + } +} diff --git a/app/Domains/Budget/Actions/DeleteEstimate/DeleteEstimateAction.php b/app/Domains/Budget/Actions/DeleteEstimate/DeleteEstimateAction.php new file mode 100644 index 0000000..0f8e87e --- /dev/null +++ b/app/Domains/Budget/Actions/DeleteEstimate/DeleteEstimateAction.php @@ -0,0 +1,16 @@ +request->estimate->delete(); + $response->success = true; + return $response; + } +} diff --git a/app/Domains/Budget/Actions/DeleteEstimate/DeleteEstimateRequest.php b/app/Domains/Budget/Actions/DeleteEstimate/DeleteEstimateRequest.php new file mode 100644 index 0000000..85a6476 --- /dev/null +++ b/app/Domains/Budget/Actions/DeleteEstimate/DeleteEstimateRequest.php @@ -0,0 +1,12 @@ +success = false; + } +} diff --git a/app/Domains/Budget/Controllers/DeleteController.php b/app/Domains/Budget/Controllers/DeleteController.php new file mode 100644 index 0000000..612f7de --- /dev/null +++ b/app/Domains/Budget/Controllers/DeleteController.php @@ -0,0 +1,43 @@ +estimates->getById($estimateId); + + if ($estimate === null) { + return response()->json([ + 'status' => 'error', + 'message' => 'Estimate not found' + ], 404); + } + + $deleteEstimateResponse = + new DeleteEstimateAction(request: new DeleteEstimateRequest($estimate) + )->execute(); + + if ($deleteEstimateResponse->success) { + return response()->json([ + 'status' => 'success', + 'message' => 'Der Eintrag wurde erfolgreich gelöscht.' + ]); + } else { + return response()->json([ + 'status' => 'error', + 'message' => 'Beim Löschen des Eintrags ist ein Fehler aufgetreten.' + ]); + } + } +} diff --git a/app/Domains/Budget/Controllers/ListController.php b/app/Domains/Budget/Controllers/ListController.php index 7d0741e..e93602b 100644 --- a/app/Domains/Budget/Controllers/ListController.php +++ b/app/Domains/Budget/Controllers/ListController.php @@ -17,7 +17,9 @@ class ListController extends CommonController 'status' => 'success', 'costUnitId' => $costUnitId, 'title' => InvoiceType::where('slug', $estimateType)->first()->name, + 'estimateType' => $estimateType, 'estimates' => $estimates, + 'totalAmountString' => $this->estimates->getTotalAmount($costUnit, $estimateType)->toString(), ]); } diff --git a/app/Domains/Budget/Controllers/SaveController.php b/app/Domains/Budget/Controllers/SaveController.php new file mode 100644 index 0000000..72c4e1b --- /dev/null +++ b/app/Domains/Budget/Controllers/SaveController.php @@ -0,0 +1,47 @@ +costUnits->getById($costUnitId); + + if ($costUnit === null) { + return response()->json([ + 'status' => 'error', + 'message' => 'Cost unit not found' + ], 404); + } + + $createCostUniResponse = + new CreateEstimateAction(request: new CreateEstimateRequest( + description: $request->input('description'), + amount: Amount::fromString($request->input('amount')), + amountType: $request->input('amount_type'), + estimateType: $request->input('estimateType'), + costUnit: $costUnit, + estimateId: $request->input('estimateId'), + ))->execute(); + + if ($createCostUniResponse->success) { + return response()->json([ + 'status' => 'success', + 'message' => 'Der Eintrag wurde erfolgreich angelegt.' + ]); + } else { + return response()->json([ + 'status' => 'error', + 'message' => 'Beim Anlegen des Eintrags ist ein Fehler aufgetreten.' + ]); + } + } +} diff --git a/app/Domains/Budget/Routes/api.php b/app/Domains/Budget/Routes/api.php index 2a7d345..d01a5ee 100644 --- a/app/Domains/Budget/Routes/api.php +++ b/app/Domains/Budget/Routes/api.php @@ -1,5 +1,7 @@ group(function () { Route::middleware(['auth'])->group(function () { Route::prefix('/{costUnitId}')->group(function () { Route::get('/list/{estimateType}', ListController::class); + Route::get('{estimateId}/delete', DeleteController::class); + Route::post('/save-estimate', SaveController::class); }); }); }); diff --git a/app/Domains/Budget/Views/AddOrUpdateEstimate.vue b/app/Domains/Budget/Views/AddOrUpdateEstimate.vue new file mode 100644 index 0000000..16cfc5a --- /dev/null +++ b/app/Domains/Budget/Views/AddOrUpdateEstimate.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/app/Domains/Budget/Views/ListBudgetTypes.vue b/app/Domains/Budget/Views/ListBudgetTypes.vue index bf58ca6..7073d92 100644 --- a/app/Domains/Budget/Views/ListBudgetTypes.vue +++ b/app/Domains/Budget/Views/ListBudgetTypes.vue @@ -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.'); - } -} -