Compare commits

...

4 Commits

Author SHA1 Message Date
3695b012d5 Extend editing invoices.
All checks were successful
Build project image / Build-and-release-image (push) Successful in 5m31s
2025-04-02 14:54:31 +02:00
2334ed0ede Merge remote-tracking branch 'origin/master' 2025-04-02 14:54:12 +02:00
286de46e3d Make incoming invoices searchable. 2025-02-13 17:41:39 +01:00
9cb9c4de23 Code formatting. 2025-02-13 17:41:06 +01:00
4 changed files with 52 additions and 9 deletions

View File

@@ -72,6 +72,9 @@ class InvoiceController extends Controller
'customer_id' => 'required|integer|exists:customers,id', 'customer_id' => 'required|integer|exists:customers,id',
'address_id' => 'required|integer|exists:addresses,id', 'address_id' => 'required|integer|exists:addresses,id',
'delivery_id' => 'nullable|integer|exists:addresses,id', 'delivery_id' => 'nullable|integer|exists:addresses,id',
'project_id' => 'nullable|integer|exists:projects,id',
'currency_code' => 'required|string',
'type' => [Rule::enum(InvoiceTypeCode::class)],
'tax' => 'required|numeric', 'tax' => 'required|numeric',
'sum' => 'required|numeric', 'sum' => 'required|numeric',
'due_date' => 'required|date', 'due_date' => 'required|date',

View File

@@ -12,6 +12,7 @@ return [
*/ */
'Incoming' => 'Eingang', 'Incoming' => 'Eingang',
'Search invoice' => 'Rechnung suchen',
'Add new invoice' => 'Neue Eingangsrechnung manuell anlegen', 'Add new invoice' => 'Neue Eingangsrechnung manuell anlegen',
'Add new invoice by clicking add' => 'Neue Eingangsrechnung durch Klick auf "Anlegen" erstellen. Die Daten zur Rechnung müssen händisch eingegeben werden.', 'Add new invoice by clicking add' => 'Neue Eingangsrechnung durch Klick auf "Anlegen" erstellen. Die Daten zur Rechnung müssen händisch eingegeben werden.',
'Upload new invoice' => 'Neue Eingangsrechnung hochladen', 'Upload new invoice' => 'Neue Eingangsrechnung hochladen',

View File

@@ -135,6 +135,7 @@
.includes(this.search_customer.replace(/ /g, '').toLowerCase()) .includes(this.search_customer.replace(/ /g, '').toLowerCase())
}); });
}, },
deleteCustomer(index) { deleteCustomer(index) {
let vm = this; let vm = this;
let customer_key = Object.keys(this.customers).find(key => (this.customers[key].id == this.getFilteredCustomers()[index].id)); let customer_key = Object.keys(this.customers).find(key => (this.customers[key].id == this.getFilteredCustomers()[index].id));

View File

@@ -23,7 +23,9 @@
{{ __("incoming.Add new invoice by clicking add") }} {{ __("incoming.Add new invoice by clicking add") }}
</p> </p>
</header> </header>
<a class="mt-6 inline-block" href="{{ route('incoming.create') }}"><x-primary-button>{{ __('form.Add') }}</x-primary-button></a> <a class="mt-6 inline-block" href="{{ route('incoming.create') }}">
<x-primary-button>{{ __('form.Add') }}</x-primary-button>
</a>
</section> </section>
<section class="w-1/2"> <section class="w-1/2">
<header> <header>
@@ -35,7 +37,9 @@
{{ __("incoming.Upload new xml invoice by clicking upload") }} {{ __("incoming.Upload new xml invoice by clicking upload") }}
</p> </p>
</header> </header>
<a class="mt-6 inline-block" href="{{ route('incoming.upload') }}"><x-primary-button>{{ __('form.Upload') }}</x-primary-button></a> <a class="mt-6 inline-block" href="{{ route('incoming.upload') }}">
<x-primary-button>{{ __('form.Upload') }}</x-primary-button>
</a>
</section> </section>
</div> </div>
</div> </div>
@@ -47,11 +51,26 @@
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100"> <h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('incoming.Existing invoices') }} {{ __('incoming.Existing invoices') }}
</h2> </h2>
<div class="flex flex-row space-x-4 items-center mt-4"> <div class="grid grid-cols-2">
<x-input-label for="from" :value="__('invoice.From')"/> <div class="flex flex-row space-x-4 items-center mt-4">
<x-text-input type="date" id="from" name="from" x-model="from" x-on:change="fetchInvoices()"/> <x-input-label for="from" :value="__('invoice.From')"/>
<x-input-label for="end" :value="__('invoice.End')"/> <x-text-input type="date" id="from" name="from" x-model="from"
<x-text-input type="date" id="end" name="end" x-model="end" x-on:change="fetchInvoices()"/> x-on:change="fetchInvoices()"/>
<x-input-label for="end" :value="__('invoice.End')"/>
<x-text-input type="date" id="end" name="end" x-model="end"
x-on:change="fetchInvoices()"/>
</div>
<div class="flex flex-row items-center gap-8">
<x-input-label for="search_invoice" :value="__('common.Search')"/>
<x-text-input id="search_invoice" name="search_invoice" type="text"
class="mt-1 block w-full"
x-ref="search_invoice"
autofocus
placeholder="{{ __('incoming.Search invoice') }}"
x-on:keydown.window.prevent.slash="$refs.search_invoice.focus()"
x-model="search_invoice"/>
</div>
</div> </div>
</header> </header>
@@ -63,9 +82,10 @@
<div class="w-1/12 font-bold border-b-2 text-right">{{ __('common.Paid at') }}</div> <div class="w-1/12 font-bold border-b-2 text-right">{{ __('common.Paid at') }}</div>
</summary> </summary>
<template x-for="invoice in invoices"> <template x-for="invoice in getFilteredInvoices()">
<details class="even:bg-gray-100 odd:bg-white hover:bg-gray-400"> <details class="even:bg-gray-100 odd:bg-white hover:bg-gray-400">
<summary class="cursor-pointer flex flex-row w-full" @click="window.location.href='/incoming/' + invoice.id + '/edit';"> <summary class="cursor-pointer flex flex-row w-full"
@click="window.location.href='/incoming/' + invoice.id + '/edit';">
<div class="w-1/3" x-text="invoice.invoice_number"></div> <div class="w-1/3" x-text="invoice.invoice_number"></div>
<div class="w-1/3" x-text="invoice.supplier.name"></div> <div class="w-1/3" x-text="invoice.supplier.name"></div>
<div class="w-1/6 text-right" x-text="invoice.gross + ' €'"></div> <div class="w-1/6 text-right" x-text="invoice.gross + ' €'"></div>
@@ -108,6 +128,8 @@
from: "{{ $first }}", from: "{{ $first }}",
end: "{{ $last }}", end: "{{ $last }}",
invoices: [], invoices: [],
search_invoice: '',
init() { init() {
this.fetchInvoices(); this.fetchInvoices();
@@ -125,6 +147,22 @@
}) })
}, },
getFilteredInvoices() {
if (this.search_invoice === '') {
return this.invoices;
}
return this.invoices.filter((invoice) => {
return invoice.supplier.name
.replace(/ /g, '')
.toLowerCase()
.includes(this.search_invoice.replace(/ /g, '').toLowerCase())
|| invoice.invoice_number
.replace(/ /g, '')
.toLowerCase()
.includes(this.search_invoice.replace(/ /g, '').toLowerCase())
});
},
calculateSum() { calculateSum() {
this.net = 0; this.net = 0;
this.gross = 0; this.gross = 0;