New repo with base sync

This commit is contained in:
Prashant Singh 2019-06-22 01:02:33 +05:30
parent 754d99d3ba
commit 6fd67e56d7
362 changed files with 17088 additions and 6 deletions

View File

@ -31,6 +31,8 @@ class Kernel extends HttpKernel
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Webkul\SAASCustomizer\Http\Middleware\ValidatesDomain::class,
\Webkul\ShowPriceAfterLogin\Http\Middleware\ShowShopAfterLogin::class
],
'api' => [

View File

@ -20,6 +20,7 @@
"doctrine/dbal": "^2.9@dev",
"fideloper/proxy": "^4.0",
"flynsarmy/db-blade-compiler": "*",
"guzzlehttp/guzzle": "^6.3@dev",
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
"kalnoy/nestedset": "^4.3",
@ -30,6 +31,7 @@
"nwidart/laravel-modules": "^3.2",
"prettus/l5-repository": "^2.6",
"propaganistas/laravel-intl": "^2.0",
"stripe/stripe-php": "6.0",
"tymon/jwt-auth": "dev-develop"
},
"require-dev": {
@ -88,7 +90,16 @@
"Webkul\\Sales\\": "packages/Webkul/Sales/src",
"Webkul\\Tax\\": "packages/Webkul/Tax/src",
"Webkul\\API\\": "packages/Webkul/API",
"Webkul\\Discount\\": "packages/Webkul/Discount/src"
"Webkul\\Discount\\": "packages/Webkul/Discount/src",
"Webkul\\CustomerDocument\\": "packages/Webkul/CustomerDocument",
"Webkul\\BulkAddToCart\\": "packages/Webkul/BulkAddToCart",
"Webkul\\SAASCustomizer\\": "packages/Webkul/SAASCustomizer/src",
"Webkul\\AdminAuthCheck\\": "packages/Webkul/AdminAuthCheck/src",
"Webkul\\StripeConnect\\": "packages/Webkul/StripeConnect/src",
"Webkul\\CustomerCreditMax\\": "packages/Webkul/CustomerCreditMax",
"Webkul\\CustomerGroupCatalog\\": "packages/Webkul/CustomerGroupCatalog",
"Webkul\\ShowPriceAfterLogin\\": "packages/Webkul/ShowPriceAfterLogin/src",
"Webkul\\SAASPreOrder\\": "packages/Webkul/SAASPreOrder/src"
}
},
"autoload-dev": {

View File

@ -52,7 +52,7 @@ return [
|
*/
'url' => env('APP_URL', 'http://localhost'),
'url' => env('APP_URL', 'http://bagsaas.com'),
/*
|--------------------------------------------------------------------------
@ -245,7 +245,16 @@ return [
Webkul\Sales\Providers\SalesServiceProvider::class,
Webkul\Tax\Providers\TaxServiceProvider::class,
Webkul\API\Providers\APIServiceProvider::class,
Webkul\Discount\Providers\DiscountServiceProvider::class
Webkul\Discount\Providers\DiscountServiceProvider::class,
Webkul\CustomerDocument\Providers\CustomerDocumentServiceProvider::class,
Webkul\BulkAddToCart\Providers\BulkAddToCartServiceProvider::class,
Webkul\AdminAuthCheck\Providers\AdminAuthCheckServiceProvider::class,
Webkul\StripeConnect\Providers\StripeConnectServiceProvider::class,
Webkul\CustomerGroupCatalog\Providers\CustomerGroupCatalogServiceProvider::class,
// Webkul\ShowPriceAfterLogin\Providers\ShowPriceAfterLoginServiceProvider::class,
Webkul\CustomerCreditMax\Providers\CustomerCreditMaxServiceProvider::class,
Webkul\SAASPreOrder\Providers\SAASPreOrderServiceProvider::class,
Webkul\SAASCustomizer\Providers\SAASCustomizerServiceProvider::class
],
/*
@ -304,5 +313,6 @@ return [
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
'Concord' => Konekt\Concord\Facades\Concord::class,
'Helper' => Konekt\Concord\Facades\Helper::class,
'Company' => Webkul\SAASCustomizer\Facades\Company::class
],
];

View File

@ -27,6 +27,11 @@ return [
'provider' => 'admins'
],
'super-admin' => [
'driver' => 'session',
'provider' => 'superadmins'
],
'admin-api' => [
'driver' => 'token',
'provider' => 'admins',
@ -42,6 +47,11 @@ return [
'admins' => [
'driver' => 'eloquent',
'model' => Webkul\User\Models\Admin::class,
],
'superadmins' => [
'driver' => 'eloquent',
'model' => Webkul\SAASCustomizer\Models\SuperAdmin::class
]
],
@ -57,4 +67,4 @@ return [
'expire' => 60,
],
],
];
];

View File

@ -15,8 +15,12 @@ return [
\Webkul\Core\Providers\ModuleServiceProvider::class,
\Webkul\Customer\Providers\ModuleServiceProvider::class,
\Webkul\Inventory\Providers\ModuleServiceProvider::class,
\Webkul\Product\Providers\ModuleServiceProvider::class,\Webkul\Sales\Providers\ModuleServiceProvider::class,
\Webkul\Product\Providers\ModuleServiceProvider::class,
\Webkul\Sales\Providers\ModuleServiceProvider::class,
\Webkul\Tax\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,\Webkul\Discount\Providers\ModuleServiceProvider::class
\Webkul\User\Providers\ModuleServiceProvider::class,
\Webkul\Discount\Providers\ModuleServiceProvider::class,
\Webkul\StripeConnect\Providers\ModuleServiceProvider::class,
\Webkul\SAASPreOrder\Providers\ModuleServiceProvider::class
]
];

5
config/purge-pool.php Normal file
View File

@ -0,0 +1,5 @@
<?php
return [
];

View File

@ -0,0 +1,27 @@
{
"name": "bagisto/laravel-AdminAuthCheck",
"license": "MIT",
"authors": [
{
"name": "Prashant Singh",
"email": "prashant.singh852@webkul.com"
}
],
"require": {
"konekt/concord": "^1.2"
},
"autoload": {
"psr-4": {
"Webkul\\AdminAuthCheck\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Webkul\\AdminAuthCheck\\Providers\\AdminAuthCheckServiceProvider"
],
"aliases": {}
}
},
"minimum-stability": "dev"
}

View File

@ -0,0 +1,33 @@
<?php
namespace Webkul\CustomerCustomizer\Http\Controllers;
use Webkul\CustomerCustomizer\Http\Controllers\Controller;
use Company;
/**
* Customer Approval controller
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CustomerApprovalController extends Controller
{
protected $_config;
public function __construct()
{
$this->_config = request('_config');
}
public function index()
{
}
public function approve()
{
dd('approving the newly created customer');
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace Webkul\AdminAuthCheck\Listeners;
use Company;
use Webkul\SAASCustomizer\Repositories\SuperAdminRepository as SuperAdmin;
/**
* Login Authentication Attempt Event handler
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class LoginAuthenticationAttempt
{
protected $superAdmin;
public function __construct(SuperAdmin $superAdmin) {
$this->superAdmin = $superAdmin;
}
public function handle()
{
$company = Company::getCurrent();
if (! auth()->guard('super-admin')->check()) {
$credentials = request()->all();
$credentials['company_id'] = $company->id;
unset($credentials['_token']);
if (auth()->guard('admin')->check()) {
$admin = auth()->guard('admin')->user();
if (Company::getCurrent()->id != $admin->company_id) {
auth()->guard('admin')->logout();
throw new \Exception('invalid_admin_login', 400);
}
} else if (auth()->guard('customer')->check()) {
$customer = auth()->guard('customer')->user();
if (Company::getCurrent()->id != $customer->company_id) {
auth()->guard('customer')->logout();
if (! auth()->guard('customer')->attempt($credentials)) {
throw new \Exception('invalid_customer_login', 400);
}
}
}
}
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Webkul\AdminAuthCheck\Providers;
use Illuminate\Support\ServiceProvider;
use Webkul\AdminAuthCheck\Providers\EventServiceProvider;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Webkul\SAASCustomizer\Exceptions\Handler;
use Illuminate\Routing\Router;
// use Webkul\Sales\Providers\ModuleServiceProvider;
class AdminAuthCheckServiceProvider extends ServiceProvider
{
public function boot(Router $router)
{
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
$this->app->bind(
ExceptionHandler::class,
Handler::class
);
// $this->app->register(ModuleServiceProvider::class);
}
public function register()
{
$this->app->register(EventServiceProvider::class);
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Webkul\AdminAuthCheck\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Auth\Events\Authenticated' => [
'Webkul\AdminAuthCheck\Listeners\LoginAuthenticationAttempt'
], // make use of this to stop admins logging into other sites
];
}

View File

@ -0,0 +1,11 @@
<?php
namespace Webkul\AdminAuthCheck\Providers;
use Konekt\Concord\AbstractModuleServiceProvider;
class ModuleServiceProvider extends AbstractModuleServiceProvider
{
protected $models = [
];
}

View File

@ -0,0 +1,5 @@
<?php
return [
'set-category-visibility' => 'Set Category Visibility',
];

View File

@ -0,0 +1,2 @@
<?php

View File

@ -0,0 +1,24 @@
{
"name": "bagisto/bulk-add-to-cart",
"license": "MIT",
"authors": [
{
"name": "Rahul Shukla",
"email": "rahulshukla517@webkul.com"
}
],
"autoload": {
"psr-4": {
"Webkul\\BulkAddToCart\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Webkul\\BulkAddToCart\\BulkAddToCartServiceProvider"
],
"aliases": {}
}
},
"minimum-stability": "dev"
}

View File

@ -0,0 +1,12 @@
<?php
return [
[
'key' => 'account.bulk-add-to-cart',
'name' => 'bulkaddtocart::app.products.bulk-add-to-cart',
'route' =>'cart.bulk-add-to-cart.create',
'sort' => 7
]
];
?>

View File

@ -0,0 +1,170 @@
<?php
namespace Webkul\BulkAddToCart\Http\Controllers;
use Webkul\Admin\Imports\DataGridImport;
use Webkul\Product\Repositories\ProductRepository as Product;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Event;
use Maatwebsite\Excel\Validators\Failure;
use Illuminate\Support\Facades\Storage;
use Excel;
use Cart;
/**
* BulkAddToCart controlller
*
* @author Rahul Shukla <rahulshukla.symfony517@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class BulkAddToCartController extends Controller
{
/**
* Contains route related configuration
*
* @var array
*/
protected $_config;
/**
* ProductRepository object
*
* @var array
*/
protected $product;
/**
* Create a new controller instance.
*
* @param \Webkul\Product\Repositories\ProductRepository $product
* @return void
*/
public function __construct(Product $product)
{
$this->product = $product;
$this->_config = request('_config');
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view($this->_config['view']);
}
/**
* Store a newly created resource in storage.
*
* @return \Illuminate\Http\Response
*/
public function store()
{
$valid_extension = ['xlsx', 'csv', 'xls', 'ods'];
if (! in_array(request()->file('file')->getClientOriginalExtension(), $valid_extension)) {
session()->flash('error', trans('bulkaddtocart::app.products.upload-error'));
return redirect()->back();
} else {
try {
$excelData = (new DataGridImport)->toArray(request()->file('file'));
$cart = [];
foreach ($excelData as $data) {
foreach ($data as $column => $uploadData) {
$validator = Validator::make($uploadData, [
'sku' => 'required',
'quantity' => 'required|numeric|min:1',
]);
$product = $this->product->findOneWhere([
'sku' => $uploadData['sku'],
]);
if ($product) {
$canAdd = $product->haveSufficientQuantity($uploadData['quantity']);
if (! $canAdd) {
$sufficientQuantity[] = $column + 1;
} else if($product->type == 'simple' && $uploadData['quantity'] > 0) {
$cart['product'] = (string)$product->id;
$cart['quantity'] = (string)$uploadData['quantity'];
$cart['is_configurable'] = 'false';
Event::fire('checkout.cart.add.before', $cart['product']);
$result = Cart::add($cart['product'], $cart);
Event::fire('checkout.cart.add.after', $result);
Cart::collectTotals();
}
} else {
$skuError[] = $column + 1;
}
if ($validator->fails()) {
$failedRules[$column+1] = $validator->errors();
}
}
}
if (isset($failedRules)) {
foreach ($failedRules as $coulmn => $fail) {
if ($fail->first('sku')) {
$errorMsg[$coulmn] = $fail->first('sku');
} else if ($fail->first('quantity')) {
$errorMsg[$coulmn] = $fail->first('quantity');
}
}
foreach ($errorMsg as $key => $msg) {
$msg = str_replace(".", "", $msg);
$message[] = $msg. ' at Row ' .$key . '.';
}
$finalMsg[] = implode(" ", $message);
}
if (isset($skuError)) {
$errorRows = implode(",", $skuError);
$finalMsg[] = trans('bulkaddtocart::app.products.sku-error') . ' ' . $errorRows . '.';
}
if (isset($sufficientQuantity)) {
$errorRows = implode(",", $sufficientQuantity);
$finalMsg[] = trans('bulkaddtocart::app.products.quantity-error') . ' ' . $errorRows . '.';
}
if (isset($finalMsg)) {
$finalErrorMsg = implode(" ", $finalMsg);
session()->flash('error', $finalErrorMsg);
return redirect()->back();
} else {
session()->flash('success', trans('bulkaddtocart::app.products.upload-sucess'));
return redirect()->route($this->_config['redirect']);
}
} catch (\Exception $e) {
$failure = new Failure(1, 'rows', [0 => trans('bulkaddtocart::app.products.enough-row-error')]);
session()->flash('error', $failure->errors()[0]);
return redirect()->back();
}
}
}
/**
* Download Sample
*
* @return \Illuminate\Http\Response
*/
public function downLoadSample()
{
return Storage::download('sample/sample.xls');
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Webkul\BulkAddToCart\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@ -0,0 +1,22 @@
<?php
Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function () {
Route::prefix('customer')->group(function () {
Route::group(['middleware' => ['customer']], function () {
Route::get('bulk-add-to-cart', 'Webkul\BulkAddToCart\Http\Controllers\BulkAddToCartController@create')->defaults('_config', [
'view' => 'bulkaddtocart::products.bulk-add-to-cart'
])->name('cart.bulk-add-to-cart.create');
Route::post('bulk-add-to-cart', 'Webkul\BulkAddToCart\Http\Controllers\BulkAddToCartController@store')->defaults('_config', [
'redirect' => 'shop.checkout.cart.index'
])->name('cart.bulk-add-to-cart.store');
Route::get('download-sample', 'Webkul\BulkAddToCart\Http\Controllers\BulkAddToCartController@downLoadSample')->defaults('_config', [
'view' => 'bulkaddtocart::products.bulk-add-to-cart'
])->name('cart.bulk-add-to-cart.sample.download');
});
});
});

View File

@ -0,0 +1,45 @@
<?php
namespace Webkul\BulkAddToCart\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\Router;
class BulkAddToCartServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot(Router $router)
{
$this->loadRoutesFrom(__DIR__ . '/../Http/routes.php');
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'bulkaddtocart');
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'bulkaddtocart');
}
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->registerConfig();
}
/**
* Register package config.
*
* @return void
*/
protected function registerConfig()
{
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/menu.php', 'menu.customer'
);
}
}

