add: full multi-tenancy control
This commit is contained in:
5
packages/Webkul/Quote/src/Contracts/Quote.php
Normal file
5
packages/Webkul/Quote/src/Contracts/Quote.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Contracts;
|
||||
|
||||
interface Quote {}
|
||||
5
packages/Webkul/Quote/src/Contracts/QuoteItem.php
Normal file
5
packages/Webkul/Quote/src/Contracts/QuoteItem.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Contracts;
|
||||
|
||||
interface QuoteItem {}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('quotes', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('subject');
|
||||
$table->string('description')->nullable();
|
||||
|
||||
$table->json('billing_address')->nullable();
|
||||
$table->json('shipping_address')->nullable();
|
||||
|
||||
$table->decimal('discount_percent', 12, 4)->default(0)->nullable();
|
||||
$table->decimal('discount_amount', 12, 4)->nullable();
|
||||
$table->decimal('tax_amount', 12, 4)->nullable();
|
||||
$table->decimal('adjustment_amount', 12, 4)->nullable();
|
||||
$table->decimal('sub_total', 12, 4)->nullable();
|
||||
$table->decimal('grand_total', 12, 4)->nullable();
|
||||
|
||||
$table->datetime('expired_at')->nullable();
|
||||
|
||||
$table->integer('person_id')->unsigned();
|
||||
$table->foreign('person_id')->references('id')->on('persons')->onDelete('cascade');
|
||||
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('quotes');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('quote_items', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('sku')->nullable();
|
||||
$table->string('name')->nullable();
|
||||
$table->integer('quantity')->default(0)->nullable();
|
||||
$table->decimal('price', 12, 4)->default(0);
|
||||
|
||||
$table->string('coupon_code')->nullable();
|
||||
$table->decimal('discount_percent', 12, 4)->default(0)->nullable();
|
||||
$table->decimal('discount_amount', 12, 4)->default(0)->nullable();
|
||||
|
||||
$table->decimal('tax_percent', 12, 4)->default(0)->nullable();
|
||||
$table->decimal('tax_amount', 12, 4)->default(0)->nullable();
|
||||
|
||||
$table->decimal('total', 12, 4)->default(0);
|
||||
|
||||
$table->integer('product_id')->unsigned();
|
||||
$table->integer('quote_id')->unsigned();
|
||||
$table->foreign('quote_id')->references('id')->on('quotes')->onDelete('cascade');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('quote_items');
|
||||
}
|
||||
};
|
||||
76
packages/Webkul/Quote/src/Models/Quote.php
Normal file
76
packages/Webkul/Quote/src/Models/Quote.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Webkul\Attribute\Traits\CustomAttribute;
|
||||
use Webkul\Contact\Models\PersonProxy;
|
||||
use Webkul\Lead\Models\LeadProxy;
|
||||
use Webkul\Quote\Contracts\Quote as QuoteContract;
|
||||
use Webkul\User\Models\UserProxy;
|
||||
|
||||
class Quote extends Model implements QuoteContract
|
||||
{
|
||||
use CustomAttribute;
|
||||
|
||||
protected $table = 'quotes';
|
||||
|
||||
protected $casts = [
|
||||
'billing_address' => 'array',
|
||||
'shipping_address' => 'array',
|
||||
'expired_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'subject',
|
||||
'description',
|
||||
'billing_address',
|
||||
'shipping_address',
|
||||
'discount_percent',
|
||||
'discount_amount',
|
||||
'tax_amount',
|
||||
'adjustment_amount',
|
||||
'sub_total',
|
||||
'grand_total',
|
||||
'expired_at',
|
||||
'user_id',
|
||||
'person_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the quote items record associated with the quote.
|
||||
*/
|
||||
public function items()
|
||||
{
|
||||
return $this->hasMany(QuoteItemProxy::modelClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user that owns the quote.
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(UserProxy::modelClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the person that owns the quote.
|
||||
*/
|
||||
public function person()
|
||||
{
|
||||
return $this->belongsTo(PersonProxy::modelClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* The leads that belong to the quote.
|
||||
*/
|
||||
public function leads()
|
||||
{
|
||||
return $this->belongsToMany(LeadProxy::modelClass(), 'lead_quotes');
|
||||
}
|
||||
}
|
||||
39
packages/Webkul/Quote/src/Models/QuoteItem.php
Normal file
39
packages/Webkul/Quote/src/Models/QuoteItem.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Webkul\Quote\Contracts\QuoteItem as QuoteItemContract;
|
||||
|
||||
class QuoteItem extends Model implements QuoteItemContract
|
||||
{
|
||||
protected $table = 'quote_items';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'sku',
|
||||
'name',
|
||||
'quantity',
|
||||
'price',
|
||||
'coupon_code',
|
||||
'discount_percent',
|
||||
'discount_amount',
|
||||
'tax_percent',
|
||||
'tax_amount',
|
||||
'total',
|
||||
'product_id',
|
||||
'quote_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the quote record associated with the quote item.
|
||||
*/
|
||||
public function quote()
|
||||
{
|
||||
return $this->belongsTo(QuoteProxy::modelClass());
|
||||
}
|
||||
}
|
||||
7
packages/Webkul/Quote/src/Models/QuoteItemProxy.php
Normal file
7
packages/Webkul/Quote/src/Models/QuoteItemProxy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
class QuoteItemProxy extends ModelProxy {}
|
||||
7
packages/Webkul/Quote/src/Models/QuoteProxy.php
Normal file
7
packages/Webkul/Quote/src/Models/QuoteProxy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
class QuoteProxy extends ModelProxy {}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Providers;
|
||||
|
||||
use Webkul\Core\Providers\BaseModuleServiceProvider;
|
||||
|
||||
class ModuleServiceProvider extends BaseModuleServiceProvider
|
||||
{
|
||||
protected $models = [
|
||||
\Webkul\Quote\Models\Quote::class,
|
||||
\Webkul\Quote\Models\QuoteItem::class,
|
||||
];
|
||||
}
|
||||
26
packages/Webkul/Quote/src/Providers/QuoteServiceProvider.php
Normal file
26
packages/Webkul/Quote/src/Providers/QuoteServiceProvider.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Providers;
|
||||
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class QuoteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot(Router $router)
|
||||
{
|
||||
$this->loadMigrationsFrom(__DIR__.'/../Database/Migrations');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register() {}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Repositories;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
|
||||
class QuoteItemRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* Create a new repository instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
protected ProductRepository $productRepository,
|
||||
Container $container
|
||||
) {
|
||||
parent::__construct($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function model()
|
||||
{
|
||||
return 'Webkul\Quote\Contracts\QuoteItem';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
if (empty($data['product_id'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$product = $this->productRepository->findOrFail($data['product_id']);
|
||||
|
||||
$quoteItem = parent::create(array_merge($data, [
|
||||
'sku' => $product->sku,
|
||||
'name' => $product->name,
|
||||
]));
|
||||
|
||||
return $quoteItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $attribute
|
||||
* @return \Webkul\Quote\Contracts\QuoteItem
|
||||
*/
|
||||
public function update(array $data, $id, $attribute = 'id')
|
||||
{
|
||||
$product = $this->productRepository->findOrFail($data['product_id']);
|
||||
|
||||
$quoteItem = parent::update(array_merge($data, [
|
||||
'sku' => $product->sku,
|
||||
'name' => $product->name,
|
||||
]), $id);
|
||||
|
||||
return $quoteItem;
|
||||
}
|
||||
}
|
||||
147
packages/Webkul/Quote/src/Repositories/QuoteRepository.php
Normal file
147
packages/Webkul/Quote/src/Repositories/QuoteRepository.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Webkul\Quote\Repositories;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Support\Str;
|
||||
use Webkul\Attribute\Repositories\AttributeRepository;
|
||||
use Webkul\Attribute\Repositories\AttributeValueRepository;
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
use Webkul\Quote\Contracts\Quote;
|
||||
|
||||
class QuoteRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* Searchable fields.
|
||||
*/
|
||||
protected $fieldSearchable = [
|
||||
'subject',
|
||||
'description',
|
||||
'person_id',
|
||||
'person.name',
|
||||
'user_id',
|
||||
'user.name',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new repository instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
protected AttributeRepository $attributeRepository,
|
||||
protected AttributeValueRepository $attributeValueRepository,
|
||||
protected QuoteItemRepository $quoteItemRepository,
|
||||
Container $container
|
||||
) {
|
||||
parent::__construct($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify model class name.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function model()
|
||||
{
|
||||
return Quote::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create.
|
||||
*
|
||||
* @return \Webkul\Quote\Contracts\Quote
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
$quote = parent::create($data);
|
||||
|
||||
$this->attributeValueRepository->save(array_merge($data, [
|
||||
'entity_id' => $quote->id,
|
||||
]));
|
||||
|
||||
foreach ($data['items'] as $itemData) {
|
||||
$this->quoteItemRepository->create(array_merge($itemData, [
|
||||
'quote_id' => $quote->id,
|
||||
]));
|
||||
}
|
||||
|
||||
return $quote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $attribute
|
||||
* @return \Webkul\Quote\Contracts\Quote
|
||||
*/
|
||||
public function update(array $data, $id, $attributes = [])
|
||||
{
|
||||
$quote = $this->find($id);
|
||||
|
||||
parent::update($data, $id);
|
||||
|
||||
/**
|
||||
* If attributes are provided then only save the provided attributes and return.
|
||||
*/
|
||||
if (! empty($attributes)) {
|
||||
$conditions = ['entity_type' => $data['entity_type']];
|
||||
|
||||
if (isset($data['quick_add'])) {
|
||||
$conditions['quick_add'] = 1;
|
||||
}
|
||||
|
||||
$attributes = $this->attributeRepository->where($conditions)
|
||||
->whereIn('code', $attributes)
|
||||
->get();
|
||||
|
||||
$this->attributeValueRepository->save(array_merge($data, [
|
||||
'entity_id' => $quote->id,
|
||||
]), $attributes);
|
||||
|
||||
return $quote;
|
||||
}
|
||||
|
||||
$this->attributeValueRepository->save(array_merge($data, [
|
||||
'entity_id' => $quote->id,
|
||||
]));
|
||||
|
||||
$previousItemIds = $quote->items->pluck('id');
|
||||
|
||||
if (isset($data['items'])) {
|
||||
foreach ($data['items'] as $itemId => $itemData) {
|
||||
if (Str::contains($itemId, 'item_')) {
|
||||
$this->quoteItemRepository->create(array_merge($itemData, [
|
||||
'quote_id' => $id,
|
||||
]));
|
||||
} else {
|
||||
if (is_numeric($index = $previousItemIds->search($itemId))) {
|
||||
$previousItemIds->forget($index);
|
||||
}
|
||||
|
||||
$this->quoteItemRepository->update($itemData, $itemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($previousItemIds as $itemId) {
|
||||
$this->quoteItemRepository->delete($itemId);
|
||||
}
|
||||
|
||||
return $quote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves customers count based on date.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
public function getQuotesCount($startDate, $endDate)
|
||||
{
|
||||
return $this
|
||||
->whereBetween('created_at', [$startDate, $endDate])
|
||||
->get()
|
||||
->count();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user