Merge branch 'master' of https://github.com/bagisto/bagisto into velocity-updated

This commit is contained in:
shubhammehrotra.symfony@webkul.com 2020-01-28 17:07:43 +05:30
commit 922e3608be
80 changed files with 1106 additions and 367 deletions

View File

@ -13,6 +13,7 @@ DB_PORT=3306
DB_DATABASE=bagisto_testing
DB_USERNAME=bagisto
DB_PASSWORD=secret
DB_PREFIX=
BROADCAST_DRIVER=log
CACHE_DRIVER=file

1
.gitignore vendored
View File

@ -7,6 +7,7 @@
/public/js
/public/vendor
/public/themes
/public/fonts
/vendor
/.idea
/.vscode

View File

@ -61,6 +61,7 @@ class GenerateProducts extends Command
try {
$result = $this->generateProduct->create();
} catch (\Exception $e) {
report($e);
continue;
}

1
bin/codecept Symbolic link
View File

@ -0,0 +1 @@
../vendor/bin/codecept

49
bin/test.sh Executable file
View File

@ -0,0 +1,49 @@
#!/bin/bash
printf "### start preparation ###\n"
WORKPATH=$(dirname ${0})
printf ">> workpath is %s\n" ${WORKPATH}
LOG_DIR="${WORKPATH}/../storage/logs/tests"
printf ">> log-dir is %s\n" ${LOG_DIR}
printf ">> create and truncate log dir\n"
mkdir -p ${LOG_DIR}
rm -rf ${LOG_DIR}/*
printf ">> truncate and migrate database\n"
php artisan migrate:fresh --env=testing --quiet
printf "### finish preparation ###\n"
printf "### start tests ###\n"
SUCCESS=1
execSuite() {
${WORKPATH}/../vendor/bin/codecept run ${1} \
--xml report_${1}.xml ${CODECEPT_OPTIONS} | tee ${LOG_DIR}/tests_${1}.log
if [[ ${PIPESTATUS[0]} -ne 0 ]]
then
SUCCESS=0
fi
}
execSuite unit
execSuite functional
if [[ ${?} -ne 0 ]]
then
SUCCESS=0
fi
printf "### finish tests ###\n"
if [[ ${SUCCESS} -eq 1 ]]
then
printf ">> all tests are \e[01;32mgreen\e[0m\n"
exit 0
else
printf ">> at least one test is \e[01;31mred\e[0m\n"
exit 1
fi

View File

@ -21,7 +21,7 @@
"resolve-url-loader": "^3.1.0",
"sass": "^1.24.5",
"sass-loader": "^8.0.2",
"vue": "^2.5.7",
"vue": "^2.6.11",
"vue-template-compiler": "^2.6.11"
},
"dependencies": {

View File

@ -52,7 +52,7 @@ class AddressDataGrid extends DataGrid
$queryBuilder = DB::table('customer_addresses as ca')
->leftJoin('countries', 'ca.country', '=', 'countries.code')
->leftJoin('customers as c', 'ca.customer_id', '=', 'c.id')
->addSelect('ca.id as address_id', 'ca.address1', 'ca.country', DB::raw('' . DB::getTablePrefix() . 'countries.name as country_name'), 'ca.state', 'ca.city', 'ca.postcode', 'ca.phone', 'ca.default_address')
->addSelect('ca.id as address_id', 'ca.company_name', 'ca.vat_id', 'ca.address1', 'ca.country', DB::raw('' . DB::getTablePrefix() . 'countries.name as country_name'), 'ca.state', 'ca.city', 'ca.postcode', 'ca.phone', 'ca.default_address')
->where('c.id', $customer->id);
$queryBuilder = $queryBuilder->leftJoin('country_states', function($qb) {
@ -65,6 +65,8 @@ class AddressDataGrid extends DataGrid
->addSelect(DB::raw(DB::getTablePrefix() . 'country_states.default_name as state_name'));
$this->addFilter('address_id', 'ca.id');
$this->addFilter('company_name', 'ca.company_name');
$this->addFilter('vat_id', 'ca.vat_id');
$this->addFilter('address1', 'ca.address1');
$this->addFilter('city', 'ca.city');
$this->addFilter('state_name', DB::raw(DB::getTablePrefix() . 'country_states.default_name'));
@ -77,6 +79,7 @@ class AddressDataGrid extends DataGrid
public function addColumns()
{
$this->addColumn([
'index' => 'address_id',
'label' => trans('admin::app.customers.addresses.address-id'),
@ -131,6 +134,15 @@ class AddressDataGrid extends DataGrid
'filterable' => true
]);
$this->addColumn([
'index' => 'vat_id',
'label' => trans('admin::app.customers.addresses.vat_id'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'default_address',
'label' => trans('admin::app.customers.addresses.default-address'),

View File

@ -2,6 +2,7 @@
namespace Webkul\Admin\Http\Controllers\Customer;
use Webkul\Customer\Rules\VatIdRule;
use Webkul\Admin\Http\Controllers\Controller;
use Webkul\Customer\Repositories\CustomerRepository as Customer;
use Webkul\Customer\Repositories\CustomerAddressRepository as CustomerAddress;
@ -20,25 +21,26 @@ class AddressController extends Controller
* @var array
*/
protected $_config;
/**
* Customer Repository object
*
* @var object
*/
*/
protected $customer;
/**
* CustomerAddress Repository object
*
* @var object
*/
*/
protected $customerAddress;
/**
* Create a new controller instance.
*
* @param Webkul\Customer\Repositories\CustomerAddressRepository $customerAddress
* @param Webkul\Customer\Repositories\CustomerAddressRepository $customerAddress
*
* @return void
*/
public function __construct(
@ -59,7 +61,7 @@ class AddressController extends Controller
* @return Mixed
*/
public function index($id)
{
{
$customer = $this->customer->find($id);
return view($this->_config['view'], compact('customer'));
@ -84,20 +86,24 @@ class AddressController extends Controller
*/
public function store()
{
request()->merge(['address1' => implode(PHP_EOL, array_filter(request()->input('address1')))]);
request()->merge([
'address1' => implode(PHP_EOL, array_filter(request()->input('address1'))),
]);
$data = collect(request()->input())->except('_token')->toArray();
$this->validate(request(), [
'address1' => 'string|required',
'country' => 'string|required',
'state' => 'string|required',
'city' => 'string|required',
'postcode' => 'required',
'phone' => 'required'
'company_name' => 'string',
'address1' => 'string|required',
'country' => 'string|required',
'state' => 'string|required',
'city' => 'string|required',
'postcode' => 'required',
'phone' => 'required',
'vat_id' => new VatIdRule(),
]);
if ( $this->customerAddress->create($data) ) {
if ($this->customerAddress->create($data)) {
session()->flash('success', trans('admin::app.customers.addresses.success-create'));
return redirect()->route('admin.customer.addresses.index', ['id' => $data['customer_id']]);
@ -131,19 +137,21 @@ class AddressController extends Controller
request()->merge(['address1' => implode(PHP_EOL, array_filter(request()->input('address1')))]);
$this->validate(request(), [
'address1' => 'string|required',
'country' => 'string|required',
'state' => 'string|required',
'city' => 'string|required',
'postcode' => 'required',
'phone' => 'required'
'company_name' => 'string',
'address1' => 'string|required',
'country' => 'string|required',
'state' => 'string|required',
'city' => 'string|required',
'postcode' => 'required',
'phone' => 'required',
'vat_id' => new VatIdRule(),
]);
$data = collect(request()->input())->except('_token')->toArray();
$address = $this->customerAddress->find($id);
if ( $address ) {
if ($address) {
$this->customerAddress->update($data, $id);
@ -157,7 +165,8 @@ class AddressController extends Controller
/**
* Remove the specified resource from storage.
*
* @param int $id
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function destroy($id)

View File

@ -31,14 +31,14 @@ class CustomerController extends Controller
*/
protected $customerRepository;
/**
/**
* CustomerGroupRepository object
*
* @var array
*/
protected $customerGroupRepository;
/**
/**
* ChannelRepository object
*
* @var array
@ -74,13 +74,13 @@ class CustomerController extends Controller
* Display a listing of the resource.
*
* @return \Illuminate\View\View
*/
*/
public function index()
{
return view($this->_config['view']);
}
/**
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\View\View
@ -91,10 +91,10 @@ class CustomerController extends Controller
$channelName = $this->channelRepository->all();
return view($this->_config['view'], compact('customerGroup','channelName'));
return view($this->_config['view'], compact('customerGroup', 'channelName'));
}
/**
/**
* Store a newly created resource in storage.
*
* @return \Illuminate\Http\Response
@ -102,16 +102,16 @@ class CustomerController extends Controller
public function store()
{
$this->validate(request(), [
'first_name' => 'string|required',
'last_name' => 'string|required',
'gender' => 'required',
'email' => 'required|unique:customers,email',
'date_of_birth' => 'date|before:today'
'first_name' => 'string|required',
'last_name' => 'string|required',
'gender' => 'required',
'email' => 'required|unique:customers,email',
'date_of_birth' => 'date|before:today',
]);
$data = request()->all();
$password = rand(100000,10000000);
$password = rand(100000, 10000000);
$data['password'] = bcrypt($password);
@ -122,7 +122,7 @@ class CustomerController extends Controller
try {
Mail::queue(new NewCustomerNotification($customer, $password));
} catch (\Exception $e) {
report($e);
}
session()->flash('success', trans('admin::app.response.create-success', ['name' => 'Customer']));
@ -133,7 +133,8 @@ class CustomerController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @param int $id
*
* @return \Illuminate\View\View
*/
public function edit($id)
@ -147,20 +148,21 @@ class CustomerController extends Controller
return view($this->_config['view'], compact('customer', 'customerGroup', 'channelName'));
}
/**
/**
* Update the specified resource in storage.
*
* @param int $id
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function update($id)
{
$this->validate(request(), [
'first_name' => 'string|required',
'last_name' => 'string|required',
'gender' => 'required',
'email' => 'required|unique:customers,email,'. $id,
'date_of_birth' => 'date|before:today'
'first_name' => 'string|required',
'last_name' => 'string|required',
'gender' => 'required',
'email' => 'required|unique:customers,email,' . $id,
'date_of_birth' => 'date|before:today',
]);
$this->customerRepository->update(request()->all(), $id);
@ -173,7 +175,8 @@ class CustomerController extends Controller
/**
* Remove the specified resource from storage.
*
* @param int $id
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function destroy($id)
@ -186,7 +189,7 @@ class CustomerController extends Controller
session()->flash('success', trans('admin::app.response.delete-success', ['name' => 'Customer']));
return response()->json(['message' => true], 200);
} catch(\Exception $e) {
} catch (\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Customer']));
}
@ -213,13 +216,13 @@ class CustomerController extends Controller
public function storeNote()
{
$this->validate(request(), [
'notes' => 'string|nullable'
'notes' => 'string|nullable',
]);
$customer = $this->customerRepository->find(request()->input('_customer'));
$noteTaken = $customer->update([
'notes' => request()->input('notes')
'notes' => request()->input('notes'),
]);
if ($noteTaken) {
@ -245,7 +248,7 @@ class CustomerController extends Controller
$customer = $this->customerRepository->find($customerId);
$customer->update([
'status' => $updateOption
'status' => $updateOption,
]);
}
@ -265,7 +268,7 @@ class CustomerController extends Controller
foreach ($customerIds as $customerId) {
$this->customerRepository->deleteWhere([
'id' => $customerId
'id' => $customerId,
]);
}

View File

@ -10,13 +10,15 @@ use Webkul\Admin\Mail\NewShipmentNotification;
use Webkul\Admin\Mail\NewInventorySourceNotification;
use Webkul\Admin\Mail\CancelOrderNotification;
use Webkul\Admin\Mail\NewRefundNotification;
/**
* Order event handler
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class Order {
class Order
{
/**
* @param mixed $order
@ -30,7 +32,7 @@ class Order {
Mail::queue(new NewAdminNotification($order));
} catch (\Exception $e) {
report($e);
}
}
@ -42,12 +44,13 @@ class Order {
public function sendNewInvoiceMail($invoice)
{
try {
if ($invoice->email_sent)
if ($invoice->email_sent) {
return;
}
Mail::queue(new NewInvoiceNotification($invoice));
} catch (\Exception $e) {
report($e);
}
}
@ -61,7 +64,7 @@ class Order {
try {
Mail::queue(new NewRefundNotification($refund));
} catch (\Exception $e) {
report($e);
}
}
@ -73,25 +76,28 @@ class Order {
public function sendNewShipmentMail($shipment)
{
try {
if ($shipment->email_sent)
if ($shipment->email_sent) {
return;
}
Mail::queue(new NewShipmentNotification($shipment));
Mail::queue(new NewInventorySourceNotification($shipment));
} catch (\Exception $e) {
report($e);
}
}
/*
/**
* @param mixed $order
* */
public function sendCancelOrderMail($order){
try{
*
*/
public function sendCancelOrderMail($order)
{
try {
Mail::queue(new CancelOrderNotification($order));
}catch (\Exception $e){
\Log::error('Error occured when sending email '.$e->getMessage());
} catch (\Exception $e) {
report($e);
}
}
}

View File

@ -867,6 +867,7 @@ return [
'addresses' => [
'title' => ':customer_name\'s Addresses List',
'vat_id' => 'Vat id',
'create-title' => 'Create Customer\'s Address',
'edit-title' => 'Update Customer\'s Address',
'title-orders' => ':customer_name\'s Orders List',

View File

@ -39,7 +39,7 @@
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.catalog.categories.name') }}</label>
<input type="text" v-validate="'required'" class="control" id="name" name="name" value="{{ old('name') }}" data-vv-as="&quot;{{ __('admin::app.catalog.categories.name') }}&quot;"/>
<input type="text" v-validate="'required'" class="control" id="name" name="name" value="{{ old('name') }}" data-vv-as="&quot;{{ __('admin::app.catalog.categories.name') }}&quot;" v-slugify-target="'slug'"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>

View File

@ -52,7 +52,7 @@
<div class="control-group" :class="[errors.has('{{$locale}}[name]') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.catalog.categories.name') }}</label>
<input type="text" v-validate="'required'" class="control" id="name" name="{{$locale}}[name]" value="{{ old($locale)['name'] ?? $category->translate($locale)['name'] }}" data-vv-as="&quot;{{ __('admin::app.catalog.categories.name') }}&quot;"/>
<input type="text" v-validate="'required'" class="control" id="name" name="{{$locale}}[name]" value="{{ old($locale)['name'] ?? $category->translate($locale)['name'] }}" data-vv-as="&quot;{{ __('admin::app.catalog.categories.name') }}&quot;" v-slugify-target="'slug'"/>
<span class="control-error" v-if="errors.has('{{$locale}}[name]')">@{{ errors.first('{!!$locale!!}[name]') }}</span>
</div>

View File

@ -1 +1,4 @@
<input type="text" v-validate="'{{$validations}}'" class="control" id="{{ $attribute->code }}" name="{{ $attribute->code }}" value="{{ old($attribute->code) ?: $product[$attribute->code] }}" data-vv-as="&quot;{{ $attribute->admin_name }}&quot;" {{ in_array($attribute->code, ['sku', 'url_key']) ? 'v-slugify' : '' }}/>
<input type="text" v-validate="'{{$validations}}'" class="control" id="{{ $attribute->code }}" name="{{ $attribute->code }}" value="{{ old($attribute->code) ?: $product[$attribute->code] }}" {{ in_array($attribute->code, ['sku', 'url_key']) ? 'v-slugify' : '' }} data-vv-as="&quot;{{ $attribute->admin_name }}&quot;" {{ $attribute->code == 'name' ? 'v-slugify-target=\'url_key\'' : '' }} />

View File

@ -36,6 +36,18 @@
<accordian :title="'{{ __('admin::app.customers.addresses.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('company_name') ? 'has-error' : '']">
<label for="company_name">{{ __('shop::app.customer.account.address.create.company_name') }}</label>
<input type="text" class="control" name="company_name" value="{{ old('company_name') }}" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.company_name') }}&quot;">
<span class="control-error" v-if="errors.has('company_name')">@{{ errors.first('company_name') }}</span>
</div>
<div class="control-group" :class="[errors.has('vat_id') ? 'has-error' : '']">
<label for="vat_id">{{ __('shop::app.customer.account.address.create.vat_id') }}</label>
<input type="text" class="control" name="vat_id" value="{{ old('vat_id') }}" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.vat_id') }}&quot;">
<span class="control-error" v-if="errors.has('vat_id')">@{{ errors.first('vat_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('address1[]') ? 'has-error' : '']">
<label for="address_0" class="required">{{ __('shop::app.customer.account.address.edit.street-address') }}</label>
<input type="text" class="control" name="address1[]" id="address_0" v-validate="'required'" value="{{ old('address1') }}" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.street-address') }}&quot;">

View File

@ -15,17 +15,17 @@
<div class="page-title">
<h1>{{ __('admin::app.customers.addresses.edit-title') }}</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-primary btn-lg">
{{ __('admin::app.customers.addresses.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
@csrf()
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="customer_id" value="{{ $address->customer_id }}">
@ -35,6 +35,18 @@
<?php $addresses = explode(PHP_EOL, $address->address1); ?>
<div class="control-group" :class="[errors.has('company_name') ? 'has-error' : '']">
<label for="company_name">{{ __('shop::app.customer.account.address.create.company_name') }}</label>
<input type="text" class="control" name="company_name" value="{{ $address->company_name }}" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.company_name') }}&quot;">
<span class="control-error" v-if="errors.has('company_name')">@{{ errors.first('company_name') }}</span>
</div>
<div class="control-group" :class="[errors.has('vat_id') ? 'has-error' : '']">
<label for="vat_id">{{ __('shop::app.customer.account.address.create.vat_id') }}</label>
<input type="text" class="control" name="vat_id" value="{{ $address->vat_id }}" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.vat_id') }}&quot;">
<span class="control-error" v-if="errors.has('vat_id')">@{{ errors.first('vat_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('address1[]') ? 'has-error' : '']">
<label for="address_0" class="required">{{ __('shop::app.customer.account.address.edit.street-address') }}</label>
<input type="text" class="control" name="address1[]" id="address_0" v-validate="'required'" value="{{ isset($addresses[0]) ? $addresses[0] : '' }}" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.street-address') }}&quot;">
@ -51,7 +63,7 @@
<div class="control-group" :class="[errors.has('city') ? 'has-error' : '']">
<label for="city" class="required">{{ __('shop::app.customer.account.address.create.city') }}</label>
<input type="text" class="control" name="city" v-validate="'required|alpha_spaces'" value="{{ $address->city }}" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.city') }}&quot;">
<input type="text" class="control" name="city" v-validate="'required'" value="{{ $address->city }}" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.city') }}&quot;">
<span class="control-error" v-if="errors.has('city')">@{{ errors.first('city') }}</span>
</div>

View File

@ -47,8 +47,8 @@
<div class="control-group" :class="[errors.has('direction') ? 'has-error' : '']">
<label for="direction" class="required">{{ __('admin::app.settings.locales.direction') }}</label>
<select v-validate="'required'" class="control" id="direction" name="direction" data-vv-as="&quot;{{ __('admin::app.settings.locales.direction') }}&quot;">
<option value="ltr" selected title="Text direction left to right">ltr</option>
<option value="rtl" title="Text direction right to left">rtl</option>
<option value="ltr" selected title="Text direction left to right">LTR</option>
<option value="rtl" title="Text direction right to left">RTL</option>
</select>
<span class="control-error" v-if="errors.has('direction')">@{{ errors.first('direction') }}</span>
</div>

View File

@ -51,8 +51,8 @@
<div class="control-group" :class="[errors.has('direction') ? 'has-error' : '']">
<label for="direction" class="required">{{ __('admin::app.settings.locales.direction') }}</label>
<select v-validate="'required'" class="control" id="direction" name="direction" data-vv-as="&quot;{{ __('admin::app.settings.locales.direction') }}&quot;">
<option value="ltr" {{ old('direction') == 'ltr' ? 'selected' : '' }} title="Text direction left to right">ltr</option>
<option value="rtl" {{ old('direction') == 'rtl' ? 'selected' : '' }} title="Text direction right to left">rtl</option>
<option value="ltr" {{ (old('direction') ?: $locale->direction) == 'ltr' ? 'selected' : '' }}>LTR</option>
<option value="rtl" {{ (old('direction') ?: $locale->direction) == 'rtl' ? 'selected' : '' }}>RTL</option>
</select>
<span class="control-error" v-if="errors.has('direction')">@{{ errors.first('direction') }}</span>
</div>

View File

@ -167,6 +167,7 @@ class AttributeController extends Controller
$this->attributeRepository->delete($value);
}
} catch (\Exception $e) {
report($e);
$suppressFlash = true;
continue;

View File

@ -154,7 +154,8 @@ class AttributeFamilyController extends Controller
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
session()->flash('error', trans( 'admin::app.response.delete-failed', ['name' => 'Family']));
report($e);
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Family']));
}
}
@ -177,16 +178,18 @@ class AttributeFamilyController extends Controller
try {
$this->attributeFamilyRepository->delete($value);
} catch (\Exception $e) {
report($e);
$suppressFlash = true;
continue;
}
}
if (! $suppressFlash)
if (!$suppressFlash) {
session()->flash('success', ('admin::app.datagrid.mass-ops.delete-success'));
else
} else {
session()->flash('info', trans('admin::app.datagrid.mass-ops.partial-action', ['resource' => 'Attribute Family']));
}
return redirect()->back();
} else {

View File

@ -144,7 +144,7 @@ class AttributeRepository extends Repository
$data['value_per_channel'] = $data['value_per_locale'] = 0;
}
if (! in_array($data['type'], ['select', 'multiselect', 'price'])) {
if (! in_array($data['type'], ['select', 'multiselect', 'price', 'checkbox'])) {
$data['is_filterable'] = 0;
}

View File

@ -65,7 +65,7 @@ class CatalogRuleIndex
$this->catalogRuleProductPriceHelper->indexRuleProductPrice(1000);
} catch (\Exception $e) {
report($e);
}
}
@ -80,7 +80,7 @@ class CatalogRuleIndex
try {
if (! $product->getTypeInstance()->priceRuleCanBeApplied())
return;
$productIds = $product->getTypeInstance()->isComposite()
? $product->getTypeInstance()->getChildrenIds()
: [$product->id];
@ -93,7 +93,7 @@ class CatalogRuleIndex
$this->catalogRuleProductPriceHelper->indexRuleProductPrice(1000, $product);
} catch (\Exception $e) {
report($e);
}
}

View File

@ -0,0 +1,52 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddApiTokenColumns extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// @see https://laravel.com/docs/6.x/api-authentication#database-preparation
Schema::table('customers', function ($table) {
$table
->string('api_token', 80)
->after('password')
->unique()
->nullable()
->default(null);
});
Schema::table('admins', function ($table) {
$table
->string('api_token', 80)
->after('password')
->unique()
->nullable()
->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('customers', function (Blueprint $table) {
$table->dropColumn('api_token');
});
Schema::table('admins', function (Blueprint $table) {
$table->dropColumn('api_token');
});
}
}

View File

@ -144,6 +144,7 @@ class CurrencyController extends Controller
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
report($e);
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Currency']));
}
}

View File

@ -200,6 +200,7 @@ class ExchangeRateController extends Controller
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
report($e);
session()->flash('error', trans('admin::app.response.delete-error', ['name' => 'Exchange rate']));
}
}

View File

@ -104,6 +104,7 @@ class SubscriptionController extends Controller
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
report($e);
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Subscriber']));
}

View File

@ -24,6 +24,8 @@ class CoreServiceProvider extends ServiceProvider
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
$this->registerEloquentFactoriesFrom(__DIR__ . '/../Database/Factories');
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'core');
Validator::extend('slug', 'Webkul\Core\Contracts\Validations\Slug@passes');
@ -37,8 +39,6 @@ class CoreServiceProvider extends ServiceProvider
]);
SliderProxy::observe(SliderObserver::class);
$this->registerEloquentFactoriesFrom(__DIR__ . '/../Database/Factories');
}
/**
@ -50,6 +50,7 @@ class CoreServiceProvider extends ServiceProvider
{
$this->registerFacades();
}
/**
* Register Bouncer as a singleton.
*
@ -68,11 +69,12 @@ class CoreServiceProvider extends ServiceProvider
/**
* Register factories.
*
* @param string $path
* @param string $path
*
* @return void
*/
protected function registerEloquentFactoriesFrom($path): void
{
$this->app->make(EloquentFactory::class)->load($path);
}
}
}

View File

@ -7,11 +7,19 @@ use Webkul\Customer\Models\Customer;
use Webkul\Customer\Models\CustomerAddress;
$factory->define(CustomerAddress::class, function (Faker $faker) {
$now = date("Y-m-d H:i:s");
// use an locale from a country in europe so the vat id can be generated
$fakerIt = \Faker\Factory::create('it_IT');
return [
'customer_id' => function () {
return factory(Customer::class)->create()->id;
},
'name' => $faker->name,
'company_name' => $faker->company,
'vat_id' => $fakerIt->vatId(),
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'address1' => $faker->streetAddress,
'country' => $faker->countryCode,
'state' => $faker->state,
@ -19,6 +27,8 @@ $factory->define(CustomerAddress::class, function (Faker $faker) {
'postcode' => $faker->postcode,
'phone' => $faker->e164PhoneNumber,
'default_address' => array_random([0, 1]),
'created_at' => $now,
'updated_at' => $now,
];
});

View File

@ -32,5 +32,3 @@ $factory->state(Customer::class, 'male', [
$factory->state(Customer::class, 'female', [
'gender' => 'Female',
]);

View File

@ -0,0 +1,44 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CustomerAddressImprovements extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('customer_addresses', function (Blueprint $table) {
$table->string('company_name')->nullable()->after('customer_id');
$table->string('vat_id')->nullable()->after('company_name');
});
Schema::table('orders', function (Blueprint $table) {
$table->string('customer_company_name')->nullable()->after('customer_last_name');
$table->string('customer_vat_id')->nullable()->after('customer_company_name');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('customer_addresses', function (Blueprint $table) {
$table->dropColumn('company_name');
$table->dropColumn('vat_id');
});
Schema::table('orders', function (Blueprint $table) {
$table->dropColumn('customer_company_name');
$table->dropColumn('customer_vat_id');
});
}
}

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddNewColumnAndRenameNameColumnInCustomerAddressesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('customer_addresses', function (Blueprint $table) {
$table->renameColumn('name', 'first_name')->nullable();
});
Schema::table('customer_addresses', function (Blueprint $table) {
$table->string('last_name')->after('first_name')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('customer_addresses', function (Blueprint $table) {
//
});
}
}

View File

@ -5,6 +5,7 @@ namespace Webkul\Customer\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Webkul\Customer\Repositories\CustomerAddressRepository;
use Webkul\Customer\Rules\VatIdRule;
use Auth;
/**
@ -77,15 +78,19 @@ class AddressController extends Controller
$data = collect(request()->input())->except('_token')->toArray();
$this->validate(request(), [
'address1' => 'string|required',
'country' => 'string|required',
'state' => 'string|required',
'city' => 'string|required',
'postcode' => 'required',
'phone' => 'required',
'company_name' => 'string',
'address1' => 'string|required',
'country' => 'string|required',
'state' => 'string|required',
'city' => 'string|required',
'postcode' => 'required',
'phone' => 'required',
'vat_id' => new VatIdRule(),
]);
$cust_id['customer_id'] = $this->customer->id;
$cust_id['first_name'] = $this->customer->first_name;
$cust_id['last_name'] = $this->customer->last_name;
$data = array_merge($cust_id, $data);
if ($this->customer->addresses->count() == 0) {
@ -136,12 +141,14 @@ class AddressController extends Controller
request()->merge(['address1' => implode(PHP_EOL, array_filter(request()->input('address1')))]);
$this->validate(request(), [
'address1' => 'string|required',
'country' => 'string|required',
'state' => 'string|required',
'city' => 'string|required',
'postcode' => 'required',
'phone' => 'required',
'company_name' => 'string',
'address1' => 'string|required',
'country' => 'string|required',
'state' => 'string|required',
'city' => 'string|required',
'postcode' => 'required',
'phone' => 'required',
'vat_id' => new VatIdRule(),
]);
$data = collect(request()->input())->except('_token')->toArray();

View File

@ -10,7 +10,7 @@ use Webkul\Product\Repositories\ProductReviewRepository;
* Customer controlller for the customer basically for the tasks of customers which will be
* done after customer authentication.
*
* @author Prashant Singh <prashant.singh852@webkul.com>
* @author Prashant Singh <prashant.singh852@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CustomerController extends Controller
@ -26,23 +26,24 @@ class CustomerController extends Controller
* CustomerRepository object
*
* @var Object
*/
*/
protected $customerRepository;
/**
* ProductReviewRepository object
*
* @var array
*/
*/
protected $productReviewRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Customer\Repositories\CustomerRepository $customer
* @param \Webkul\Product\Repositories\ProductReviewRepository $productReview
* @param \Webkul\Customer\Repositories\CustomerRepository $customer
* @param \Webkul\Product\Repositories\ProductReviewRepository $productReview
*
* @return void
*/
*/
public function __construct(CustomerRepository $customerRepository, ProductReviewRepository $productReviewRepository)
{
$this->middleware('customer');
@ -88,31 +89,34 @@ class CustomerController extends Controller
$id = auth()->guard('customer')->user()->id;
$this->validate(request(), [
'first_name' => 'string',
'last_name' => 'string',
'gender' => 'required',
'date_of_birth' => 'date|before:today',
'email' => 'email|unique:customers,email,'.$id,
'password' => 'confirmed|min:6|required_with:oldpassword',
'oldpassword' => 'required_with:password',
'first_name' => 'string',
'last_name' => 'string',
'gender' => 'required',
'date_of_birth' => 'date|before:today',
'email' => 'email|unique:customers,email,' . $id,
'password' => 'confirmed|min:6|required_with:oldpassword',
'oldpassword' => 'required_with:password',
'password_confirmation' => 'required_with:password',
]);
$data = collect(request()->input())->except('_token')->toArray();
if ($data['date_of_birth'] == "")
if (isset ($data['date_of_birth']) && $data['date_of_birth'] == "") {
unset($data['date_of_birth']);
}
if ($data['oldpassword'] != "" || $data['oldpassword'] != null) {
if(Hash::check($data['oldpassword'], auth()->guard('customer')->user()->password)) {
$data['password'] = bcrypt($data['password']);
if (isset ($data['oldpassword'])) {
if ($data['oldpassword'] != "" || $data['oldpassword'] != null) {
if (Hash::check($data['oldpassword'], auth()->guard('customer')->user()->password)) {
$data['password'] = bcrypt($data['password']);
} else {
session()->flash('warning', trans('shop::app.customer.account.profile.unmatch'));
return redirect()->back();
}
} else {
session()->flash('warning', trans('shop::app.customer.account.profile.unmatch'));
return redirect()->back();
unset($data['password']);
}
} else {
unset($data['password']);
}
if ($this->customerRepository->update($data, $id)) {
@ -129,7 +133,8 @@ class CustomerController extends Controller
/**
* Remove the specified resource from storage.
*
* @param int $id
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function destroy($id)
@ -160,7 +165,7 @@ class CustomerController extends Controller
return redirect()->back();
}
} catch(\Exception $e) {
} catch (\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Customer']));
return redirect()->route($this->_config['redirect']);

View File

@ -71,6 +71,7 @@ class ForgotPasswordController extends Controller
['email' => trans($response)]
);
} catch (\Exception $e) {
report($e);
session()->flash('error', trans($e->getMessage()));
return redirect()->back();

View File

@ -2,6 +2,8 @@
namespace Webkul\Customer\Http\Controllers;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Mail;
use Webkul\Customer\Mail\RegistrationEmail;
@ -85,6 +87,7 @@ class RegistrationController extends Controller
$data = request()->input();
$data['password'] = bcrypt($data['password']);
$data['api_token'] = Str::random(80);
if (core()->getConfigData('customer.settings.email.verification')) {
$data['is_verified'] = 0;
@ -111,18 +114,19 @@ class RegistrationController extends Controller
session()->flash('success', trans('shop::app.customer.signup-form.success-verify'));
} catch (\Exception $e) {
report($e);
session()->flash('info', trans('shop::app.customer.signup-form.success-verify-email-unsent'));
}
} else {
try {
try {
Mail::queue(new RegistrationEmail(request()->all()));
session()->flash('success', trans('shop::app.customer.signup-form.success-verify')); //customer registered successfully
} catch (\Exception $e) {
report($e);
session()->flash('info', trans('shop::app.customer.signup-form.success-verify-email-unsent'));
}
session()->flash('success', trans('shop::app.customer.signup-form.success'));
}
@ -174,6 +178,7 @@ class RegistrationController extends Controller
\Cookie::queue(\Cookie::forget('email-for-resend'));
}
} catch (\Exception $e) {
report($e);
session()->flash('error', trans('shop::app.customer.signup-form.verification-not-sent'));
return redirect()->back();

View File

@ -172,6 +172,7 @@ class WishlistController extends Controller
return redirect()->back();
} catch (\Exception $e) {
report($e);
session()->flash('warning', $e->getMessage());
return redirect()->route('shop.productOrCategory.index', $wishlistItem->product->url_key);

View File

@ -17,9 +17,9 @@ class Customer extends Authenticatable implements CustomerContract, JWTSubject
protected $table = 'customers';
protected $fillable = ['first_name', 'last_name', 'gender', 'date_of_birth', 'email', 'phone', 'password', 'customer_group_id', 'subscribed_to_news_letter', 'is_verified', 'token', 'notes', 'status'];
protected $fillable = ['first_name', 'last_name', 'gender', 'date_of_birth', 'email', 'phone', 'password', 'api_token', 'customer_group_id', 'subscribed_to_news_letter', 'is_verified', 'token', 'notes', 'status'];
protected $hidden = ['password', 'remember_token'];
protected $hidden = ['password', 'api_token', 'remember_token'];
/**
* Get the customer full name.

View File

@ -1,4 +1,5 @@
<?php
namespace Webkul\Customer\Models;
use Illuminate\Database\Eloquent\Model;
@ -8,5 +9,27 @@ class CustomerAddress extends Model implements CustomerAddressContract
{
protected $table = 'customer_addresses';
protected $fillable = ['customer_id' ,'address1', 'country', 'state', 'city', 'postcode', 'phone', 'default_address'];
protected $fillable = [
'customer_id',
'company_name',
'vat_id',
'address1',
'address2',
'country',
'state',
'city',
'postcode',
'phone',
'default_address',
'first_name',
'last_name',
];
/**
* Get the customer address full name.
*/
public function getNameAttribute()
{
return $this->first_name . ' ' . $this->last_name;
}
}

View File

@ -6,12 +6,11 @@ use Webkul\Core\Eloquent\Repository;
use Illuminate\Support\Facades\Event;
/**
* Customer Reposotory
* Customer Repository
*
* @author Prashant Singh <prashant.singh852@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CustomerAddressRepository extends Repository
{
/**
@ -27,21 +26,20 @@ class CustomerAddressRepository extends Repository
/**
* @param array $data
*
* @return mixed
*/
public function create(array $data)
{
Event::dispatch('customer.addresses.create.before');
if ( isset($data['default_address']) ) {
$data['default_address'] = 1;
} else {
$data['default_address'] = 0;
}
$data['default_address'] = isset($data['default_address']) ? 1 : 0;
$default_address = $this->findWhere(['customer_id' => $data['customer_id'], 'default_address' => 1])->first();
$default_address = $this
->findWhere(['customer_id' => $data['customer_id'], 'default_address' => 1])
->first();
if ( isset($default_address->id) && $data['default_address'] ) {
if (isset($default_address->id) && $data['default_address']) {
$default_address->update(['default_address' => 0]);
}
@ -54,7 +52,8 @@ class CustomerAddressRepository extends Repository
/**
* @param array $data
* @param $id
* @param $id
*
* @return mixed
*/
public function update(array $data, $id)
@ -63,16 +62,14 @@ class CustomerAddressRepository extends Repository
Event::dispatch('customer.addresses.update.before', $id);
if (isset($data['default_address']) ) {
$data['default_address'] = 1;
} else {
$data['default_address'] = 0;
}
$data['default_address'] = isset($data['default_address']) ? 1 : 0;
$default_address = $this->findWhere(['customer_id' => $address->customer_id, 'default_address' => 1])->first();
$default_address = $this
->findWhere(['customer_id' => $address->customer_id, 'default_address' => 1])
->first();
if ( isset($default_address->id) && $data['default_address'] ) {
if ( $default_address->id != $address->id ) {
if (isset($default_address->id) && $data['default_address']) {
if ($default_address->id != $address->id) {
$default_address->update(['default_address' => 0]);
}
$address->update($data);

View File

@ -0,0 +1,42 @@
<?php
namespace Webkul\Customer\Rules;
use Illuminate\Contracts\Validation\Rule;
use Webkul\Customer\Rules\VatValidator;
/**
* Class VatIdRule
*
* @see https://laravel.com/docs/5.8/validation#using-rule-objects
* @package App\Rules
*/
class VatIdRule implements Rule
{
/**
* Determine if the validation rule passes.
*
* The rules are borrowed from:
* @see https://raw.githubusercontent.com/danielebarbaro/laravel-vat-eu-validator/master/src/VatValidator.php
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$validator = new VatValidator();
return $validator->validate($value);
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return trans('shop::app.invalid_vat_format');
}
}

View File

@ -0,0 +1,95 @@
<?php
namespace Webkul\Customer\Rules;
/**
* Class VatValidator
*
* This class is borrowed from:
*
* @see https://raw.githubusercontent.com/danielebarbaro/laravel-vat-eu-validator
*
* @package Danielebarbaro\LaravelVatEuValidator
*/
class VatValidator
{
/**
* Regular expression patterns per country code
*
* @var array
* @link http://ec.europa.eu/taxation_customs/vies/faq.html?locale=en#item_11
*/
protected static $pattern_expression = array(
'AT' => 'U[A-Z\d]{8}',
'BE' => '(0\d{9}|\d{10})',
'BG' => '\d{9,10}',
'CY' => '\d{8}[A-Z]',
'CZ' => '\d{8,10}',
'DE' => '\d{9}',
'DK' => '(\d{2} ?){3}\d{2}',
'EE' => '\d{9}',
'EL' => '\d{9}',
'ES' => '[A-Z]\d{7}[A-Z]|\d{8}[A-Z]|[A-Z]\d{8}',
'FI' => '\d{8}',
'FR' => '([A-Z]{2}|\d{2})\d{9}',
'GB' => '\d{9}|\d{12}|(GD|HA)\d{3}',
'HR' => '\d{11}',
'HU' => '\d{8}',
'IE' => '[A-Z\d]{8}|[A-Z\d]{9}',
'IT' => '\d{11}',
'LT' => '(\d{9}|\d{12})',
'LU' => '\d{8}',
'LV' => '\d{11}',
'MT' => '\d{8}',
'NL' => '\d{9}B\d{2}',
'PL' => '\d{10}',
'PT' => '\d{9}',
'RO' => '\d{2,10}',
'SE' => '\d{12}',
'SI' => '\d{8}',
'SK' => '\d{10}',
);
/**
* Validate a VAT number format.
*
* @param string $vatNumber
*
* @return boolean
*/
public function validate(string $vatNumber): bool
{
$vatNumber = $this->vatCleaner($vatNumber);
list($country, $number) = $this->splitVat($vatNumber);
if (! isset(self::$pattern_expression[$country])) {
return false;
}
return preg_match('/^' . self::$pattern_expression[$country] . '$/', $number) > 0;
}
/**
* @param string $vatNumber
*
* @return string
*/
private function vatCleaner(string $vatNumber): string
{
$vatNumber_no_spaces = trim($vatNumber);
return strtoupper($vatNumber_no_spaces);
}
/**
* @param string $vatNumber
*
* @return array
*/
private function splitVat(string $vatNumber): array
{
return [
substr($vatNumber, 0, 2),
substr($vatNumber, 2),
];
}
}

View File

@ -168,6 +168,7 @@ class InventorySourceController extends Controller
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
report($e);
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Inventory source']));
}
}

View File

@ -3,7 +3,7 @@ return [
'cashondelivery' => [
'code' => 'cashondelivery',
'title' => 'Cash On Delivery',
'description' => 'shop::app.checkout.onepage.cash-desc',
'description' => 'Cash On Delivery',
'class' => 'Webkul\Payment\Payment\CashOnDelivery',
'active' => true,
'sort' => 1
@ -12,7 +12,7 @@ return [
'moneytransfer' => [
'code' => 'moneytransfer',
'title' => 'Money Transfer',
'description' => 'shop::app.checkout.onepage.money-desc',
'description' => 'Money Transfer',
'class' => 'Webkul\Payment\Payment\MoneyTransfer',
'active' => true,
'sort' => 2
@ -21,7 +21,7 @@ return [
'paypal_standard' => [
'code' => 'paypal_standard',
'title' => 'Paypal Standard',
'description' => 'shop::app.checkout.onepage.paypal-desc',
'description' => 'Paypal Standard',
'class' => 'Webkul\Paypal\Payment\Standard',
'sandbox' => true,
'active' => true,

View File

@ -45,6 +45,14 @@ class BundleOption extends AbstractProduct
$options[$option->id] = $this->getOptionItemData($option);
}
usort ($options, function($a, $b) {
if ($a['sort_order'] == $b['sort_order']) {
return 0;
}
return ($a['sort_order'] < $b['sort_order']) ? -1 : 1;
});
return $options;
}
@ -68,7 +76,7 @@ class BundleOption extends AbstractProduct
/**
* Get formed data from bundle option product
*
*
* @param ProductBundleOption $option
* @return array
*/
@ -83,10 +91,19 @@ class BundleOption extends AbstractProduct
'price' => $bundleOptionProduct->product->getTypeInstance()->getProductPrices(),
'name' => $bundleOptionProduct->product->name,
'product_id' => $bundleOptionProduct->product_id,
'is_default' => $bundleOptionProduct->is_default
'is_default' => $bundleOptionProduct->is_default,
'sort_order' => $bundleOptionProduct->sort_order
];
}
usort ($products, function($a, $b) {
if ($a['sort_order'] == $b['sort_order']) {
return 0;
}
return ($a['sort_order'] < $b['sort_order']) ? -1 : 1;
});
return $products;
}
}

View File

@ -245,6 +245,7 @@ class ProductController extends Controller
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
report($e);
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Product']));
}

View File

@ -105,6 +105,7 @@ class ReviewController extends Controller
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
report($e);
session()->flash('success', trans('admin::app.response.delete-failed', ['name' => 'Review']));
}

View File

@ -74,7 +74,8 @@ class ProductForm extends FormRequest
'sku' => ['required', 'unique:products,sku,' . $this->id, new \Webkul\Core\Contracts\Validations\Slug],
'images.*' => 'mimes:jpeg,jpg,bmp,png',
'special_price_from' => 'nullable|date',
'special_price_to' => 'nullable|date|after_or_equal:special_price_from'
'special_price_to' => 'nullable|date|after_or_equal:special_price_from',
'special_price' => ['nullable', new \Webkul\Core\Contracts\Validations\Decimal, 'lt:price']
]);
foreach ($product->getEditableAttributes() as $attribute) {

View File

@ -68,7 +68,7 @@ class ProductBundleOptionProductRepository extends Repository
}
}
if (! $haveIsDefaulFlag)
if (! $haveIsDefaulFlag && $data['is_required'])
$data['products'][key($data['products'])]['is_default'] = 1;
}
}

View File

@ -523,7 +523,7 @@ class Bundle extends AbstractType
*/
public function getAdditionalOptions($data)
{
$bundleOptionQuantities = $data['bundle_option_qty'];
$bundleOptionQuantities = $data['bundle_option_qty'] ?? [];
foreach ($data['bundle_options'] as $optionId => $optionProductIds) {
$option = $this->productBundleOptionRepository->find($optionId);
@ -535,12 +535,12 @@ class Bundle extends AbstractType
continue;
$optionProduct = $this->productBundleOptionProductRepository->find($optionProductId);
$qty = $data['bundle_option_qty'][$optionId] ?? $optionProduct->qty;
if (! isset($data['bundle_option_qty'][$optionId]))
$bundleOptionQuantities[$optionId] = $qty;
$labels[] = $qty . ' x ' . $optionProduct->product->name . ' ' . core()->currency($optionProduct->product->getTypeInstance()->getMinimalPrice());
}

View File

@ -7,16 +7,26 @@ use Webkul\Sales\Contracts\Order as OrderContract;
class Order extends Model implements OrderContract
{
protected $guarded = ['id', 'items', 'shipping_address', 'billing_address', 'customer', 'channel', 'payment', 'created_at', 'updated_at'];
protected $guarded = [
'id',
'items',
'shipping_address',
'billing_address',
'customer',
'channel',
'payment',
'created_at',
'updated_at',
];
protected $statusLabel = [
'pending' => 'Pending',
'pending' => 'Pending',
'pending_payment' => 'Pending Payment',
'processing' => 'Processing',
'completed' => 'Completed',
'canceled' => 'Canceled',
'closed' => 'Closed',
'fraud' => 'Fraud'
'processing' => 'Processing',
'completed' => 'Completed',
'canceled' => 'Canceled',
'closed' => 'Closed',
'fraud' => 'Fraud',
];
/**
@ -90,7 +100,7 @@ class Order extends Model implements OrderContract
{
return $this->hasMany(RefundProxy::modelClass());
}
/**
* Get the customer record associated with the order.
*/
@ -193,12 +203,12 @@ class Order extends Model implements OrderContract
{
if ($this->status == 'fraud')
return false;
foreach ($this->items as $item) {
if ($item->canInvoice())
return true;
}
return false;
}
@ -209,7 +219,7 @@ class Order extends Model implements OrderContract
{
if ($this->status == 'fraud')
return false;
foreach ($this->items as $item) {
if ($item->canCancel())
return true;
@ -225,7 +235,7 @@ class Order extends Model implements OrderContract
{
if ($this->status == 'fraud')
return false;
foreach ($this->items as $item) {
if ($item->qty_to_refund > 0)
return true;

View File

@ -12,6 +12,8 @@ class AddStoredFunctionToGetUrlPathOfCategory extends Migration
*/
public function up()
{
$dbPrefix = DB::getTablePrefix();
$functionSQL = <<< SQL
DROP FUNCTION IF EXISTS `get_url_path_of_category`;
CREATE FUNCTION get_url_path_of_category(
@ -21,7 +23,7 @@ class AddStoredFunctionToGetUrlPathOfCategory extends Migration
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE urlPath VARCHAR(255);
-- Category with id 1 is root by default
IF categoryId <> 1
@ -29,9 +31,9 @@ class AddStoredFunctionToGetUrlPathOfCategory extends Migration
SELECT
GROUP_CONCAT(parent_translations.slug SEPARATOR '/') INTO urlPath
FROM
categories AS node,
categories AS parent
JOIN category_translations AS parent_translations ON parent.id = parent_translations.category_id
${dbPrefix}categories AS node,
${dbPrefix}categories AS parent
JOIN ${dbPrefix}category_translations AS parent_translations ON parent.id = parent_translations.category_id
WHERE
node._lft >= parent._lft
AND node._rgt <= parent._rgt
@ -40,15 +42,15 @@ class AddStoredFunctionToGetUrlPathOfCategory extends Migration
AND parent_translations.locale = localeCode
GROUP BY
node.id;
IF urlPath IS NULL
THEN
SET urlPath = (SELECT slug FROM category_translations WHERE category_translations.category_id = categoryId);
SET urlPath = (SELECT slug FROM ${dbPrefix}category_translations WHERE ${dbPrefix}category_translations.category_id = categoryId);
END IF;
ELSE
SET urlPath = '';
END IF;
RETURN urlPath;
END;
SQL;

View File

@ -2,6 +2,7 @@
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
use Webkul\Category\Models\CategoryTranslation;
class AddTriggerToCategoryTranslations extends Migration
{
@ -15,11 +16,13 @@ class AddTriggerToCategoryTranslations extends Migration
*/
public function up()
{
$dbPrefix = DB::getTablePrefix();
$triggerBody = $this->getTriggerBody();
$insertTrigger = <<< SQL
CREATE TRIGGER %s
BEFORE INSERT ON category_translations
FOR EACH ROW
BEFORE INSERT ON ${dbPrefix}category_translations
FOR EACH ROW
BEGIN
$triggerBody
END;
@ -27,8 +30,8 @@ SQL;
$updateTrigger = <<< SQL
CREATE TRIGGER %s
BEFORE UPDATE ON category_translations
FOR EACH ROW
BEFORE UPDATE ON ${dbPrefix}category_translations
FOR EACH ROW
BEGIN
$triggerBody
END;
@ -59,20 +62,22 @@ SQL;
*/
private function getTriggerBody()
{
$dbPrefix = DB::getTablePrefix();
return <<<SQL
DECLARE parentUrlPath varchar(255);
DECLARE urlPath varchar(255);
-- Category with id 1 is root by default
IF NEW.category_id <> 1
THEN
SELECT
GROUP_CONCAT(parent_translations.slug SEPARATOR '/') INTO parentUrlPath
FROM
categories AS node,
categories AS parent
JOIN category_translations AS parent_translations ON parent.id = parent_translations.category_id
${dbPrefix}categories AS node,
${dbPrefix}categories AS parent
JOIN ${dbPrefix}category_translations AS parent_translations ON parent.id = parent_translations.category_id
WHERE
node._lft >= parent._lft
AND node._rgt <= parent._rgt
@ -81,16 +86,16 @@ SQL;
AND parent_translations.locale = NEW.locale
GROUP BY
node.id;
IF parentUrlPath IS NULL
IF parentUrlPath IS NULL
THEN
SET urlPath = NEW.slug;
ELSE
SET urlPath = concat(parentUrlPath, '/', NEW.slug);
END IF;
SET NEW.url_path = urlPath;
END IF;
SQL;

View File

@ -16,10 +16,11 @@ class AddTriggerToCategories extends Migration
public function up()
{
$triggerBody = $this->getTriggerBody();
$dbPrefix = DB::getTablePrefix();
$insertTrigger = <<< SQL
CREATE TRIGGER %s
AFTER INSERT ON categories
CREATE TRIGGER %s
AFTER INSERT ON ${dbPrefix}categories
FOR EACH ROW
BEGIN
$triggerBody
@ -27,8 +28,8 @@ class AddTriggerToCategories extends Migration
SQL;
$updateTrigger = <<< SQL
CREATE TRIGGER %s
AFTER UPDATE ON categories
CREATE TRIGGER %s
AFTER UPDATE ON ${dbPrefix}categories
FOR EACH ROW
BEGIN
$triggerBody
@ -60,39 +61,41 @@ SQL;
*/
private function getTriggerBody(): string
{
$dbPrefix = DB::getTablePrefix();
return <<< SQL
DECLARE urlPath VARCHAR(255);
DECLARE localeCode VARCHAR(255);
DECLARE done INT;
DECLARE curs CURSOR FOR (SELECT category_translations.locale
FROM category_translations
DECLARE curs CURSOR FOR (SELECT ${dbPrefix}category_translations.locale
FROM ${dbPrefix}category_translations
WHERE category_id = NEW.id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
IF EXISTS (
SELECT *
FROM category_translations
FROM ${dbPrefix}category_translations
WHERE category_id = NEW.id
)
THEN
OPEN curs;
SET done = 0;
REPEAT
REPEAT
FETCH curs INTO localeCode;
SELECT get_url_path_of_category(NEW.id, localeCode) INTO urlPath;
UPDATE category_translations
SET url_path = urlPath
WHERE category_translations.category_id = NEW.id;
UPDATE ${dbPrefix}category_translations
SET url_path = urlPath
WHERE ${dbPrefix}category_translations.category_id = NEW.id;
UNTIL done END REPEAT;
CLOSE curs;
END IF;
SQL;
}

View File

@ -16,10 +16,12 @@ class AlterTriggerCategoryTranslations extends Migration
public function up()
{
$triggerBody = $this->getTriggerBody();
$dbPrefix = DB::getTablePrefix();
$insertTrigger = <<< SQL
CREATE TRIGGER %s
BEFORE INSERT ON category_translations
FOR EACH ROW
BEFORE INSERT ON ${dbPrefix}category_translations
FOR EACH ROW
BEGIN
$triggerBody
END;
@ -27,8 +29,8 @@ SQL;
$updateTrigger = <<< SQL
CREATE TRIGGER %s
BEFORE UPDATE ON category_translations
FOR EACH ROW
BEFORE UPDATE ON ${dbPrefix}category_translations
FOR EACH ROW
BEGIN
$triggerBody
END;
@ -66,44 +68,46 @@ SQL;
*/
private function getTriggerBody()
{
$dbPrefix = DB::getTablePrefix();
return <<<SQL
DECLARE parentUrlPath varchar(255);
DECLARE urlPath varchar(255);
IF NOT EXISTS (
SELECT id
FROM categories
FROM ${dbPrefix}categories
WHERE
id = NEW.category_id
AND parent_id IS NULL
)
THEN
SELECT
GROUP_CONCAT(parent_translations.slug SEPARATOR '/') INTO parentUrlPath
FROM
categories AS node,
categories AS parent
JOIN category_translations AS parent_translations ON parent.id = parent_translations.category_id
${dbPrefix}categories AS node,
${dbPrefix}categories AS parent
JOIN ${dbPrefix}category_translations AS parent_translations ON parent.id = parent_translations.category_id
WHERE
node._lft >= parent._lft
AND node._rgt <= parent._rgt
AND node.id = (SELECT parent_id FROM categories WHERE id = NEW.category_id)
AND node.parent_id IS NOT NULL
AND node.id = (SELECT parent_id FROM ${dbPrefix}categories WHERE id = NEW.category_id)
AND node.parent_id IS NOT NULL
AND parent.parent_id IS NOT NULL
AND parent_translations.locale = NEW.locale
GROUP BY
node.id;
IF parentUrlPath IS NULL
IF parentUrlPath IS NULL
THEN
SET urlPath = NEW.slug;
ELSE
SET urlPath = concat(parentUrlPath, '/', NEW.slug);
END IF;
SET NEW.url_path = urlPath;
END IF;
SQL;

View File

@ -12,6 +12,8 @@ class AlterStoredFunctionUrlPathCategory extends Migration
*/
public function up()
{
$dbPrefix = DB::getTablePrefix();
$functionSQL = <<< SQL
DROP FUNCTION IF EXISTS `get_url_path_of_category`;
CREATE FUNCTION get_url_path_of_category(
@ -21,12 +23,12 @@ class AlterStoredFunctionUrlPathCategory extends Migration
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE urlPath VARCHAR(255);
IF NOT EXISTS (
SELECT id
FROM categories
SELECT id
FROM ${dbPrefix}categories
WHERE
id = categoryId
AND parent_id IS NULL
@ -35,9 +37,9 @@ class AlterStoredFunctionUrlPathCategory extends Migration
SELECT
GROUP_CONCAT(parent_translations.slug SEPARATOR '/') INTO urlPath
FROM
categories AS node,
categories AS parent
JOIN category_translations AS parent_translations ON parent.id = parent_translations.category_id
${dbPrefix}categories AS node,
${dbPrefix}categories AS parent
JOIN ${dbPrefix}category_translations AS parent_translations ON parent.id = parent_translations.category_id
WHERE
node._lft >= parent._lft
AND node._rgt <= parent._rgt
@ -47,15 +49,15 @@ class AlterStoredFunctionUrlPathCategory extends Migration
AND parent_translations.locale = localeCode
GROUP BY
node.id;
IF urlPath IS NULL
THEN
SET urlPath = (SELECT slug FROM category_translations WHERE category_translations.category_id = categoryId);
SET urlPath = (SELECT slug FROM ${dbPrefix}category_translations WHERE ${dbPrefix}category_translations.category_id = categoryId);
END IF;
ELSE
SET urlPath = '';
END IF;
RETURN urlPath;
END;
SQL;

View File

@ -18,10 +18,11 @@ class AlterTriggerOnCategories extends Migration
public function up()
{
$triggerBody = $this->getTriggerBody();
$dbPrefix = DB::getTablePrefix();
$insertTrigger = <<< SQL
CREATE TRIGGER %s
AFTER INSERT ON categories
CREATE TRIGGER %s
AFTER INSERT ON ${dbPrefix}categories
FOR EACH ROW
BEGIN
$triggerBody
@ -29,8 +30,8 @@ class AlterTriggerOnCategories extends Migration
SQL;
$updateTrigger = <<< SQL
CREATE TRIGGER %s
AFTER UPDATE ON categories
CREATE TRIGGER %s
AFTER UPDATE ON ${dbPrefix}categories
FOR EACH ROW
BEGIN
$triggerBody
@ -68,46 +69,48 @@ SQL;
*/
private function getTriggerBody(): string
{
$dbPrefix = DB::getTablePrefix();
return <<< SQL
DECLARE urlPath VARCHAR(255);
DECLARE localeCode VARCHAR(255);
DECLARE done INT;
DECLARE curs CURSOR FOR (SELECT category_translations.locale
FROM category_translations
DECLARE curs CURSOR FOR (SELECT ${dbPrefix}category_translations.locale
FROM ${dbPrefix}category_translations
WHERE category_id = NEW.id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
IF EXISTS (
SELECT *
FROM category_translations
FROM ${dbPrefix}category_translations
WHERE category_id = NEW.id
)
THEN
OPEN curs;
SET done = 0;
REPEAT
REPEAT
FETCH curs INTO localeCode;
SELECT get_url_path_of_category(NEW.id, localeCode) INTO urlPath;
IF NEW.parent_id IS NULL
IF NEW.parent_id IS NULL
THEN
SET urlPath = '';
END IF;
UPDATE category_translations
SET url_path = urlPath
WHERE
category_translations.category_id = NEW.id
AND category_translations.locale = localeCode;
UPDATE ${dbPrefix}category_translations
SET url_path = urlPath
WHERE
${dbPrefix}category_translations.category_id = NEW.id
AND ${dbPrefix}category_translations.locale = localeCode;
UNTIL done END REPEAT;
CLOSE curs;
END IF;
SQL;
}

View File

@ -182,6 +182,8 @@ class CartController extends Controller
'message' => trans('shop::app.checkout.total.invalid-coupon')
]);
} catch (\Exception $e) {
report($e);
return response()->json([
'success' => false,
'message' => trans('shop::app.checkout.total.coupon-apply-issue')

View File

@ -75,6 +75,7 @@ class SubscriptionController extends Controller
session()->flash('success', trans('shop::app.subscription.subscribed'));
} catch (\Exception $e) {
report($e);
session()->flash('error', trans('shop::app.subscription.not-subscribed'));
$mailSent = false;

View File

@ -1,6 +1,7 @@
<?php
return [
'invalid_vat_format' => 'The given vat id has a wrong format',
'security-warning' => 'Suspicious activity found!!!',
'nothing-to-delete' => 'Nothing to delete',
@ -219,6 +220,10 @@ return [
'create' => [
'page-title' => 'Add Address Form',
'company_name' => 'Company name',
'first_name' => 'First name',
'last_name' => 'Last name',
'vat_id' => 'Vat id',
'title' => 'Add Address',
'street-address' => 'Street Address',
'country' => 'Country',
@ -234,6 +239,10 @@ return [
'edit' => [
'page-title' => 'Edit Address',
'company_name' => 'Company name',
'first_name' => 'First name',
'last_name' => 'Last name',
'vat_id' => 'Vat id',
'title' => 'Edit Address',
'street-address' => 'Street Address',
'submit' => 'Save Address',

View File

@ -19,13 +19,32 @@
{!! view_render_event('bagisto.shop.customers.account.address.create.before') !!}
<form method="post" action="{{ route('customer.address.create') }}" @submit.prevent="onSubmit">
<form id="customer-address-form" method="post" action="{{ route('customer.address.create') }}" @submit.prevent="onSubmit">
<div class="account-table-content">
@csrf
{!! view_render_event('bagisto.shop.customers.account.address.create_form_controls.before') !!}
<div class="control-group" :class="[errors.has('company_name') ? 'has-error' : '']">
<label for="company_name">{{ __('shop::app.customer.account.address.create.company_name') }}</label>
<input value="<?= old('company_name'); ?>" type="text" class="control" name="company_name" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.company_name') }}&quot;">
<span class="control-error" v-if="errors.has('company_name')">@{{ errors.first('company_name') }}</span>
</div>
<div class="control-group {!! $errors->has('vat_id') ? 'has-error' : '' !!}">
<label for="vat_id">{{ __('shop::app.customer.account.address.create.vat_id') }}</label>
<input type="text" class="control" name="vat_id"
value="<?= old('vat_id'); ?>"
data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.vat_id') }}&quot;">
<span class="control-error" v-if="{!! $errors->has('vat_id') !!}">
@foreach ($errors->get('vat_id') as $message)
{{ $message }}
@endforeach
</span>
</div>
<div class="control-group" :class="[errors.has('address1[]') ? 'has-error' : '']">
<label for="address_0" class="required">{{ __('shop::app.customer.account.address.create.street-address') }}</label>
<input type="text" class="control" name="address1[]" id="address_0" v-validate="'required'" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.street-address') }}&quot;">
@ -44,19 +63,19 @@
<div class="control-group" :class="[errors.has('city') ? 'has-error' : '']">
<label for="city" class="required">{{ __('shop::app.customer.account.address.create.city') }}</label>
<input type="text" class="control" name="city" v-validate="'required'" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.city') }}&quot;">
<input value="<?= old('city'); ?>" type="text" class="control" name="city" v-validate="'required'" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.city') }}&quot;">
<span class="control-error" v-if="errors.has('city')">@{{ errors.first('city') }}</span>
</div>
<div class="control-group" :class="[errors.has('postcode') ? 'has-error' : '']">
<label for="postcode" class="required">{{ __('shop::app.customer.account.address.create.postcode') }}</label>
<input type="text" class="control" name="postcode" v-validate="'required'" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.postcode') }}&quot;">
<input value="<?= old('postcode'); ?>" type="text" class="control" name="postcode" v-validate="'required'" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.postcode') }}&quot;">
<span class="control-error" v-if="errors.has('postcode')">@{{ errors.first('postcode') }}</span>
</div>
<div class="control-group" :class="[errors.has('phone') ? 'has-error' : '']">
<label for="phone" class="required">{{ __('shop::app.customer.account.address.create.phone') }}</label>
<input type="text" class="control" name="phone" v-validate="'required'" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.phone') }}&quot;">
<input value="<?= old('phone'); ?>" type="text" class="control" name="phone" v-validate="'required'" data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.phone') }}&quot;">
<span class="control-error" v-if="errors.has('phone')">@{{ errors.first('phone') }}</span>
</div>

View File

@ -18,8 +18,8 @@
</div>
{!! view_render_event('bagisto.shop.customers.account.address.edit.before', ['address' => $address]) !!}
<form method="post" action="{{ route('customer.address.edit', $address->id) }}" @submit.prevent="onSubmit">
<form id="customer-address-form" method="post" action="{{ route('customer.address.edit', $address->id) }}" @submit.prevent="onSubmit">
<div class="account-table-content">
@method('PUT')
@ -27,6 +27,24 @@
{!! view_render_event('bagisto.shop.customers.account.address.edit_form_controls.before', ['address' => $address]) !!}
<div class="control-group" :class="[errors.has('company_name') ? 'has-error' : '']">
<label for="company_name">{{ __('shop::app.customer.account.address.edit.company_name') }}</label>
<input type="text" value="{{ $address->company_name }}" class="control" name="company_name" data-vv-as="&quot;{{ __('shop::app.customer.account.address.edit.company_name') }}&quot;">
<span class="control-error" v-if="errors.has('company_name')">@{{ errors.first('company_name') }}</span>
</div>
<div class="control-group {!! $errors->has('vat_id') ? 'has-error' : '' !!}">
<label for="vat_id">{{ __('shop::app.customer.account.address.create.vat_id') }}</label>
<input type="text" class="control" name="vat_id"
value="{{ $address->vat_id }}"
data-vv-as="&quot;{{ __('shop::app.customer.account.address.create.vat_id') }}&quot;">
<span class="control-error" v-if="{!! $errors->has('vat_id') !!}">
@foreach ($errors->get('vat_id') as $message)
{{ $message }}
@endforeach
</span>
</div>
<?php $addresses = explode(PHP_EOL, $address->address1); ?>

View File

@ -6,95 +6,108 @@
@section('content-wrapper')
<div class="account-content">
<div class="account-content">
@include('shop::customers.account.partials.sidemenu')
@include('shop::customers.account.partials.sidemenu')
<div class="account-layout">
<div class="account-layout">
<div class="account-head">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading">{{ __('shop::app.customer.account.address.index.title') }}</span>
<div class="account-head">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i
class="icon icon-menu-back"></i></a></span>
<span
class="account-heading">{{ __('shop::app.customer.account.address.index.title') }}</span>
@if (! $addresses->isEmpty())
<span class="account-action">
@if (! $addresses->isEmpty())
<span class="account-action">
<a href="{{ route('customer.address.create') }}">{{ __('shop::app.customer.account.address.index.add') }}</a>
</span>
@else
<span></span>
@endif
<div class="horizontal-rule"></div>
</div>
@else
<span></span>
@endif
<div class="horizontal-rule"></div>
</div>
{!! view_render_event('bagisto.shop.customers.account.address.list.before', ['addresses' => $addresses]) !!}
{!! view_render_event('bagisto.shop.customers.account.address.list.before', ['addresses' => $addresses]) !!}
<div class="account-table-content">
@if ($addresses->isEmpty())
<div>{{ __('shop::app.customer.account.address.index.empty') }}</div>
<br/>
<a href="{{ route('customer.address.create') }}">{{ __('shop::app.customer.account.address.index.add') }}</a>
@else
<div class="address-holder">
@foreach ($addresses as $address)
<div class="address-card">
<div class="details">
<span class="bold">{{ auth()->guard('customer')->user()->name }}</span>
<ul class="address-card-list">
<li class="mt-5">
{{ $address->name }}
</li>
<div class="account-table-content">
@if ($addresses->isEmpty())
<div>{{ __('shop::app.customer.account.address.index.empty') }}</div>
<br/>
<a href="{{ route('customer.address.create') }}">{{ __('shop::app.customer.account.address.index.add') }}</a>
@else
<div class="address-holder">
@foreach ($addresses as $address)
<div class="address-card">
<div class="details">
<span
class="bold">{{ auth()->guard('customer')->user()->name }}</span>
<ul class="address-card-list">
<li class="mt-5">
{{ $address->company_name }}
</li>
<li class="mt-5">
{{ $address->address1 }},
</li>
<li class="mt-5">
{{ $address->first_name }}
</li>
<li class="mt-5">
{{ $address->city }}
</li>
<li class="mt-5">
{{ $address->last_name }}
</li>
<li class="mt-5">
{{ $address->state }}
</li>
<li class="mt-5">
{{ $address->address1 }},
</li>
<li class="mt-5">
{{ core()->country_name($address->country) }} {{ $address->postcode }}
</li>
<li class="mt-5">
{{ $address->city }}
</li>
<li class="mt-10">
{{ __('shop::app.customer.account.address.index.contact') }} : {{ $address->phone }}
</li>
</ul>
<li class="mt-5">
{{ $address->state }}
</li>
<div class="control-links mt-20">
<li class="mt-5">
{{ core()->country_name($address->country) }} {{ $address->postcode }}
</li>
<li class="mt-10">
{{ __('shop::app.customer.account.address.index.contact') }}
: {{ $address->phone }}
</li>
</ul>
<div class="control-links mt-20">
<span>
<a href="{{ route('customer.address.edit', $address->id) }}">
{{ __('shop::app.customer.account.address.index.edit') }}
</a>
</span>
<span>
<a href="{{ route('address.delete', $address->id) }}" onclick="deleteAddress('{{ __('shop::app.customer.account.address.index.confirm-delete') }}')">
<span>
<a href="{{ route('address.delete', $address->id) }}"
onclick="deleteAddress('{{ __('shop::app.customer.account.address.index.confirm-delete') }}')">
{{ __('shop::app.customer.account.address.index.delete') }}
</a>
</span>
</div>
</div>
</div>
</div>
@endforeach
</div>
@endif
</div>
@endforeach
</div>
@endif
</div>
{!! view_render_event('bagisto.shop.customers.account.address.list.after', ['addresses' => $addresses]) !!}
{!! view_render_event('bagisto.shop.customers.account.address.list.after', ['addresses' => $addresses]) !!}
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
function deleteAddress(message) {
if (!confirm(message))
event.preventDefault();
event.preventDefault();
}
</script>
@endpush

View File

@ -42,13 +42,10 @@
@endif
<?php
$query = parse_url(\Illuminate\Support\Facades\Request::path(), PHP_URL_QUERY);
$searchTerm = explode("&", $query);
$term = request()->input('term');
foreach($searchTerm as $term){
if (strpos($term, 'term') !== false) {
$serachQuery = $term;
}
if (! is_null($term)) {
$serachQuery = 'term='.request()->input('term');
}
?>

View File

@ -29,13 +29,10 @@
</div>
<?php
$query = parse_url(\Illuminate\Support\Facades\Request::path(), PHP_URL_QUERY);
$searchTerm = explode("&", $query);
$term = request()->input('term');
foreach($searchTerm as $term){
if (strpos($term, 'term') !== false) {
$serachQuery = $term;
}
if (! is_null($term)) {
$serachQuery = 'term='.request()->input('term');
}
?>

View File

@ -182,7 +182,7 @@
data: function() {
return {
selected_product: (this.option.type == 'checkbox' || this.option.type == 'multiselect') ? [] : null,
qty_validations: ''
}
},

View File

@ -282,6 +282,7 @@ class TaxRateController extends Controller
}
}
} catch (\Exception $e) {
report($e);
$failure = new Failure(1, 'rows', [0 => trans('admin::app.export.enough-row-error')]);
session()->flash('error', $failure->errors()[0]);

View File

@ -16,7 +16,10 @@
"jquery": "^3.4.1",
"laravel-mix": "^5.0.0",
"laravel-mix-merge-manifest": "^0.1.2",
"vue": "^2.6.10"
"sass": "^1.24.4",
"sass-loader": "^8.0.2",
"vue": "^2.6.10",
"vue-template-compiler": "^2.6.11"
},
"dependencies": {
"@babel/polyfill": "^7.7.0",

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/ui.js": "/js/ui.js?id=ed9978ac7d054203f0bc",
"/js/ui.js": "/js/ui.js?id=d6802d7d61cdbdfc21e5",
"/css/ui.css": "/css/ui.css?id=0895b560bbc19259cee8"
}

View File

@ -14,6 +14,7 @@ import ImageUpload from './components/image/image-upload';
import ImageWrapper from './components/image/image-wrapper';
import ImageItem from './components/image/image-item';
import Slugify from './directives/slugify';
import SlugifyTarget from './directives/slugify-target';
import Code from './directives/code';
import Alert from './directives/alert';
import DatetimeComponent from './components/datetime';
@ -35,6 +36,7 @@ Vue.component('image-upload', ImageUpload);
Vue.component('image-wrapper', ImageWrapper);
Vue.component('image-item', ImageItem);
Vue.directive('slugify', Slugify);
Vue.directive('slugify-target', SlugifyTarget);
Vue.directive('code', Code);
Vue.directive('alert', Alert);
Vue.component('datetime', DatetimeComponent);

View File

@ -0,0 +1,24 @@
<script>
export default {
bind(el, binding, vnode) {
let handler = function (e) {
setTimeout(function () {
var target = document.getElementById(binding.value);
target.value = e.target.value.toString()
.toLowerCase()
.replace(/[^\w- ]+/g, '')
// replace whitespaces with dashes
.replace(/ +/g, '-')
// avoid having multiple dashes (---- translates into -)
.replace('![-\s]+!u', '-')
.trim();
}, 100);
};
el.addEventListener('input', handler);
}
}
</script>

View File

@ -2,6 +2,7 @@
namespace Webkul\User\Database\Seeders;
use Illuminate\Support\Str;
use Illuminate\Database\Seeder;
use DB;
@ -16,6 +17,9 @@ class AdminsTableSeeder extends Seeder
'name' => 'Example',
'email' => 'admin@example.com',
'password' => bcrypt('admin123'),
'api_token' => Str::random(80),
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
'status' => 1,
'role_id' => 1,
]);

View File

@ -2,6 +2,7 @@
namespace Webkul\User\Http\Controllers;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Event;
use Webkul\User\Repositories\AdminRepository;
use Webkul\User\Repositories\RoleRepository;
@ -90,8 +91,10 @@ class UserController extends Controller
{
$data = $request->all();
if (isset($data['password']) && $data['password'])
if (isset($data['password']) && $data['password']) {
$data['password'] = bcrypt($data['password']);
$data['api_token'] = Str::random(80);
}
Event::dispatch('user.admin.create.before');
@ -130,10 +133,11 @@ class UserController extends Controller
{
$data = $request->all();
if (! $data['password'])
if (! $data['password']) {
unset($data['password']);
else
} else {
$data['password'] = bcrypt($data['password']);
}
if (isset($data['status'])) {
$data['status'] = 1;

View File

@ -19,7 +19,7 @@ class Admin extends Authenticatable implements AdminContract
* @var array
*/
protected $fillable = [
'name', 'email', 'password', 'role_id', 'status',
'name', 'email', 'password', 'api_token', 'role_id', 'status',
];
/**
@ -28,7 +28,7 @@ class Admin extends Authenticatable implements AdminContract
* @var array
*/
protected $hidden = [
'password', 'remember_token',
'password', 'api_token', 'remember_token',
];
/**

View File

@ -28,15 +28,15 @@
<label for="mail_from" class="required">Store email address</label>
<input type="text" name="mail_from" class="control" placeholder="store@example.com" data-validation="required">
</div>
<div class="control-group" id="mail_username">
<label for="mail_username" class="required">Username</label>
<input type="text" name="mail_username" class="control" placeholder="store@example.com" data-validation="required">
</div>
<div class="control-group" id="mail_password">
<label for="mail_password" class="required">Password</label>
<input type="password" name="mail_password" class="control" data-validation="length required" data-validation-length="min6">
<input type="password" name="mail_password" class="control">
</div>
</div>
</div>
@ -71,7 +71,7 @@
var EmailTarget = window.location.href.concat('/EmailConfig.php');
$.ajax({type : 'POST', url : EmailTarget, data : mailformData, dataType : 'json', encode : true})
$.ajax({type : 'POST', url : EmailTarget, data : mailformData, dataType : 'json', encode : true})
.done(function(data) {
if (!data.success) {
// handle errors
@ -112,7 +112,7 @@
} else {
$('#admin').hide();
$('#email').hide();
$('#finish').show();
$('#finish').show();
}
});
// stop the form from submitting the normal way and refreshing the page

View File

@ -25,15 +25,7 @@
<img class="logo" src= "<?php echo $logo; ?>" >
</div>
<div class="footer">
<img class="left-patern" src= "<?php echo $leftIcon; ?>" >
<img class="right-patern" src= "<?php echo $rightIcon; ?>" >
<div>
Powered by <a href="https://bagisto.com/" target="_blank" style="color: blue">Bagisto</a>, A Community Project by
<a href="https://webkul.com/" target="_blank" style="color: blue">Webkul</a>
</div>
</div>
</div>
<?php
@ -142,5 +134,10 @@
}
?>
<div style="margin-bottom: 10px; margin-top: 10px;">
Powered by <a href="https://bagisto.com/" target="_blank" style="color: blue">Bagisto</a>, A Community Project by
<a href="https://webkul.com/" target="_blank" style="color: blue">Webkul</a>
</div>
</body>
</html>

0
storage/app/db-blade-compiler/views/.gitignore vendored Executable file → Normal file
View File

View File

@ -5,7 +5,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use Webkul\User\Models\Admin;
use Webkul\Customer\Models\Customer;
/**
* Inherited Methods
@ -31,26 +31,65 @@ class FunctionalTester extends \Codeception\Actor
*/
/**
* Login as default administrator
* Set the logged in user to the admin identity.
*
* @param \Webkul\User\Models\Admin|null $admin
*
* @throws \Exception
* @returns Admin
*/
public function loginAsAdmin(): void
public function loginAsAdmin(Admin $admin = null): Admin
{
$I = $this;
Auth::guard('admin')->login($I->grabRecord(Admin::class, ['email' => 'admin@example.com']));
if (! $admin) {
$admin = $I->grabRecord(Admin::class, ['email' => 'admin@example.com']);
}
if (! $admin) {
throw new \Exception(
'Admin user not found in database. Please ensure Seeders are executed');
}
Auth::guard('admin')
->login($admin);
$I->seeAuthentication('admin');
return $admin;
}
/**
* Go to a specific route and check if admin guard is applied on it
* Set the logged in user to the customer identity.
*
* @param string $name name of the route
* @param array|null $params params the route will be created with
* @param \Webkul\User\Models\Customer|null $customer
*
* @throws \Exception
* @returns Customer
*/
public function amOnAdminRoute(string $name, array $params = null): void
public function loginAsCustomer(Customer $customer = null): Customer
{
$I = $this;
$I->amOnRoute($name, $params);
if (! $customer) {
$customer = $I->have(Customer::class);
}
Auth::guard('customer')
->login($customer);
$I->seeAuthentication('customer');
return $customer;
}
/**
* @param string $name
*/
public function amOnAdminRoute(string $name)
{
$I = $this;
$I->amOnRoute($name);
$I->seeCurrentRouteIs($name);
/** @var RouteCollection $routes */

View File

@ -2,12 +2,10 @@
namespace Tests\Functional\Admin\Sales;
use FunctionalTester;
use Webkul\Sales\Models\Invoice;
use Webkul\Sales\Models\OrderAddress;
class InvoiceCest
{
public function testIndex(FunctionalTester $I): void
@ -16,7 +14,7 @@ class InvoiceCest
$invoice = $I->have(Invoice::class,
[
'order_id' => $orderAddress->order_id,
'order_address_id' => $orderAddress->id
'order_address_id' => $orderAddress->id,
]);
$I->loginAsAdmin();

View File

@ -0,0 +1,125 @@
<?php
use Webkul\Customer\Models\Customer;
use Webkul\Customer\Models\CustomerAddress;
class CustomerCest
{
public $fields = [];
public function updateCustomerProfile(FunctionalTester $I)
{
$customer = $I->loginAsCustomer();
$I->amOnPage('/');
$I->click('Profile');
$I->click('Edit');
$I->selectOption('gender', 'Other');
$I->click('Update Profile');
$I->dontSeeInSource('The old password does not match.');
$I->seeInSource('Profile updated successfully.');
$I->seeRecord(Customer::class, [
'id' => $customer->id,
'gender' => 'Other',
]);
}
public function updateCustomerAddress(FunctionalTester $I)
{
$I->wantTo('Instantiate a european faker factory to have the vat provider available');
$faker = Faker\Factory::create('at_AT');
$formCssSelector = '#customer-address-form';
$I->loginAsCustomer();
$I->amOnPage('/');
$I->click('Profile');
$I->click('Address');
$I->click('Add Address');
$this->fields = [
'company_name' => $faker->company,
'vat_id' => 'INVALIDVAT',
'address1[]' => $faker->streetAddress,
'country' => $faker->countryCode,
'state' => $faker->state,
'city' => $faker->city,
'postcode' => $faker->postcode,
'phone' => $faker->phoneNumber,
];
foreach ($this->fields as $key => $value) {
// the following fields are being rendered via javascript so we ignore them:
if (! in_array($key, [
'country',
'state',
])) {
$selector = 'input[name="' . $key . '"]';
$I->fillField($selector, $value);
}
}
$I->wantTo('Ensure that the company_name field is being displayed');
$I->seeElement('.account-table-content > div:nth-child(2) > input:nth-child(2)');
// we need to use this css selector to hit the correct <form>. There is another one at the
// page header (search)
$I->submitForm($formCssSelector, $this->fields);
$I->seeInSource('The given vat id has a wrong format');
$I->wantTo('enter a valid vat id');
$this->fields['vat_id'] = $faker->vat(false);
$I->submitForm($formCssSelector, $this->fields);
$I->seeInSource('Address have been successfully added.');
$this->assertCustomerAddress($I);
$I->wantTo('Update the created customer address again');
$I->click('Edit');
$oldcompany = $this->fields['company_name'];
$this->fields['company_name'] = $faker->company;
$I->submitForm($formCssSelector, $this->fields);
$I->seeInSource('Address updated successfully.');
$I->dontSeeRecord(CustomerAddress::class, [
'company_name' => $oldcompany,
]);
$this->assertCustomerAddress($I);
}
/**
* @param \FunctionalTester $I
* @param array $fields
*/
private function assertCustomerAddress(FunctionalTester $I): void
{
$I->seeRecord(CustomerAddress::class, [
'company_name' => $this->fields['company_name'],
'vat_id' => $this->fields['vat_id'],
'address1' => $this->fields['address1[]'],
'country' => $this->fields['country'],
'state' => $this->fields['state'],
'city' => $this->fields['city'],
'phone' => $this->fields['phone'],
'postcode' => $this->fields['postcode'],
]);
}
}