浏览代码

Merge branch 'Invoices' into development

Dennis 3 年之前
父节点
当前提交
26eb7c349e

+ 2 - 0
.gitignore

@@ -18,3 +18,5 @@ yarn-error.log
 .gitignore
 .gitignore
 .env.dev
 .env.dev
 .env.testing
 .env.testing
+storage/invoices.zip
+storage/app/public/logo.png

+ 79 - 14
app/Http/Controllers/Admin/PaymentController.php

@@ -5,11 +5,11 @@ namespace App\Http\Controllers\Admin;
 use App\Events\UserUpdateCreditsEvent;
 use App\Events\UserUpdateCreditsEvent;
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
 use App\Models\Configuration;
 use App\Models\Configuration;
+use App\Models\InvoiceSettings;
 use App\Models\Payment;
 use App\Models\Payment;
 use App\Models\PaypalProduct;
 use App\Models\PaypalProduct;
-use App\Models\Product;
 use App\Models\User;
 use App\Models\User;
-use App\Notifications\ConfirmPaymentNotification;
+use App\Notifications\InvoiceNotification;
 use Exception;
 use Exception;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\Factory;
@@ -18,6 +18,11 @@ use Illuminate\Http\JsonResponse;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Storage;
+use LaravelDaily\Invoices\Classes\Buyer;
+use LaravelDaily\Invoices\Classes\InvoiceItem;
+use LaravelDaily\Invoices\Classes\Party;
+use LaravelDaily\Invoices\Invoice;
 use PayPalCheckoutSdk\Core\PayPalHttpClient;
 use PayPalCheckoutSdk\Core\PayPalHttpClient;
 use PayPalCheckoutSdk\Core\ProductionEnvironment;
 use PayPalCheckoutSdk\Core\ProductionEnvironment;
 use PayPalCheckoutSdk\Core\SandboxEnvironment;
 use PayPalCheckoutSdk\Core\SandboxEnvironment;
@@ -46,10 +51,10 @@ class PaymentController extends Controller
     public function checkOut(Request $request, PaypalProduct $paypalProduct)
     public function checkOut(Request $request, PaypalProduct $paypalProduct)
     {
     {
         return view('store.checkout')->with([
         return view('store.checkout')->with([
-            'product'      => $paypalProduct,
-            'taxvalue'     => $paypalProduct->getTaxValue(),
-            'taxpercent'   => $paypalProduct->getTaxPercent(),
-            'total'        => $paypalProduct->getTotalPrice()
+            'product' => $paypalProduct,
+            'taxvalue' => $paypalProduct->getTaxValue(),
+            'taxpercent' => $paypalProduct->getTaxPercent(),
+            'total' => $paypalProduct->getTotalPrice()
         ]);
         ]);
     }
     }
 
 
@@ -68,12 +73,12 @@ class PaymentController extends Controller
                 [
                 [
                     "reference_id" => uniqid(),
                     "reference_id" => uniqid(),
                     "description" => $paypalProduct->description,
                     "description" => $paypalProduct->description,
-                    "amount"       => [
-                        "value"         => $paypalProduct->getTotalPrice(),
+                    "amount" => [
+                        "value" => $paypalProduct->getTotalPrice(),
                         'currency_code' => strtoupper($paypalProduct->currency_code),
                         'currency_code' => strtoupper($paypalProduct->currency_code),
-                        'breakdown' =>[
+                        'breakdown' => [
                             'item_total' =>
                             'item_total' =>
-                               [
+                                [
                                     'currency_code' => strtoupper($paypalProduct->currency_code),
                                     'currency_code' => strtoupper($paypalProduct->currency_code),
                                     'value' => $paypalProduct->price,
                                     'value' => $paypalProduct->price,
                                 ],
                                 ],
@@ -89,8 +94,8 @@ class PaymentController extends Controller
             "application_context" => [
             "application_context" => [
                 "cancel_url" => route('payment.cancel'),
                 "cancel_url" => route('payment.cancel'),
                 "return_url" => route('payment.success', ['product' => $paypalProduct->id]),
                 "return_url" => route('payment.success', ['product' => $paypalProduct->id]),
-                'brand_name' =>  config('app.name', 'Laravel'),
-                'shipping_preference'  => 'NO_SHIPPING'
+                'brand_name' => config('app.name', 'Laravel'),
+                'shipping_preference' => 'NO_SHIPPING'
             ]
             ]
 
 
 
 
@@ -186,15 +191,75 @@ class PaymentController extends Controller
                     'payer' => json_encode($response->result->payer),
                     'payer' => json_encode($response->result->payer),
                 ]);
                 ]);
 
 
-                //payment notification
-                $user->notify(new ConfirmPaymentNotification($payment));
 
 
                 event(new UserUpdateCreditsEvent($user));
                 event(new UserUpdateCreditsEvent($user));
 
 
+                //create invoice
+                $lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
+                $newInvoiceID = $lastInvoiceID + 1;
+                $InvoiceSettings = InvoiceSettings::all()->first();
+                $logoPath = storage_path('app/public/logo.png');
+
+                $seller = new Party([
+                    'name' => $InvoiceSettings->company_name,
+                    'phone' => $InvoiceSettings->company_phone,
+                    'address' => $InvoiceSettings->company_adress,
+                    'vat' => $InvoiceSettings->company_vat,
+                    'custom_fields' => [
+                        'E-Mail' => $InvoiceSettings->company_mail,
+                        "Web" => $InvoiceSettings->company_web
+                    ],
+                ]);
+
+
+                $customer = new Buyer([
+                    'name' => $user->name,
+                    'custom_fields' => [
+                        'E-Mail' => $user->email,
+                        'Client ID' => $user->id,
+                    ],
+                ]);
+                $item = (new InvoiceItem())
+                    ->title($paypalProduct->description)
+                    ->pricePerUnit($paypalProduct->price);
+
+                $invoice = Invoice::make()
+                    ->template('controlpanel')
+                    ->buyer($customer)
+                    ->seller($seller)
+                    ->discountByPercent(0)
+                    ->taxRate(floatval($paypalProduct->getTaxPercent()))
+                    ->shipping(0)
+                    ->addItem($item)
+                    ->status(__('invoices::invoice.paid'))
+                    ->series(now()->format('mY'))
+                    ->delimiter("-")
+                    ->sequence($newInvoiceID)
+                    ->serialNumberFormat($InvoiceSettings->invoice_prefix . '{DELIMITER}{SERIES}{SEQUENCE}');
+
+                if (file_exists($logoPath)) {
+                    $invoice->logo($logoPath);
+                }
+                //Save the invoice in "storage\app\invoice\USER_ID\YEAR"
+                $invoice->filename = $invoice->getSerialNumber() . '.pdf';
+                $invoice->render();
+                Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output);
+
+
+                \App\Models\Invoice::create([
+                    'invoice_user' => $user->id,
+                    'invoice_name' => $invoice->getSerialNumber(),
+                    'payment_id' => $payment->payment_id,
+                ]);
+
+                //Send Invoice per Mail
+                $user->notify(new InvoiceNotification($invoice, $user, $payment));
+
                 //redirect back to home
                 //redirect back to home
                 return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
                 return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
             }
             }
 
 
