Cost units can be edited
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitDetails;
|
||||
|
||||
class ChangeCostUnitDetailsCommand {
|
||||
private ChangeCostUnitDetailsRequest $request;
|
||||
|
||||
public function __construct(ChangeCostUnitDetailsRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute(): ChangeCostUnitDetailsResponse {
|
||||
$response = new ChangeCostUnitDetailsResponse();
|
||||
|
||||
$this->request->costUnit->distance_allowance = $this->request->distanceAllowance->getAmount();
|
||||
$this->request->costUnit->mail_on_new = $this->request->mailOnNew;
|
||||
$this->request->costUnit->billing_deadline = $this->request->billingDeadline;
|
||||
|
||||
$response->success = $this->request->costUnit->save();
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitDetails;
|
||||
|
||||
use App\Models\CostUnit;
|
||||
use App\ValueObjects\Amount;
|
||||
use DateTime;
|
||||
|
||||
class ChangeCostUnitDetailsRequest {
|
||||
public CostUnit $costUnit;
|
||||
|
||||
public Amount $distanceAllowance;
|
||||
public bool $mailOnNew;
|
||||
public ?DateTime $billingDeadline;
|
||||
|
||||
public function __construct(CostUnit $costUnit, Amount $distanceAllowance, bool $mailOnNew, ?DateTime $billingDeadline = null) {
|
||||
$this->costUnit = $costUnit;
|
||||
$this->distanceAllowance = $distanceAllowance;
|
||||
$this->mailOnNew = $mailOnNew;
|
||||
$this->billingDeadline = $billingDeadline;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitDetails;
|
||||
|
||||
class ChangeCostUnitDetailsResponse {
|
||||
public bool $success;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitState;
|
||||
|
||||
class ChangeCostUnitStateCommand {
|
||||
private ChangeCostUnitStateRequest $request;
|
||||
|
||||
public function __construct(ChangeCostUnitStateRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute() : ChangeCostUnitStateResponse {
|
||||
$response = new ChangeCostUnitStateResponse();
|
||||
|
||||
$this->request->costUnit->allow_new = $this->request->allowNew;
|
||||
$this->request->costUnit->archived = $this->request->isArchived;
|
||||
$response->success = $this->request->costUnit->save();
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitState;
|
||||
|
||||
use App\Models\CostUnit;
|
||||
|
||||
class ChangeCostUnitStateRequest {
|
||||
public bool $allowNew;
|
||||
public bool $isArchived;
|
||||
|
||||
public CostUnit $costUnit;
|
||||
|
||||
public function __construct(CostUnit $costUnit, bool $allowNew, bool $isArchived) {
|
||||
$this->costUnit = $costUnit;
|
||||
$this->allowNew = $allowNew;
|
||||
$this->isArchived = $isArchived;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitState;
|
||||
|
||||
class ChangeCostUnitStateResponse {
|
||||
public bool $success;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitTreasurers;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
class ChangeCostUnitTreasurersCommand {
|
||||
private ChangeCostUnitTreasurersRequest $request;
|
||||
|
||||
public function __construct(ChangeCostUnitTreasurersRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute() : ChangeCostUnitTreasurersResponse {
|
||||
$response = new ChangeCostUnitTreasurersResponse();
|
||||
|
||||
try {
|
||||
$this->request->costUnit->resetTreasurers();
|
||||
|
||||
foreach ($this->request->treasurers as $treasurer) {
|
||||
$this->request->costUnit->tresurers()->attach($treasurer);
|
||||
}
|
||||
|
||||
$this->request->costUnit->save();
|
||||
} catch (\Throwable $th) {
|
||||
$response->success = false;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitTreasurers;
|
||||
|
||||
use App\Models\CostUnit;
|
||||
|
||||
class ChangeCostUnitTreasurersRequest {
|
||||
public array $treasurers;
|
||||
public CostUnit $costUnit;
|
||||
|
||||
public function __construct(CostUnit $costUnit, array $treasurers) {
|
||||
$this->treasurers = $treasurers;
|
||||
$this->costUnit = $costUnit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\ChangeCostUnitTreasurers;
|
||||
|
||||
class ChangeCostUnitTreasurersResponse {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\CreateCostUnit;
|
||||
|
||||
use App\Models\CostUnit;
|
||||
|
||||
class CreateCostUnitCommand {
|
||||
private CreateCostUnitRequest $request;
|
||||
|
||||
public function __construct(CreateCostUnitRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute() : CreateCostUnitResponse {
|
||||
$response = new CreateCostUnitResponse();
|
||||
$costUnit = CostUnit::create([
|
||||
'name' => $this->request->name,
|
||||
'tenant' => app('tenant')->slug,
|
||||
'type' => $this->request->type,
|
||||
'billing_deadline' => $this->request->billingDeadline,
|
||||
'distance_allowance' => $this->request->distanceAllowance->getAmount(),
|
||||
'mail_on_new' => $this->request->mailOnNew,
|
||||
'allow_new' => true,
|
||||
'archived' => false,
|
||||
|
||||
]);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\CreateCostUnit;
|
||||
|
||||
use App\Enumerations\CostUnitType;
|
||||
use App\ValueObjects\Amount;
|
||||
use DateTime;
|
||||
|
||||
class CreateCostUnitRequest {
|
||||
public string $name;
|
||||
public string $type;
|
||||
public Amount $distanceAllowance;
|
||||
public bool $mailOnNew;
|
||||
public ?DateTime $billingDeadline;
|
||||
|
||||
public function __construct(string $name, string $type, Amount $distanceAllowance, bool $mailOnNew, ?DateTime $billingDeadline = null) {
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
$this->distanceAllowance = $distanceAllowance;
|
||||
$this->mailOnNew = $mailOnNew;
|
||||
$this->billingDeadline = $billingDeadline;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\CreateCostUnit;
|
||||
|
||||
class CreateCostUnitResponse {
|
||||
|
||||
}
|
||||
47
app/Domains/CostUnit/Controllers/ChangeStateController.php
Normal file
47
app/Domains/CostUnit/Controllers/ChangeStateController.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Controllers;
|
||||
|
||||
use App\Domains\CostUnit\Actions\ChangeCostUnitState\ChangeCostUnitStateCommand;
|
||||
use App\Domains\CostUnit\Actions\ChangeCostUnitState\ChangeCostUnitStateRequest;
|
||||
use App\Scopes\CommonController;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class ChangeStateController extends CommonController {
|
||||
public function close(int $costUnitId) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId);
|
||||
|
||||
$changeStatRequest = new ChangeCostUnitStateRequest($costUnit, false, false);
|
||||
return $this->changeCostUnitState($changeStatRequest, 'Der CostUnit wurde geschlossen.');
|
||||
}
|
||||
|
||||
public function open(int $costUnitId) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId);
|
||||
|
||||
$changeStatRequest = new ChangeCostUnitStateRequest($costUnit, true, false);
|
||||
return $this->changeCostUnitState($changeStatRequest, 'Der CostUnit wurde geöffnet.');
|
||||
}
|
||||
|
||||
public function archive(int $costUnitId) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId);
|
||||
|
||||
$changeStatRequest = new ChangeCostUnitStateRequest($costUnit, false, true);
|
||||
return $this->changeCostUnitState($changeStatRequest, 'Der CostUnit wurde archiviert.');
|
||||
}
|
||||
|
||||
private function changeCostUnitState(ChangeCostUnitStateRequest $request, string $responseMessage) : JsonResponse {
|
||||
$changeStatCommand = new ChangeCostUnitStateCommand($request);
|
||||
|
||||
if ($changeStatCommand->execute()) {
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => $responseMessage
|
||||
]);
|
||||
};
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Ein Fehler ist aufgetreten.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
35
app/Domains/CostUnit/Controllers/CreateController.php
Normal file
35
app/Domains/CostUnit/Controllers/CreateController.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Controllers;
|
||||
|
||||
use App\Domains\CostUnit\Actions\CreateCostUnit\CreateCostUnitCommand;
|
||||
use App\Domains\CostUnit\Actions\CreateCostUnit\CreateCostUnitRequest;
|
||||
use App\Enumerations\CostUnitType;
|
||||
use App\Models\CostUnit;
|
||||
use App\Providers\InertiaProvider;
|
||||
use App\Scopes\CommonController;
|
||||
use App\ValueObjects\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CreateController extends CommonController{
|
||||
public function showForm() {
|
||||
$inertiaProvider = new InertiaProvider('CostUnit/Create', []);
|
||||
return $inertiaProvider->render();
|
||||
}
|
||||
|
||||
public function createCostUnitRunningJob(Request $request) : JsonResponse {
|
||||
$createCostUnitRequest = new CreateCostUnitRequest(
|
||||
$request->get('cost_unit_name'),
|
||||
CostUnitType::COST_UNIT_TYPE_RUNNING_JOB,
|
||||
Amount::fromString($request->get('distance_allowance')),
|
||||
$request->get('mail_on_new')
|
||||
);
|
||||
|
||||
$createCostUnitCommand = new CreateCostUnitCommand($createCostUnitRequest);
|
||||
$result = $createCostUnitCommand->execute();
|
||||
session()->put('message', 'Die laufende Tätigkeit wurde erfolgreich angelegt.');
|
||||
|
||||
return response()->json([]);
|
||||
}
|
||||
}
|
||||
58
app/Domains/CostUnit/Controllers/EditController.php
Normal file
58
app/Domains/CostUnit/Controllers/EditController.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Controllers;
|
||||
|
||||
use App\Domains\CostUnit\Actions\ChangeCostUnitDetails\ChangeCostUnitDetailsCommand;
|
||||
use App\Domains\CostUnit\Actions\ChangeCostUnitDetails\ChangeCostUnitDetailsRequest;
|
||||
use App\Resources\CostUnitResource;
|
||||
use App\Scopes\CommonController;
|
||||
use App\ValueObjects\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EditController extends CommonController{
|
||||
function __invoke(int $costUnitId) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId);
|
||||
if (null === $costUnit) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Die Kotenstelle konnte nicht geladen werden.'
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'costUnit' => new CostUnitResource($costUnit)->toArray(request())
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, int $costUnitId) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId);
|
||||
if (null === $costUnit) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Die Kotenstelle konnte nicht geladen werden.'
|
||||
]);
|
||||
}
|
||||
|
||||
$saveParams = $request->get('formData');
|
||||
$distanceAllowance = Amount::fromString($saveParams['distanceAllowance']);
|
||||
$billingDeadline = isset($saveParams['billingDeadline']) ? \DateTime::createFromFormat('Y-m-d', $saveParams['billingDeadline']) : null;
|
||||
|
||||
$request = new ChangeCostUnitDetailsRequest($costUnit, $distanceAllowance, $saveParams['mailOnNew'], $billingDeadline);
|
||||
$command = new ChangeCostUnitDetailsCommand($request);
|
||||
$result = $command->execute();
|
||||
|
||||
if (!$result->success) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Bei der Verarbeitung ist ein Fehler aufgetreten.'
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Die Kostenstellendetails wurden erfolgreich gespeichert.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
50
app/Domains/CostUnit/Controllers/ListController.php
Normal file
50
app/Domains/CostUnit/Controllers/ListController.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Controllers;
|
||||
|
||||
use App\Providers\InertiaProvider;
|
||||
use App\Scopes\CommonController;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ListController extends CommonController {
|
||||
public function __invoke() {
|
||||
|
||||
|
||||
$inertiaProvider = new InertiaProvider('CostUnit/List', [
|
||||
'cost_unit_id' => 1
|
||||
]);
|
||||
return $inertiaProvider->render();
|
||||
}
|
||||
|
||||
public function listCurrentEvents(Request $request) : JsonResponse {
|
||||
|
||||
return response()->json([
|
||||
'cost_unit_title' => 'Aktuelle Veranstaltungen',
|
||||
'cost_units' => $this->costUnits->getCurrentEvents(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function listCurrentRunningJobs(Request $request) : JsonResponse {
|
||||
return response()->json([
|
||||
'cost_unit_title' => 'Laufende Tätigkeiten',
|
||||
'cost_units' => $this->costUnits->getRunningJobs(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function listClosedCostUnits(Request $request) : JsonResponse {
|
||||
return response()->json([
|
||||
'cost_unit_title' => 'Geschlossene Kostenstellen',
|
||||
'cost_units' => $this->costUnits->getClosedCostUnits(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function listArchivedCostUnits(Request $request) : JsonResponse {
|
||||
return response()->json([
|
||||
'cost_unit_title' => 'Archivierte Kostenstellen',
|
||||
'cost_units' => $this->costUnits->getArchivedCostUnits(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\CostUnit\Controllers;
|
||||
|
||||
use App\Domains\CostUnit\Actions\ChangeCostUnitTreasurers\ChangeCostUnitTreasurersCommand;
|
||||
use App\Domains\CostUnit\Actions\ChangeCostUnitTreasurers\ChangeCostUnitTreasurersRequest;
|
||||
use App\Providers\InertiaProvider;
|
||||
use App\Resources\CostUnitResource;
|
||||
use App\Scopes\CommonController;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TreasurersEditController extends CommonController {
|
||||
public function __invoke(int $costUnitId) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId);
|
||||
if (null === $costUnit) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Die Kostenstelle konnte nicht geladen werden.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'costUnit' => new CostUnitResource($costUnit)->toArray(request())
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, int $costUnitId) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId);
|
||||
if (null === $costUnit) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Die Kostenstelle konnte nicht geladen werden.'
|
||||
]);
|
||||
}
|
||||
|
||||
$changeTreasurersRequest = new ChangeCostUnitTreasurersRequest($costUnit, $request->get('selectedTreasurers'));
|
||||
$changeTreasurersCommand = new ChangeCostUnitTreasurersCommand($changeTreasurersRequest);
|
||||
if ($changeTreasurersCommand->execute()) {
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Die Schatzis wurden erfolgreich gespeichert.'
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Beim Bearbeiten der Kostenstelle ist ein Fehler aufgetreten.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
49
app/Domains/CostUnit/Routes/api.php
Normal file
49
app/Domains/CostUnit/Routes/api.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\CostUnit\Controllers\ChangeStateController;
|
||||
use App\Domains\CostUnit\Controllers\CreateController;
|
||||
use App\Domains\CostUnit\Controllers\EditController;
|
||||
use App\Domains\CostUnit\Controllers\ListController;
|
||||
use App\Domains\CostUnit\Controllers\TreasurersEditController;
|
||||
use App\Domains\UserManagement\Controllers\EmailVerificationController;
|
||||
use App\Domains\UserManagement\Controllers\RegistrationController;
|
||||
use App\Domains\UserManagement\Controllers\ResetPasswordController;
|
||||
use App\Middleware\IdentifyTenant;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Inertia\Inertia;
|
||||
|
||||
Route::prefix('api/v1')
|
||||
->group(function () {
|
||||
Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::prefix('cost-unit')->group(function () {
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::post('/create-running-job', [CreateController::class, 'createCostUnitRunningJob']);
|
||||
|
||||
|
||||
Route::prefix('/{costUnitId}') ->group(function () {
|
||||
Route::post('/close', [ChangeStateController::class, 'close']);
|
||||
Route::post('/open', [ChangeStateController::class, 'open']);
|
||||
Route::post('/archive', [ChangeStateController::class, 'archive']);
|
||||
|
||||
Route::get('/details', EditController::class);
|
||||
Route::post('/details', [EditController::class, 'update']);
|
||||
|
||||
Route::get('/treasurers', TreasurersEditController::class);
|
||||
Route::post('/treasurers', [TreasurersEditController::class, 'update']);
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
Route::prefix('open')->group(function () {
|
||||
Route::get('/current-events', [ListController::class, 'listCurrentEvents']);
|
||||
Route::get('/current-running-jobs', [ListController::class, 'listCurrentRunningJobs']);
|
||||
Route::get('/closed-cost-units', [ListController::class, 'listClosedCostUnits']);
|
||||
Route::get('/archived-cost-units', [ListController::class, 'listArchivedCostUnits']);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
39
app/Domains/CostUnit/Routes/web.php
Normal file
39
app/Domains/CostUnit/Routes/web.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\CostUnit\Controllers\CreateController;
|
||||
use App\Domains\CostUnit\Controllers\ListController;
|
||||
use App\Domains\Dashboard\Controllers\DashboardController;
|
||||
use App\Domains\UserManagement\Controllers\EmailVerificationController;
|
||||
use App\Domains\UserManagement\Controllers\LoginController;
|
||||
use App\Domains\UserManagement\Controllers\LogOutController;
|
||||
use App\Domains\UserManagement\Controllers\RegistrationController;
|
||||
use App\Domains\UserManagement\Controllers\ResetPasswordController;
|
||||
use App\Http\Controllers\TestRenderInertiaProvider;
|
||||
use App\Middleware\IdentifyTenant;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Inertia\Inertia;
|
||||
|
||||
Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::prefix('cost-unit')->group(function () {
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/create', [CreateController::class, 'showForm']);
|
||||
Route::get('/list', ListController::class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
Route::get('/register', [RegistrationController::class, 'loginForm']);
|
||||
Route::get('/register/verifyEmail', [EmailVerificationController::class, 'verifyEmailForm']);
|
||||
|
||||
Route::get('/reset-password', [ResetPasswordController::class, 'resetPasswordForm']);
|
||||
|
||||
route::get('/logout', LogOutController::class);
|
||||
route::post('/login', [LoginController::class, 'doLogin']);
|
||||
route::get('/login', [LoginController::class, 'loginForm']);
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
78
app/Domains/CostUnit/Views/Create.vue
Normal file
78
app/Domains/CostUnit/Views/Create.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<script setup>
|
||||
import { reactive, inject } from 'vue';
|
||||
import AppLayout from '../../../../resources/js/layouts/AppLayout.vue';
|
||||
import AmountInput from "../../../Views/Components/AmountInput.vue";
|
||||
import { useAjax } from "../../../../resources/js/components/ajaxHandler.js";
|
||||
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
|
||||
import {toast} from "vue3-toastify";
|
||||
|
||||
const props = defineProps({
|
||||
activeUsers: Object,
|
||||
}
|
||||
)
|
||||
|
||||
const { request } = useAjax();
|
||||
|
||||
const formData = reactive({
|
||||
cost_unit_name: '',
|
||||
distance_allowance: '0,25',
|
||||
|
||||
emailAddress: '',
|
||||
mailOnNew: true
|
||||
});
|
||||
|
||||
async function save() {
|
||||
const data = await request("/api/v1/cost-unit/create-running-job", {
|
||||
method: "POST",
|
||||
body: {
|
||||
cost_unit_name: formData.cost_unit_name,
|
||||
distance_allowance: formData.distance_allowance,
|
||||
mailOnNew: formData.mailOnNew
|
||||
}
|
||||
});
|
||||
|
||||
window.location.href = '/cost-unit/list';
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title="Laufende Tätigkeit hinzufügen">
|
||||
<form method="POST" action="/api/v1/cost-unit/create-running-job" @submit.prevent="save">
|
||||
<input type="hidden" name="_token" :value="csrfToken" />
|
||||
|
||||
<shadowed-box style="width: 90%; margin: 20px auto; padding: 20px;">
|
||||
<p>
|
||||
Über dieses Formular können laufende Tätigkeiten angelegt werden.<br />
|
||||
Eine Kostenstelle für eine Veranstaltung wird automatisch erstellt, sobald die Veranstaltung angelegt wurde.
|
||||
</p>
|
||||
<table style="margin-top: 40px; width: 100%">
|
||||
<tr>
|
||||
<th class="width-medium pr-20">Name der laufenden Tätigkeit</th>
|
||||
<td><input type="text" v-model="formData.cost_unit_name" class="width-half-full" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="pr-20">Kilometerpauschale</th>
|
||||
<td>
|
||||
<AmountInput v-model="formData.distance_allowance" class="width-small" /> Euro / Kilometer
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<label style="display:flex;align-items:center;cursor:pointer;">
|
||||
<input type="checkbox" v-model="formData.mailOnNew" style="margin-right:8px;cursor:pointer;" />
|
||||
<span>E-Mail-Benachrichtigung bei neuen Abrechnungen</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input type="submit" value="Speichern" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</shadowed-box>
|
||||
</form>
|
||||
</AppLayout>
|
||||
</template>
|
||||
83
app/Domains/CostUnit/Views/Edit.vue
Normal file
83
app/Domains/CostUnit/Views/Edit.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<script setup>
|
||||
import { reactive, inject } from 'vue';
|
||||
import AppLayout from '../../../../resources/js/layouts/AppLayout.vue';
|
||||
import AmountInput from "../../../Views/Components/AmountInput.vue";
|
||||
import { useAjax } from "../../../../resources/js/components/ajaxHandler.js";
|
||||
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
|
||||
|
||||
const props = defineProps({
|
||||
activeUsers: Object,
|
||||
}
|
||||
)
|
||||
|
||||
const { request } = useAjax();
|
||||
|
||||
const formData = reactive({
|
||||
cost_unit_name: '',
|
||||
distance_allowance: '0,25',
|
||||
|
||||
emailAddress: '',
|
||||
mailOnNew: true
|
||||
});
|
||||
|
||||
async function save() {
|
||||
const data = await request("/wp-json/mareike/costunits/create-new-cost-unit", {
|
||||
method: "POST",
|
||||
body: {
|
||||
mareike_nonce: _mareike_nonce(),
|
||||
cost_unit_name: formData.cost_unit_name,
|
||||
distance_allowance: formData.distance_allowance,
|
||||
email_address: formData.emailAddress,
|
||||
mailOnNew: formData.mailOnNew
|
||||
}
|
||||
});
|
||||
|
||||
toast('Die laufende Tätigkeit wurde erfolgreich angelegt.', { type: 'success' });
|
||||
window.location.href = '/cost-units';
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title="Laufende Tätigkeit hinzufügen">
|
||||
<shadowed-box style="width: 90%; margin: 20px auto; padding: 20px;">
|
||||
<p>
|
||||
Über dieses Formular können laufende Tätigkeiten angelegt werden.<br />
|
||||
Eine Kostenstelle für eine Veranstaltung wird automatisch erstellt, sobald die Veranstaltung angelegt wurde.
|
||||
</p>
|
||||
<table style="margin-top: 40px; width: 100%">
|
||||
<tr>
|
||||
<th class="width-medium pr-20">Name der laufenden Tätigkeit</th>
|
||||
<td><input type="text" v-model="formData.cost_unit_name" class="width-half-full" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="pr-20">Kilometerpauschale</th>
|
||||
<td>
|
||||
<AmountInput v-model="formData.distance_allowance" class="width-small" /> Euro / Kilometer
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<label style="display:flex;align-items:center;cursor:pointer;">
|
||||
<input type="checkbox" v-model="formData.mailOnNew" style="margin-right:8px;cursor:pointer;" />
|
||||
<span>E-Mail-Benachrichtigung bei neuen Abrechnungen</span>
|
||||
</label>
|
||||
<hr />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<span v-for="user in props.activeUsers">
|
||||
<input type="checkbox" :id="'user_' + user.id" />
|
||||
<label :for="'user_' + user.id">{{user.fullname}} ({{user.localGroup}})</label>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input type="button" @click="save" value="Speichern" class="mareike-button button-small button-block" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</shadowed-box>
|
||||
</AppLayout>
|
||||
</template>
|
||||
84
app/Domains/CostUnit/Views/List.vue
Normal file
84
app/Domains/CostUnit/Views/List.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<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 ListCostUnits from "./Partials/ListCostUnits.vue";
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
message: String,
|
||||
|
||||
data: {
|
||||
type: [Array, Object],
|
||||
default: () => []
|
||||
},
|
||||
cost_unit_id: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
|
||||
invoice_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 initialInvoiceId = props.invoice_id
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
title: 'Aktuelle Veranstaltungen',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/current-events",
|
||||
deep_jump_id: initialCostUnitId,
|
||||
deep_jump_id_sub: initialInvoiceId,
|
||||
|
||||
},
|
||||
{
|
||||
title: 'Laufende Tätigkeiten',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/current-running-jobs",
|
||||
deep_jump_id: initialCostUnitId,
|
||||
deep_jump_id_sub: initialInvoiceId,
|
||||
},
|
||||
{
|
||||
title: 'Geschlossene Kostenstellen',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/closed-cost-units",
|
||||
deep_jump_id: initialCostUnitId,
|
||||
deep_jump_id_sub: initialInvoiceId,
|
||||
},
|
||||
{
|
||||
title: 'Archivierte Kostenstellen',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/archived-cost-units",
|
||||
deep_jump_id: initialCostUnitId,
|
||||
deep_jump_id_sub: initialInvoiceId,
|
||||
},
|
||||
]
|
||||
|
||||
onMounted(() => {
|
||||
if (undefined !== props.message) {
|
||||
toast.success(props.message)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title="Kostenstellen">
|
||||
<shadowed-box style="width: 95%; margin: 20px auto; padding: 20px; overflow-x: hidden;">
|
||||
<tabbed-page :tabs="tabs" :initial-tab-id="initialCostUnitId" :initial-sub-tab-id="initialInvoiceId" />
|
||||
|
||||
</shadowed-box>
|
||||
</AppLayout>
|
||||
</template>
|
||||
90
app/Domains/CostUnit/Views/Partials/CostUnitDetails.vue
Normal file
90
app/Domains/CostUnit/Views/Partials/CostUnitDetails.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<script setup>
|
||||
|
||||
import {reactive, ref} from "vue";
|
||||
import Modal from "../../../../Views/Components/Modal.vue";
|
||||
import { useAjax } from "../../../../../resources/js/components/ajaxHandler.js";
|
||||
import AmountInput from "../../../../Views/Components/AmountInput.vue";
|
||||
import {toast} from "vue3-toastify";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}, showCostUnit: Boolean
|
||||
})
|
||||
|
||||
const mail_on_new = ref(Boolean(Number(props.data.mail_on_new)))
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const { request } = useAjax()
|
||||
function close() {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
|
||||
const formData = reactive({
|
||||
billingDeadline: props.data.billingDeadline,
|
||||
mailOnNew: mail_on_new.value,
|
||||
distanceAllowance: props.data.distanceAllowanceSmall,
|
||||
});
|
||||
|
||||
async function updateCostUnit() {
|
||||
const data = await request('/api/v1/cost-unit/' + props.data.id + '/details', {
|
||||
method: "POST",
|
||||
body: {
|
||||
formData
|
||||
}
|
||||
});
|
||||
|
||||
close();
|
||||
if (data.status === 'success') {
|
||||
toast.success(data.message);
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<Modal
|
||||
:show="showCostUnit"
|
||||
title="Details anpassen"
|
||||
@close="emit('close')"
|
||||
>
|
||||
Kilometerpauschale:
|
||||
<amount-input v-model="formData.distanceAllowance" class="width-small" /> Euro / km
|
||||
<br /><br />
|
||||
|
||||
<span v-if="props.data.type !== 'running_job'">
|
||||
Abrechnungsschluss am:
|
||||
<input type="date" style="margin-top: 10px;" id="autoclose_date" v-model="formData.billingDeadline" />
|
||||
<br /><br />
|
||||
</span>
|
||||
|
||||
<div style="margin-top: 10px;">
|
||||
<label style="display: flex; align-items: center; cursor: pointer;">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="mail_on_new"
|
||||
v-model="formData.mailOnNew"
|
||||
style="margin-right: 8px; cursor: pointer;"
|
||||
/>
|
||||
<span>E-Mail-Benachrichtigung bei neuen Abrechnungen</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<input type="button" value="Speichern" @click="updateCostUnit" />
|
||||
</Modal>
|
||||
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.mareike-save-button {
|
||||
background-color: #2271b1 !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
</style>
|
||||
255
app/Domains/CostUnit/Views/Partials/ListCostUnits.vue
Normal file
255
app/Domains/CostUnit/Views/Partials/ListCostUnits.vue
Normal file
@@ -0,0 +1,255 @@
|
||||
<script setup>
|
||||
import {createApp, ref} from 'vue'
|
||||
/*import {
|
||||
_mareike_download_as_zip,
|
||||
|
||||
_mareike_use_webdav
|
||||
} from "../../../assets/javascripts/library";*/
|
||||
//import LoadingModal from "../../../assets/components/LoadingModal.vue";
|
||||
//import Invoices from '../invoices/index.vue'
|
||||
import { useAjax } from "../../../../../resources/js/components/ajaxHandler.js";
|
||||
import CostUnitDetails from "./CostUnitDetails.vue";
|
||||
import {toast} from "vue3-toastify";
|
||||
import Treasurers from "./Treasurers.vue";
|
||||
|
||||
//import CostUnitDetails from "./CostUnitDetails.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 show_cost_unit = ref(false)
|
||||
const showTreasurers = ref(false)
|
||||
const costUnit = ref(null)
|
||||
|
||||
|
||||
const { data, loading, error, request, download } = useAjax()
|
||||
|
||||
if (props.deep_jump_id > 0) {
|
||||
open_invoice_list(props.deep_jump_id, 'new', props.deep_jump_id_sub)
|
||||
}
|
||||
|
||||
async function costUnitDetails(costUnitId) {
|
||||
const data = await request('/api/v1/cost-unit/' + costUnitId + '/details', {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
showLoading.value = false;
|
||||
|
||||
if (data.status === 'success') {
|
||||
costUnit.value = data.costUnit
|
||||
show_cost_unit.value = true
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function editTreasurers(costUnitId) {
|
||||
const data = await request('/api/v1/cost-unit/' + costUnitId + '/treasurers', {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
showLoading.value = false;
|
||||
|
||||
if (data.status === 'success') {
|
||||
costUnit.value = data.costUnit
|
||||
showTreasurers.value = true
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function open_invoice_list(cost_unit_id, endpoint, invoice_id) {
|
||||
const url = '' // `/wp-json/mareike/invoices/list-${endpoint}?invoice_id=${invoice_id}&cost_unit_id=${cost_unit_id}
|
||||
try {
|
||||
const response = await fetch(url, { method: 'GET' })
|
||||
if (!response.ok) throw new Error('Fehler beim Laden')
|
||||
invoices.value = await response.json()
|
||||
current_cost_unit.value = cost_unit_id
|
||||
invoice_id = invoice_id
|
||||
showInvoiceList.value = true
|
||||
} catch (err) {
|
||||
}
|
||||
}
|
||||
|
||||
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';
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function export_payouts(cost_unit_id) {
|
||||
showLoading.value = true;
|
||||
|
||||
try {
|
||||
if (_mareike_download_as_zip()) {
|
||||
const response = await fetch("/wp-json/mareike/costunits/export-payouts", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
mareike_nonce: _mareike_nonce(),
|
||||
costunit: cost_unit_id,
|
||||
}),
|
||||
});
|
||||
|
||||
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.href = downloadUrl;
|
||||
a.download = `payouts-${cost_unit_id}.zip`;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
window.URL.revokeObjectURL(downloadUrl);
|
||||
} else {
|
||||
await request("/wp-json/mareike/costunits/export-payouts", {
|
||||
method: "POST",
|
||||
body: {
|
||||
mareike_nonce: _mareike_nonce(),
|
||||
costunit: cost_unit_id,
|
||||
}
|
||||
});
|
||||
}
|
||||
showLoading.value = false;
|
||||
toast.success('Die Abrechnungen wurden exportiert.');
|
||||
} catch (err) {
|
||||
showLoading.value = false;
|
||||
toast.error('Beim Export der Abrechnungen ist ein Fehler aufgetreten.');
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="props.data.cost_units && props.data.cost_units.length > 0 && !showInvoiceList">
|
||||
<h2>{{ props.data.cost_unit_title }}</h2>
|
||||
<span v-for="costUnit in props.data.cost_units" class="costunit-list" :id="'costUnitBox_' + costUnit.id">
|
||||
<table style="width: 100%">
|
||||
<thead>
|
||||
<tr><td colspan="5">
|
||||
{{ costUnit.name }}
|
||||
</td></tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<th>Gesamtbeitrag</th>
|
||||
<td>{{ costUnit.totalAmount }}</td>
|
||||
<th>Unbearbeitet</th>
|
||||
<td>{{ costUnit.countNewInvoices }}</td>
|
||||
<td rowspan="4" style="vertical-align: top;">
|
||||
<input v-if="!costUnit.archived" type="button" value="Abrechnungen bearbeiten" />
|
||||
<input v-else type="button" value="Abrechnungen einsehen" />
|
||||
<br />
|
||||
<input v-if="!costUnit.archived" type="button" value="Genehmigte Abrechnungen exportieren" style="margin-top: 10px;" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Spenden</th>
|
||||
<td>{{ costUnit.donatedAmount }}</td>
|
||||
|
||||
<th>Nicht exportiert</th>
|
||||
<td>{{ costUnit.countApprovedInvoices }}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2"></td>
|
||||
|
||||
<th>Ohne Auszahlung</th>
|
||||
<td colspan="2">{{ costUnit.countDonatedInvoices }}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2"></td>
|
||||
|
||||
<th>Abgelehnt</th>
|
||||
<td colspan="2">{{ costUnit.countDeniedInvoices }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="5" style="width: 100%; padding-top: 20px;">
|
||||
<strong @click="costUnitDetails(costUnit.id)" v-if="costUnit.allow_new" class="link">Details anpassen</strong>
|
||||
<strong @click="editTreasurers(costUnit.id)" v-if="!costUnit.archived" class="link">Schatzis zuweisen</strong>
|
||||
<strong @click="denyNewRequests(costUnit.id)" v-if="costUnit.allow_new" class="link" style="color: #ff0000">Neue Abrechnungen verbieten</strong>
|
||||
<strong @click="allowNewRequests(costUnit.id)" v-if="!costUnit.allow_new && !costUnit.archived" class="link" style="color: #529a30">Neue Abrechnungen erlauben</strong>
|
||||
<strong @click="archiveCostUnit(costUnit.id)" v-if="!costUnit.allow_new && !costUnit.archived" class="link" style="color: #ff0000">Veranstaltung archivieren</strong>
|
||||
</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" />
|
||||
|
||||
|
||||
<LoadingModal :show="showLoading" v-if="_mareike_use_webdav()" message="Die PDF-Dateien werden asynchron erzeugt, diese sollten in 10 Minuten auf dem Webdav-Server liegen', 'mareike')" />
|
||||
<LoadingModal :show="showLoading" v-else message='Die Abrechnungen werden exportiert, bitte warten.' />
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<strong style="width: 100%; text-align: center; display: block; margin-top: 20px;">
|
||||
Es gibt keine Kostenstellen in dieser Kategorie, für die du verantwortlich bist.
|
||||
</strong>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.costunit-list {
|
||||
width: 96% !important;
|
||||
}
|
||||
</style>
|
||||
99
app/Domains/CostUnit/Views/Partials/Treasurers.vue
Normal file
99
app/Domains/CostUnit/Views/Partials/Treasurers.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<script setup>
|
||||
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import Modal from "../../../../Views/Components/Modal.vue";
|
||||
import { useAjax } from "../../../../../resources/js/components/ajaxHandler.js";
|
||||
import AmountInput from "../../../../Views/Components/AmountInput.vue";
|
||||
import {toast} from "vue3-toastify";
|
||||
|
||||
const selectedTreasurers = ref([])
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}, showTreasurers: Boolean
|
||||
})
|
||||
|
||||
const commonProps = reactive({
|
||||
activeUsers: [],
|
||||
});
|
||||
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
const response = await fetch('/api/v1/retreive-global-data');
|
||||
const data = await response.json();
|
||||
Object.assign(commonProps, data);
|
||||
|
||||
selectedTreasurers.value = props.data.treasurers?.map(t => t.id) ?? []
|
||||
});
|
||||
|
||||
|
||||
|
||||
const mail_on_new = ref(Boolean(Number(props.data.mail_on_new)))
|
||||
|
||||
const emit = defineEmits(['closeTreasurers'])
|
||||
|
||||
const { request } = useAjax()
|
||||
function closeTreasurers() {
|
||||
emit('closeTreasurers')
|
||||
}
|
||||
|
||||
|
||||
const formData = reactive({
|
||||
billingDeadline: props.data.billingDeadline,
|
||||
mailOnNew: mail_on_new.value,
|
||||
distanceAllowance: props.data.distanceAllowanceSmall,
|
||||
});
|
||||
|
||||
async function updateCostUnit() {
|
||||
const data = await request('/api/v1/cost-unit/' + props.data.id + '/treasurers', {
|
||||
method: "POST",
|
||||
body: {
|
||||
selectedTreasurers: selectedTreasurers.value,
|
||||
}
|
||||
});
|
||||
|
||||
closeTreasurers();
|
||||
if (data.status === 'success') {
|
||||
toast.success(data.message);
|
||||
} else {
|
||||
toast.error(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(props.data.treasurers)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<Modal
|
||||
:show="showTreasurers"
|
||||
title="Schatzis zuweisen"
|
||||
@close="emit('closeTreasurers')"
|
||||
>
|
||||
Zuständige Schatzis:
|
||||
|
||||
<p v-for="user in commonProps.activeUsers">
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="'user_' + user.id"
|
||||
:value="user.id"
|
||||
v-model="selectedTreasurers"
|
||||
/>
|
||||
<label :for="'user_' + user.id">{{user.fullname}}</label>
|
||||
</p>
|
||||
|
||||
<input type="button" value="Speichern" @click="updateCostUnit" />
|
||||
</Modal>
|
||||
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.mareike-save-button {
|
||||
background-color: #2271b1 !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user