Finalize invoice creation and handling addresses.
This commit is contained in:
@@ -29,12 +29,34 @@ class Customer extends Model
|
|||||||
*/
|
*/
|
||||||
protected $appends = [
|
protected $appends = [
|
||||||
'created',
|
'created',
|
||||||
|
'street',
|
||||||
|
'city'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deliver the customer's address as street directly with the model.
|
||||||
|
*/
|
||||||
|
public function getStreetAttribute(): string
|
||||||
|
{
|
||||||
|
if (is_null($this->address)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return $this->address->address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deliver the customer's address as city directly with the model.
|
||||||
|
*/
|
||||||
|
public function getCityAttribute(): string
|
||||||
|
{
|
||||||
|
if (is_null($this->address)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return $this->address->city;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the created_at attribute in local time format.
|
* Get the created_at attribute in local time format.
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function getCreatedAttribute(): string
|
public function getCreatedAttribute(): string
|
||||||
{
|
{
|
||||||
@@ -43,8 +65,6 @@ class Customer extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the invoice address.
|
* Get the invoice address.
|
||||||
*
|
|
||||||
* @return HasOne
|
|
||||||
*/
|
*/
|
||||||
public function address(): HasOne
|
public function address(): HasOne
|
||||||
{
|
{
|
||||||
@@ -56,8 +76,6 @@ class Customer extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the delivery address.
|
* Get the delivery address.
|
||||||
*
|
|
||||||
* @return HasOne
|
|
||||||
*/
|
*/
|
||||||
public function delivery(): HasOne
|
public function delivery(): HasOne
|
||||||
{
|
{
|
||||||
@@ -69,8 +87,6 @@ class Customer extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all customer's addresses.
|
* Get all customer's addresses.
|
||||||
*
|
|
||||||
* @return HasMany
|
|
||||||
*/
|
*/
|
||||||
public function addresses(): HasMany
|
public function addresses(): HasMany
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ return new class extends Migration
|
|||||||
$table->foreignId('user_id')->constrained();
|
$table->foreignId('user_id')->constrained();
|
||||||
$table->foreignId('customer_id')->constrained();
|
$table->foreignId('customer_id')->constrained();
|
||||||
$table->foreignId('address_id')->constrained();
|
$table->foreignId('address_id')->constrained();
|
||||||
$table->foreignId('delivery_id')->references('id')->on('addresses');
|
$table->foreignId('delivery_id')->nullable()->references('id')->on('addresses');
|
||||||
|
|
||||||
$table->string('invoice_number');
|
$table->string('invoice_number');
|
||||||
$table->string('type'); // Map to external formats
|
$table->string('type'); // Map to external formats
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ return [
|
|||||||
'Select customer' => 'Kunde auswählen',
|
'Select customer' => 'Kunde auswählen',
|
||||||
'Select address' => 'Adresse auswählen',
|
'Select address' => 'Adresse auswählen',
|
||||||
'Search customer' => 'Kunden suchen',
|
'Search customer' => 'Kunden suchen',
|
||||||
'Select your customer and address' => 'Wähle einen Kunden und seine Adresse aus',
|
'Select your customer and address' => 'Wähle einen Kunden und seine Adresse aus.',
|
||||||
|
'Select your customer\'s address' =>'Wähle die Adresse des Kunden aus.',
|
||||||
'Invoice item' => 'Rechnungsposition',
|
'Invoice item' => 'Rechnungsposition',
|
||||||
'Invoice items' => 'Rechnungspositionen',
|
'Invoice items' => 'Rechnungspositionen',
|
||||||
'Amount' => 'Menge',
|
'Amount' => 'Menge',
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
||||||
|
|
||||||
<!-- Customer data -->
|
<!-- Customer data -->
|
||||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg"
|
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||||
x-show="customer_id == 0 || step == 1">
|
|
||||||
<div class="max-w">
|
<div class="max-w">
|
||||||
<section>
|
<section>
|
||||||
<header>
|
<header>
|
||||||
@@ -35,6 +34,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<template x-for="(customer, index) in getFilteredCustomer()">
|
<template x-for="(customer, index) in getFilteredCustomer()">
|
||||||
<div class="cursor-pointer grid grid-cols-4 even:bg-gray-100 odd:bg-white"
|
<div class="cursor-pointer grid grid-cols-4 even:bg-gray-100 odd:bg-white"
|
||||||
|
:class="customer.id == customer_id ? 'font-bold' : ''"
|
||||||
x-on:click="getAddress(index);">
|
x-on:click="getAddress(index);">
|
||||||
<div x-text="customer.name"></div>
|
<div x-text="customer.name"></div>
|
||||||
<div x-text="customer.email"></div>
|
<div x-text="customer.email"></div>
|
||||||
@@ -50,8 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Address data -->
|
<!-- Address data -->
|
||||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg"
|
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||||
x-show="customer_id != 0 || step == 2">
|
|
||||||
<div class="max-w">
|
<div class="max-w">
|
||||||
<section>
|
<section>
|
||||||
<header>
|
<header>
|
||||||
@@ -59,17 +58,55 @@
|
|||||||
{{ __('invoice.Select address') }}
|
{{ __('invoice.Select address') }}
|
||||||
</h2>
|
</h2>
|
||||||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||||
{{ __("invoice.Select your customer and address") }}
|
{{ __("invoice.Select your customer's address") }}
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="flex flex-row my-8">
|
<div class="flex flex-row my-8">
|
||||||
<div x-show="address_id != 0" class="w-1/2">
|
<div class="w-1/2">
|
||||||
<x-address-card/>
|
<div class="flex flex-row">
|
||||||
|
<div class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('customer.Invoice Address') }}</div>
|
||||||
|
<x-danger-button class="ml-4 px-0 py-0" x-show="address_id != 0">
|
||||||
|
<x-trash-icon class="h-5 p-0" x-on:click="address_id = 0; address = {}"/>
|
||||||
|
</x-danger-button>
|
||||||
|
</div>
|
||||||
|
<select class="absolute z-10 bg-white 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" id="select_address_id" x-show="address_id == 0" x-on:click="setInvoiceAddress()">
|
||||||
|
<template x-for="addr in addresses[customer_id]" >
|
||||||
|
<option :value="addr.id" x-text="addr.name + '; ' + addr.address + '; ' + addr.zip + addr.city + '; ' + addr.phone + '; ' + addr.email"></option>
|
||||||
|
</template>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<div x-text="address.name"></div>
|
||||||
|
<div x-text="address.address"></div>
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<div class="mr-2" x-text="address.zip"></div>
|
||||||
|
<div x-text="address.city"></div>
|
||||||
|
</div>
|
||||||
|
<div x-text="address.phone"></div>
|
||||||
|
<div x-text="address.email"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div x-show="delivery_id != 0" class="w-1/2">
|
|
||||||
<x-delivery-card x-data="{card: {name: 'Chris'}}"/>
|
<div class="w-1/2">
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<div class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('customer.Delivery Address') }}</div>
|
||||||
|
<x-danger-button class="ml-4 px-0 py-0" x-show="delivery_id != null">
|
||||||
|
<x-trash-icon class="h-5 p-0" x-on:click="delivery_id = null; delivery = {}"/>
|
||||||
|
</x-danger-button>
|
||||||
|
</div>
|
||||||
|
<select class="absolute z-10 bg-white 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" id="select_delivery_id" x-show="delivery_id == null" x-on:click="setIDeliveryAddress()">
|
||||||
|
<template x-for="addr in addresses[customer_id]" >
|
||||||
|
<option :value="addr.id" x-text="addr.name + '; ' + addr.address + '; ' + addr.zip + addr.city + '; ' + addr.phone + '; ' + addr.email"></option>
|
||||||
|
</template>
|
||||||
|
</select>
|
||||||
|
<div x-text="delivery.name"></div>
|
||||||
|
<div x-text="delivery.address"></div>
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<div class="mr-2" x-text="delivery.zip"></div>
|
||||||
|
<div x-text="delivery.city"></div>
|
||||||
|
</div>
|
||||||
|
<div x-text="delivery.phone"></div>
|
||||||
|
<div x-text="delivery.email"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -193,7 +230,7 @@
|
|||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<x-primary-button x-on:click="submitForm();" class="">Sprrelkfdsiodsaich</x-primary-button>
|
<x-primary-button x-on:click="submitForm();" class="">{{ __('form.Save') }}</x-primary-button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -208,8 +245,6 @@
|
|||||||
|
|
||||||
function invoiceForm() {
|
function invoiceForm() {
|
||||||
return {
|
return {
|
||||||
step: 1,
|
|
||||||
|
|
||||||
card: {},
|
card: {},
|
||||||
customers: {},
|
customers: {},
|
||||||
customer: {},
|
customer: {},
|
||||||
@@ -235,7 +270,6 @@
|
|||||||
message: '',
|
message: '',
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
// this.items.push(this.newItem());
|
|
||||||
this.getCustomers();
|
this.getCustomers();
|
||||||
this.getTaxRates();
|
this.getTaxRates();
|
||||||
self = this;
|
self = this;
|
||||||
@@ -288,14 +322,32 @@
|
|||||||
return customer.name
|
return customer.name
|
||||||
.replace(/ /g, '')
|
.replace(/ /g, '')
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(this.search.replace(/ /g, '').toLowerCase());
|
.includes(this.search.replace(/ /g, '').toLowerCase())
|
||||||
|
||
|
||||||
|
customer.email
|
||||||
|
.replace(/ /g, '')
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(this.search.replace(/ /g, '').toLowerCase())
|
||||||
|
||
|
||||||
|
customer.street
|
||||||
|
.replace(/ /g, '')
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(this.search.replace(/ /g, '').toLowerCase())
|
||||||
|
||
|
||||||
|
customer.city
|
||||||
|
.replace(/ /g, '')
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(this.search.replace(/ /g, '').toLowerCase())
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getAddress(index) {
|
getAddress(index) {
|
||||||
this.customer = this.customers[index];
|
this.customer = this.customers[index];
|
||||||
this.customer_id = this.customer.id;
|
this.customer_id = this.customer.id;
|
||||||
this.step = 2;
|
this.address_id = 0;
|
||||||
|
this.delivery_id = null;
|
||||||
|
this.address = {};
|
||||||
|
this.delivery = {};
|
||||||
if (this.customer.address) {
|
if (this.customer.address) {
|
||||||
this.address_id = this.customer.address.id;
|
this.address_id = this.customer.address.id;
|
||||||
this.address = this.customer.address;
|
this.address = this.customer.address;
|
||||||
@@ -304,6 +356,17 @@
|
|||||||
this.delivery_id = this.customer.delivery.id;
|
this.delivery_id = this.customer.delivery.id;
|
||||||
this.delivery = this.customer.delivery;
|
this.delivery = this.customer.delivery;
|
||||||
}
|
}
|
||||||
|
this.getCustomerAddresses();
|
||||||
|
},
|
||||||
|
|
||||||
|
getCustomerAddresses() {
|
||||||
|
if (typeof (this.addresses[this.customer_id]) == 'undefined') {
|
||||||
|
let vm = this;
|
||||||
|
axios.get('/customer/' + this.customer_id + '/address')
|
||||||
|
.then(function (response) {
|
||||||
|
vm.addresses[vm.customer_id] = response.data;
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
addItem() {
|
addItem() {
|
||||||
@@ -358,13 +421,21 @@
|
|||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
})
|
})
|
||||||
console.log(this.customer_id);
|
},
|
||||||
console.log(this.address_id);
|
|
||||||
console.log(this.delivery_id);
|
setInvoiceAddress() {
|
||||||
console.log(sum);
|
let id = document.querySelector('#select_address_id').value;
|
||||||
console.log(tax);
|
this.address_id = id;
|
||||||
|
let address_key = Object.keys(this.addresses[this.customer_id]).find(key => (this.addresses[this.customer_id][key].id == id ));
|
||||||
|
this.address = this.addresses[this.customer_id][address_key];
|
||||||
|
},
|
||||||
|
|
||||||
|
setIDeliveryAddress() {
|
||||||
|
let id = document.querySelector('#select_delivery_id').value;
|
||||||
|
this.delivery_id = id;
|
||||||
|
let address_key = Object.keys(this.addresses[this.customer_id]).find(key => (this.addresses[this.customer_id][key].id == id ));
|
||||||
|
this.delivery = this.addresses[this.customer_id][address_key];
|
||||||
|
|
||||||
console.log(this.items);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handle(item, position) {
|
handle(item, position) {
|
||||||
@@ -385,7 +456,8 @@
|
|||||||
}
|
}
|
||||||
self.sort[item] = position;
|
self.sort[item] = position;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -35,9 +35,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<x-php-card :address="$invoice->address"/>
|
<x-php-card :address="$invoice->address"/>
|
||||||
</div>
|
</div>
|
||||||
|
@if($invoice->delivery)
|
||||||
<div>
|
<div>
|
||||||
<x-php-card :address="$invoice->delivery"/>
|
<x-php-card :address="$invoice->delivery"/>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ Route::group(['as' => 'api.'], function () {
|
|||||||
Route::apiResource('/customer.address', AddressController::class)->shallow();
|
Route::apiResource('/customer.address', AddressController::class)->shallow();
|
||||||
Route::apiResource('/taxrate', TaxRateController::class)->except(['show']);
|
Route::apiResource('/taxrate', TaxRateController::class)->except(['show']);
|
||||||
Route::get('/invoice/{start?}/{end?}', [InvoiceController::class, 'index'])->name('invoice.index');
|
Route::get('/invoice/{start?}/{end?}', [InvoiceController::class, 'index'])->name('invoice.index');
|
||||||
|
Route::post('/invoice', [InvoiceController::class, 'store'])->name('invoice.store');
|
||||||
Route::apiResource('/invoice.item', InvoiceItemController::class)->shallow();
|
Route::apiResource('/invoice.item', InvoiceItemController::class)->shallow();
|
||||||
Route::get('/option', [OptionController::class, 'index'])->name('option.index');
|
Route::get('/option', [OptionController::class, 'index'])->name('option.index');
|
||||||
Route::post('/option', [OptionController::class, 'store'])->name('option.store');
|
Route::post('/option', [OptionController::class, 'store'])->name('option.store');
|
||||||
|
|||||||
Reference in New Issue
Block a user