Signed URL for invoice
This commit is contained in:
parent
2deec6792b
commit
7ee300e5d1
@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Events\InvoicePrinting;
|
||||
use App\Models\Banking\Account;
|
||||
use App\Models\Income\Customer;
|
||||
use App\Models\Income\Revenue;
|
||||
use App\Models\Income\Invoice;
|
||||
use App\Models\Income\InvoiceStatus;
|
||||
use App\Models\Setting\Category;
|
||||
@ -16,6 +17,7 @@ use App\Traits\DateTime;
|
||||
use App\Traits\Uploads;
|
||||
use App\Utilities\Modules;
|
||||
use File;
|
||||
use Illuminate\Http\Request;
|
||||
use Image;
|
||||
use Storage;
|
||||
|
||||
@ -178,4 +180,37 @@ class Invoices extends Controller
|
||||
|
||||
return $logo;
|
||||
}
|
||||
|
||||
public function link(Invoice $invoice, Request $request)
|
||||
{
|
||||
$paid = 0;
|
||||
|
||||
foreach ($invoice->payments as $item) {
|
||||
$amount = $item->amount;
|
||||
|
||||
if ($invoice->currency_code != $item->currency_code) {
|
||||
$item->default_currency_code = $invoice->currency_code;
|
||||
|
||||
$amount = $item->getDynamicConvertedAmount();
|
||||
}
|
||||
|
||||
$paid += $amount;
|
||||
}
|
||||
|
||||
$invoice->paid = $paid;
|
||||
|
||||
$accounts = Account::enabled()->pluck('name', 'id');
|
||||
|
||||
$currencies = Currency::enabled()->pluck('name', 'code')->toArray();
|
||||
|
||||
$account_currency_code = Account::where('id', setting('general.default_account'))->pluck('currency_code')->first();
|
||||
|
||||
$customers = Customer::enabled()->pluck('name', 'id');
|
||||
|
||||
$categories = Category::enabled()->type('income')->pluck('name', 'id');
|
||||
|
||||
$payment_methods = Modules::getPaymentMethods();
|
||||
|
||||
return view('customers.invoices.link', compact('invoice', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods'));
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
"akaunting/language": "1.0.*",
|
||||
"akaunting/money": "1.0.*",
|
||||
"akaunting/setting": "1.0.*",
|
||||
"akaunting/signed-url": "1.0.*",
|
||||
"akaunting/version": "1.0.*",
|
||||
"almasaeed2010/adminlte": "2.3.*",
|
||||
"barryvdh/laravel-debugbar": "2.3.*",
|
||||
|
@ -187,6 +187,7 @@ return [
|
||||
Akaunting\Language\Provider::class,
|
||||
Akaunting\Money\Provider::class,
|
||||
Akaunting\Setting\Provider::class,
|
||||
Akaunting\SignedUrl\Provider::class,
|
||||
Akaunting\Version\Provider::class,
|
||||
Barryvdh\DomPDF\ServiceProvider::class,
|
||||
Bkwld\Cloner\ServiceProvider::class,
|
||||
@ -273,6 +274,7 @@ return [
|
||||
'Module' => Nwidart\Modules\Facades\Module::class,
|
||||
'PDF' => Barryvdh\DomPDF\Facade::class,
|
||||
'Setting' => Akaunting\Setting\Facade::class,
|
||||
'SignedUrl' => Akaunting\SignedUrl\Facade::class,
|
||||
'Version' => Akaunting\Version\Facade::class,
|
||||
|
||||
],
|
||||
|
219
resources/views/customers/invoices/link.blade.php
Normal file
219
resources/views/customers/invoices/link.blade.php
Normal file
@ -0,0 +1,219 @@
|
||||
@extends('layouts.link')
|
||||
|
||||
@section('title', trans_choice('general.invoices', 1) . ': ' . $invoice->invoice_number)
|
||||
|
||||
@section('content')
|
||||
<div class="box box-success">
|
||||
<section class="invoice">
|
||||
<div id="badge">
|
||||
<div class="arrow-up"></div>
|
||||
<div class="label {{ $invoice->status->label }}">{{ trans('invoices.status.' . $invoice->status->code) }}</div>
|
||||
<div class="arrow-right"></div>
|
||||
</div>
|
||||
|
||||
<div class="row invoice-header">
|
||||
<div class="col-xs-7">
|
||||
@if (setting('general.invoice_logo'))
|
||||
<img src="{{ Storage::url(setting('general.invoice_logo')) }}" class="invoice-logo" />
|
||||
@elseif (setting('general.company_logo'))
|
||||
<img src="{{ Storage::url(setting('general.company_logo')) }}" class="invoice-logo" />
|
||||
@else
|
||||
<img src="{{ asset('public/img/company.png') }}" class="invoice-logo" />
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-xs-5 invoice-company">
|
||||
<address>
|
||||
<strong>{{ setting('general.company_name') }}</strong><br>
|
||||
{{ setting('general.company_address') }}<br>
|
||||
@if (setting('general.company_tax_number'))
|
||||
{{ trans('general.tax_number') }}: {{ setting('general.company_tax_number') }}<br>
|
||||
@endif
|
||||
<br>
|
||||
@if (setting('general.company_phone'))
|
||||
{{ setting('general.company_phone') }}<br>
|
||||
@endif
|
||||
{{ setting('general.company_email') }}
|
||||
</address>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-7">
|
||||
{{ trans('invoices.bill_to') }}
|
||||
<address>
|
||||
<strong>{{ $invoice->customer_name }}</strong><br>
|
||||
{{ $invoice->customer_address }}<br>
|
||||
@if ($invoice->customer_tax_number)
|
||||
{{ trans('general.tax_number') }}: {{ $invoice->customer_tax_number }}<br>
|
||||
@endif
|
||||
<br>
|
||||
@if ($invoice->customer_phone)
|
||||
{{ $invoice->customer_phone }}<br>
|
||||
@endif
|
||||
{{ $invoice->customer_email }}
|
||||
</address>
|
||||
</div>
|
||||
<div class="col-xs-5">
|
||||
<div class="table-responsive">
|
||||
<table class="table no-border">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{{ trans('invoices.invoice_number') }}:</th>
|
||||
<td class="text-right">{{ $invoice->invoice_number }}</td>
|
||||
</tr>
|
||||
@if ($invoice->order_number)
|
||||
<tr>
|
||||
<th>{{ trans('invoices.order_number') }}:</th>
|
||||
<td class="text-right">{{ $invoice->order_number }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
<tr>
|
||||
<th>{{ trans('invoices.invoice_date') }}:</th>
|
||||
<td class="text-right">{{ Date::parse($invoice->invoiced_at)->format($date_format) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ trans('invoices.payment_due') }}:</th>
|
||||
<td class="text-right">{{ Date::parse($invoice->due_at)->format($date_format) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 table-responsive">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{{ trans_choice('general.items', 1) }}</th>
|
||||
<th class="text-center">{{ trans('invoices.quantity') }}</th>
|
||||
<th class="text-right">{{ trans('invoices.price') }}</th>
|
||||
<th class="text-right">{{ trans('invoices.total') }}</th>
|
||||
</tr>
|
||||
@foreach($invoice->items as $item)
|
||||
<tr>
|
||||
<td>
|
||||
{{ $item->name }}
|
||||
@if ($item->sku)
|
||||
<br><small>{{ trans('items.sku') }}: {{ $item->sku }}</small>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center">{{ $item->quantity }}</td>
|
||||
<td class="text-right">@money($item->price, $invoice->currency_code, true)</td>
|
||||
<td class="text-right">@money($item->total, $invoice->currency_code, true)</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-7">
|
||||
@if ($invoice->notes)
|
||||
<p class="lead">{{ trans_choice('general.notes', 2) }}</p>
|
||||
|
||||
<p class="text-muted well well-sm no-shadow" style="margin-top: 10px;">
|
||||
{{ $invoice->notes }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-xs-5">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
@foreach($invoice->totals as $total)
|
||||
@if($total->code != 'total')
|
||||
<tr>
|
||||
<th>{{ trans($total['name']) }}:</th>
|
||||
<td class="text-right">@money($total->amount, $invoice->currency_code, true)</td>
|
||||
</tr>
|
||||
@else
|
||||
@if ($invoice->paid)
|
||||
<tr class="text-success">
|
||||
<th>{{ trans('invoices.paid') }}:</th>
|
||||
<td class="text-right">- @money($invoice->paid, $invoice->currency_code, true)</td>
|
||||
</tr>
|
||||
@endif
|
||||
<tr>
|
||||
<th>{{ trans($total['name']) }}:</th>
|
||||
<td class="text-right">@money($total->amount - $invoice->paid, $invoice->currency_code, true)</td>
|
||||
</tr>
|
||||
@endif
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box-footer row no-print">
|
||||
<div class="col-md-10">
|
||||
<a href="{{ url('customers/invoices/' . $invoice->id . '/print') }}" target="_blank" class="btn btn-default">
|
||||
<i class="fa fa-print"></i> {{ trans('general.print') }}
|
||||
</a>
|
||||
<a href="{{ url('customers/invoices/' . $invoice->id . '/pdf') }}" class="btn btn-default" data-toggle="tooltip" title="{{ trans('invoices.download_pdf') }}">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ trans('general.download') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 no-padding-right">
|
||||
@if($invoice->invoice_status_code != 'paid')
|
||||
@if ($payment_methods)
|
||||
{!! Form::select('payment_method', $payment_methods, null, array_merge(['id' => 'payment-method', 'class' => 'form-control', 'placeholder' => trans('general.form.select.field', ['field' => trans_choice('general.payment_methods', 1)])])) !!}
|
||||
{!! Form::hidden('invoice_id', $invoice->id, []) !!}
|
||||
@else
|
||||
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
<div id="confirm" class="col-md-12"></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$(document).on('change', '#payment-method', function (e) {
|
||||
var payment_method = $(this).val();
|
||||
|
||||
gateway = payment_method.split('.');
|
||||
|
||||
$.ajax({
|
||||
url: '{{ url("customers/invoices/" . $invoice->id) }}/' + gateway[0],
|
||||
type: 'GET',
|
||||
dataType: 'JSON',
|
||||
data: $('.box-footer input, .box-footer select'),
|
||||
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
|
||||
beforeSend: function() {
|
||||
$('#confirm').html('');
|
||||
|
||||
$('#confirm').append('<div id="loading" class="text-center"><i class="fa fa-spinner fa-spin fa-5x checkout-spin"></i></div>');
|
||||
},
|
||||
complete: function() {
|
||||
$('#loading').remove();
|
||||
},
|
||||
success: function(data) {
|
||||
if (data['error']) {
|
||||
|
||||
}
|
||||
|
||||
if (data['redirect']) {
|
||||
location = data['redirect'];
|
||||
}
|
||||
|
||||
if (data['html']) {
|
||||
$('#confirm').append(data['html']);
|
||||
}
|
||||
},
|
||||
error: function(data){
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
16
resources/views/layouts/link.blade.php
Normal file
16
resources/views/layouts/link.blade.php
Normal file
@ -0,0 +1,16 @@
|
||||
<html lang="{{ setting('general.default_locale') }}">
|
||||
@include('partials.link.head')
|
||||
|
||||
<body class="hold-transition skin-green-light sidebar-mini fixed link">
|
||||
@stack('body_start')
|
||||
|
||||
<!-- Site wrapper -->
|
||||
<div class="wrapper">
|
||||
@include('partials.link.content')
|
||||
|
||||
@include('partials.link.footer')
|
||||
</div>
|
||||
|
||||
@stack('body_end')
|
||||
</body>
|
||||
</html>
|
39
resources/views/partials/link/content.blade.php
Normal file
39
resources/views/partials/link/content.blade.php
Normal file
@ -0,0 +1,39 @@
|
||||
@stack('content_start')
|
||||
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
@stack('content_wrapper_start')
|
||||
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header content-center">
|
||||
@stack('content_header_start')
|
||||
|
||||
<h1>
|
||||
@yield('title')
|
||||
@yield('new_button')
|
||||
</h1>
|
||||
|
||||
@stack('content_header_end')
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content content-center">
|
||||
@include('flash::message')
|
||||
|
||||
@stack('content_content_start')
|
||||
|
||||
@yield('content')
|
||||
|
||||
@stack('content_content_end')
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
|
||||
@stack('content_wrapper_end')
|
||||
</div>
|
||||
<!-- /.content-wrapper -->
|
||||
|
||||
<script type="text/javascript">
|
||||
$('div.alert').not('.alert-important').delay(3000).fadeOut(350);
|
||||
</script>
|
||||
|
||||
@stack('content_end')
|
7
resources/views/partials/link/footer.blade.php
Normal file
7
resources/views/partials/link/footer.blade.php
Normal file
@ -0,0 +1,7 @@
|
||||
@stack('footer_start')
|
||||
|
||||
<footer class="main-footer">
|
||||
<strong>{{ trans('footer.powered') }}</strong>: <a href="{{ trans('footer.link') }}">{{ trans('footer.software') }}</a>
|
||||
</footer>
|
||||
|
||||
@stack('footer_end')
|
77
resources/views/partials/link/head.blade.php
Normal file
77
resources/views/partials/link/head.blade.php
Normal file
@ -0,0 +1,77 @@
|
||||
<head>
|
||||
@stack('head_start')
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!-- Tell the browser to be responsive to screen width -->
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
||||
|
||||
<title>@yield('title') - @setting('general.company_name')</title>
|
||||
|
||||
<!-- Bootstrap 3.3.6 -->
|
||||
<link rel="stylesheet" href="{{ asset('vendor/almasaeed2010/adminlte/bootstrap/css/bootstrap.min.css') }}">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="{{ asset('public/css/font-awesome.min.css') }}">
|
||||
<!-- Ionicons -->
|
||||
<link rel="stylesheet" href="{{ asset('public/css/ionicons.min.css') }}">
|
||||
<!-- Theme style -->
|
||||
<link rel="stylesheet" href="{{ asset('vendor/almasaeed2010/adminlte/dist/css/AdminLTE.min.css') }}">
|
||||
<!-- AdminLTE Skins -->
|
||||
@if (setting('general.admin_theme', 'skin-green-light') == 'skin-green-light')
|
||||
<link rel="stylesheet" href="{{ asset('vendor/almasaeed2010/adminlte/dist/css/skins/skin-green-light.min.css') }}">
|
||||
@else
|
||||
<link rel="stylesheet" href="{{ asset('vendor/almasaeed2010/adminlte/dist/css/skins/skin-black.min.css') }}">
|
||||
<link rel="stylesheet" href="{{ asset('public/css/skin-black.css?v=' . version('short')) }}">
|
||||
@endif
|
||||
<!-- Data Tables -->
|
||||
<link rel="stylesheet" href="{{ asset('vendor/almasaeed2010/adminlte/plugins/datatables/dataTables.bootstrap.css') }}">
|
||||
<!-- Select2 -->
|
||||
<link rel="stylesheet" href="{{ asset('vendor/almasaeed2010/adminlte/plugins/select2/select2.min.css') }}">
|
||||
<!-- App style -->
|
||||
<link rel="stylesheet" href="{{ asset('public/css/app.css?v=' . version('short')) }}">
|
||||
<link rel="stylesheet" href="{{ asset('public/css/akaunting-green.css?v=' . version('short')) }}">
|
||||
|
||||
<link rel="shortcut icon" href="{{ asset('public/img/favicon.ico') }}">
|
||||
|
||||
@stack('css')
|
||||
|
||||
@stack('stylesheet')
|
||||
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<!-- jQuery 2.2.3 -->
|
||||
<script src="{{ asset('vendor/almasaeed2010/adminlte/plugins/jQuery/jquery-2.2.3.min.js') }}"></script>
|
||||
<!-- Bootstrap 3.3.6 -->
|
||||
<script src="{{ asset('vendor/almasaeed2010/adminlte/bootstrap/js/bootstrap.min.js') }}"></script>
|
||||
<!-- SlimScroll -->
|
||||
<script src="{{ asset('vendor/almasaeed2010/adminlte/plugins/slimScroll/jquery.slimscroll.min.js') }}"></script>
|
||||
<!-- FastClick -->
|
||||
<script src="{{ asset('vendor/almasaeed2010/adminlte/plugins/fastclick/fastclick.js') }}"></script>
|
||||
<!-- Data Tables -->
|
||||
<script src="{{ asset('vendor/almasaeed2010/adminlte/plugins/datatables/jquery.dataTables.min.js') }}"></script>
|
||||
<script src="{{ asset('vendor/almasaeed2010/adminlte/plugins/datatables/dataTables.bootstrap.min.js') }}"></script>
|
||||
<!-- AdminLTE App -->
|
||||
<script src="{{ asset('vendor/almasaeed2010/adminlte/dist/js/app.min.js') }}"></script>
|
||||
|
||||
<!-- Select2 -->
|
||||
<script src="{{ asset('vendor/almasaeed2010/adminlte/plugins/select2/select2.min.js') }}"></script>
|
||||
<!-- Mask Money -->
|
||||
<script src="{{ asset('public/js/jquery/jquery.maskMoney.js') }}"></script>
|
||||
|
||||
<script src="{{ asset('public/js/app.js?v=' . version('short')) }}"></script>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
var url_search = '{{ url("common/search/search") }}';
|
||||
//--></script>
|
||||
|
||||
@stack('js')
|
||||
|
||||
@stack('scripts')
|
||||
|
||||
@stack('head_end')
|
||||
</head>
|
@ -227,6 +227,16 @@ Route::group(['middleware' => 'language'], function () {
|
||||
});
|
||||
});
|
||||
|
||||
Route::group(['middleware' => 'signed-url'], function () {
|
||||
Route::group(['prefix' => 'links'], function () {
|
||||
Route::get('invoices/{invoice}', 'Customers\Invoices@link');
|
||||
Route::get('invoices/{invoice}/print', 'Customers\Invoices@printInvoice');
|
||||
Route::get('invoices/{invoice}/pdf', 'Customers\Invoices@pdfInvoice');
|
||||
Route::post('invoices/{invoice}/payment', 'Customers\Invoices@payment');
|
||||
Route::post('invoices/{invoice}/confirm', 'Customers\Invoices@confirm');
|
||||
});
|
||||
});
|
||||
|
||||
Route::group(['middleware' => 'guest'], function () {
|
||||
Route::group(['prefix' => 'auth'], function () {
|
||||
Route::get('login', 'Auth\Login@create')->name('login');
|
||||
|
Loading…
x
Reference in New Issue
Block a user