+
             // If call returns body in response, you can get the deserialized version from the result attribute of the response
             // If call returns body in response, you can get the deserialized version from the result attribute of the response
             if (env('APP_ENV') == 'local') {
             if (env('APP_ENV') == 'local') {
                 dd($response);
                 dd($response);

+ 61 - 1
app/Http/Controllers/Admin/SettingsController.php

@@ -3,11 +3,13 @@
 namespace App\Http\Controllers\Admin;
 namespace App\Http\Controllers\Admin;
 
 
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
+use App\Models\InvoiceSettings;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\View;
 use Illuminate\Contracts\View\View;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Illuminate\Http\Response;
+use ZipArchive;
 
 
 class SettingsController extends Controller
 class SettingsController extends Controller
 {
 {
@@ -18,7 +20,16 @@ class SettingsController extends Controller
      */
      */
     public function index()
     public function index()
     {
     {
-        return view('admin.settings.index');
+        return view('admin.settings.index',
+            [
+                'company_name' => InvoiceSettings::get()->first()->company_name,
+                'company_adress' => InvoiceSettings::get()->first()->company_adress,
+                'company_phone' => InvoiceSettings::get()->first()->company_phone,
+                'company_vat' => InvoiceSettings::get()->first()->company_vat,
+                'company_mail' => InvoiceSettings::get()->first()->company_mail,
+                'company_web' => InvoiceSettings::get()->first()->company_web,
+                'invoice_prefix' => InvoiceSettings::get()->first()->invoice_prefix
+            ]);
     }
     }
 
 
     public function updateIcons(Request $request)
     public function updateIcons(Request $request)
@@ -39,4 +50,53 @@ class SettingsController extends Controller
         return redirect()->route('admin.settings.index')->with('success', __('Icons updated!'));
         return redirect()->route('admin.settings.index')->with('success', __('Icons updated!'));
     }
     }
 
 
+    public function updateInvoiceSettings(Request $request)
+    {
+        $request->validate([
+            'logo' => 'nullable|max:10000|mimes:jpg,png,jpeg',
+        ]);
+
+        InvoiceSettings::updateOrCreate(['id' => "1"], ['company_name' => $request->get('company-name')]);
+        InvoiceSettings::updateOrCreate(['id' => "1",], ['company_adress' => $request->get('company-adress')]);
+        InvoiceSettings::updateOrCreate(['id' => "1",], ['company_phone' => $request->get('company-phone')]);
+        InvoiceSettings::updateOrCreate(['id' => "1",], ['company_mail' => $request->get('company-mail')]);
+        InvoiceSettings::updateOrCreate(['id' => "1",], ['company_vat' => $request->get('company-vat')]);
+        InvoiceSettings::updateOrCreate(['id' => "1",], ['company_web' => $request->get('company-web')]);
+        InvoiceSettings::updateOrCreate(['id' => "1",], ['invoice_prefix' => $request->get('invoice-prefix')]);
+
+        if ($request->hasFile('logo')) {
+            $request->file('logo')->storeAs('public', 'logo.png');
+        }
+
+
+        return redirect()->route('admin.settings.index')->with('success', 'Invoice settings updated!');
+    }
+
+    public function downloadAllInvoices()
+    {
+        $zip = new ZipArchive;
+        $zip_safe_path = storage_path('invoices.zip');
+        $res = $zip->open($zip_safe_path, ZipArchive::CREATE | ZipArchive::OVERWRITE);
+        $result = $this::rglob(storage_path('app/invoice/*'));
+        if ($res === TRUE) {
+            $zip->addFromString("1. Info.txt", "This Archive contains all Invoices from all Users!\nIf there are no Invoices here, no Invoices have ever been created!");
+            foreach ($result as $file) {
+                if (file_exists($file) && is_file($file)) {
+                    $zip->addFile($file, basename($file));
+                }
+            }
+            $zip->close();
+        }
+        return response()->download($zip_safe_path);
+    }
+
+    public function rglob($pattern, $flags = 0)
+    {
+        $files = glob($pattern, $flags);
+        foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
+            $files = array_merge($files, $this::rglob($dir . '/' . basename($pattern), $flags));
+        }
+        return $files;
+    }
+
 }
 }

+ 18 - 0
app/Models/Invoice.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Invoice extends Model
+{
+    use HasFactory;
+
+    protected $fillable = [
+        'invoice_name',
+        'invoice_user',
+        'payment_id'
+    ];
+
+}

+ 23 - 0
app/Models/InvoiceSettings.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class InvoiceSettings extends Model
+{
+    use HasFactory;
+
+    protected $table = 'invoice_settings';
+
+    protected $fillable = [
+        'company_name',
+        'company_adress',
+        'company_phone',
+        'company_mail',
+        'company_vat',
+        'company_web',
+        'invoice_prefix'
+    ];
+}

+ 3 - 0
app/Notifications/ConfirmPaymentNotification.php

@@ -10,6 +10,9 @@ use Illuminate\Notifications\Notification;
 
 
 class ConfirmPaymentNotification extends Notification implements ShouldQueue
 class ConfirmPaymentNotification extends Notification implements ShouldQueue
 {
 {
+
+    //THIS IS BASICALLY NOT USED ANYMORE WITH INVOICENOTIFICATION IN PLACE
+
     use Queueable;
     use Queueable;
 
 
     private Payment $payment;
     private Payment $payment;

+ 69 - 0
app/Notifications/InvoiceNotification.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace App\Notifications;
+
+use App\Models\Payment;
+use App\Models\User;
+use Illuminate\Bus\Queueable;
+use Illuminate\Notifications\Messages\MailMessage;
+use Illuminate\Notifications\Notification;
+use LaravelDaily\Invoices\Invoice;
+
+class InvoiceNotification extends Notification
+
+{
+    use Queueable;
+
+    /**
+     * @var invoice
+     *      * @var invoice
+     *      * @var invoice
+     */
+    private $invoice;
+    private $user;
+    private $payment;
+
+    /**
+     * Create a new notification instance.
+     *
+     * @param Invoice $invoice
+     */
+    public function __construct(Invoice $invoice, User $user, Payment $payment)
+    {
+        $this->invoice = $invoice;
+        $this->user = $user;
+        $this->payment = $payment;
+    }
+
+    /**
+     * Get the notification's delivery channels.
+     *
+     * @param mixed $notifiable
+     * @return array
+     */
+    public function via($notifiable)
+    {
+        return ['mail'];
+    }
+
+    /**
+     * Get the array representation of the notification.
+     *
+     * @param mixed $notifiable
+     * @return MailMessage
+     */
+    public function toMail($notifiable)
+    {
+        return (new MailMessage)
+            ->subject('Your Payment was successful!')
+            ->greeting('Hello,')
+            ->line("Your payment was processed successfully!")
+            ->line('Status: ' . $this->payment->status)
+            ->line('Price: ' . $this->payment->formatToCurrency($this->payment->total_price))
+            ->line('Type: ' . $this->payment->type)
+            ->line('Amount: ' . $this->payment->amount)
+            ->line('Balance: ' . number_format($this->user->credits,2))
+            ->line('User ID: ' . $this->payment->user_id)
+            ->attach(storage_path('app/invoice/' . $this->user->id . '/' . now()->format('Y') . '/' . $this->invoice->filename));
+    }
+}

+ 1 - 0
composer.json

@@ -19,6 +19,7 @@
         "laravel/framework": "^8.12",
         "laravel/framework": "^8.12",
         "laravel/tinker": "^2.5",
         "laravel/tinker": "^2.5",
         "laravel/ui": "^3.2",
         "laravel/ui": "^3.2",
+        "laraveldaily/laravel-invoices": "^2.0",
         "paypal/paypal-checkout-sdk": "^1.0",
         "paypal/paypal-checkout-sdk": "^1.0",
         "paypal/rest-api-sdk-php": "^1.14",
         "paypal/rest-api-sdk-php": "^1.14",
         "socialiteproviders/discord": "^4.1",
         "socialiteproviders/discord": "^4.1",

+ 335 - 1
composer.lock

@@ -4,7 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
         "This file is @generated automatically"
     ],
     ],
