<?php
namespace App\Manager;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Cart;
use App\Service\Mailer;
use App\Manager\CustomerManager;
use App\Entity\Product;
use App\Entity\Coupon;
class CartManager {
private $em;
private $mailer;
private $customerMgr;
private $priceMgr;
private $session;
private $translator;
public function __construct(\Symfony\Component\HttpFoundation\Session\SessionInterface $session, EntityManagerInterface $em, Mailer $mailer, CustomerManager $customerMgr, \Symfony\Contracts\Translation\TranslatorInterface $translator)
{
$this->em = $em;
$this->mailer = $mailer;
$this->customerMgr = $customerMgr;
$this->session = $session;
$this->translator = $translator;
}
public function getCustomer()
{
return $this->customerMgr->getCustomer();
}
public function isExpert()
{
return $this->customerMgr->isExpert();
}
public function getPriceContext()
{
return $this->customerMgr->getPriceContext();
}
public function getCartByCustomerId($cid)
{
$customer = $this->em->getRepository('App:Customer')->find($cid);
if($customer){
return $this->getCartByCustomer($customer);
}
return null;
}
public function getCartByCustomer($customer)
{
return $this->em->getRepository('App:Cart')->findOneByCustomer($customer);
}
public function remindCustomer(Cart $cart)
{
$this->markCartAsReminded($cart);
return $this->mailer->remindCart($cart);
}
protected function markCartAsReminded(Cart $cart)
{
// $items = $cart->getItems();
// if(!empty($items)){
// foreach ($items as $item){
// $item->setReminded(new \DateTime);
// $this->em->persist($item);
// }
// $this->em->flush();
// }
return true;
}
public function getLastUnremindedCarts()
{
$carts = [];
$customerIds = $this->getLastUnremindedCustomerIds();
if(!empty($customerIds)){
foreach ($customerIds as $cid){
$cart = $this->getCartByCustomerId($cid);
if($cart)
$carts[] = $cart;
}
}
return $carts;
}
public function getLastUnremindedCustomerIds() {
$yesterday = new \DateTime();
$yesterday->modify('-1 day');
$conn = $this->em->getConnection();
$stmt = $conn->prepare('SELECT distinct(customers_id) FROM customers_basket where customers_basket_reminded is null and `customers_basket_date_added`=\''.$yesterday->format('Ymd').'\'');
$stmt->execute();
$customerIds = [];
$lines = $stmt->fetchAll();
foreach($lines as $row){
$customerIds[] = $row['customers_id'];
}
return $customerIds;
}
public function getLastCarts($sinceNbDays=180) {
$yesterday = new \DateTime();
$yesterday->modify('-'.$sinceNbDays.' day');
$conn = $this->em->getConnection();
$stmt = $conn->prepare('SELECT distinct(customers_id) FROM customers_basket where `customers_basket_date_added`>=\''.$yesterday->format('Ymd').'\'');
$stmt->execute();
$carts = [];
$lines = $stmt->fetchAll();
foreach($lines as $row){
$cart = $this->getCartByCustomerId($row['customers_id']);
if($cart)
$carts[] = $cart;
}
return $carts;
}
public function getCartSession()
{
return $this->session->get('cart',$this->getEmptyCart());
}
private function getEmptyCart()
{
return ['products'=>[],'id'=>null,'createdAt'=>(new \DateTime())->format('Y-m-d H:i:s'),'updatedAt'=>'0000-00-00 00:00:00', 'coupons'=>[]];
}
public function getGifts()
{
return $this->em->getRepository('App:Product')->getGifts();
}
public function fillCartFromSession(&$cart)
{
$cart->setItems([]);
$cartSession = $this->getCartSession();
if(empty($cartSession['products']))
return;
foreach($cartSession['products'] as $item){
$product = $this->em->getRepository('App:Product')->find($item['product']['id']);
if(!empty($product))
$cart->addItem(
$product,
$item['qty']
);
}
}
public function getCart($reload=false) : Cart
{
$customer = $this->customerMgr->getCustomer();
$cartSession = $this->getCartSession();
$cart = null;
$fillFromSession = false;
$priceGroup = $this->customerMgr->getPriceContext();
if($customer){
$cart = $this->em->getRepository('App:Cart')->findOneBy([
'customer' => $customer->getId(),
'priceGroup' => $priceGroup,
]);
if($cart)
$cart->setCustomer($customer);
}else if(!empty($cartSession['id'])){
$cart = $this->em->getRepository('App:Cart')->find($cartSession['id']);
}
if(empty($cart)){
$cart = new Cart();
$cart->setPriceGroup($priceGroup);
if($customer){
$cart->setCustomer($customer);
}
}
if(!isset($cartSession['coupons'])){
$cartSession['coupons'] = [];
}
foreach($cartSession['coupons'] as $c){
$coupon = $this->em->getRepository(\App\Entity\Coupon::class)->find($c['id']);
if(!empty($coupon))
$cart->addCoupon($coupon);
}
$this->cart = $cart;
return $this->cart;
}
public function add(Product $product,$qty,$actionType=null,$genericProductId=null,$categoryId=null,$force=false)
{
if(!$this->customerMgr->isLogged()){
return [
'success'=>false,
'error'=>'',
'requestQty'=>$qty,
'totalQty'=>$qty
];
}
$cart = $this->getCart();
if($cart->hasProduct($product)){
$qtyUpdate = $cart->getItemQuantityByProduct($product)+$qty;
if($qtyUpdate<=0){
return $this->remove($product);
}
return $this->update($product, $qtyUpdate);
}
if($product->isGift()){
$qty = 1;
}
$cart->addItem($product,$qty);
$checkQuantity = $this->checkQuantityForProduct($product, $qty, $force);
if($checkQuantity === true){
return $this->save($cart);
}else{
return [
'success'=>false,
'error'=>$checkQuantity,
'requestQty'=>$qty,
'totalQty'=>$qty
];
}
return [
'success'=>false,
'error'=>'',
'requestQty'=>$qty,
'totalQty'=>$qty
];
}
public function update(Product $product,$qty)
{
$cart = $this->getCart();
if(empty($cart)){
$cart = [];
}
if(!$cart->hasProduct($product)){
return $this->add($product, $qty, null, null, null, $force);
}
if($qty<=0){
return $this->remove($product);
}
if($product->isGift()){
$qty = 1;
}
$cart->updateItem($product,$qty);
$cart = $this->save($cart);
return $cart;
}
public function qtyInCart(Product $product)
{
$cart = $this->getCart();
if(empty($cart))
return 0;
return $cart->getItemQuantityByProduct($product);
}
public function setAddress(\App\Entity\Address $address, $type) {
$cart = $this->getCart();
if($type == 'shipping'){
$cart->setShippingAddress($address);
}else if($type == 'billing'){
$cart->setBillingAddress($address);
}else{
throw new \Exception("Type d'adresse inconnu (".$type.")");
}
return $this->save($cart);
}
public function setCarrier(\App\Entity\Carrier $carrier) {
$cart = $this->getCart();
$cart->setCarrier($carrier);
return $this->save($cart);
}
public function checkQuantityForProduct(Product $product, $qty, $force){
return $product->getQuantity()>=$qty;
}
public function checkCartDisponibility(Cart $cart) {
// $output = [
// 'products' => [],
// 'message' => ''
// ];
// foreach($cart->getItems() as $item){
// $product = $item->getProduct();
// if(!$item->getProduct()->isAvailable()){
// $cart->removeItem($product);
// $output['products'][] = $product;
// }
// }
// if(!empty($output['products'])){
// $this->save($cart);
// return false;
// }
return true;
}
public function remove(Product $product)
{
$cart = $this->getCart();
if(empty($cart)){
return false;
}
$item = $cart->getItemByProduct($product);
if($item){
$this->em->remove($item);
$this->em->flush();
$cart = $this->save($cart);
}
return $this->save($cart);
}
public function empty()
{
$cart = $this->getCart();
$this->em->remove($cart);
$this->em->flush();
$this->session->remove('cart');
}
public function save(Cart $cart)
{
$customer = $this->customerMgr->getCustomer();
$cartId = $cart->getId();
$items = $cart->getItems();
if($customer){
if(empty($cartId))
$cart->setCustomer($customer);
}
if(empty($items)){
$this->em->remove($cart);
}else{
$this->em->persist($cart);
}
$this->em->flush();
$this->session->set('cart',$cart->toArray());
$this->cart = $cart;
return $this->cart;
}
public function assignCartToCustomer($cartId, Customer $customer)
{
// utilisation d'une requête SQL pour empecher l'ecrasement de la date de mise à jour.
$conn = $this->em->getConnection();
$conn->executeQuery("update Cart set CustomerId=".$customer->getId()." where Id=:id",['id'=>$cartId]);
}
public function checkCartItems(Cart $cart) {
// Available
$refs = [];
foreach($cart->getItems() as $item){
$product = $item->getProduct();
if(!$item->getProduct()->isAvailable() || $item->getProduct()->isStopped()){
$cart->removeItem($product);
$refs[] = $product->getReference();
}
}
if(!empty($refs)){
$this->session->getFlashBag()->add('error', $this->translator->trans('Les articles suivants ne sont plus disponibles à la vente : ') . ' ' . implode(', ',$refs));
$this->save($cart);
return false;
}
$refs = [];
foreach($cart->getItems() as $item){
$product = $item->getProduct();
if($item->getProduct()->getQuantity() < $item->getQuantity()){
$refs[] = $product->getReference();
}
}
if(!empty($refs)){
$this->session->getFlashBag()->add('error', $this->translator->trans('La quantité demandée pour les articles suivants n\'est pas disponible : ') . ' ' . implode(', ',$refs));
$this->save($cart);
return false;
}
$refs = [];
$country = $this->customerMgr->getCustomerCountry();
foreach($cart->getItems() as $item){
$product = $item->getProduct();
if(!$item->getProduct()->isAvailableForCountry($country)){
$cart->removeItem($product);
$refs[] = $product->getReference();
}
}
if(!empty($refs)){
$this->session->getFlashBag()->add('error', $this->translator->trans('Les articles suivants ne sont pas disponibles à la vente pour votre zone géographique : ') . ' ' . implode(', ',$refs));
$this->save($cart);
return false;
}
return true;
}
public function checkShippingRate(Cart $cart) {
$shippingRate = $cart->getShippingRate();
return empty($shippingRate) ? false : true;
}
public function checkDropShipping(Cart $cart) {
if($cart->getCarrier()->getCode() != 'dropshipping')
return true;
return $cart->getBillingAddress()->getId() != $cart->getShippingAddress()->getId();
}
public function addCoupon(Coupon $coupon) {
$cart = $this->getCart();
$result = $cart->addCoupon($coupon);
if($result === true){
return $this->save($cart);
}
return $result;
}
}