<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Product;
/**
* @ORM\Table(name="carts")
* @ORM\Entity(repositoryClass="App\Repository\CartRepository")
* @ORM\HasLifecycleCallbacks()
*/
class Cart
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var \App\Entity\Customer
*
* @ORM\ManyToOne(targetEntity="App\Entity\Customer")
* @ORM\JoinColumn(name="customer_id", referencedColumnName="customers_id", nullable=true)
*/
private $customer;
/**
* @var array
*
* @ORM\OneToMany(targetEntity="App\Entity\CartItem", mappedBy="cart", cascade={"persist", "remove"})
*/
private $items = [];
/**
* @var \App\Entity\PriceGroup|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\PriceGroup")
* @ORM\JoinColumn(name="price_group_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $priceGroup;
/**
* @var \App\Entity\Address|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\Address")
* @ORM\JoinColumn(name="shipping_address_id", referencedColumnName="address_book_id", nullable=true, onDelete="SET NULL")
*/
private $shippingAddress;
/**
* @var \App\Entity\Address|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\Address")
* @ORM\JoinColumn(name="billing_address_id", referencedColumnName="address_book_id", nullable=true, onDelete="SET NULL")
*/
private $billingAddress;
/**
* @var \App\Entity\Carrier|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\Carrier")
* @ORM\JoinColumn(name="carrier_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $carrier;
/**
* @var \App\Entity\PaymentMean|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\PaymentMean")
* @ORM\JoinColumn(name="payment_mean_id", referencedColumnName="id", nullable=true)
*/
private $paymentMean;
/**
* @var string|null
*
* @ORM\Column(name="shipping_infos", type="string", length=255, nullable=true)
*/
private $shippingInfos;
/**
* @var string|null
*
* @ORM\Column(name="comment", type="text", length=1024, nullable=true)
*/
private $comment;
/**
* @var \DateTime|null
*
* @ORM\Column(name="created_at", type="datetime", nullable=false)
*/
private $createdAt;
/**
* @var \DateTime|null
*
* @ORM\Column(name="updated_at", type="datetime", nullable=true)
*/
private $updatedAt;
private $shippingRate;
private $shippingRates = [];
private $coupons = [];
private $pickupStore = null;
private $total = 0;
public function __construct()
{
$this->items = new ArrayCollection();
}
public function getId() {
return $this->id;
}
public function getCustomer(): ?\App\Entity\Customer {
return $this->customer;
}
public function getItems($lang = 'fr') {
if(empty($this->items))
return $this->items;
foreach($this->items as &$item){
if($item->getProduct())
$item->getProduct()->translate($lang);
}
return $this->items;
}
public function getShippingAddress(): ?\App\Entity\Address {
if(empty($this->shippingAddress) && !empty($this->customer))
return $this->getCustomer()->getDefaultAddress();
return $this->shippingAddress;
}
public function getBillingAddress(): ?\App\Entity\Address {
if(empty($this->billingAddress) && !empty($this->customer))
return $this->getCustomer()->getDefaultAddress ();
return $this->billingAddress;
}
public function getCarrier(): ?\App\Entity\Carrier {
return $this->carrier;
}
public function getPaymentMean(): ?\App\Entity\PaymentMean {
return $this->paymentMean;
}
public function getCreatedAt() {
return $this->createdAt;
}
public function getUpdatedAt() {
return $this->updatedAt;
}
public function getLanguageCode() {
$customer = $this->getCustomer();
if($customer){
$address = $customer->getDefaultAddress();
if(in_array($address->getCountry()->getIsoCode2(), ['FR','MQ','GP','FO','YT','NC','RE','GF']))
return 'fr';
return 'en';
}
return 'fr';
}
public function getPickupStore() {
return $this->pickupStore;
}
public function getShippingInfos(): ?string {
return $this->shippingInfos;
}
public function getComment(): ?string {
return $this->comment;
}
public function getPaymentDiscount() {
if(empty($this->paymentMean))
return 0;
$totalProduct = $this->getTotalProducts();
if(($totalProduct > \App\Manager\OrderManager::DIRECT_PAYMENT_DISCOUNT_FROM) && $this->paymentMean->isDirect()){
return \App\Manager\OrderManager::DIRECT_PAYMENT_DISCOUNT * $this->getTotalProducts() * -1;
}
return 0;
}
public function getShippingRate() {
return $this->shippingRate;
}
public function getShippingRateByCarrier(Carrier $carrier) {
foreach($this->getShippingRates() as $shippingRate){
if($shippingRate->getCarrier() == $carrier){
return $shippingRate;
}
}
return null;
}
public function getShippingRates() {
return $this->shippingRates;
}
public function getPriceGroup(): ?\App\Entity\PriceGroup {
return $this->priceGroup;
}
public function setId($id) {
$this->id = $id;
}
public function setCustomer(?\App\Entity\Customer $customer) {
$this->customer = $customer;
}
public function setItems($items) {
$this->items = $items;
$this->init();
}
public function setShippingAddress(?\App\Entity\Address $shippingAddress): void {
$this->shippingAddress = $shippingAddress;
}
public function setBillingAddress(?\App\Entity\Address $billingAddress): void {
$this->billingAddress = $billingAddress;
}
public function setCreatedAt($createdAt) {
$this->createdAt = $createdAt;
}
public function setUpdatedAt($updatedAt) {
$this->updatedAt = $updatedAt;
}
public function setCarrier(?\App\Entity\Carrier $carrier): void {
$this->carrier = $carrier;
}
public function setPaymentMean(?\App\Entity\PaymentMean $paymentMean): void {
$this->paymentMean = $paymentMean;
}
public function setShippingInfos(?string $shippingInfos): void {
$this->shippingInfos = $shippingInfos;
}
public function setPickupStore($pickupStore): void {
$this->pickupStore = $pickupStore;
if($pickupStore){
$this->setShippingInfos($pickupStore->getId());
}
}
public function setComment(?string $comment): void {
$this->comment = $comment;
}
public function setShippingRate($shippingRate): void {
$this->shippingRate = $shippingRate;
}
public function setShippingRates($shippingRates): void {
$this->shippingRates = $shippingRates;
}
public function setPriceGroup(?\App\Entity\PriceGroup $priceGroup): void {
$this->priceGroup = $priceGroup;
}
public function calculate() {
foreach ($this->getItems() as $item){
$this->total += $item->getTotalPrice();
}
return $this->total;
}
public function init() {
$items = $this->getItems();
foreach($this->items as $item){
if($item->getProduct())
$item->getProduct()->translate('fr');
}
return $this->calculate();
}
public function getTotalProducts($withDiscount = false)
{
$total = 0;
$items = [];
foreach($this->getItems() as $item)
{
$total += $item->getTotalPrice();
}
if($withDiscount){
$total += $this->getTotalProductsDiscount();
}
return $total;
}
public function getTotalProductsDiscount()
{
if($this->isExpert()) {
return $this->getTotalProducts() * 0.2 * -1;
}
$total = 0;
if(empty($this->coupons))
return 0;
foreach($this->coupons as $coupon)
{
$total += $coupon->getMarketingRule()->getCartDiscount($this);
}
return $total;
}
public function getTotalProductsWithPaymentDiscount()
{
return $this->getTotalProducts()+$this->getPaymentDiscount();
}
public function getTotalShipping()
{
return $this->carrier ? $this->carrier->getPriceByCart($this) : 0;;
}
public function getTotalTax()
{
if(!$this->hasTax())
return 0;
$tax = 0;
$tax += $this->getTotalProducts(true) * Product::VAT_RATE;
$tax += $this->getTotalShipping() * Carrier::VAT_RATE;
return $tax;
}
public function getTotal()
{
$total = $this->getTotalProducts();
$total += $this->getTotalProductsDiscount();
$total += $this->getPaymentDiscount();
$total += $this->getTotalShipping();
$total += $this->getTotalTax();
return $total>0?$total:0;
}
public function getSoleilTotal()
{
$total = 0;
foreach($this->getItems() as $item)
{
if($item->getProduct()->isSoleil()){
$total += $item->getProduct()->getPrice() * $item->getQuantity();
}
}
return $total;
}
public function getNonSoleilTotal()
{
$total = 0;
foreach($this->getItems() as $item)
{
if($item->getProduct()->isNonSoleil()){
$total += $item->getProduct()->getPrice() * $item->getQuantity();
}
}
return $total;
}
public function getVivogTotal()
{
$total = 0;
foreach($this->getItems() as $item)
{
if($item->getProduct()->isVivog()){
$total += $item->getProduct()->getPrice() * $item->getQuantity();
}
}
return $total;
}
public function getExpertTotal(PriceGroup $priceGroup, $withVat = true)
{
$total = 0;
foreach($this->getItems() as $item)
{
if($item->getProduct()->isVivog()){
$total += $item->getProduct()->getPrice(true, $priceGroup, $withVat) * $item->getQuantity();
}
}
return $total;
}
public function hasProduct(Product $product)
{
if(empty($this->items))
return false;
foreach($this->items as $item){
if($item->getProduct()->getId() == $product->getId())
return true;
}
return false;
}
public function getProducts()
{
$products = [];
foreach($this->getItems() as $item)
{
$products[] = $item->getProduct();
}
return $products;
}
public function hasTax()
{
try{
$customer = $this->getCustomer();
if($customer && $customer->hasNoTva())
return false;
$billingAddress = $this->getBillingAddress();
if(empty($billingAddress))
return false;
$billingCountry = $billingAddress->getCountry();
if($billingCountry->isDom())
return false;
if(!$billingCountry->isFrance() && $customer->getTva())
return false;
} catch (\Exception $ex) {
}
return true;
}
public function addItem(Product $product,$qty=1,$oa=null,$gid=null,$cid=null,$oc=null,$d=null)
{
if($this->hasProduct($product)){
$qty = $this->getItemQuantityByProduct($product)+$qty;
return $this->updateItem($product, $qty);
}else{
$item = new CartItem($product,$qty);
$item->setCart($this);
$item->setUnitPrice($product->getPrice(false, $this->getPriceGroup()));
$this->items[] = $item;
}
}
public function updateItem(Product $product,$qty)
{
foreach($this->items as &$item){
if($item->getProduct()->getId() == $product->getId()){
$item->setQuantity($qty);
$item->setUnitPrice($product->getPrice(false, $this->getPriceGroup()));
}
}
}
public function removeItem(Product $product)
{
$result = false;
$tab = [];
foreach($this->items as &$item){
if($item->getProduct()->getId() != $product->getId()){
$tab[] = $item;
$result = true;
}
}
$this->setItems($tab);
return $result;
}
public function getItemByProduct(Product $product)
{
foreach($this->items as $item){
if($item->getProduct()->getId() == $product->getId())
return $item;
}
return false;
}
public function getItemQuantityByProduct(Product $product)
{
$item = $this->getItemByProduct($product);
return $item ? $item->getQuantity() : 0;
}
public function hasGift()
{
foreach($this->items as &$item){
if($item->getProduct()->isGift()){
return true;
}
}
return false;
}
public function canAddGift()
{
foreach($this->items as &$item){
if($item->getProduct()->isProduct()){
return true;
}
}
return false;
}
public function getCoupons() {
return $this->coupons;
}
public function setCoupons($coupons): void {
$this->coupons = $coupons;
}
public function hasCoupon(Coupon $coupon)
{
if(empty($this->coupons))
return false;
foreach($this->coupons as $c){
if($coupon->getCode() == $c->getCode())
return true;
}
return false;
}
public function addCoupon(Coupon $coupon)
{
if(!$this->hasCoupon($coupon)){
$this->coupons[] = $coupon;
return true;
}
return "Coupon déjà présent...";
}
public function removeCoupon(Coupon $coupon)
{
$result = false;
$tab = [];
if(empty($this->coupons))
return false;
foreach($this->coupons as &$c){
if($coupon->getId() != $c->getId()){
$tab[] = $coupon;
$result = true;
}
}
$this->setCoupons($tab);
return $result;
}
public function hasSoleilDiscount(?Product $product = null)
{
if(!empty($product)) {
if($product->isSoleil()) {
$total = $this->getSoleilTotal() + $product->getPrice();
return $total >= 100;
}else if($product->isNonSoleil()) {
$total = $this->getNonSoleilTotal() + $product->getPrice();
return $total >= 100;
}
return false;
}
return $this->getNonSoleilTotal() >= 100 || $this->getSoleilTotal() >= 100;
}
public function applyDiscount(MarketingRule $discount)
{
if($discount->getType() == MarketingRule::TYPE_OFFERED) {
if(true) { // pas de panaché
$discountedProducts = $discount->getProductsDiscounted();
foreach ($this->items as $item) {
$qtyOffered = $discount->getNbProductsOffered($this, $item->getProduct());
if($qtyOffered > 0) {
$qtyRequired = $discount->getQtyRequested();
$item->setQuantityOffered($qtyOffered);
$item->setMarketingRule($discount);
}
}
}else{ //panaché
// $iterator = $this->items->getIterator();
// $iterator->uasort(function ($a, $b) {
// if ($a->getProduct()->getPrice() == $b->getProduct()->getPrice() ) {
// return 0;
// }
// return ($a->getProduct()->getPrice() < $b->getProduct()->getPrice() ) ? -1 : 1;
// });
// $this->items = new ArrayCollection(iterator_to_array($iterator));
// $qtyOffered = $discount->getNbProductsOffered($this);
// $remainingFreeItems = $qtyOffered;
// foreach ($this->items as $item) {
// if ($remainingFreeItems > 0) {
// $freeItemsOnThisLine = min($remainingFreeItems, $item->getQuantity());
// $item->setQuantityOffered($freeItemsOnThisLine);
// $item->setMarketingRule($discount);
// $remainingFreeItems -= $freeItemsOnThisLine;
// }
// }
}
}
}
public function isExpert()
{
return $this->priceGroup && $this->priceGroup->getCode() == PriceGroup::CODE_EXPERT;
}
public function toArray()
{
$items = [];
foreach ($this->getItems() as $item){
$items[] = $item->toArray();
}
$coupons = [];
foreach ($this->getCoupons() as $coupon){
$coupons[] = $coupon->toArray();
}
return [
'id'=>$this->getId(),
'products'=>$items,
'totalProducts'=>$this->getTotalProducts(),
'totalProductsWithDiscount'=>$this->getTotalProducts(true),
'discount'=>$this->getTotalProductsDiscount(),
'total'=>$this->getTotal(),
'coupons'=>$coupons,
'customerId'=>!empty($this->customer)?$this->getCustomer()->getId():null,
'carrier'=>!empty($this->carrier)?$this->getCarrier()->toArray():null,
'createdAt'=>empty($this->createdAt)?null:$this->createdAt->format('Y-m-d H:i:s'),
'updatedAt'=>empty($this->updatedAt)?null:$this->updatedAt->format('Y-m-d H:i:s')
];
}
/**
* @ORM\PostLoad
*/
public function postLoad(\Doctrine\ORM\Event\LifecycleEventArgs $args) {
if(!empty($this->shippingAddress)){
$shippingRates = $args->getEntityManager()->getRepository('App:ShippingRate')->findBy([
'country' => $this->getShippingAddress()->getCountry()
]);
$this->setShippingRates($shippingRates);
if($this->carrier){
$shippingRate = $this->getShippingRateByCarrier($this->carrier);
$this->setShippingRate($shippingRate);
}
}else if(empty($this->shippingAddress) && !empty($this->customer)){
$this->setShippingAddress($this->getCustomer()->getDefaultAddress());
}
$this->init();
}
/**
* @ORM\PrePersist()
*/
public function prePersist(\Doctrine\ORM\Event\LifecycleEventArgs $args) {
$this->setCreatedAt(new \DateTime());
}
/**
* @ORM\PreUpdate()
*/
public function preUpdate(\Doctrine\ORM\Event\LifecycleEventArgs $args) {
$this->setUpdatedAt(new \DateTime());
}
public function __toString() {
return 'carttostring';
}
}