View File

@ -0,0 +1,17 @@
<?php
return [
'products' => [
'bulk-add-to-cart' => 'Bulk Add to Cart',
'file' => 'File',
'submit' => 'Submit',
'upload-sucess' => 'Products Sucessfully added to Cart',
'quantity-error' => 'Products have not sufficient quantity at row',
'upload-error' => 'The file must be a file of type: xls, xlsx, csv, ods.',
'enough-row-error' => 'file has not enough rows',
'sku-error' => 'Invalid SKU at row',
'allowed-type' => 'Allowed Type :',
'file-type' => 'csv, xls, xlsx, ods.',
'download-sample' => 'Download Sample'
],
];

View File

@ -0,0 +1,50 @@
@extends('shop::layouts.master')
@section('page_title')
{{ __('bulkaddtocart::app.products.bulk-add-to-cart') }}
@endsection
@section('content-wrapper')
<div class="account-content">
@include('shop::customers.account.partials.sidemenu')
<div class="account-layout">
<div class="account-head mb-15">
<span class="account-heading">{{ __('bulkaddtocart::app.products.bulk-add-to-cart') }}</span>
<div class="horizontal-rule"></div>
</div>
<div class="account-items-list">
<form method="POST" action="{{ route('cart.bulk-add-to-cart.store') }}" enctype="multipart/form-data" @submit.prevent="onSubmit">
@csrf()
<div class="control-group" :class="[errors.has('file') ? 'has-error' : '']">
<label for="file" class="required">{{ __('bulkaddtocart::app.products.file') }}</label>
<input v-validate="'required'" type="file" class="control" id="file" name="file" data-vv-as="&quot;{{ __('bulkaddtocart::app.products.file') }}&quot;" value="{{ old('file') }}" style="padding-top: 5px"><br>
<span>{{ __('bulkaddtocart::app.products.allowed-type') }}</span>
<span><b>{{ __('bulkaddtocart::app.products.file-type') }}</b></span>
<span class="control-error" v-if="errors.has('file')">@{{ errors.first('file') }}</span>
</div>
<button type="submit" class="btn btn-lg btn-primary">
{{ __('bulkaddtocart::app.products.submit') }}
</button>
</form>
<div class="download-sample" style="margin-top: 30px;">
<span><b>{{ __('bulkaddtocart::app.products.download-sample') }}</b></span>
<span>
<a href="{{ route('cart.bulk-add-to-cart.sample.download') }}">
<i class="icon sort-down-icon" style="position: absolute; margin-left: 30px; cursor: pointer;"></i>
</a>
</span>
</div>
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,23 @@
<?php
return [
[
'key' => 'customer.settings.credit_max',
'name' => 'customercreditmax::app.admin.system.credit-max',
'sort' => 4,
'fields' => [
[
'name' => 'status',
'title' => 'customercreditmax::app.admin.system.use-credit-max',
'type' => 'boolean',
'channel_based' => true
], [
'name' => 'amount',
'title' => 'customercreditmax::app.admin.system.max-credit-amount',
'type' => 'text',
'validation' => 'decimal',
'channel_based' => true
]
],
]
];

View File

@ -0,0 +1,68 @@
<?php
namespace Webkul\CustomerCreditMax\Listeners;
use Illuminate\Support\Facades\Mail;
use Webkul\Sales\Repositories\OrderRepository;
use Cart as CartFacade;
/**
* Cart event handler
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class Cart
{
/**
* OrderRepository object
*
* @var Product
*/
protected $orderRepository;
/**
* Create a new cart event listener instance.
*
* @param Webkul\Sales\Repositories\OrderRepository $orderRepository
* @return void
*/
public function __construct(OrderRepository $orderRepository)
{
$this->orderRepository = $orderRepository;
}
/**
* Return current logged in customer
*
* @return Customer | Boolean
*/
public function getCurrentCustomerGuard()
{
$guard = request()->has('token') ? 'api' : 'customer';
return auth()->guard($guard);
}
/**
* Checks if customer credit amount exceeded or not
*
* @param mixed $cartItem
*/
public function cartItemAddBefore($productId)
{
if (! core()->getConfigData('customer.settings.credit_max.status') || ! $this->getCurrentCustomerGuard()->check())
return;
$baseGrandTotal = $this->orderRepository->scopeQuery(function ($query) {
return $query->where('orders.customer_id', $this->getCurrentCustomerGuard()->user()->id);
})->sum('base_grand_total');
$baseGrandTotalInvoiced = $this->orderRepository->scopeQuery(function ($query) {
return $query->where('orders.customer_id', $this->getCurrentCustomerGuard()->user()->id);
})->sum('base_grand_total_invoiced');
if ( ($baseGrandTotal - $baseGrandTotalInvoiced) >= core()->getConfigData('customer.settings.credit_max.amount'))
throw new \Exception('You available credit limit has been exceeded. Please you pay your pending invoice.');
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Webkul\CustomerCreditMax\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\Router;
class CustomerCreditMaxServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot(Router $router)
{
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'customercreditmax');
$this->app->register(EventServiceProvider::class);
}
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/system.php', 'core'
);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\CustomerCreditMax\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
Event::listen('checkout.cart.add.before', 'Webkul\CustomerCreditMax\Listeners\Cart@cartItemAddBefore');
}
}

View File

@ -0,0 +1,11 @@
<?php
return [
'admin' => [
'system' => [
'credit-max' => 'Credit Max',
'use-credit-max' => 'Use Credit Max',
'max-credit-amount' => 'Max Credit Amount'
]
]
];

View File

@ -0,0 +1,24 @@
{
"name": "bagisto/customer-document",
"license": "MIT",
"authors": [
{
"name": "Rahul Shukla",
"email": "rahulshukla517@webkul.com"
}
],
"autoload": {
"psr-4": {
"Webkul\\CustomerDocument\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Webkul\\CustomerDocument\\CustomerDocumentServiceProvider"
],
"aliases": {}
}
},
"minimum-stability": "dev"
}

View File

@ -0,0 +1,12 @@
<?php
return [
[
'key' => 'account.documents',
'name' => 'customerdocument::app.admin.customers.documents',
'route' =>'customer.documents.index',
'sort' => 6
]
];
?>

View File

@ -0,0 +1,7 @@
<?php
namespace Webkul\CustomerDocument\Contracts;
interface CustomerDocument
{
}

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CustomerDocumentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('customer_documents', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('description')->nullable();
$table->string('path');
$table->integer('customer_id')->unsigned();
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('customer_documents');
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Webkul\CustomerDocument\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@ -0,0 +1,127 @@
<?php
namespace Webkul\CustomerDocument\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Webkul\CustomerDocument\Repositories\CustomerDocumentRepository;
use Webkul\CustomerDocument\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
/**
* Document controlller
*
* @author Rahul Shukla <rahulshukla.symfony517@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class DocumentController extends Controller
{
/**
* Contains route related configuration
*
* @var array
*/
protected $_config;
/**
* CustomerDocumentRepository object
*
* @var array
*/
protected $customerDocument;
/**
* Create a new controller instance.
*
* @param \Webkul\Customer\Repositories\CustomerDocumentRepository $customerDocument
*/
public function __construct(CustomerDocumentRepository $customerDocument)
{
$this->_config = request('_config');
$this->customerDocument = $customerDocument;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$documents = $this->customerDocument->findWhere(['customer_id' => auth()->guard('customer')->user()->id]);
return view($this->_config['view'], compact('documents'));
}
/**
* upload document
*
* @return \Illuminate\Http\Response
*/
public function upload()
{
$valid_extension = ['xlsx', 'csv', 'xls', 'ods', 'png', 'jpeg', 'zip'];
if (! in_array(request()->file('file')->getClientOriginalExtension(), $valid_extension)) {
session()->flash('error', trans('customerdocument::app.admin.customers.upload-error'));
return redirect()->back();
} else {
try {
$data = request()->all();
if (request()->hasFile('file')) {
$dir = 'customer';
$document['path'] = request()->file('file')->store($dir);
}
$document['customer_id'] = $data['customer_id'];
$document['name'] = $data['name'];
$document['description'] = $data['description'];
$this->customerDocument->create($document);
session()->flash('success', trans('customerdocument::app.admin.customers.upload-success'));
return redirect()->back();
} catch (\Exception $e) {
session()->flash('error', $e);
return redirect()->back();
}
}
}
/**
* download the file for the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function download($id)
{
$document = $this->customerDocument->findOrfail($id);
return Storage::download($document['path'], $document['name']);
}
/**
* Remove the specified resource from storage..
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function delete($id)
{
$document = $this->customerDocument->findOrfail($id);
$this->customerDocument->delete($id);
Storage::delete($document['path']);
session()->flash('success', trans('customerdocument::app.admin.customers.delete-success'));
return redirect()->back();
}
}

View File

@ -0,0 +1,26 @@
<?php
Route::group(['middleware' => ['web']], function () {
Route::prefix('admin')->group(function () {
Route::group(['middleware' => ['admin']], function () {
//document Management Routes
Route::post('upload-document', 'Webkul\CustomerDocument\Http\Controllers\DocumentController@upload')->defaults('_config', [
'redirect' => 'admin.customer.index'
])->name('admin.customer.document.upload');
Route::get('download-document/{id}', 'Webkul\CustomerDocument\Http\Controllers\DocumentController@download')->defaults('_config', [
'redirect' => 'admin.customer.index'
])->name('admin.customer.document.download');
Route::get('delete-document/{id}', 'Webkul\CustomerDocument\Http\Controllers\DocumentController@delete')->defaults('_config', [
'redirect' => 'admin.customer.index'
])->name('admin.customer.document.delete');
});
});
});

View File

@ -0,0 +1,21 @@
<?php
Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function () {
Route::prefix('customer')->group(function () {
Route::group(['middleware' => ['customer']], function () {
Route::prefix('account')->group(function () {
Route::get('documents', 'Webkul\CustomerDocument\Http\Controllers\DocumentController@index')->defaults('_config', [
'view' => 'customerdocument::shop.customers.document'
])->name('customer.documents.index');
Route::get('download-document/{id}', 'Webkul\CustomerDocument\Http\Controllers\DocumentController@download')->defaults('_config', [
'redirect' => 'admin.customer.index'
])->name('customer.document.download');
});
});
});
});

View File

@ -0,0 +1,13 @@
<?php
namespace Webkul\CustomerDocument\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\CustomerDocument\Contracts\CustomerDocument as CustomerDocumentContract;
class CustomerDocument extends Model implements CustomerDocumentContract
{
protected $table = 'customer_documents';
protected $fillable = ['name', 'path', 'customer_id', 'description'];
}

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\CustomerDocument\Models;
use Konekt\Concord\Proxies\ModelProxy;
class CustomerDocumentProxy extends ModelProxy
{
}

View File

@ -0,0 +1,53 @@
<?php
namespace Webkul\CustomerDocument\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\Router;
class CustomerDocumentServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot(Router $router)
{
$this->loadRoutesFrom(__DIR__ . '/../Http/admin-routes.php');
$this->loadRoutesFrom(__DIR__ . '/../Http/front-routes.php');
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'customerdocument');
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'customerdocument');
$this->loadMigrationsFrom(__DIR__ . '/../Database/migrations');
$this->app->register(ModuleServiceProvider::class);
$this->app->register(EventServiceProvider::class);
}
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->registerConfig();
}
/**
* Register package config.
*
* @return void
*/
protected function registerConfig()
{
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/menu.php', 'menu.customer'
);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Webkul\CustomerDocument\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
Event::listen('bagisto.admin.customer.edit.after', function($viewRenderEventManager) {
$viewRenderEventManager->addTemplate('customerdocument::admin.customers.upload');
});
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Webkul\CustomerDocument\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
{
protected $models = [
\Webkul\CustomerDocument\Models\CustomerDocument::class,
];
}

View File

@ -0,0 +1,25 @@
<?php
namespace Webkul\CustomerDocument\Repositories;
use Webkul\Core\Eloquent\Repository;
/**
* Customer Reposotory
*
* @author Rahul Shukla <rahulshukla517@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CustomerDocumentRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\CustomerDocument\Contracts\CustomerDocument';
}
}

View File

@ -0,0 +1,21 @@
<?php
return [
'admin' =>[
'customers' => [
'documents' => 'Documents',
'add-document' => 'Add Document',
'submit' => 'Submit',
'file' => 'File',
'name' => 'Name',
'download' => 'Download',
'upload-success' => 'Document uploaded successfully.',
'delete-success' => 'Document deleted successfully.',
'empty' => 'You Do not Have Any Documents.',
'allowed-type' => 'Allowed Type :',
'file-type' => 'csv, xls, xlsx, ods, png, jpeg, zip.',
'upload-error' => 'The file must be a file of type: csv, xls, xlsx, ods, png, jpeg, zip.',
'description' => 'Description'
],
],
];

View File

@ -0,0 +1,87 @@
<?php
$customerDocumentRepository = app('Webkul\CustomerDocument\Repositories\CustomerDocumentRepository');
$documents = $customerDocumentRepository->findWhere(['customer_id' => $customer->id]);
?>
<accordian :title="'{{ __('customerdocument::app.admin.customers.documents') }}'" :active="true">
<div slot="body">
<button type="button" style="margin-bottom : 20px" class="btn btn-md btn-primary" @click="showModal('addDocument')">
{{ __('customerdocument::app.admin.customers.add-document') }}
</button>
<div class="table" style="margin-bottom: 20px;">
<table>
<thead>
<tr>
<th>{{ __('customerdocument::app.admin.customers.name') }}</th>
<th>{{ __('customerdocument::app.admin.customers.description') }}</th>
<th>{{ __('customerdocument::app.admin.customers.download') }}</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach ($documents as $document)
<tr>
<td>{{ $document->name }}</td>
<td>{{ $document->description }}</td>
<td>
<a href="{{ route('admin.customer.document.download', $document->id) }}">
<i class="icon sort-down-icon"></i>
</a>
</td>
<td class="actions">
<a href="{{ route('admin.customer.document.delete', $document->id) }}">
<i class="icon trash-icon"></i>
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</accordian>
<modal id="addDocument" :is-open="modalIds.addDocument">
<h3 slot="header">{{ __('customerdocument::app.admin.customers.add-document') }}</h3>
<div slot="body">
<form method="POST" action="{{ route('admin.customer.document.upload') }}" enctype="multipart/form-data" @submit.prevent="onSubmit">
@csrf()
<input type="hidden" name="customer_id" value="{{ $customer->id }}">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('customerdocument::app.admin.customers.name') }}</label>
<input v-validate="'required'" type="text" class="control" id="name" name="name" data-vv-as="&quot;{{ __('customerdocument::app.admin.customers.name') }}&quot;" value="{{ old('name') }}"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('description') ? 'has-error' : '']">
<label for="description">{{ __('customerdocument::app.admin.customers.description') }}</label>
<textarea class="control" id="description" name="description" data-vv-as="&quot;{{ __('customerdocument::app.admin.customers.description') }}&quot;" value="{{ old('description') }}"/
></textarea>
<span class="control-error" v-if="errors.has('description')">@{{ errors.first('description') }}</span>
</div>
<div class="control-group" :class="[errors.has('file') ? 'has-error' : '']">
<label for="file" class="required">{{ __('customerdocument::app.admin.customers.file') }}</label>
<input v-validate="'required'" type="file" class="control" id="file" name="file" data-vv-as="&quot;{{ __('customerdocument::app.admin.customers.file') }}&quot;" value="{{ old('file') }}" style="padding-top: 5px">
<span>{{ __('customerdocument::app.admin.customers.allowed-type') }}</span>
<span><b>{{ __('customerdocument::app.admin.customers.file-type') }}</b></span>
<span class="control-error" v-if="errors.has('file')">@{{ errors.first('file') }}</span>
</div>
<button type="submit" class="btn btn-lg btn-primary">
{{ __('customerdocument::app.admin.customers.submit') }}
</button>
</form>
</div>
</modal>

View File

@ -0,0 +1,57 @@
@extends('shop::layouts.master')
@section('page_title')
{{ __('customerdocument::app.admin.customers.documents') }}
@endsection
@section('content-wrapper')
<div class="account-content">
@include('shop::customers.account.partials.sidemenu')
<div class="account-layout">
<div class="account-head mb-15">
<span class="account-heading">{{ __('customerdocument::app.admin.customers.documents') }}</span>
<div class="horizontal-rule"></div>
</div>
<div class="account-items-list">
@if ($documents->count())
<div class="table" style="margin-bottom: 20px;">
<table>
<thead>
<tr>
<th>{{ __('customerdocument::app.admin.customers.name') }}</th>
<th>{{ __('customerdocument::app.admin.customers.description') }}</th>
<th>{{ __('customerdocument::app.admin.customers.download') }}</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach ($documents as $document)
<tr>
<td>{{ $document->name }}</td>
<td>{{ $document->description }}</td>
<td>
<a href="{{ route('customer.document.download', $document->id) }}">
<i class="icon sort-down-icon"></i>
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div class="empty">
{{ __('customerdocument::app.admin.customers.empty') }}
</div>
@endif
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCustomerGroupProductsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('customer_group_products', function (Blueprint $table) {
$table->integer('customer_group_id')->unsigned();
$table->integer('product_id')->unsigned();
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('customer_group_products');
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCustomerGroupCategoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('customer_group_categories', function (Blueprint $table) {
$table->integer('customer_group_id')->unsigned();
$table->integer('category_id')->unsigned();
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('customer_group_categories');
}
}

View File

@ -0,0 +1,139 @@
<?php
namespace Webkul\CustomerGroupCatalog\Http\Controllers\Admin;
use Illuminate\Http\Request;
use Webkul\Admin\Http\Controllers\Controller;
use Webkul\CustomerGroupCatalog\Repositories\CustomerGroupRepository;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\CustomerGroupCatalog\Repositories\CategoryRepository;
/**
* Customer Group controlller
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CustomerGroupController extends Controller
{
/**
* Contains route related configuration
*
* @var array
*/
protected $_config;
/**
* CustomerGroupRepository object
*
* @var object
*/
protected $customerGroupRepository;
/**
* ProductRepository object
*
* @var object
*/
protected $productRepository;
/**
* CategoryRepository object
*
* @var object
*/
protected $categoryRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Customer\Repositories\CustomerGroupRepository $customerGroupRepositor;
* @param \Webkul\Product\Repositories\ProductRepository $productRepository;
* @param \Webkul\Category\Repositories\CategoryRepository $categoryRepository;
* @return void
*/
public function __construct(
CustomerGroupRepository $customerGroupRepository,
ProductRepository $productRepository,
CategoryRepository $categoryRepository
)
{
$this->_config = request('_config');
$this->customerGroupRepository = $customerGroupRepository;
$this->productRepository = $productRepository;
$this->categoryRepository = $categoryRepository;
}
/**
* Search for catalog
*
* @return \Illuminate\Http\Response
*/
public function search()
{
$results = [];
if (request()->input('type') == 'products') {
foreach ($this->productRepository->searchProductByAttribute(request()->input('query')) as $row) {
$results[] = [
'id' => $row->product_id,
'name' => $row->name,
];
}
} else {
foreach ($this->categoryRepository->search(request()->input('query')) as $row) {
$results[] = [
'id' => $row->id,
'name' => $row->name,
];
}
}
return response()->json($results);
}
/**
* Store a newly created resource in storage.
*
* @return \Illuminate\Http\Response
*/
public function store()
{
$this->validate(request(), [
'name' => 'string|required',
]);
$data = request()->all();
$data['is_user_defined'] = 1;
$this->customerGroupRepository->create($data);
session()->flash('success', trans('admin::app.response.create-success', ['name' => 'Customer Group']));
return redirect()->route($this->_config['redirect']);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->validate(request(), [
'name' => 'string|required',
]);
$this->customerGroupRepository->update(request()->all(), $id);
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Customer Group']));
return redirect()->route($this->_config['redirect']);
}
}

