Send invoices by email.

This commit is contained in:
2025-01-09 11:18:12 +01:00
parent 8da6da471d
commit 6235112f74
19 changed files with 468 additions and 23 deletions

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" {{ $attributes->merge(['class' => 'size-8 p-1']) }}>
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75" />
</svg>

After

Width:  |  Height:  |  Size: 492 B

View File

@@ -55,18 +55,22 @@
<div class="w-1/6" x-text="invoice.number"></div>
<div class="w-1/6" x-text="invoice.address.name"></div>
<div class="w-1/4" x-text="invoice.address.email"></div>
<div class="w-1/12" x-text="invoice.status"></div>
<div class="w-1/6 text-right" x-text="invoice.sum"></div>
<div class="w-1/12" x-text="invoice.localized_state"></div>
<div class="w-1/6 text-right" x-text="invoice.sum + ' €'"></div>
<div class="w-1/6 text-right" x-text="invoice.created"></div>
</summary>
</details>
</template>
<div class="grid grid-cols-2 border-t-2">
<div>{{ __('invoice.Sum') }}</div>
<div x-text="sum"></div>
<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="(sum - tax).toFixed(2) + ' €'"></div>
<div>{{ __('invoice.Tax') }}</div>
<div x-text="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="sum + ' €'"></div>
</div>
</section>

View File

@@ -0,0 +1,113 @@
<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">
{{ __('invoice.Invoice') }} {{ $invoice->number }}
</h2>
</div>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<!-- Customer data -->
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w" x-data="mailForm">
<section>
<header>
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('invoice.Mail') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __("invoice.Send email to your customer with attachments.") }}
</p>
</header>
<form class="mt-6 space-y-6" @submit.prevent="">
<div class="flex flex-row items-center">
<x-input-label for="To" :value="__('common.Email-To')" class="w-1/4"/>
<x-text-input id="To" name="To" type="email" class="mt-1 block w-full"
:value="old('To')" required multiple autocomplete="To"
x-model="data.To"/>
</div>
<div class="flex flex-row items-center">
<x-input-label for="Cc" :value="__('common.Email-Cc')" class="w-1/4"/>
<x-text-input id="Cc" name="Cc" type="email" class="mt-1 block w-full"
:value="old('Cc')" multiple autocomplete="Cc"
x-model="data.Cc"/>
</div>
<div class="flex flex-row items-center">
<x-input-label for="Bcc" :value="__('common.Email-Bcc')" class="w-1/4"/>
<x-text-input id="Bcc" name="Bcc" type="email" class="mt-1 block w-full"
:value="old('Bcc')" multiple autocomplete="Bcc"
x-model="data.Bcc"/>
</div>
<div class="flex flex-row items-center">
<x-input-label for="Subject" :value="__('common.Email-Subject')" class="w-1/4"/>
<x-text-input id="Subject" name="Subject" type="text" class="mt-1 block w-full"
:value="old('Subject')" required autocomplete="Subject"
x-model="data.Subject"/>
</div>
<div class="flex flex-row items-center">
<x-input-label for="Body" :value="__('common.Email-Body')" class="w-1/4"/>
<textarea rows="10" id="Body" name="Body" 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"
required autocomplete="Body"
x-model="data.Body"></textarea>
</div>
<div class="flex flex-row items-center">
<x-input-label for="Pdf" :value="__('invoice.Send Pdf')" class="w-1/4"/>
<x-text-input id="Pdf" name="Pdf" x-model="data.Pdf" type="checkbox"/>
<x-pdf-icon class="text-gray-800 cursor-pointer" onclick="window.open('/invoice/{{ $invoice->id }}/pdf-download', '_blank', 'popup=true')"/>
</div>
<div class="flex flex-row items-center">
<x-input-label for="Xml" :value="__('invoice.Send Xml')" class="w-1/4"/>
<x-text-input id="Xml" name="Xml" x-model="data.Xml" type="checkbox"/>
<x-e-icon class="cursor-pointer" onclick="window.open('/invoice/{{ $invoice->id }}/xml-download', '_blank', 'popup=true')"/>
</div>
<div class="flex items-center gap-4" x-show="!sent">
<x-primary-button @click="submit">{{ __('form.Send') }}</x-primary-button>
</div>
</form>
</section>
</div>
</div>
</div>
</div>
</x-app-layout>
<script>
function mailForm() {
return {
data: {
id: {{ $invoice->id }},
To: '{{ $invoice->customer->email }}',
Cc: '{{ $invoice->address->email }}',
Bcc: '',
Subject: '{{ __('invoice.Invoice') . ' ' . $invoice->number }}',
Body: '{{ __('invoice.Invoice body', ['invoice_number' => $invoice->number]) }}',
Pdf: true,
Xml: true,
},
sent: false,
submit() {
this.sent = true;
axios.post('/sendInvoice', this.data)
.then(function (response) {
console.log(response);
}).catch(function(error) {
console.log(error);
})
console.log(this.data);
}
}
}
</script>

