resolve conflicts

This commit is contained in:
Steffen Mahler 2020-08-06 15:23:32 +02:00
commit c9f7c70d52
199 changed files with 2918 additions and 1019 deletions

View File

@ -4,6 +4,7 @@ APP_VERSION=1.1.2
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_ADMIN_URL=admin
APP_TIMEZONE=Asia/Kolkata
APP_LOCALE=en
LOG_CHANNEL=stack

View File

@ -4,6 +4,7 @@ APP_VERSION=1.1.2
APP_KEY=base64:G4KY3tUsTaY9ONo1n/QyJvVLQZdJDgbIkSJswFK01HE=
APP_DEBUG=true
APP_URL=http://localhost
APP_ADMIN_URL=admin
LOG_CHANNEL=stack

View File

@ -20,6 +20,7 @@
"algolia/algoliasearch-client-php": "^2.2",
"astrotomic/laravel-translatable": "^11.0.0",
"babenkoivan/elastic-scout-driver": "^1.1",
"bagistobrasil/bagisto-product-social-share": "^0.1.2",
"barryvdh/laravel-debugbar": "^3.1",
"barryvdh/laravel-dompdf": "0.8.6",
"doctrine/dbal": "2.9.2",

42
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "fdf74de7a5b3178ce60852ca512a6f21",
"content-hash": "3332479a65fc6c67057c2946a27fe95e",
"packages": [
{
"name": "algolia/algoliasearch-client-php",
@ -302,6 +302,46 @@
],
"time": "2020-06-22T14:14:32+00:00"
},
{
"name": "bagistobrasil/bagisto-product-social-share",
"version": "0.1.2",
"source": {
"type": "git",
"url": "https://github.com/bagistobrasil/bagisto-product-social-share.git",
"reference": "a81c4f29a3e79ce911a9e419cc83ccf513c0ab38"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bagistobrasil/bagisto-product-social-share/zipball/a81c4f29a3e79ce911a9e419cc83ccf513c0ab38",
"reference": "a81c4f29a3e79ce911a9e419cc83ccf513c0ab38",
"shasum": ""
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"BagistoBrasil\\ProductSocialShare\\Providers\\ProductSocialShareProvider"
],
"aliases": []
}
},
"autoload": {
"psr-4": {
"BagistoBrasil\\ProductSocialShare\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Carlos Gartner",
"email": "contato@carlosgartner.com.br"
}
],
"time": "2020-08-04T12:36:28+00:00"
},
{
"name": "barryvdh/laravel-debugbar",
"version": "v3.3.3",

View File

@ -54,6 +54,18 @@ return [
'url' => env('APP_URL', 'http://localhost'),
/*
|--------------------------------------------------------------------------
| Application Admin URL
|--------------------------------------------------------------------------
|
| This URL suffix is used to define the admin url for example
| admin/ or backend/
|
*/
'admin_url' => env('APP_ADMIN_URL', 'admin'),
/*
|--------------------------------------------------------------------------
| Application Timezone

View File

@ -16,7 +16,7 @@
"cross-env": "^5.1",
"jquery": "^3.2",
"laravel-mix": "^5.0.1",
"lodash": "^4.17.4",
"lodash": "^4.17.19",
"popper.js": "^1.12",
"resolve-url-loader": "^3.1.0",
"sass": "^1.24.5",

View File

@ -15,6 +15,12 @@ class CartRuleDataGrid extends DataGrid
protected $channel = 'all';
/** @var string[] contains the keys for which extra filters to show */
protected $extraFilters = [
'channels',
'customer_groups',
];
public function __construct()
{
parent::__construct();

View File

@ -45,6 +45,19 @@ class OrderInvoicesDataGrid extends DataGrid
'filterable' => true,
]);
$this->addColumn([
'index' => 'created_at',
'label' => trans('admin::app.datagrid.invoice-date'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
'closure' => true,
'wrapper' => function ($value) {
return \Carbon\Carbon::parse($value->created_at)->format('d-m-Y');
}
]);
$this->addColumn([
'index' => 'base_grand_total',
'label' => trans('admin::app.datagrid.grand-total'),
@ -55,12 +68,22 @@ class OrderInvoicesDataGrid extends DataGrid
]);
$this->addColumn([
'index' => 'created_at',
'label' => trans('admin::app.datagrid.invoice-date'),
'type' => 'datetime',
'index' => 'state',
'label' => trans('admin::app.datagrid.state'),
'type' => 'string',
'closure' => true,
'searchable' => true,
'sortable' => true,
'filterable' => true,
'wrapper' => function ($value) {
if ($value->state == 'paid') {
return '<span class="badge badge-md badge-success">'. trans('admin::app.sales.orders.invoice-status-paid') .'</span>';
} elseif ($value->state == "pending") {
return '<span class="badge badge-md badge-warning">'. trans('admin::app.sales.orders.invoice-status-pending') .'</span>';
} elseif ($value->state == "overdue") {
return '<span class="badge badge-md badge-danger">'. trans('admin::app.sales.orders.invoice-status-overdue') . '</span>';
}
}
]);
}

View File

@ -17,6 +17,12 @@ class ProductDataGrid extends DataGrid
protected $channel = 'all';
/** @var string[] contains the keys for which extra filters to render */
protected $extraFilters = [
'channels',
'locales',
];
public function __construct()
{
parent::__construct();
@ -44,15 +50,11 @@ class ProductDataGrid extends DataGrid
);
if ($this->locale !== 'all') {
$queryBuilder->where('locale', $this->locale);
$queryBuilder->where('product_flat.locale', $this->locale);
}
if ($this->channel !== 'all') {
$queryBuilder->where('channel', $this->channel);
}
if ($currentLocale = app()->getLocale()) {
$queryBuilder->where('product_flat.locale', $currentLocale);
$queryBuilder->where('product_flat.channel', $this->channel);
}
$queryBuilder->groupBy('product_flat.product_id');

View File

@ -15,6 +15,12 @@ class SliderDataGrid extends DataGrid
protected $channel = 'all';
/** @var string[] contains the keys for which extra filters to render */
protected $extraFilters = [
'channels',
'locales',
];
public function __construct()
{
parent::__construct();

View File

@ -64,12 +64,12 @@ class CustomerController extends Controller
CustomerGroupRepository $customerGroupRepository,
ChannelRepository $channelRepository
)
{
$this->_config = request('_config');
$this->middleware('admin');
$this->customerRepository = $customerRepository;
$this->customerAddressRepository = $customerAddressRepository;
$this->customerGroupRepository = $customerGroupRepository;
$this->channelRepository = $channelRepository;
@ -200,12 +200,19 @@ class CustomerController extends Controller
$customer = $this->customerRepository->findorFail($id);
try {
$this->customerRepository->delete($id);
if (! $this->customerRepository->checkIfCustomerHasOrderPendingOrProcessing($customer)) {
$this->customerRepository->delete($id);
} else {
return response()->json(['message' => false], 400);
}
session()->flash('success', trans('admin::app.response.delete-success', ['name' => 'Customer']));
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Customer']));
}
@ -279,12 +286,18 @@ class CustomerController extends Controller
{
$customerIds = explode(',', request()->input('indexes'));
foreach ($customerIds as $customerId) {
$this->customerRepository->deleteWhere(['id' => $customerId]);
if (!$this->customerRepository->checkBulkCustomerIfTheyHaveOrderPendingOrProcessing($customerIds)) {
foreach ($customerIds as $customerId) {
$this->customerRepository->deleteWhere(['id' => $customerId]);
}
session()->flash('success', trans('admin::app.customers.customers.mass-destroy-success'));
return redirect()->back();
}
session()->flash('success', trans('admin::app.customers.customers.mass-destroy-success'));
session()->flash('error', trans('admin::app.response.order-pending', ['name' => 'Customers']));
return redirect()->back();
}
}

View File

@ -241,6 +241,8 @@ class DashboardController extends Controller
->addSelect('id', 'customer_id', 'customer_email', 'customer_first_name', 'customer_last_name')
->where('orders.created_at', '>=', $this->startDate)
->where('orders.created_at', '<=', $this->endDate)
->where('orders.status', '<>', 'closed')
->where('orders.status', '<>', 'canceled')
->groupBy('customer_email')
->orderBy('total_base_grand_total', 'DESC')
->limit(5)

View File

@ -2,9 +2,12 @@
namespace Webkul\Admin\Http\Controllers\Sales;
use Illuminate\Http\Request;
use Webkul\Admin\Http\Controllers\Controller;
use Webkul\Sales\Repositories\OrderRepository;
use Webkul\Sales\Repositories\InvoiceRepository;
use PDF;
class InvoiceController extends Controller
@ -97,7 +100,7 @@ class InvoiceController extends Controller
$data = request()->all();
$haveProductToInvoice = false;
foreach ($data['invoice']['items'] as $itemId => $qty) {
if ($qty) {
$haveProductToInvoice = true;
@ -145,4 +148,29 @@ class InvoiceController extends Controller
return $pdf->download('invoice-' . $invoice->created_at->format('d-m-Y') . '.pdf');
}
/**
* Update the invoice state.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function updateState($id, Request $request)
{
$invoice = $this->invoiceRepository->findOrFail($id);
$task = $this->invoiceRepository->updateInvoiceState($invoice, $request->state);
if($request->state == 'paid'){
$order = $this->orderRepository->findOrFail($invoice->order->id);
$this->orderRepository->updateOrderStatus($order);
}
if ($task){
session()->flash('success', trans('admin::app.sales.orders.invoice-status-confirmed'));
} else {
session()->flash('success', trans('admin::app.sales.orders.invoice-status-error'));
}
return back();
}
}

View File

@ -3,10 +3,30 @@
namespace Webkul\Admin\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Factory as ValidationFactory;
class ConfigurationForm extends FormRequest
{
/*
Added custom validator.
*/
public function __construct(ValidationFactory $validationFactory)
{
/* added custom comma seperated integer validator */
$validationFactory->extend(
'comma_seperated_integer',
function ($attribute, $value, $parameters) {
$pages = explode(',', $value);
foreach($pages as $page){
if (! is_numeric($page)) {
return false;
}
}
return true;
}
);
}
/**
* Determine if the Configuraion is authorized to make this request.
*
@ -26,12 +46,28 @@ class ConfigurationForm extends FormRequest
{
$this->rules = [];
if (request()->has('catalog.products.storefront.products_per_page')
&& ! empty(request()->input('catalog.products.storefront.products_per_page'))
) {
$this->rules = [
'catalog.products.storefront.products_per_page' => 'comma_seperated_integer',
];
}
if (request()->has('general.design.admin_logo.logo_image')
&& ! request()->input('general.design.admin_logo.logo_image.delete')
) {
$this->rules = [
'general.design.admin_logo.logo_image' => 'required|mimes:jpeg,bmp,png,jpg',
];
$this->rules = array_merge($this->rules, [
'general.design.admin_logo.logo_image' => 'required|mimes:jpeg,bmp,png,jpg|max:5000',
]);
}
if (request()->has('general.design.admin_logo.favicon')
&& ! request()->input('general.design.admin_logo.favicon.delete')
) {
$this->rules = array_merge($this->rules, [
'general.design.admin_logo.favicon' => 'required|mimes:jpeg,bmp,png,jpg|max:5000',
]);
}
return $this->rules;
@ -46,6 +82,18 @@ class ConfigurationForm extends FormRequest
{
return [
'general.design.admin_logo.logo_image.mimes' => 'Invalid file format. Use only jpeg, bmp, png, jpg.',
'catalog.products.storefront.products_per_page.comma_seperated_integer' => 'The "Product Per Page" field must be numeric and may contain comma.'
];
}
}
/**
* Set the attribute name.
*/
public function attributes()
{
return [
'general.design.admin_logo.logo_image' => 'Logo Image',
'general.design.admin_logo.favicon' => 'Favicon Image'
];
}
}

View File

@ -1,7 +1,7 @@
<?php
Route::group(['middleware' => ['web']], function () {
Route::prefix('admin')->group(function () {
Route::prefix(config('app.admin_url'))->group(function () {
Route::get('/', 'Webkul\Admin\Http\Controllers\Controller@redirectToLogin');
@ -211,6 +211,10 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'admin::sales.invoices.print',
])->name('admin.sales.invoices.print');
Route::post('/invoices/update/state/{order_id}', 'Webkul\Admin\Http\Controllers\Sales\InvoiceController@updateState')->defaults('_config', [
'redirect' => 'admin.sales.orders.view',
])->name('admin.sales.invoices.update.state');
// Sales Shipments Routes
Route::get('/shipments', 'Webkul\Admin\Http\Controllers\Sales\ShipmentController@index')->defaults('_config', [
@ -673,7 +677,7 @@ Route::group(['middleware' => ['web']], function () {
//tax rate ends
//DataGrid Export
Route::post('admin/export', 'Webkul\Admin\Http\Controllers\ExportController@export')->name('admin.datagrid.export');
Route::post(config('app.admin_url') . '/export', 'Webkul\Admin\Http\Controllers\ExportController@export')->name('admin.datagrid.export');
Route::prefix('promotions')->group(function () {
Route::get('cart-rules', 'Webkul\CartRule\Http\Controllers\CartRuleController@index')->defaults('_config', [

View File

@ -3,14 +3,15 @@
namespace Webkul\Admin\Listeners;
use Illuminate\Support\Facades\Mail;
use Webkul\Admin\Mail\NewOrderNotification;
use Webkul\Admin\Mail\NewAdminNotification;
use Webkul\Admin\Mail\NewInvoiceNotification;
use Webkul\Admin\Mail\NewShipmentNotification;
use Webkul\Admin\Mail\NewInventorySourceNotification;
use Webkul\Admin\Mail\CancelOrderNotification;
use Webkul\Admin\Mail\NewOrderNotification;
use Webkul\Admin\Mail\NewRefundNotification;
use Webkul\Admin\Mail\NewInvoiceNotification;
use Webkul\Admin\Mail\CancelOrderNotification;
use Webkul\Admin\Mail\NewShipmentNotification;
use Webkul\Admin\Mail\OrderCommentNotification;
use Webkul\Admin\Mail\CancelOrderAdminNotification;
use Webkul\Admin\Mail\NewInventorySourceNotification;
class Order
{
@ -117,10 +118,18 @@ class Order
public function sendCancelOrderMail($order)
{
try {
/* email to customer */
$configKey = 'emails.general.notifications.emails.general.notifications.cancel-order';
if (core()->getConfigData($configKey)) {
Mail::queue(new CancelOrderNotification($order));
}
/* email to admin */
$configKey = 'emails.general.notifications.emails.general.notifications.new-admin';
if (core()->getConfigData($configKey)) {
app()->setLocale(env('APP_LOCALE'));
Mail::queue(new CancelOrderAdminNotification($order));
}
} catch (\Exception $e) {
report($e);
}

View File

@ -0,0 +1,31 @@
<?php
namespace Webkul\Admin\Listeners;
use Illuminate\Support\Facades\Mail;
use Webkul\User\Notifications\AdminUpdatePassword;
use Webkul\Customer\Notifications\CustomerUpdatePassword;
class PasswordChange
{
/**
* Send mail on updating password.
*
* @param \Webkul\Customer\Models\Customer|\Webkul\User\Models\Admin $adminOrCustomer
* @return void
*/
public function sendUpdatePasswordMail($adminOrCustomer)
{
try {
if ($adminOrCustomer instanceof \Webkul\Customer\Models\Customer) {
Mail::queue(new CustomerUpdatePassword($adminOrCustomer));
}
if ($adminOrCustomer instanceof \Webkul\User\Models\Admin) {
Mail::queue(new AdminUpdatePassword($adminOrCustomer));
}
} catch (\Exception $e) {
report($e);
}
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Webkul\Admin\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class CancelOrderAdminNotification extends Mailable
{
use Queueable, SerializesModels;
/**
* @var \Webkul\Sales\Contracts\Order
*/
public $order;
/**
* @param \Webkul\Sales\Contracts\Order $order
* @return void
*/
public function __construct($order)
{
$this->order = $order;
}
public function build()
{
return $this->from(core()->getSenderEmailDetails()['email'], core()->getSenderEmailDetails()['name'])
->to(core()->getAdminEmailDetails()['email'])
->subject(trans('shop::app.mail.order.cancel.subject'))
->view('shop::emails.sales.order-cancel-admin');
}
}

View File

@ -38,7 +38,7 @@ class OrderCommentNotification extends Mailable
{
return $this->from(core()->getSenderEmailDetails()['email'], core()->getSenderEmailDetails()['name'])
->to($this->comment->order->customer_email, $this->comment->order->customer_full_name)
->subject(trans('shop::app.mail.order.comment.subject'))
->subject(trans('shop::app.mail.order.comment.subject', ['order_id' => $this->comment->order->increment_id]))
->view('shop::emails.sales.new-order-comment');
}
}

View File

@ -14,6 +14,8 @@ class EventServiceProvider extends ServiceProvider
*/
public function boot()
{
Event::listen('user.admin.update-password', 'Webkul\Admin\Listeners\PasswordChange@sendUpdatePasswordMail');
Event::listen('checkout.order.save.after', 'Webkul\Admin\Listeners\Order@sendNewOrderMail');
Event::listen('sales.invoice.save.after', 'Webkul\Admin\Listeners\Order@sendNewInvoiceMail');

View File

@ -320,6 +320,14 @@ return array (
'invoice-btn-title' => 'Rechnung',
'info' => 'Informationen',
'invoices' => 'Rechnungen',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Sendungen',
'order-and-account' => 'Bestellung und Rechnung',
'order-info' => 'Bestellinformationen',

View File

@ -319,6 +319,14 @@ return [
'invoice-btn-title' => 'Invoice',
'info' => 'Information',
'invoices' => 'Invoices',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Shipments',
'order-and-account' => 'Order and Account',
'order-info' => 'Order Information',
@ -1219,7 +1227,7 @@ return [
'cancel-success' => ':name canceled successfully.',
'cancel-error' => ':name can not be canceled.',
'already-taken' => 'The :name has already been taken.',
'order-pending' => 'Cannot delete account because some Order(s) are pending or processing state.'
'order-pending' => 'Cannot delete :name account because some Order(s) are pending or processing state.'
],
'footer' => [

View File

@ -318,6 +318,14 @@ return [
'invoice-btn-title' => 'صورت حساب',
'info' => 'اطلاعات',
'invoices' => 'صورت حساب ها',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'حمل و نقل ها',
'order-and-account' => 'سفارش و حساب',
'order-info' => 'اطلاعات سفارش',

View File

@ -318,6 +318,14 @@ return [
'invoice-btn-title' => 'Fattura',
'info' => 'Informazoni',
'invoices' => 'Fatture',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Spedizioni',
'order-and-account' => 'Ordine e Account',
'order-info' => 'informazioni Ordine',

View File

@ -318,6 +318,14 @@ return [
'invoice-btn-title' => 'Factuur',
'info' => 'Informatie',
'invoices' => 'Facturen',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Verzendingen',
'order-and-account' => 'Order and Account',
'order-info' => 'Order Information',

View File

@ -317,6 +317,14 @@ return [
'invoice-btn-title' => 'Faktura',
'info' => 'Informacje',
'invoices' => 'Faktury',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Przesyłki',
'order-and-account' => 'Zamówienie i konto',
'order-info' => 'Informacje o zamówieniu',

View File

@ -318,6 +318,14 @@ return [
'invoice-btn-title' => 'Faturar',
'info' => 'Informação',
'invoices' => 'Faturas',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Envios',
'order-and-account' => 'Pedido e Conta',
'order-info' => 'Informação do Pedido',

View File

@ -316,6 +316,14 @@ return [
'invoice-btn-title' => 'Fatura',
'info' => 'Bilgi',
'invoices' => 'Faturalar',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Kargo',
'order-and-account' => 'Sipariş ve Hesap',
'order-info' => 'Sipariş Bilgisi',

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.catalog.attributes.add-title') }}
</h1>
@ -296,7 +296,10 @@
</td>
<td v-if="show_swatch && swatch_type == 'image'">
<input type="file" accept="image/*" :name="'options[' + row.id + '][swatch_value]'"/>
<div class="control-group" :class="[errors.has('options[' + row.id + '][swatch_value]') ? 'has-error' : '']">
<input type="file" v-validate="'size:600'" accept="image/*" :name="'options[' + row.id + '][swatch_value]'"/>
<span class="control-error" v-if="errors.has('options[' + row.id + '][swatch_value]')">The image size must be less than 600 KB</span>
</div>
</td>
<td>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.catalog.attributes.edit-title') }}
</h1>
@ -365,8 +365,11 @@
</td>
<td style="white-space: nowrap;" v-if="show_swatch && swatch_type == 'image'">
<img style="width: 36px;height: 36px;vertical-align: middle;background: #F2F2F2;border-radius: 2px;margin-right: 10px;" v-if="row.swatch_value_url" :src="row.swatch_value_url"/>
<input type="file" accept="image/*" :name="'options[' + row.id + '][swatch_value]'"/>
<div class="control-group" :class="[errors.has('options[' + row.id + '][swatch_value]') ? 'has-error' : '']">
<img style="width: 36px;height: 36px;vertical-align: middle;background: #F2F2F2;border-radius: 2px;margin-right: 10px;" v-if="row.swatch_value_url" :src="row.swatch_value_url"/>
<input type="file" v-validate="'size:600'" accept="image/*" :name="'options[' + row.id + '][swatch_value]'"/>
<span class="control-error" v-if="errors.has('options[' + row.id + '][swatch_value]')">The image size must be less than 600 KB</span>
</div>
</td>
<td>
@ -418,7 +421,7 @@
optionRowCount: 0,
optionRows: [],
show_swatch: "{{ $attribute->type == 'select' ? true : false }}",
swatch_type: "{{ $attribute->swatch_type }}",
swatch_type: "{{ $attribute->swatch_type == '' ? 'dropdown' : $attribute->swatch_type }}",
isNullOptionChecked: false,
idNullOption: null
}

View File

@ -12,7 +12,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.catalog.categories.add-title') }}
</h1>

View File

@ -13,7 +13,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.catalog.categories.edit-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.catalog.families.add-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.catalog.families.edit-title') }}
</h1>

View File

@ -26,7 +26,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.catalog.products.add-title') }}
</h1>

View File

@ -18,7 +18,7 @@
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link"
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.catalog.products.edit-title') }}
</h1>

View File

@ -11,39 +11,6 @@
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.catalog.products.title') }}</h1>
<div class="control-group">
<select class="control" id="channel-switcher" name="channel" onchange="reloadPage('channel', this.value)" >
<option value="all" {{ ! isset($channel) ? 'selected' : '' }}>
{{ __('admin::app.admin.system.all-channels') }}
</option>
@foreach (core()->getAllChannels() as $channelModel)
<option
value="{{ $channelModel->code }}" {{ (isset($channel) && ($channelModel->code) == $channel) ? 'selected' : '' }}>
{{ $channelModel->name }}
</option>
@endforeach
</select>
</div>
<div class="control-group">
<select class="control" id="locale-switcher" name="locale" onchange="reloadPage('locale', this.value)" >
<option value="all" {{ ! isset($locale) ? 'selected' : '' }}>
{{ __('admin::app.admin.system.all-locales') }}
</option>
@foreach (core()->getAllLocales() as $localeModel)
<option
value="{{ $localeModel->code }}" {{ (isset($locale) && ($localeModel->code) == $locale) ? 'selected' : '' }}>
{{ $localeModel->name }}
</option>
@endforeach
</select>
</div>
</div>
<div class="page-action">

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.cms.pages.add-title') }}
</h1>

View File

@ -13,7 +13,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.cms.pages.edit-title') }}
</h1>

View File

@ -14,7 +14,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.customers.addresses.create-title') }}
</h1>

View File

@ -10,7 +10,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('address::app.admin.addresses.title-orders', ['customer_name' => $customer->first_name . ' ' . $customer->last_name]) }}
</h1>

View File

@ -9,7 +9,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.users.users.confirm-delete-title') }}
</h1>
</div>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.customers.customers.title') }}

View File

@ -9,7 +9,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ $customer->first_name . " " . $customer->last_name }}
</h1>
</div>
@ -25,11 +25,11 @@
<tab name="{{ __('admin::app.customers.customers.addresses') }}" :selected="false">
<div class="style:overflow: auto;">&nbsp;</div>
{!! view_render_event('bagisto.admin.customer.addresses.list.before') !!}
{!! view_render_event('bagisto.admin.customer.addresses.list.before') !!}
{!! app('Webkul\Admin\DataGrids\AddressDataGrid')->render() !!}
{!! view_render_event('bagisto.admin.customer.addresses.list.after') !!}
</div>
</tab>
</tab>
{!! view_render_event('bagisto.admin.customer.edit.after', ['customer' => $customer]) !!}
</tabs>
</div>

View File

@ -11,8 +11,8 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.customers.groups.add-title') }}
</h1>
</div>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.customers.groups.edit-title') }}
</h1>

View File

@ -10,7 +10,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.customers.note.title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.customers.reviews.edit-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.customers.subscribers.title-edit') }}
</h1>

View File

@ -22,7 +22,7 @@
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link"
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.promotions.cart-rules.add-title') }}
</h1>

View File

@ -27,7 +27,7 @@
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link"
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.promotions.cart-rules.edit-title') }}
</h1>

View File

@ -14,38 +14,6 @@
</div>
<div class="page-action">
<div class="control-group">
<select class="control" id="channel-switcher" name="channel" onchange="reloadPage('channel', this.value)" >
<option value="all" {{ ! isset($channel) ? 'selected' : '' }}>
{{ __('admin::app.admin.system.all-channels') }}
</option>
@foreach (core()->getAllChannels() as $channelModel)
<option
value="{{ $channelModel->id }}" {{ (isset($channel) && ($channelModel->id) == $channel) ? 'selected' : '' }}>
{{ $channelModel->name }}
</option>
@endforeach
</select>
</div>
<div class="control-group">
<select class="control" id="customer-group-switcher" name="customer_group" onchange="reloadPage('customer_group', this.value)" >
<option value="all" {{ ! isset($locale) ? 'selected' : '' }}>
{{ __('admin::app.admin.system.all-customer-groups') }}
</option>
@foreach (core()->getAllCustomerGroups() as $customerGroupModel)
<option
value="{{ $customerGroupModel->id }}" {{ (isset($customerGroupModel) && ($customerGroupModel->id) == $customer_group) ? 'selected' : '' }}>
{{ $customerGroupModel->name }}
</option>
@endforeach
</select>
</div>
<a href="{{ route('admin.cart-rules.create') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.promotions.cart-rules.add-title') }}
</a>

View File

@ -22,7 +22,7 @@
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link"
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.promotions.catalog-rules.add-title') }}
</h1>
@ -57,7 +57,7 @@
<div class="control-group">
<label for="status">{{ __('admin::app.promotions.catalog-rules.status') }}</label>
<label class="switch">
<input type="checkbox" id="status" name="status" value="1" {{ old('status') ? 'checked' : '' }}>
<span class="slider round"></span>
@ -346,7 +346,7 @@
attribute_type_indexes: {
'product': 0
},
},
condition_operators: {
'price': [{

View File

@ -22,7 +22,7 @@
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link"
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.promotions.catalog-rules.edit-title') }}
</h1>
@ -57,7 +57,7 @@
<div class="control-group">
<label for="status">{{ __('admin::app.promotions.catalog-rules.status') }}</label>
<label class="switch">
<input type="checkbox" id="status" name="status" value="{{ $catalogRule->status }}" {{ $catalogRule->status ? 'checked' : '' }}>
<span class="slider round"></span>

View File

@ -12,7 +12,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.sales.invoices.add-title') }}
</h1>
@ -181,21 +181,21 @@
<div class="section-content">
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.shipping-method') }}
</span>
<span class="value">
<span class="value">
{{ $order->shipping_title }}
</span>
</div>
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.shipping-price') }}
</span>
<span class="value">
<span class="value">
{{ core()->formatBasePrice($order->base_shipping_amount) }}
</span>
</div>
@ -230,7 +230,7 @@
@if (isset($item->additional['attributes']))
<div class="item-options">
@foreach ($item->additional['attributes'] as $attribute)
<b>{{ $attribute['attribute_name'] }} : </b>{{ $attribute['option_label'] }}</br>
@endforeach

View File

@ -13,10 +13,7 @@
<div class="page-action">
<div class="export-import" @click="showModal('downloadDataGrid')">
<i class="export-icon"></i>
<span>
{{ __('admin::app.export.export') }}
</span>
<i class="export-icon"></i> <span>{{ __('admin::app.export.export') }}</span>
</div>
</div>
</div>

View File

@ -1,10 +1,10 @@
@extends('admin::layouts.master')
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.sales.invoices.view-title', ['invoice_id' => $invoice->id]) }}
@stop
@section('content-wrapper')
@section('content')
<?php $order = $invoice->order; ?>
@ -14,12 +14,19 @@
<h1>
{!! view_render_event('sales.invoice.title.before', ['order' => $order]) !!}
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.sales.invoices.view-title', ['invoice_id' => $invoice->id]) }}
{!! view_render_event('sales.invoice.title.after', ['order' => $order]) !!}
</h1>
@if($invoice->state == 'paid')
<small><span class="badge badge-md badge-success">{{ __('admin::app.sales.orders.invoice-status-paid') }}</span></small>
@elseif($invoice->state == 'pending')
<span class="badge badge-md badge-warning">{{ __('admin::app.sales.orders.invoice-status-pending') }}</span>
@else
<span class="badge badge-md badge-danger">{{ __('admin::app.sales.orders.invoice-status-overdue') }}</span>
@endif
</div>
<div class="page-action">
@ -29,6 +36,10 @@
{{ __('admin::app.sales.invoices.print') }}
</a>
@if($invoice->state == "pending" || $invoice->state == "overdue")
<a href="#" id="ChangeStatus" class="btn btn-lg btn-primary" @click="showModal('changeInvoiceState')">{{ __('admin::app.sales.orders.invoices-change-title') }}</a>
@endif
{!! view_render_event('sales.invoice.page_action.after', ['order' => $order]) !!}
</div>
</div>
@ -37,7 +48,7 @@
<div class="sale-container">
<accordian :title="'{{ __('admin::app.sales.orders.order-and-account') }}'" :active="true">
<div slot="body">
<div slot="body" style="display: flex; overflow:auto;">
<div class="sale-section">
<div class="secton-title">
@ -46,10 +57,7 @@
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.invoices.order-id') }}
</span>
<span class="title">{{ __('admin::app.sales.invoices.order-id') }}</span>
<span class="value">
<a href="{{ route('admin.sales.orders.view', $order->id) }}">#{{ $order->increment_id }}</a>
</span>
@ -58,69 +66,55 @@
{!! view_render_event('sales.invoice.increment_id.after', ['order' => $order]) !!}
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.order-date') }}
</span>
<span class="value">
{{ $order->created_at }}
</span>
<span class="title">{{ __('admin::app.sales.orders.order-date') }}</span>
<span class="value">{{ $order->created_at }}</span>
</div>
{!! view_render_event('sales.invoice.created_at.after', ['order' => $order]) !!}
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.order-status') }}
</span>
<span class="value">
{{ $order->status_label }}
</span>
<span class="title">{{ __('admin::app.sales.orders.order-status') }}</span>
<span class="value">{{ $order->status_label }}</span>
</div>
{!! view_render_event('sales.invoice.status_label.after', ['order' => $order]) !!}
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.channel') }}
</span>
<span class="value">
{{ $order->channel_name }}
</span>
<span class="title">{{ __('admin::app.sales.orders.channel') }}</span>
<span class="value">{{ $order->channel_name }}</span>
</div>
{!! view_render_event('sales.invoice.channel_name.after', ['order' => $order]) !!}
<div class="row">
<span class="title">{{ __('admin::app.sales.orders.payment-method') }}</span>
<span class="value">{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}</span>
</div>
<div class="row">
<span class="title">{{ __('admin::app.sales.orders.shipping-method') }}</span>
<span class="value">{{ $order->shipping_title }}</span>
</div>
{!! view_render_event('sales.invoice.shipping-method.after', ['order' => $order]) !!}
</div>
</div>
<div class="sale-section">
<div class="sale-section" style="margin: 0 0 0 300px;">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.account-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.customer-name') }}
</span>
<span class="value">
{{ $invoice->address->name }}
</span>
<span class="title">{{ __('admin::app.sales.orders.customer-name') }}</span>
<span class="value">{{ $invoice->address->name }}</span>
</div>
{!! view_render_event('sales.invoice.customer_name.after', ['order' => $order]) !!}
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.email') }}
</span>
<span class="value">
{{ $invoice->address->email }}
</span>
<span class="title">{{ __('admin::app.sales.orders.email') }}</span>
<span class="value">{{ $invoice->address->email }}</span>
</div>
{!! view_render_event('sales.invoice.customer_email.after', ['order' => $order]) !!}
@ -131,14 +125,14 @@
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
<div slot="body" style="display: flex; overflow:auto;">
<div class="sale-section">
<div class="secton-title">
<div class="secton-title" style="width: 380px;">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
<div class="section-content">
<div class="section-content" style="width: 380px;">
@include ('admin::sales.address', ['address' => $order->billing_address])
{!! view_render_event('sales.invoice.billing_address.after', ['order' => $order]) !!}
@ -146,86 +140,18 @@
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<div class="sale-section" style="margin: 0 0 0 300px;">
<div class="secton-title" style="width: 400px;">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
<div class="section-content" style="width: 400px;">
@include ('admin::sales.address', ['address' => $order->shipping_address])
{!! view_render_event('sales.invoice.shipping_address.after', ['order' => $order]) !!}
</div>
</div>
@endif
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.payment-and-shipping') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.payment-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.payment-method') }}
</span>
<span class="value">
{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.currency') }}
</span>
<span class="value">
{{ $order->order_currency_code }}
</span>
</div>
{!! view_render_event('sales.invoice.payment-method.after', ['order' => $order]) !!}
</div>
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.shipping-method') }}
</span>
<span class="value">
{{ $order->shipping_title }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.shipping-price') }}
</span>
<span class="value">
{{ core()->formatBasePrice($order->base_shipping_amount) }}
</span>
</div>
{!! view_render_event('sales.invoice.shipping-method.after', ['order' => $order]) !!}
</div>
</div>
@endif
</div>
</accordian>
@ -254,9 +180,7 @@
@foreach ($invoice->items as $item)
<tr>
<td>{{ $item->getTypeInstance()->getOrderedItem($item)->sku }}</td>
<td>
{{ $item->name }}
<td>{{ $item->name }}
@if (isset($item->additional['attributes']))
<div class="item-options">
@ -264,19 +188,14 @@
@foreach ($item->additional['attributes'] as $attribute)
<b>{{ $attribute['attribute_name'] }} : </b>{{ $attribute['option_label'] }}</br>
@endforeach
</div>
@endif
</td>
<td>{{ core()->formatBasePrice($item->base_price) }}</td>
<td>{{ $item->qty }}</td>
<td>{{ core()->formatBasePrice($item->base_total) }}</td>
<td>{{ core()->formatBasePrice($item->base_tax_amount) }}</td>
@if ($invoice->base_discount_amount > 0)
<td>{{ core()->formatBasePrice($item->base_discount_amount) }}</td>
@endif
@ -284,7 +203,6 @@
<td>{{ core()->formatBasePrice($item->base_total + $item->base_tax_amount - $item->base_discount_amount) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@ -322,12 +240,61 @@
<td>{{ core()->formatBasePrice($invoice->base_grand_total) }}</td>
</tr>
</table>
</div>
</accordian>
</div>
</div>
</div>
@stop
</div>
<modal id="changeInvoiceState" :is-open="modalIds.changeInvoiceState">
<h3 slot="header">{{ __('admin::app.sales.orders.invoices-change-title') }}</h3>
<div slot="body">
<option-wrapper></option-wrapper>
</div>
</modal>
@stop
@push('scripts')
<script type="text/x-template" id="options-template">
<form method="POST" action="{{ route('admin.sales.invoices.update.state', $invoice->id) }}">
<div class="page-content">
<p>Please select the new invoice state:</p>
<div class="form-container">
@csrf()
<div>
<input type="radio" name="state" id="paid" value="paid">
<label for="paid">{{ __('admin::app.sales.orders.invoice-status-paid') }}</label>
</div>
<div>
<input type="radio" name="state" id="pending" value="pending" @if($invoice->state == "pending") checked @endif>
<label for="pending">{{ __('admin::app.sales.orders.invoice-status-pending') }}</label>
</div>
<div>
<input type="radio" name="state" id="overdue" value="overdue" @if($invoice->state == "overdue") checked @endif>
<label for="overdue">{{ __('admin::app.sales.orders.invoice-status-overdue') }}</label>
</div>
</div>
<br />
<button type="submit" class="btn btn-md btn-primary">{{ __('admin::app.sales.orders.invoice-status-update')}}</button>
</div>
</form>
</script>
<script>
Vue.component('option-wrapper', {
template: '#options-template',
methods: {
onSubmit: function(e) {
// e.target.submit();
}
}
});
</script>
@endpush

View File

@ -14,7 +14,7 @@
<h1>
{!! view_render_event('sales.order.title.before', ['order' => $order]) !!}
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.sales.orders.view-title', ['order_id' => $order->increment_id]) }}
@ -157,37 +157,41 @@
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
@if ($order->billing_address || $order->shipping_address)
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
@if($order->billing_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
{!! view_render_event('sales.order.billing_address.after', ['order' => $order]) !!}
</div>
</div>
@endif
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
{!! view_render_event('sales.order.shipping_address.after', ['order' => $order]) !!}
</div>
</div>
@endif
{!! view_render_event('sales.order.billing_address.after', ['order' => $order]) !!}
</div>
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
{!! view_render_event('sales.order.shipping_address.after', ['order' => $order]) !!}
</div>
</div>
@endif
</div>
</accordian>
</accordian>
@endif
<accordian :title="'{{ __('admin::app.sales.orders.payment-and-shipping') }}'" :active="true">
<div slot="body">
@ -470,7 +474,15 @@
<td>{{ $invoice->created_at }}</td>
<td>#{{ $invoice->order->increment_id }}</td>
<td>{{ $invoice->address->name }}</td>
<td>{{ $invoice->status_label }}</td>
<td>
@if($invoice->state == "paid")
{{ __('admin::app.sales.orders.invoice-status-paid') }}
@elseif($invoice->state == "overdue")
{{ __('admin::app.sales.orders.invoice-status-overdue') }}
@else
{{ __('admin::app.sales.orders.invoice-status-pending') }}
@endif
</td>
<td>{{ core()->formatBasePrice($invoice->base_grand_total) }}</td>
<td class="action">
<a href="{{ route('admin.sales.invoices.view', $invoice->id) }}">

View File

@ -12,7 +12,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.sales.refunds.add-title') }}
</h1>

View File

@ -12,7 +12,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.sales.refunds.view-title', ['refund_id' => $refund->id]) }}
</h1>
@ -107,37 +107,41 @@
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
@if ($order->billing_address || $order->shipping_address)
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
@if ($order->billing_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
<div class="section-content">
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
@include ('admin::sales.address', ['address' => $order->billing_address])
</div>
</div>
@endif
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
</div>
</div>
@endif
</div>
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
</div>
</div>
@endif
</div>
</accordian>
</accordian>
@endif
<accordian :title="'{{ __('admin::app.sales.orders.payment-and-shipping') }}'" :active="true">
<div slot="body">
@ -229,7 +233,7 @@
@if (isset($item->additional['attributes']))
<div class="item-options">
@foreach ($item->additional['attributes'] as $attribute)
<b>{{ $attribute['attribute_name'] }} : </b>{{ $attribute['option_label'] }}</br>
@endforeach

View File

@ -12,7 +12,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.sales.shipments.add-title') }}
</h1>
@ -274,7 +274,7 @@
@if (isset($item->additional['attributes']))
<div class="item-options">
@foreach ($item->additional['attributes'] as $attribute)
<b>{{ $attribute['attribute_name'] }} : </b>{{ $attribute['option_label'] }}</br>
@endforeach
@ -321,7 +321,7 @@
<div class="control-group" :class="[errors.has('{{ $inputName }}') ? 'has-error' : '']">
<input type="text" v-validate="'required|numeric|min_value:0|max_value:{{$sourceQty}}'" class="control" id="{{ $inputName }}" name="{{ $inputName }}" value="{{ $item->qty_invoiced }}" data-vv-as="&quot;{{ __('admin::app.sales.shipments.qty-to-ship') }}&quot;" :disabled="source != '{{ $inventorySource->id }}'"/>
<span class="control-error" v-if="errors.has('{{ $inputName }}')">
@verbatim
{{ errors.first('<?php echo $inputName; ?>') }}

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.sales.shipments.view-title', ['shipment_id' => $shipment->id]) }}
</h1>
@ -254,7 +254,7 @@
@if (isset($item->additional['attributes']))
<div class="item-options">
@foreach ($item->additional['attributes'] as $attribute)
<b>{{ $attribute['attribute_name'] }} : </b>{{ $attribute['option_label'] }}</br>
@endforeach

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.channels.add-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.channels.edit-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.currencies.add-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.currencies.edit-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.exchange_rates.add-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.exchange_rates.edit-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.inventory_sources.add-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.inventory_sources.edit-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.locales.add-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.locales.edit-title') }}
</h1>

View File

@ -15,7 +15,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.sliders.add-title') }}
</h1>

View File

@ -12,7 +12,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.sliders.edit-title') }}

View File

@ -14,41 +14,6 @@
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.settings.sliders.title') }}</h1>
<div class="control-group">
<select class="control" id="channel-switcher" name="channel" onchange="reloadPage('channel', this.value)" >
<option value="all" {{ ! isset($channel) ? 'selected' : '' }}>
{{ __('admin::app.admin.system.all-channels') }}
</option>
@foreach (core()->getAllChannels() as $channelModel)
<option
value="{{ $channelModel->code }}" {{ (isset($channel) && ($channelModel->code) == $channel) ? 'selected' : '' }}>
{{ $channelModel->name }}
</option>
@endforeach
</select>
</div>
<div class="control-group">
<select class="control" id="locale-switcher" name="locale" onchange="reloadPage('locale', this.value)" >
<option value="all" {{ ! isset($locale) ? 'selected' : '' }}>
{{ __('admin::app.admin.system.all-locales') }}
</option>
@foreach (core()->getAllLocales() as $localeModel)
<option
value="{{ $localeModel->code }}" {{ (isset($locale) && ($localeModel->code) == $locale) ? 'selected' : '' }}>
{{ $localeModel->name }}
</option>
@endforeach
</select>
</div>
</div>
<div class="page-action">

View File

@ -10,7 +10,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.tax-categories.add-title') }}
</h1>

View File

@ -10,7 +10,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.tax-categories.edit.title') }}
</h1>

View File

@ -10,7 +10,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.tax-rates.add-title') }}
</h1>

View File

@ -10,7 +10,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.settings.tax-rates.edit.title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.users.roles.add-role-title') }}
</h1>

View File

@ -11,7 +11,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.users.roles.edit-role-title') }}
</h1>

View File

@ -10,7 +10,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.users.users.add-user-title') }}
</h1>
@ -73,7 +73,7 @@
<div class="control-group">
<label for="status">{{ __('admin::app.users.users.status') }}</label>
<label class="switch">
<input type="checkbox" id="status" name="status" value="1" {{ old('status') ? 'checked' : '' }}>
<span class="slider round"></span>

View File

@ -10,7 +10,7 @@
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.users.users.edit-user-title') }}
</h1>
@ -74,7 +74,7 @@
<div class="control-group">
<label for="status">{{ __('admin::app.users.users.status') }}</label>
<label class="switch">
<input type="checkbox" id="status" name="status" value="{{ $user->status }}" {{ $user->status ? 'checked' : '' }}>
<span class="slider round"></span>

View File

@ -33,7 +33,7 @@ class AttributeOption extends TranslatableModel implements AttributeOptionContra
public function swatch_value_url()
{
if ($this->swatch_value && $this->attribute->swatch_type == 'image') {
return Storage::url($this->swatch_value);
return url('cache/small/'.$this->swatch_value);
}
return;

View File

@ -2,16 +2,14 @@
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Carbon\Carbon;
use Faker\Generator as Faker;
use Webkul\BookingProduct\Models\BookingProduct;
use Webkul\BookingProduct\Models\BookingProductEventTicket;
use Webkul\Product\Models\Product;
$factory->define(BookingProductEventTicket::class, function (Faker $faker, array $attributes) {
$factory->define(BookingProductEventTicket::class, static function (Faker $faker, array $attributes) {
return [
'price' => $faker->randomFloat(4, 3, 900),
'qty' => $faker->numberBetween(1, 99),
'qty' => $faker->numberBetween(100, 1000),
'booking_product_id' => static function () {
return factory(BookingProduct::class)->create(['type' => 'event'])->id;
}

View File

@ -2,6 +2,7 @@
namespace Webkul\BookingProduct\Repositories;
use Illuminate\Support\Facades\Event;
use Webkul\Core\Eloquent\Repository;
use Illuminate\Support\Str;
@ -18,12 +19,16 @@ class BookingProductEventTicketRepository extends Repository
}
/**
* @param array $data
* @param \Webkul\BookingProduct\Contracts\BookingProduct $bookingProduct
* @param array $data
* @param \Webkul\BookingProduct\Contracts\BookingProduct $bookingProduct
*
* @return void
* @throws \Prettus\Validator\Exceptions\ValidatorException
*/
public function saveEventTickets($data, $bookingProduct)
public function saveEventTickets($data, $bookingProduct): void
{
Event::dispatch('booking_product.booking.event-ticket.save.before', ['data' => $data, 'bookingProduct' => $bookingProduct]);
$previousTicketIds = $bookingProduct->event_tickets()->pluck('id');
if (isset($data['tickets'])) {
@ -54,7 +59,7 @@ class BookingProductEventTicketRepository extends Repository
}
if (Str::contains($ticketId, 'ticket_')) {
$this->create(array_merge([
$ticket = $this->create(array_merge([
'booking_product_id' => $bookingProduct->id,
], $ticketInputs));
} else {
@ -62,13 +67,18 @@ class BookingProductEventTicketRepository extends Repository
$previousTicketIds->forget($index);
}
$this->update($ticketInputs, $ticketId);
$ticket = $this->update($ticketInputs, $ticketId);
}
$savedTickets[$ticketId]['ticket'] = $ticket;
$savedTickets[$ticketId]['ticketInputs'] = $ticketInputs;
}
}
foreach ($previousTicketIds as $previousTicketId) {
$this->delete($previousTicketId);
}
Event::dispatch('booking_product.booking.event-ticket.save.after', ['tickets' => $savedTickets]);
}
}

View File

@ -177,10 +177,9 @@ class CartRule
if ($rule->coupon_type) {
if (strlen($cart->coupon_code)) {
/** @var \Webkul\CartRule\Models\CartRule $rule */
// Laravel relation is used instead of repository for performance
// reasons (cart_rule_coupon-relation is pre-loaded by self::getCartRuleQuery())
$coupon = $rule->cart_rule_coupon;
$coupon = $rule->cart_rule_coupon->where('code', $cart->coupon_code)->first();
if ($coupon && $coupon->code === $cart->coupon_code) {
if ($coupon->usage_limit && $coupon->times_used >= $coupon->usage_limit) {
@ -444,29 +443,34 @@ class CartRule
$cart = Cart::getCart();
foreach ($this->getCartRules() as $rule) {
if (! $this->canProcessRule($cart, $rule)) {
continue;
}
foreach ($cart->items->all() as $item) {
if (! $this->validator->validate($rule, $cart)) {
continue;
}
foreach ($this->getCartRules() as $rule) {
if (! $rule || ! $rule->free_shipping) {
continue;
}
if (! $this->canProcessRule($cart, $rule)) {
continue;
}
$selectedShipping->price = 0;
/* given CartItem instance to the validator */
if (! $this->validator->validate($rule, $item)) {
continue;
}
$selectedShipping->base_price = 0;
if (! $rule || ! $rule->free_shipping) {
continue;
}
$selectedShipping->save();
$selectedShipping->price = 0;
$appliedRuleIds[$rule->id] = $rule->id;
$selectedShipping->base_price = 0;
if ($rule->end_other_rules) {
break;
$selectedShipping->save();
$appliedRuleIds[$rule->id] = $rule->id;
if ($rule->end_other_rules) {
break;
}
}
}

View File

@ -3,20 +3,20 @@
namespace Webkul\Checkout;
use Exception;
use Illuminate\Support\Facades\Log;
use Webkul\Checkout\Models\Cart as CartModel;
use Webkul\Checkout\Models\CartAddress;
use Webkul\Checkout\Repositories\CartRepository;
use Webkul\Checkout\Repositories\CartItemRepository;
use Webkul\Checkout\Repositories\CartAddressRepository;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Tax\Helpers\Tax;
use Webkul\Tax\Repositories\TaxCategoryRepository;
use Webkul\Checkout\Models\CartPayment;
use Webkul\Customer\Repositories\WishlistRepository;
use Webkul\Customer\Repositories\CustomerAddressRepository;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Arr;
use Webkul\Tax\Helpers\Tax;
use Illuminate\Support\Facades\Event;
use Webkul\Shipping\Facades\Shipping;
use Webkul\Checkout\Models\CartAddress;
use Webkul\Checkout\Models\CartPayment;
use Webkul\Checkout\Models\Cart as CartModel;
use Webkul\Checkout\Repositories\CartRepository;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Tax\Repositories\TaxCategoryRepository;
use Webkul\Checkout\Repositories\CartItemRepository;
use Webkul\Customer\Repositories\WishlistRepository;
use Webkul\Checkout\Repositories\CartAddressRepository;
use Webkul\Customer\Repositories\CustomerAddressRepository;
class Cart
{
@ -331,6 +331,8 @@ class Cart
}
}
Shipping::collectRates();
Event::dispatch('checkout.cart.delete.after', $itemId);
$this->collectTotals();

View File

@ -7,8 +7,11 @@ namespace Webkul\Core\Helpers;
use Faker\Factory;
use Codeception\Module\Laravel5;
use Webkul\BookingProduct\Models\BookingProduct;
use Webkul\BookingProduct\Models\BookingProductEventTicket;
use Webkul\Checkout\Models\Cart;
use Webkul\Checkout\Models\CartItem;
use Webkul\Customer\Models\Customer;
use Webkul\Product\Models\Product;
use Webkul\Attribute\Models\Attribute;
use Webkul\Checkout\Models\CartAddress;
@ -31,21 +34,19 @@ class Laravel5Helper extends Laravel5
public const SIMPLE_PRODUCT = 1;
public const VIRTUAL_PRODUCT = 2;
public const DOWNLOADABLE_PRODUCT = 3;
public const BOOKING_EVENT_PRODUCT = 4;
/**
* Returns the field name of the given attribute in which a value should be saved inside
* the 'product_attribute_values' table. Depends on the type.
*
* @param string $attribute
* @param string $type
*
* @return string|null
* @part ORM
*/
public static function getAttributeFieldName(string $type): ?string
{
$attributes = [];
$possibleTypes = [
'text' => 'text_value',
'select' => 'integer_value',
@ -60,7 +61,7 @@ class Laravel5Helper extends Laravel5
public function prepareCart(array $options = []): array
{
$faker = \Faker\Factory::create();
$faker = Factory::create();
$I = $this;
@ -108,7 +109,7 @@ class Laravel5Helper extends Laravel5
$cartItems = [];
$generatedCartItems = rand(3, 10);
$generatedCartItems = random_int(3, 10);
for ($i = 2; $i <= $generatedCartItems; $i++) {
$quantity = random_int(1, 10);
@ -178,6 +179,10 @@ class Laravel5Helper extends Laravel5
$I = $this;
switch ($productType) {
case self::BOOKING_EVENT_PRODUCT:
$product = $I->haveBookingEventProduct($configs, $productStates);
break;
case self::DOWNLOADABLE_PRODUCT:
$product = $I->haveDownloadableProduct($configs, $productStates);
break;
@ -205,7 +210,6 @@ class Laravel5Helper extends Laravel5
$productStates = array_merge($productStates, ['simple']);
}
/** @var Product $product */
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
$I->createAttributeValues($product->id, $configs['attributeValues'] ?? []);
@ -222,7 +226,6 @@ class Laravel5Helper extends Laravel5
$productStates = array_merge($productStates, ['virtual']);
}
/** @var Product $product */
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
$I->createAttributeValues($product->id, $configs['attributeValues'] ?? []);
@ -239,7 +242,6 @@ class Laravel5Helper extends Laravel5
$productStates = array_merge($productStates, ['downloadable']);
}
/** @var Product $product */
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
$I->createAttributeValues($product->id, $configs['attributeValues'] ?? []);
@ -249,6 +251,22 @@ class Laravel5Helper extends Laravel5
return $product->refresh();
}
private function haveBookingEventProduct(array $configs = [], array $productStates = []): Product
{
$I = $this;
if (! in_array('booking', $productStates)) {
$productStates = array_merge($productStates, ['booking']);
}
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
$I->createAttributeValues($product->id, $configs['attributeValues'] ?? []);
$I->createBookingEventProduct($product->id);
return $product->refresh();
}
private function createProduct(array $attributes = [], array $states = []): Product
{
return factory(Product::class)->states($states)->create($attributes);
@ -275,6 +293,18 @@ class Laravel5Helper extends Laravel5
]);
}
private function createBookingEventProduct(int $productId): void
{
$I = $this;
$bookingProduct = $I->have(BookingProduct::class, [
'product_id' => $productId,
]);
$I->have(BookingProductEventTicket::class, [
'booking_product_id' => $bookingProduct->id,
]);
}
private function createAttributeValues(int $productId, array $attributeValues = []): void
{
$I = $this;
@ -295,7 +325,7 @@ class Laravel5Helper extends Laravel5
}
/** @var array $defaultAttributeValues
/**
* Some defaults that should apply to all generated products.
* By defaults products will be generated as saleable.
* If you do not want this, this defaults can be overriden by $attributeValues.
@ -314,7 +344,7 @@ class Laravel5Helper extends Laravel5
'special_price' => null,
'price' => $faker->randomFloat(2, 1, 1000),
'weight' => '1.00', // necessary for shipping
'brand' => AttributeOption::firstWhere('attribute_id', $brand->id)->id,
'brand' => AttributeOption::query()->firstWhere('attribute_id', $brand->id)->id,
];
$attributeValues = array_merge($defaultAttributeValues, $attributeValues);

View File

@ -82,6 +82,7 @@ class CustomerController extends Controller
*/
public function update()
{
$isPasswordChanged = false;
$id = auth()->guard('customer')->user()->id;
$this->validate(request(), [
@ -104,6 +105,7 @@ class CustomerController extends Controller
if (isset ($data['oldpassword'])) {
if ($data['oldpassword'] != "" || $data['oldpassword'] != null) {
if (Hash::check($data['oldpassword'], auth()->guard('customer')->user()->password)) {
$isPasswordChanged = true;
$data['password'] = bcrypt($data['password']);
} else {
session()->flash('warning', trans('shop::app.customer.account.profile.unmatch'));
@ -119,6 +121,10 @@ class CustomerController extends Controller
if ($customer = $this->customerRepository->update($data, $id)) {
if ($isPasswordChanged) {
Event::dispatch('user.admin.update-password', $customer);
}
Event::dispatch('customer.update.after', $customer);
Session()->flash('success', trans('shop::app.customer.account.profile.edit-success'));
@ -150,7 +156,7 @@ class CustomerController extends Controller
$orders = $customerRepository->all_orders->whereIn('status', ['pending', 'processing'])->first();
if ($orders) {
session()->flash('error', trans('admin::app.response.order-pending'));
session()->flash('error', trans('admin::app.response.order-pending', ['name' => 'Customer']));
return redirect()->route($this->_config['redirect']);
} else {

View File

@ -0,0 +1,43 @@
<?php
namespace Webkul\Customer\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class CustomerUpdatePassword extends Mailable
{
use Queueable, SerializesModels;
/**
* The customer instance.
*
* @var \Webkul\Customer\Models\Customer $customer
*/
public $customer;
/**
* Create a new message instance.
*
* @param \Webkul\Customer\Models\Customer $customer
* @return void
*/
public function __construct($customer)
{
$this->customer = $customer;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from(core()->getSenderEmailDetails()['email'], core()->getSenderEmailDetails()['name'])
->to($this->customer->email, $this->customer->name)
->subject(trans('shop::app.mail.update-password.subject'))
->view('shop::emails.customer.update-password', ['user' => $this->customer]);
}
}

View File

@ -16,4 +16,36 @@ class CustomerRepository extends Repository
{
return 'Webkul\Customer\Contracts\Customer';
}
/**
* Check if customer has order pending or processing.
*
* @param Webkul\Customer\Models\Customer
* @return boolean
*/
public function checkIfCustomerHasOrderPendingOrProcessing($customer)
{
return $customer->all_orders->pluck('status')->contains(function ($val) {
return $val === 'pending' || $val === 'processing';
});
}
/**
* Check if bulk customers, if they have order pending or processing.
*
* @param array
* @return boolean
*/
public function checkBulkCustomerIfTheyHaveOrderPendingOrProcessing($customerIds)
{
foreach ($customerIds as $customerId) {
$customer = $this->findorFail($customerId);
if ($this->checkIfCustomerHasOrderPendingOrProcessing($customer)) {
return true;
}
}
return false;
}
}

View File

@ -105,7 +105,9 @@ class Ipn
$this->orderRepository->update(['status' => 'processing'], $this->order->id);
if ($this->order->canInvoice()) {
$this->invoiceRepository->create($this->prepareInvoiceData());
$invoice = $this->invoiceRepository->create($this->prepareInvoiceData());
$this->invoiceRepository->updateInvoiceState($invoice, "paid");
}
}
}

View File

@ -6,12 +6,8 @@ use Faker\Generator as Faker;
use Webkul\Product\Models\Product;
$factory->define(Product::class, function (Faker $faker) {
$now = date("Y-m-d H:i:s");
return [
'sku' => $faker->uuid,
'created_at' => $now,
'updated_at' => $now,
'attribute_family_id' => 1,
];
});
@ -26,4 +22,8 @@ $factory->state(Product::class, 'virtual', [
$factory->state(Product::class, 'downloadable', [
'type' => 'downloadable',
]);
$factory->state(Product::class, 'booking', [
'type' => 'booking',
]);

View File

@ -95,7 +95,7 @@ class Toolbar extends AbstractProduct
$sortBy = core()->getConfigData('catalog.products.storefront.sort_by')
? core()->getConfigData('catalog.products.storefront.sort_by')
: 'created_at-asc';
if ($key == $sortBy) {
return true;
}
@ -155,4 +155,27 @@ class Toolbar extends AbstractProduct
? core()->getConfigData('catalog.products.storefront.mode')
: 'grid';
}
/**
* Returns the view option if mode is set by param then it will overwrite default one and return new mode
*
* @return string
*/
public function getViewOption()
{
/* checking default option first */
$viewOption = core()->getConfigData('catalog.products.storefront.mode');
/* checking mode param if exist then overwrite the default option */
if ($this->isModeActive('grid')) {
$viewOption = 'grid';
}
/* checking mode param if exist then overwrite the default option */
if ($this->isModeActive('list')) {
$viewOption = 'list';
}
return $viewOption;
}
}

View File

@ -189,7 +189,33 @@ class ProductController extends Controller
*/
public function update(ProductForm $request, $id)
{
$product = $this->productRepository->update(request()->all(), $id);
$data = request()->all();
$multiselectAttributeCodes = array();
$productAttributes = $this->productRepository->findOrFail($id);
foreach ($productAttributes->attribute_family->attribute_groups as $attributeGroup) {
$customAttributes = $productAttributes->getEditableAttributes($attributeGroup);
if (count($customAttributes)) {
foreach ($customAttributes as $attribute) {
if ($attribute->type == 'multiselect') {
array_push($multiselectAttributeCodes,$attribute->code);
}
}
}
}
if (count($multiselectAttributeCodes)) {
foreach ($multiselectAttributeCodes as $multiselectAttributeCode) {
if(! isset($data[$multiselectAttributeCode])){
$data[$multiselectAttributeCode] = array();
}
}
}
$product = $this->productRepository->update($data, $id);
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Product']));

View File

@ -136,6 +136,9 @@ class ProductFlat
$table->dropColumn($attribute->code . '_label');
}
});
$this->productFlatRepository->updateAttributeColumn( $attribute , $this );
}
}
@ -313,4 +316,4 @@ class ProductFlat
}
}
}
}
}

View File

@ -86,4 +86,22 @@ class ProductFlatRepository extends Repository
return $filterAttributes;
}
/**
* update product_flat custom column
*
* @param \Webkul\Attribute\Models\Attribute $attribute
* @param \Webkul\Product\Listeners\ProductFlat $listener
*/
public function updateAttributeColumn(
\Webkul\Attribute\Models\Attribute $attribute ,
\Webkul\Product\Listeners\ProductFlat $listener ) {
return $this->model
->leftJoin('product_attribute_values as v', function($join) use ($attribute) {
$join->on('product_flat.id', '=', 'v.product_id')
->on('v.attribute_id', '=', \DB::raw($attribute->id));
})->update(['product_flat.'.$attribute->code => \DB::raw($listener->attributeTypeFields[$attribute->type] .'_value')]);
}
}

View File

@ -111,7 +111,7 @@ class ProductRepository extends Repository
if (core()->getConfigData('catalog.products.storefront.products_per_page')) {
$pages = explode(',', core()->getConfigData('catalog.products.storefront.products_per_page'));
$perPage = isset($params['limit']) ? $params['limit'] : current($pages);
$perPage = isset($params['limit']) ? (!empty($params['limit']) ? $params['limit'] : 9) : current($pages);
} else {
$perPage = isset($params['limit']) && !empty($params['limit']) ? $params['limit'] : 9;
}
@ -125,7 +125,7 @@ class ProductRepository extends Repository
$qb = $query->distinct()
->select('product_flat.*')
->join('product_flat as variants', 'product_flat.id', '=', DB::raw('COALESCE(variants.parent_id, variants.id)'))
->join('product_flat as variants', 'product_flat.id', '=', DB::raw('COALESCE('.DB::getTablePrefix().'variants.parent_id, '.DB::getTablePrefix().'variants.id)'))
->leftJoin('product_categories', 'product_categories.product_id', '=', 'product_flat.product_id')
->leftJoin('product_attribute_values', 'product_attribute_values.product_id', '=', 'variants.product_id')
->where('product_flat.channel', $channel)
@ -151,17 +151,17 @@ class ProductRepository extends Repository
$orderDirection = 'asc';
if( isset($params['order']) && in_array($params['order'], ['desc', 'asc']) ){
$orderDirection = $params['order'];
} else {
$sortOptions = $this->getDefaultSortByOption();
$orderDirection = !empty($sortOptions) ? $sortOptions[1] : 'asc';
}
if (isset($params['sort'])) {
$attribute = $this->attributeRepository->findOneByField('code', $params['sort']);
if ($attribute) {
if ($attribute->code == 'price') {
$qb->orderBy('min_price', $orderDirection);
} else {
$qb->orderBy($params['sort'] == 'created_at' ? 'product_flat.created_at' : $attribute->code, $orderDirection);
}
$this->checkSortAttributeAndGenerateQuery($qb, $params['sort'], $orderDirection);
} else {
$sortOptions = $this->getDefaultSortByOption();
if (!empty($sortOptions)) {
$this->checkSortAttributeAndGenerateQuery($qb, $sortOptions[0], $orderDirection);
}
}
@ -184,7 +184,7 @@ class ProductRepository extends Repository
foreach ($attributeFilters as $attribute) {
$filterQuery->orWhere(function ($attributeQuery) use ($attribute) {
$column = 'product_attribute_values.' . ProductAttributeValueProxy::modelClass()::$attributeTypeFields[$attribute->type];
$column = DB::getTablePrefix() . 'product_attribute_values.' . ProductAttributeValueProxy::modelClass()::$attributeTypeFields[$attribute->type];
$filterInputValues = explode(',', request()->get($attribute->code));
@ -453,4 +453,41 @@ class ProductRepository extends Repository
->orderBy('product_id', 'desc');
})->get();
}
/**
* Get default sort by option
*
* @return array
*/
private function getDefaultSortByOption()
{
$value = core()->getConfigData('catalog.products.storefront.sort_by');
$config = $value ? $value : 'name-desc';
return explode('-', $config);
}
/**
* Check sort attribute and generate query
*
* @param object $query
* @param string $sort
* @param string $direction
* @return object
*/
private function checkSortAttributeAndGenerateQuery($query, $sort, $direction)
{
$attribute = $this->attributeRepository->findOneByField('code', $sort);
if ($attribute) {
if ($attribute->code == 'price') {
$query->orderBy('min_price', $direction);
} else {
$query->orderBy($sort == 'created_at' ? 'product_flat.created_at' : $attribute->code, $direction);
}
}
return $query;
}
}

View File

@ -452,6 +452,8 @@ class Bundle extends AbstractType
*/
public function prepareForCart($data)
{
$bundleQuantity = $data['quantity'];
if (isset($data['bundle_options'])) {
$data['bundle_options'] = array_filter($this->validateBundleOptionForCart($data['bundle_options']));
}
@ -460,11 +462,21 @@ class Bundle extends AbstractType
return trans('shop::app.checkout.cart.integrity.missing_options');
}
if (! $this->haveSufficientQuantity($data['quantity'])) {
return trans('shop::app.checkout.cart.quantity.inventory_warning');
}
$products = parent::prepareForCart($data);
foreach ($this->getCartChildProducts($data) as $productId => $data) {
$product = $this->productRepository->find($productId);
/* need to check each individual quantity as well if don't have then show error */
if (! $product->getTypeInstance()->haveSufficientQuantity($data['quantity'] * $bundleQuantity)) {
return trans('shop::app.checkout.cart.quantity.inventory_warning');
}
if (! $product->getTypeInstance()->isSaleable()) {
continue;
}
@ -738,7 +750,7 @@ class Bundle extends AbstractType
if ($option->is_required) {
foreach ($option->bundle_option_products as $bundleOptionProduct) {
# as long as at least one product in the required group is available we can continue checking other groups
if($bundleOptionProduct->product->haveSufficientQuantity($bundleOptionProduct->qty * $qty)) {
if ($bundleOptionProduct->product->haveSufficientQuantity($bundleOptionProduct->qty * $qty)) {
continue 2;
}
}

Some files were not shown because too many files have changed in this diff Show More