first upload all files
This commit is contained in:
432
Modules/Cart/Cart.php
Normal file
432
Modules/Cart/Cart.php
Normal file
@@ -0,0 +1,432 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart;
|
||||
|
||||
use JsonSerializable;
|
||||
use Modules\Support\Money;
|
||||
use Modules\Tax\Entities\TaxRate;
|
||||
use Illuminate\Support\Collection;
|
||||
use Modules\Coupon\Entities\Coupon;
|
||||
use Modules\Product\Entities\Product;
|
||||
use Modules\Shipping\Facades\ShippingMethod;
|
||||
use Darryldecode\Cart\Cart as DarryldecodeCart;
|
||||
use Modules\Product\Services\ChosenProductOptions;
|
||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||
|
||||
class Cart extends DarryldecodeCart implements JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Get the current instance.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function instance()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cart.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
parent::clear();
|
||||
|
||||
$this->clearCartConditions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new item to the cart.
|
||||
*
|
||||
* @param int $productId
|
||||
* @param int $qty
|
||||
* @param array $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function store($productId, $qty, $options = [])
|
||||
{
|
||||
$options = array_filter($options);
|
||||
$product = Product::with('files', 'categories', 'taxClass')->findOrFail($productId);
|
||||
$chosenOptions = new ChosenProductOptions($product, $options);
|
||||
|
||||
$this->add([
|
||||
'id' => md5("product_id.{$product->id}:options." . serialize($options)),
|
||||
'name' => $product->name,
|
||||
'price' => $product->selling_price->amount(),
|
||||
'quantity' => $qty,
|
||||
'attributes' => [
|
||||
'product' => $product,
|
||||
'options' => $chosenOptions->getEntities(),
|
||||
'created_at' => time(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateQuantity($id, $qty)
|
||||
{
|
||||
$this->update($id, [
|
||||
'quantity' => [
|
||||
'relative' => false,
|
||||
'value' => $qty,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function items()
|
||||
{
|
||||
return $this->getContent()
|
||||
->sortBy('attributes.created_at')
|
||||
->map(function ($item) {
|
||||
return new CartItem($item);
|
||||
});
|
||||
}
|
||||
|
||||
public function addedQty($productId)
|
||||
{
|
||||
return $this->findByProductId($productId)->sum('qty');
|
||||
}
|
||||
|
||||
public function findByProductId($productId)
|
||||
{
|
||||
return $this->items()->filter(function ($cartItem) use ($productId) {
|
||||
return $cartItem->product->id == $productId;
|
||||
});
|
||||
}
|
||||
|
||||
public function crossSellProducts()
|
||||
{
|
||||
return $this->getAllProducts()
|
||||
->load([
|
||||
'crossSellProducts' => function ($query) {
|
||||
$query->forCard();
|
||||
},
|
||||
])
|
||||
->pluck('crossSellProducts')
|
||||
->flatten();
|
||||
}
|
||||
|
||||
public function getAllProducts()
|
||||
{
|
||||
return $this->items()
|
||||
->map(function ($cartItem) {
|
||||
return $cartItem->product;
|
||||
})
|
||||
->flatten()
|
||||
->pipe(function ($products) {
|
||||
return new EloquentCollection($products);
|
||||
});
|
||||
}
|
||||
|
||||
public function reduceStock()
|
||||
{
|
||||
$this->manageStock(function ($cartItem) {
|
||||
$cartItem->product->decrement('qty', $cartItem->qty);
|
||||
|
||||
if ($cartItem->refreshStock()->product->qty === 0) {
|
||||
$cartItem->product->markAsOutOfStock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function restoreStock()
|
||||
{
|
||||
$this->manageStock(function ($cartItem) {
|
||||
$cartItem->product->increment('qty', $cartItem->qty);
|
||||
|
||||
if ($cartItem->product->qty > 0) {
|
||||
$cartItem->product->markAsInStock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function manageStock($callback)
|
||||
{
|
||||
$this->items()
|
||||
->filter(function ($cartItem) {
|
||||
return $cartItem->product->manage_stock;
|
||||
})
|
||||
->each($callback);
|
||||
}
|
||||
|
||||
public function quantity()
|
||||
{
|
||||
return $this->getTotalQuantity();
|
||||
}
|
||||
|
||||
public function hasAvailableShippingMethod()
|
||||
{
|
||||
return $this->availableShippingMethods()->isNotEmpty();
|
||||
}
|
||||
|
||||
public function availableShippingMethods()
|
||||
{
|
||||
if ($this->allItemsAreVirtual()) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return ShippingMethod::available();
|
||||
}
|
||||
|
||||
public function allItemsAreVirtual()
|
||||
{
|
||||
return $this->items()->every(function (CartItem $cartItem) {
|
||||
return $cartItem->product->is_virtual;
|
||||
});
|
||||
}
|
||||
|
||||
public function hasShippingMethod()
|
||||
{
|
||||
return $this->getConditionsByType('shipping_method')->isNotEmpty();
|
||||
}
|
||||
|
||||
public function shippingMethod()
|
||||
{
|
||||
if (!$this->hasShippingMethod()) {
|
||||
return new NullCartShippingMethod();
|
||||
}
|
||||
|
||||
return new CartShippingMethod($this, $this->getConditionsByType('shipping_method')->first());
|
||||
}
|
||||
|
||||
public function shippingCost()
|
||||
{
|
||||
return $this->shippingMethod()->cost();
|
||||
}
|
||||
|
||||
public function addShippingMethod($shippingMethod)
|
||||
{
|
||||
$this->removeShippingMethod();
|
||||
|
||||
$this->condition(
|
||||
new CartCondition([
|
||||
'name' => $shippingMethod->label,
|
||||
'type' => 'shipping_method',
|
||||
'target' => 'total',
|
||||
'value' => "+{$shippingMethod->cost->amount()}",
|
||||
'order' => 1,
|
||||
'attributes' => [
|
||||
'shipping_method' => $shippingMethod,
|
||||
],
|
||||
]),
|
||||
);
|
||||
|
||||
$this->refreshFreeShippingCoupon();
|
||||
|
||||
return $this->shippingMethod();
|
||||
}
|
||||
|
||||
public function removeShippingMethod()
|
||||
{
|
||||
$this->removeConditionsByType('shipping_method');
|
||||
}
|
||||
|
||||
private function refreshFreeShippingCoupon()
|
||||
{
|
||||
if ($this->coupon()->isFreeShipping()) {
|
||||
$this->applyCoupon($this->coupon()->entity());
|
||||
}
|
||||
}
|
||||
|
||||
public function hasCoupon()
|
||||
{
|
||||
if ($this->getConditionsByType('coupon')->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$couponId = $this->getConditionsByType('coupon')
|
||||
->first()
|
||||
->getAttribute('coupon_id');
|
||||
|
||||
return Coupon::where('id', $couponId)->exists();
|
||||
}
|
||||
|
||||
public function couponAlreadyApplied(Coupon $coupon)
|
||||
{
|
||||
return $this->coupon()->code() === $coupon->code;
|
||||
}
|
||||
|
||||
public function coupon()
|
||||
{
|
||||
if (!$this->hasCoupon()) {
|
||||
return new NullCartCoupon();
|
||||
}
|
||||
|
||||
$couponCondition = $this->getConditionsByType('coupon')->first();
|
||||
$coupon = Coupon::with('products', 'categories')->find($couponCondition->getAttribute('coupon_id'));
|
||||
|
||||
return new CartCoupon($this, $coupon, $couponCondition);
|
||||
}
|
||||
|
||||
public function discount()
|
||||
{
|
||||
return $this->coupon()->value();
|
||||
}
|
||||
|
||||
public function applyCoupon(Coupon $coupon)
|
||||
{
|
||||
$this->removeCoupon();
|
||||
|
||||
$this->condition(
|
||||
new CartCondition([
|
||||
'name' => $coupon->code,
|
||||
'type' => 'coupon',
|
||||
'target' => 'total',
|
||||
'value' => $this->getCouponValue($coupon),
|
||||
'order' => 2,
|
||||
'attributes' => [
|
||||
'coupon_id' => $coupon->id,
|
||||
],
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
private function getCouponValue($coupon)
|
||||
{
|
||||
if ($coupon->free_shipping) {
|
||||
return "-{$this->shippingMethod()->cost()->amount()}";
|
||||
}
|
||||
|
||||
if ($coupon->is_percent) {
|
||||
return "-{$coupon->value}%";
|
||||
}
|
||||
|
||||
return "-{$coupon->value->amount()}";
|
||||
}
|
||||
|
||||
public function removeCoupon()
|
||||
{
|
||||
$this->removeConditionsByType('coupon');
|
||||
}
|
||||
|
||||
public function hasTax()
|
||||
{
|
||||
return $this->getConditionsByType('tax')->isNotEmpty();
|
||||
}
|
||||
|
||||
public function taxes()
|
||||
{
|
||||
if (!$this->hasTax()) {
|
||||
return new Collection();
|
||||
}
|
||||
|
||||
$taxConditions = $this->getConditionsByType('tax');
|
||||
$taxRates = TaxRate::whereIn('id', $this->getTaxRateIds($taxConditions))->get();
|
||||
|
||||
return $taxConditions->map(function ($taxCondition) use ($taxRates) {
|
||||
$taxRate = $taxRates->where('id', $taxCondition->getAttribute('tax_rate_id'))->first();
|
||||
|
||||
return new CartTax($this, $taxRate, $taxCondition);
|
||||
});
|
||||
}
|
||||
|
||||
private function getTaxRateIds($taxConditions)
|
||||
{
|
||||
return $taxConditions->map(function ($taxCondition) {
|
||||
return $taxCondition->getAttribute('tax_rate_id');
|
||||
});
|
||||
}
|
||||
|
||||
public function tax()
|
||||
{
|
||||
return Money::inDefaultCurrency($this->calculateTax());
|
||||
}
|
||||
|
||||
private function calculateTax()
|
||||
{
|
||||
return $this->taxes()->sum(function ($cartTax) {
|
||||
return $cartTax->amount()->amount();
|
||||
});
|
||||
}
|
||||
|
||||
public function addTaxes($request)
|
||||
{
|
||||
$this->removeTaxes();
|
||||
|
||||
$this->findTaxes($request)->each(function ($taxRate) {
|
||||
$this->condition(
|
||||
new CartCondition([
|
||||
'name' => $taxRate->id,
|
||||
'type' => 'tax',
|
||||
'target' => 'total',
|
||||
'value' => "+{$taxRate->rate}%",
|
||||
'order' => 3,
|
||||
'attributes' => [
|
||||
'tax_rate_id' => $taxRate->id,
|
||||
],
|
||||
]),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public function removeTaxes()
|
||||
{
|
||||
$this->removeConditionsByType('tax');
|
||||
}
|
||||
|
||||
private function findTaxes($request)
|
||||
{
|
||||
return $this->items()
|
||||
->groupBy('tax_class_id')
|
||||
->flatten()
|
||||
->map(function (CartItem $cartItem) use ($request) {
|
||||
return $cartItem->findTax($request->only(['billing', 'shipping']));
|
||||
})
|
||||
->filter();
|
||||
}
|
||||
|
||||
public function subTotal()
|
||||
{
|
||||
return Money::inDefaultCurrency($this->getSubTotal())->add($this->optionsPrice());
|
||||
}
|
||||
|
||||
private function optionsPrice()
|
||||
{
|
||||
return Money::inDefaultCurrency($this->calculateOptionsPrice());
|
||||
}
|
||||
|
||||
private function calculateOptionsPrice()
|
||||
{
|
||||
return $this->items()->sum(function ($cartItem) {
|
||||
return $cartItem
|
||||
->optionsPrice()
|
||||
->multiply($cartItem->qty)
|
||||
->amount();
|
||||
});
|
||||
}
|
||||
|
||||
public function total()
|
||||
{
|
||||
return $this->subTotal()
|
||||
->add($this->shippingMethod()->cost())
|
||||
->subtract($this->coupon()->value())
|
||||
->add($this->tax());
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'items' => $this->items(),
|
||||
'quantity' => $this->quantity(),
|
||||
'availableShippingMethods' => $this->availableShippingMethods(),
|
||||
'subTotal' => $this->subTotal(),
|
||||
'shippingMethodName' => $this->shippingMethod()->name(),
|
||||
'shippingCost' => $this->shippingCost(),
|
||||
'coupon' => $this->coupon(),
|
||||
'taxes' => $this->taxes(),
|
||||
'total' => $this->total(),
|
||||
];
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return json_encode($this->jsonSerialize());
|
||||
}
|
||||
}
|
||||
13
Modules/Cart/CartCondition.php
Normal file
13
Modules/Cart/CartCondition.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart;
|
||||
|
||||
use Darryldecode\Cart\CartCondition as DarryldecodeCartCondition;
|
||||
|
||||
class CartCondition extends DarryldecodeCartCondition
|
||||
{
|
||||
public function getAttribute($key, $default = null)
|
||||
{
|
||||
return array_get($this->getAttributes(), $key, $default);
|
||||
}
|
||||
}
|
||||
160
Modules/Cart/CartCoupon.php
Normal file
160
Modules/Cart/CartCoupon.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart;
|
||||
|
||||
use JsonSerializable;
|
||||
use Modules\Support\Money;
|
||||
|
||||
class CartCoupon implements JsonSerializable
|
||||
{
|
||||
private $cart;
|
||||
private $coupon;
|
||||
private $couponCondition;
|
||||
|
||||
public function __construct($cart, $coupon, $couponCondition)
|
||||
{
|
||||
$this->cart = $cart;
|
||||
$this->coupon = $coupon;
|
||||
$this->couponCondition = $couponCondition;
|
||||
}
|
||||
|
||||
public function entity()
|
||||
{
|
||||
return $this->coupon;
|
||||
}
|
||||
|
||||
public function id()
|
||||
{
|
||||
return $this->coupon->id;
|
||||
}
|
||||
|
||||
public function code()
|
||||
{
|
||||
return $this->coupon->code;
|
||||
}
|
||||
|
||||
public function isFreeShipping()
|
||||
{
|
||||
return $this->coupon->free_shipping;
|
||||
}
|
||||
|
||||
public function usageLimitReached($customerEmail)
|
||||
{
|
||||
return $this->fresh()->coupon->usageLimitReached($customerEmail);
|
||||
}
|
||||
|
||||
public function didNotSpendTheRequiredAmount()
|
||||
{
|
||||
return $this->fresh()->coupon->didNotSpendTheRequiredAmount();
|
||||
}
|
||||
|
||||
public function spentMoreThanMaximumAmount()
|
||||
{
|
||||
return $this->fresh()->coupon->spentMoreThanMaximumAmount();
|
||||
}
|
||||
|
||||
public function fresh()
|
||||
{
|
||||
$this->coupon = $this->coupon->refresh();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function usedOnce()
|
||||
{
|
||||
$this->coupon->increment('used');
|
||||
}
|
||||
|
||||
public function value()
|
||||
{
|
||||
if ($this->coupon->free_shipping) {
|
||||
return $this->cart->shippingMethod()->cost();
|
||||
}
|
||||
|
||||
return Money::inDefaultCurrency($this->calculate());
|
||||
}
|
||||
|
||||
private function calculate()
|
||||
{
|
||||
return $this->couponCondition->getCalculatedValue($this->productsTotalPrice());
|
||||
}
|
||||
|
||||
private function productsTotalPrice()
|
||||
{
|
||||
return $this->couponApplicableProducts()->sum(function ($cartItem) {
|
||||
return $cartItem->total()->amount();
|
||||
});
|
||||
}
|
||||
|
||||
private function couponApplicableProducts()
|
||||
{
|
||||
return $this->cart->items()->filter(function ($cartItem) {
|
||||
return $this->inApplicableProducts($cartItem);
|
||||
})->reject(function ($cartItem) {
|
||||
return $this->inExcludedProducts($cartItem);
|
||||
})->filter(function ($cartItem) {
|
||||
return $this->inApplicableCategories($cartItem);
|
||||
})->reject(function ($cartItem) {
|
||||
return $this->inExcludedCategories($cartItem);
|
||||
});
|
||||
}
|
||||
|
||||
private function inApplicableProducts($cartItem)
|
||||
{
|
||||
if ($this->coupon->products->isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->coupon->products->contains($cartItem->product);
|
||||
}
|
||||
|
||||
private function inExcludedProducts($cartItem)
|
||||
{
|
||||
if ($this->coupon->excludeProducts->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->coupon->excludeProducts->contains($cartItem->product);
|
||||
}
|
||||
|
||||
private function inApplicableCategories($cartItem)
|
||||
{
|
||||
if ($this->coupon->categories->isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->coupon->categories->intersect($cartItem->product->categories)->isNotEmpty();
|
||||
}
|
||||
|
||||
private function inExcludedCategories($cartItem)
|
||||
{
|
||||
if ($this->coupon->excludeCategories->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->coupon->excludeCategories->intersect($cartItem->product->categories)->isNotEmpty();
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'code' => $this->code(),
|
||||
'value' => $this->value(),
|
||||
];
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return json_encode($this->jsonSerialize());
|
||||
}
|
||||
|
||||
public function __get($attribute)
|
||||
{
|
||||
return $this->coupon->{$attribute};
|
||||
}
|
||||
}
|
||||
91
Modules/Cart/CartItem.php
Normal file
91
Modules/Cart/CartItem.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart;
|
||||
|
||||
use JsonSerializable;
|
||||
use Modules\Support\Money;
|
||||
use Modules\Product\Entities\Product;
|
||||
|
||||
class CartItem implements JsonSerializable
|
||||
{
|
||||
public $id;
|
||||
public $qty;
|
||||
public $product;
|
||||
public $options;
|
||||
|
||||
public function __construct($item)
|
||||
{
|
||||
$this->id = $item->id;
|
||||
$this->qty = $item->quantity;
|
||||
$this->product = $item->attributes['product'];
|
||||
$this->options = $item->attributes['options'];
|
||||
}
|
||||
|
||||
public function unitPrice()
|
||||
{
|
||||
return $this->product->selling_price->add($this->optionsPrice());
|
||||
}
|
||||
|
||||
public function total()
|
||||
{
|
||||
return $this->unitPrice()->multiply($this->qty);
|
||||
}
|
||||
|
||||
public function optionsPrice()
|
||||
{
|
||||
return Money::inDefaultCurrency($this->calculateOptionsPrice());
|
||||
}
|
||||
|
||||
public function calculateOptionsPrice()
|
||||
{
|
||||
return $this->options->sum(function ($option) {
|
||||
return $this->valuesSum($option->values);
|
||||
});
|
||||
}
|
||||
|
||||
private function valuesSum($values)
|
||||
{
|
||||
return $values->sum(function ($value) {
|
||||
if ($value->price_type === 'fixed') {
|
||||
return $value->price->amount();
|
||||
}
|
||||
|
||||
return ($value->price / 100) * $this->product->selling_price->amount();
|
||||
});
|
||||
}
|
||||
|
||||
public function refreshStock()
|
||||
{
|
||||
$product = Product::select(['manage_stock', 'in_stock', 'qty'])->find($this->product->id);
|
||||
|
||||
$this->product->fill([
|
||||
'manage_stock' => $product->manage_stock,
|
||||
'in_stock' => $product->in_stock,
|
||||
'qty' => $product->qty,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function findTax(array $addresses)
|
||||
{
|
||||
return $this->product->taxClass->findTaxRate($addresses);
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'qty' => $this->qty,
|
||||
'product' => $this->product->clean(),
|
||||
'options' => $this->options->keyBy('position'),
|
||||
'unitPrice' => $this->unitPrice(),
|
||||
'total' => $this->total(),
|
||||
];
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return json_encode($this->jsonSerialize());
|
||||
}
|
||||
}
|
||||
37
Modules/Cart/CartShippingMethod.php
Normal file
37
Modules/Cart/CartShippingMethod.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart;
|
||||
|
||||
use Modules\Support\Money;
|
||||
|
||||
class CartShippingMethod
|
||||
{
|
||||
private $cart;
|
||||
private $shippingMethodCondition;
|
||||
|
||||
public function __construct($cart, $shippingMethodCondition)
|
||||
{
|
||||
$this->cart = $cart;
|
||||
$this->shippingMethodCondition = $shippingMethodCondition;
|
||||
}
|
||||
|
||||
public function name()
|
||||
{
|
||||
return $this->shippingMethodCondition->getAttribute('shipping_method')->name;
|
||||
}
|
||||
|
||||
public function label()
|
||||
{
|
||||
return $this->shippingMethodCondition->getAttribute('shipping_method')->label;
|
||||
}
|
||||
|
||||
public function cost()
|
||||
{
|
||||
return Money::inDefaultCurrency($this->calculate());
|
||||
}
|
||||
|
||||
private function calculate()
|
||||
{
|
||||
return $this->shippingMethodCondition->getCalculatedValue($this->cart->subTotal()->amount());
|
||||
}
|
||||
}
|
||||
77
Modules/Cart/CartTax.php
Normal file
77
Modules/Cart/CartTax.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart;
|
||||
|
||||
use JsonSerializable;
|
||||
use Modules\Support\Money;
|
||||
|
||||
class CartTax implements JsonSerializable
|
||||
{
|
||||
private $cart;
|
||||
private $taxRate;
|
||||
private $taxCondition;
|
||||
|
||||
public function __construct($cart, $taxRate, $taxCondition)
|
||||
{
|
||||
$this->cart = $cart;
|
||||
$this->taxRate = $taxRate;
|
||||
$this->taxCondition = $taxCondition;
|
||||
}
|
||||
|
||||
public function id()
|
||||
{
|
||||
return $this->taxRate->id;
|
||||
}
|
||||
|
||||
public function name()
|
||||
{
|
||||
return $this->taxRate->name;
|
||||
}
|
||||
|
||||
public function amount()
|
||||
{
|
||||
return Money::inDefaultCurrency($this->calculate());
|
||||
}
|
||||
|
||||
private function calculate()
|
||||
{
|
||||
return $this->taxCondition->getCalculatedValue($this->productsTotalPrice());
|
||||
}
|
||||
|
||||
private function productsTotalPrice()
|
||||
{
|
||||
return $this->taxApplicableProducts()->sum(function ($cartItem) {
|
||||
return $cartItem->total()->amount();
|
||||
});
|
||||
}
|
||||
|
||||
private function taxApplicableProducts()
|
||||
{
|
||||
return $this->cart->items()->filter(function ($cartItem) {
|
||||
return $this->hasMatchingTaxClass($cartItem);
|
||||
});
|
||||
}
|
||||
|
||||
private function hasMatchingTaxClass($cartItem)
|
||||
{
|
||||
return $cartItem->product->tax_class_id === $this->taxRate->tax_class_id;
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'name' => $this->name(),
|
||||
'amount' => $this->amount(),
|
||||
];
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return json_encode($this->jsonSerialize());
|
||||
}
|
||||
}
|
||||
36
Modules/Cart/Config/config.php
Normal file
36
Modules/Cart/Config/config.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* formatting
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* the formatting of shopping cart values
|
||||
*/
|
||||
'format_numbers' => env('SHOPPING_FORMAT_VALUES', false),
|
||||
|
||||
'decimals' => env('SHOPPING_DECIMALS', 0),
|
||||
|
||||
'dec_point' => env('SHOPPING_DEC_POINT', '.'),
|
||||
|
||||
'thousands_sep' => env('SHOPPING_THOUSANDS_SEP', ','),
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* persistence
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* the configuration for persisting cart
|
||||
*/
|
||||
'storage' => null,
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* events
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* the configuration for cart events
|
||||
*/
|
||||
'events' => null,
|
||||
];
|
||||
56
Modules/Cart/Facades/Cart.php
Normal file
56
Modules/Cart/Facades/Cart.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
/**
|
||||
* @method static \Modules\Cart\Cart instance()
|
||||
* @method static void clear()
|
||||
* @method static void store(int $productId, int $qty, array $options = [])
|
||||
* @method static void updateQuantity(string $id, int $qty)
|
||||
* @method static \Darryldecode\Cart\CartCollection items()
|
||||
* @method static int addedQty(int $productId)
|
||||
* @method static int findByProductId(int $productId)
|
||||
* @method static \Illuminate\Database\Eloquent\Collection crossSellProducts()
|
||||
* @method static \Illuminate\Database\Eloquent\Collection getAllProducts()
|
||||
* @method static void reduceStock()
|
||||
* @method static void restoreStock()
|
||||
* @method static int quantity()
|
||||
* @method static bool hasAvailableShippingMethod()
|
||||
* @method static \Illuminate\Support\Collection availableShippingMethods()
|
||||
* @method static bool hasShippingMethod()
|
||||
* @method static \Modules\Cart\CartShippingMethod shippingMethod()
|
||||
* @method static \Modules\Support\Money shippingCost()
|
||||
* @method static \Modules\Support\Money addShippingMethod(\Modules\Shipping\Method $shippingMethod)
|
||||
* @method static void removeShippingMethod()
|
||||
* @method static bool hasCoupon()
|
||||
* @method static bool couponAlreadyApplied()
|
||||
* @method static \Modules\Cart\CartCoupon coupon()
|
||||
* @method static \Modules\Support\Money discount()
|
||||
* @method static void applyCoupon(\Modules\Coupon\Entities\Coupon $coupon)
|
||||
* @method static void removeCoupon()
|
||||
* @method static void hasTax()
|
||||
* @method static \Darryldecode\Cart\CartConditionCollection taxes()
|
||||
* @method static \Modules\Support\Money tax()
|
||||
* @method static void addTaxes(\Illuminate\Http\Request $request)
|
||||
* @method static void removeTaxes()
|
||||
* @method static \Modules\Support\Money subTotal()
|
||||
* @method static \Modules\Support\Money total()
|
||||
* @method static array toArray()
|
||||
* @method static array jsonSerialize()
|
||||
*
|
||||
* @see \Modules\Cart\Cart
|
||||
*/
|
||||
class Cart extends Facade
|
||||
{
|
||||
/**
|
||||
* Get the registered name of the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return \Modules\Cart\Cart::class;
|
||||
}
|
||||
}
|
||||
20
Modules/Cart/Http/Controllers/CartClearController.php
Normal file
20
Modules/Cart/Http/Controllers/CartClearController.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Controllers;
|
||||
|
||||
use Modules\Cart\Facades\Cart;
|
||||
|
||||
class CartClearController
|
||||
{
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
Cart::clear();
|
||||
|
||||
return Cart::instance();
|
||||
}
|
||||
}
|
||||
16
Modules/Cart/Http/Controllers/CartController.php
Normal file
16
Modules/Cart/Http/Controllers/CartController.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Controllers;
|
||||
|
||||
class CartController
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('public.cart.index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Controllers;
|
||||
|
||||
use Modules\Cart\Facades\Cart;
|
||||
|
||||
class CartCrossSellProductsController
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return Cart::crossSellProducts();
|
||||
}
|
||||
}
|
||||
79
Modules/Cart/Http/Controllers/CartItemController.php
Normal file
79
Modules/Cart/Http/Controllers/CartItemController.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Controllers;
|
||||
|
||||
use Modules\Cart\Facades\Cart;
|
||||
use Illuminate\Pipeline\Pipeline;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Coupon\Checkers\MaximumSpend;
|
||||
use Modules\Coupon\Checkers\MinimumSpend;
|
||||
use Modules\Cart\Http\Requests\StoreCartItemRequest;
|
||||
use Modules\Coupon\Exceptions\MaximumSpendException;
|
||||
use Modules\Coupon\Exceptions\MinimumSpendException;
|
||||
use Modules\Cart\Http\Middleware\CheckProductIsInStock;
|
||||
|
||||
class CartItemController extends Controller
|
||||
{
|
||||
private $checkers = [
|
||||
MinimumSpend::class,
|
||||
MaximumSpend::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(CheckProductIsInStock::class)->only(['store', 'update']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Modules\Cart\Http\Requests\StoreCartItemRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreCartItemRequest $request)
|
||||
{
|
||||
Cart::store($request->product_id, $request->qty, $request->options ?? []);
|
||||
|
||||
return Cart::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param mixed $cartItemId
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update($cartItemId)
|
||||
{
|
||||
Cart::updateQuantity($cartItemId, request('qty'));
|
||||
|
||||
try {
|
||||
resolve(Pipeline::class)
|
||||
->send(Cart::coupon())
|
||||
->through($this->checkers)
|
||||
->thenReturn();
|
||||
} catch (MinimumSpendException | MaximumSpendException $e) {
|
||||
Cart::removeCoupon();
|
||||
}
|
||||
|
||||
return Cart::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param string $cartItemId
|
||||
* @return \Illuminhtate\Http\Response
|
||||
*/
|
||||
public function destroy($cartItemId)
|
||||
{
|
||||
Cart::remove($cartItemId);
|
||||
|
||||
return Cart::instance();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Controllers;
|
||||
|
||||
use Modules\Cart\Facades\Cart;
|
||||
use Modules\Shipping\Facades\ShippingMethod;
|
||||
|
||||
class CartShippingMethodController
|
||||
{
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
$shippingMethod = ShippingMethod::get(request('shipping_method'));
|
||||
|
||||
Cart::addShippingMethod($shippingMethod);
|
||||
|
||||
return Cart::instance();
|
||||
}
|
||||
}
|
||||
73
Modules/Cart/Http/Middleware/CheckCartStock.php
Normal file
73
Modules/Cart/Http/Middleware/CheckCartStock.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Modules\Cart\CartItem;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Cart\Facades\Cart;
|
||||
use Modules\FlashSale\Entities\FlashSale;
|
||||
|
||||
class CheckCartStock
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
try {
|
||||
Cart::items()->each(function (CartItem $cartItem) {
|
||||
$cartItem->refreshStock();
|
||||
|
||||
$this->checkQuantity($cartItem);
|
||||
});
|
||||
} catch (Exception $e) {
|
||||
return redirect()->route('cart.index')->with('error', $e->getMessage());
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
private function checkQuantity(CartItem $cartItem)
|
||||
{
|
||||
if ($cartItem->product->isOutOfStock()) {
|
||||
throw new Exception(trans('cart::messages.one_or_more_product_is_out_of_stock'));
|
||||
}
|
||||
|
||||
if (! $this->hasFlashSaleStock($cartItem)) {
|
||||
throw new Exception(trans('cart::messages.one_or_more_product_doesn\'t_have_enough_stock'));
|
||||
}
|
||||
|
||||
if (! $this->hasStock($cartItem)) {
|
||||
throw new Exception(trans('cart::messages.one_or_more_product_doesn\'t_have_enough_stock'));
|
||||
}
|
||||
}
|
||||
|
||||
private function hasFlashSaleStock(CartItem $cartItem)
|
||||
{
|
||||
if (! FlashSale::contains($cartItem->product)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$remainingQty = FlashSale::remainingQty($cartItem->product);
|
||||
$addedCartQty = Cart::addedQty($cartItem->product->id);
|
||||
|
||||
return ($remainingQty - $addedCartQty) >= 0;
|
||||
}
|
||||
|
||||
private function hasStock(CartItem $cartItem)
|
||||
{
|
||||
if (! $cartItem->product->manage_stock) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$addedCartQty = Cart::addedQty($cartItem->product->id);
|
||||
|
||||
return ($cartItem->product->qty - $addedCartQty) >= 0;
|
||||
}
|
||||
}
|
||||
27
Modules/Cart/Http/Middleware/CheckCouponUsageLimit.php
Normal file
27
Modules/Cart/Http/Middleware/CheckCouponUsageLimit.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Cart\Facades\Cart;
|
||||
use Modules\Coupon\Exceptions\CouponUsageLimitReachedException;
|
||||
|
||||
class CheckCouponUsageLimit
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (Cart::coupon()->usageLimitReached($request->customer_email)) {
|
||||
throw new CouponUsageLimitReachedException;
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
103
Modules/Cart/Http/Middleware/CheckProductIsInStock.php
Normal file
103
Modules/Cart/Http/Middleware/CheckProductIsInStock.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Cart\Facades\Cart;
|
||||
use Modules\Product\Entities\Product;
|
||||
use Modules\FlashSale\Entities\FlashSale;
|
||||
|
||||
class CheckProductIsInStock
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$product = Product::withName()
|
||||
->addSelect('id', 'in_stock', 'manage_stock', 'qty')
|
||||
->where('id', $this->getProductId($request))
|
||||
->firstOrFail();
|
||||
|
||||
if ($product->isOutOfStock()) {
|
||||
abort(400, trans('cart::messages.out_of_stock'));
|
||||
}
|
||||
|
||||
if (! $this->hasFlashSaleStock($product, $request)) {
|
||||
abort(400, trans('cart::messages.not_have_enough_quantity_in_stock', [
|
||||
'stock' => FlashSale::remainingQty($product),
|
||||
]));
|
||||
}
|
||||
|
||||
if (! $this->hasStock($product, $request)) {
|
||||
abort(400, trans('cart::messages.not_have_enough_quantity_in_stock', [
|
||||
'stock' => $product->qty,
|
||||
]));
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
private function getProductId(Request $request)
|
||||
{
|
||||
if ($request->routeIs('cart.items.store')) {
|
||||
return $request->product_id;
|
||||
}
|
||||
|
||||
$cartItem = $this->getCartItemForUpdateRequest($request);
|
||||
|
||||
if (! is_null($cartItem)) {
|
||||
return $cartItem->product->id;
|
||||
}
|
||||
}
|
||||
|
||||
private function getCartItemForUpdateRequest(Request $request)
|
||||
{
|
||||
return Cart::items()->get($request->route()->parameter('cartItemId'));
|
||||
}
|
||||
|
||||
private function hasFlashSaleStock(Product $product, Request $request)
|
||||
{
|
||||
if (! FlashSale::contains($product)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$remainingQty = FlashSale::remainingQty($product);
|
||||
$addedCartQty = Cart::addedQty($product->id);
|
||||
|
||||
// Exclude current cart item quantity from the total added cart quantity
|
||||
// So, that current quantity is not added with the updated quantity.
|
||||
$addedCartQty -= $this->currentCartItemQuantity($request);
|
||||
|
||||
return ($remainingQty - $addedCartQty) >= $request->qty;
|
||||
}
|
||||
|
||||
private function hasStock(Product $product, Request $request)
|
||||
{
|
||||
if (! $product->manage_stock) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$addedCartQty = Cart::addedQty($product->id);
|
||||
|
||||
// Exclude current cart item quantity from the total added cart quantity
|
||||
// So, that current quantity is not added with the updated quantity.
|
||||
$addedCartQty -= $this->currentCartItemQuantity($request);
|
||||
|
||||
return ($product->qty - $addedCartQty) >= $request->qty;
|
||||
}
|
||||
|
||||
private function currentCartItemQuantity(Request $request)
|
||||
{
|
||||
if ($request->routeIs('cart.items.update')) {
|
||||
return $this->getCartItemForUpdateRequest($request)->qty;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
26
Modules/Cart/Http/Middleware/RedirectIfCartIsEmpty.php
Normal file
26
Modules/Cart/Http/Middleware/RedirectIfCartIsEmpty.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Cart\Facades\Cart;
|
||||
|
||||
class RedirectIfCartIsEmpty
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (Cart::isEmpty()) {
|
||||
return redirect()->route('cart.index');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
101
Modules/Cart/Http/Requests/StoreCartItemRequest.php
Normal file
101
Modules/Cart/Http/Requests/StoreCartItemRequest.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Http\Requests;
|
||||
|
||||
use Illuminate\Validation\Rule;
|
||||
use Modules\Product\Entities\Product;
|
||||
use Modules\Core\Http\Requests\Request;
|
||||
|
||||
class StoreCartItemRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$product = Product::with('options')
|
||||
->select('id', 'manage_stock', 'qty')
|
||||
->findOrFail($this->product_id);
|
||||
|
||||
return array_merge([
|
||||
'qty' => ['required', 'numeric', $this->maxQty($product)],
|
||||
], $this->getOptionsRules($product->options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max qty rule for the given product.
|
||||
*
|
||||
* @param \Modules\Product\Entities\Product $product
|
||||
* @return string|null
|
||||
*/
|
||||
private function maxQty($product)
|
||||
{
|
||||
if ($product->manage_stock) {
|
||||
return "max:{$product->qty}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rules for the given options.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $options
|
||||
* @return array
|
||||
*/
|
||||
private function getOptionsRules($options)
|
||||
{
|
||||
return $options->flatMap(function ($option) {
|
||||
return ["options.{$option->id}" => $this->getOptionRules($option)];
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rules for the given option.
|
||||
*
|
||||
* @param \Modules\Option\Entities\Option $option
|
||||
* @return array
|
||||
*/
|
||||
private function getOptionRules($option)
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
if ($option->is_required) {
|
||||
$rules[] = 'required';
|
||||
}
|
||||
|
||||
if (in_array($option->type, ['dropdown', 'radio'])) {
|
||||
$rules[] = Rule::in($option->values->map->id->all());
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data to be validated from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function validationData()
|
||||
{
|
||||
return array_merge(
|
||||
$this->all(),
|
||||
[
|
||||
'options' => array_filter($this->options ?? []),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom messages for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages()
|
||||
{
|
||||
return array_merge([
|
||||
'options.*.required' => trans('cart::validation.this_field_is_required'),
|
||||
'options.*.in' => trans('cart::validation.the_selected_option_is_invalid'),
|
||||
], parent::messages());
|
||||
}
|
||||
}
|
||||
18
Modules/Cart/Listeners/ClearCart.php
Normal file
18
Modules/Cart/Listeners/ClearCart.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Listeners;
|
||||
|
||||
use Modules\Cart\Facades\Cart;
|
||||
|
||||
class ClearCart
|
||||
{
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Cart::clear();
|
||||
}
|
||||
}
|
||||
53
Modules/Cart/NullCartCoupon.php
Normal file
53
Modules/Cart/NullCartCoupon.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart;
|
||||
|
||||
use Modules\Support\Money;
|
||||
|
||||
class NullCartCoupon
|
||||
{
|
||||
public function id()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function code()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function isFreeShipping()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function usageLimitReached()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function didNotSpendTheRequiredAmount()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function spentMoreThanMaximumAmount()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function usedOnce()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function value()
|
||||
{
|
||||
return Money::inDefaultCurrency(0);
|
||||
}
|
||||
|
||||
public function __get($attribute)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
23
Modules/Cart/NullCartShippingMethod.php
Normal file
23
Modules/Cart/NullCartShippingMethod.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart;
|
||||
|
||||
use Modules\Support\Money;
|
||||
|
||||
class NullCartShippingMethod
|
||||
{
|
||||
public function name()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function title()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function cost()
|
||||
{
|
||||
return Money::inDefaultCurrency(0);
|
||||
}
|
||||
}
|
||||
29
Modules/Cart/Providers/CartServiceProvider.php
Normal file
29
Modules/Cart/Providers/CartServiceProvider.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Providers;
|
||||
|
||||
use Modules\Cart\Cart;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class CartServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton(Cart::class, function ($app) {
|
||||
return new Cart(
|
||||
$app['session'],
|
||||
$app['events'],
|
||||
'cart',
|
||||
session()->getId(),
|
||||
config('fleetcart.modules.cart.config')
|
||||
);
|
||||
});
|
||||
|
||||
$this->app->alias(Cart::class, 'cart');
|
||||
}
|
||||
}
|
||||
19
Modules/Cart/Providers/EventServiceProvider.php
Normal file
19
Modules/Cart/Providers/EventServiceProvider.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cart\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The event listener mappings for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $listen = [
|
||||
\Modules\Checkout\Events\OrderPlaced::class => [
|
||||
\Modules\Cart\Listeners\ClearCart::class,
|
||||
],
|
||||
];
|
||||
}
|
||||
8
Modules/Cart/Resources/lang/en/messages.php
Normal file
8
Modules/Cart/Resources/lang/en/messages.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'out_of_stock' => 'Sorry, the product is out of stock.',
|
||||
'not_have_enough_quantity_in_stock' => 'Sorry, we only have :stock in stock.',
|
||||
'one_or_more_product_is_out_of_stock' => 'Sorry, one or more product is out of stock.',
|
||||
'one_or_more_product_doesn\'t_have_enough_stock' => 'Sorry, one or more product doesn\'t have enough stock.',
|
||||
];
|
||||
6
Modules/Cart/Resources/lang/en/validation.php
Normal file
6
Modules/Cart/Resources/lang/en/validation.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'this_field_is_required' => 'This field is required.',
|
||||
'the_selected_option_is_invalid' => 'The selected option is invalid.',
|
||||
];
|
||||
15
Modules/Cart/Routes/public.php
Normal file
15
Modules/Cart/Routes/public.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get('cart', 'CartController@index')->name('cart.index');
|
||||
|
||||
Route::post('cart/items', 'CartItemController@store')->name('cart.items.store');
|
||||
Route::put('cart/items/{cartItemId}', 'CartItemController@update')->name('cart.items.update');
|
||||
Route::delete('cart/items/{cartItemId}', 'CartItemController@destroy')->name('cart.items.destroy');
|
||||
|
||||
Route::post('cart/clear', 'CartClearController@store')->name('cart.clear.store');
|
||||
|
||||
Route::post('cart/shipping-method', 'CartShippingMethodController@store')->name('cart.shipping_method.store');
|
||||
|
||||
Route::get('cart/cross-sell-products', 'CartCrossSellProductsController@index')->name('cart.cross_sell_products.index');
|
||||
28
Modules/Cart/composer.json
Normal file
28
Modules/Cart/composer.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "fleetcart/cart",
|
||||
"description": "The FleetCart Cart Module.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Envay Soft",
|
||||
"email": "envaysoft@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.0.2",
|
||||
"darryldecode/cart": "^4.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\Cart\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
10
Modules/Cart/module.json
Normal file
10
Modules/Cart/module.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Cart",
|
||||
"alias": "cart",
|
||||
"description": "The FleetCart Cart Module.",
|
||||
"priority": 100,
|
||||
"providers": [
|
||||
"Modules\\Cart\\Providers\\CartServiceProvider",
|
||||
"Modules\\Cart\\Providers\\EventServiceProvider"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user