-    "content-hash": "c3168498b058b38657de646f5cddb531",
+
+    "content-hash": "51c5797dc1629fe1f42b1fdc91c6e5d8",
     "packages": [
     "packages": [
         {
         {
             "name": "asm89/stack-cors",
             "name": "asm89/stack-cors",
@@ -62,6 +63,72 @@
             },
             },
             "time": "2021-03-11T06:42:03+00:00"
             "time": "2021-03-11T06:42:03+00:00"
         },
         },
+        {
+            "name": "barryvdh/laravel-dompdf",
+            "version": "v0.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/barryvdh/laravel-dompdf.git",
+                "reference": "5b99e1f94157d74e450f4c97e8444fcaffa2144b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/5b99e1f94157d74e450f4c97e8444fcaffa2144b",
+                "reference": "5b99e1f94157d74e450f4c97e8444fcaffa2144b",
+                "shasum": ""
+            },
+            "require": {
+                "dompdf/dompdf": "^1",
+                "illuminate/support": "^5.5|^6|^7|^8",
+                "php": "^7.1 || ^8.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "0.9-dev"
+                },
+                "laravel": {
+                    "providers": [
+                        "Barryvdh\\DomPDF\\ServiceProvider"
+                    ],
+                    "aliases": {
+                        "PDF": "Barryvdh\\DomPDF\\Facade"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Barryvdh\\DomPDF\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Barry vd. Heuvel",
+                    "email": "barryvdh@gmail.com"
+                }
+            ],
+            "description": "A DOMPDF Wrapper for Laravel",
+            "keywords": [
+                "dompdf",
+                "laravel",
+                "pdf"
+            ],
+            "support": {
+                "issues": "https://github.com/barryvdh/laravel-dompdf/issues",
+                "source": "https://github.com/barryvdh/laravel-dompdf/tree/v0.9.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/barryvdh",
+                    "type": "github"
+                }
+            ],
+            "time": "2020-12-27T12:05:53+00:00"
+        },
         {
         {
             "name": "biscolab/laravel-recaptcha",
             "name": "biscolab/laravel-recaptcha",
             "version": "5.0.1",
             "version": "5.0.1",
@@ -780,6 +847,73 @@
             ],
             ],
             "time": "2020-05-25T17:44:05+00:00"
             "time": "2020-05-25T17:44:05+00:00"
         },
         },
+        {
+            "name": "dompdf/dompdf",
+            "version": "v1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/dompdf/dompdf.git",
+                "reference": "de4aad040737a89fae2129cdeb0f79c45513128d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/dompdf/dompdf/zipball/de4aad040737a89fae2129cdeb0f79c45513128d",
+                "reference": "de4aad040737a89fae2129cdeb0f79c45513128d",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-mbstring": "*",
+                "phenx/php-font-lib": "^0.5.2",
+                "phenx/php-svg-lib": "^0.3.3",
+                "php": "^7.1 || ^8.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "^1.3",
+                "phpunit/phpunit": "^7.5 || ^8 || ^9",
+                "squizlabs/php_codesniffer": "^3.5"
+            },
+            "suggest": {
+                "ext-gd": "Needed to process images",
+                "ext-gmagick": "Improves image processing performance",
+                "ext-imagick": "Improves image processing performance",
+                "ext-zlib": "Needed for pdf stream compression"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Dompdf\\": "src/"
+                },
+                "classmap": [
+                    "lib/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-2.1"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Ménager",
+                    "email": "fabien.menager@gmail.com"
+                },
+                {
+                    "name": "Brian Sweeney",
+                    "email": "eclecticgeek@gmail.com"
+                },
+                {
+                    "name": "Gabriel Bull",
+                    "email": "me@gabrielbull.com"
+                }
+            ],
+            "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
+            "homepage": "https://github.com/dompdf/dompdf",
+            "support": {
+                "issues": "https://github.com/dompdf/dompdf/issues",
+                "source": "https://github.com/dompdf/dompdf/tree/v1.1.1"
+            },
+            "time": "2021-11-24T00:45:04+00:00"
+        },
         {
         {
             "name": "dragonmantank/cron-expression",
             "name": "dragonmantank/cron-expression",
             "version": "v3.1.0",
             "version": "v3.1.0",
@@ -1763,6 +1897,71 @@
             },
             },
             "time": "2021-05-25T16:45:33+00:00"
             "time": "2021-05-25T16:45:33+00:00"
         },
         },
+        {
+            "name": "laraveldaily/laravel-invoices",
+            "version": "2.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/LaravelDaily/laravel-invoices.git",
+                "reference": "88c472680951acc57ccf179711add7d8dda36821"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/LaravelDaily/laravel-invoices/zipball/88c472680951acc57ccf179711add7d8dda36821",
+                "reference": "88c472680951acc57ccf179711add7d8dda36821",
+                "shasum": ""
+            },
+            "require": {
+                "barryvdh/laravel-dompdf": "^0.9",
+                "illuminate/http": "^5.5|^6|^7|^8",
+                "illuminate/support": "^5.5|^6|^7|^8",
+                "php": ">=7.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.4",
+                "symfony/var-dumper": "^5.0"
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "providers": [
+                        "LaravelDaily\\Invoices\\InvoiceServiceProvider"
+                    ],
+                    "aliases": {
+                        "Invoice": "LaravelDaily\\Invoices\\Facades\\Invoice"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "LaravelDaily\\Invoices\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-3.0-only"
+            ],
+            "authors": [
+                {
+                    "name": "David Lun",
+                    "email": "mysticcode@gmail.com",
+                    "homepage": "https://lun.lt",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Missing invoices for Laravel",
+            "homepage": "https://github.com/LaravelDaily/laravel-invoices",
+            "keywords": [
+                "invoice",
+                "invoices",
+                "laravel"
+            ],
+            "support": {
+                "issues": "https://github.com/LaravelDaily/laravel-invoices/issues",
+                "source": "https://github.com/LaravelDaily/laravel-invoices/tree/2.2.0"
+            },
+            "time": "2021-09-29T08:31:40+00:00"
+        },
         {
         {
             "name": "league/commonmark",
             "name": "league/commonmark",
             "version": "1.6.2",
             "version": "1.6.2",
@@ -2601,6 +2800,92 @@
             "abandoned": true,
             "abandoned": true,
             "time": "2019-01-04T20:04:25+00:00"
             "time": "2019-01-04T20:04:25+00:00"
         },
         },
+        {
+            "name": "phenx/php-font-lib",
+            "version": "0.5.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/PhenX/php-font-lib.git",
+                "reference": "ca6ad461f032145fff5971b5985e5af9e7fa88d8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/ca6ad461f032145fff5971b5985e5af9e7fa88d8",
+                "reference": "ca6ad461f032145fff5971b5985e5af9e7fa88d8",
+                "shasum": ""
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35 || ^5 || ^6 || ^7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "FontLib\\": "src/FontLib"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-3.0"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Ménager",
+                    "email": "fabien.menager@gmail.com"
+                }
+            ],
+            "description": "A library to read, parse, export and make subsets of different types of font files.",
+            "homepage": "https://github.com/PhenX/php-font-lib",
+            "support": {
+                "issues": "https://github.com/PhenX/php-font-lib/issues",
+                "source": "https://github.com/PhenX/php-font-lib/tree/0.5.2"
+            },
+            "time": "2020-03-08T15:31:32+00:00"
+        },
+        {
+            "name": "phenx/php-svg-lib",
+            "version": "0.3.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/PhenX/php-svg-lib.git",
+                "reference": "f627771eb854aa7f45f80add0f23c6c4d67ea0f2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/PhenX/php-svg-lib/zipball/f627771eb854aa7f45f80add0f23c6c4d67ea0f2",
+                "reference": "f627771eb854aa7f45f80add0f23c6c4d67ea0f2",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.4 || ^8.0",
+                "sabberworm/php-css-parser": "^8.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.5"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Svg\\": "src/Svg"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-3.0"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Ménager",
+                    "email": "fabien.menager@gmail.com"
+                }
+            ],
+            "description": "A library to read, parse and export to PDF SVG files.",
+            "homepage": "https://github.com/PhenX/php-svg-lib",
+            "support": {
+                "issues": "https://github.com/PhenX/php-svg-lib/issues",
+                "source": "https://github.com/PhenX/php-svg-lib/tree/0.3.4"
+            },
+            "time": "2021-10-18T02:13:32+00:00"
+        },
         {
         {
             "name": "phpoption/phpoption",
             "name": "phpoption/phpoption",
             "version": "1.7.5",
             "version": "1.7.5",
@@ -3262,6 +3547,55 @@
             ],
             ],
             "time": "2020-08-18T17:17:46+00:00"
             "time": "2020-08-18T17:17:46+00:00"
         },
         },
