Merge pull request 'Displaying estimates' (#6) from dev-4.4.0 into main
Implemented Event Budgets
This commit was merged in pull request #6.
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Actions\CreateEstimate;
|
||||||
|
|
||||||
|
use App\Models\CostUnitEstimate;
|
||||||
|
|
||||||
|
class CreateEstimateAction {
|
||||||
|
private CreateEstimateResponse $response;
|
||||||
|
|
||||||
|
public function __construct(private CreateEstimateRequest $request) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(): CreateEstimateResponse {
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Actions\CreateEstimate;
|
||||||
|
|
||||||
|
use App\Enumerations\InvoiceType;
|
||||||
|
use App\Models\CostUnit;
|
||||||
|
use App\ValueObjects\Amount;
|
||||||
|
|
||||||
|
class CreateEstimateRequest {
|
||||||
|
function __construct(
|
||||||
|
public string $amountType,
|
||||||
|
public string $description,
|
||||||
|
public Amount $amount,
|
||||||
|
public string $estimateType,
|
||||||
|
public CostUnit $costUnit,
|
||||||
|
public int $estimateId,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Actions\CreateEstimate;
|
||||||
|
|
||||||
|
class CreateEstimateResponse {
|
||||||
|
public bool $success;
|
||||||
|
public ?int $estimateId;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->success = false;
|
||||||
|
$this->estimateId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Actions\DeleteEstimate;
|
||||||
|
|
||||||
|
class DeleteEstimateAction {
|
||||||
|
public function __construct(private DeleteEstimateRequest $request) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute() : DeleteEstimateResponse {
|
||||||
|
$response = new DeleteEstimateResponse();
|
||||||
|
$this->request->estimate->delete();
|
||||||
|
$response->success = true;
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Actions\DeleteEstimate;
|
||||||
|
|
||||||
|
use App\Models\CostUnitEstimate;
|
||||||
|
|
||||||
|
class DeleteEstimateRequest {
|
||||||
|
public function __construct(public CostUnitEstimate $estimate)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Actions\DeleteEstimate;
|
||||||
|
|
||||||
|
class DeleteEstimateResponse {
|
||||||
|
public bool $success;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Controllers;
|
||||||
|
|
||||||
|
use App\Domains\Budget\Actions\CreateEstimate\CreateEstimateAction;
|
||||||
|
use App\Domains\Budget\Actions\CreateEstimate\CreateEstimateRequest;
|
||||||
|
use App\Domains\Budget\Actions\DeleteEstimate\DeleteEstimateAction;
|
||||||
|
use App\Domains\Budget\Actions\DeleteEstimate\DeleteEstimateRequest;
|
||||||
|
use App\Domains\CostUnit\Actions\CreateCostUnit\CreateCostUnitRequest;
|
||||||
|
use App\Scopes\CommonController;
|
||||||
|
use App\ValueObjects\Amount;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class DeleteController extends CommonController
|
||||||
|
{
|
||||||
|
public function __invoke(int $costUnitId, int $estimateId, Request $request) : JsonResponse {
|
||||||
|
$estimate = $this->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.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Controllers;
|
||||||
|
|
||||||
|
use App\Enumerations\InvoiceType;
|
||||||
|
use App\Scopes\CommonController;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ListController extends CommonController
|
||||||
|
{
|
||||||
|
public function __invoke(int $costUnitId, string $estimateType, Request $request) : JsonResponse {
|
||||||
|
$costUnit = $this->costUnits->getById($costUnitId);
|
||||||
|
$estimates = $this->estimates->getEstimates($costUnit, $estimateType);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'success',
|
||||||
|
'costUnitId' => $costUnitId,
|
||||||
|
'title' => InvoiceType::where('slug', $estimateType)->first()->name,
|
||||||
|
'estimateType' => $estimateType,
|
||||||
|
'estimates' => $estimates,
|
||||||
|
'totalAmountString' => $this->estimates->getTotalAmount($costUnit, $estimateType)->toString(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Controllers;
|
||||||
|
|
||||||
|
use App\Providers\InertiaProvider;
|
||||||
|
use App\Scopes\CommonController;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Inertia\Response;
|
||||||
|
|
||||||
|
class MainController extends CommonController
|
||||||
|
{
|
||||||
|
public function __invoke(int $costUnitId, Request $request) : Response
|
||||||
|
{
|
||||||
|
$inertiaProvider = new InertiaProvider('Budget/List', [
|
||||||
|
'cost_unit_id' => $costUnitId
|
||||||
|
]);
|
||||||
|
return $inertiaProvider->render();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Budget\Controllers;
|
||||||
|
|
||||||
|
use App\Domains\Budget\Actions\CreateEstimate\CreateEstimateAction;
|
||||||
|
use App\Domains\Budget\Actions\CreateEstimate\CreateEstimateRequest;
|
||||||
|
use App\Domains\CostUnit\Actions\CreateCostUnit\CreateCostUnitRequest;
|
||||||
|
use App\Scopes\CommonController;
|
||||||
|
use App\ValueObjects\Amount;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class SaveController extends CommonController
|
||||||
|
{
|
||||||
|
public function __invoke(int $costUnitId, Request $request) : JsonResponse {
|
||||||
|
$costUnit = $this->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.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Domains\Budget\Controllers\DeleteController;
|
||||||
|
use App\Domains\Budget\Controllers\SaveController;
|
||||||
|
use App\Domains\Budget\Controllers\ListController;
|
||||||
|
use App\Middleware\IdentifyTenant;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::prefix('api/v1')->group(function () {
|
||||||
|
Route::middleware(IdentifyTenant::class)->group(function () {
|
||||||
|
Route::prefix('budget')->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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Domains\Budget\Controllers\MainController;
|
||||||
|
use App\Middleware\IdentifyTenant;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::middleware(IdentifyTenant::class)->group(function () {
|
||||||
|
Route::prefix('budget')->group(function () {
|
||||||
|
Route::middleware(['auth'])->group(function () {
|
||||||
|
Route::prefix('/{costUnitId}')->group(function() {
|
||||||
|
Route::get('/', MainController::class);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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>
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
<script setup>
|
||||||
|
import {reactive, inject, onMounted} from 'vue';
|
||||||
|
import AppLayout from '../../../../resources/js/layouts/AppLayout.vue';
|
||||||
|
import { useAjax } from "../../../../resources/js/components/ajaxHandler.js";
|
||||||
|
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
|
||||||
|
import TabbedPage from "../../../Views/Components/TabbedPage.vue";
|
||||||
|
import {toast} from "vue3-toastify";
|
||||||
|
|
||||||
|
import ListBudgets from "./ListBudgetTypes.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
message: String,
|
||||||
|
|
||||||
|
data: {
|
||||||
|
type: [Array, Object],
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
cost_unit_id: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Prüfen, ob ein ?id= Parameter in der URL übergeben wurde
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
const initialCostUnitId = props.cost_unit_id
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
title: 'Verpflegung',
|
||||||
|
component: ListBudgets,
|
||||||
|
endpoint: "/api/v1/budget/" + props.cost_unit_id + "/list/catering",
|
||||||
|
deep_jump_id: initialCostUnitId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Unterkunft',
|
||||||
|
component: ListBudgets,
|
||||||
|
endpoint: "/api/v1/budget/" + props.cost_unit_id + "/list/accommodation",
|
||||||
|
deep_jump_id: initialCostUnitId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Programm',
|
||||||
|
component: ListBudgets,
|
||||||
|
endpoint: "/api/v1/budget/" + props.cost_unit_id + "/list/program",
|
||||||
|
deep_jump_id: initialCostUnitId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Logistik',
|
||||||
|
component: ListBudgets,
|
||||||
|
endpoint: "/api/v1/budget/" + props.cost_unit_id + "/list/logistic",
|
||||||
|
deep_jump_id: initialCostUnitId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Technik',
|
||||||
|
component: ListBudgets,
|
||||||
|
endpoint: "/api/v1/budget/" + props.cost_unit_id + "/list/technical",
|
||||||
|
deep_jump_id: initialCostUnitId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Reisekosten',
|
||||||
|
component: ListBudgets,
|
||||||
|
endpoint: "/api/v1/budget/" + props.cost_unit_id + "/list/travelling",
|
||||||
|
deep_jump_id: initialCostUnitId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Verwaltung',
|
||||||
|
component: ListBudgets,
|
||||||
|
endpoint: "/api/v1/budget/" + props.cost_unit_id + "/list/management",
|
||||||
|
deep_jump_id: initialCostUnitId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Sonstiges',
|
||||||
|
component: ListBudgets,
|
||||||
|
endpoint: "/api/v1/budget/" + props.cost_unit_id + "/list/other",
|
||||||
|
deep_jump_id: initialCostUnitId,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (undefined !== props.message) {
|
||||||
|
toast.success(props.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppLayout title="Veranstaltungsbudget">
|
||||||
|
<shadowed-box style="width: 95%; margin: 20px auto; padding: 20px; overflow-x: hidden;">
|
||||||
|
<tabbed-page :tabs="tabs" :initial-tab-id="initialCostUnitId" />
|
||||||
|
|
||||||
|
</shadowed-box>
|
||||||
|
</AppLayout>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<script setup>
|
||||||
|
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: () => []
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const localData = ref(props.data)
|
||||||
|
|
||||||
|
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 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')
|
||||||
|
|
||||||
|
const result = await response.json()
|
||||||
|
localData.value = result
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching estimates:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.status === 'success') {
|
||||||
|
toast.success(data.message);
|
||||||
|
reload()
|
||||||
|
} else {
|
||||||
|
toast.error(data.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="localData.estimates && localData.estimates.length > 0">
|
||||||
|
<h2>{{ props.data.title }}</h2>
|
||||||
|
<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.singleAmountString }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<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>
|
||||||
|
</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" @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>
|
||||||
|
.costunit-list {
|
||||||
|
width: 96% !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
const invoice = ref(null)
|
const invoice = ref(null)
|
||||||
const show_invoice = ref(false)
|
const show_invoice = ref(false)
|
||||||
const localData = ref(props.data)
|
const localData = ref(props.data)
|
||||||
console.log(props.data)
|
|
||||||
async function openInvoiceDetails(invoiceId) {
|
async function openInvoiceDetails(invoiceId) {
|
||||||
const url = '/api/v1/invoice/details/' + invoiceId
|
const url = '/api/v1/invoice/details/' + invoiceId
|
||||||
|
|
||||||
|
|||||||
@@ -112,8 +112,8 @@
|
|||||||
|
|
||||||
<div class="event-flexbox" v-else>
|
<div class="event-flexbox" v-else>
|
||||||
<div class="event-flexbox-row top">
|
<div class="event-flexbox-row top">
|
||||||
<div class="left"><ParticipationSummary v-if="dynamicProps.event" :event="dynamicProps.event" /></div>
|
<div class="actions-left"><ParticipationSummary v-if="dynamicProps.event" :event="dynamicProps.event" /></div>
|
||||||
<div class="right">
|
<div class="actions-right">
|
||||||
<a :href="'/event/details/' + props.data.event.identifier + '/pdf/first-aid-list'">
|
<a :href="'/event/details/' + props.data.event.identifier + '/pdf/first-aid-list'">
|
||||||
<input type="button" value="Erste-Hilfe-Liste (PDF)" />
|
<input type="button" value="Erste-Hilfe-Liste (PDF)" />
|
||||||
</a><br/>
|
</a><br/>
|
||||||
@@ -186,6 +186,7 @@
|
|||||||
<label style="font-size: 9pt;" class="link" @click="showCommonSettings">Allgemeine Einstellungen</label>
|
<label style="font-size: 9pt;" class="link" @click="showCommonSettings">Allgemeine Einstellungen</label>
|
||||||
<label style="font-size: 9pt;" class="link" @click="showEventManagement">Veranstaltungsleitung</label>
|
<label style="font-size: 9pt;" class="link" @click="showEventManagement">Veranstaltungsleitung</label>
|
||||||
<label style="font-size: 9pt;" class="link" @click="showParticipationFees">Teilnahmegebühren</label>
|
<label style="font-size: 9pt;" class="link" @click="showParticipationFees">Teilnahmegebühren</label>
|
||||||
|
<a style="font-size: 9pt;" class="link" :href="'/budget/' + props.data.event.costUnit.id">Budget bearbeiten</a>
|
||||||
<a style="font-size: 9pt;" class="link" :href="'/cost-unit/' + props.data.event.costUnit.id">Ausgabenübersicht</a>
|
<a style="font-size: 9pt;" class="link" :href="'/cost-unit/' + props.data.event.costUnit.id">Ausgabenübersicht</a>
|
||||||
<a v-if="!dynamicProps.event.registrationAllowed && !dynamicProps.event.archived" style="color: #ff0000; font-size: 9pt;" class="link" @click="archiveEvent">Archivieren</a>
|
<a v-if="!dynamicProps.event.registrationAllowed && !dynamicProps.event.archived" style="color: #ff0000; font-size: 9pt;" class="link" @click="archiveEvent">Archivieren</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -248,13 +249,13 @@
|
|||||||
gap: 10px; /* Abstand zwischen den Spalten */
|
gap: 10px; /* Abstand zwischen den Spalten */
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-flexbox-row.top .left {
|
.event-flexbox-row.top .actions-left {
|
||||||
flex: 0 0 calc(100% - 300px);
|
flex: 0 0 calc(100% - 300px);
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-flexbox-row.top .right {
|
.event-flexbox-row.top .actions-right {
|
||||||
flex: 0 0 250px;
|
flex: 0 0 200px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +264,7 @@
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-flexbox-row.top .right input[type="button"] {
|
.event-flexbox-row.top .actions-right input[type="button"] {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,19 +96,31 @@ const props = defineProps({
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th style="padding-top: 20px; font-size: 12pt !important;" colspan="2">Budget</th>
|
||||||
|
<td v-if="props.event.totalBalance.expected.value >= 0" style="color: #4caf50; font-weight: bold; padding-top: 20px; font-size: 12pt !important;">
|
||||||
|
{{ props.event.totalBalance.estimated.readable }}
|
||||||
|
</td>
|
||||||
|
<td v-else style="color: #f44336; font-weight: bold; padding-top: 20px; font-size: 12pt !important;">
|
||||||
|
{{props.event.totalBalance.estimated.readable}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<h3>Ausgaben</h3>
|
<h3>Ausgaben</h3>
|
||||||
<table class="event-payment-table" style="font-size: 10pt;">
|
<table class="event-payment-table" style="font-size: 10pt; width:100%">
|
||||||
<tr v-for="amount in props.event.costUnit.amounts">
|
<tr v-for="amount in props.event.costUnit.amounts">
|
||||||
<th>{{amount.name}}</th>
|
<th>{{amount.name}}</th>
|
||||||
<td>{{amount.string}}</td>
|
<td>{{amount.string}}</td>
|
||||||
|
<td>({{ amount.estimatedString }}) </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="color:#f44336; border-width: 1px; border-top-style: solid; ">Gesamt</th>
|
<th style="color:#f44336; border-width: 1px; border-top-style: solid; ">Gesamt</th>
|
||||||
<td style="color:#f44336; border-width: 1px; border-top-style: solid; font-weight: bold">{{props.event.costUnit.overAllAmount.text}}</td>
|
<td style="color:#f44336; border-width: 1px; border-top-style: solid; font-weight: bold; padding-right: 20px;">{{props.event.costUnit.overAllAmount.text}}</td>
|
||||||
|
<td style="color:#f44336; border-width: 1px; border-top-style: solid; font-weight: bold">({{props.event.costUnit.overAllEstimatedAmount.text}}))</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@@ -121,7 +133,7 @@ const props = defineProps({
|
|||||||
.participant-flexbox {
|
.participant-flexbox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 20px;
|
||||||
width: 95%;
|
width: 95%;
|
||||||
margin: 20px auto 0;
|
margin: 20px auto 0;
|
||||||
}
|
}
|
||||||
@@ -135,7 +147,7 @@ const props = defineProps({
|
|||||||
.participant-flexbox-row.top .left,
|
.participant-flexbox-row.top .left,
|
||||||
.participant-flexbox-row.top .right {
|
.participant-flexbox-row.top .right {
|
||||||
|
|
||||||
padding: 10px;
|
padding: 20px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use App\Scopes\InstancedModel;
|
|||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property string $name
|
* @property string $name
|
||||||
@@ -44,7 +45,15 @@ class CostUnit extends InstancedModel
|
|||||||
return $this->hasMany(Invoice::class);
|
return $this->hasMany(Invoice::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function estimates() : hasMany {
|
||||||
|
return $this->hasMany(CostUnitEstimate::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function tenant() : BelongsTo {
|
public function tenant() : BelongsTo {
|
||||||
return $this->belongsTo(Tenant::class, 'tenant', 'slug');
|
return $this->belongsTo(Tenant::class, 'tenant', 'slug');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function event() : HasOne {
|
||||||
|
return $this->hasOne(Event::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Casts\AmountCast;
|
||||||
|
use App\Enumerations\InvoiceStatus;
|
||||||
|
use App\Enumerations\InvoiceType;
|
||||||
|
use App\Resources\EventResource;
|
||||||
|
use App\Scopes\InstancedModel;
|
||||||
|
use App\ValueObjects\Amount;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
|
||||||
|
class CostUnitEstimate extends InstancedModel
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'tenant',
|
||||||
|
'cost_unit_id',
|
||||||
|
'type',
|
||||||
|
'description',
|
||||||
|
'flat_amount',
|
||||||
|
'amount_by_user',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'flat_amount' => AmountCast::class,
|
||||||
|
'amount_by_user' => AmountCast::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function costUnit() : BelongsTo{
|
||||||
|
return $this->belongsTo(CostUnit::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invoiceType() : InvoiceType {
|
||||||
|
return $this->belongsTo(InvoiceType::class, 'type', 'slug')->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function calculateAmount() : ?Amount {
|
||||||
|
switch (true) {
|
||||||
|
case $this->flat_amount !== null:
|
||||||
|
return $this->flat_amount;
|
||||||
|
default:
|
||||||
|
$event = $this->costUnit()->first()->event()?->first();
|
||||||
|
if (null !== $event) {
|
||||||
|
$participants = $event->participants()->count();
|
||||||
|
$amount = clone($this->amount_by_user);
|
||||||
|
return $amount->multiply($participants);
|
||||||
|
} else {
|
||||||
|
return $this->amount_by_user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -178,6 +178,18 @@ class CostUnitRepository {
|
|||||||
return $amount;
|
return $amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function sumupEstimatedByInvoiceType(CostUnit $costUnit, InvoiceType $invoiceType) : Amount {
|
||||||
|
$amount = new Amount(0, 'Euro');
|
||||||
|
foreach ($costUnit->estimates()->get() as $estimate) {
|
||||||
|
if ($estimate->type !== $invoiceType->slug) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$amount->addAmount($estimate->calculateAmount());
|
||||||
|
}
|
||||||
|
return $amount;
|
||||||
|
}
|
||||||
|
|
||||||
public function sumupUnhandledAmounts(CostUnit $costUnit, bool $donatedAmount = false) : Amount {
|
public function sumupUnhandledAmounts(CostUnit $costUnit, bool $donatedAmount = false) : Amount {
|
||||||
$amount = new Amount(0, '');
|
$amount = new Amount(0, '');
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Models\CostUnit;
|
||||||
|
use App\Models\CostUnitEstimate;
|
||||||
|
use App\ValueObjects\Amount;
|
||||||
|
|
||||||
|
class EstimatesRepository {
|
||||||
|
public function getEstimates(CostUnit $costUnit, string $estimateType) : array {
|
||||||
|
$return = [];
|
||||||
|
foreach ($costUnit->estimates()->where('type', $estimateType)->get() as $estimate) {
|
||||||
|
$return[] = $estimate->toResource()->toArray(request());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getById(int $estimateId, bool $accessCheck = true) : ?CostUnitEstimate {
|
||||||
|
$estimate = CostUnitEstimate::find($estimateId);
|
||||||
|
if ($estimate === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($accessCheck) {
|
||||||
|
$costUnitRepository = new CostUnitRepository();
|
||||||
|
if (null === $costUnitRepository->getById($estimate->cost_unit_id)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $estimate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotalAmount(CostUnit $costUnit, string $estimateType) : Amount {
|
||||||
|
$total = new Amount(0, 'Euro');
|
||||||
|
foreach ($costUnit->estimates()->where('type', $estimateType)->get() as $estimate) {
|
||||||
|
$total->addAmount($estimate->calculateAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Resources;
|
||||||
|
|
||||||
|
use App\Enumerations\EatingHabit;
|
||||||
|
use App\Enumerations\EfzStatus;
|
||||||
|
use App\Enumerations\ParticipationType;
|
||||||
|
use App\Models\CostUnitEstimate;
|
||||||
|
use App\Models\EventParticipant;
|
||||||
|
use App\ValueObjects\Age;
|
||||||
|
use App\ValueObjects\Amount;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class CostUnitEstimateResource extends JsonResource
|
||||||
|
{
|
||||||
|
function __construct(CostUnitEstimate $estimate)
|
||||||
|
{
|
||||||
|
parent::__construct($estimate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray($request) : array
|
||||||
|
{
|
||||||
|
$amount = $this->resource->calculateAmount();
|
||||||
|
$singleAmountString = $this->resource->flat_amount?->toString();
|
||||||
|
$amountType = 'flat';
|
||||||
|
if ($singleAmountString === null) {
|
||||||
|
$amountType = 'per_person';
|
||||||
|
$singleAmountString = $this->resource->amount_by_user->toString() . ' / Person (' . $amount->toString() . ' Gesamt)';
|
||||||
|
} else {
|
||||||
|
$singleAmountString .= ' Gesamt';
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $this->resource->id,
|
||||||
|
'title' => $this->resource->description,
|
||||||
|
'singleAmountString' => $singleAmountString,
|
||||||
|
'calculatedAmount' => $amount,
|
||||||
|
'calculatedAmountString' => $amount->toString(),
|
||||||
|
'amountValue' => $amount->getAmount(),
|
||||||
|
'amountType' => $amountType,
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,10 +31,15 @@ class CostUnitResource {
|
|||||||
|
|
||||||
$amounts = [];
|
$amounts = [];
|
||||||
$overAllAmount = new Amount(0, 'Euro');
|
$overAllAmount = new Amount(0, 'Euro');
|
||||||
|
$overAllEstimatedAmount = new Amount(0, 'Euro');
|
||||||
foreach (InvoiceType::orderBy('sort_order')->get() as $invoiceType) {
|
foreach (InvoiceType::orderBy('sort_order')->get() as $invoiceType) {
|
||||||
$overAllAmount->addAmount($costUnitRepository->sumupByInvoiceType($this->costUnit, $invoiceType));
|
$overAllAmount->addAmount($costUnitRepository->sumupByInvoiceType($this->costUnit, $invoiceType));
|
||||||
|
$overAllEstimatedAmount->addAmount($costUnitRepository->sumupEstimatedByInvoiceType($this->costUnit, $invoiceType));
|
||||||
$amounts[$invoiceType->slug]['string'] = $costUnitRepository->sumupByInvoiceType($this->costUnit, $invoiceType)->toString();
|
$amounts[$invoiceType->slug]['string'] = $costUnitRepository->sumupByInvoiceType($this->costUnit, $invoiceType)->toString();
|
||||||
$amounts[$invoiceType->slug]['name'] = $invoiceType->name;
|
$amounts[$invoiceType->slug]['name'] = $invoiceType->name;
|
||||||
|
$amounts[$invoiceType->slug]['estimated'] = $costUnitRepository->sumupEstimatedByInvoiceType($this->costUnit, $invoiceType);
|
||||||
|
$amounts[$invoiceType->slug]['estimatedString'] = $costUnitRepository->sumupEstimatedByInvoiceType($this->costUnit, $invoiceType)->toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -52,6 +57,7 @@ class CostUnitResource {
|
|||||||
'treasurers' => $this->costUnit->treasurers()->get()->map(fn($user) => new UserResource($user))->toArray(),
|
'treasurers' => $this->costUnit->treasurers()->get()->map(fn($user) => new UserResource($user))->toArray(),
|
||||||
'amounts' => $amounts,
|
'amounts' => $amounts,
|
||||||
'overAllAmount' => ['text' => $overAllAmount->toString(), 'value' => $overAllAmount],
|
'overAllAmount' => ['text' => $overAllAmount->toString(), 'value' => $overAllAmount],
|
||||||
|
'overAllEstimatedAmount' => ['text' => $overAllEstimatedAmount->toString(), 'value' => $overAllEstimatedAmount],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ class EventResource extends JsonResource{
|
|||||||
$returnArray['eventEnd'] = $this->event->end_date->format('d.m.Y');
|
$returnArray['eventEnd'] = $this->event->end_date->format('d.m.Y');
|
||||||
$returnArray['eventEndInternal'] = $this->event->end_date;
|
$returnArray['eventEndInternal'] = $this->event->end_date;
|
||||||
$returnArray['duration'] = $duration;
|
$returnArray['duration'] = $duration;
|
||||||
|
$returnArray['totalParticipantCount'] = $this->event->participants()->count();
|
||||||
|
|
||||||
$returnArray['supportPersonIndex'] = $this->event->support_per_person->toString();
|
$returnArray['supportPersonIndex'] = $this->event->support_per_person->toString();
|
||||||
$returnArray['supportPerson'] = $this->calculateSupportPerPerson($returnArray['participants']);
|
$returnArray['supportPerson'] = $this->calculateSupportPerPerson($returnArray['participants']);
|
||||||
@@ -95,12 +96,15 @@ class EventResource extends JsonResource{
|
|||||||
|
|
||||||
$totalBalanceReal = new Amount(0, 'Euro');
|
$totalBalanceReal = new Amount(0, 'Euro');
|
||||||
$totalBalanceExpected = new Amount(0, 'Euro');
|
$totalBalanceExpected = new Amount(0, 'Euro');
|
||||||
|
$totalBalanceEstimated = new Amount(0, 'Euro');
|
||||||
|
|
||||||
$totalBalanceReal->addAmount($returnArray['income']['real']['amount']);
|
$totalBalanceReal->addAmount($returnArray['income']['real']['amount']);
|
||||||
$totalBalanceExpected->addAmount($returnArray['income']['expected']['amount']);
|
$totalBalanceExpected->addAmount($returnArray['income']['expected']['amount']);
|
||||||
|
$totalBalanceEstimated->addAmount($returnArray['income']['expected']['amount']);
|
||||||
|
|
||||||
$totalBalanceReal->subtractAmount($returnArray['costUnit']['overAllAmount']['value']);
|
$totalBalanceReal->subtractAmount($returnArray['costUnit']['overAllAmount']['value']);
|
||||||
$totalBalanceExpected->subtractAmount($returnArray['costUnit']['overAllAmount']['value']);
|
$totalBalanceExpected->subtractAmount($returnArray['costUnit']['overAllAmount']['value']);
|
||||||
|
$totalBalanceEstimated->subtractAmount($returnArray['costUnit']['overAllEstimatedAmount']['value']);
|
||||||
$returnArray['totalBalance'] = [
|
$returnArray['totalBalance'] = [
|
||||||
'real' => [
|
'real' => [
|
||||||
'value' => $totalBalanceReal->getAmount(),
|
'value' => $totalBalanceReal->getAmount(),
|
||||||
@@ -108,7 +112,11 @@ class EventResource extends JsonResource{
|
|||||||
], 'expected' => [
|
], 'expected' => [
|
||||||
'value' => $totalBalanceExpected->getAmount(),
|
'value' => $totalBalanceExpected->getAmount(),
|
||||||
'readable' => $totalBalanceExpected->toString(),
|
'readable' => $totalBalanceExpected->toString(),
|
||||||
]
|
],
|
||||||
|
'estimated' => [
|
||||||
|
'value' => $totalBalanceEstimated->getAmount(),
|
||||||
|
'readable' => $totalBalanceEstimated->toString(),
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
$returnArray['flatSupport'] = $this->event->support_flat->toString();
|
$returnArray['flatSupport'] = $this->event->support_flat->toString();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace App\Scopes;
|
|||||||
use App\Models\Tenant;
|
use App\Models\Tenant;
|
||||||
use App\Providers\AuthCheckProvider;
|
use App\Providers\AuthCheckProvider;
|
||||||
use App\Repositories\CostUnitRepository;
|
use App\Repositories\CostUnitRepository;
|
||||||
|
use App\Repositories\EstimatesRepository;
|
||||||
use App\Repositories\EventParticipantRepository;
|
use App\Repositories\EventParticipantRepository;
|
||||||
use App\Repositories\EventRepository;
|
use App\Repositories\EventRepository;
|
||||||
use App\Repositories\InvoiceRepository;
|
use App\Repositories\InvoiceRepository;
|
||||||
@@ -21,6 +22,7 @@ abstract class CommonController {
|
|||||||
protected InvoiceRepository $invoices;
|
protected InvoiceRepository $invoices;
|
||||||
protected EventRepository $events;
|
protected EventRepository $events;
|
||||||
protected EventParticipantRepository $eventParticipants;
|
protected EventParticipantRepository $eventParticipants;
|
||||||
|
protected EstimatesRepository $estimates;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->tenant = app('tenant');
|
$this->tenant = app('tenant');
|
||||||
@@ -30,6 +32,7 @@ abstract class CommonController {
|
|||||||
$this->invoices = new InvoiceRepository();
|
$this->invoices = new InvoiceRepository();
|
||||||
$this->events = new EventRepository();
|
$this->events = new EventRepository();
|
||||||
$this->eventParticipants = new EventParticipantRepository();
|
$this->eventParticipants = new EventParticipantRepository();
|
||||||
|
$this->estimates = new EstimatesRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkAuth() {
|
protected function checkAuth() {
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration {
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('cost_unit_estimates', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('tenant');
|
||||||
|
$table->foreignId('cost_unit_id')->constrained('cost_units', 'id')->restrictOnDelete()->cascadeOnUpdate();
|
||||||
|
$table->string('type');
|
||||||
|
$table->string('description');
|
||||||
|
$table->float('flat_amount', 2)->nullable();
|
||||||
|
$table->float('amount_by_user', 2)->nullable();
|
||||||
|
|
||||||
|
$table->foreign('tenant')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate();
|
||||||
|
$table->foreign('type')->references('slug')->on('invoice_types')->restrictOnDelete()->cascadeOnUpdate();
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('cost_unit_estimates');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -21,6 +21,8 @@ require_once __DIR__ . '/../app/Domains/Invoice/Routes/web.php';
|
|||||||
require_once __DIR__ . '/../app/Domains/Invoice/Routes/api.php';
|
require_once __DIR__ . '/../app/Domains/Invoice/Routes/api.php';
|
||||||
require_once __DIR__ . '/../app/Domains/Event/Routes/web.php';
|
require_once __DIR__ . '/../app/Domains/Event/Routes/web.php';
|
||||||
require_once __DIR__ . '/../app/Domains/Event/Routes/api.php';
|
require_once __DIR__ . '/../app/Domains/Event/Routes/api.php';
|
||||||
|
require_once __DIR__ . '/../app/Domains/Budget/Routes/web.php';
|
||||||
|
require_once __DIR__ . '/../app/Domains/Budget/Routes/api.php';
|
||||||
|
|
||||||
|
|
||||||
Route::get('/LKvDUqWl', function () {
|
Route::get('/LKvDUqWl', function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user