View File

@ -0,0 +1,23 @@
<?php
Route::group(['middleware' => ['web']], function () {
Route::prefix('admin')->group(function () {
Route::group(['middleware' => ['admin']], function () {
//Seller routes
Route::get('groups/catalog/search', 'Webkul\CustomerGroupCatalog\Http\Controllers\Admin\CustomerGroupController@search')->name('admin.customer_group_catalog.search.catalog');
Route::post('groups/create', 'Webkul\CustomerGroupCatalog\Http\Controllers\Admin\CustomerGroupController@store')->defaults('_config',[
'redirect' => 'admin.groups.index'
])->name('admin.customer_group_catalog.store');
Route::put('groups/edit/{id}', 'Webkul\CustomerGroupCatalog\Http\Controllers\Admin\CustomerGroupController@update')->defaults('_config',[
'redirect' => 'admin.groups.index'
])->name('admin.customer_group_catalog.update');
});
});
});

View File

@ -0,0 +1,26 @@
<?php
namespace Webkul\CustomerGroupCatalog\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Customer\Models\CustomerGroup as BaseCustomerGroup;
use Webkul\Product\Models\ProductProxy;
use Webkul\Category\Models\CategoryProxy;
class CustomerGroup extends BaseCustomerGroup
{
/**
* The products that belong to the customer group.
*/
public function products()
{
return $this->belongsToMany(ProductProxy::modelClass(), 'customer_group_products');
}
/**
* The categories that belong to the customer group.
*/
public function categories()
{
return $this->belongsToMany(CategoryProxy::modelClass(), 'customer_group_categories');
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Webkul\CustomerGroupCatalog\Providers;
use Illuminate\Support\ServiceProvider;
class CustomerGroupCatalogServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
$this->loadRoutesFrom(__DIR__ . '/../Http/admin-routes.php');
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'customergroupcatalog');
$this->publishes([
__DIR__ . '/../Resources/views/admin/customers/groups' => resource_path('views/vendor/admin/customers/groups'),
__DIR__ . '/../Resources/views/shop/products' => resource_path('views/vendor/shop/products'),
__DIR__ . '/../Resources/views/shop/layouts' => resource_path('views/vendor/shop/layouts'),
]);
}
/**
* Register services.
*
* @return void
*/
public function register()
{
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace Webkul\CustomerGroupCatalog\Repositories;
use Webkul\Core\Eloquent\Repository;
use Webkul\Category\Repositories\CategoryRepository as BaseCategoryRepository;
/**
* Category Reposotory
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CategoryRepository extends BaseCategoryRepository
{
/**
* Search Category
*
* @return Collection
*/
public function search($term)
{
return $this->getModel()->join('category_translations', function ($join) {
$join->on('categories.id', 'category_translations.category_id')
->where('category_translations.locale', app()->getLocale())
->where('category_translations.name', 'like', '%' . urldecode(request()->input('query')) . '%');
})
->select('categories.*')
->groupBy('categories.id')
->get();
}
/**
* get visible category tree
*
* @param integer $id
* @return mixed
*/
public function getVisibleCategoryTree($id = null)
{
static $categories = [];
if(array_key_exists($id, $categories))
return $categories[$id];
$customer = auth()->guard(request()->has('token') ? 'api' : 'customer')->user();
$categoryIds = [];
if (! $customer) {
$categoryIds = app('Webkul\CustomerGroupCatalog\Repositories\CustomerGroupRepository')->findOneByField('code', 'guest')->categories()->pluck('id');
} else {
if ($customer->group) {
$categoryIds = app('Webkul\CustomerGroupCatalog\Repositories\CustomerGroupRepository')->find($customer->group->id)->categories()->pluck('id');
}
}
if (count($categoryIds)) {
$categories[$id] = $id
? $this->model::orderBy('position', 'ASC')->where('status', 1)->whereIn('id', $categoryIds)->descendantsOf($id)->toTree()
: $this->model::orderBy('position', 'ASC')->where('status', 1)->whereIn('id', $categoryIds)->get()->toTree();
} else {
$categories[$id] = $id
? $this->model::orderBy('position', 'ASC')->where('status', 1)->descendantsOf($id)->toTree()
: $this->model::orderBy('position', 'ASC')->where('status', 1)->get()->toTree();
}
return $categories[$id];
}
}

View File

@ -0,0 +1,102 @@
<?php
namespace Webkul\CustomerGroupCatalog\Repositories;
use Webkul\Core\Eloquent\Repository;
/**
* CustomerGroup Reposotory
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CustomerGroupRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\CustomerGroupCatalog\Models\CustomerGroup';
}
/**
* @param array $data
* @return mixed
*/
public function create(array $data)
{
$group = parent::create($data);
if (isset($data['products'])) {
$group->products()->sync($data['products']);
} else {
$group->products()->sync([]);
}
if (isset($data['categories'])) {
$group->categories()->sync($data['categories']);
} else {
$group->categories()->sync([]);
}
return $group;
}
/**
* @param array $data
* @param $id
* @param string $attribute
* @return mixed
*/
public function update(array $data, $id, $attribute = "id")
{
parent::update($data, $id, $attribute);
$group = $this->find($id);
if (isset($data['products'])) {
$group->products()->sync($data['products']);
} else {
$group->products()->sync([]);
}
if (isset($data['categories'])) {
$group->categories()->sync($data['categories']);
} else {
$group->categories()->sync([]);
}
return ;
}
/**
* @return Collection
*/
public function getProducts($group)
{
$products = [];
foreach ($this->find($group->id)->products as $product) {
$products[] = ['id' => $product->id, 'name' => $product->name];
}
return $products;
}
/**
* @return Collection
*/
public function getCategories($group)
{
$categories = [];
foreach ($this->find($group->id)->categories as $category) {
$categories[] = ['id' => $category->id, 'name' => $category->name];
}
return $categories;
}
}

View File

@ -0,0 +1,13 @@
<?php
return [
'customers' => [
'groups' => [
'general' => 'General',
'linked-product-categories' => 'Linked Products and Categories',
'categories' => 'Categories',
'products' => 'Products',
'search-hint' => 'Start typing name'
]
]
];

View File