+        {
+            "name": "sabberworm/php-css-parser",
+            "version": "8.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sabberworm/PHP-CSS-Parser.git",
+                "reference": "d217848e1396ef962fb1997cf3e2421acba7f796"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/d217848e1396ef962fb1997cf3e2421acba7f796",
+                "reference": "d217848e1396ef962fb1997cf3e2421acba7f796",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "codacy/coverage": "^1.4",
+                "phpunit/phpunit": "~4.8"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Sabberworm\\CSS": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Raphael Schweikert"
+                }
+            ],
+            "description": "Parser for CSS Files written in PHP",
+            "homepage": "http://www.sabberworm.com/blog/2010/6/10/php-css-parser",
+            "keywords": [
+                "css",
+                "parser",
+                "stylesheet"
+            ],
+            "support": {
+                "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues",
+                "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.3.1"
+            },
+            "time": "2020-06-01T09:10:00+00:00"
+        },
         {
         {
             "name": "socialiteproviders/discord",
             "name": "socialiteproviders/discord",
             "version": "4.1.1",
             "version": "4.1.1",

+ 2 - 0
config/app.php

@@ -83,6 +83,7 @@ return [
 
 
     'locale' => env('LOCALE', 'en'),
     'locale' => env('LOCALE', 'en'),
 
 
+
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     | Datatable Language Setting
     | Datatable Language Setting
@@ -96,6 +97,7 @@ return [
 
 
     'datatable_locale' => env('DATATABLE_LOCALE', 'en-gb'),
     'datatable_locale' => env('DATATABLE_LOCALE', 'en-gb'),
 
 
+
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     | Application Fallback Locale
     | Application Fallback Locale

+ 97 - 0
config/invoices.php

@@ -0,0 +1,97 @@
+<?php
+
+return [
+    'date' => [
+        /*
+         * Carbon date format
+         */
+        'format' => 'Y-m-d',
+        /*
+         * Due date for payment since invoice's date.
+         */
+        'pay_until_days' => 7,
+    ],
+
+    'serial_number' => [
+        'series'   => 'AA',
+        'sequence' => 1,
+        /*
+         * Sequence will be padded accordingly, for ex. 00001
+         */
+        'sequence_padding' => 5,
+        'delimiter'        => '.',
+        /*
+         * Supported tags {SERIES}, {DELIMITER}, {SEQUENCE}
+         * Example: AA.00001
+         */
+        'format' => '{SERIES}{DELIMITER}{SEQUENCE}',
+    ],
+
+    'currency' => [
+        'code' => 'eur',
+        /*
+         * Usually cents
+         * Used when spelling out the amount and if your currency has decimals.
+         *
+         * Example: Amount in words: Eight hundred fifty thousand sixty-eight EUR and fifteen ct.
+         */
+        'fraction' => 'ct.',
+        'symbol'   => '€',
+        /*
+         * Example: 19.00
+         */
+        'decimals' => 2,
+        /*
+         * Example: 1.99
+         */
+        'decimal_point' => '.',
+        /*
+         * By default empty.
+         * Example: 1,999.00
+         */
+        'thousands_separator' => '',
+        /*
+         * Supported tags {VALUE}, {SYMBOL}, {CODE}
+         * Example: 1.99 €
+         */
+        'format' => '{VALUE} {SYMBOL}',
+    ],
+
+    'paper' => [
+        // A4 = 210 mm x 297 mm = 595 pt x 842 pt
+        'size'        => 'a4',
+        'orientation' => 'portrait',
+    ],
+
+    'disk' => 'local',
+
+    'seller' => [
+        /*
+         * Class used in templates via $invoice->seller
+         *
+         * Must implement LaravelDaily\Invoices\Contracts\PartyContract
+         *      or extend LaravelDaily\Invoices\Classes\Party
+         */
+        'class' => \LaravelDaily\Invoices\Classes\Seller::class,
+
+        /*
+         * Default attributes for Seller::class
+         */
+        'attributes' => [
+            'name'          => 'Towne, Smith and Ebert',
+            'address'       => '89982 Pfeffer Falls Damianstad, CO 66972-8160',
+            'code'          => '41-1985581',
+            'vat'           => '123456789',
+            'phone'         => '760-355-3930',
+            'custom_fields' => [
+                /*
+                 * Custom attributes for Seller::class
+                 *
+                 * Used to display additional info on Seller section in invoice
+                 * attribute => value
+                 */
+                'SWIFT' => 'BANK101',
+            ],
+        ],
+    ],
+];

+ 34 - 0
database/migrations/2021_11_27_014226_create_invoices.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateInvoices extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('invoices', function (Blueprint $table) {
+            $table->id();
+            $table->string('invoice_name');
+            $table->string('invoice_user');
+            $table->string('payment_id');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('invoices');
+    }
+}

+ 48 - 0
database/migrations/2021_12_1_174440_invoice-settings.php

@@ -0,0 +1,48 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Schema;
+
+class InvoiceSettings extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('invoice_settings', function (Blueprint $table) {
+            $table->id();
+            $table->string('company_name')->nullable();
+            $table->string('company_adress')->nullable();
+            $table->string('company_phone')->nullable();
+            $table->string('company_vat')->nullable();
+            $table->string('company_mail')->nullable();
+            $table->string('company_web')->nullable()->default(env("APP_URL",""));
+            $table->string('invoice_prefix')->nullable();
+            $table->timestamps();
+        });
+
+        DB::table('invoice_settings')->insert(
+            array(
+                'company_name' => env("APP_NAME","MyCompany"),
+                'company_web' => env("APP_URL",""),
+                'invoice_prefix' => "INV"
+
+            )
+        );
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('invoice_settings');
+    }
+}

+ 1 - 0
database/seeders/DatabaseSeeder.php

@@ -3,6 +3,7 @@
 namespace Database\Seeders;
 namespace Database\Seeders;
 
 
 use Database\Seeders\Seeds\ConfigurationSeeder;
 use Database\Seeders\Seeds\ConfigurationSeeder;
+use Database\Seeders\Seeds\InvoiceSettingsSeeder;
 use Illuminate\Database\Seeder;
 use Illuminate\Database\Seeder;
 
 
 class DatabaseSeeder extends Seeder
 class DatabaseSeeder extends Seeder

+ 0 - 1
resources/lang/de.json

@@ -358,5 +358,4 @@
     "Login as User": "Als User anmelden",
     "Login as User": "Als User anmelden",
     "Clone": "Klonen"
     "Clone": "Klonen"
 
 
-
 }
 }