View File

@@ -5,6 +5,7 @@
{{ __('invoice.Invoice') }} {{ $invoice->number }}
</h2>
<p class="relative flex flex-row">
<x-mail-icon class="cursor-pointer mr-4" onclick="window.location.href = '{{ route('invoice.mail', $invoice->id) }}'"/>
<x-pdf-icon class="text-gray-800 cursor-pointer" onclick="window.open('/invoice/{{ $invoice->id }}/pdf-download', '_blank', 'popup=true')"/>
<x-e-icon class="cursor-pointer" onclick="window.open('/invoice/{{ $invoice->id }}/xml-download', '_blank', 'popup=true')"/>
</p>

View File

@@ -0,0 +1,3 @@
<body>
{!! nl2br($html) !!}
</body>

View File

@@ -199,7 +199,7 @@
</div>
</div>
<!-- correspondence -->
<!-- Correspondence -->
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w">
<section>
@@ -233,6 +233,95 @@
</div>
</div>
<!-- Mail derlivery -->
<!--
'transport' => $options->mail_transport,
'host' => $options->mail_host,
'port' => $options->mail_port,
'encryption' => $options->mail_encryption,
'username' => $options->mail_username,
'password' => $options->mail_password,
-->
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w">
<section>
<details>
<summary class="text-lg font-medium text-gray-900 dark:text-gray-100 cursor-pointer">
{{ __('configuration.Mail delivery') }}
</summary>
<form class="mt-6 space-y-2" @submit.prevent="">
<div class="flex flex-row items-center">
<x-input-label class="w-1/4" for="mail_transport"
:value="__('configuration.Mail transport')"/>
<x-text-input id="mail_transport" name="mail_transport" type="text"
class="mt-1 block w-full"
:value="old('mail_transport')" autofocus
placeholder="smtp"
autocomplete="mail_transport"
x-model="options.mail_transport"/>
</div>
<div class="flex flex-row items-center">
<x-input-label class="w-1/4" for="mail_host"
:value="__('configuration.Mail host')"/>
<x-text-input id="mail_host" name="mail_host" type="text"
class="mt-1 block w-full"
:value="old('mail_host')" autofocus
placeholder="mail.example.com"
autocomplete="mail_host"
x-model="options.mail_host"/>
</div>
<div class="flex flex-row items-center">
<x-input-label class="w-1/4" for="mail_port"
:value="__('configuration.Mail port')"/>
<x-text-input id="mail_port" name="mail_port" type="text"
class="mt-1 block w-full"
:value="old('mail_port')" autofocus
placeholder="587"
autocomplete="mail_port"
x-model="options.mail_port"/>
</div>
<div class="flex flex-row items-center">
<x-input-label class="w-1/4" for="mail_encryption"
:value="__('configuration.Mail encryption')"/>
<x-text-input id="mail_encryption" name="mail_encryption" type="text"
class="mt-1 block w-full"
:value="old('mail_encryption')" autofocus
placeholder="tls"
autocomplete="mail_encryption"
x-model="options.mail_encryption"/>
</div>
<div class="flex flex-row items-center">
<x-input-label class="w-1/4" for="mail_username"
:value="__('configuration.Mail username')"/>
<x-text-input id="mail_username" name="mail_username" type="text"
class="mt-1 block w-full"
:value="old('mail_username')" autofocus
placeholder="Username"
autocomplete="mail_username"
x-model="options.mail_username"/>
</div>
<div class="flex flex-row items-center">
<x-input-label class="w-1/4" for="mail_password"
:value="__('configuration.Mail password')"/>
<x-text-input id="mail_password" name="mail_password" type="password"
class="mt-1 block w-full"
:value="old('mail_password')" autofocus
autocomplete="mail_password"
x-model="options.mail_password"/>
</div>
</form>
</details>
</section>
</div>
</div>
<div class="flex items-center gap-4">
<x-primary-button @click="submit">{{ __('form.Save') }}</x-primary-button>
</div>