@ -0,0 +1,211 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.customers.groups.add-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.customer_group_catalog.store') }}" @submit.prevent="onSubmit">
<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>
{{ __('admin::app.customers.groups.add-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.customers.groups.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
<accordian :title="'{{ __('customergroupcatalog::app.customers.groups.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">
{{ __('admin::app.customers.groups.name') }}
</label>
<input type="text" class="control" name="name" v-validate="'required'" value="{{ old('name') }}" data-vv-as="&quot;{{ __('admin::app.customers.groups.name') }}&quot;">
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
</div>
</accordian>
<accordian :title="'{{ __('customergroupcatalog::app.customers.groups.linked-product-categories') }}'">
<div slot="body">
<linked-products-categories></linked-products-categories>
</div>
</accordian>
</div>
</div>
</form>
</div>
@stop
@push('scripts')
<script type="text/x-template" id="linked-products-categories-template">
<div>
<div class="control-group" v-for='key in controls'>
<label>@{{ controls_labels[key] }}</label>
<input type="text" class="control" placeholder="{{ __('customergroupcatalog::app.customers.groups.search-hint') }}" v-model.lazy="search_terms[key]" v-debounce="500" autocomplete="off">
<div class="linked-product-search-result">
<ul>
<li v-for='(result, index) in searched_results[key]' v-if='searched_results[key].length' @click="addItem(result, key)">
@{{ result.name }}
</li>
<li v-if='! searched_results[key].length && search_terms[key].length && ! is_searching[key]'>
{{ __('admin::app.catalog.products.no-result-found') }}
</li>
<li v-if="is_searching[key] && search_terms[key].length">
{{ __('admin::app.catalog.products.searching') }}
</li>
</ul>
</div>
<input type="hidden" name="products[]" v-for='(product, index) in searched_results.products' v-if="(key == 'products') && searched_results.products.length" :value="product.id"/>
<span class="filter-tag" style="text-transform: capitalize; margin-top: 10px; margin-right: 0px; justify-content: flex-start" v-if="saved_results[key].length">
<span class="wrapper" style="margin-left: 0px; margin-right: 10px;" v-for='(savedItem, index) in saved_results[key]'>
<input type="hidden" :name="key + '[]'" :value="savedItem.id"/>
@{{ savedItem.name }}
<span class="icon cross-icon" @click="removeItem(savedItem, key)"></span>
</span>
</span>
</div>
</div>
</script>
<script>
Vue.component('linked-products-categories', {
template: '#linked-products-categories-template',
data: function() {
return {
searched_results: {
products: [],
categories: [],
},
saved_results: {
products: [],
categories: [],
},
search_terms: {
products: '',
categories: ''
},
is_searching: {
products: false,
categories: false
},
controls: [
// 'products',
'categories'
],
controls_labels: {
'products': "{{ __('customergroupcatalog::app.customers.groups.products') }}",
'categories': "{{ __('customergroupcatalog::app.customers.groups.categories') }}",
}
}
},
watch: {
'search_terms.products': function(newVal, oldVal) {
this.search('products')
},
'search_terms.categories': function(newVal, oldVal) {
this.search('categories')
}
},
methods: {
addItem: function (item, key) {
this.saved_results[key].push(item);
this.search_terms[key] = '';
this.searched_results[key] = [];
},
removeItem: function (item, key) {
for (var index in this.saved_results[key]) {
if (this.saved_results[key][index].id == item.id) {
this.saved_results[key].splice(index, 1);
}
}
},
search: function (key) {
this_this = this;
this.is_searching[key] = true;
if (! this.search_terms[key].length) {
this_this.searched_results[key] = [];
this_this.is_searching[key] = false;
return;
}
this.$http.get ("{{ route('admin.customer_group_catalog.search.catalog') }}", {params: {query: this.search_terms[key], type: key}})
.then (function(response) {
for (var key1 in this_this.saved_results[key]) {
for (var key2 in response.data) {
if (response.data[key2].id == this_this.saved_results[key][key1].id) {
response.data.splice(key2, 1);
}
}
}
this_this.searched_results[key] = response.data;
this_this.is_searching[key] = false;
})
.catch (function (error) {
this_this.is_searching[key] = false;
})
}
}
});
</script>
@endpush

View File

@ -0,0 +1,227 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.customers.groups.edit-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.customer_group_catalog.update', $group->id) }}">
<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>
{{ __('admin::app.customers.groups.edit-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.customers.groups.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
<input name="_method" type="hidden" value="PUT">
<accordian :title="'{{ __('customergroupcatalog::app.customers.groups.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">
{{ __('admin::app.customers.groups.name') }}
</label>
<input type="text" class="control" name="name" v-validate="'required'" value="{{ $group->name }}" data-vv-as="&quot;{{ __('admin::app.customers.groups.name') }}&quot;">
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
</div>
</accordian>
<accordian :title="'{{ __('customergroupcatalog::app.customers.groups.linked-product-categories') }}'">
<div slot="body">
<linked-products-categories></linked-products-categories>
</div>
</accordian>
</div>
</div>
</form>
</div>
@stop
@push('scripts')
<script type="text/x-template" id="linked-products-categories-template">
<div>
<div class="control-group" v-for='key in controls'>
<label>@{{ controls_labels[key] }}</label>
<input type="text" class="control" placeholder="{{ __('customergroupcatalog::app.customers.groups.search-hint') }}" v-model.lazy="search_terms[key]" v-debounce="500" autocomplete="off">
<div class="linked-product-search-result">
<ul>
<li v-for='(result, index) in searched_results[key]' v-if='searched_results[key].length' @click="addItem(result, key)">
@{{ result.name }}
</li>
<li v-if='! searched_results[key].length && search_terms[key].length && ! is_searching[key]'>
{{ __('admin::app.catalog.products.no-result-found') }}
</li>
<li v-if="is_searching[key] && search_terms[key].length">
{{ __('admin::app.catalog.products.searching') }}
</li>
</ul>
</div>
<span class="filter-tag" style="text-transform: capitalize; margin-top: 10px; margin-right: 0px; justify-content: flex-start" v-if="saved_results[key].length">
<span class="wrapper" style="margin-left: 0px; margin-right: 10px;" v-for='(savedItem, index) in saved_results[key]'>
<input type="hidden" :name="key + '[]'" :value="savedItem.id"/>
@{{ savedItem.name }}
<span class="icon cross-icon" @click="removeItem(savedItem, key)"></span>
</span>
</span>
</div>
</div>
</script>
<script>
Vue.component('linked-products-categories', {
template: '#linked-products-categories-template',
data: function() {
return {
searched_results: {
products: [],
categories: []
},
saved_results: {
products: [],
categories: []
},
linked_results: {
products: @json(app('Webkul\CustomerGroupCatalog\Repositories\CustomerGroupRepository')->getProducts($group)),
categories: @json(app('Webkul\CustomerGroupCatalog\Repositories\CustomerGroupRepository')->getCategories($group))
},
search_terms: {
products: '',
categories: ''
},
is_searching: {
products: false,
categories: false
},
controls: [
// 'products',
'categories'
],
controls_labels: {
products: "{{ __('customergroupcatalog::app.customers.groups.products') }}",
categories: "{{ __('customergroupcatalog::app.customers.groups.categories') }}"
}
}
},
created: function () {
for (var index in this.linked_results.products) {
this.saved_results['products'].push(this.linked_results.products[index]);
}
for (var index in this.linked_results.categories) {
this.saved_results['categories'].push(this.linked_results.categories[index]);
}
},
watch: {
'search_terms.products': function(newVal, oldVal) {
this.search('products')
},
'search_terms.categories': function(newVal, oldVal) {
this.search('categories')
}
},
methods: {
addItem: function (item, key) {
this.saved_results[key].push(item);
this.search_terms[key] = '';
this.searched_results[key] = [];
},
removeItem: function (item, key) {
for (var index in this.saved_results[key]) {
if (this.saved_results[key][index].id == item.id) {
this.saved_results[key].splice(index, 1);
}
}
},
search: function (key) {
this_this = this;
this.is_searching[key] = true;
if (! this.search_terms[key].length) {
this_this.searched_results[key] = [];
this_this.is_searching[key] = false;
return;
}
this.$http.get ("{{ route('admin.customer_group_catalog.search.catalog') }}", {params: {query: this.search_terms[key], type: key}})
.then (function(response) {
for (var key1 in this_this.saved_results[key]) {
for (var key2 in response.data) {
if (response.data[key2].id == this_this.saved_results[key][key1].id) {
response.data.splice(key2, 1);
}
}
}
this_this.searched_results[key] = response.data;
this_this.is_searching[key] = false;
})
.catch (function (error) {
this_this.is_searching[key] = false;
})
}
}
});
</script>
@endpush

View File

@ -0,0 +1,94 @@
<div class="footer">
<div class="footer-content">
<div class="footer-list-container">
<?php
$categories = [];
foreach (app('Webkul\CustomerGroupCatalog\Repositories\CategoryRepository')->getVisibleCategoryTree(core()->getCurrentChannel()->root_category_id) as $category){
if ($category->slug)
array_push($categories, $category);
}
?>
@if (count($categories))
<div class="list-container">
<span class="list-heading">Categories</span>
<ul class="list-group">
@foreach ($categories as $key => $category)
<li>
<a href="{{ route('shop.categories.index', $category->slug) }}">{{ $category->name }}</a>
</li>
@endforeach
</ul>
</div>
@endif
{!! DbView::make(core()->getCurrentChannel())->field('footer_content')->render() !!}
<div class="list-container">
@if(core()->getConfigData('customer.settings.newsletter.subscription'))
<span class="list-heading">{{ __('shop::app.footer.subscribe-newsletter') }}</span>
<div class="form-container">
<form action="{{ route('shop.subscribe') }}">
<div class="control-group" :class="[errors.has('subscriber_email') ? 'has-error' : '']">
<input type="email" class="control subscribe-field" name="subscriber_email" placeholder="Email Address" required><br/>
<button class="btn btn-md btn-primary">{{ __('shop::app.subscription.subscribe') }}</button>
</div>
</form>
</div>
@endif
<?php
$query = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);
$searchTerm = explode("?", $query);
foreach($searchTerm as $term){
if (strpos($term, 'term') !== false) {
$serachQuery = $term;
}
}
?>
<span class="list-heading">{{ __('shop::app.footer.locale') }}</span>
<div class="form-container">
<div class="control-group">
<select class="control locale-switcher" onchange="window.location.href = this.value" @if (count(core()->getCurrentChannel()->locales) == 1) disabled="disabled" @endif>
@foreach (core()->getCurrentChannel()->locales as $locale)
@if(isset($serachQuery))
<option value="?{{ $serachQuery }}?locale={{ $locale->code }}" {{ $locale->code == app()->getLocale() ? 'selected' : '' }}>{{ $locale->name }}</option>
@else
<option value="?locale={{ $locale->code }}" {{ $locale->code == app()->getLocale() ? 'selected' : '' }}>{{ $locale->name }}</option>
@endif
@endforeach
</select>
</div>
</div>
<div class="currency">
<span class="list-heading">{{ __('shop::app.footer.currency') }}</span>
<div class="form-container">
<div class="control-group">
<select class="control locale-switcher" onchange="window.location.href = this.value">
@foreach (core()->getCurrentChannel()->currencies as $currency)
@if(isset($serachQuery))
<option value="?{{ $serachQuery }}?currency={{ $currency->code }}" {{ $currency->code == core()->getCurrentCurrencyCode() ? 'selected' : '' }}>{{ $currency->code }}</option>
@else
<option value="?currency={{ $currency->code }}" {{ $currency->code == core()->getCurrentCurrencyCode() ? 'selected' : '' }}>{{ $currency->code }}</option>
@endif
@endforeach
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,137 @@
{!! view_render_event('bagisto.shop.layout.header.category.before') !!}
<?php
$categories = [];
foreach (app('Webkul\CustomerGroupCatalog\Repositories\CategoryRepository')->getVisibleCategoryTree(core()->getCurrentChannel()->root_category_id) as $category) {
if ($category->slug)
array_push($categories, $category);
}
?>
<category-nav categories='@json($categories)' url="{{url()->to('/')}}"></category-nav>
{!! view_render_event('bagisto.shop.layout.header.category.after') !!}
@push('scripts')
<script type="text/x-template" id="category-nav-template">
<ul class="nav">
<category-item
v-for="(item, index) in items"
:key="index"
:url="url"
:item="item"
:parent="index">
</category-item>
</ul>
</script>
<script>
Vue.component('category-nav', {
template: '#category-nav-template',
props: {
categories: {
type: [Array, String, Object],
required: false,
default: (function () {
return [];
})
},
url: String
},
data: function(){
return {
items_count:0
};
},
computed: {
items: function() {
return JSON.parse(this.categories)
}
},
});
</script>
<script type="text/x-template" id="category-item-template">
<li>
<a :href="url+'/categories/'+this.item['translations'][0].slug">
@{{ name }}&emsp;
<i class="icon dropdown-right-icon" v-if="haveChildren && item.parent_id != null"></i>
</a>
<i :class="[show ? 'icon icon-arrow-down mt-15' : 'icon dropdown-right-icon left mt-15']"
v-if="haveChildren" @click="showOrHide"></i>
<ul v-if="haveChildren && show">
<category-item
v-for="(child, index) in item.children"
:key="index"
:url="url"
:item="child">
</category-item>
</ul>
</li>
</script>
<script>
Vue.component('category-item', {
template: '#category-item-template',
props: {
item: Object,
url: String,
},
data: function() {
return {
items_count:0,
show: false,
};
},
mounted: function() {
if(window.innerWidth > 770){
this.show = true;
}
},
computed: {
haveChildren: function() {
return this.item.children.length ? true : false;
},
name: function() {
if (this.item.translations && this.item.translations.length) {
this.item.translations.forEach(function(translation) {
if (translation.locale == document.documentElement.lang)
return translation.name;
});
}
return this.item.name;
}
},
methods: {
showOrHide: function() {
this.show = !this.show;
}
}
});
</script>
@endpush

View File

@ -0,0 +1,128 @@
@extends('shop::layouts.master')
@section('page_title')
{{ $category->meta_title ?? $category->name }}
@stop
@section('seo')
<meta name="description" content="{{ $category->meta_description }}"/>
<meta name="keywords" content="{{ $category->meta_keywords }}"/>
@stop
@section('content-wrapper')
@inject ('productRepository', 'Webkul\Product\Repositories\ProductRepository')
<div class="main">
{!! view_render_event('bagisto.shop.products.index.before', ['category' => $category]) !!}
<div class="category-container">
@if (in_array($category->display_mode, [null, 'products_only', 'products_and_description']))
@include ('shop::products.list.layered-navigation')
@endif
<div class="category-block" @if ($category->display_mode == 'description_only') style="width: 100%" @endif>
<div class="hero-image mb-35">
@if (!is_null($category->image))
<img class="logo" src="{{ $category->image_url }}" />
@endif
</div>
@if (in_array($category->display_mode, [null, 'description_only', 'products_and_description']))
@if ($category->description)
<div class="category-description">
{!! $category->description !!}
</div>
@endif
@endif
@if (in_array($category->display_mode, [null, 'products_only', 'products_and_description']))
<?php $products = $productRepository->getAll($category->id); ?>
@if ($products->count())
@include ('shop::products.list.toolbar')
@inject ('toolbarHelper', 'Webkul\Product\Helpers\Toolbar')
@if ($toolbarHelper->getCurrentMode() == 'grid')
<div class="product-grid-3">
@foreach ($products as $productFlat)
@include ('shop::products.list.card', ['product' => $productFlat])
@endforeach
</div>
@else
<div class="product-list">
@foreach ($products as $productFlat)
@include ('shop::products.list.card', ['product' => $productFlat])
@endforeach
</div>
@endif
{!! view_render_event('bagisto.shop.products.index.pagination.before', ['category' => $category]) !!}
<div class="bottom-toolbar">
{{ $products->appends(request()->input())->links() }}
</div>
{!! view_render_event('bagisto.shop.products.index.pagination.after', ['category' => $category]) !!}
@else
<div class="product-list empty">
<h2>{{ __('shop::app.products.whoops') }}</h2>
<p>
{{ __('shop::app.products.empty') }}
</p>
</div>
@endif
@endif
</div>
</div>
{!! view_render_event('bagisto.shop.products.index.after', ['category' => $category]) !!}
</div>
@stop
@push('scripts')
<script>
$(document).ready(function() {
$('.responsive-layred-filter').css('display','none');
$(".sort-icon, .filter-icon").on('click', function(e){
var currentElement = $(e.currentTarget);
if (currentElement.hasClass('sort-icon')) {
currentElement.removeClass('sort-icon');
currentElement.addClass('icon-menu-close-adj');
currentElement.next().removeClass();
currentElement.next().addClass('icon filter-icon');
$('.responsive-layred-filter').css('display','none');
$('.pager').css('display','flex');
$('.pager').css('justify-content','space-between');
} else if (currentElement.hasClass('filter-icon')) {
currentElement.removeClass('filter-icon');
currentElement.addClass('icon-menu-close-adj');
currentElement.prev().removeClass();
currentElement.prev().addClass('icon sort-icon');
$('.pager').css('display','none');
$('.responsive-layred-filter').css('display','block');
$('.responsive-layred-filter').css('margin-top','10px');
} else {
currentElement.removeClass('icon-menu-close-adj');
$('.responsive-layred-filter').css('display','none');
$('.pager').css('display','none');
if ($(this).index() == 0) {
currentElement.addClass('sort-icon');
} else {
currentElement.addClass('filter-icon');
}
}
});
});
</script>
@endpush

1
packages/Webkul/SAASCustomizer/.gitignore vendored Executable file
View File

@ -0,0 +1 @@
/node_modules

View File

@ -0,0 +1,27 @@
{
"name": "bagisto/laravel-Saas",
"license": "MIT",
"authors": [
{
"name": "Prashant Singh",
"email": "prashant.singh852@webkul.com"
}
],
"require": {
"konekt/concord": "^1.2"
},
"autoload": {
"psr-4": {
"Webkul\\SAASCustomizer\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Webkul\\SAASCustomizer\\Providers\\SAASCustomizerServiceProvider"
],
"aliases": {}
}
},
"minimum-stability": "dev"
}

View File

@ -0,0 +1,31 @@
# Requirements:
1. SaaS-based system on Bagisto with all the core features .
2. Seller Creation with their own store and domain
3. Stripe Connect as payment, where the connect is under our Stripe account.
4. Seller functionality : Own Admin dashboard, Create/Edit Products, Checked Order status and Completion, Edit/Create Customers, Add Notes on Customer
5. Create discount rules
6. The seller should approve customers who sign up
7. Platform locale in English
8. The seller should control which categories or products a specific customer can see.
9. Upload CSV/Excel file with SKU,Quantity for bulk add to cart
10. Customers should be logged in to see prices and buy.
11. The seller should make custom prices for customers. So this customer gets 10% of all products.
12. The seller can upload PDF and images documents to a page, where the customer can download them.
13. The seller can upload documents to a customer, where the customer can see their documents on their account.
14. It should be possible to add credit max on the customer, so if the customer has unpaid invoices of xxx dollars, they cannot buy any more, before the invoices are paid.
15. Pre Order and Backorder products
# Installation Steps:
* Inside the project root '.env' have 'app_url' parameter which must be set as your main domain.
* Then run the command 'php artisan saas:install'
* Open the main domain you would be only be able to see the registration page.
* There should only be a commission/fee on every transaction, made with Stripe. Not on products.
There is the Stripe fee 2.9% + 30cent, and there is our platform fee, which we can set in Stripe(it is going to be 2%). We would like them to be shown as a total service fee in the totals on the cart. So if the customer is buying a product to 100$
The will see subtotal of 100$, shipping: 3$, service fee 5,347 $. ((103*2,9%+2%)+0,30)-103 = 5,347$
We would like that the Seller can choose from their backend settings, who should pay the service fee. Is it the customer, so the amount will be 108,347 $ for the customer, and the Seller will get 103$ after fees.
If the Seller should pay the fees, the amount will be 103$ for the customer and the payout for the Seller will be 103-5,347$ = 97,653$

View File

@ -0,0 +1,25 @@
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "cross-env npm run watch -- --watch-poll --progress",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.18",
"cross-env": "^5.1.4",
"laravel-mix": "^2.1",
"laravel-mix-merge-manifest": "^0.1.1",
"jquery": "^3.2",
"vue": "^2.1.10"
},
"dependencies": {
"vee-validate": "2.0.0-rc.26",
"vue-flatpickr": "^2.3.0",
"vue-slider-component": "^2.7.5"
}
}

View File

@ -0,0 +1 @@
@import url(https://fonts.googleapis.com/css?family=Montserrat:400,500);html{font-family:montserrat,sans-serif}::-webkit-input-placeholder{font-family:montserrat,sans-serif}::-ms-input-placeholder{font-family:montserrat,sans-serif}::placeholder{font-family:montserrat,sans-serif}.mt-30{margin-top:30px}.mt-60{margin-top:60px}.mt-90{margin-top:90px}.content-container{width:100%;min-height:100vh;height:auto}.form-container{width:420px;margin-left:auto;margin-right:auto}.form-container .brand-logo{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:100%}.form-container .step-one button,.form-container .step-three button,.form-container .step-two button{width:150px;margin-left:calc(50% - 75px)}.registration{padding:10px;-webkit-box-shadow:0 2px 25px 0 rgba(0,0,0,.15);box-shadow:0 2px 25px 0 rgba(0,0,0,.15)}.registration .control-group .control{width:100%}.step-navigator{margin-top:15px;margin-bottom:15px;width:100%}.step-list{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.step-list .step-item{cursor:pointer;height:64px;width:64px;border:1px solid #c7c7c7;border-radius:50%;text-align:center;padding-top:24px}.step-list .step-item.active{border:1px solid blue}

View File

@ -0,0 +1 @@
!function(n){var t={};function r(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return n[e].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=n,r.c=t,r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:e})},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},r.p="/",r(r.s=0)}({0:function(n,t,r){r("J66Q"),n.exports=r("MT9B")},J66Q:function(n,t){},MT9B:function(n,t){}});