+ 114 - 2
resources/views/admin/settings/index.blade.php

@@ -39,6 +39,9 @@
                         <li class="nav-item">
                         <li class="nav-item">
                             <a class="nav-link active" data-toggle="pill" href="#dashboard-icons">{{__('Dashboard icons')}}</a>
                             <a class="nav-link active" data-toggle="pill" href="#dashboard-icons">{{__('Dashboard icons')}}</a>
                         </li>
                         </li>
+                        <li class="nav-item">
+                            <a class="nav-link" data-toggle="pill" href="#invoice-settings">{{__('Invoice Settings')}}</a>
+                        </li>
                     </ul>
                     </ul>
 
 
                     <!-- Tab panes -->
                     <!-- Tab panes -->
@@ -88,14 +91,123 @@
                                     chrome hotkey)</sup> to reload without cache to see your changes appear :)</p>
                                     chrome hotkey)</sup> to reload without cache to see your changes appear :)</p>
 
 
                         </div>
                         </div>
+
+                        <div class="tab-pane mt-3" id="invoice-settings">
+                            <div class="float-right">
+                                <a href="{{route('admin.settings.downloadAllInvoices')}}"><button class="btn btn-success">{{__('Download all Invoices')}}</button></a>
+                            </div>
+
+                            <form method="POST" enctype="multipart/form-data" class="mb-3"
+                                  action="{{route('admin.settings.update.invoicesettings')}}">
+                                @csrf
+                                @method('PATCH')
+
+                                <div class="row">
+                                    <div class="col-md-6 col-lg-4 col-12">
+                                        <!-- Name -->
+                                        <div class="form-group">
+                                            <div class="custom-control mb-3">
+                                                <label for="company-name">{{__('Enter your companys name' )}}</label>
+                                                <input x-model="company-name" id="company-name" name="company-name"
+                                                       type="text" value="{{$company_name}}"
+                                                       class="form-control @error('company-name') is-invalid @enderror">
+                                            </div>
+                                        </div>
+                                        <!-- adress -->
+                                        <div class="form-group">
+                                            <div class="custom-control mb-3">
+                                                <label
+                                                    for="company-adress">{{__('Enter your companys adress' )}}</label>
+                                                <input x-model="company-adress" id="company-adress"
+                                                       name="company-adress" type="text" value="{{$company_adress}}"
+                                                       class="form-control @error('company-adress') is-invalid @enderror">
+                                            </div>
+                                        </div>
+                                        <!-- Phone -->
+                                        <div class="form-group">
+                                            <div class="custom-control mb-3">
+                                                <label
+                                                    for="company-phone">{{__('Enter your companys phone number' )}}</label>
+                                                <input x-model="company-phone" id="company-phone" name="company-phone"
+                                                       type="text" value="{{$company_phone}}"
+                                                       class="form-control @error('company-phone') is-invalid @enderror">
+                                            </div>
+                                        </div>
+
+                                        <!-- VAT -->
+                                        <div class="form-group">
+                                            <div class="custom-control mb-3">
+                                                <label for="company-vat">{{__('Enter your companys VAT id' )}}</label>
+                                                <input x-model="company-vat" id="company-vat" name="company-vat"
+                                                       type="text" value="{{$company_vat}}"
+                                                       class="form-control @error('company-vat') is-invalid @enderror">
+                                            </div>
+                                        </div>
+
+                                        <!-- email -->
+                                        <div class="form-group">
+                                            <div class="custom-control mb-3">
+                                                <label
+                                                    for="company-mail">{{__('Enter your companys email adress' )}}</label>
+                                                <input x-model="company-mail" id="company-mail" name="company-mail"
+                                                       type="text" value="{{$company_mail}}"
+                                                       class="form-control @error('company-mail') is-invalid @enderror">
+                                            </div>
+                                        </div>
+                                        <!-- website -->
+                                        <div class="form-group">
+                                            <div class="custom-control mb-3">
+                                                <label
+                                                    for="company-web">{{__('Enter your companys website' )}}</label>
+                                                <input x-model="company-web" id="company-web" name="company-web"
+                                                       type="text" value="{{$company_web}}"
+                                                       class="form-control @error('company-web') is-invalid @enderror">
+                                            </div>
+                                        </div>
+
+                                        <!-- website -->
+                                        <div class="form-group">
+                                            <div class="custom-control mb-3">
+                                                <label
+                                                    for="invoice-prefix">{{__('Enter your custom invoice prefix' )}}</label>
+                                                <input x-model="invoice-prefix" id="invoice-prefix" name="invoice-prefix"
+                                                       type="text" value="{{$invoice_prefix}}"
+                                                       class="form-control @error('invoice-prefix') is-invalid @enderror">
+                                            </div>
+                                        </div>
+
+                                        <!-- logo -->
+                                        <div class="form-group">
+                                            <div class="custom-file mb-3">
+                                                <input type="file" accept="image/png,image/jpeg,image/jpg" class="custom-file-input"
+                                                       name="logo" id="logo">
+                                                <label class="custom-file-label selected"
+                                                       for="favicon">{{__('Select Invoice Logo')}}</label>
+                                            </div>
+                                            @error('logo')
+                                            <span class="text-danger">
+                                                   {{$message}}
+                                               </span>
+                                            @enderror
+                                        </div>
+                                    </div>
+                                </div>
+                                <button class="btn btn-primary">{{__('Submit')}}</button>
+                                <!-- end -->
+
+                        </div>
                     </div>
                     </div>
 
 
 
 
+                    </form>
+
                 </div>
                 </div>
             </div>
             </div>
 
 
-
         </div>
         </div>
+        </div>
+
+
         <!-- END CUSTOM CONTENT -->
         <!-- END CUSTOM CONTENT -->
 
 
     </section>
     </section>
@@ -103,7 +215,7 @@
 
 
     <script>
     <script>
         // Add the following code if you want the name of the file appear on select
         // Add the following code if you want the name of the file appear on select
