From fd403f8520e8925438838a8090e598c70e86a306 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Fri, 13 Feb 2026 00:11:51 +0100
Subject: [PATCH] Operation processes on invoices
---
.../ChangeCostUnitTreasurersCommand.php | 2 +-
.../CostUnit/Controllers/ListController.php | 2 -
.../CostUnit/Controllers/OpenController.php | 28 ++
app/Domains/CostUnit/Routes/api.php | 6 +
app/Domains/CostUnit/Routes/web.php | 4 +
app/Domains/CostUnit/Views/List.vue | 2 -
app/Domains/CostUnit/Views/Open.vue | 67 ++++
.../CostUnit/Views/Partials/ListCostUnits.vue | 17 +-
.../CostUnit/Views/Partials/ListInvoices.vue | 80 +++++
.../Views/Partials/Widgets/OpenCostUnits.vue | 2 +-
.../ChangeStatus/ChangeStatusCommand.php | 51 ++++
.../ChangeStatus/ChangeStatusRequest.php | 17 ++
.../ChangeStatus/ChangeStatusResponse.php | 11 +
.../CreateInvoice/CreateInvoiceCommand.php | 2 +-
.../CreateInvoice/CreateInvoiceRequest.php | 5 +
.../UpdateInvoice/UpdateInvoiceCommand.php | 33 ++
.../UpdateInvoice/UpdateInvoiceRequest.php | 24 ++
.../UpdateInvoice/UpdateInvoiceResponse.php | 15 +
.../Controllers/ChangeStateController.php | 27 ++
.../Invoice/Controllers/EditController.php | 132 ++++++++
.../Controllers/ShowInvoiceController.php | 55 ++++
app/Domains/Invoice/Routes/api.php | 19 +-
.../invoiceDetails/DistanceAllowance.vue | 78 +++++
.../Partials/invoiceDetails/EditInvoice.vue | 116 +++++++
.../Views/Partials/invoiceDetails/Header.vue | 117 +++++++
.../invoiceDetails/InvoiceDetails.vue | 285 ++++++++++++++++++
.../Partials/invoiceDetails/ShowInvoice.vue | 21 ++
app/Enumerations/InvoiceStatus.php | 5 +-
app/Models/CostUnit.php | 4 +-
app/Models/Invoice.php | 5 +
app/Providers/GlobalDataProvider.php | 22 ++
app/Repositories/CostUnitRepository.php | 52 +++-
app/Repositories/InvoiceRepository.php | 40 +++
app/Resources/CostUnitResource.php | 21 +-
app/Resources/InvoiceResource.php | 69 +++++
app/ValueObjects/Amount.php | 4 +
app/Views/Components/FullScreenModal.vue | 146 +++++++++
app/Views/Components/Icon.vue | 13 +-
app/Views/Components/PdfViewer.vue | 46 +++
package.json | 3 +-
public/css/app.css | 1 +
public/css/elements.css | 3 +-
public/css/invoices.css | 24 ++
routes/web.php | 1 +
44 files changed, 1635 insertions(+), 42 deletions(-)
create mode 100644 app/Domains/CostUnit/Controllers/OpenController.php
create mode 100644 app/Domains/CostUnit/Views/Open.vue
create mode 100644 app/Domains/CostUnit/Views/Partials/ListInvoices.vue
create mode 100644 app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusCommand.php
create mode 100644 app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusRequest.php
create mode 100644 app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusResponse.php
create mode 100644 app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceCommand.php
create mode 100644 app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceRequest.php
create mode 100644 app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceResponse.php
create mode 100644 app/Domains/Invoice/Controllers/ChangeStateController.php
create mode 100644 app/Domains/Invoice/Controllers/EditController.php
create mode 100644 app/Domains/Invoice/Controllers/ShowInvoiceController.php
create mode 100644 app/Domains/Invoice/Views/Partials/invoiceDetails/DistanceAllowance.vue
create mode 100644 app/Domains/Invoice/Views/Partials/invoiceDetails/EditInvoice.vue
create mode 100644 app/Domains/Invoice/Views/Partials/invoiceDetails/Header.vue
create mode 100644 app/Domains/Invoice/Views/Partials/invoiceDetails/InvoiceDetails.vue
create mode 100644 app/Domains/Invoice/Views/Partials/invoiceDetails/ShowInvoice.vue
create mode 100644 app/Resources/InvoiceResource.php
create mode 100644 app/Views/Components/FullScreenModal.vue
create mode 100644 app/Views/Components/PdfViewer.vue
diff --git a/app/Domains/CostUnit/Actions/ChangeCostUnitTreasurers/ChangeCostUnitTreasurersCommand.php b/app/Domains/CostUnit/Actions/ChangeCostUnitTreasurers/ChangeCostUnitTreasurersCommand.php
index b1bff4d..bacb627 100644
--- a/app/Domains/CostUnit/Actions/ChangeCostUnitTreasurers/ChangeCostUnitTreasurersCommand.php
+++ b/app/Domains/CostUnit/Actions/ChangeCostUnitTreasurers/ChangeCostUnitTreasurersCommand.php
@@ -18,7 +18,7 @@ class ChangeCostUnitTreasurersCommand {
$this->request->costUnit->resetTreasurers();
foreach ($this->request->treasurers as $treasurer) {
- $this->request->costUnit->tresurers()->attach($treasurer);
+ $this->request->costUnit->treasurers()->attach($treasurer);
}
$this->request->costUnit->save();
diff --git a/app/Domains/CostUnit/Controllers/ListController.php b/app/Domains/CostUnit/Controllers/ListController.php
index 145ae00..de9ddfb 100644
--- a/app/Domains/CostUnit/Controllers/ListController.php
+++ b/app/Domains/CostUnit/Controllers/ListController.php
@@ -9,8 +9,6 @@ use Illuminate\Http\Request;
class ListController extends CommonController {
public function __invoke() {
-
-
$inertiaProvider = new InertiaProvider('CostUnit/List', [
'cost_unit_id' => 1
]);
diff --git a/app/Domains/CostUnit/Controllers/OpenController.php b/app/Domains/CostUnit/Controllers/OpenController.php
new file mode 100644
index 0000000..a72567f
--- /dev/null
+++ b/app/Domains/CostUnit/Controllers/OpenController.php
@@ -0,0 +1,28 @@
+ $costUnitId
+ ]);
+ return $inertiaProvider->render();
+ }
+
+ public function listInvoices(int $costUnitId, string $invoiceStatus) : JsonResponse {
+ $costUnit = $this->costUnits->getById($costUnitId);
+ $invoices = $this->invoices->getByStatus($costUnit, $invoiceStatus);
+
+ return response()->json([
+ 'status' => 'success',
+ 'costUnit' => $costUnit,
+ 'invoices' => $invoices,
+ 'endpoint' => $invoiceStatus,
+ ]);
+ }
+}
diff --git a/app/Domains/CostUnit/Routes/api.php b/app/Domains/CostUnit/Routes/api.php
index 38e9186..2461809 100644
--- a/app/Domains/CostUnit/Routes/api.php
+++ b/app/Domains/CostUnit/Routes/api.php
@@ -4,6 +4,7 @@ use App\Domains\CostUnit\Controllers\CreateController;
use App\Domains\CostUnit\Controllers\DistanceAllowanceController;
use App\Domains\CostUnit\Controllers\EditController;
use App\Domains\CostUnit\Controllers\ListController;
+use App\Domains\CostUnit\Controllers\OpenController;
use App\Domains\CostUnit\Controllers\TreasurersEditController;
use App\Middleware\IdentifyTenant;
use Illuminate\Support\Facades\Route;
@@ -21,6 +22,11 @@ Route::prefix('api/v1')
Route::prefix('/{costUnitId}') ->group(function () {
+ Route::get('/invoice-list/{invoiceStatus}', [OpenController::class, 'listInvoices']);
+
+
+
+
Route::post('/close', [ChangeStateController::class, 'close']);
Route::post('/open', [ChangeStateController::class, 'open']);
Route::post('/archive', [ChangeStateController::class, 'archive']);
diff --git a/app/Domains/CostUnit/Routes/web.php b/app/Domains/CostUnit/Routes/web.php
index 715d4c3..ed2400c 100644
--- a/app/Domains/CostUnit/Routes/web.php
+++ b/app/Domains/CostUnit/Routes/web.php
@@ -1,6 +1,7 @@
group(function () {
Route::middleware(['auth'])->group(function () {
Route::get('/create', [CreateController::class, 'showForm']);
Route::get('/list', ListController::class);
+ Route::get('/{costUnitId}/', OpenController::class);
+
+
});
diff --git a/app/Domains/CostUnit/Views/List.vue b/app/Domains/CostUnit/Views/List.vue
index 019cf68..b842a97 100644
--- a/app/Domains/CostUnit/Views/List.vue
+++ b/app/Domains/CostUnit/Views/List.vue
@@ -6,10 +6,8 @@ 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,
diff --git a/app/Domains/CostUnit/Views/Open.vue b/app/Domains/CostUnit/Views/Open.vue
new file mode 100644
index 0000000..77d4f04
--- /dev/null
+++ b/app/Domains/CostUnit/Views/Open.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/Domains/CostUnit/Views/Partials/ListCostUnits.vue b/app/Domains/CostUnit/Views/Partials/ListCostUnits.vue
index a8a1ccd..8e88874 100644
--- a/app/Domains/CostUnit/Views/Partials/ListCostUnits.vue
+++ b/app/Domains/CostUnit/Views/Partials/ListCostUnits.vue
@@ -46,7 +46,7 @@ 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)
+// open_invoice_list(props.deep_jump_id, 'new', props.deep_jump_id_sub)
}
async function costUnitDetails(costUnitId) {
@@ -79,17 +79,8 @@ async function editTreasurers(costUnitId) {
}
}
- 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) {
- }
+ function loadInvoices(cost_unit_id) {
+ window.location.href = '/cost-unit/' + cost_unit_id;
}
async function denyNewRequests(costUnitId) {
@@ -182,7 +173,7 @@ async function export_payouts(cost_unit_id) {
Unbearbeitet |
{{ costUnit.countNewInvoices }} |
-
+
diff --git a/app/Domains/CostUnit/Views/Partials/ListInvoices.vue b/app/Domains/CostUnit/Views/Partials/ListInvoices.vue
new file mode 100644
index 0000000..00bc03a
--- /dev/null
+++ b/app/Domains/CostUnit/Views/Partials/ListInvoices.vue
@@ -0,0 +1,80 @@
+
+
+
+
+ Es sind keine Abrechnungen in dieser Kategorie vorhanden.
+
+
+
+
+
+
diff --git a/app/Domains/Dashboard/Views/Partials/Widgets/OpenCostUnits.vue b/app/Domains/Dashboard/Views/Partials/Widgets/OpenCostUnits.vue
index 5eea62f..baa7053 100644
--- a/app/Domains/Dashboard/Views/Partials/Widgets/OpenCostUnits.vue
+++ b/app/Domains/Dashboard/Views/Partials/Widgets/OpenCostUnits.vue
@@ -24,7 +24,7 @@ onMounted(async () => {
|
- | {{costUnit.name}} |
+ {{costUnit.name}} |
{{costUnit.new_invoices_count}} |
{{costUnit.approved_invoices_count}} |
{{costUnit.totalAmount}} |
diff --git a/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusCommand.php b/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusCommand.php
new file mode 100644
index 0000000..3657845
--- /dev/null
+++ b/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusCommand.php
@@ -0,0 +1,51 @@
+request = $request;
+ }
+
+ public function execute() : ChangeStatusResponse {
+ $response = new ChangeStatusResponse();
+
+ switch ($this->request->status) {
+ case InvoiceStatus::INVOICE_STATUS_APPROVED:
+ $this->request->invoice->status = InvoiceStatus::INVOICE_STATUS_APPROVED;
+ $this->request->invoice->approved_by = auth()->user()->id;
+ $this->request->invoice->approved_at = now();
+ break;
+
+ case InvoiceStatus::INVOICE_STATUS_DENIED:
+ $this->request->invoice->status = InvoiceStatus::INVOICE_STATUS_DENIED;
+ $this->request->invoice->denied_by = auth()->user()->id;
+ $this->request->invoice->denied_at = now();
+ $this->request->invoice->denied_reason = $this->request->comment;
+ break;
+ case InvoiceStatus::INVOICE_STATUS_NEW:
+ $this->request->invoice->status = InvoiceStatus::INVOICE_STATUS_NEW;
+ $this->request->invoice->approved_by = null;
+ $this->request->invoice->approved_at = null;
+ $this->request->invoice->denied_by = null;
+ $this->request->invoice->denied_at = null;
+ $this->request->invoice->comment = $this->request->invoice->denied_reason;
+ $this->request->invoice->denied_reason = null;
+ break;
+
+
+
+ }
+
+ if ($this->request->invoice->save()) {
+ $response->success = true;
+ }
+
+
+ return $response;
+ }
+}
diff --git a/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusRequest.php b/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusRequest.php
new file mode 100644
index 0000000..5c2b4ae
--- /dev/null
+++ b/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusRequest.php
@@ -0,0 +1,17 @@
+invoice = $invoice;
+ $this->status = $status;
+ $this->comment = $comment;
+ }
+}
diff --git a/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusResponse.php b/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusResponse.php
new file mode 100644
index 0000000..e9c9365
--- /dev/null
+++ b/app/Domains/Invoice/Actions/ChangeStatus/ChangeStatusResponse.php
@@ -0,0 +1,11 @@
+success = false;
+ }
+}
diff --git a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceCommand.php b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceCommand.php
index 73b4fea..fc55c6f 100644
--- a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceCommand.php
+++ b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceCommand.php
@@ -38,7 +38,7 @@ class CreateInvoiceCommand {
'travel_direction' => $this->request->travelRoute,
'passengers' => $this->request->passengers,
'transportation' => $this->request->transportations,
- 'document_filename' => $this->request->receiptFile !== null ? $this->request->receiptFile->path : null,
+ 'document_filename' => $this->request->receiptFile !== null ? $this->request->receiptFile->fullPath : null,
]);
if ($invoice !== null) {
diff --git a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceRequest.php b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceRequest.php
index 27cb211..cc88a39 100644
--- a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceRequest.php
+++ b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceRequest.php
@@ -59,6 +59,11 @@ class CreateInvoiceRequest {
$this->totalAmount = $totalAmount;
$this->isDonation = $isDonation;
$this->userId = $userId;
+
+ if ($accountIban === 'undefined') {
+ $this->accountIban = null;
+ $this->accountOwner = null;
+ }
}
}
diff --git a/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceCommand.php b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceCommand.php
new file mode 100644
index 0000000..cb1fcec
--- /dev/null
+++ b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceCommand.php
@@ -0,0 +1,33 @@
+request = $request;
+ }
+
+ public function execute() : UpdateInvoiceResponse {
+ $response = new UpdateInvoiceResponse();
+
+ $this->request->invoice->amount = $this->request->amount->getAmount();
+ $this->request->invoice->cost_unit_id = $this->request->costUnit->id;
+ $this->request->invoice->type = $this->request->invoiceType;
+ $this->request->invoice->comment = $this->request->comment;
+
+ $this->request->invoice->save();
+
+ $request = new ChangeStatusRequest($this->request->invoice, InvoiceStatus::INVOICE_STATUS_APPROVED);
+ $changeStatusCommand = new ChangeStatusCommand($request);
+ $changeStatusCommand->execute();
+
+ return $response;
+ }
+
+}
diff --git a/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceRequest.php b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceRequest.php
new file mode 100644
index 0000000..2086978
--- /dev/null
+++ b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceRequest.php
@@ -0,0 +1,24 @@
+comment = $comment;
+ $this->invoiceType = $invoiceType;
+ $this->costUnit = $costUnit;
+ $this->invoice = $invoice;
+ $this->amount = $amount;
+ }
+}
diff --git a/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceResponse.php b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceResponse.php
new file mode 100644
index 0000000..e05bd83
--- /dev/null
+++ b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceResponse.php
@@ -0,0 +1,15 @@
+success = false;
+ $this->invoice = null;
+ }
+}
diff --git a/app/Domains/Invoice/Controllers/ChangeStateController.php b/app/Domains/Invoice/Controllers/ChangeStateController.php
new file mode 100644
index 0000000..40b7c61
--- /dev/null
+++ b/app/Domains/Invoice/Controllers/ChangeStateController.php
@@ -0,0 +1,27 @@
+invoices->getAsTreasurer($invoiceId);
+ if ($invoice === null) {
+ return response()->json([]);
+ }
+
+ $comment = request()->get('reason') ?? null;
+ $changeStatusRequest = new ChangeStatusRequest($invoice, $newState, $comment);
+ $changeStatusCommand = new ChangeStatusCommand($changeStatusRequest);
+ if ($changeStatusCommand->execute()->success) {
+ return response()->json(['status' => 'success']);
+ }
+
+ return response()->json([]);
+ }
+}
diff --git a/app/Domains/Invoice/Controllers/EditController.php b/app/Domains/Invoice/Controllers/EditController.php
new file mode 100644
index 0000000..f3c5659
--- /dev/null
+++ b/app/Domains/Invoice/Controllers/EditController.php
@@ -0,0 +1,132 @@
+invoices->getAsTreasurer($invoiceId);
+ if ($invoice === null) {
+ return response()->json([]);
+ }
+
+ $receiptfile = null;
+ if ($invoice->document_filename !== null) {
+ $receiptfile = new InvoiceFile();
+ $receiptfile->filename = $invoice->document_filename;
+ $receiptfile->fullPath = $invoice->document_filename;
+ }
+ $createInvoiceRequest = new CreateInvoiceRequest(
+ $invoice->costUnit()->first(),
+ $invoice->contact_name,
+ $invoice->type,
+ $invoice->amount,
+ $receiptfile,
+ $invoice->donation,
+ $invoice->user_id,
+ $invoice->contact_email,
+ $invoice->contact_phone,
+ $invoice->contact_bank_owner,
+ $invoice->contact_bank_iban,
+ $invoice->type_other,
+ $invoice->travel_direction,
+ $invoice->distance,
+ $invoice->passengers,
+ $invoice->transportation
+ );
+
+ $invoiceCreationCommand = new CreateInvoiceCommand($createInvoiceRequest);
+ $newInvoice = $invoiceCreationCommand->execute()->invoice;
+
+ $invoiceDenyRequest = new ChangeStatusRequest($invoice,InvoiceStatus::INVOICE_STATUS_DENIED, 'Abrechnungskorrektur in Rechnungsnummer #' . $newInvoice->invoice_number . ' erstellt.');
+ $invoiceDenyCommand = new ChangeStatusCommand($invoiceDenyRequest);
+ $invoiceDenyCommand->execute();
+
+
+ $runningJobs = $this->costUnits->getCostUnitsForNewInvoice(CostUnitType::COST_UNIT_TYPE_RUNNING_JOB);
+ $currentEvents = $this->costUnits->getCostUnitsForNewInvoice(CostUnitType::COST_UNIT_TYPE_EVENT);
+
+ return response()->json([
+ 'invoice' => new InvoiceResource($invoice)->toArray(),
+ 'status' => 'success',
+ 'costUnits' => array_merge($runningJobs, $currentEvents),
+ ]);
+ }
+
+ public function updateInvoice(int $invoiceId, Request $request) : JsonResponse {
+ $invoice = $this->invoices->getAsTreasurer($invoiceId);
+ if ($invoice === null) {
+ return response()->json([]);
+ }
+
+ $modifyData = $request->get('invoiceData');
+
+ $newAmount = Amount::fromString($modifyData['amount']);
+ $amountLeft = Amount::fromString($invoice->amount);
+ $amountLeft->subtractAmount($newAmount);
+
+ $newCostUnit = $this->costUnits->getById($modifyData['cost_unit'],true);
+ $updateInvoiceRequest = new UpdateInvoiceRequest(
+ $invoice,
+ $modifyData['reason_of_correction'] ?? 'Abrechnungskorrektur',
+ $modifyData['type_internal'],
+ $newCostUnit,
+ $newAmount
+ );
+ $updateInvoiceCommand = new UpdateInvoiceCommand($updateInvoiceRequest);
+ $updateInvoiceCommand->execute();
+
+
+ $newInvoice = null;
+ if (isset($modifyData['duplicate']) && $modifyData['duplicate'] === true) {
+ $receiptfile = null;
+ if ($invoice->document_filename !== null) {
+ $receiptfile = new InvoiceFile();
+ $receiptfile->filename = $invoice->document_filename;
+ $receiptfile->fullPath = $invoice->document_filename;
+ }
+ $createInvoiceRequest = new CreateInvoiceRequest(
+ $invoice->costUnit()->first(),
+ $invoice->contact_name,
+ $invoice->type,
+ $amountLeft->getAmount(),
+ $receiptfile,
+ $invoice->donation,
+ $invoice->user_id,
+ $invoice->contact_email,
+ $invoice->contact_phone,
+ $invoice->contact_bank_owner,
+ $invoice->contact_bank_iban,
+ $invoice->type_other,
+ $invoice->travel_direction,
+ $invoice->distance,
+ $invoice->passengers,
+ $invoice->transportation
+ );
+
+ $invoiceCreationCommand = new CreateInvoiceCommand($createInvoiceRequest);
+ $newInvoice = $invoiceCreationCommand->execute()->invoice;
+ }
+
+ $useInvoice = $newInvoice ?? $invoice;
+ $do_copy = $newInvoice !== null ? true : false;
+ return response()->json([
+ 'invoice' => new InvoiceResource($useInvoice)->toArray(),
+ 'do_copy' => $do_copy,
+ ]);
+ }
+}
diff --git a/app/Domains/Invoice/Controllers/ShowInvoiceController.php b/app/Domains/Invoice/Controllers/ShowInvoiceController.php
new file mode 100644
index 0000000..7865118
--- /dev/null
+++ b/app/Domains/Invoice/Controllers/ShowInvoiceController.php
@@ -0,0 +1,55 @@
+invoices->getAsTreasurer($invoiceId);
+
+ $runningJobs = $this->costUnits->getCostUnitsForNewInvoice(CostUnitType::COST_UNIT_TYPE_RUNNING_JOB);
+ $currentEvents = $this->costUnits->getCostUnitsForNewInvoice(CostUnitType::COST_UNIT_TYPE_EVENT);
+
+ return response()->json([
+ 'invoice' => new InvoiceResource($invoice)->toArray(),
+ 'costUnits' => array_merge($runningJobs, $currentEvents),
+ ]);
+ }
+
+ public function showReceipt(int $invoiceId): BinaryFileResponse
+ {
+ $invoice = $this->invoices->getAsTreasurer($invoiceId);
+ if (null === $invoice) {
+ abort(404, 'Datei nicht gefunden');
+ }
+
+ if (null === $invoice->document_filename) {
+ abort(404, 'Datei nicht gefunden');
+ }
+
+ $path = $invoice->document_filename;
+ // Pfad zur Datei
+ $fullPath = 'private/' . $path;
+
+
+
+
+ if (!Storage::exists($path)) {
+
+
+
+ abort(404, 'Datei nicht gefunden');
+ }
+
+ return response()->file(storage_path('app/' . $fullPath), [
+ 'Content-Type' => 'application/pdf'
+ ]);
+ }
+}
diff --git a/app/Domains/Invoice/Routes/api.php b/app/Domains/Invoice/Routes/api.php
index ea6710c..3d985d9 100644
--- a/app/Domains/Invoice/Routes/api.php
+++ b/app/Domains/Invoice/Routes/api.php
@@ -2,20 +2,27 @@
use App\Domains\CostUnit\Controllers\DistanceAllowanceController;
use App\Domains\CostUnit\Controllers\ListController;
+use App\Domains\Invoice\Controllers\ChangeStateController;
+use App\Domains\Invoice\Controllers\EditController;
use App\Domains\Invoice\Controllers\NewInvoiceController;
+use App\Domains\Invoice\Controllers\ShowInvoiceController;
use App\Middleware\IdentifyTenant;
use Illuminate\Support\Facades\Route;
Route::middleware(IdentifyTenant::class)->group(function () {
Route::prefix('api/v1/invoice')->group(function () {
Route::post('/new/{costUnitId}/{invoiceType}', [NewInvoiceController::class, 'saveInvoice']);
-
-
-
-
-
-
Route::middleware(['auth'])->group(function () {
+ Route::get('/details/{invoiceId}', ShowInvoiceController::class);
+ Route::get('/showReceipt/{invoiceId}', [ShowInvoiceController::class, 'showReceipt']);
+
+ Route::post('/details/{invoiceId}/change-state/{newState}', ChangeStateController::class);
+ Route::post('/details/{invoiceId}/copy', [EditController::class, 'copyInvoice']);
+ Route::post('/details/{invoiceId}/update', [EditController::class, 'updateInvoice']);
+
+
+
+
Route::get('/create', [CreateController::class, 'showForm']);
});
diff --git a/app/Domains/Invoice/Views/Partials/invoiceDetails/DistanceAllowance.vue b/app/Domains/Invoice/Views/Partials/invoiceDetails/DistanceAllowance.vue
new file mode 100644
index 0000000..34fd61f
--- /dev/null
+++ b/app/Domains/Invoice/Views/Partials/invoiceDetails/DistanceAllowance.vue
@@ -0,0 +1,78 @@
+
+
+
+
+ |
+ Abrechnung einer Reisekostenpauschale
+ |
+
+ | Reiseroute |
+ {{props.invoice.travelRoute}} |
+
+
+
+ | Gesamte Wegstrecke |
+ {{props.invoice.distance}} km |
+
+
+
+ | Kilometerpauschale |
+ {{props.invoice.distanceAllowance}} Euro / km |
+
+
+
+ | Gesamtbetrag |
+ {{props.invoice.amount}} |
+
+
+
+ | Marterialtransport |
+ {{props.invoice.transportation}} |
+
+
+
+ | Hat Personen mitgenommen |
+ {{props.invoice.passengers}} |
+
+
+
+
+
+
diff --git a/app/Domains/Invoice/Views/Partials/invoiceDetails/EditInvoice.vue b/app/Domains/Invoice/Views/Partials/invoiceDetails/EditInvoice.vue
new file mode 100644
index 0000000..adba409
--- /dev/null
+++ b/app/Domains/Invoice/Views/Partials/invoiceDetails/EditInvoice.vue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/Domains/Invoice/Views/Partials/invoiceDetails/Header.vue b/app/Domains/Invoice/Views/Partials/invoiceDetails/Header.vue
new file mode 100644
index 0000000..f98bf89
--- /dev/null
+++ b/app/Domains/Invoice/Views/Partials/invoiceDetails/Header.vue
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
diff --git a/app/Domains/Invoice/Views/Partials/invoiceDetails/InvoiceDetails.vue b/app/Domains/Invoice/Views/Partials/invoiceDetails/InvoiceDetails.vue
new file mode 100644
index 0000000..29fc008
--- /dev/null
+++ b/app/Domains/Invoice/Views/Partials/invoiceDetails/InvoiceDetails.vue
@@ -0,0 +1,285 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Begründung:
+
+
+
+
+
+
+
diff --git a/app/Domains/Invoice/Views/Partials/invoiceDetails/ShowInvoice.vue b/app/Domains/Invoice/Views/Partials/invoiceDetails/ShowInvoice.vue
new file mode 100644
index 0000000..332f4d5
--- /dev/null
+++ b/app/Domains/Invoice/Views/Partials/invoiceDetails/ShowInvoice.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
diff --git a/app/Enumerations/InvoiceStatus.php b/app/Enumerations/InvoiceStatus.php
index b8ab0b7..bb15116 100644
--- a/app/Enumerations/InvoiceStatus.php
+++ b/app/Enumerations/InvoiceStatus.php
@@ -10,7 +10,10 @@ class InvoiceStatus extends CommonModel
public const INVOICE_STATUS_APPROVED = 'approved';
public const INVOICE_STATUS_DENIED = 'denied';
public const INVOICE_STATUS_EXPORTED = 'exported';
- public const INVOICE_STAUTS_DELETED = 'deleted';
+ public const INVOICE_STATUS_DELETED = 'deleted';
+
+ public const INVOICE_META_STATUS_NO_PAYOUT = 'no_payout';
+ public const INVOICE_META_STATUS_DONATED = 'donated';
protected $table = 'invoice_status';
diff --git a/app/Models/CostUnit.php b/app/Models/CostUnit.php
index 6337cf3..c8332f3 100644
--- a/app/Models/CostUnit.php
+++ b/app/Models/CostUnit.php
@@ -29,13 +29,13 @@ class CostUnit extends InstancedModel
'archived',
];
- public function tresurers() : BelongsToMany{
+ public function treasurers() : BelongsToMany{
return $this->belongsToMany(User::class, 'cost_unit_treasurers', 'cost_unit_id', 'user_id')
->withTimestamps();
}
public function resetTreasurers() {
- $this->tresurers()->detach();
+ $this->treasurers()->detach();
$this->save();
}
diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php
index d34bd89..06f5817 100644
--- a/app/Models/Invoice.php
+++ b/app/Models/Invoice.php
@@ -3,6 +3,7 @@
namespace App\Models;
use App\Enumerations\InvoiceStatus;
+use App\Enumerations\InvoiceType;
use App\Scopes\InstancedModel;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -75,4 +76,8 @@ class Invoice extends InstancedModel
public function status() : BelongsTo {
return $this->belongsTo(InvoiceStatus::class, 'status')->first();
}
+
+ public function invoiceType() : InvoiceType {
+ return $this->belongsTo(InvoiceType::class, 'type', 'slug')->first();
+ }
}
diff --git a/app/Providers/GlobalDataProvider.php b/app/Providers/GlobalDataProvider.php
index d3033e4..86946fd 100644
--- a/app/Providers/GlobalDataProvider.php
+++ b/app/Providers/GlobalDataProvider.php
@@ -24,6 +24,28 @@ class GlobalDataProvider {
]);
}
+ public function getAllInvoiceTypes() : JsonResponse {
+ $invoiceTypes = [];
+ foreach (InvoiceType::all() as $invoiceType) {
+ if (
+ $invoiceType->slug === InvoiceType::INVOICE_TYPE_OTHER
+ ) {
+ continue;
+ }
+
+ $invoiceTypes[] = [
+ 'slug' => $invoiceType->slug,
+ 'name' => $invoiceType->name
+ ];
+ }
+
+ $invoiceTypes[] = ['slug' => InvoiceType::INVOICE_TYPE_OTHER, 'name' => 'Sonstige Kosten'];
+
+ return response()->json([
+ 'invoiceTypes' => $invoiceTypes
+ ]);
+ }
+
public function getInvoiceTypes() : JsonResponse {
$invoiceTypes = [];
foreach (InvoiceType::all() as $invoiceType) {
diff --git a/app/Repositories/CostUnitRepository.php b/app/Repositories/CostUnitRepository.php
index 23a46a7..f9121ce 100644
--- a/app/Repositories/CostUnitRepository.php
+++ b/app/Repositories/CostUnitRepository.php
@@ -85,7 +85,7 @@ class CostUnitRepository {
$visibleCostUnits = [];
/** @var CostUnit $costUnit */
foreach (Costunit::where($criteria)->get() as $costUnit) {
- if ($costUnit->tresurers()->where('user_id', $user->id)->exists() || $canSeeAll || $disableAccessCheck) {
+ if ($costUnit->treasurers()->where('user_id', $user->id)->exists() || $canSeeAll || $disableAccessCheck) {
if ($forDisplay) {
$visibleCostUnits[] = new CostUnitResource($costUnit)->toArray(request());
} else {
@@ -134,7 +134,7 @@ class CostUnitRepository {
return $returnData;
}
- public function sumupAmounts(CostUnit $costUnit) : Amount {
+ public function sumupAmounts(CostUnit $costUnit, bool $donatedAmount = false) : Amount {
$amount = new Amount(0, '');
foreach ($costUnit->invoices()->get() as $invoice) {
@@ -142,9 +142,57 @@ class CostUnitRepository {
continue;
}
+ if (
+ ($donatedAmount && !$invoice->donation) ||
+ (!$donatedAmount && $invoice->donation)
+ ) {
+ continue;
+ }
+
$amount->addAmount(Amount::fromString($invoice->amount));
}
return $amount;
}
+ public function countInvoices(CostUnit $costUnit) : array {
+ $returnData = [
+ InvoiceStatus::INVOICE_STATUS_NEW => 0,
+ InvoiceStatus::INVOICE_STATUS_APPROVED => 0,
+ InvoiceStatus::INVOICE_STATUS_DENIED => 0,
+ InvoiceStatus::INVOICE_META_STATUS_NO_PAYOUT => 0,
+ InvoiceStatus::INVOICE_META_STATUS_DONATED => 0
+ ];
+
+ foreach ($costUnit->invoices()->get() as $invoice) {
+ if ($invoice->status === InvoiceStatus::INVOICE_STATUS_DELETED) {
+ continue;
+ }
+
+ if( $invoice->status === InvoiceStatus::INVOICE_STATUS_DENIED) {
+ $returnData[InvoiceStatus::INVOICE_STATUS_DENIED]++;
+ continue;
+ }
+
+ switch ($invoice->status) {
+ case InvoiceStatus::INVOICE_STATUS_NEW:
+ $returnData[InvoiceStatus::INVOICE_STATUS_NEW]++;
+ break;
+ case InvoiceStatus::INVOICE_STATUS_APPROVED:
+ $returnData[InvoiceStatus::INVOICE_STATUS_APPROVED]++;
+ break;
+ case InvoiceStatus::INVOICE_STATUS_EXPORTED:
+ if ($invoice->donation) {
+ $returnData[InvoiceStatus::INVOICE_META_STATUS_DONATED]++;
+ } else {
+ if ($invoice->contact_bank_iban === null) {
+ $returnData[InvoiceStatus::INVOICE_META_STATUS_NO_PAYOUT]++;
+ }
+ }
+ break;
+ }
+ }
+
+ return $returnData;
+ }
+
}
diff --git a/app/Repositories/InvoiceRepository.php b/app/Repositories/InvoiceRepository.php
index 2725f4b..0ccc17e 100644
--- a/app/Repositories/InvoiceRepository.php
+++ b/app/Repositories/InvoiceRepository.php
@@ -3,8 +3,12 @@
namespace App\Repositories;
use App\Enumerations\InvoiceStatus;
+use App\Enumerations\UserRole;
+use App\Models\CostUnit;
use App\Models\Invoice;
+use App\Resources\InvoiceResource;
use App\ValueObjects\Amount;
+use Illuminate\Database\Eloquent\Collection;
class InvoiceRepository {
public function getMyInvoicesWidget() : array {
@@ -34,4 +38,40 @@ class InvoiceRepository {
return $invoices;
}
+
+ public function getByStatus(CostUnit $costUnit, string $status) : array {
+ $returnData = [];
+ foreach ($costUnit->invoices()->where('status', $status)->get() as $invoice) {
+ $returnData[] = new InvoiceResource($invoice)->toArray();
+ };
+
+ return $returnData;
+ }
+
+ public function getAsTreasurer(int $invoiceId) : ?Invoice {
+ $invoice = Invoice::where('id', $invoiceId)->first();
+ if ($invoice === null) {
+ return null;
+ }
+
+ $isTreasurer = $invoice->costUnit()->first()->treasurers()->where('user_id', auth()->user()->id)->exists();
+ if ($isTreasurer) {
+ return $invoice;
+ }
+
+ $user = auth()->user();
+ if ($user->user_role_main === UserRole::USER_ROLE_ADMIN) {
+ return $invoice;
+ }
+
+ if (app('tenant')->slug === 'lv' && $user->user_role_main === UserRole::USER_ROLE_GROUP_LEADER) {
+ return $invoice;
+ }
+
+ if (app('tenant')->slug !== 'lv' && $user->local_group === app('tenant')->slug && $user->user_role_local_group === UserRole::USER_ROLE_GROUP_LEADER) {
+ return $invoice;
+ }
+
+ return null;
+ }
}
diff --git a/app/Resources/CostUnitResource.php b/app/Resources/CostUnitResource.php
index fdbf923..eb55d20 100644
--- a/app/Resources/CostUnitResource.php
+++ b/app/Resources/CostUnitResource.php
@@ -2,7 +2,9 @@
namespace App\Resources;
+use App\Enumerations\InvoiceStatus;
use App\Models\CostUnit;
+use App\Repositories\CostUnitRepository;
use App\ValueObjects\Amount;
class CostUnitResource {
@@ -13,13 +15,18 @@ class CostUnitResource {
}
public function toArray($request) {
- $totalAmount = 0;
- $donatedAmount = 0;
+ $costUnitRepository = new CostUnitRepository();
- $countNewInvoices = 0;
- $countApprovedInvoices = 0;
- $countDonatedInvoices = 0;
- $countDeniedInvoices = 0;
+
+ $totalAmount = $costUnitRepository->sumupAmounts($this->costUnit)->getAmount();
+ $donatedAmount = $costUnitRepository->sumupAmounts($this->costUnit, true)->getAmount();
+
+ $countInvoices = $costUnitRepository->countInvoices($this->costUnit);
+
+ $countNewInvoices = $countInvoices[InvoiceStatus::INVOICE_STATUS_NEW];
+ $countApprovedInvoices = $countInvoices[InvoiceStatus::INVOICE_STATUS_APPROVED];
+ $countDonatedInvoices = $countInvoices[InvoiceStatus::INVOICE_META_STATUS_DONATED];
+ $countDeniedInvoices = $countInvoices[InvoiceStatus::INVOICE_STATUS_DENIED];
$data = array_merge(
@@ -33,7 +40,7 @@ class CostUnitResource {
'countApprovedInvoices' => $countApprovedInvoices,
'countDonatedInvoices' => $countDonatedInvoices,
'countDeniedInvoices' => $countDeniedInvoices,
- 'treasurers' => $this->costUnit->tresurers()->get()->map(fn($user) => new UserResource($user))->toArray(),
+ 'treasurers' => $this->costUnit->treasurers()->get()->map(fn($user) => new UserResource($user))->toArray(),
]);
diff --git a/app/Resources/InvoiceResource.php b/app/Resources/InvoiceResource.php
new file mode 100644
index 0000000..206e13c
--- /dev/null
+++ b/app/Resources/InvoiceResource.php
@@ -0,0 +1,69 @@
+invoice = $invoice;
+ }
+
+ public function toArray() {
+ $returnData = [];
+ $returnData['invoiceType'] = $this->invoice->invoiceType()->name;
+ if ($this->invoice->invoiceType()->slug === InvoiceType::INVOICE_TYPE_OTHER) {
+ $returnData['invoiceType'] .= ' (' . $this->invoice->type_other . ')';
+ }
+
+ $returnData['costUnitName'] = $this->invoice->costUnit()->first()->name;
+ $returnData['invoiceNumber'] = $this->invoice->invoice_number;
+ $returnData['contactName'] = $this->invoice->contact_name;
+ $returnData['contactEmail'] = $this->invoice->contact_email ?? '--';
+ $returnData['contactPhone'] = $this->invoice->contact_phone ?? '--';
+ $returnData['amount'] = Amount::fromString($this->invoice->amount, ' Euro')->toString();
+ $returnData['id'] = $this->invoice->id;
+ $returnData['donation'] = $this->invoice->donation;
+ $returnData['alreadyPaid'] = !$this->invoice->donation && null === $this->invoice->contact_bank_iban;
+ $returnData['accountOwner'] = $this->invoice->contact_bank_owner ?? '--';
+ $returnData['accountIban'] = $this->invoice->contact_bank_iban ?? '--';
+ $returnData['status'] = $this->invoice->status;
+ $returnData['documentFilename'] = $this->invoice->document_filename;
+ $returnData['readableStatus'] = $this->getReadableStatus();
+ $returnData['comment'] = $this->invoice->comment ?? '--';
+ $returnData['changes'] = $this->invoice->changes ?? '--';
+ $returnData['deniedReason'] = $this->invoice->denied_reason ?? '--';
+ $returnData['travelDirection'] = $this->invoice->travel_direction ?? '--';
+ $returnData['distance'] = $this->invoice->distance;
+ $returnData['distanceAllowance'] = new Amount($this->invoice->costUnit()->first()->distance_allowance, '')->toString();
+ $returnData['passengers'] = $this->invoice->passengers ? 'Ja' : 'Nein';
+ $returnData['transportation'] = $this->invoice->transportation ? 'Ja' : 'Nein';
+ $returnData['travelRoute'] = $this->invoice->travel_direction;
+ $returnData['costUnitId'] = $this->invoice->cost_unit_id;
+ $returnData['amountPlain'] = new Amount($this->invoice->amount, '')->toString();
+ $returnData['internalType'] = $this->invoice->type;
+
+
+ return $returnData;
+ }
+
+ private function getReadableStatus() : string {
+ switch ($this->invoice->status) {
+ case InvoiceStatus::INVOICE_STATUS_NEW:
+ return 'Unbearbeitet';
+ case InvoiceStatus::INVOICE_STATUS_APPROVED:
+ return 'Nicht exportiert';
+ case InvoiceStatus::INVOICE_STATUS_DENIED:
+ return 'Abgelehnt';
+ case InvoiceStatus::INVOICE_STATUS_EXPORTED:
+ return 'Exportiert';
+ }
+ return $this->invoice->status;
+ }
+
+}
diff --git a/app/ValueObjects/Amount.php b/app/ValueObjects/Amount.php
index cfeb9cd..feb2c22 100644
--- a/app/ValueObjects/Amount.php
+++ b/app/ValueObjects/Amount.php
@@ -40,4 +40,8 @@ class Amount {
public function addAmount(Amount $amount) : void {
$this->amount += $amount->getAmount();
}
+
+ public function subtractAmount(Amount $amount) : void {
+ $this->amount -= $amount->getAmount();
+ }
}
diff --git a/app/Views/Components/FullScreenModal.vue b/app/Views/Components/FullScreenModal.vue
new file mode 100644
index 0000000..2c100dc
--- /dev/null
+++ b/app/Views/Components/FullScreenModal.vue
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/Views/Components/Icon.vue b/app/Views/Components/Icon.vue
index 24996a4..559fd1d 100644
--- a/app/Views/Components/Icon.vue
+++ b/app/Views/Components/Icon.vue
@@ -7,8 +7,17 @@ const props = defineProps({
name: { type: String, required: true },
})
-if (SolidIcons[`fa${props.name.charAt(0).toUpperCase()}${props.name.slice(1)}`]) {
- library.add(SolidIcons[`fa${props.name.charAt(0).toUpperCase()}${props.name.slice(1)}`])
+function toPascalCase(str) {
+ return str
+ .split('-')
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
+ .join('')
+}
+
+const iconName = `fa${toPascalCase(props.name)}`
+
+if (SolidIcons[iconName]) {
+ library.add(SolidIcons[iconName])
}
diff --git a/app/Views/Components/PdfViewer.vue b/app/Views/Components/PdfViewer.vue
new file mode 100644
index 0000000..5c4c95f
--- /dev/null
+++ b/app/Views/Components/PdfViewer.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+ {{ page }} / {{ pages }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
index b9b69b2..50aca59 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"@inertiajs/progress": "^0.2.7",
"@inertiajs/vue3": "^2.3.12",
"vue": "^3.5.27",
- "vue3-toastify": "^0.2.8"
+ "vue3-toastify": "^0.2.8",
+ "@tato30/vue-pdf": "^2.0.0"
}
}
diff --git a/public/css/app.css b/public/css/app.css
index 1954920..b642dd1 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -153,6 +153,7 @@ th:after {
.widget-content-item td,
.widget-content-item th {
font-size: 10pt;
+ padding: 4px 0;
}
.widget-content-item label {
diff --git a/public/css/elements.css b/public/css/elements.css
index c2fe6c9..05d29b2 100644
--- a/public/css/elements.css
+++ b/public/css/elements.css
@@ -66,5 +66,6 @@ input[type="submit"]:hover {
.link {
cursor: pointer;
text-decoration: underline;
- color: #47a0d8;
+ font-weight: bold;
+ color: #2a7caf;
}
diff --git a/public/css/invoices.css b/public/css/invoices.css
index dcf1bfa..5b245ad 100644
--- a/public/css/invoices.css
+++ b/public/css/invoices.css
@@ -39,3 +39,27 @@ fieldset legend {
background-color: #ffffff;
border-radius: 10px;
}
+
+
+.invoice-list-table {
+ width: 90%;
+ margin: 20px auto;
+}
+
+.invoice-list-table td {
+ border-bottom: 1px solid #c3c4c7;
+ padding: 10px;
+}
+
+.invoice-list-table tr td:first-child {
+ border-left: 1px solid #c3c4c7;
+}
+
+.invoice-list-table tr td:last-child {
+ border-right: 1px solid #c3c4c7;
+}
+
+
+.invoice-list-table tr:first-child td {
+ background: linear-gradient(to bottom, #fff, #f6f7f7);
+}
diff --git a/routes/web.php b/routes/web.php
index 0805013..6d12720 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -26,6 +26,7 @@ Route::middleware(IdentifyTenant::class)->group(function () {
Route::get('/retrieve-text-resource/{textResource}', [GlobalDataProvider::class, 'getTextResourceText']);
Route::get('/retrieve-messages', [GlobalDataProvider::class, 'getMessages']);
Route::get('/retrieve-invoice-types', [GlobalDataProvider::class, 'getInvoiceTypes']);
+ Route::get('/retrieve-invoice-types-all', [GlobalDataProvider::class, 'getAllInvoiceTypes']);
});