View File

@ -0,0 +1,4 @@
{
"/js/saas.js": "/js/saas.js?id=245497d286e5c4f9d97d",
"/css/saas.css": "/css/saas.css?id=a62abbc117a7478bace8"
}

View File

@ -0,0 +1,70 @@
# Introduction:
Bagisto SAAS extension is eCommerce virtual mall, where multiple-vendor can sign-up and create their own e-commerce store with their personalized domain name. SAAS extension will help you in appealing sellers to get registered with your business and use common resources such as Payment gateways, Shipping methods, etc.
Get involved and control your mall by managing commissions directly from single place, control on customer signups, super cool super admin panel to manage sellers, activate/deactivate your sellers from super admin panel too and lots more.
# Feature of Laravel ecommerce SAAS Module
* Easy to Setup and manage SAAS based eCommerce solution.
* Scaling your business is now directly proportional to no. of sellers.
* Separate admin panel for each seller.
* Ability of seller to change domain at will.
* Easily manageable orders.
* Faster updates will bring lots of demanding features.
# Requirements
* Bagisto v0.1.6 or higher.
# Note
1. Do not install bagisto till you configure this extension initially w/ it.
2. Before proceeding this extension you need to copy files from zip
file to root location of your Bagisto installed inside it
3. Do not try to seed the database with command 'php artisan db:seed'
# Installation
* Run the command from root in terminal 'composer create-project'
* Find '.env' file in root directory and change the APP_URL param to domain,
ex: www.example.com and do not forget to configure Mail and DB parameters inside .env file
* Run the following commands:
```
php artisan migrate (will take a while)
php artisan storage:link
php artisan vendor:publish
```
* Do couple of entries in root composer.json in psr-4 object:
```
'Webkul\SAASCustomizer\": "packages/Webkul/SAASCustomizer/src',
'Webkul\CustomerCustomizer\": "packages/Webkul/CustomerCustomizer/src'
```
* Another entry inside file('app/Http/Kernel.php',):
In this file you can find an array 'middlewareGroups' inside it there is
a key named 'web' inside it do an entry:
```
Webkul\SAASCustomizer\Http\Middleware\ValidatesDomain::class'
```
* Find a file auth.php present inside config folder from root and do the following entries:
```
'super-admin' => [
'driver' => 'session',
'provider' => 'superadmins'
]
```
> insert the above code in 'guards' array.
```
'superadmins' => [
'driver' => 'eloquent',
'model' => Webkul\SAASCustomizer\Models\SuperAdmin::class
]
```
> insert the above code in 'providers' array.
* Run the command from root in terminal 'composer dump-autoload'.
* In your terminal now type command 'php artisan SAAS:install', to generate the super admin credentials
* Access super admin panel using:
www.domain.com/super/login
* Run your SAAS based store.

View File

@ -0,0 +1,117 @@
<?php
namespace Webkul\SAASCustomizer\Commands\Console;
use Illuminate\Console\Command;
use Webkul\SAASCustomizer\Repositories\CompanyRepository;
use Webkul\SAASCustomizer\Repositories\CompanyDetailsRepository;
use Webkul\User\Repositories\AdminRepository as Admin;
use Webkul\User\Repositories\RoleRepository as Role;
use Company;
use Validator;
class GenerateSU extends Command
{
/**
* Holds the execution signature of the command needed
* to be executed for generating super user
*/
protected $signature = 'saas:install';
/**
* Will inhibit the description related to this
* command's role
*/
protected $description = 'Generates only one super user for the system';
public function __construct(CompanyRepository $company, CompanyDetailsRepository $details, Admin $admin, Role $role)
{
parent::__construct();
$this->company = $company;
$this->details = $details;
$this->admin = $admin;
$this->role = $role;
}
/**
* Does the all sought of lifting required to be performed for
* generating a super user
*/
public function handle()
{
$this->comment('Generating super user for the system....');
$email = $this->ask('Please enter email?');
$data = [
'email' => $email
];
$validator = Validator::make($data, [
'email' => 'required|email',
]);
if($validator->fails()) {
$this->comment('Email invalid, please enter try again.');
return false;
}
unset($data);
$this->comment('You entered = '. $email);
$password = $this->ask('Please enter password?');
$data = [
'password' => $password
];
$validator = Validator::make($data, [
'password' => 'required|string|min:6'
]);
if ($validator->fails()) {
$this->comment('Password invalid, make sure password is atleast 6 characters of length.');
return false;
}
$this->comment('You entered = '. $password);
unset($data);
if ($this->confirm('Do you wish to continue?')) {
$result = $this->generateSuperUserCompany($email, $password);
if ($result) {
$this->comment('Super user for the system is created');
} else {
$this->comment('Super user for the system already exists, please contact support@bagisto.com for troubleshooting.');
}
} else {
$this->comment('Please try creating the super user again');
}
}
public function generateSuperUserCompany($email, $password)
{
$super_admin = \DB::select('select * from super_admins');
if(count($super_admin)) {
return false;
}
$data = [
'email' => $email,
'password' => bcrypt($password),
];
\DB::insert('insert into super_admins (id, email, password, created_at, updated_at) values (?, ?, ?, ?, ?)', [1, $data['email'], $data['password'], now(), now()]);
return true;
}
}

View File

@ -0,0 +1,133 @@
<?php
namespace Webkul\SAASCustomizer;
use Illuminate\Support\Facades\Config;
use Webkul\SAASCustomizer\Repositories\CompanyRepository;
use Webkul\SAASCustomizer\Models\SuperAdmin;
use Carbon\Carbon;
class Company
{
/**
* To hold the instance of currently active company
*/
protected $company;
/**
* Holds the currently request server name variable
*/
protected $domain;
/**
* To hold the super admin instance
*/
protected $superAdmin;
public function __construct(CompanyRepository $company)
{
$this->company = $company;
}
public function isAllowed()
{
$primaryServerName = config('app.url');
if (isset($_SERVER['SERVER_NAME']))
$currentURL = $_SERVER['SERVER_NAME'];
else
$currentURL = $primaryServerName;
$primaryServerNameWithoutProtocol = null;
if (str_contains($primaryServerName, 'http://')) {
$primaryServerNameWithoutProtocol = explode('http://', $primaryServerName)[1];
} else if (str_contains($primaryServerName, 'https://')) {
$primaryServerNameWithoutProtocol = explode('https://', $primaryServerName)[1];
}
if ($currentURL == $primaryServerNameWithoutProtocol) {
return true;
} else {
return false;
}
}
protected function getAllRegisteredDomains()
{
$domains = $this->company->all();
return $domains;
}
public function getCurrent()
{
$superAdmin = new SuperAdmin;
$primaryServerName = config('app.url');
if (isset($_SERVER['SERVER_NAME']))
$currentURL = $_SERVER['SERVER_NAME'];
else
$currentURL = $primaryServerName;
if (str_contains($primaryServerName, 'http://')) {
$primaryServerNameWithoutProtocol = explode('http://', $primaryServerName)[1];
} else if (str_contains($primaryServerName, 'https://')) {
$primaryServerNameWithoutProtocol = explode('https://', $primaryServerName)[1];
}
if (str_contains($currentURL, 'http://')) {
$currentURL = explode('http://', $currentURL)[1];
} else if (str_contains($currentURL, 'http://')) {
$currentURL = explode('http://', $currentURL)[1];
}
if ($currentURL == $primaryServerNameWithoutProtocol) {
if (session()->has('company')) {
$company = session()->get('company');
} else {
$company = 'super-company';
session()->put('company', $company);
}
return $company;
} else {
if (session()->has('company')) {
$company = session()->get('company');
}else {
$company = $this->company->findWhere(['domain' => $currentURL])->first();
if ($company->is_active == 0) {
throw new \Exception('company_blocked_by_administrator', 400);
}
session()->put('company', $company);
}
return $company;
}
}
/**
* Returns if there are companies
* already created
*/
public function count()
{
return $this->company->findWhere([['id', '>', '0']])->count();
}
public function getPrimaryUrl()
{
if (str_contains(env('APP_URL'), 'http://')) {
$primaryServerNameWithoutProtocol = explode('http://', env('APP_URL'))[1];
} else if (str_contains($primaryServerName, 'https://')) {
$primaryServerNameWithoutProtocol = explode('https://', env('APP_URL'))[1];
}
return $primaryServerNameWithoutProtocol;
}
}

View File

@ -0,0 +1,11 @@
<?php
return [
[
'key' => 'company',
'name' => 'saas::app.menu.companies',
'route' => 'super.companies.index',
'sort' => 1,
'icon-class' => 'settings-icon',
]
];

View File