-        document.addEventListener('DOMContentLoaded', ()=>{
+        document.addEventListener('DOMContentLoaded', () => {
             $(".custom-file-input").on("change", function () {
             $(".custom-file-input").on("change", function () {
                 var fileName = $(this).val().split("\\").pop();
                 var fileName = $(this).val().split("\\").pop();
                 $(this).siblings(".custom-file-label").addClass("selected").html(fileName);
                 $(this).siblings(".custom-file-label").addClass("selected").html(fileName);

+ 390 - 0
resources/views/vendor/invoices/templates/controlpanel.blade.php

@@ -0,0 +1,390 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title>{{ $invoice->name }}</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+        <style type="text/css" media="screen">
+            html {
+                font-family: sans-serif;
+                line-height: 1.15;
+                margin: 0;
+            }
+
+            body {
+                font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+                font-weight: 400;
+                line-height: 1.5;
+                color: #212529;
+                text-align: left;
+                background-color: #fff;
+                font-size: 10px;
+                margin: 36pt;
+            }
+
+            h4 {
+                margin-top: 0;
+                margin-bottom: 0.5rem;
+            }
+
+            p {
+                margin-top: 0;
+                margin-bottom: 1rem;
+            }
+
+            strong {
+                font-weight: bolder;
+            }
+
+            img {
+                vertical-align: middle;
+                border-style: none;
+            }
+
+            table {
+                border-collapse: collapse;
+            }
+
+            th {
+                text-align: inherit;
+            }
+
+            h4, .h4 {
+                margin-bottom: 0.5rem;
+                font-weight: 500;
+                line-height: 1.2;
+            }
+
+            h4, .h4 {
+                font-size: 1.5rem;
+            }
+
+            .table {
+                width: 100%;
+                margin-bottom: 1rem;
+                color: #212529;
+            }
+
+            .table th,
+            .table td {
+                padding: 0.75rem;
+                vertical-align: top;
+            }
+
+            .table.table-items td {
+                border-top: 1px solid #dee2e6;
+            }
+
+            .table thead th {
+                vertical-align: bottom;
+                border-bottom: 2px solid #dee2e6;
+            }
+
+            .mt-5 {
+                margin-top: 3rem !important;
+            }
+
+            .pr-0,
+            .px-0 {
+                padding-right: 0 !important;
+            }
+
+            .pl-0,
+            .px-0 {
+                padding-left: 0 !important;
+            }
+
+            .text-right {
+                text-align: right !important;
+            }
+
+            .text-center {
+                text-align: center !important;
+            }
+
+            .text-uppercase {
+                text-transform: uppercase !important;
+            }
+            * {
+                font-family: "DejaVu Sans";
+            }
+            body, h1, h2, h3, h4, h5, h6, table, th, tr, td, p, div {
+                line-height: 1.1;
+            }
+            .party-header {
+                font-size: 1.5rem;
+                font-weight: 400;
+            }
+            .total-amount {
+                font-size: 12px;
+                font-weight: 700;
+            }
+            .border-0 {
+                border: none !important;
+            }
+            .cool-gray {
+                color: #6B7280;
+            }
+            .cool-green {
+                color: #308d00;
+            }
+        </style>
+    </head>
+
+    <body>
+        {{-- Header --}}
+        @if($invoice->logo)
+            <img src="{{ $invoice->getLogo() }}" alt="logo" height="100">
+        @endif
+
+        <table class="table mt-5">
+            <tbody>
+                <tr>
+                <tr>
+                    <td class="border-0 pl-0" width="70%">
+                        <h4 class="text-uppercase">
+                            <strong>{{ $invoice->name }} {{$invoice->getSerialNumber()}}</strong>
+                        </h4>
+                    </td>
+                    <td class="border-0 pl-0">
+                        @if($invoice->status)
+                            <h4 class="text-uppercase cool-green">
+                                <strong>{{ $invoice->status }}</strong>
+                            </h4>
+                        @endif
+                        <p>{{ __('Serial No.') }} <strong>{{ $invoice->getSerialNumber() }}</strong></p>
+                        <p>{{ __('Invoice date') }}: <strong>{{ $invoice->getDate() }}</strong></p>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+
+        {{-- Seller - Buyer --}}
+        <table class="table">
+            <thead>
+                <tr>
+                    <th class="border-0 pl-0 party-header" width="48.5%">
+                        {{ __('Seller') }}
+                    </th>
+                    <th class="border-0" width="3%"></th>
+                    <th class="border-0 pl-0 party-header">
+                        {{ __('Buyer') }}
+                    </th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="px-0">
+                        @if($invoice->seller->name)
+                            <p class="seller-name">
+                                <strong>{{ $invoice->seller->name }}</strong>
+                            </p>
+                        @endif
+
+                        @if($invoice->seller->address)
+                            <p class="seller-address">
+                                {{ __('Adress') }}: {{ $invoice->seller->address }}
+                            </p>
+                        @endif
+
+                        @if($invoice->seller->code)
+                            <p class="seller-code">
+                                {{ __('Code') }}: {{ $invoice->seller->code }}
+                            </p>
+                        @endif
+
+                        @if($invoice->seller->vat)
+                            <p class="seller-vat">
+                                {{ __('VAT Code') }}: {{ $invoice->seller->vat }}
+                            </p>
+                        @endif
+
+                        @if($invoice->seller->phone)
+                            <p class="seller-phone">
+                                {{ __('Phone') }}: {{ $invoice->seller->phone }}
+                            </p>
+                        @endif
+
+                        @foreach($invoice->seller->custom_fields as $key => $value)
+                            <p class="seller-custom-field">
+                                {{ ucfirst($key) }}: {{ $value }}
+                            </p>
+                        @endforeach
+                    </td>
+                    <td class="border-0"></td>
+                    <td class="px-0">
+                        @if($invoice->buyer->name)
+                            <p class="buyer-name">
+                                <strong>{{ $invoice->buyer->name }}</strong>
+                            </p>
+                        @endif
+
+                        @if($invoice->buyer->address)
+                            <p class="buyer-address">
+                                {{ __('Adress') }}: {{ $invoice->buyer->address }}
+                            </p>
+                        @endif
+
+                        @if($invoice->buyer->code)
+                            <p class="buyer-code">
+                                {{ __('Code') }}: {{ $invoice->buyer->code }}
+                            </p>
+                        @endif
+
+                        @if($invoice->buyer->vat)
+                            <p class="buyer-vat">
+                                {{ __('VAT Code') }}: {{ $invoice->buyer->vat }}
+                            </p>
+                        @endif
+
+                        @if($invoice->buyer->phone)
+                            <p class="buyer-phone">
+                                {{ __('Phone') }}: {{ $invoice->buyer->phone }}
+                            </p>
+                        @endif
+
+                        @foreach($invoice->buyer->custom_fields as $key => $value)
+                            <p class="buyer-custom-field">
+                                {{ ucfirst($key) }}: {{ $value }}
+                            </p>
+                        @endforeach
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+
+        {{-- Table --}}
+        <table class="table table-items">
+            <thead>
+                <tr>
+                    <th scope="col" class="border-0 pl-0">{{ __('Description') }}</th>
+                    @if($invoice->hasItemUnits)
+                        <th scope="col" class="text-center border-0">{{ __('Units') }}</th>
+                    @endif
+                    <th scope="col" class="text-center border-0">{{ __('Quantity') }}</th>
+                    <th scope="col" class="text-right border-0">{{ __('Price') }}</th>
+                    @if($invoice->hasItemDiscount)
+                        <th scope="col" class="text-right border-0">{{ __('Discount') }}</th>
+                    @endif
+                    @if($invoice->hasItemTax)
+                        <th scope="col" class="text-right border-0">{{ __('Tax') }}</th>
+                    @endif
+                    <th scope="col" class="text-right border-0 pr-0">{{ __('Subtotal') }}</th>
+                </tr>
+            </thead>
+            <tbody>
+                {{-- Items --}}
+                @foreach($invoice->items as $item)
+                <tr>
+                    <td class="pl-0">
+                        {{ $item->title }}
+
+                        @if($item->description)
+                            <p class="cool-gray">{{ $item->description }}</p>
+                        @endif
+                    </td>
+                    @if($invoice->hasItemUnits)
+                        <td class="text-center">{{ $item->units }}</td>
+                    @endif
+                    <td class="text-center">{{ $item->quantity }}</td>
+                    <td class="text-right">
+                        {{ $invoice->formatCurrency($item->price_per_unit) }}
+                    </td>
+                    @if($invoice->hasItemDiscount)
+                        <td class="text-right">
+                            {{ $invoice->formatCurrency($item->discount) }}
+                        </td>
+                    @endif
+                    @if($invoice->hasItemTax)
+                        <td class="text-right">
+                            {{ $invoice->formatCurrency($item->tax) }}
+                        </td>
+                    @endif
+
+                    <td class="text-right pr-0">
+                        {{ $invoice->formatCurrency($item->sub_total_price) }}
+                    </td>
+                </tr>
+                @endforeach
+                {{-- Summary --}}
+                @if($invoice->hasItemOrInvoiceDiscount())
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('Total Discount') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->formatCurrency($invoice->total_discount) }}
+                        </td>
+                    </tr>
+                @endif
+                @if($invoice->taxable_amount)
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('Taxable amount') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->formatCurrency($invoice->taxable_amount) }}
+                        </td>
+                    </tr>
+                @endif
+                @if($invoice->tax_rate)
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('Tax rate') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->tax_rate }}%
+                        </td>
+                    </tr>
+                @endif
+                @if($invoice->hasItemOrInvoiceTax())
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('Total taxes') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->formatCurrency($invoice->total_taxes) }}
+                        </td>
+                    </tr>
+                @endif
+                @if($invoice->shipping_amount)
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('Shipping') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->formatCurrency($invoice->shipping_amount) }}
+                        </td>
+                    </tr>
+                @endif
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('Total amount') }}</td>
+                        <td class="text-right pr-0 total-amount">
+                            {{ $invoice->formatCurrency($invoice->total_amount) }}
+                        </td>
+                    </tr>
+            </tbody>
+        </table>
+
+        @if($invoice->notes)
+            <p>
+                {{ trans('Notes') }}: {!! $invoice->notes !!}
+            </p>
+        @endif
+
+        <p>
+            {{ trans('Amount in words') }}: {{ $invoice->getTotalAmountInWords() }}
+        </p>
+        <p>
+            {{ trans('Please pay until') }}: {{ $invoice->getPayUntilDate() }}
+        </p>
+
+        <script type="text/php">
+            if (isset($pdf) && $PAGE_COUNT > 1) {
+                $text = "Page {PAGE_NUM} / {PAGE_COUNT}";
+                $size = 10;
+                $font = $fontMetrics->getFont("Verdana");
+                $width = $fontMetrics->get_text_width($text, $font, $size) / 2;
+                $x = ($pdf->get_width() - $width);
+                $y = $pdf->get_height() - 35;
+                $pdf->page_text($x, $y, $text, $font, $size);
+            }
+        </script>
+    </body>
+</html>

