Extend incoming for better usage.
This commit is contained in:
17
app/Http/Controllers/Api/SupplierController.php
Normal file
17
app/Http/Controllers/Api/SupplierController.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Supplier;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
class SupplierController extends Controller
|
||||||
|
{
|
||||||
|
public function index(): JsonResponse
|
||||||
|
{
|
||||||
|
$suppliers = Supplier::orderBy('name')->get();
|
||||||
|
return response()->json($suppliers);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -22,6 +22,19 @@ class Incomingtax extends Model
|
|||||||
'currency',
|
'currency',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are appended with attribute getters.
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
protected $appends = [
|
||||||
|
'gross',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function getGrossAttribute() {
|
||||||
|
return number_format($this->taxable_amount + $this->amount, 2);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the incoming invoice this tax belongs to.
|
* Get the incoming invoice this tax belongs to.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,5 +23,7 @@ return [
|
|||||||
'Existing invoices' => 'Bestehende Eingangsrechnungen',
|
'Existing invoices' => 'Bestehende Eingangsrechnungen',
|
||||||
'Edit incoming' => 'Bestehende Eingangsrechnungen bearbeiten',
|
'Edit incoming' => 'Bestehende Eingangsrechnungen bearbeiten',
|
||||||
'Incoming data' => 'Daten der Eingangsrechnung',
|
'Incoming data' => 'Daten der Eingangsrechnung',
|
||||||
|
'Select supplier' => 'Lieferant wählen',
|
||||||
|
'Create incoming' => 'Neue Eingangsrechnung anlegen',
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<x-slot name="header">
|
<x-slot name="header">
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||||
{{ __('incoming.Edit incoming') }}
|
{{ __('incoming.Create incoming') }}
|
||||||
</h2>
|
</h2>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
|
|
||||||
@@ -105,8 +105,18 @@
|
|||||||
|
|
||||||
<form class="mt-6 space-y-6" @submit.prevent="">
|
<form class="mt-6 space-y-6" @submit.prevent="">
|
||||||
|
|
||||||
|
<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">
|
||||||
|
<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">
|
<div class="flex flex-row space-x-8 items-start">
|
||||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||||
<x-input-label for="name" :value="__('common.Name')"/>
|
<x-input-label for="name" :value="__('common.Name')"/>
|
||||||
<x-text-input id="name" name="name" type="text"
|
<x-text-input id="name" name="name" type="text"
|
||||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||||
@@ -201,6 +211,7 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="flex flex-row items-end gap-2 w-full">
|
<div class="flex flex-row items-end gap-2 w-full">
|
||||||
|
<x-input-label for="invoice_item.gross" :value="__('invoice.Gross')" class="w-1/6"/>
|
||||||
<x-input-label for="invoice_item.amount" :value="__('invoice.Net')" class="w-1/6"/>
|
<x-input-label for="invoice_item.amount" :value="__('invoice.Net')" class="w-1/6"/>
|
||||||
<x-input-label for="invoice_item.price" :value="__('configuration.Taxrate')" class="w-1/6"/>
|
<x-input-label for="invoice_item.price" :value="__('configuration.Taxrate')" class="w-1/6"/>
|
||||||
<x-input-label for="invoice_item.tax" :value="__('common.Currency code')" class="w-1/6"/>
|
<x-input-label for="invoice_item.tax" :value="__('common.Currency code')" class="w-1/6"/>
|
||||||
@@ -211,14 +222,19 @@
|
|||||||
<div>
|
<div>
|
||||||
<template x-for="(tax, index) in taxes">
|
<template x-for="(tax, index) in taxes">
|
||||||
<div class="flex flex-row items-end gap-2 w-full relative">
|
<div class="flex flex-row items-end gap-2 w-full relative">
|
||||||
|
<x-text-input id="taxes[index].gross" name="taxes[index].gross" type="number"
|
||||||
|
class="mt-1 block w-1/6"
|
||||||
|
autofocus x-on:blur="calculateFromGross(index);"
|
||||||
|
x-model="taxes[index].gross" />
|
||||||
|
|
||||||
<x-text-input id="taxes[index].taxable_amount" name="taxes[index].taxable_amount" type="number"
|
<x-text-input id="taxes[index].taxable_amount" name="taxes[index].taxable_amount" type="number"
|
||||||
class="mt-1 block w-1/6"
|
class="mt-1 block w-1/6"
|
||||||
autofocus x-on:blur="calculateTax(index);"
|
autofocus x-on:blur="calculateFromNet(index);"
|
||||||
x-model="taxes[index].taxable_amount" />
|
x-model="taxes[index].taxable_amount" />
|
||||||
|
|
||||||
<x-text-input id="taxes[index].percentage" name="taxes[index].percentage" type="number"
|
<x-text-input id="taxes[index].percentage" name="taxes[index].percentage" type="number"
|
||||||
class="mt-1 block w-1/6"
|
class="mt-1 block w-1/6"
|
||||||
autofocus x-on:blur="calculateTax(index);"
|
autofocus x-on:blur="calculateFromNet(index);"
|
||||||
x-model="taxes[index].percentage"/>
|
x-model="taxes[index].percentage"/>
|
||||||
|
|
||||||
<x-text-input id="taxes[index].currency" name="taxes[index].currency" type="text"
|
<x-text-input id="taxes[index].currency" name="taxes[index].currency" type="text"
|
||||||
@@ -265,19 +281,46 @@
|
|||||||
},
|
},
|
||||||
supplier: {},
|
supplier: {},
|
||||||
taxes: [],
|
taxes: [],
|
||||||
|
suppliers: [],
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.addTax();
|
||||||
|
this.getSuppliers();
|
||||||
|
},
|
||||||
|
|
||||||
addTax() {
|
addTax() {
|
||||||
let tax = {
|
let tax = {
|
||||||
|
gross: 0,
|
||||||
taxable_amount: 0,
|
taxable_amount: 0,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
percentage: 0,
|
percentage: 19,
|
||||||
currency: this.incoming.currency_code
|
currency: this.incoming.currency_code
|
||||||
};
|
};
|
||||||
this.taxes.push(tax);
|
this.taxes.push(tax);
|
||||||
},
|
},
|
||||||
|
|
||||||
calculateTax(index) {
|
getSuppliers() {
|
||||||
|
let vm = this;
|
||||||
|
axios.get('/supplier')
|
||||||
|
.then(function(response) {
|
||||||
|
vm.suppliers = response.data;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
setSupplier() {
|
||||||
|
let id = document.querySelector('#select_supplier').value;
|
||||||
|
let supplier_key = Object.keys(this.suppliers).find(key => (this.suppliers[key].id == id));
|
||||||
|
this.supplier = this.suppliers[supplier_key];
|
||||||
|
},
|
||||||
|
|
||||||
|
calculateFromGross(index) {
|
||||||
|
this.taxes[index].taxable_amount = this.taxes[index].gross * 100 / (100 + parseFloat(this.taxes[index].percentage));
|
||||||
|
this.calculateFromNet(index);
|
||||||
|
},
|
||||||
|
|
||||||
|
calculateFromNet(index) {
|
||||||
this.taxes[index].amount = this.taxes[index].taxable_amount * this.taxes[index].percentage / 100;
|
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.net = 0;
|
||||||
this.incoming.gross = 0;
|
this.incoming.gross = 0;
|
||||||
this.incoming.tax = 0;
|
this.incoming.tax = 0;
|
||||||
|
|||||||
@@ -105,6 +105,16 @@
|
|||||||
|
|
||||||
<form class="mt-6 space-y-6" @submit.prevent="">
|
<form class="mt-6 space-y-6" @submit.prevent="">
|
||||||
|
|
||||||
|
<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">
|
||||||
|
<template x-for="sup in suppliers">
|
||||||
|
<option :value="sup.id" :selected="sup.id == supplier.id" x-text="sup.name"></option>
|
||||||
|
</template>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row space-x-8 items-start">
|
<div class="flex flex-row space-x-8 items-start">
|
||||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||||
<x-input-label for="name" :value="__('common.Name')"/>
|
<x-input-label for="name" :value="__('common.Name')"/>
|
||||||
@@ -273,7 +283,6 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -290,29 +299,30 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="flex flex-row items-end gap-2 w-full">
|
<div class="flex flex-row items-end gap-2 w-full">
|
||||||
|
<x-input-label for="invoice_item.gross" :value="__('invoice.Gross')" class="w-1/6"/>
|
||||||
<x-input-label for="invoice_item.amount" :value="__('invoice.Net')" class="w-1/6"/>
|
<x-input-label for="invoice_item.amount" :value="__('invoice.Net')" class="w-1/6"/>
|
||||||
<x-input-label for="invoice_item.name" :value="__('invoice.Tax')" class="w-1/6"/>
|
|
||||||
<x-input-label for="invoice_item.price" :value="__('configuration.Taxrate')" class="w-1/6"/>
|
<x-input-label for="invoice_item.price" :value="__('configuration.Taxrate')" class="w-1/6"/>
|
||||||
<x-input-label for="invoice_item.tax" :value="__('common.Currency code')" class="w-1/6"/>
|
<x-input-label for="invoice_item.tax" :value="__('common.Currency code')" class="w-1/6"/>
|
||||||
|
<x-input-label for="invoice_item.name" :value="__('invoice.Tax')" class="w-1/6"/>
|
||||||
<div class="w-1/12 relative h-10"></div>
|
<div class="w-1/12 relative h-10"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<template x-for="(tax, index) in taxes">
|
<template x-for="(tax, index) in taxes">
|
||||||
<div class="flex flex-row items-end gap-2 w-full relative">
|
<div class="flex flex-row items-end gap-2 w-full relative">
|
||||||
|
<x-text-input id="taxes[index].gross" name="taxes[index].gross" type="number"
|
||||||
|
class="mt-1 block w-1/6"
|
||||||
|
autofocus x-on:blur="calculateFromGross(index);"
|
||||||
|
x-model="taxes[index].gross"/>
|
||||||
|
|
||||||
<x-text-input id="taxes[index].taxable_amount" name="taxes[index].taxable_amount" type="number"
|
<x-text-input id="taxes[index].taxable_amount" name="taxes[index].taxable_amount" type="number"
|
||||||
class="mt-1 block w-1/6"
|
class="mt-1 block w-1/6"
|
||||||
autofocus
|
autofocus x-on:blur="calculateFromNet(index);"
|
||||||
x-model="taxes[index].taxable_amount"/>
|
x-model="taxes[index].taxable_amount"/>
|
||||||
|
|
||||||
<x-text-input id="taxes[index].amount" name="taxes[index].amount" type="number"
|
|
||||||
class="mt-1 block w-1/6"
|
|
||||||
autofocus
|
|
||||||
x-model="taxes[index].amount"/>
|
|
||||||
|
|
||||||
<x-text-input id="taxes[index].percentage" name="taxes[index].percentage" type="number"
|
<x-text-input id="taxes[index].percentage" name="taxes[index].percentage" type="number"
|
||||||
class="mt-1 block w-1/6"
|
class="mt-1 block w-1/6"
|
||||||
autofocus
|
autofocus x-on:blur="calculateFromNet(index);"
|
||||||
x-model="taxes[index].percentage"/>
|
x-model="taxes[index].percentage"/>
|
||||||
|
|
||||||
<x-text-input id="taxes[index].currency" name="taxes[index].currency" type="text"
|
<x-text-input id="taxes[index].currency" name="taxes[index].currency" type="text"
|
||||||
@@ -321,6 +331,11 @@
|
|||||||
placeholder="{{ __('invoice.Name') }}"
|
placeholder="{{ __('invoice.Name') }}"
|
||||||
x-model="taxes[index].currency"/>
|
x-model="taxes[index].currency"/>
|
||||||
|
|
||||||
|
<x-text-input id="taxes[index].amount" name="taxes[index].amount" type="number"
|
||||||
|
class="mt-1 block w-1/6"
|
||||||
|
autofocus disabled
|
||||||
|
x-model="taxes[index].amount"/>
|
||||||
|
|
||||||
<div class="flex flex-row w-1/12 h-10 relative">
|
<div class="flex flex-row w-1/12 h-10 relative">
|
||||||
<x-danger-button x-on:click="deleteTax(index);" class="absolute right-0">
|
<x-danger-button x-on:click="deleteTax(index);" class="absolute right-0">
|
||||||
-
|
-
|
||||||
@@ -347,6 +362,44 @@
|
|||||||
supplier: {!! $supplier !!},
|
supplier: {!! $supplier !!},
|
||||||
items: {!! $items !!},
|
items: {!! $items !!},
|
||||||
taxes: {!! $taxes !!},
|
taxes: {!! $taxes !!},
|
||||||
|
suppliers: [],
|
||||||
|
|
||||||
|
init() {
|
||||||
|
let vm = this;
|
||||||
|
axios.get('/supplier')
|
||||||
|
.then(function(response) {
|
||||||
|
vm.suppliers = response.data;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
setSupplier() {
|
||||||
|
let id = document.querySelector('#select_supplier').value;
|
||||||
|
let supplier_key = Object.keys(this.suppliers).find(key => (this.suppliers[key].id == id));
|
||||||
|
this.supplier = this.suppliers[supplier_key];
|
||||||
|
},
|
||||||
|
|
||||||
|
calculateFromGross(index) {
|
||||||
|
this.taxes[index].taxable_amount = this.taxes[index].gross * 100 / (100 + parseFloat(this.taxes[index].percentage));
|
||||||
|
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.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.gross += (vm.incoming.tax + vm.incoming.net);
|
||||||
|
},
|
||||||
|
|
||||||
addItem() {
|
addItem() {
|
||||||
let item = {
|
let item = {
|
||||||
@@ -366,9 +419,10 @@
|
|||||||
addTax() {
|
addTax() {
|
||||||
let tax = {
|
let tax = {
|
||||||
incoming_id: this.incoming_id,
|
incoming_id: this.incoming_id,
|
||||||
|
gross: 0,
|
||||||
taxable_amount: 0,
|
taxable_amount: 0,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
percentage: 0,
|
percentage: 19,
|
||||||
currency: 'EUR'
|
currency: 'EUR'
|
||||||
};
|
};
|
||||||
this.taxes.push(tax);
|
this.taxes.push(tax);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use App\Http\Controllers\Api\MailController;
|
|||||||
use App\Http\Controllers\Api\OptionController;
|
use App\Http\Controllers\Api\OptionController;
|
||||||
use App\Http\Controllers\Api\PaymentController;
|
use App\Http\Controllers\Api\PaymentController;
|
||||||
use App\Http\Controllers\Api\ProjectController;
|
use App\Http\Controllers\Api\ProjectController;
|
||||||
|
use App\Http\Controllers\Api\SupplierController;
|
||||||
use App\Http\Controllers\Api\TaxrateController;
|
use App\Http\Controllers\Api\TaxrateController;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
@@ -51,6 +52,7 @@ Route::group(['as' => 'api.'], function () {
|
|||||||
Route::post('/incoming', [IncomingController::class, 'store'])->name('incoming.store');
|
Route::post('/incoming', [IncomingController::class, 'store'])->name('incoming.store');
|
||||||
Route::apiResource('/project', ProjectController::class);
|
Route::apiResource('/project', ProjectController::class);
|
||||||
Route::apiResource('/dashboard', DashboardController::class)->only(['index', 'update']);
|
Route::apiResource('/dashboard', DashboardController::class)->only(['index', 'update']);
|
||||||
|
Route::apiResource('/supplier', SupplierController::class)->only(['index']);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user