Make handling of incoming invoices smoother.

This commit is contained in:
2025-02-12 19:08:33 +01:00
parent 7b4d8f7fb0
commit c5a58436e1
3 changed files with 93 additions and 46 deletions

View File

@@ -79,7 +79,7 @@ class IncomingController extends Controller
'supplier.contact_email' => 'nullable|string',
]);
$supplier = Supplier::where('name', '=', $supplierData['supplier']['name'])->firstOrNew($supplierData['supplier']);
$supplier = Supplier::updateOrCreate(['name' => $supplierData['supplier']['name']], $supplierData['supplier']);
$supplier->save();
$incomingData = $request->validate([
@@ -118,23 +118,6 @@ class IncomingController extends Controller
*/
public function update(Request $request, Incoming $incoming): JsonResponse
{
$incomingData = $request->validate([
'incoming.invoice_number' => 'required|string',
'incoming.issue_date' => 'required|date',
'incoming.due_date' => 'nullable|date',
'incoming.invoice_type_code' => 'required|string',
'incoming.currency_code' => 'required|string',
'incoming.net' => 'required|numeric',
'incoming.gross' => 'required|numeric',
'incoming.tax' => 'required|numeric',
'incoming.pay_date' => 'nullable|date',
'incoming.pay_name' => 'nullable|string',
'incoming.pay_bic' => 'nullable|string',
'incoming.pay_iban' => 'nullable|string',
]);
$incoming->update($incomingData['incoming']);
$supplierData = $request->validate([
'supplier.name' => 'required|string',
'supplier.registration_name' => 'nullable|string',
@@ -150,7 +133,25 @@ class IncomingController extends Controller
'supplier.contact_email' => 'nullable|string',
]);
$incoming->supplier()->update($supplierData['supplier']);
$supplier = Supplier::updateOrCreate(['name' => $supplierData['supplier']['name']], $supplierData['supplier']);
$incomingData = $request->validate([
'incoming.invoice_number' => 'required|string',
'incoming.issue_date' => 'required|date',
'incoming.due_date' => 'nullable|date',
'incoming.invoice_type_code' => 'required|string',
'incoming.currency_code' => 'required|string',
'incoming.net' => 'required|numeric',
'incoming.gross' => 'required|numeric',
'incoming.tax' => 'required|numeric',
'incoming.pay_date' => 'nullable|date',
'incoming.pay_name' => 'nullable|string',
'incoming.pay_bic' => 'nullable|string',
'incoming.pay_iban' => 'nullable|string',
]);
$incomingData['incoming']['supplier_id'] = $supplier->id;
$incoming->update($incomingData['incoming']);
$itemsData = $request->validate([
'items.*.name' => 'required|string',

View File

@@ -57,6 +57,7 @@ return [
'state_created' => 'Erstellt',
'state_sent' => 'Gesendet',
'state_paid' => 'Bezahlt',
'state_deleted' => 'Storniert',
'Mail' => 'E-Mail',
'Send email to your customer with attachments.' => 'E-Mail mit Anlagen an den Kunden versenden.',
'Invoice body' => 'Sehr geehrte Kundin, sehr geehrter Kunde\n\nim Anhang erhalten Sie die Rechnung :invoice_number.\n\nMit freundlichen Grüßen',

View File

@@ -84,15 +84,22 @@
autocomplete="name" x-model="incoming.pay_date"/>
</div>
<x-primary-button x-on:click="submit();" class="absolute right-0 bottom-0">{{ __('form.Save') }}</x-primary-button>
</div>
</form>
</section>
</div>
</div>
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<p class="text-red-600 font-bold mb-8" x-text="message" x-show="error"></p>
<p x-show="success" x-transition
class="text-sm text-green-600 dark:text-green-400 mb-8">{{ __('form.Saved') }}</p>
<x-primary-button @click="submit">{{ __('form.Save') }}</x-primary-button>
<x-primary-button @click="submitAndContinue">{{ __('form.SaveAndContinue') }}</x-primary-button>
</div>
<!-- Supplier data -->
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w">
@@ -107,12 +114,19 @@
<div class="flex flex-row">
<x-input-label class="w-1/6" for="select_supplier" :value="__('incoming.Select supplier')"/>
<select id="select_supplier" name="select_supplier" type="text" x-on:click="setSupplier();"
class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm">
<input list="all_suppliers" id="select_supplier" name="select_supplier" type="text" x-on:change="setSupplier();"
class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm"/>
<datalist id="all_suppliers" x-on:change="alert('hier');">
<template x-for="supplier in suppliers">
<option :value="supplier.id" x-text="supplier.name"></option>
<option x-on:click="alert('da');" :value="supplier.id" x-text="supplier.name"></option>
</template>
</select>
</datalist>
{{-- <select id="select_supplier" name="select_supplier" type="text" x-on:click="setSupplier();"--}}
{{-- class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm">--}}
{{-- <template x-for="supplier in suppliers">--}}
{{-- <option :value="supplier.id" x-text="supplier.name"></option>--}}
{{-- </template>--}}
{{-- </select>--}}
</div>
<div class="flex flex-row space-x-8 items-start">
@@ -269,23 +283,32 @@
<script>
function incomingForm() {
return {
incoming: {
incoming: {},
supplier: {},
taxes: [],
suppliers: [],
success: false,
error: false,
message: '',
init() {
this.getSuppliers();
this.incoming = this.getInitialIncoming();
this.addTax();
},
getInitialIncoming() {
return {
invoice_number: 'R01',
issue_date: "{{ \Illuminate\Support\Facades\Date::now()->format('Y-m-d') }}",
due_date: "{{ \Illuminate\Support\Facades\Date::now()->addDays(14)->format('Y-m-d') }}",
invoice_type_code: '380',
currency_code: 'EUR',
net: 0,
gross: 0,
tax: 0
},
supplier: {},
taxes: [],
suppliers: [],
init() {
this.addTax();
this.getSuppliers();
net: 0.0,
gross: 0.0,
tax: 0.0
}
},
addTax() {
@@ -314,26 +337,26 @@
},
calculateFromGross(index) {
this.taxes[index].taxable_amount = this.taxes[index].gross * 100 / (100 + parseFloat(this.taxes[index].percentage));
this.taxes[index].taxable_amount = (this.taxes[index].gross * 100 / (100 + parseFloat(this.taxes[index].percentage))).toFixed(2);
this.calculateFromNet(index);
},
calculateFromNet(index) {
this.taxes[index].amount = this.taxes[index].taxable_amount * this.taxes[index].percentage / 100;
this.taxes[index].gross = this.taxes[index].taxable_amount * (100 + parseFloat(this.taxes[index].percentage)) / 100;
this.incoming.net = 0;
this.incoming.gross = 0;
this.incoming.tax = 0;
this.taxes[index].amount = (this.taxes[index].taxable_amount * this.taxes[index].percentage / 100).toFixed(2);
this.taxes[index].gross = (this.taxes[index].taxable_amount * (100 + parseFloat(this.taxes[index].percentage)) / 100).toFixed(2);
this.incoming.net = 0.0;
this.incoming.gross = 0.0;
this.incoming.tax = 0.0;
this.calculateSum();
},
calculateSum() {
let vm = this;
this.taxes.forEach(function(tax) {
vm.incoming.tax += tax.amount * 1;
vm.incoming.net += tax.taxable_amount * 1;
vm.incoming.tax += parseFloat(tax.amount);
vm.incoming.net += parseFloat(tax.taxable_amount);
});
vm.incoming.gross += (vm.incoming.tax + vm.incoming.net);
vm.incoming.gross = (vm.incoming.tax * 1 + vm.incoming.net * 1).toFixed(2);
},
deleteTax(index) {
@@ -346,6 +369,28 @@
.then(function(response) {
window.location.href = '/incoming';
})
},
submitAndContinue() {
let vm = this;
axios.post('/incoming', {incoming: this.incoming, taxes: this.taxes, supplier: this.supplier})
.then(function(response) {
vm.success = true;
vm.error = false;
vm.message = '';
vm.taxes = [];
vm.supplier = {};
vm.incoming = vm.getInitialIncoming();
document.querySelector('#select_supplier').value = '';
vm.addTax();
window.setTimeout(function() {
vm.success = false;
}, 1000);
})
.catch(function(error) {
vm.error = true;
vm.message = error.response.data.message;
})
}
}