+ 390 - 0
resources/views/vendor/invoices/templates/default.blade.php

@@ -0,0 +1,390 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title>{{ $invoice->name }}</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+        <style type="text/css" media="screen">
+            html {
+                font-family: sans-serif;
+                line-height: 1.15;
+                margin: 0;
+            }
+
+            body {
+                font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+                font-weight: 400;
+                line-height: 1.5;
+                color: #212529;
+                text-align: left;
+                background-color: #fff;
+                font-size: 10px;
+                margin: 36pt;
+            }
+
+            h4 {
+                margin-top: 0;
+                margin-bottom: 0.5rem;
+            }
+
+            p {
+                margin-top: 0;
+                margin-bottom: 1rem;
+            }
+
+            strong {
+                font-weight: bolder;
+            }
+
+            img {
+                vertical-align: middle;
+                border-style: none;
+            }
+
+            table {
+                border-collapse: collapse;
+            }
+
+            th {
+                text-align: inherit;
+            }
+
+            h4, .h4 {
+                margin-bottom: 0.5rem;
+                font-weight: 500;
+                line-height: 1.2;
+            }
+
+            h4, .h4 {
+                font-size: 1.5rem;
+            }
+
+            .table {
+                width: 100%;
+                margin-bottom: 1rem;
+                color: #212529;
+            }
+
+            .table th,
+            .table td {
+                padding: 0.75rem;
+                vertical-align: top;
+            }
+
+            .table.table-items td {
+                border-top: 1px solid #dee2e6;
+            }
+
+            .table thead th {
+                vertical-align: bottom;
+                border-bottom: 2px solid #dee2e6;
+            }
+
+            .mt-5 {
+                margin-top: 3rem !important;
+            }
+
+            .pr-0,
+            .px-0 {
+                padding-right: 0 !important;
+            }
+
+            .pl-0,
+            .px-0 {
+                padding-left: 0 !important;
+            }
+
+            .text-right {
+                text-align: right !important;
+            }
+
+            .text-center {
+                text-align: center !important;
+            }
+
+            .text-uppercase {
+                text-transform: uppercase !important;
+            }
+            * {
+                font-family: "DejaVu Sans";
+            }
+            body, h1, h2, h3, h4, h5, h6, table, th, tr, td, p, div {
+                line-height: 1.1;
+            }
+            .party-header {
+                font-size: 1.5rem;
+                font-weight: 400;
+            }
+            .total-amount {
+                font-size: 12px;
+                font-weight: 700;
+            }
+            .border-0 {
+                border: none !important;
+            }
+            .cool-gray {
+                color: #6B7280;
+            }
+            .cool-green {
+                color: #308d00;
+            }
+        </style>
+    </head>
+
+    <body>
+        {{-- Header --}}
+        @if($invoice->logo)
+            <img src="{{ $invoice->getLogo() }}" alt="logo" height="100">
+        @endif
+
+        <table class="table mt-5">
+            <tbody>
+                <tr>
+                <tr>
+                    <td class="border-0 pl-0" width="70%">
+                        <h4 class="text-uppercase">
+                            <strong>{{ $invoice->name }} {{$invoice->getSerialNumber()}}</strong>
+                        </h4>
+                    </td>
+                    <td class="border-0 pl-0">
+                        @if($invoice->status)
+                            <h4 class="text-uppercase cool-green">
+                                <strong>{{ $invoice->status }}</strong>
+                            </h4>
+                        @endif
+                        <p>{{ __('invoices::invoice.serial') }} <strong>{{ $invoice->getSerialNumber() }}</strong></p>
+                        <p>{{ __('invoices::invoice.date') }}: <strong>{{ $invoice->getDate() }}</strong></p>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+
+        {{-- Seller - Buyer --}}
+        <table class="table">
+            <thead>
+                <tr>
+                    <th class="border-0 pl-0 party-header" width="48.5%">
+                        {{ __('invoices::invoice.seller') }}
+                    </th>
+                    <th class="border-0" width="3%"></th>
+                    <th class="border-0 pl-0 party-header">
+                        {{ __('invoices::invoice.buyer') }}
+                    </th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="px-0">
+                        @if($invoice->seller->name)
+                            <p class="seller-name">
+                                <strong>{{ $invoice->seller->name }}</strong>
+                            </p>
+                        @endif
+
+                        @if($invoice->seller->address)
+                            <p class="seller-address">
+                                {{ __('invoices::invoice.address') }}: {{ $invoice->seller->address }}
+                            </p>
+                        @endif
+
+                        @if($invoice->seller->code)
+                            <p class="seller-code">
+                                {{ __('invoices::invoice.code') }}: {{ $invoice->seller->code }}
+                            </p>
+                        @endif
+
+                        @if($invoice->seller->vat)
+                            <p class="seller-vat">
+                                {{ __('invoices::invoice.vat') }}: {{ $invoice->seller->vat }}
+                            </p>
+                        @endif
+
+                        @if($invoice->seller->phone)
+                            <p class="seller-phone">
+                                {{ __('invoices::invoice.phone') }}: {{ $invoice->seller->phone }}
+                            </p>
+                        @endif
+
+                        @foreach($invoice->seller->custom_fields as $key => $value)
+                            <p class="seller-custom-field">
+                                {{ ucfirst($key) }}: {{ $value }}
+                            </p>
+                        @endforeach
+                    </td>
+                    <td class="border-0"></td>
+                    <td class="px-0">
+                        @if($invoice->buyer->name)
+                            <p class="buyer-name">
+                                <strong>{{ $invoice->buyer->name }}</strong>
+                            </p>
+                        @endif
+
+                        @if($invoice->buyer->address)
+                            <p class="buyer-address">
+                                {{ __('invoices::invoice.address') }}: {{ $invoice->buyer->address }}
+                            </p>
+                        @endif
+
+                        @if($invoice->buyer->code)
+                            <p class="buyer-code">
+                                {{ __('invoices::invoice.code') }}: {{ $invoice->buyer->code }}
+                            </p>
+                        @endif
+
+                        @if($invoice->buyer->vat)
+                            <p class="buyer-vat">
+                                {{ __('invoices::invoice.vat') }}: {{ $invoice->buyer->vat }}
+                            </p>
+                        @endif
+
+                        @if($invoice->buyer->phone)
+                            <p class="buyer-phone">
+                                {{ __('invoices::invoice.phone') }}: {{ $invoice->buyer->phone }}
+                            </p>
+                        @endif
+
+                        @foreach($invoice->buyer->custom_fields as $key => $value)
+                            <p class="buyer-custom-field">
+                                {{ ucfirst($key) }}: {{ $value }}
+                            </p>
+                        @endforeach
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+
+        {{-- Table --}}
+        <table class="table table-items">
+            <thead>
+                <tr>
+                    <th scope="col" class="border-0 pl-0">{{ __('invoices::invoice.description') }}</th>
+                    @if($invoice->hasItemUnits)
+                        <th scope="col" class="text-center border-0">{{ __('invoices::invoice.units') }}</th>
+                    @endif
+                    <th scope="col" class="text-center border-0">{{ __('invoices::invoice.quantity') }}</th>
+                    <th scope="col" class="text-right border-0">{{ __('invoices::invoice.price') }}</th>
+                    @if($invoice->hasItemDiscount)
+                        <th scope="col" class="text-right border-0">{{ __('invoices::invoice.discount') }}</th>
+                    @endif
+                    @if($invoice->hasItemTax)
+                        <th scope="col" class="text-right border-0">{{ __('invoices::invoice.tax') }}</th>
+                    @endif
+                    <th scope="col" class="text-right border-0 pr-0">{{ __('invoices::invoice.sub_total') }}</th>
+                </tr>
+            </thead>
+            <tbody>
+                {{-- Items --}}
+                @foreach($invoice->items as $item)
+                <tr>
+                    <td class="pl-0">
+                        {{ $item->title }}
+
+                        @if($item->description)
+                            <p class="cool-gray">{{ $item->description }}</p>
+                        @endif
+                    </td>
+                    @if($invoice->hasItemUnits)
+                        <td class="text-center">{{ $item->units }}</td>
+                    @endif
+                    <td class="text-center">{{ $item->quantity }}</td>
+                    <td class="text-right">
+                        {{ $invoice->formatCurrency($item->price_per_unit) }}
+                    </td>
+                    @if($invoice->hasItemDiscount)
+                        <td class="text-right">
+                            {{ $invoice->formatCurrency($item->discount) }}
+                        </td>
+                    @endif
+                    @if($invoice->hasItemTax)
+                        <td class="text-right">
+                            {{ $invoice->formatCurrency($item->tax) }}
+                        </td>
+                    @endif
+
+                    <td class="text-right pr-0">
+                        {{ $invoice->formatCurrency($item->sub_total_price) }}
+                    </td>
+                </tr>
+                @endforeach
+                {{-- Summary --}}
+                @if($invoice->hasItemOrInvoiceDiscount())
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('invoices::invoice.total_discount') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->formatCurrency($invoice->total_discount) }}
+                        </td>
+                    </tr>
+                @endif
+                @if($invoice->taxable_amount)
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('invoices::invoice.taxable_amount') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->formatCurrency($invoice->taxable_amount) }}
+                        </td>
+                    </tr>
+                @endif
+                @if($invoice->tax_rate)
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('invoices::invoice.tax_rate') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->tax_rate }}%
+                        </td>
+                    </tr>
+                @endif
+                @if($invoice->hasItemOrInvoiceTax())
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('invoices::invoice.total_taxes') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->formatCurrency($invoice->total_taxes) }}
+                        </td>
+                    </tr>
+                @endif
+                @if($invoice->shipping_amount)
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('invoices::invoice.shipping') }}</td>
+                        <td class="text-right pr-0">
+                            {{ $invoice->formatCurrency($invoice->shipping_amount) }}
+                        </td>
+                    </tr>
+                @endif
+                    <tr>
+                        <td colspan="{{ $invoice->table_columns - 2 }}" class="border-0"></td>
+                        <td class="text-right pl-0">{{ __('invoices::invoice.total_amount') }}</td>
+                        <td class="text-right pr-0 total-amount">
+                            {{ $invoice->formatCurrency($invoice->total_amount) }}
+                        </td>
+                    </tr>
+            </tbody>
+        </table>
+
+        @if($invoice->notes)
+            <p>
+                {{ trans('invoices::invoice.notes') }}: {!! $invoice->notes !!}
+            </p>
+        @endif
+
+        <p>
+            {{ trans('invoices::invoice.amount_in_words') }}: {{ $invoice->getTotalAmountInWords() }}
+        </p>
+        <p>
+            {{ trans('invoices::invoice.pay_until') }}: {{ $invoice->getPayUntilDate() }}
+        </p>
+
+        <script type="text/php">
+            if (isset($pdf) && $PAGE_COUNT > 1) {
+                $text = "Page {PAGE_NUM} / {PAGE_COUNT}";
+                $size = 10;
+                $font = $fontMetrics->getFont("Verdana");
+                $width = $fontMetrics->get_text_width($text, $font, $size) / 2;
+                $x = ($pdf->get_width() - $width);
+                $y = $pdf->get_height() - 35;
+                $pdf->page_text($x, $y, $text, $font, $size);
+            }
+        </script>
+    </body>
+</html>

+ 2 - 0
routes/web.php

@@ -123,6 +123,8 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
         Route::resource('configurations', ConfigurationController::class);
         Route::resource('configurations', ConfigurationController::class);
 
 
         Route::patch('settings/update/icons', [SettingsController::class, 'updateIcons'])->name('settings.update.icons');
         Route::patch('settings/update/icons', [SettingsController::class, 'updateIcons'])->name('settings.update.icons');
+        Route::patch('settings/update/invoice-settings', [SettingsController::class, 'updateInvoiceSettings'])->name('settings.update.invoicesettings');
+        Route::get('settings/download-invoices', [SettingsController::class, 'downloadAllInvoices'])->name('settings.downloadAllInvoices');;
         Route::resource('settings', SettingsController::class)->only('index');
         Route::resource('settings', SettingsController::class)->only('index');
 
 
         Route::get('usefullinks/datatable', [UsefulLinkController::class, 'datatable'])->name('usefullinks.datatable');
         Route::get('usefullinks/datatable', [UsefulLinkController::class, 'datatable'])->name('usefullinks.datatable');

+ 1 - 0
storage/app/public/.gitignore

@@ -1,2 +1,3 @@
 *
 *
 !.gitignore
 !.gitignore
+!logo.png