Build the stuff for incoming invoices.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
$customers = \App\Models\Customer::doesntHave('address')->get();
|
||||
$created_invoices = \App\Models\Invoice::where('status', '=', 'created')->orderBy('created_at')->get();
|
||||
$sent_invoices = \App\Models\Invoice::where('status', '=', 'sent')->orderBy('created_at')->get();
|
||||
|
||||
$unpaid_incoming = \App\Models\Incoming::where('pay_date', '=', null)->orderBy('due_date')->get();
|
||||
@endphp
|
||||
|
||||
<x-app-layout>
|
||||
@@ -24,7 +24,7 @@
|
||||
class="flex max-w even:bg-gray-100 odd:bg-white">
|
||||
<div class="w-1/4">{{ $invoice->number }}</div>
|
||||
<div class="w-1/4">{{ $invoice->address->name }}</div>
|
||||
<div class="w-1/4">{{ $invoice->sum }}</div>
|
||||
<div class="w-1/4">{{ \Illuminate\Support\Number::currency($invoice->sum) }}</div>
|
||||
<div class="w-1/4">{{ $invoice->created }}</div>
|
||||
</a>
|
||||
@endforeach
|
||||
@@ -59,6 +59,22 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Incoming invoices, that are not paid -->
|
||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg col-span-2">
|
||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||
<h2 class="mb-4 text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('dashboard.Incoming not paid') }}</h2>
|
||||
@foreach($unpaid_incoming as $incoming)
|
||||
<a href="{{ route('incoming.edit', $incoming->id) }}"
|
||||
class="flex max-w even:bg-gray-100 odd:bg-white">
|
||||
<div class="w-1/6">{{ $incoming->invoice_number }}</div>
|
||||
<div class="w-1/2">{{ $incoming->supplier->name }}</div>
|
||||
<div class="w-1/6">{{ \Illuminate\Support\Number::currency($incoming->gross) }}</div>
|
||||
<div class="w-1/6">{{ $incoming->due }}</div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
<select name="report" id="report" x-model="data.report" 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 w-1/4">
|
||||
<option value="invoice">{{ __('excel.Outgoing invoices') }}</option>
|
||||
<option value="payment">{{ __('excel.Incoming payments') }}</option>
|
||||
<option value="incoming">{{ __('excel.Incoming by issue date') }}</option>
|
||||
<option value="outgoing">{{ __('excel.Outgoing by pay date') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</header>
|
||||
@@ -60,7 +62,6 @@
|
||||
let vm = this;
|
||||
axios.post('/excel', this.data, {responseType: "blob"})
|
||||
.then(function(response) {
|
||||
console.log(response);
|
||||
let url = window.URL.createObjectURL(response.data);
|
||||
let a = document.createElement('a');
|
||||
a.href = url;
|
||||
@@ -71,6 +72,12 @@
|
||||
if (vm.data.report === 'payment') {
|
||||
a.download = '{{ __('invoice.Payments') }}' + '.xlsx';
|
||||
}
|
||||
if (vm.data.report === 'incoming') {
|
||||
a.download = '{{ __('incoming.Incoming') }}' + '.xlsx';
|
||||
}
|
||||
if (vm.data.report === 'outgoing') {
|
||||
a.download = '{{ __('incoming.Outgoing') }}' + '.xlsx';
|
||||
}
|
||||
let download = document.querySelector('#download');
|
||||
download.appendChild(a);
|
||||
a.click();
|
||||
|
||||
310
resources/views/incoming/create.blade.php
Normal file
310
resources/views/incoming/create.blade.php
Normal file
@@ -0,0 +1,310 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
{{ __('incoming.Edit incoming') }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12" x-data="incomingForm()">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
||||
|
||||
<!-- Incoming data -->
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('incoming.Incoming data') }}
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<form class="mt-6 space-y-6" @submit.prevent="">
|
||||
|
||||
<div class="flex flex-row space-x-8 items-start relative">
|
||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||
<x-input-label for="name" :value="__('invoice.Invoice Number')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.invoice_number"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Invoice Date')"/>
|
||||
<x-text-input id="name" name="name" type="date"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.issue_date"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Invoice Due date')"/>
|
||||
<x-text-input id="name" name="name" type="date"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.due_date"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Type code')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus disabled
|
||||
autocomplete="name" x-model="incoming.invoice_type_code"/>
|
||||
|
||||
<x-input-label for="name" :value="__('common.Currency code')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus disabled
|
||||
autocomplete="name" x-model="incoming.currency_code"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Net')"/>
|
||||
<x-text-input id="name" name="name" type="number" step="0.01"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus disabled
|
||||
autocomplete="net" x-model="incoming.net"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Gross')"/>
|
||||
<x-text-input id="name" name="name" type="number" step="0.01"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus disabled
|
||||
autocomplete="gross" x-model="incoming.gross"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Tax')"/>
|
||||
<x-text-input id="name" name="name" type="number" step="0.01"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus disabled
|
||||
autocomplete="tax" x-model="incoming.tax"/>
|
||||
</div>
|
||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||
<x-input-label for="name" :value="__('invoice.Account holder')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.pay_name"/>
|
||||
|
||||
<x-input-label for="name" :value="__('configuration.IBAN')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.pay_iban"/>
|
||||
|
||||
<x-input-label for="name" :value="__('configuration.BIC')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.pay_bic"/>
|
||||
|
||||
<x-input-label for="name" :value="__('common.Paid at')"/>
|
||||
<x-text-input id="name" name="name" type="date"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
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>
|
||||
|
||||
<!-- Supplier data -->
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('supplier.Supplier') }}
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<form class="mt-6 space-y-6" @submit.prevent="">
|
||||
|
||||
<div class="flex flex-row space-x-8 items-start">
|
||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||
<x-input-label for="name" :value="__('common.Name')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="supplier.name"/>
|
||||
|
||||
<x-input-label for="registration_name" :value="__('common.Registration name')"/>
|
||||
<x-text-input id="registration_name" name="registration_name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('registration_name')" autofocus
|
||||
autocomplete="registration_name"
|
||||
x-model="supplier.registration_name"/>
|
||||
|
||||
<x-input-label for="email" :value="__('common.Email')"/>
|
||||
<x-text-input id="email" name="email" type="email"
|
||||
class="mt-1 col-span-2" :value="old('email')"
|
||||
autocomplete="email" x-model="supplier.email"/>
|
||||
|
||||
<x-input-label for="address" :value="__('common.Address')"/>
|
||||
<x-text-input id="address" name="address" type="text"
|
||||
class="mt-1 col-span-2" :value="old('address')"
|
||||
autocomplete="address"
|
||||
x-model="supplier.address"/>
|
||||
|
||||
<x-input-label for="zip" :value="__('common.Zip Code')"/>
|
||||
<x-text-input id="zip" name="zip" type="text"
|
||||
class="mt-1 col-span-2" :value="old('zip')"
|
||||
autocomplete="zip"
|
||||
x-model="supplier.zip"/>
|
||||
|
||||
<x-input-label for="city" :value="__('common.City')"/>
|
||||
<x-text-input id="city" name="city" type="text"
|
||||
class="mt-1 col-span-2" :value="old('city')"
|
||||
autocomplete="city"
|
||||
x-model="supplier.city"/>
|
||||
</div>
|
||||
|
||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||
<x-input-label for="country_code" :value="__('common.Country code')"/>
|
||||
<x-text-input id="country_code" name="country_code" type="text"
|
||||
class="mt-1 col-span-2" :value="old('country_code')"
|
||||
autocomplete="country_code"
|
||||
x-model="supplier.country_code"/>
|
||||
|
||||
<x-input-label for="tax_fc" :value="__('common.Tax FC')"/>
|
||||
<x-text-input id="tax_fc" name="tax_fc" type="text"
|
||||
class="mt-1 col-span-2" :value="old('tax_fc')"
|
||||
autocomplete="tax_fc"
|
||||
x-model="supplier.tax_fc"/>
|
||||
|
||||
<x-input-label for="tax_vat" :value="__('common.Tax VAT')"/>
|
||||
<x-text-input id="tax_vat" name="tax_vat" type="text"
|
||||
class="mt-1 col-span-2" :value="old('tax_vat')"
|
||||
autocomplete="tax_vat"
|
||||
x-model="supplier.tax_vat"/>
|
||||
|
||||
<x-input-label for="contact_name" :value="__('common.Contact name')"/>
|
||||
<x-text-input id="contact_name" name="contact_name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('contact_name')"
|
||||
autocomplete="contact_name"
|
||||
x-model="supplier.contact_name"/>
|
||||
|
||||
<x-input-label for="contact_phone" :value="__('common.Contact phone')"/>
|
||||
<x-text-input id="contact_phone" name="contact_phone" type="text"
|
||||
class="mt-1 col-span-2" :value="old('contact_phone')"
|
||||
autocomplete="contact_phone"
|
||||
x-model="supplier.contact_phone"/>
|
||||
|
||||
<x-input-label for="contact_email" :value="__('common.Contact email')"/>
|
||||
<x-text-input id="contact_email" name="t" type="email"
|
||||
class="mt-1 col-span-2" :value="old('contact_email')"
|
||||
autocomplete="contact_email"
|
||||
x-model="supplier.contact_email"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Incoming taxes -->
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100 relative">
|
||||
{{ __('invoice.Tax items') }}
|
||||
<x-primary-button x-on:click="addTax();" class="absolute right-0">+</x-primary-button>
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<div class="flex flex-row items-end gap-2 w-full">
|
||||
<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.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>
|
||||
|
||||
<div>
|
||||
<template x-for="(tax, index) in taxes">
|
||||
<div class="flex flex-row items-end gap-2 w-full relative">
|
||||
<x-text-input id="taxes[index].taxable_amount" name="taxes[index].taxable_amount" type="number"
|
||||
class="mt-1 block w-1/6"
|
||||
autofocus x-on:blur="calculateTax(index);"
|
||||
x-model="taxes[index].taxable_amount" />
|
||||
|
||||
<x-text-input id="taxes[index].percentage" name="taxes[index].percentage" type="number"
|
||||
class="mt-1 block w-1/6"
|
||||
autofocus x-on:blur="calculateTax(index);"
|
||||
x-model="taxes[index].percentage"/>
|
||||
|
||||
<x-text-input id="taxes[index].currency" name="taxes[index].currency" type="text"
|
||||
class="mt-1 block w-1/6"
|
||||
autofocus disabled
|
||||
placeholder="{{ __('invoice.Name') }}"
|
||||
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">
|
||||
<x-danger-button x-on:click="deleteTax(index);" class="absolute right-0">
|
||||
-
|
||||
</x-danger-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
||||
<script>
|
||||
function incomingForm() {
|
||||
return {
|
||||
incoming: {
|
||||
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: [],
|
||||
|
||||
addTax() {
|
||||
let tax = {
|
||||
taxable_amount: 0,
|
||||
amount: 0,
|
||||
percentage: 0,
|
||||
currency: this.incoming.currency_code
|
||||
};
|
||||
this.taxes.push(tax);
|
||||
},
|
||||
|
||||
calculateTax(index) {
|
||||
this.taxes[index].amount = this.taxes[index].taxable_amount * 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);
|
||||
},
|
||||
|
||||
deleteTax(index) {
|
||||
this.taxes.splice(index, 1);
|
||||
this.calculateSum();
|
||||
},
|
||||
|
||||
submit() {
|
||||
axios.post('/incoming', {incoming: this.incoming, taxes: this.taxes, supplier: this.supplier})
|
||||
.then(function(response) {
|
||||
window.location.href = '/incoming';
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
394
resources/views/incoming/edit.blade.php
Normal file
394
resources/views/incoming/edit.blade.php
Normal file
@@ -0,0 +1,394 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
{{ __('incoming.Edit incoming') }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12" x-data="incomingForm()">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
||||
|
||||
<!-- Incoming data -->
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('incoming.Incoming data') }}
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<form class="mt-6 space-y-6" @submit.prevent="">
|
||||
|
||||
<div class="flex flex-row space-x-8 items-start relative">
|
||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||
<x-input-label for="name" :value="__('invoice.Invoice Number')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.invoice_number"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Invoice Date')"/>
|
||||
<x-text-input id="name" name="name" type="date"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.issue_date"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Invoice Due date')"/>
|
||||
<x-text-input id="name" name="name" type="date"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.due_date"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Type code')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.invoice_type_code"/>
|
||||
|
||||
<x-input-label for="name" :value="__('common.Currency code')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.currency_code"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Net')"/>
|
||||
<x-text-input id="name" name="name" type="number" step="0.01"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.net"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Gross')"/>
|
||||
<x-text-input id="name" name="name" type="number" step="0.01"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.gross"/>
|
||||
|
||||
<x-input-label for="name" :value="__('invoice.Tax')"/>
|
||||
<x-text-input id="name" name="name" type="number" step="0.01"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.tax"/>
|
||||
</div>
|
||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||
<x-input-label for="name" :value="__('invoice.Account holder')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.pay_name"/>
|
||||
|
||||
<x-input-label for="name" :value="__('configuration.IBAN')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.pay_iban"/>
|
||||
|
||||
<x-input-label for="name" :value="__('configuration.BIC')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="incoming.pay_bic"/>
|
||||
|
||||
<x-input-label for="name" :value="__('common.Paid at')"/>
|
||||
<x-text-input id="name" name="name" type="date"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
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>
|
||||
|
||||
<!-- Supplier data -->
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('supplier.Supplier') }}
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<form class="mt-6 space-y-6" @submit.prevent="">
|
||||
|
||||
<div class="flex flex-row space-x-8 items-start">
|
||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||
<x-input-label for="name" :value="__('common.Name')"/>
|
||||
<x-text-input id="name" name="name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('name')" autofocus
|
||||
autocomplete="name" x-model="supplier.name"/>
|
||||
|
||||
<x-input-label for="registration_name" :value="__('common.Registration name')"/>
|
||||
<x-text-input id="registration_name" name="registration_name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('registration_name')" autofocus
|
||||
autocomplete="registration_name"
|
||||
x-model="supplier.registration_name"/>
|
||||
|
||||
<x-input-label for="email" :value="__('common.Email')"/>
|
||||
<x-text-input id="email" name="email" type="email"
|
||||
class="mt-1 col-span-2" :value="old('email')"
|
||||
autocomplete="email" x-model="supplier.email"/>
|
||||
|
||||
<x-input-label for="address" :value="__('common.Address')"/>
|
||||
<x-text-input id="address" name="address" type="text"
|
||||
class="mt-1 col-span-2" :value="old('address')"
|
||||
autocomplete="address"
|
||||
x-model="supplier.address"/>
|
||||
|
||||
<x-input-label for="zip" :value="__('common.Zip Code')"/>
|
||||
<x-text-input id="zip" name="zip" type="text"
|
||||
class="mt-1 col-span-2" :value="old('zip')"
|
||||
autocomplete="zip"
|
||||
x-model="supplier.zip"/>
|
||||
|
||||
<x-input-label for="city" :value="__('common.City')"/>
|
||||
<x-text-input id="city" name="city" type="text"
|
||||
class="mt-1 col-span-2" :value="old('city')"
|
||||
autocomplete="city"
|
||||
x-model="supplier.city"/>
|
||||
</div>
|
||||
|
||||
<div class="w-1/2 grid grid-cols-3 items-center">
|
||||
<x-input-label for="country_code" :value="__('common.Country code')"/>
|
||||
<x-text-input id="country_code" name="country_code" type="text"
|
||||
class="mt-1 col-span-2" :value="old('country_code')"
|
||||
autocomplete="country_code"
|
||||
x-model="supplier.country_code"/>
|
||||
|
||||
<x-input-label for="tax_fc" :value="__('common.Tax FC')"/>
|
||||
<x-text-input id="tax_fc" name="tax_fc" type="text"
|
||||
class="mt-1 col-span-2" :value="old('tax_fc')"
|
||||
autocomplete="tax_fc"
|
||||
x-model="supplier.tax_fc"/>
|
||||
|
||||
<x-input-label for="tax_vat" :value="__('common.Tax VAT')"/>
|
||||
<x-text-input id="tax_vat" name="tax_vat" type="text"
|
||||
class="mt-1 col-span-2" :value="old('tax_vat')"
|
||||
autocomplete="tax_vat"
|
||||
x-model="supplier.tax_vat"/>
|
||||
|
||||
<x-input-label for="contact_name" :value="__('common.Contact name')"/>
|
||||
<x-text-input id="contact_name" name="contact_name" type="text"
|
||||
class="mt-1 col-span-2" :value="old('contact_name')"
|
||||
autocomplete="contact_name"
|
||||
x-model="supplier.contact_name"/>
|
||||
|
||||
<x-input-label for="contact_phone" :value="__('common.Contact phone')"/>
|
||||
<x-text-input id="contact_phone" name="contact_phone" type="text"
|
||||
class="mt-1 col-span-2" :value="old('contact_phone')"
|
||||
autocomplete="contact_phone"
|
||||
x-model="supplier.contact_phone"/>
|
||||
|
||||
<x-input-label for="contact_email" :value="__('common.Contact email')"/>
|
||||
<x-text-input id="contact_email" name="t" type="email"
|
||||
class="mt-1 col-span-2" :value="old('contact_email')"
|
||||
autocomplete="contact_email"
|
||||
x-model="supplier.contact_email"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Incoming items -->
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100 relative">
|
||||
{{ __('invoice.Invoice items') }}
|
||||
<x-primary-button x-on:click="addItem();" class="absolute right-0">+</x-primary-button>
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<div class="flex flex-row items-end gap-2 w-full">
|
||||
<x-input-label for="invoice_item.amount" :value="__('invoice.Amount')" class="w-1/12"/>
|
||||
<x-input-label for="invoice_item.name" :value="__('invoice.Name') . ' / ' . __('invoice.Article number') . ' / ' . __('invoice.Description')" class="w-1/2"/>
|
||||
<x-input-label for="invoice_item.price" :value="__('invoice.Price')" class="w-1/12"/>
|
||||
<x-input-label for="invoice_item.discount" :value="__('invoice.Discount')" class="w-1/12"/>
|
||||
<x-input-label for="invoice_item.tax" :value="__('invoice.Tax')" class="w-1/12"/>
|
||||
<x-input-label for="invoice_item.tax" :value="__('invoice.Net')" class="w-1/12"/>
|
||||
<div class="w-1/12 relative h-10"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<template x-for="(item, index) in items">
|
||||
<div>
|
||||
<div class="flex flex-row items-end gap-2 w-full relative">
|
||||
<x-text-input id="items[index].amount" name="items[index].amount" type="number"
|
||||
class="mt-1 block w-1/12"
|
||||
autofocus
|
||||
x-model="items[index].amount"/>
|
||||
|
||||
<x-text-input id="items[index].name" name="items[index].name" type="text"
|
||||
class="mt-1 block w-1/2"
|
||||
autofocus
|
||||
placeholder="{{ __('invoice.Name') }}"
|
||||
x-model="items[index].name"/>
|
||||
|
||||
<x-text-input id="items[index].price" name="items[index].price" type="number"
|
||||
class="mt-1 block w-1/12"
|
||||
autofocus
|
||||
x-model="items[index].price"/>
|
||||
|
||||
<x-text-input id="items[index].discount" name="items[index].discount" type="number"
|
||||
class="mt-1 block w-1/12"
|
||||
autofocus
|
||||
x-model="items[index].discount"/>
|
||||
|
||||
<x-text-input id="items[index].tax" name="items[index].tax" type="number"
|
||||
class="mt-1 block w-1/12"
|
||||
autofocus
|
||||
x-model="items[index].tax"/>
|
||||
|
||||
<x-text-input id="items[index].total" name="items[index].total" type="number"
|
||||
class="mt-1 block w-1/12"
|
||||
autofocus
|
||||
x-model="items[index].total"/>
|
||||
|
||||
<div class="flex flex-row w-1/12 h-10 relative">
|
||||
<x-danger-button x-on:click="deleteItem(index);" class="absolute right-0">
|
||||
-
|
||||
</x-danger-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div class="w-1/12"></div>
|
||||
<div class="flex flex-col w-1/2 gap-2">
|
||||
<x-text-input id="items[index].article_number" name="items[index].article_number" type="text"
|
||||
class="mt-1 block full+"
|
||||
autofocus
|
||||
placeholder="{{ __('invoice.Article number') }}"
|
||||
x-model="items[index].article_number"/>
|
||||
|
||||
|
||||
<textarea placeholder="{{ __('invoice.Description') }}"
|
||||
name="items[index].description" x-model="items[index].description"
|
||||
x-text="items[index].description"
|
||||
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 mt-1 block w-full"></textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Incoming taxes -->
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100 relative">
|
||||
{{ __('invoice.Tax items') }}
|
||||
<x-primary-button x-on:click="addTax();" class="absolute right-0">+</x-primary-button>
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<div class="flex flex-row items-end gap-2 w-full">
|
||||
<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.tax" :value="__('common.Currency code')" class="w-1/6"/>
|
||||
<div class="w-1/12 relative h-10"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<template x-for="(tax, index) in taxes">
|
||||
<div class="flex flex-row items-end gap-2 w-full relative">
|
||||
<x-text-input id="taxes[index].taxable_amount" name="taxes[index].taxable_amount" type="number"
|
||||
class="mt-1 block w-1/6"
|
||||
autofocus
|
||||
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"
|
||||
class="mt-1 block w-1/6"
|
||||
autofocus
|
||||
x-model="taxes[index].percentage"/>
|
||||
|
||||
<x-text-input id="taxes[index].currency" name="taxes[index].currency" type="text"
|
||||
class="mt-1 block w-1/6"
|
||||
autofocus
|
||||
placeholder="{{ __('invoice.Name') }}"
|
||||
x-model="taxes[index].currency"/>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
||||
<script>
|
||||
function incomingForm() {
|
||||
return {
|
||||
incoming_id: {!! $incoming->id !!},
|
||||
incoming: {!! $incoming !!},
|
||||
supplier: {!! $supplier !!},
|
||||
items: {!! $items !!},
|
||||
taxes: {!! $taxes !!},
|
||||
|
||||
addItem() {
|
||||
let item = {
|
||||
incoming_id: this.incoming_id,
|
||||
name: '',
|
||||
article_number: '',
|
||||
description: '',
|
||||
amount: 0,
|
||||
discount: 0,
|
||||
tax: 0,
|
||||
price: 0,
|
||||
total: 0
|
||||
};
|
||||
this.items.push(item);
|
||||
},
|
||||
|
||||
addTax() {
|
||||
let tax = {
|
||||
incoming_id: this.incoming_id,
|
||||
taxable_amount: 0,
|
||||
amount: 0,
|
||||
percentage: 0,
|
||||
currency: 'EUR'
|
||||
};
|
||||
this.taxes.push(tax);
|
||||
},
|
||||
|
||||
deleteItem(index) {
|
||||
this.items.splice(index, 1);
|
||||
},
|
||||
|
||||
deleteTax(index) {
|
||||
this.taxes.splice(index, 1);
|
||||
},
|
||||
|
||||
submit() {
|
||||
axios.put('/incoming/' + this.incoming_id, {incoming: this.incoming, items: this.items, taxes: this.taxes, supplier: this.supplier})
|
||||
.then(function(response) {
|
||||
window.location.href = '/incoming';
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
143
resources/views/incoming/index.blade.php
Normal file
143
resources/views/incoming/index.blade.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<div class="flex flex-row w-full">
|
||||
<h2 class="grow font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
{{ __('incoming.Incoming') }}
|
||||
</h2>
|
||||
<a href="{{ route('excel') }}" class="relative flex flex-row">
|
||||
<x-excel-icon class="text-gray-800 cursor-pointer"/>
|
||||
</a>
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w flex flex-row">
|
||||
<section class="w-1/2">
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('incoming.Add new invoice') }}
|
||||
</h2>
|
||||
|
||||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ __("incoming.Add new invoice by clicking add") }}
|
||||
</p>
|
||||
</header>
|
||||
<a class="mt-6 inline-block" href="{{ route('incoming.create') }}"><x-primary-button>{{ __('form.Add') }}</x-primary-button></a>
|
||||
</section>
|
||||
<section class="w-1/2">
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('incoming.Upload new invoice') }}
|
||||
</h2>
|
||||
|
||||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ __("incoming.Upload new xml invoice by clicking upload") }}
|
||||
</p>
|
||||
</header>
|
||||
<a class="mt-6 inline-block" href="{{ route('incoming.upload') }}"><x-primary-button>{{ __('form.Upload') }}</x-primary-button></a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w" x-data="incomingForm">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('incoming.Existing invoices') }}
|
||||
</h2>
|
||||
<div class="flex flex-row space-x-4 items-center mt-4">
|
||||
<x-input-label for="from" :value="__('invoice.From')"/>
|
||||
<x-text-input type="date" id="from" name="from" x-model="from" 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>
|
||||
</header>
|
||||
|
||||
<summary class="cursor-pointer flex flex-row w-full mt-4">
|
||||
<div class="w-1/6 font-bold border-b-2">{{ __('invoice.Invoice Number') }}</div>
|
||||
<div class="w-1/3 font-bold border-b-2">{{ __('supplier.Supplier') }}</div>
|
||||
<div class="w-1/4 font-bold border-b-2">{{ __('common.Name') }}</div>
|
||||
<div class="w-1/12 font-bold border-b-2 text-right">{{ __('invoice.Sum') }}</div>
|
||||
<div class="w-1/12 font-bold border-b-2 text-right">{{ __('common.Created at') }}</div>
|
||||
<div class="w-1/12 font-bold border-b-2 text-right">{{ __('common.Paid at') }}</div>
|
||||
</summary>
|
||||
|
||||
<template x-for="invoice in invoices">
|
||||
<details class="even:bg-gray-100 odd:bg-white">
|
||||
<summary class="cursor-pointer flex flex-row w-full" @click="window.location.href='/incoming/' + invoice.id + '/edit';">
|
||||
<div class="w-1/6" x-text="invoice.invoice_number"></div>
|
||||
<div class="w-1/3" x-text="invoice.supplier.name"></div>
|
||||
<div class="w-1/4" x-text="invoice.supplier.email"></div>
|
||||
<div class="w-1/12 text-right" x-text="invoice.gross + ' €'"></div>
|
||||
<div class="w-1/12 text-right" x-text="invoice.created"></div>
|
||||
<div class="w-1/12 text-right" x-text="invoice.paid"></div>
|
||||
</summary>
|
||||
</details>
|
||||
</template>
|
||||
|
||||
<div class="w-full border-t-2"></div>
|
||||
|
||||
<div class="w-1/2 grid grid-cols-2">
|
||||
<div>{{ __('invoice.Net') }}</div>
|
||||
<div class="text-right" x-text="net + ' €'"></div>
|
||||
<div>{{ __('invoice.Tax') }}</div>
|
||||
<div class="text-right" x-text="tax + ' €'"></div>
|
||||
<div class="font-bold">{{ __('invoice.Sum') }}</div>
|
||||
<div class="font-bold text-right" x-text="gross + ' €'"></div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
||||
<script>
|
||||
function incomingForm() {
|
||||
return {
|
||||
net: 0,
|
||||
gross: 0,
|
||||
tax: 0,
|
||||
from: "{{ \Illuminate\Support\Facades\Date::now()->firstOfMonth()->format('Y-m-d') }}",
|
||||
end: "{{ \Illuminate\Support\Facades\Date::now()->format('Y-m-d') }}",
|
||||
invoices: [],
|
||||
|
||||
init() {
|
||||
this.fetchInvoices();
|
||||
},
|
||||
|
||||
fetchInvoices() {
|
||||
let vm = this;
|
||||
axios.get('/incoming-filter/' + this.from + '/' + this.end)
|
||||
.then(function (response) {
|
||||
vm.invoices = response.data;
|
||||
vm.calculateSum();
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
})
|
||||
},
|
||||
|
||||
calculateSum() {
|
||||
this.net = 0;
|
||||
this.gross = 0;
|
||||
this.tax = 0;
|
||||
for (const [key, invoice] of Object.entries(this.invoices)) {
|
||||
this.net += parseFloat(invoice.net);
|
||||
this.gross += parseFloat(invoice.gross);
|
||||
this.tax += parseFloat(invoice.tax)
|
||||
}
|
||||
this.net = this.net.toFixed(2)
|
||||
this.gross = this.gross.toFixed(2);
|
||||
this.tax = this.tax.toFixed(2);
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
77
resources/views/incoming/upload.blade.php
Normal file
77
resources/views/incoming/upload.blade.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<div class="flex flex-row w-full">
|
||||
<h2 class="grow font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
{{ __('incoming.Upload new invoice') }}
|
||||
</h2>
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12" x-data="uploadForm">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="max-w ">
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('incoming.Upload new invoice') }}
|
||||
</h2>
|
||||
|
||||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ __("incoming.Upload new xml invoice by clicking upload") }}
|
||||
</p>
|
||||
</header>
|
||||
</section>
|
||||
<form class="mt-6 space-y-2" @submit.prevent="">
|
||||
<p class="text-red-600 font-bold" x-text="message" x-show="error"></p>
|
||||
<div class="flex flex-row items-start">
|
||||
<x-input-label class="w-1/4" for="upload_file"
|
||||
:value="__('incoming.Invoice file')"/>
|
||||
<x-text-input id="upload_file" name="upload_file" type="file" accept=".xml"
|
||||
class="mt-1 block w-full"
|
||||
@change="checkUpload()"/>
|
||||
</div>
|
||||
<x-primary-button x-show="may_upload"
|
||||
@click="submit()">{{ __('form.Upload') }}</x-primary-button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
||||
<script>
|
||||
function uploadForm() {
|
||||
return {
|
||||
error: false,
|
||||
message: '',
|
||||
may_upload: false,
|
||||
upload_file: null,
|
||||
|
||||
checkUpload() {
|
||||
let reader, files = document.getElementById('upload_file').files;
|
||||
reader = new FileReader();
|
||||
reader.onload = e => {
|
||||
this.may_upload = true;
|
||||
this.upload_file = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(files[0]);
|
||||
},
|
||||
|
||||
submit() {
|
||||
let vm = this;
|
||||
axios.post('incoming-upload', {uploadFile: this.upload_file})
|
||||
.then(function (response) {
|
||||
window.location.href = '/incoming/' + response.data.id + '/edit';
|
||||
})
|
||||
.catch(function (error) {
|
||||
vm.error = true;
|
||||
vm.may_upload = false;
|
||||
vm.message = error.response.data.message;
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -31,6 +31,10 @@
|
||||
:active="\Illuminate\Support\Str::startsWith(request()->route()->getName(), 'taxrate.')">
|
||||
{{ __('configuration.Taxrates') }}
|
||||
</x-nav-link>
|
||||
<x-nav-link :href="route('incoming.index')"
|
||||
:active="\Illuminate\Support\Str::startsWith(request()->route()->getName(), 'incoming.')">
|
||||
{{ __('incoming.Incoming') }}
|
||||
</x-nav-link>
|
||||
<x-nav-link :href="route('option.index')"
|
||||
:active="\Illuminate\Support\Str::startsWith(request()->route()->getName(), 'option.')">
|
||||
{{ __('configuration.Options') }}
|
||||
|
||||
Reference in New Issue
Block a user