@ -0,0 +1,92 @@
<?php
namespace Webkul\SAASCustomizer\DataGrids;
use Webkul\Ui\DataGrid\DataGrid;
use DB;
/**
* Companies DataGrid class
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CompaniesDataGrid extends DataGrid
{
protected $index = 'id'; //the column that needs to be treated as index column
protected $sortOrder = 'desc'; //asc or desc
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('companies')
->select('id')
->addSelect('id', 'name', 'domain', 'is_active');
$this->setQueryBuilder($queryBuilder);
}
public function addColumns()
{
$this->addColumn([
'index' => 'id',
'label' => trans('admin::app.datagrid.id'),
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'name',
'label' => trans('admin::app.datagrid.name'),
'type' => 'string',
'searchable' => false,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'domain',
'label' => trans('saas::app.datagrid.domain'),
'type' => 'string',
'searchable' => false,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'is_active',
'label' => trans('admin::app.datagrid.status'),
'type' => 'boolean',
'searchable' => false,
'sortable' => true,
'filterable' => true,
'closure' => true,
'wrapper' => function ($row) {
if ($row->is_active ==1) {
return '<i class="icon graph-up-icon"></i>';
} else {
return '<i class="icon graph-down-icon"></i>';
}
}
]);
}
public function prepareActions()
{
$this->addAction([
'type' => 'View',
'method' => 'GET', //use post only for redirects only
'route' => 'super.companies.show-stats',
'icon' => 'icon eye-icon'
]);
$this->addAction([
'type' => 'View',
'method' => 'GET', //use post only for redirects only
'route' => 'super.companies.edit',
'icon' => 'icon pencil-lg-icon'
]);
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace Webkul\SAASCustomizer\Database;
use Illuminate\Database\DatabaseManager as BaseDatabaseManager;
use Company;
/**
* @mixin \Illuminate\Database\Connection
*/
class DatabaseManager extends BaseDatabaseManager
{
/**
* Begin a fluent query against a database table.
*
* @param string $table
* @return \Illuminate\Database\Query\Builder
*/
public function table($table)
{
$company = Company::getCurrent();
if (! auth()->guard('super-admin')->check()) {
if (count(explode('as', $table)) == 1) {
if ($table == 'companies' || $table == 'country_states' || $table == 'countries') {
return $this->query()->from($table);
} else {
return $this->query()->from($table)->where($table . '.company_id', $company->id);
}
} else if (count(explode('as', $table)) == 2) {
$name = explode('as', $table);
$tempName = trim($name[0]);
if ($tempName == 'companies' || $tempName == 'country_states' || $tempName == 'countries') {
return $this->query()->from($table);
} else {
return $this->query()->from($table)->where(trim($name[1]) . '.company_id', $company->id);
}
} else {
throw \Exception('Unusual Entities');
}
} else {
return $this->query()->from($table);
}
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Webkul\SAASCustomizer\Database\Eloquent;
use Illuminate\Database\Eloquent\Builder as BaseBuilder;
use Illuminate\Pagination\Paginator;
/**
* @mixin \Illuminate\Database\Query\Builder
*/
class Builder extends BaseBuilder
{
}

View File

@ -0,0 +1,45 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCompaniesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('companies', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('email')->nullable();
$table->string('username')->unique();
$table->string('logo')->nullable();
$table->string('domain')->unique();
$table->string('city')->nullable();
$table->string('state')->nullable();
$table->string('zip_code')->nullable();
$table->string('country')->nullable();
$table->text('address1')->nullable();
$table->text('address2')->nullable();
$table->text('description')->nullable();
$table->json('more_info')->nullable();
$table->boolean('is_active')->default(1);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('companies');
}
}

View File

@ -0,0 +1,248 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AlterAllUniqueContraints extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// Attribute package migration alterations
Schema::table('attributes', function (Blueprint $table) {
$table->dropUnique('attributes_code_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->unique(['code', 'company_id'], 'attribute_company_code_unique_index');
});
Schema::table('attribute_families', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('attribute_groups', function (Blueprint $table) {
$table->dropForeign(['attribute_family_id']);
$table->dropUnique('attribute_groups_attribute_family_id_name_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->foreign('attribute_family_id')->references('id')->on('attribute_families')->onDelete('cascade');
$table->unique(['attribute_family_id', 'name', 'company_id'], 'attribute_family_id_name_company_id_unique_index');
});
// Category package migration alterations
Schema::table('categories', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('category_translations', function (Blueprint $table) {
$table->dropForeign(['category_id']);
$table->dropUnique('category_translations_category_id_slug_locale_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->unique(['category_id', 'slug', 'locale', 'company_id'], 'id_slug_locale_company_id_unique_index');
});
// Checkout package migration alterations
Schema::table('cart', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
// Core package migration alterations
Schema::table('channels', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('core_config', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('currencies', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('currency_exchange_rates', function(Blueprint $table) {
$table->dropForeign(['target_currency']);
$table->dropUnique('currency_exchange_rates_target_currency_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->foreign('target_currency')->references('id')->on('currencies')->onDelete('cascade');
$table->unique(['target_currency', 'company_id'], 'target_currency_company_id_unique_id');
});
Schema::table('locales', function(Blueprint $table) {
$table->dropUnique('locales_code_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->unique(['code', 'company_id'], 'code_company_id_unqiue_index');
});
Schema::table('sliders', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('subscribers_list', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
// customer package table alterations
Schema::table('customers', function (Blueprint $table) {
$table->dropUnique('customers_email_unique');
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->unique(['email', 'company_id']);
});
// Schema::table('customer_password_resets', function (Blueprint $table) {
// $table->integer('company_id')->unsigned()->after('email');
// $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
// });
Schema::table('customer_addresses', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('customer_groups', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('wishlist', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
// Inventory package table alterations
Schema::table('inventory_sources', function (Blueprint $table) {
$table->dropUnique('inventory_sources_code_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->unique(['code', 'company_id'], 'code_company_id_unique');
});
// product package table alterations
Schema::table('products', function (Blueprint $table) {
$table->dropUnique('products_sku_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->unique(['sku', 'company_id'], 'sku_company_id_unique');
});
Schema::table('product_flat', function (Blueprint $table) {
$table->dropForeign(['product_id']);
$table->dropUnique('product_flat_unique_index');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->unique(['product_id', 'channel', 'locale', 'company_id'], 'product_flat_unique_index');
});
Schema::table('product_attribute_values', function (Blueprint $table) {
$table->dropUnique('chanel_locale_attribute_value_index_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->unique(['channel', 'locale', 'attribute_id', 'product_id', 'company_id'], 'channel_locale_attr_id_product_id_company_unique');
});
Schema::table('product_inventories', function (Blueprint $table) {
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('product_reviews', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
// sales package table alterations
Schema::table('invoices', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('invoice_items', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('orders', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('order_items', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('order_address', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('order_payment', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('shipments', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
// Schema::table('shipment_items', function (Blueprint $table) {
// $table->integer('company_id')->unsigned()->after('id');
// $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
// });
// tax package table alterations
Schema::table('tax_categories', function (Blueprint $table) {
$table->dropUnique('tax_categories_code_unique');
$table->dropUnique('tax_categories_name_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->unique(['name', 'company_id']);
$table->unique(['code', 'company_id']);
});
Schema::table('tax_rates', function (Blueprint $table) {
$table->dropUnique('tax_rates_identifier_unique');
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->unique(['identifier', 'company_id']);
});
Schema::table('roles', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
Schema::table('admins', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
}

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCompanyPersonalDetailsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('company_personal_details', function (Blueprint $table) {
$table->increments('id');
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('email')->nullable()->unique();
$table->string('skype')->nullable();
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->json('more_info')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('company_personal_details');
}
}

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSuperAdminsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('super_admins', function (Blueprint $table) {
$table->enum('id', [1])->unique();
$table->string('email');
$table->string('password');
$table->boolean('status')->default(1);
$table->string('remember_token')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('super_admins');
}
}

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AlterCatalogRulesTables extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// Checkout package migration alterations
Schema::table('cart_rules', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->after('id');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -0,0 +1,108 @@
<?php
namespace Webkul\SAASCustomizer\Exceptions;
use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\PDOException;
use Illuminate\Database\Eloquent\ErrorException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
protected $jsonErrorMessages = [
404 => 'Resource not found',
403 => '403 forbidden Error',
401 => 'Unauthenticated',
500 => '500 Internal Server Error',
];
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
$path = 'saas';
if ($exception->getMessage() == 'domain_not_found') {
return $this->response($path, 500, 'Domain Not Found');
}
if ($exception->getMessage() == 'company_blocked_by_administrator') {
return $this->response($path, 400, 'This seller is blocked');
}
if ($exception->getMessage() == 'not_allowed_to_visit_this_section') {
return $this->response($path, 400, 'You are not allowed to use this section');
}
if ($exception->getMessage() == 'invalid_admin_login' || $exception->getMessage() == 'invalid_customer_login') {
return $this->responseCustom($path, 400, 'auth', 'Authentication Error');
}
if ($exception instanceof HttpException) {
$statusCode = in_array($exception->getStatusCode(), [401, 403, 404, 503]) ? $exception->getStatusCode() : 500;
return $this->response($path, $statusCode);
} else if ($exception instanceof ModelNotFoundException) {
return $this->response($path, 404);
} else if ($exception instanceof PDOException) {
return $this->response($path, 500);
}
return parent::render($request, $exception);
}
/**
* Convert an authentication exception into a response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Auth\AuthenticationException $exception
* @return \Illuminate\Http\Response
*/
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => $this->jsonErrorMessages[401]], 401);
}
return redirect()->guest(route('super.session.index'));
}
private function isAdminUri()
{
return strpos($_SERVER['REQUEST_URI'], 'super') !== false ? true : false;
}
private function response($path, $statusCode, $message = null)
{
if (request()->expectsJson()) {
return response()->json([
'error' => isset($this->jsonErrorMessages[$statusCode])
? $this->jsonErrorMessages[$statusCode]
: 'Something went wrong, please try again later.'
], $statusCode);
}
return response()->view("{$path}::errors.{$statusCode}", ['message' => $message, 'status' => $statusCode], $statusCode);
}
private function responseCustom($path, $statusCode, $view, $message = null)
{
if (request()->expectsJson()) {
return response()->json([
'error' => isset($this->jsonErrorMessages[$statusCode])
? $this->jsonErrorMessages[$statusCode]
: 'Something went wrong, please try again later.'
], $statusCode);
}
return response()->view("{$path}::errors.{$view}", ['message' => $message, 'status' => $statusCode], $statusCode);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Webkul\SAASCustomizer\Facades;
use Illuminate\Support\Facades\Facade;
class Company extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'company';
}
}

View File

@ -0,0 +1,562 @@
<?php
namespace Webkul\SAASCustomizer\Helpers;
use Carbon\Carbon;
use DB;
use Company;
use Webkul\Category\Repositories\CategoryRepository as Category;
use Webkul\Inventory\Repositories\InventorySourceRepository as Inventory;
use Webkul\Core\Repositories\LocaleRepository as Locale;
use Webkul\Core\Repositories\CurrencyRepository as Currency;
use Webkul\Core\Repositories\ChannelRepository as Channel;
use Webkul\Attribute\Repositories\AttributeRepository as Attribute;
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
use Webkul\Attribute\Repositories\AttributeFamilyRepository as AttributeFamily;
use Webkul\Attribute\Repositories\AttributeGroupRepository as AttributeGroup;
use Webkul\Customer\Repositories\CustomerGroupRepository as CustomerGroup;
use Log;
/**
* Class meant for preparing functional and sample data required for functioning of a new seller
*/
class DataPurger
{
/**
* Company Repository Object
*/
protected $company;
/**
* CategoryRepository Object
*/
protected $category;
/**
* InventoryRepository Object
*/
protected $inventory;
/**
* LocaleRepository Object
*/
protected $locale;
/**
* CurrencyRepository Object
*/
protected $currency;
/**
* ChannelRepository Object
*/
protected $channel;
/**
* AttributeRepository Object
*/
protected $attribute;
/**
* AttributeFamilyRepository Object
*/
protected $attributeFamily;
/**
* AttributeGroupRepository Object
*/
protected $attributeGroup;
/**
* CustomerGroupRepository Object
*/
protected $customerGroup;
protected $seedCompleted = true;
public function __construct(
Category $category,
Inventory $inventory,
Locale $locale,
Currency $currency,
Channel $channel,
Attribute $attribute,
AttributeFamily $attributeFamily,
AttributeGroup $attributeGroup,
CustomerGroup $customerGroup
)
{
// $this->company = Company::getCurrent();
$this->category = $category;
$this->inventory = $inventory;
$this->locale = $locale;
$this->currency = $currency;
$this->channel = $channel;
$this->attribute = $attribute;
$this->attributeFamily = $attributeFamily;
$this->attributeGroup = $attributeGroup;
$this->customerGroup = $customerGroup;
}
/**
* Prepare data for the customer groups
*/
public function prepareCustomerGroupData()
{
$this->company = Company::getCurrent();
$data = [
'code' => 'guest',
'name' => 'Guest',
'is_user_defined' => 0,
];
$customerGroup0 = $this->customerGroup->create($data);
// default customer group 1
$data = [
'id' => 1,
'code' => 'general',
'name' => 'General',
'is_user_defined' => 0,
'company_id' => $this->company->id
];
$customerGroup1 = $this->customerGroup->create($data);
// default customer group 2
$data = [
'id' => 2,
'code' => 'wholesale',
'name' => 'Wholesale',
'is_user_defined' => 0,
'company_id' => $this->company->id
];
$customerGroup2 = $this->customerGroup->create($data);
return ['default' => $customerGroup1, 'wholesale' => $customerGroup2];
}
/**
* Prepares category data
*/
public function prepareCategoryData()
{
$this->company = Company::getCurrent();
$data = [
'position' => '1',
'image' => NULL,
'status' => '1',
'parent_id' => NULL,
'name' => 'Root',
'slug' => 'root',
'description' => 'Root',
'meta_title' => '',
'meta_description' => '',
'meta_keywords' => '',
'locale' => 'all',
'company_id' => $this->company->id
];
$category = $this->category->create($data);
return $category;
}
/**
* Prepares data for a default inventory
*/
public function prepareInventoryData()
{
$this->company = Company::getCurrent();
$data = [
'code' => 'default',
'name' => 'Default',
'contact_name' => 'Detroit Warehouse',
'contact_email' => 'warehouse@example.com',
'contact_number' => '9876543210',
'status' => 1,
'country' => 'US',
'state' => 'MI',
'street' => '12th Street',
'city' => 'Detroit',
'postcode' => '48127',
'company_id' => $this->company->id
];
return $this->inventory->create($data);
}
/**
* Creates a default locale
*/
public function prepareLocaleData()
{
$this->company = Company::getCurrent();
$data = [
'code' => 'en',
'name' => 'English',
'company_id' => $this->company->id
];
return $this->locale->create($data);
}
/**
* Prepares a default currency
*/
public function prepareCurrencyData()
{
$this->company = Company::getCurrent();
$data = [
'code' => 'USD',
'name' => 'US Dollar',
'company_id' => $this->company->id
];
return $this->currency->create($data);
}
/**
* Prepares a default channel
*/
public function prepareChannelData()
{
$this->company = Company::getCurrent();
$inventorySource = $this->inventory->findOneWhere(['company_id' => $this->company->id]);
$locale = $this->locale->findOneWhere(['company_id' => $this->company->id]);
$currency = $this->currency->findOneWhere(['company_id' => $this->company->id]);
$category = $this->category->findOneWhere(['company_id' => $this->company->id]);
$data = [
'code' => 'default',
'name' => 'Default Channel',
'description' => 'Default Channel',
"inventory_sources" => [
0 => $inventorySource->id
],
"root_category_id" => $category->id,
'hostname' => $this->company->domain,
'locales' => [
0 => $locale->id
],
"default_locale_id" => $locale->id,
'currencies' => [
0 => $currency->id
],
'base_currency_id' => $currency->id,
'theme' => 'default',
'home_page_content' => '<p>@include("shop::home.slider") @include("shop::home.featured-products") @include("shop::home.new-products")</p><div class="banner-container"><div class="left-banner"><img src="https://s3-ap-southeast-1.amazonaws.com/cdn.uvdesk.com/website/1/201902045c581f9494b8a1.png" /></div><div class="right-banner"><img src="https://s3-ap-southeast-1.amazonaws.com/cdn.uvdesk.com/website/1/201902045c581fb045cf02.png" /> <img src="https://s3-ap-southeast-1.amazonaws.com/cdn.uvdesk.com/website/1/201902045c581fc352d803.png" /></div></div>',
'footer_content' => '<div class="list-container"><span class="list-heading">Quick Links</span><ul class="list-group"><li><a href="#">About Us</a></li><li><a href="#">Return Policy</a></li><li><a href="#">Refund Policy</a></li><li><a href="#">Terms and conditions</a></li><li><a href="#">Terms of Use</a></li><li><a href="#">Contact Us</a></li></ul></div><div class="list-container"><span class="list-heading">Connect With Us</span><ul class="list-group"><li><a href="#"><span class="icon icon-facebook"></span>Facebook </a></li><li><a href="#"><span class="icon icon-twitter"></span> Twitter </a></li><li><a href="#"><span class="icon icon-instagram"></span> Instagram </a></li><li><a href="#"> <span class="icon icon-google-plus"></span>Google+ </a></li><li><a href="#"> <span class="icon icon-linkedin"></span>LinkedIn </a></li></ul></div>',
'company_id' => $this->company->id
];
return $this->channel->create($data);
// $newChannel->locales()->sync($data['locales']);
// $newChannel->currencies()->sync($data['currencies']);
// $newChannel->inventory_sources()->sync($data['inventory_sources']);
// $this->uploadImages($data, $channel);
// $this->uploadImages($data, $channel, 'favicon');
}
/**
* Prepare Attribute Data
*/
public function prepareAttributeData()
{
$this->company = Company::getCurrent();
$sku = ['code' => 'sku','admin_name' => 'SKU','type' => 'text','validation' => NULL,'position' => '1','is_required' => '1','is_unique' => '1','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'SKU']];
$this->attribute->create($sku);
$name = ['code' => 'name', 'admin_name' => 'Name', 'type' => 'text', 'validation' => NULL, 'position' => '2', 'is_required' => '1', 'is_unique' => '0', 'value_per_locale' => '1', 'value_per_channel' => '1', 'is_filterable' => '0', 'is_configurable' => '0', 'is_user_defined' => '0', 'is_visible_on_front' => '0', 'company_id' => $this->company->id,'en' => ['name' => 'Name']];
$this->attribute->create($name);
$url_key = ['code' => 'url_key', 'admin_name' => 'URL Key', 'type' => 'text', 'validation' => NULL, 'position' => '3', 'is_required' => '1', 'is_unique' => '1', 'value_per_locale' => '0', 'value_per_channel' => '0', 'is_filterable' => '0', 'is_configurable' => '0', 'is_user_defined' => '0', 'is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'URL Key']];
$this->attribute->create($url_key);
$taxCategoryId = ['code' => 'tax_category_id', 'admin_name' => 'Tax Category', 'type' => 'select', 'validation' => NULL, 'position' => '4', 'is_required' => '0', 'is_unique' => '0', 'value_per_locale' => '0', 'value_per_channel' => '1', 'is_filterable' => '0', 'is_configurable' => '0', 'is_user_defined' => '0', 'is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Tax Category']];
$this->attribute->create($taxCategoryId);
$new = ['code' => 'new', 'admin_name' => 'New', 'type' => 'boolean', 'validation' => NULL, 'position' => '5', 'is_required' => '0', 'is_unique' => '0', 'value_per_locale' => '0', 'value_per_channel' => '0', 'is_filterable' => '0','is_configurable' => '0', 'is_user_defined' => '0', 'is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'New']];
$this->attribute->create($new);
$featured = ['id' => '6', 'code' => 'featured', 'admin_name' => 'Featured', 'type' => 'boolean', 'validation' => NULL, 'position' => '6', 'is_required' => '0', 'is_unique' => '0', 'value_per_locale' => '0', 'value_per_channel' => '0', 'is_filterable' => '0', 'is_configurable' => '0', 'is_user_defined' => '0', 'is_visible_on_front' => '0', 'company_id' => 1, 'en' => ['name' => 'Featured']];
$this->attribute->create($featured);
$visibleIndividually = ['code' => 'visible_individually','admin_name' => 'Visible Individually','type' => 'boolean','validation' => NULL,'position' => '7','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Visible Individually']];
$this->attribute->create($visibleIndividually);
$status = ['code' => 'status','admin_name' => 'Status','type' => 'boolean','validation' => NULL,'position' => '8','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Status']];
$this->attribute->create($status);
$shortDesc = ['code' => 'short_description','admin_name' => 'Short Description','type' => 'textarea','validation' => NULL,'position' => '9','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Short Description']];
$this->attribute->create($shortDesc);
$desc = ['code' => 'description','admin_name' => 'Description','type' => 'textarea','validation' => NULL,'position' => '10','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Description']];
$this->attribute->create($desc);
$price = ['code' => 'price','admin_name' => 'Price','type' => 'price','validation' => 'decimal','position' => '11','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Price']];
$this->attribute->create($price);
$cost = ['code' => 'cost','admin_name' => 'Cost','type' => 'price','validation' => 'decimal','position' => '12','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0', 'company_id' => 1, 'en' => ['name' => 'Cost']];
$this->attribute->create($cost);
$specialPrice = ['code' => 'special_price','admin_name' => 'Special Price','type' => 'price','validation' => 'decimal','position' => '13','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Special Price']];
$this->attribute->create($specialPrice);
$specialFrom = ['code' => 'special_price_from','admin_name' => 'Special Price From','type' => 'date','validation' => NULL,'position' => '14','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Special Price From']];
$this->attribute->create($specialFrom);
$specialTo = ['code' => 'special_price_to','admin_name' => 'Special Price To','type' => 'date','validation' => NULL,'position' => '15','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Special Price To']];
$this->attribute->create($specialTo);
$metaTitle = ['code' => 'meta_title','admin_name' => 'Meta Title','type' => 'textarea','validation' => NULL,'position' => '16','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Meta Title']];
$this->attribute->create($metaTitle);
$metaKeywords = ['code' => 'meta_keywords','admin_name' => 'Meta Keywords','type' => 'textarea','validation' => NULL,'position' => '17','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0', 'is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','company_id' => $this->company->id, 'en' => ['name' => 'Meta Keywords']];
$this->attribute->create($metaKeywords);
$metaDesc = ['code' => 'meta_description','admin_name' => 'Meta Description','type' => 'textarea','validation' => NULL,'position' => '18','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Meta Description']];
$this->attribute->create($metaDesc);
$width = ['code' => 'width','admin_name' => 'Width','type' => 'text','validation' => 'decimal','position' => '19','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Width']];
$this->attribute->create($width);
$height = ['code' => 'height','admin_name' => 'Height','type' => 'text','validation' => 'decimal','position' => '20','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Height']];
$this->attribute->create($height);
$depth = ['code' => 'depth','admin_name' => 'Depth','type' => 'text','validation' => 'decimal','position' => '21','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Depth']];
$this->attribute->create($depth);
$weight = ['code' => 'weight','admin_name' => 'Weight','type' => 'text','validation' => 'decimal','position' => '22','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','company_id' => $this->company->id, 'en' => ['name' => 'Weight']];
$this->attribute->create($weight);
$color = ['code' => 'color','admin_name' => 'Color','type' => 'select','validation' => NULL,'position' => '23','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '1','is_user_defined' => '1','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Color'], 'options' => [
'option_0' => ['admin_name' => 'Red', 'en' => ['label' => 'Red'], 'sort_order' => '1'],
'option_1' => ['admin_name' => 'Green', 'en' => ['label' => 'Green'],'sort_order' => '2'],
'option_2' => ['admin_name' => 'Yellow', 'en' => ['label' => 'Yellow'], 'sort_order' => '3'],
'option_3' => ['admin_name' => 'Black', 'en' => ['label' => 'Black'], 'sort_order' => '4'],
'option_4' => ['admin_name' => 'White', 'en' => ['label' => 'White'], 'sort_order' => '5']
]];
$this->attribute->create($color);
$size = ['code' => 'size','admin_name' => 'Size','type' => 'select','validation' => NULL,'position' => '24','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '1','is_user_defined' => '1','is_visible_on_front' => '0', 'company_id' => $this->company->id, 'en' => ['name' => 'Size'], 'options' => [
'option_0' => ['id' => '6','admin_name' => 'S', 'en' => ['label' => 'S'], 'sort_order' => '1'],
'option_1' => ['id' => '7','admin_name' => 'M', 'en' => ['label' => 'M'], 'sort_order' => '2'],
'option_2' => ['id' => '8','admin_name' => 'L', 'en' => ['label' => 'L'], 'sort_order' => '3'],
'option_3' => ['id' => '9','admin_name' => 'XL', 'en' => ['label' => 'XL'], 'sort_order' => '4']
]];
$this->attribute->create($size);
return true;
}
/**
* To prepare the attribute family
*/
public function prepareAttributeFamilyData()
{
$this->company = Company::getCurrent();
$data = ['code' => 'default', 'name' => 'Default', 'status' => '0', 'is_user_defined' => '1', 'company_id' => $this->company->id];
$attributeFamily = $this->attributeFamily->create($data);
return $attributeFamily;
}
/**
* To prepare the attribute group mappings
*/
public function prepareAttributeGroupData()
{
$this->company = Company::getCurrent();
$attributeFamily = $this->attributeFamily->findOneWhere(['company_id' => $this->company->id]);
$attributes = $this->attribute->all();
$group1 = ['sku', 'name', 'url_key', 'tax_category_id', 'new', 'featured', 'visible_individually', 'status', 'color', 'size'];
$group2 = ['short_description', 'description'];
$group3 = ['meta_title', 'meta_keywords', 'meta_description'];
$group4 = ['price', 'cost', 'special_price', 'special_price_from', 'special_price_to'];
$group5 = ['width', 'height', 'depth', 'weight'];
// creating group 1
$this->attributeGroup->create(['name' => 'General', 'position' => '1', 'is_user_defined' => '0', 'attribute_family_id' => $attributeFamily->id, 'company_id' => $this->company->id]);
$attributeGroup = $this->attributeGroup->findOneWhere(['name' => 'General']);
$i = 1;
foreach($group1 as $code) {
$i++;
foreach ($attributes as $value) {
if($value->code == $code) {
DB::table('attribute_group_mappings')->insert([
['attribute_id' => $value->id, 'attribute_group_id' => $attributeGroup->id, 'position' => $i]
]);
}
}
}
// creating group 2
$g2 = $this->attributeGroup->create(['name' => 'Description', 'position' => '2', 'is_user_defined' => '0', 'attribute_family_id' => $attributeFamily->id, 'company_id' => $this->company->id]);
$attributeGroup = $this->attributeGroup->findOneWhere(['name' => 'Description']);
$i = 1;
foreach($group2 as $code) {
$i++;
foreach ($attributes as $value) {
if($value->code == $code) {
DB::table('attribute_group_mappings')->insert([
['attribute_id' => $value->id, 'attribute_group_id' => $attributeGroup->id, 'position' => $i]
]);
}
}
}
// creating group 3
$g3 = $this->attributeGroup->create(['name' => 'Meta Description', 'position' => '3', 'is_user_defined' => '0', 'attribute_family_id' => $attributeFamily->id, 'company_id' => $this->company->id]);
$attributeGroup = $this->attributeGroup->findOneWhere(['name' => 'Meta Description']);
$i = 1;
foreach($group3 as $code) {
$i++;
foreach ($attributes as $value) {
if($value->code == $code) {
DB::table('attribute_group_mappings')->insert([
['attribute_id' => $value->id, 'attribute_group_id' => $attributeGroup->id, 'position' => $i]
]);
}
}
}
// creating group 4
$g4 = $this->attributeGroup->create(['name' => 'Price', 'position' => '4', 'is_user_defined' => '0', 'attribute_family_id' => $attributeFamily->id, 'company_id' => $this->company->id]);
$attributeGroup = $this->attributeGroup->findOneWhere(['name' => 'Price']);
$i = 1;
foreach($group4 as $code) {
$i++;
foreach ($attributes as $value) {
if($value->code == $code) {
DB::table('attribute_group_mappings')->insert([
['attribute_id' => $value->id, 'attribute_group_id' => $attributeGroup->id, 'position' => $i]
]);
}
}
}
// creating group 5
$g5 = $this->attributeGroup->create(['name' => 'Shipping', 'position' => '5', 'is_user_defined' => '0', 'attribute_family_id' => $attributeFamily->id, 'company_id' => $this->company->id]);
$attributeGroup = $this->attributeGroup->findOneWhere(['name' => 'Shipping']);
$i = 1;
foreach($group5 as $code) {
$i++;
foreach ($attributes as $value) {
if($value->code == $code) {
DB::table('attribute_group_mappings')->insert([
['attribute_id' => $value->id, 'attribute_group_id' => $attributeGroup->id, 'position' => $i]
]);
}
}
}
return true;
}
/**
* To prepare the country state data for
* admin and customers country & state fields
* auto population
*/
public function prepareCountryStateData()
{
$countries = json_decode(file_get_contents(base_path().'/packages/Webkul/Core/src/Data/countries.json'), true);
DB::table('countries')->insert($countries);
$states = json_decode(file_get_contents(base_path().'/packages/Webkul/Core/src/Data/states.json'), true);
DB::table('country_states')->insert($states);
return true;
}
/**
* It will store a check in the companies
* that all the necessary data had been
* inserted successfully or not
*
* @param boolean seedCompleted
*/
public function setInstallationCompleteParam()
{
$this->seedCompleted = true;
$info = [
'company_created' => true,
'seeded' => true,
];
$info = json_encode($info);
$this->company->update([
'more_info' => $info
]);
return true;
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace Webkul\SAASCustomizer\Helpers;
use Company;
use DB;
use Webkul\Category\Repositories\CategoryRepository as Category;
use Webkul\Inventory\Repositories\InventorySourceRepository as Inventory;
use Webkul\Core\Repositories\LocaleRepository as Locale;
use Webkul\Core\Repositories\CurrencyRepository as Currency;
use Webkul\Core\Repositories\ChannelRepository as Channel;
use Webkul\Attribute\Repositories\AttributeRepository as Attribute;
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
use Webkul\Attribute\Repositories\AttributeFamilyRepository as AttributeFamily;
use Webkul\Attribute\Repositories\AttributeGroupRepository as AttributeGroup;
use Webkul\Customer\Repositories\CustomerGroupRepository as CustomerGroup;
use Webkul\Product\Repositories\ProductRepository as Product;
/**
* Class meant for extracting essential information about the seller
*/
class StatsPurger
{
protected $category;
protected $inventory;
protected $locale;
protected $currency;
protected $channel;
protected $attribute;
protected $attributeFamily;
protected $attributeGroup;
protected $customerGroup;
protected $product;
protected $seedCompleted = true;
public function __construct(
Category $category,
Inventory $inventory,
Locale $locale,
Currency $currency,
Channel $channel,
Attribute $attribute,
AttributeFamily $attributeFamily,
AttributeGroup $attributeGroup,
CustomerGroup $customerGroup,
Product $product
)
{
$this->category = $category;
$this->inventory = $inventory;
$this->locale = $locale;
$this->currency = $currency;
$this->channel = $channel;
$this->attribute = $attribute;
$this->attributeFamily = $attributeFamily;
$this->attributeGroup = $attributeGroup;
$this->customerGroup = $customerGroup;
$this->product = $product;
}
public function getAggregates($companyId)
{
$products = DB::table('products')->where('company_id', '=', $companyId)->count();
$attributes = DB::table('attributes')->where('company_id', '=', $companyId)->count();
$customers = DB::table('customers')->where('company_id', '=', $companyId)->count();
$customerGroups = DB::table('customer_groups')->where('company_id', '=', $companyId)->count();
$categories = DB::table('categories')->where('company_id', '=', $companyId)->count();
return [
'products' => $products,
'attributes' => $attributes,
'customers' => $customers,
'customer-groups' => $customerGroups,
'categories' => $categories
];
}
}

View File

@ -0,0 +1,234 @@
<?php
namespace Webkul\SAASCustomizer\Http\Controllers;
use Webkul\SAASCustomizer\Http\Controllers\Controller;
use Webkul\SAASCustomizer\Repositories\CompanyRepository;
use Webkul\SAASCustomizer\Repositories\CompanyDetailsRepository;
use Webkul\User\Repositories\AdminRepository as Admin;
use Webkul\User\Repositories\RoleRepository as Role;
use Webkul\SAASCustomizer\Helpers\DataPurger;
use Webkul\SAASCustomizer\Helpers\StatsPurger;
use Company;
use DB;
use Request;
use Validator;
/**
* Company controller
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CompanyController extends Controller
{
protected $attribute;
protected $_config;
protected $details;
protected $admin;
protected $role;
protected $dataSeed;
protected $companyStats;
public function __construct(CompanyRepository $company, CompanyDetailsRepository $details, Admin $admin, Role $role, DataPurger $dataSeed, StatsPurger $companyStats)
{
$this->company = $company;
$this->details = $details;
$this->admin = $admin;
$this->role = $role;
$this->dataSeed = $dataSeed;
$this->companyStats = $companyStats;
$this->_config = request('_config');
if (! Company::isAllowed()) {
abort(404);
}
}
public function showCompanyStats($id)
{
$aggregates = $this->companyStats->getAggregates($id);
$company = $this->company->find($id);
return view('saas::companies.company.index')->with('company', [$company, $aggregates]);
}
public function create()
{
if (session()->has('company')) {
session()->regenerate();
session()->forget('company');
}
return view($this->_config['view']);
}
protected function store()
{
$validator = Validator::make(Request::all(), [
'email' => 'required|email|max:191|unique:admins,email',
'password' => 'required|string|confirmed|min:6',
'username' => 'required|alpha_num|min:3|max:64',
'first_name' => 'required|string|max:191',
'last_name' => 'nullable|string|max:191',
'phone_no' => 'required|digits_between:10,11',
'org_name' => 'required|string|max:191'
]);
$data = Request::all();
$authEmail = $data['email'];
unset($data['email']);
if ($validator->fails()) {
return response()->json(['success' => false, 'errors' => $validator->errors()], 403);
}
$validator = Validator::make(Request::all(), [
'username' => 'not_in:www,http,https,WWW,HTTP,HTTPS'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'errors' => $validator->errors()
], 403);
}
if (strtolower($data['username']) == 'www' || strtolower($data['username']) == 'http' || strtolower($data['username']) == 'https') {
session()->flash('warning', 'Illegal subdomain name');
}
$data['name'] = $data['org_name'];
unset($data['org_name']);
$primaryServerName = config('app.url');
if (str_contains($primaryServerName, 'http://')) {
$primaryServerNameWithoutProtocol = explode('http://', $primaryServerName)[1];
} else if (str_contains($primaryServerName, 'https://')) {
$primaryServerNameWithoutProtocol = explode('https://', $primaryServerName)[1];
}
$data['domain'] = strtolower($data['username']). '.' . $primaryServerNameWithoutProtocol;
$validator = Validator::make($data, [
'domain' => 'required|unique:companies,domain'
]);
if ($validator->fails()) {
return response()->json(['success' => false, 'errors' => $validator->errors()], 403);
}
$company = $this->company->create($data);
if ($company) {
$info = [
'created' => true,
'seeded' => false
];
$info = json_encode($info);
$company->update([
'extra_info' => $info
]);
$data['password'] = bcrypt($data['password']);
$data['name'] = $data['first_name'].' '.$data['last_name'];
$data['status'] = 1;
//creates a new full privilege role when new company is registered
$role = $this->role->create([
'name' => 'Administrator',
'description' => 'Administrator role',
'permission_type' => 'all',
'company_id' => $company->id
]);
$data['role_id'] = $role->id;
$data['email'] = $authEmail;
$data['company_id'] = $company->id;
//creates a new full privilege admin with newly created role above
$this->admin->create($data);
//creates the personal details record for the company
$this->details->create($data);
if (session()->has('company')) {
session()->forget('company');
session()->put('company', $company);
} else {
session()->put('company', $company);
}
return response()->json([
'success' => true, 'redirect' => $data['domain']
], 200);
} else {
return response()->json([
'success' => false
], 403);
}
}
public function edit($id)
{
$company = $this->company->findOrFail($id);
return view('saas::companies.company.edit')->with('company', $company);
}
public function update($id)
{
$this->validate(request(), [
'email' => 'required|email|max:191|unique:companies,email,'.$id,
'name' => 'required|string|max:191|unique:companies,name,'.$id,
'domain' => 'required|string|max:191|unique:companies,domain,'.$id,
'is_active' => 'required|boolean'
]);
$data = request()->all();
$company = $this->company->findOrFail($id);
if ($company) {
$result = $company->update($data);
if ($result) {
session()->flash('success', 'Company Updated Successfully');
} else {
session()->flash('warning', 'Something went wrong');
}
} else {
session()->flash('warning', 'Something went wrong');
}
return redirect()->back();
}
protected function changeStatus($id)
{
$company = $this->company->find($id);
if ($company->is_active == 0) {
$company->update([
'is_active' => 1
]);
session()->flash('success', 'Company successfully activated');
} else {
$company->update([
'is_active' => 0
]);
session()->flash('warning', 'Company successfully deactivated');
}
return redirect()->back();
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Webkul\SAASCustomizer\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@ -0,0 +1,55 @@
<?php
namespace Webkul\SAASCustomizer\Http\Controllers;
use Webkul\SAASCustomizer\Http\Controllers\Controller;
use Webkul\SAASCustomizer\Helpers\DataPurger;
use Event;
use Company;
/**
* Purge controller
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class PurgeController extends Controller
{
protected $dataSeed;
public function __construct(DataPurger $dataSeed)
{
$this->dataSeed = $dataSeed;
$this->_config = request('_config');
}
public function seedDatabase()
{
if (session()->has('company')) {
session()->forget('company');
session()->regenerate();
}
$this->dataSeed->prepareLocaleData();
$this->dataSeed->prepareCategoryData(); //translation table not getting populated
$this->dataSeed->prepareInventoryData();
$this->dataSeed->prepareCurrencyData();
$this->dataSeed->prepareChannelData();
// need to get executed only first time
if (Company::count() == 1)
$this->dataSeed->prepareCountryStateData();
$this->dataSeed->prepareCustomerGroupData();
$this->dataSeed->prepareAttributeData();
$this->dataSeed->prepareAttributeFamilyData();
$this->dataSeed->prepareAttributeGroupData();
Event::fire('new.company.registered');
$this->dataSeed->setInstallationCompleteParam();
session()->flash('success', 'Store Created Successfully');
return redirect()->route('shop.home.index');
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace Webkul\SAASCustomizer\Http\Controllers;
use Webkul\SAASCustomizer\Http\Controllers\Controller;
use Webkul\SAASCustomizer\Models\SuperAdmin;
use Company;
/**
* Super User controller
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class SuperUserController extends Controller
{
public function __construct()
{
$this->middleware('auth:super-admin', ['only' => ['list']]);
}
/**
* To show the login screen
*/
public function index()
{
if (! auth()->guard('super-admin')->check()) {
return view('saas::companies.auth.login');
} else {
return redirect()->route('super.session.index');
}
}
public function store()
{
$this->validate(request(), [
'email' => 'required|email',
'password' => 'required'
]);
if (! auth()->guard('super-admin')->attempt(request(['email', 'password']))) {
session()->flash('error', trans('admin::app.users.users.login-error'));
return redirect()->route('super.session.index');
}
session()->flash('success', 'Logged in successfully');
return redirect()->route('super.companies.index');
}
public function list()
{
return view('saas::companies.index');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy()
{
auth()->guard('super-admin')->logout();
return redirect()->route('super.session.index');
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace Webkul\SAASCustomizer\Http\Middleware;
use Webkul\SAASCustomizer\Repositories\CompanyRepository;
use Closure;
use Company;
use Validator;
class ValidatesDomain
{
/**
* @var CompanyRepository Instance
*/
protected $company;
public function __construct(CompanyRepository $company)
{
$this->company = $company;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$primaryServerName = config('app.url');
$currentURL = $_SERVER['SERVER_NAME'];
$params['domain'] = $currentURL;
$validator = Validator::make($params, [
'domain' => 'required|ip'
]);
if (str_contains($primaryServerName, 'http://')) {
$primaryServerNameWithoutProtocol = explode('http://', $primaryServerName)[1];
} else if (str_contains($primaryServerName, 'https://')) {
$primaryServerNameWithoutProtocol = explode('https://', $primaryServerName)[1];
}
//restricts the IP address usage to access the system
if ($validator->fails()) {
//case where IP validation fails
if (str_contains($currentURL, 'http://')) {
$currentURL = explode('http://', $currentURL)[1];
} else if (str_contains($currentURL, 'http://')) {
$currentURL = explode('http://', $currentURL)[1];
}
} else {
//case where IP validation passes then it should redirect to the main domain
return redirect()->route('company.home.index');
}
if ($currentURL == $primaryServerNameWithoutProtocol) {
if (request()->is('company/*') || request()->is('super/*')) {
return $next($request);
} else {
return redirect()->route('company.create.index');
}
} else {
if ((request()->is('company/*') || request()->is('super/*')) && ! request()->is('company/seed-data')) {
throw new \Exception('not_allowed_to_visit_this_section', 400);
} else {
$company = $this->company->findWhere(['domain' => $currentURL]);
if (count($company) == 1) {
return $next($request);
} else if (count($company) == 0) {
throw new \Exception('domain_not_found', 400);
} else {
return $next($request);
}
}
}
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace Webkul\SAASCustomizer\Listeners;
use Company;
/**
* New company registered events handler
*
* @author Prashant Singh <prashant.singh852@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CompanyRegistered
{
public function handle()
{
$company = Company::getCurrent();
foreach(config('purge-pool') as $key => $pool) {
$poolInstance = app($pool);
$poolInstance->createPreOrderData($company->id);
}
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Webkul\SAASCustomizer\Models\Attribute;
use Webkul\Attribute\Models\Attribute as BaseModel;
use Company;
class Attribute extends BaseModel
{
protected $fillable = ['code', 'admin_name', 'type', 'position', 'is_required', 'is_unique', 'validation', 'value_per_locale', 'value_per_channel', 'is_filterable', 'is_configurable', 'is_visible_on_front', 'is_user_defined', 'swatch_type', 'company_id'];
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
$company = Company::getCurrent();
if (auth()->guard('super-admin')->check() || ! isset($company->id)) {
return new \Illuminate\Database\Eloquent\Builder($query);
} else {
return new \Illuminate\Database\Eloquent\Builder($query->where('attributes' . '.company_id', $company->id));
}
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Webkul\SAASCustomizer\Models\Attribute;
use Webkul\Attribute\Models\AttributeFamily as BaseModel;
use Company;
class AttributeFamily extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
$company = Company::getCurrent();
if (auth()->guard('super-admin')->check() || ! isset($company->id)) {
return new \Illuminate\Database\Eloquent\Builder($query);
} else {
return new \Illuminate\Database\Eloquent\Builder($query->where('attribute_families' . '.company_id', $company->id));
}
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Webkul\SAASCustomizer\Models\Attribute;
use Webkul\Attribute\Models\AttributeGroup as BaseModel;
use Company;
class AttributeGroup extends BaseModel
{
protected $fillable = ['name', 'position', 'is_user_defined', 'company_id', 'attribute_family_id'];
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
$company = Company::getCurrent();
if (auth()->guard('super-admin')->check() || ! isset($company->id)) {
return new \Illuminate\Database\Eloquent\Builder($query);
} else {
return new \Illuminate\Database\Eloquent\Builder($query->where('attribute_groups' . '.company_id', $company->id));
}
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Webkul\SAASCustomizer\Models\Attribute;
use Webkul\Attribute\Models\AttributeOption as BaseModel;
class AttributeOption extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new \Illuminate\Database\Eloquent\Builder($query);
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Webkul\SAASCustomizer\Models\Attribute;
use Webkul\Attribute\Models\AttributeOptionTranslation as BaseModel;
class AttributeOptionTranslation extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new \Illuminate\Database\Eloquent\Builder($query);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\SAASCustomizer\Models\Attribute;
use Webkul\Attribute\Models\AttributeTranslation as BaseModel;
class AttributeTranslation extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new \Illuminate\Database\Eloquent\Builder($query);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Webkul\SAASCustomizer\Models\Category;
use Webkul\Category\Models\Category as BaseModel;
use Kalnoy\Nestedset\QueryBuilder;
use Company;
class Category extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
$company = Company::getCurrent();
if (auth()->guard('super-admin')->check() || ! isset($company->id)) {
return new QueryBuilder($query);
} else {
return new QueryBuilder($query->where('company_id', $company->id));
}
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Webkul\SAASCustomizer\Models\Category;
use Webkul\Category\Models\CategoryTranslation as BaseModel;
use Company;
class CategoryTranslation extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
// $company = Company::getCurrent();
return new \Webkul\SAASCustomizer\Database\Eloquent\Builder($query);
// if ($company != null) {
// return new \Illuminate\Database\Eloquent\Builder($query->where('category_translations' . '.company_id', $company->id));
// } else {
// return new \Illuminate\Database\Eloquent\Builder($query->where('category_translations' . '.company_id', null));
// }
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Webkul\SAASCustomizer\Models\Checkout;
use Webkul\Checkout\Models\Cart as BaseModel;
use Company;
class Cart extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
$company = Company::getCurrent();
if (auth()->guard('super-admin')->check() || ! isset($company->id)) {
return new \Illuminate\Database\Eloquent\Builder($query);
} else {
return new \Illuminate\Database\Eloquent\Builder($query->where('cart' . '.company_id', $company->id));
}
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace Webkul\SAASCustomizer\Models\Checkout;
use Webkul\Checkout\Models\CartAddress as BaseModel;
use Company;
class CartAddress extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new \Illuminate\Database\Eloquent\Builder($query);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\SAASCustomizer\Models\Checkout;
use Webkul\Checkout\Models\CartItem as BaseModel;
class CartItem extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new \Illuminate\Database\Eloquent\Builder($query);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\SAASCustomizer\Models\Checkout;
use Webkul\Checkout\Models\CartPayment as BaseModel;
class CartPayment extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new \Illuminate\Database\Eloquent\Builder($query);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\SAASCustomizer\Models\Checkout;
use Webkul\Checkout\Models\CartShippingRate as BaseModel;
class CartShippingRate extends BaseModel
{
/**
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new \Illuminate\Database\Eloquent\Builder($query);
}
}

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