diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index 679a4ec..ea9c35b 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -234,22 +234,22 @@ class ClientController extends Controller if (mb_strlen($q) < 3) { return abort(403, __('Search word is too short')); } - $q = '%'.$q.'%'; - $posts = Post::where('status', 1)->where(function($query) use ($q) { + $q = '%' . $q . '%'; + $posts = Post::where('status', 1)->where(function ($query) use ($q) { $query->where('title', 'LIKE', $q) ->orWhere('subtitle', 'LIKE', $q) ->orWhere('body', 'LIKE', $q); })->paginate(100); - $products = Product::where('status', 1)->where(function($query) use ($q) { + $products = Product::where('status', 1)->where(function ($query) use ($q) { $query->where('name', 'LIKE', $q) ->orWhere('excerpt', 'LIKE', $q) ->orWhere('description', 'LIKE', $q); })->paginate(100); - $clips = Clip::where('status', 1)->where(function($query) use ($q) { + $clips = Clip::where('status', 1)->where(function ($query) use ($q) { $query->where('title', 'LIKE', $q) ->orWhere('body', 'LIKE', $q); })->paginate(100); - $title = __('Search for') . ': ' . $request->input('q'); + $title = __('Search for') . ': ' . $request->input('q'); $subtitle = ''; return view('client.tag', compact('posts', 'products', 'clips', 'title', 'subtitle')); } @@ -469,7 +469,7 @@ class ClientController extends Controller { $area = 'login'; $title = __("sign in"); - $subtitle = 'Sign in as customer'; + $subtitle = __('Sign in as customer'); return view('client.default-list', compact('area', 'title', 'subtitle')); } @@ -624,13 +624,14 @@ class ClientController extends Controller } - public function pay($hash){ + public function pay($hash) + { $invoice = Invoice::where('hash', $hash)->first(); // dd($invoice->created_at->timestamp , (time() - 3600)); - if (!in_array($invoice->status, ['PENDING', 'CANCELED', 'FAILED'] ) || $invoice->created_at->timestamp < (time() - 3600) ){ - return redirect()->back()->withErrors(__('This payment method is not available.')); + if (!in_array($invoice->status, ['PENDING', 'CANCELED', 'FAILED']) || $invoice->created_at->timestamp < (time() - 3600)) { + return redirect()->back()->withErrors(__('This payment method is not available.')); } $activeGateway = config('xshop.payment.active_gateway'); /** @var Payment $gateway */ diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 5f418b8..8df6261 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -7,6 +7,8 @@ use App\Models\Customer; use App\Models\Invoice; use App\Models\Product; use App\Models\Ticket; +use chillerlan\QRCode\QRCode; +use chillerlan\QRCode\QROptions; use Illuminate\Http\Request; use Illuminate\Validation\Rules\In; @@ -18,18 +20,18 @@ class CustomerController extends Controller $address->address = $request->input('address'); $address->lat = $request->input('lat'); $address->lng = $request->input('lng'); - $address->state_id = $request->input('state_id')??null; - $address->city_id = $request->input('city_id')??null; + $address->state_id = $request->input('state_id') ?? null; + $address->city_id = $request->input('city_id') ?? null; $address->zip = $request->input('zip'); $address->save(); return $address; } + // public function __construct() { - $this->middleware(function ($request, $next) { if (!auth('customer')->check()) { @@ -76,7 +78,22 @@ class CustomerController extends Controller public function invoice(Invoice $invoice) { - return $invoice; + if (!auth('customer')->check() || $invoice->customer_id != auth('customer')->id()) { + return redirect()->route('client.sign-in')->withErrors([__('You need to login to access this page')]); + } + + $area = 'invoice'; + $title = __("Invoice"); + $subtitle = __("Invoice ID:") . ' ' . $invoice->hash; + + $options = new QROptions([ + 'version' => 5, + 'outputType' => QRCode::OUTPUT_MARKUP_SVG, + 'eccLevel' => QRCode::ECC_L, +// 'imageTransparent' => true, + ]); + $qr = new QRCode($options); + return view('client.invoice', compact('area', 'title', 'subtitle','invoice','qr')); } @@ -108,12 +125,13 @@ class CustomerController extends Controller } - public function addresses(){ + public function addresses() + { return auth('customer')->user()->addresses; } - public function addressUpdate(Request $request, $item) + public function addressUpdate(Request $request, $item) { $item = Address::where('id', $item)->firstOrFail(); @@ -142,10 +160,10 @@ class CustomerController extends Controller if ($item->customer_id != auth('customer')->id()) { return abort(403); } - $add = $item->address ; + $add = $item->address; $item->delete(); - return ['OK' => true, "message" => __(":ADDRESS removed",['ADDRESS' => $add])]; + return ['OK' => true, "message" => __(":ADDRESS removed", ['ADDRESS' => $add])]; } public function addressStore(Request $request) @@ -164,14 +182,15 @@ class CustomerController extends Controller $address = new Address(); $address->customer_id = auth('customer')->user()->id; $address = $this->addressSave($address, $request); - return ['OK' => true,'message' => __("Address added successfully"), 'list'=> auth('customer')->user()->addresses]; + return ['OK' => true, 'message' => __("Address added successfully"), 'list' => auth('customer')->user()->addresses]; } - public function submitTicket(Request $request){ + public function submitTicket(Request $request) + { $request->validate([ - 'title' => ['required', 'string', 'max:255'], - 'body' => ['required', 'string'], + 'title' => ['required', 'string', 'max:255'], + 'body' => ['required', 'string'], ]); $ticket = new Ticket(); @@ -182,12 +201,14 @@ class CustomerController extends Controller return redirect()->route('client.profile')->with('message', __('Ticket added successfully')); } - public function showTicket(Ticket $ticket){ - return view('client.ticket',compact('ticket')); + public function showTicket(Ticket $ticket) + { + return view('client.ticket', compact('ticket')); } - public function ticketAnswer(Ticket $ticket, Request $request){ + public function ticketAnswer(Ticket $ticket, Request $request) + { $request->validate([ 'body' => ['required', 'string'], @@ -201,7 +222,7 @@ class CustomerController extends Controller $nticket->body = trim($request->body); $nticket->customer_id = auth('customer')->user()->id; $nticket->save(); - return redirect(route('client.profile').'#tickets')->with('message', __('Ticket answered successfully')); + return redirect(route('client.profile') . '#tickets')->with('message', __('Ticket answered successfully')); } diff --git a/app/Models/Address.php b/app/Models/Address.php index 14f5391..7cfb22d 100644 --- a/app/Models/Address.php +++ b/app/Models/Address.php @@ -8,4 +8,12 @@ use Illuminate\Database\Eloquent\Model; class Address extends Model { use HasFactory; + + public function state(){ + return $this->belongsTo(State::class); + } + + public function city(){ + return $this->belongsTo(City::class); + } } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index cb8ca30..b12b79f 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -24,7 +24,7 @@ class Invoice extends Model public static $invoiceStatus = ['PENDING', 'CANCELED', 'FAILED', 'PAID', 'PROCESSING', 'COMPLETED']; - public function getRouteKey() + public function getRouteKeyName() { return 'hash'; } @@ -147,4 +147,9 @@ class Invoice extends Model return $payment; } + public function address() + { + return $this->belongsTo(Address::class); + } + } diff --git a/composer.lock b/composer.lock index 435b03b..e018613 100644 --- a/composer.lock +++ b/composer.lock @@ -10516,5 +10516,5 @@ "php": "^8.2" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/resources/js/client.js b/resources/js/client.js index 3bfcc48..0e358e5 100644 --- a/resources/js/client.js +++ b/resources/js/client.js @@ -38,4 +38,4 @@ import "../views/segments/customer/AvisaCustomer/AvisaCustomer.js"; import "../views/segments/attachments_page/DenaAttachList/DenaAttachList.js"; import "../views/segments/attachment/AttachmentWithPreview/AttachmentWithPreview.js"; import "../views/segments/contact/MeloContact/MeloContact.js"; -import "../views/segments/index/InlineMap/InlineMap.js"; +import "../views/segments/invoice/LianaInvoice/LianaInvoice.js"; diff --git a/resources/sass/client-custom/_general.scss b/resources/sass/client-custom/_general.scss index 265654c..2ac2f18 100644 --- a/resources/sass/client-custom/_general.scss +++ b/resources/sass/client-custom/_general.scss @@ -162,3 +162,11 @@ body { height: 64px; object-fit: cover; } + + + +@media print { + .no-print{ + display: none; + } +} diff --git a/resources/sass/client.scss b/resources/sass/client.scss index 12f4ac8..bc35618 100644 --- a/resources/sass/client.scss +++ b/resources/sass/client.scss @@ -49,4 +49,4 @@ $xshop-shadow:2px 2px 4px #777777; @import "../views/segments/attachments_page/DenaAttachList/DenaAttachList"; @import "../views/segments/attachment/AttachmentWithPreview/AttachmentWithPreview"; @import "../views/segments/contact/MeloContact/MeloContact"; -@import "../views/segments/index/InlineMap/InlineMap"; +@import "../views/segments/invoice/LianaInvoice/LianaInvoice"; diff --git a/resources/views/client/invoice.blade.php b/resources/views/client/invoice.blade.php new file mode 100644 index 0000000..a746481 --- /dev/null +++ b/resources/views/client/invoice.blade.php @@ -0,0 +1,29 @@ +@extends('website.inc.website-layout') + +@section('title') + {{$title}} - {{config('app.name')}} +@endsection +@section('content') +
+
+ @if(\App\Models\Area::where('name',$area)->first()->use_default) + @foreach(getParts('default_header') as $part) + @php($p = $part->getBladeWithData()) + @include($p['blade'],['data' => $p['data']]) + @endforeach + @endif +
+ @foreach(getParts($area) as $part) + @php($p = $part->getBladeWithData()) + @include($p['blade'],['data' => $p['data']]) + @endforeach +
+ @if(\App\Models\Area::where('name',$area)->first()->use_default) + @foreach(getParts('default_footer') as $part) + @php($p = $part->getBladeWithData()) + @include($p['blade'],['data' => $p['data']]) + @endforeach + @endif +
+
+@endsection diff --git a/resources/views/segments/invoice/LianaInvoice/LianaInvoice.blade.php b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.blade.php new file mode 100644 index 0000000..5f1df52 --- /dev/null +++ b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.blade.php @@ -0,0 +1,118 @@ +
+
+ +
+
+
+ + +

+ {{config('app.name')}} +

+
+ {{-- @php($invoice == \App\Models\Invoice::first())--}} +
+
+ {{__("Date")}}: {{$invoice->created_at->ldate('Y-m-d')}} +
+
+ {{__("Customer")}}: {{$invoice->customer->name}} +
+
+
+
+ {{__("ID")}}: {{$invoice->hash}} ({{$invoice->status}}) +
+
+ {{__("Customer mobile")}}: {{$invoice->customer->mobile}} +
+
+
+
+ qr code +
+
+ + + + + + + + + + @foreach($invoice->orders as $k => $order) + + + + + + + + @endforeach + + + + + + + +
+ # + + {{__("Product")}} + + {{__("Count")}} + + {{__("Quantity")}} + + {{__("Price")}} +
+ {{$k + 1}} + + {{$order->product->name}} + + {{number_format($order->count)}} + + @if( ($order->quantity->meta??null) == null) + - + @else + @foreach($order->quantity->meta as $m) + + {{$m->human_value}} + + @endforeach + @endif + + {{number_format($order->price_total)}} +
+ - + + {{__("Transport")}} + {{number_format($invoice->transport_price)}} + + {{__("Total price")}} + {{number_format($invoice->total_price)}} + + {{__("Orders count")}}: ({{number_format($invoice->count)}}) +
+ + +
+ {{__("Print")}} +
+
+
diff --git a/resources/views/segments/invoice/LianaInvoice/LianaInvoice.js b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.js new file mode 100644 index 0000000..e69de29 diff --git a/resources/views/segments/invoice/LianaInvoice/LianaInvoice.json b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.json new file mode 100644 index 0000000..7889c34 --- /dev/null +++ b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.json @@ -0,0 +1,10 @@ +{ + "name": "LianaInvoice", + "version": "1.0", + "author": "xStack", + "email": "xshop@xstack.ir", + "license": "GPL-3.0-or-later", + "url": "https:\/\/xstack.ir", + "author_url": "https:\/\/4xmen.ir", + "packages": [] +} \ No newline at end of file diff --git a/resources/views/segments/invoice/LianaInvoice/LianaInvoice.php b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.php new file mode 100644 index 0000000..dcb102c --- /dev/null +++ b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.php @@ -0,0 +1,30 @@ +section = 'theme'; + $setting->key = $part->area->name . '_' . $part->part.'_desc'; + $setting->value = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus aliquid consequuntur culpa cupiditate dignissimos dolor doloremque error facilis ipsum iure officia quam qui, tempora! Fuga harum impedit iusto magnam veniam.'; + $setting->size = 12; + $setting->title = $part->area->name . ' ' . $part->part. ' invoice footer description'; + $setting->type = 'EDITOR'; + $setting->save(); + } + public static function onRemove(Part $part = null) + { + Setting::where('key',$part->area->name . '_' . $part->part.'_desc')->first()?->delete(); + } + public static function onMount(Part $part = null) + { + return $part; + } +} diff --git a/resources/views/segments/invoice/LianaInvoice/LianaInvoice.scss b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.scss new file mode 100644 index 0000000..bfee527 --- /dev/null +++ b/resources/views/segments/invoice/LianaInvoice/LianaInvoice.scss @@ -0,0 +1,31 @@ +.LianaInvoice { + .inv-footer{ + border: 1px solid gray; + padding: 1rem; + border-radius: var(--xshop-border-radius); + } + + + .liana-logo{ + height: 64px; + margin-top: 2rem; + } + + + .qr-code{ + max-width: 150px; + } + @media print { + &{ + font-size: 90%; + } + .qr-code{ + max-width: 100%; + } + .liana-logo{ + width: 64px; + margin-top: 0; + } + } +} + diff --git a/resources/views/segments/invoice/LianaInvoice/screenshot.png b/resources/views/segments/invoice/LianaInvoice/screenshot.png new file mode 100644 index 0000000..aae09e8 Binary files /dev/null and b/resources/views/segments/invoice/LianaInvoice/screenshot.png differ