Ver código fonte

Livraisons Produits/réductions

master
Fab 4 anos atrás
pai
commit
130ab33218
38 arquivos alterados com 1413 adições e 717 exclusões
  1. +8
    -0
      ShopBundle/Context/OrderProductReductionCatalogInterface.php
  2. +8
    -0
      ShopBundle/Context/ProductFamilyUtilsInterface.php
  3. +80
    -67
      ShopBundle/Controller/Admin/AdminController.php
  4. +1
    -1
      ShopBundle/Controller/Admin/OrderController.php
  5. +56
    -42
      ShopBundle/Controller/Admin/ProductFamilyController.php
  6. +1
    -1
      ShopBundle/Controller/Frontend/CartController.php
  7. +4
    -7
      ShopBundle/Form/ProductType.php
  8. +96
    -12
      ShopBundle/Form/ReductionCatalogType.php
  9. +1
    -1
      ShopBundle/Model/OrderAmountMin.php
  10. +21
    -1
      ShopBundle/Model/OrderProduct.php
  11. +31
    -0
      ShopBundle/Model/OrderProductReductionCatalog.php
  12. +3
    -103
      ShopBundle/Model/PriceTrait.php
  13. +38
    -23
      ShopBundle/Model/Product.php
  14. +11
    -39
      ShopBundle/Model/ProductFamily.php
  15. +8
    -3
      ShopBundle/Model/ProductPropertyTrait.php
  16. +2
    -1
      ShopBundle/Model/ReductionCart.php
  17. +18
    -5
      ShopBundle/Model/ReductionCatalog.php
  18. +61
    -0
      ShopBundle/Model/ReductionPropertyTrait.php
  19. +0
    -55
      ShopBundle/Model/ReductionTrait.php
  20. +14
    -0
      ShopBundle/Repository/ProductFamilyRepository.php
  21. +6
    -1
      ShopBundle/Resources/public/css/backend/custom.css
  22. +13
    -1
      ShopBundle/Resources/public/js/backend/script/default/utils.js
  23. +150
    -90
      ShopBundle/Resources/public/js/backend/script/default/vuejs-mixins.js
  24. +140
    -63
      ShopBundle/Resources/public/js/backend/script/productfamily/vuejs-product-family.js
  25. +1
    -24
      ShopBundle/Resources/public/js/backend/script/reductioncatalog/vuejs-reduction-catalog.js
  26. +10
    -3
      ShopBundle/Resources/translations/lcshop.fr.yaml
  27. +128
    -3
      ShopBundle/Resources/views/backend/default/block/macros.html.twig
  28. +1
    -0
      ShopBundle/Resources/views/backend/default/list-fields/field_price.html.twig
  29. +13
    -0
      ShopBundle/Resources/views/backend/productfamily/edit.html.twig
  30. +12
    -2
      ShopBundle/Resources/views/backend/productfamily/form.html.twig
  31. +25
    -24
      ShopBundle/Resources/views/backend/productfamily/panel_price.html.twig
  32. +66
    -6
      ShopBundle/Resources/views/backend/productfamily/panel_products.html.twig
  33. +21
    -0
      ShopBundle/Resources/views/backend/productfamily/panel_reduction.html.twig
  34. +1
    -1
      ShopBundle/Resources/views/backend/productfamily/panel_stock.html.twig
  35. +2
    -108
      ShopBundle/Resources/views/backend/reductioncatalog/form.html.twig
  36. +68
    -30
      ShopBundle/Services/OrderUtils.php
  37. +242
    -0
      ShopBundle/Services/PriceUtils.php
  38. +52
    -0
      ShopBundle/Services/ProductFamilyUtils.php

+ 8
- 0
ShopBundle/Context/OrderProductReductionCatalogInterface.php Ver arquivo

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

namespace Lc\ShopBundle\Context ;

interface OrderProductReductionCatalogInterface
{

}

+ 8
- 0
ShopBundle/Context/ProductFamilyUtilsInterface.php Ver arquivo

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

namespace Lc\ShopBundle\Context ;

interface ProductFamilyUtilsInterface
{

}

+ 80
- 67
ShopBundle/Controller/Admin/AdminController.php Ver arquivo

@@ -240,11 +240,17 @@ class AdminController extends EasyAdminController
return $this->executeDynamicMethod('render<EntityName>Template', ['sortable', "@LcShop/backend/default/sortable.html.twig", $parameters]);
}

public function createEntityFormBuilder($entity, $view)
public function createEntityFormBuilder($entity, $view, $override = true)
{

$formBuilder = parent::createEntityFormBuilder($entity, $view);

if($override)$formBuilder = $this->overrideFormBuilder($formBuilder, $entity, $view);

return $formBuilder;
}

public function overrideFormBuilder($formBuilder, $entity, $view){
$id = (null !== $entity->getId()) ? $entity->getId() : 0;

if ($entity instanceof StatusInterface) {
@@ -277,75 +283,82 @@ class AdminController extends EasyAdminController

$formBuilder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$allChilds = $form->all();
foreach ($allChilds as $child) {
$statusInterface = false;
$treeInterface = false;
$type = $child->getConfig()->getType()->getInnerType();

if ($type instanceof EntityType) {
$passedOptions = $child->getConfig()->getOptions();
$classImplements = class_implements($passedOptions['class']);

$isFilterMerchantInterface = in_array('Lc\ShopBundle\Context\FilterMerchantInterface', $classImplements) ;
$isFilterMultipleMerchantsInterface = in_array('Lc\ShopBundle\Context\FilterMultipleMerchantsInterface', $classImplements) ;

if ($isFilterMerchantInterface || $isFilterMultipleMerchantsInterface) {

if (in_array('Lc\ShopBundle\Context\StatusInterface', $classImplements)) {
$statusInterface = true;
}

if (in_array('Lc\ShopBundle\Context\TreeInterface', $classImplements)) {
$treeInterface = true;
}
$propertyMerchant = 'merchant';
if($isFilterMultipleMerchantsInterface) {
$propertyMerchant .= 's' ;
}

$form->add($child->getName(), EntityType::class, array(
'class' => $this->em->getClassMetadata($passedOptions['class'])->getName(),
'label' => $passedOptions['label'],
'multiple' => isset($passedOptions['multiple']) ? $passedOptions['multiple'] : false,
'placeholder' => '--',
'translation_domain'=> 'lcshop',
'query_builder' => function (EntityRepository $repo) use ($passedOptions, $propertyMerchant, $statusInterface, $treeInterface, $child) {
$queryBuilder = $repo->createQueryBuilder('e');
$propertyMerchant = 'e.' . $propertyMerchant;

if ($passedOptions['class'] == 'App\Entity\PointSale') {
$queryBuilder->where(':currentMerchant MEMBER OF ' . $propertyMerchant);
} else {
$queryBuilder->where($propertyMerchant . ' = :currentMerchant');
}

if($statusInterface){
$queryBuilder->andWhere('e.status >= 0');
}
if($treeInterface && $child->getName() =='parent'){
$queryBuilder->andWhere('e.parent is null');
}
$queryBuilder->setParameter(':currentMerchant', $this->getUser()->getMerchant()->getId());

return $queryBuilder;
},
'choice_label' => function($choice) {
if($choice instanceof StatusInterface && $choice->getStatus() == 0){
return $choice.' [hors ligne]';
}
return $choice;

},
'required' => $passedOptions['required'],
)
);
$childrens = $form->all();
$this->loopFormField($form, $childrens);
});
return $formBuilder;
}

private function loopFormField($form, $childrens){
foreach ($childrens as $child) {
$statusInterface = false;
$treeInterface = false;
$type = $child->getConfig()->getType()->getInnerType();;
if ($type instanceof EntityType) {
$passedOptions = $child->getConfig()->getOptions();
$classImplements = class_implements($passedOptions['class']);

$isFilterMerchantInterface = in_array('Lc\ShopBundle\Context\FilterMerchantInterface', $classImplements) ;
$isFilterMultipleMerchantsInterface = in_array('Lc\ShopBundle\Context\FilterMultipleMerchantsInterface', $classImplements) ;

if ($isFilterMerchantInterface || $isFilterMultipleMerchantsInterface) {

if (in_array('Lc\ShopBundle\Context\StatusInterface', $classImplements)) {
$statusInterface = true;
}

if (in_array('Lc\ShopBundle\Context\TreeInterface', $classImplements)) {
$treeInterface = true;
}
$propertyMerchant = 'merchant';
if($isFilterMultipleMerchantsInterface) {
$propertyMerchant .= 's' ;
}

$form->add($child->getName(), EntityType::class, array(
'class' => $this->em->getClassMetadata($passedOptions['class'])->getName(),
'label' => $passedOptions['label'],
'multiple' => isset($passedOptions['multiple']) ? $passedOptions['multiple'] : false,
'placeholder' => '--',
'translation_domain'=> 'lcshop',
'query_builder' => function (EntityRepository $repo) use ($passedOptions, $propertyMerchant, $statusInterface, $treeInterface, $child) {
$queryBuilder = $repo->createQueryBuilder('e');
$propertyMerchant = 'e.' . $propertyMerchant;

if ($passedOptions['class'] == 'App\Entity\PointSale') {
$queryBuilder->where(':currentMerchant MEMBER OF ' . $propertyMerchant);
} else {
$queryBuilder->where($propertyMerchant . ' = :currentMerchant');
}

if($statusInterface){
$queryBuilder->andWhere('e.status >= 0');
}
if($treeInterface && $child->getName() =='parent'){
$queryBuilder->andWhere('e.parent is null');
}
$queryBuilder->setParameter(':currentMerchant', $this->getUser()->getMerchant()->getId());

return $queryBuilder;
},
'choice_label' => function($choice) {
if($choice instanceof StatusInterface && $choice->getStatus() == 0){
return $choice.' [hors ligne]';
}
return $choice;

},
'required' => $passedOptions['required'],
)
);
}
}else{
$subChildrens = $child->all();
if(count($subChildrens)){
$this->loopFormField($child, $subChildrens);
}
}
});

return $formBuilder;
}
}
}


+ 1
- 1
ShopBundle/Controller/Admin/OrderController.php Ver arquivo

@@ -77,7 +77,7 @@ class OrderController extends AdminController
parent::persistEntity($entity);
}

public function createEntityFormBuilder($entity, $view)
public function createEntityFormBuilder($entity, $view, $override=true)
{
$formBuilder = parent::createEntityFormBuilder($entity, $view);


+ 56
- 42
ShopBundle/Controller/Admin/ProductFamilyController.php Ver arquivo

@@ -3,12 +3,15 @@
namespace Lc\ShopBundle\Controller\Admin;

use App\Entity\Product;
use App\Entity\ReductionCatalog;
use Doctrine\DBAL\Types\FloatType;
use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Event\EasyAdminEvents;
use Lc\ShopBundle\Context\ProductCategoryInterface;
use Lc\ShopBundle\Context\ProductFamilyInterface;
use Lc\ShopBundle\Context\ProductInterface;
use Lc\ShopBundle\Context\ReductionCartInterface;
use Lc\ShopBundle\Context\ReductionCatalogInterface;
use Lc\ShopBundle\Context\TaxRateInterface;
use Lc\ShopBundle\Context\UnitInterface;
use Lc\ShopBundle\Form\ProductFamilyCategoriesType;
@@ -29,21 +32,27 @@ class ProductFamilyController extends AdminController
private $choicesTaxRateParam;
private $choicesSupplierTaxRateParam;

public function createEntityFormBuilder($entity, $view)
public function createEntityFormBuilder($entity, $view, $override = true)
{
$formBuilder = parent::createEntityFormBuilder($entity, $view);

$formBuilder = parent::createEntityFormBuilder($entity, $view, false);

$class = $this->em->getClassMetadata(ProductCategoryInterface::class);
$this->taxRateClass = $this->em->getClassMetadata(TaxRateInterface::class);

$formBuilder->add('productCategories', ProductFamilyCategoriesType::class);
//$formBuilder->add('reductionCatalog', ReductionCatalogType::class);

/*$formBuilder->add('taxRate', EntityType::class, array(
'class' => $this->em->getClassMetadata(TaxRateInterface::class)->name,
'required' =>false,
'placeholder'=> 'Tva par défaut ('.$this->getUser()->getMerchant()->getTaxRate()->getValue().'%)'
));*/

$reductionCatalogRepo = $this->em->getRepository(ReductionCatalogInterface::class);

$reductionCatalogClass = $this->em->getClassMetadata(ReductionCatalogInterface::class);
$reductionCatalog = $reductionCatalogRepo->findOneBy(array('status'=>false, 'productFamily'=>$entity));

if($reductionCatalog == null)$reductionCatalog = new $reductionCatalogClass->name;
$formBuilder->add('reductionCatalog', ReductionCatalogType::class,array(
'mapped'=>false,
'data'=> $reductionCatalog
));


$formBuilder->add('warningMessageType', ChoiceType::class, array(
@@ -72,14 +81,13 @@ class ProductFamilyController extends AdminController
));

$formBuilder->add('behaviorAddToCart', ChoiceType::class, array(
'empty_data' => 'by-product-family',
'data' => $entity->getBehaviorAddToCart() ? $entity->getBehaviorAddToCart() : 'simple',
'choices' => array(
'field.ProductFamily.behaviorAddToCartOptions.simple' => 'simple',
'field.ProductFamily.behaviorAddToCartOptions.multiple' => 'multiple'
),
'translation_domain' => 'lcshop',
'multiple' => false,
'required'=>false,
'expanded' => true
));

@@ -94,6 +102,11 @@ class ProductFamilyController extends AdminController
'expanded' => true
));

$formBuilder->add('multiplyingFactor', NumberType::class, array(
'mapped'=> false,
'data'=> floatval($this->merchantUtils->getMerchantConfig('multiplying-factor')),
));

$formBuilder->add('propertyOrganicLabel', ChoiceType::class, array(
'choices' => array(
'field.ProductFamily.organicLabelOptions.ab' => 'ab',
@@ -140,67 +153,67 @@ class ProductFamilyController extends AdminController
)
);

$formBuilder = $this->overrideFormBuilder($formBuilder, $entity, $view);

return $formBuilder;
}

public function updateEntity($entity)
public function updateProductFamilyEntity($entity, $editForm)
{
$productFamilyRequest = $this->request->request->get('productfamily');

if(isset($productFamilyRequest['taxRate'])) {
$taxRateId = intval($productFamilyRequest['taxRate']);
if ($taxRateId > 0) {
$repo = $this->em->getRepository(TaxRateInterface::class);
$entity->setTaxRate($repo->find($taxRateId));
}
}

$unitId = intval($productFamilyRequest['unit']);
if ($unitId > 0) {
$repo = $this->em->getRepository(UnitInterface::class);
$entity->setUnit($repo->find($unitId));
}

//$reductionCatalogInfo = $productFamilyRequest['reductionCatalog'];



$this->processReductionCatalog($entity, $editForm);
$this->processCategories($entity);
$this->processProducts($entity);
/* dump($reductionCatalog);
dump($productFamilyRequest);*/
$this->processPrice($entity);

parent::updateEntity($entity);
}

public function persistEntity($entity)
public function persistProductFamilyEntity($entity, $newForm)
{
$this->processReductionCatalog($entity, $newForm);
$this->processCategories($entity);
$this->processProducts($entity);
$this->processPrice($entity);

$this->em->persist($entity);
$this->em->flush();
}

parent::persistEntity($entity);
protected function processReductionCatalog($entity, $editForm){
$reductionCatalog = $editForm->get('reductionCatalog')->getData();
if($reductionCatalog instanceof ReductionCatalogInterface ) {
if($reductionCatalog->getValue() && $reductionCatalog->getBehaviorTaxRate() && $reductionCatalog->getUnit()){
$reductionCatalog->setMerchant($entity->getMerchant());
$reductionCatalog->setStatus($editForm->get('activeReductionCatalog')->getData());
$reductionCatalog->setProductFamily($entity);
$this->em->persist($reductionCatalog);
}
}
}

protected function processPrice($entity){
if($entity->getBehaviorPrice()=='by-piece'){
$entity->setPriceByRefUnit(null);
$entity->setBuyingPriceByRefUnit(null);
}else if($entity->getBehaviorPrice()=='by-reference-unit') {
$entity->setPrice(null);
$entity->setBuyingPrice(null);
}
}

protected function processProducts($entity)
{
$repo = $this->em->getRepository(UnitInterface::class);
//si il existe un et un seul produit pour ce product family n'ajoute rien supprime rien
if (count($entity->getProducts()) == 0) {
$product = new Product();
$product->setProductFamily($entity);
$this->em->persist($product);

$entity->addProduct($product);
} else {

foreach ($entity->getProducts() as $i=>$product) {

$product->setProductFamily($entity);
$this->em->persist($product);
$entity->addProduct($product);

// die('ncici');
}
}

@@ -260,6 +273,7 @@ class ProductFamilyController extends AdminController
$sortableProductsField[$product->getPosition()] = $k;
}
ksort($sortableProductsField);

$editForm->handleRequest($this->request);
if ($editForm->isSubmitted() && $editForm->isValid()) {


+ 1
- 1
ShopBundle/Controller/Frontend/CartController.php Ver arquivo

@@ -47,7 +47,7 @@ class CartController extends BaseController
foreach($data as $orderProduct) {
if($orderProduct instanceof OrderProductInterface) {
$this->orderUtils->addOrderProduct($orderShop, $orderProduct) ;
if($orderProduct->getQuantity() > 0) {
if($orderProduct->getQuantityorder() > 0) {
$this->orderProducts[] = $orderProduct ;
}
}

+ 4
- 7
ShopBundle/Form/ProductType.php Ver arquivo

@@ -82,8 +82,7 @@ class ProductType extends AbstractType

$builder->add('buyingPriceByRefUnit', NumberType::class, array(
'label' => 'Prix d\'achat',
'required'=>false,
'mapped' => false
'required'=>false
));

$builder->add('buyingPriceByRefUnitWithTax', NumberType::class, array(
@@ -98,8 +97,7 @@ class ProductType extends AbstractType
));

$builder->add('priceByRefUnit', NumberType::class, array(
'required'=>false,
'mapped' => false
'required'=>false
));

$builder->add('priceByRefUnitWithTax', NumberType::class, array(
@@ -117,9 +115,8 @@ class ProductType extends AbstractType
'required' => false,
));

$builder->add('propertyExpirationDate', DateType::class, array(
'required' => false,
'widget'=> 'single_text'
$builder->add('propertyExpirationDate', TextType::class, array(
'required' => false
));

$builder->add('position', HiddenType::class);

+ 96
- 12
ShopBundle/Form/ReductionCatalogType.php Ver arquivo

@@ -2,7 +2,13 @@

namespace Lc\ShopBundle\Form;

use App\Entity\Supplier;
use Lc\ShopBundle\Context\GroupUserInterface;
use Lc\ShopBundle\Context\ProductCategoryInterface;
use Lc\ShopBundle\Context\ProductFamilyInterface;
use Lc\ShopBundle\Context\ReductionCatalogInterface;
use Lc\ShopBundle\Context\UserInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
@@ -25,34 +31,112 @@ class ReductionCatalogType extends AbstractType

public function buildForm(FormBuilderInterface $builder, array $options)
{

$userClass = $this->em->getClassMetadata(UserInterface::class);
$groupUserClass = $this->em->getClassMetadata(GroupUserInterface::class);
$supplierClass = Supplier::class;
$productFamilyClass = $this->em->getClassMetadata(ProductFamilyInterface::class);
$productCategoryClass = $this->em->getClassMetadata(ProductCategoryInterface::class);


$builder
->add('title', TextType::class, ['label' => 'Titre'])
->add('title', TextType::class, [
'label' => 'Titre',
'required' => false,
])
->add('behaviorTaxRate', ChoiceType::class, [
'required'=> true,
'required' => false,
'choices' => [
'field.default.taxIncluded'=> 'tax-included',
'field.default.taxExcluded'=> 'tax-excluded'
'field.default.taxIncluded' => 'tax-included',
'field.default.taxExcluded' => 'tax-excluded'
]
])
->add('unit', ChoiceType::class, [
'required'=> true,
'required' => false,
'choices' => [
'field.default.percent'=> 'percent',
'field.default.amount'=> 'amount'
'field.default.percent' => 'percent',
'field.default.amount' => 'amount'
]
])
->add('value', NumberType::class, [
'required' => false
])
->add('permanent', CheckboxType::class, array(
'required'=>false
))
->add('dateStart', DateTimeType::class,
['widget' => 'single_text',
'required'=>false,
])
->add('dateEnd', DateTimeType::class, [
'widget' => 'single_text',
'required'=>false,
])
->add('usersActive', CheckboxType::class, array(
'label' => 'field.ReductionCatalog.usersActive',
'mapped' => false,
'required'=>false,
'attr' => ['class' => 'big']
))
->add('users', EntityType::class, array(
'class' => $userClass->name,
'required'=>false,
'multiple'=>true
))
->add('groupUsersActive', CheckboxType::class, array(
'label' => 'field.ReductionCatalog.groupUsersActive',
'mapped' => false,
'required'=>false,
'attr' => ['class' => 'big']
))
->add('groupUsers', EntityType::class, array(
'class' => $groupUserClass->name,
'required'=>false,
'multiple'=>true

));
/* ->add('productFamiliesActive', CheckboxType::class, array(
'label' => 'field.ReductionCatalog.productFamiliesActive',
'mapped' => false,
'required'=>false,
'attr' => ['class' => 'big']
))
->add('productFamilies', EntityType::class, array(
'class' => $productFamilyClass->name,
'required'=>false,
'multiple'=>true
))
->add('productCategoriesActive', CheckboxType::class, array(
'label' => 'field.ReductionCatalog.productCategoriesActive',
'mapped' => false,
'required'=>false,
'attr' => ['class' => 'big']
))
->add('productCategories', EntityType::class, array(
'class' => $productCategoryClass->name,
'required'=>false,
'multiple'=>true
))
->add('suppliersActive', CheckboxType::class, array(
'label' => 'field.ReductionCatalog.suppliersActive',
'mapped' => false,
'required'=>false,
'attr' => ['class' => 'big']
))
->add('suppliers', EntityType::class, array(
'class' => $supplierClass,
'required'=>false,
'multiple'=>true
));*/

->add('value', NumberType::class, ['required' => true])
->add('permanent', CheckboxType::class, ['required' => true])
->add('dateStart', DateTimeType::class, ['widget' => 'single_text'])
->add('dateEnd', DateTimeType::class, ['widget' => 'single_text']);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'label' => false,
'data_class' => $this->em->getClassMetadata(ReductionCatalogInterface::class)->getName()
//'data_class' => $this->em->getClassMetadata(ReductionCatalogInterface::class)->getName(),
'translation_domain'=> 'lcshop'
]);
}
}

+ 1
- 1
ShopBundle/Model/OrderAmountMin.php Ver arquivo

@@ -9,7 +9,7 @@ trait OrderAmountMin
/**
* @ORM\Column(type="float")
*/
private $orderAmountMin;
protected $orderAmountMin;

public function getOrderAmountMin(): ?float
{

+ 21
- 1
ShopBundle/Model/OrderProduct.php Ver arquivo

@@ -2,6 +2,7 @@

namespace Lc\ShopBundle\Model;

use App\Entity\OrderProductReductionCatalog;
use Doctrine\ORM\Mapping as ORM;
use Lc\ShopBundle\Context\PriceInterface;

@@ -38,6 +39,11 @@ abstract class OrderProduct implements PriceInterface
*/
protected $title;

/**
* @ORM\OneToOne(targetEntity="Lc\ShopBundle\Context\OrderProductReductionCatalogInterface", cascade={"persist", "remove"})
*/
protected $orderProductReductionCatalog;

public function __toString()
{
if($this->getTitle()) {
@@ -52,7 +58,8 @@ abstract class OrderProduct implements PriceInterface
{
$product = $this->getProduct() ;
$productFamily = $product->getProductFamily() ;
$titleProduct = $product->getTitleInherited() ;

$titleProduct = $product->getTitle() ;
$titleProductFamily = $productFamily->getTitle() ;

if(strlen($titleProduct) > 0 && strlen($titleProductFamily) > 0) {
@@ -158,4 +165,17 @@ abstract class OrderProduct implements PriceInterface

return $this;
}

public function getOrderProductReductionCatalog(): ?OrderProductReductionCatalog
{
return $this->orderProductReductionCatalog;
}

public function setOrderProductReductionCatalog(?OrderProductReductionCatalog $orderProductReductionCatalog): self
{
$this->orderProductReductionCatalog = $orderProductReductionCatalog;

return $this;
}

}

+ 31
- 0
ShopBundle/Model/OrderProductReductionCatalog.php Ver arquivo

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

namespace Lc\ShopBundle\Model;

use Doctrine\ORM\Mapping as ORM;
use Lc\ShopBundle\Context\OrderProductReductionCatalogInterface;

/**
* @ORM\MappedSuperclass()
*/
abstract class OrderProductReductionCatalog implements OrderProductReductionCatalogInterface
{
use ReductionTrait ;

/**
* @ORM\Column(type="string", length=255)
*/
protected $title;

public function getTitle(): ?string
{
return $this->title;
}

public function setTitle(string $title): self
{
$this->title = $title;

return $this;
}
}

+ 3
- 103
ShopBundle/Model/PriceTrait.php Ver arquivo

@@ -24,11 +24,6 @@ trait PriceTrait
*/
protected $taxRate;

public function getPrice(): ?float
{
return $this->price;
}

public function getPriceInherited(): ?float
{
return $this->getPrice() ;
@@ -44,83 +39,13 @@ trait PriceTrait
return $this->getTaxRate() ;
}

public function getPriceWithTax(): ?float
{
return $this->calculatePriceWithTax($this->getPriceInherited(), $this->getTaxRateInherited()->getValue()) ;
}

public function getPriceByUnitRef(): ?float
{
return $this->calculatePriceByUnitRef($this->getPriceInherited()) ;
}

public function getPriceByUnitRefWithTax(): ?float
{
return $this->calculatePriceByUnitRef($this->getPriceWithTax()) ;
}

public function getTheReductionCatalog()
{
$reductionCatalog = false;

if($this instanceof ProductFamily) {
$reductionCatalog = $this->getReductionCatalog() ;
}
if($this instanceof Product) {
$reductionCatalog = $this->getProductFamily()->getReductionCatalog() ;
}

return $reductionCatalog ;
}

public function getPriceByUnitRefWithTaxAndReduction(): ?float
{
$reductionCatalog = $this->getTheReductionCatalog() ;

if (isset($reductionCatalog) && $reductionCatalog) {
return $this->calculatePriceByUnitRef($this->getPriceWithTaxAndReductionCatalog($reductionCatalog)) ;
}
else {
return $this->calculatePriceByUnitRef($this->getPriceWithTax());
}
}

public function getPriceWithTaxAndReduction(): ?float
{
$reductionCatalog = $this->getTheReductionCatalog() ;

if (isset($reductionCatalog) && $reductionCatalog) {
return $this->getPriceWithTaxAndReductionCatalog($reductionCatalog);
}
else {
return $this->getPriceWithTax();
}
}

public function getPriceWithTaxAndReductionCatalog(ReductionCatalogInterface $reductionCatalog): ?float
public function getPrice(): ?float
{

if ($reductionCatalog->getUnit() == 'percent') {
//Théoriquement que la réduction s'applique sur le prixHT ou le prixTTC le résultat est le même,j'ai laisser mon code au cas où ;)
return $this->calculatePriceWithReductionPercent($this->getPriceWithTax(), $reductionCatalog->getValue());
/*if ($reductionCatalog->getBehaviorTaxRate() == 'tax-excluded') {
$priceReductionHT = $this->calculatePriceWithReductionPercent($this->getPriceInherited(), $reductionCatalog->getValue());
return $this->calculatePriceWithTax($priceReductionHT, $this->getTaxRateInherited()->getValue());
} else if ($reductionCatalog->getBehaviorTaxRate() == 'tax-included') {

return $this->calculatePriceWithReductionPercent($this->getPriceWithTax(), $reductionCatalog->getValue());
}*/
}elseif ($reductionCatalog->getUnit() == 'amount') {
if ($reductionCatalog->getBehaviorTaxRate() == 'tax-excluded') {
$priceReductionHT = $this->calculatePriceWithReductionAmount($this->getPriceInherited(), $reductionCatalog->getValue());
return $this->calculatePriceWithTax($priceReductionHT, $this->getTaxRateInherited()->getValue());
}else if ($reductionCatalog->getBehaviorTaxRate() == 'tax-included') {
return $this->calculatePriceWithReductionAmount($this->getPriceWithTax(), $reductionCatalog->getValue());
}
}
return $this->price;
}

public function setPrice(float $price): self
public function setPrice(?float $price): self
{
$this->price = $price;

@@ -150,29 +75,4 @@ trait PriceTrait

return $this;
}

private function calculatePriceWithTax($priceWithoutTax, $taxRateValue): ?float
{
$price = floatval($priceWithoutTax) * ($taxRateValue / 100 + 1);
$price = round((($price * 100)) / 100, 2);
return $price;
}

public function calculatePriceWithReductionPercent($price, $percentValue): ?float
{
$price = floatval($price) * (1 - $percentValue / 100);
$price = round((($price * 100)) / 100, 2);
return $price;
}
public function calculatePriceWithReductionAmount($price, $amountValue): ?float
{
$price = floatval($price) - $amountValue;
$price = round((($price * 100)) / 100, 2);
return $price;
}

private function calculatePriceByUnitRef($price)
{
return ($price * $this->getUnitInherited()->getCoefficient()) / $this->getQuantityInherited() ;
}
}

+ 38
- 23
ShopBundle/Model/Product.php Ver arquivo

@@ -43,41 +43,61 @@ abstract class Product extends AbstractEntity implements SortableInterface, Prod

public function getPriceInherited()
{
if($this->price) {
return $this->price;
if($this->getPrice()) {
return $this->getPrice();
}
else {
return $this->productFamily->getPrice();
return $this->getProductFamily()->getPrice();
}
}

public function getPriceByRefUnitInherited()
{
if($this->getPriceByRefUnit()) {
return $this->getPriceByRefUnit();
}
else {
return $this->getProductFamily()->getPriceByRefUnit();
}
}

public function getBehaviorPriceInherited()
{
return $this->getProductFamily()->getBehaviorPrice() ;
}

public function getReductionCatalogInherited()
{
return $this->getProductFamily()->getReductionCatalog() ;
}

public function getUnitInherited()
{
if($this->unit) {
return $this->unit;
if($this->getUnit()) {
return $this->getUnit();
}
else{
return $this->productFamily->getUnit();
else {
return $this->getProductFamily()->getUnit();
}
}

public function getTitleInherited()
{
if($this->title){
return $this->title;
if($this->getTitle()){
return $this->getTitle();
}
else{
return $this->productFamily->getTitle();
return $this->getProductFamily()->getTitle();
}
}

public function getQuantityInherited()
{
if($this->quantity) {
return $this->quantity;
if($this->getQuantity()) {
return $this->getQuantity();
}
else{
return $this->productFamily->getQuantity();
return $this->getProductFamily()->getQuantity();
}
}

@@ -90,22 +110,17 @@ abstract class Product extends AbstractEntity implements SortableInterface, Prod

public function getAvailableQuantityInherited()
{
if($this->productFamily->getBehaviorCountStock()) {
return $this->availableQuantity;
if($this->getProductFamily()->getBehaviorCountStock()) {
return $this->getAvailableQuantity();
}
else{
return $this->productFamily->getAvailableQuantity();
else {
return $this->getProductFamily()->getAvailableQuantity();
}
}

public function getTaxRateInherited()
{
if($this->productFamily->getTaxRate()) {
return $this->productFamily->getTaxRate();
}
else{
return $this->productFamily->getMerchant()->getTaxRate()->getValue();
}
return $this->getProductFamily()->getTaxRateInherited();
}

public function getProductFamily(): ?ProductFamily

+ 11
- 39
ShopBundle/Model/ProductFamily.php Ver arquivo

@@ -66,7 +66,7 @@ abstract class ProductFamily extends AbstractDocumentEntity implements ProductPr
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $warningMessageType;
protected $warningMessageType;

/**
* @ORM\Column(type="text", nullable=true)
@@ -236,6 +236,11 @@ abstract class ProductFamily extends AbstractDocumentEntity implements ProductPr
return $this->reductionCatalog;
}

public function getReductionCatalogInherited(): ?ReductionCatalog
{
return $this->getReductionCatalog() ;
}

public function setReductionCatalog(?ReductionCatalog $reductionCatalog): self
{
$this->reductionCatalog = $reductionCatalog;
@@ -383,44 +388,6 @@ abstract class ProductFamily extends AbstractDocumentEntity implements ProductPr
return $this;
}




private function getCheapestOrMostExpensiveProduct($comparisonFunction, $returnSelfIfNotActiveProducts)
{
$products = $this->getProducts()->getValues();
if (count($products) > 0) {
usort($products, $comparisonFunction);
return $products[0];
}
if ($returnSelfIfNotActiveProducts) {
return $this;
} else {
return false;
}
}

public function getCheapestProduct()
{
return $this->getCheapestOrMostExpensiveProduct(function ($a, $b) {
return $a->getPriceInherited() > $b->getPriceInherited();
}, true);
}

public function getCheapestProductByUnitRef()
{
return $this->getCheapestOrMostExpensiveProduct(function ($a, $b) {
return $a->getPriceByUnitRef() > $b->getPriceByUnitRef();
}, false);
}

public function getMostExpensiveProductByUnitRef()
{
return $this->getCheapestOrMostExpensiveProduct(function ($a, $b) {
return $a->getPriceByUnitRef() < $b->getPriceByUnitRef();
}, false);
}

public function isPropertyNoveltyOnline(): ?bool
{
if ($this->getPropertyNoveltyExpirationDate()) {
@@ -585,6 +552,11 @@ abstract class ProductFamily extends AbstractDocumentEntity implements ProductPr
return $this->behaviorPrice;
}

public function getBehaviorPriceInherited()
{
return $this->getBehaviorPrice() ;
}

public function setBehaviorPrice(?string $behaviorPrice): self
{
$this->behaviorPrice = $behaviorPrice;

+ 8
- 3
ShopBundle/Model/ProductPropertyTrait.php Ver arquivo

@@ -28,7 +28,7 @@ trait ProductPropertyTrait
/**
* @ORM\Column(type="float", nullable=true)
*/
protected $quantity = 1; //par défaut valeur à 1
protected $quantity;

/**
* @ORM\Column(type="float", nullable=true)
@@ -75,6 +75,11 @@ trait ProductPropertyTrait
return $this->priceByRefUnit;
}

public function getPriceByRefUnitInherited(): ?float
{
return $this->getPriceByRefUnit();
}

public function setPriceByRefUnit(?float $priceByRefUnit): self
{
$this->priceByRefUnit = $priceByRefUnit;
@@ -124,12 +129,12 @@ trait ProductPropertyTrait
return $this;
}

public function getPropertyExpirationDate(): ?\DateTimeInterface
public function getPropertyExpirationDate(): ?string
{
return $this->propertyExpirationDate;
}

public function setPropertyExpirationDate(?\DateTimeInterface $propertyExpirationDate): self
public function setPropertyExpirationDate(?string $propertyExpirationDate): self
{
$this->propertyExpirationDate = $propertyExpirationDate;


+ 2
- 1
ShopBundle/Model/ReductionCart.php Ver arquivo

@@ -7,6 +7,7 @@ use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Lc\ShopBundle\Context\ReductionInterface;
use Lc\ShopBundle\Model\AbstractDocumentEntity;
use Lc\ShopBundle\Model\ReductionPropertyTrait;
use Lc\ShopBundle\Model\ReductionTrait;

/**
@@ -15,7 +16,7 @@ use Lc\ShopBundle\Model\ReductionTrait;
abstract class ReductionCart extends AbstractDocumentEntity
{
use ReductionTrait;
use ReductionPropertyTrait ;

/**
* @ORM\Column(type="boolean", nullable=true)

+ 18
- 5
ShopBundle/Model/ReductionCatalog.php Ver arquivo

@@ -15,8 +15,8 @@ use phpDocumentor\Reflection\Types\Integer;
*/
abstract class ReductionCatalog extends AbstractDocumentEntity implements ReductionCatalogInterface, FilterMerchantInterface
{

use ReductionTrait;
use ReductionPropertyTrait ;

/**
* @ORM\ManyToOne(targetEntity="Lc\ShopBundle\Context\MerchantInterface", inversedBy="productFamilies")
@@ -29,6 +29,11 @@ abstract class ReductionCatalog extends AbstractDocumentEntity implements Reduct
*/
protected $productFamilies;

/**
* @ORM\OneToOne(targetEntity="Lc\ShopBundle\Context\ProductFamilyInterface")
*/
protected $productFamily;

/**
* @ORM\ManyToMany(targetEntity="Lc\ShopBundle\Context\ProductCategoryInterface")
*/
@@ -44,10 +49,6 @@ abstract class ReductionCatalog extends AbstractDocumentEntity implements Reduct
*/
protected $users;

/*
* @ORM\Column(type="smallint")
*/
// protected $fromQuantity = 1;


public function __construct()
@@ -98,6 +99,18 @@ abstract class ReductionCatalog extends AbstractDocumentEntity implements Reduct
}


public function getProductFamily(): ?ProductFamily
{
return $this->productFamily;
}

public function setProductFamily(?ProductFamily $productFamily): self
{
$this->productFamily = $productFamily;

return $this;
}

/**
* @return Collection|GroupUser[]
*/

+ 61
- 0
ShopBundle/Model/ReductionPropertyTrait.php Ver arquivo

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

namespace Lc\ShopBundle\Model;

use Doctrine\ORM\Mapping as ORM;

trait ReductionPropertyTrait
{
/**
* @ORM\Column(type="datetime", nullable=true)
*/
protected $dateStart;

/**
* @ORM\Column(type="datetime", nullable=true)
*/
protected $dateEnd;

/**
* @ORM\Column(type="boolean")
*/
protected $permanent;


public function getDateStart(): ?\DateTimeInterface
{
return $this->dateStart;
}

public function setDateStart(?\DateTimeInterface $dateStart): self
{
$this->dateStart = $dateStart;

return $this;
}

public function getDateEnd(): ?\DateTimeInterface
{
return $this->dateEnd;
}

public function setDateEnd(?\DateTimeInterface $dateEnd): self
{
$this->dateEnd = $dateEnd;

return $this;
}

public function getPermanent(): ?bool
{
return $this->permanent;
}

public function setPermanent(bool $permanent): self
{
$this->permanent = $permanent;

return $this;
}

}

+ 0
- 55
ShopBundle/Model/ReductionTrait.php Ver arquivo

@@ -2,22 +2,10 @@

namespace Lc\ShopBundle\Model;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Lc\ShopBundle\Context\StatusInterface;

trait ReductionTrait
{
/**
* @ORM\Column(type="datetime", nullable=true)
*/
protected $dateStart;

/**
* @ORM\Column(type="datetime", nullable=true)
*/
protected $dateEnd;

/**
* @ORM\Column(type="float", nullable=true)
*/
@@ -33,36 +21,6 @@ trait ReductionTrait
*/
protected $behaviorTaxRate;

/**
* @ORM\Column(type="boolean")
*/
protected $permanent;



public function getDateStart(): ?\DateTimeInterface
{
return $this->dateStart;
}

public function setDateStart(?\DateTimeInterface $dateStart): self
{
$this->dateStart = $dateStart;

return $this;
}

public function getDateEnd(): ?\DateTimeInterface
{
return $this->dateEnd;
}

public function setDateEnd(?\DateTimeInterface $dateEnd): self
{
$this->dateEnd = $dateEnd;

return $this;
}

public function getValue(): ?float
{
@@ -99,17 +57,4 @@ trait ReductionTrait

return $this;
}

public function getPermanent(): ?bool
{
return $this->permanent;
}

public function setPermanent(bool $permanent): self
{
$this->permanent = $permanent;

return $this;
}

}

+ 14
- 0
ShopBundle/Repository/ProductFamilyRepository.php Ver arquivo

@@ -79,5 +79,19 @@ class ProductFamilyRepository extends BaseRepository implements DefaultRepositor
return $query->getQuery()->getResult() ;
}

public function findByTerms($terms, $maxResults = false)
{
$query = $this->findByMerchantQuery() ;
$query->andWhere('e.status = 1');
$query->andWhere('e.title LIKE :terms');
$query->setParameter(':terms', '%'.$terms.'%') ;

if($maxResults) {
$query->setMaxResults($maxResults) ;
}

return $query->getQuery()->getResult() ;
}


}

+ 6
- 1
ShopBundle/Resources/public/css/backend/custom.css Ver arquivo

@@ -120,6 +120,8 @@ table th .select2-container--default .select2-selection--single{padding:0.3rem 0

/* ProductFamily */

.field-unit-quantity{border-bottom: 2px dotted #eee; padding-bottom: 10px; margin-bottom: 20px;}

.new-productfamily #nav-params,
.edit-productfamily #nav-params {
margin-bottom: 30px ;
@@ -168,6 +170,7 @@ table th .select2-container--default .select2-selection--single{padding:0.3rem 0
.autoresize textarea{height: auto; min-height: 38px;}



/* ORDER */

.table-order-summary{width: 100%;}
@@ -179,7 +182,8 @@ table th .select2-container--default .select2-selection--single{padding:0.3rem 0
.product-form-modal{display: none;}
.product-form.modal .form-check-label{font-style: italic; color: #666; text-align: left;}
.products-collection-table .inherited{color: #888; font-style: italic; font-weight: initial;}
.products-collection-table td{}
.products-collection-table td{position: relative;}
.products-collection-table .btn-empty-field{position: absolute; right: 3px; font-size: 0.7rem; top: 5px; padding: 0px;}
#lc-product-family-edit .products-collection-table {table-layout:fixed;}
#lc-product-family-edit .products-collection-table tr{border-bottom: 1px solid #dee2e6;}
#lc-product-family-edit .products-collection-table th{font-size:13px; border-left: 1px solid #dee2e6; border-top: 1px solid #dee2e6; text-align: center;}
@@ -189,6 +193,7 @@ table th .select2-container--default .select2-selection--single{padding:0.3rem 0
#lc-product-family-edit .products-collection-table td:last-child{border-right: 1px solid #dee2e6;}
#lc-product-family-edit .btn-add-product {margin: 20px 0; float: right;}
#lc-product-family-edit .inherited {color: #888; font-style: italic; font-weight: initial;}
#lc-product-family-edit .products-collection-table td .value {min-width: 80%; margin: auto; min-height: 20px; cursor: pointer;}

/* DeliveryZone */


+ 13
- 1
ShopBundle/Resources/public/js/backend/script/default/utils.js Ver arquivo

@@ -49,7 +49,7 @@ function lcTaxPriceUpdate(priceType) {
* @returns {string}
*/
function getPrice(priceWithTax, taxRate) {
return parseFloat(parseFloat(priceWithTax) / ((taxRate/100) + 1)).toFixed(3);
return parseFloat(parseFloat(priceWithTax) / ((taxRate/100) + 1)).toFixed(4);
}

/**
@@ -63,6 +63,18 @@ function getPriceWithTax(priceWithoutTax, taxRate) {
return parseFloat(parseFloat(priceWithoutTax) * ((taxRate/100) + 1)).toFixed(2);
}


function formatNumber(number, toFixed){
if(number)return Number(number.replace(',', '.')).toFixed(toFixed);
else return null;
}
function formatNumberWithoutFixed(number){
if(typeof number == 'string')number = number.replace(',', '.');
if(number)return Number(number);
else return null;
}


/**
* Formate un prix en l'arrondissant et en ajoutant le sigle de la monnaie
*

+ 150
- 90
ShopBundle/Resources/public/js/backend/script/default/vuejs-mixins.js Ver arquivo

@@ -17,183 +17,225 @@ let mixinPrice = {

},
computed: {
taxRateValue: function () {
if (this.taxRate) {
return this.taxRatesList[this.taxRate]['value'];
} else if (this.taxRate == null || this.taxRate == "undefined") {
return this.taxRatesList['default']['value'];
} else {
log('ERREUR : pas de taxRate')
/*priceWithTaxAndReduction:function () {
if(this.productFamily.reductionActive){
log(this.productFamily.value);
}
},
supplierTaxRateValue: function () {
if (this.supplierTaxRate) {
return this.taxRatesList[this.supplierTaxRate]['value'];
} else if (this.supplierTaxRate == null || this.supplierTaxRate == "undefined") {
return this.taxRateValue;
} else {
log('ERREUR : pas de supplier taxRate')
}
},

}*/
},
mounted: function () {

},
methods: {
init: function () {
this.buyingPriceUpdated();
if (this.behaviorPriceValue == 'by-piece') {
this.initByPiece();
} else if (this.behaviorPriceValue == 'by-reference-unit') {
this.initByRefUnit();
}
},
initByPiece: function () {
this.priceUpdated();
this.unitUpdated();
this.buyingPriceUpdated();
},

priceUpdated: function () {
if(this.price) {
this.setPriceWithTax();
this.setMultiplyingFactor();
this.setPriceByRefUnit();
this.setPriceByRefUnitWithTax();
}
initByRefUnit: function () {
this.buyingPriceByRefUnitUpdated();
this.priceByRefUnitUpdated();
},


buyingPriceUpdated: function () {
if(this.buyingPrice) {
if (this.buyingPrice) {
this.buyingPrice = formatNumber(this.buyingPrice, 4)
this.setBuyingPriceWithTax();
this.setMultiplyingFactor();
//Mise à jour dans le panel price
if (this.priceValue == null) {
this.setPriceFromMultiplyingFactor();
this.priceUpdated();
} else {
this.setMultiplyingFactor();
}
this.setBuyingPriceByRefUnit();
this.setBuyingPriceByRefUnitWithTax();
}
},

unitUpdated: function () {
/*if(this.unit) {
buyingPriceByRefUnitUpdated: function () {
if (this.buyingPriceByRefUnit) {
this.buyingPriceByRefUnit = formatNumber(this.buyingPriceByRefUnit, 4)
this.setBuyingPriceByRefUnitWithTax();
if (this.priceByRefUnitValue == null) {
this.setPriceByRefUnitFromMultiplyingFactor();
this.priceByRefUnitUpdated();
} else {
this.setMultiplyingFactor();
}
this.setBuyingPriceFromBuyingPriceByRefUnit();
this.setBuyingPriceWithTax();
}
},


priceUpdated: function () {
if (this.price) {

this.price = formatNumber(this.price, 4)
this.setPriceWithTax();
this.setMultiplyingFactor();
this.setPriceByRefUnit();
this.setPriceByRefUnitWithTax();
//this.setBuyingPriceByRefUnit();
//this.setBuyingPriceByRefUnitWithTax();
}*/
}
},
quantityUpdated: function () {
/*if(this.quantity ) {
if(this.behaviorPriceValue == 'by-piece'){
this.setPriceByRefUnit();
this.setPriceByRefUnitWithTax();
*/
if(this.behaviorPriceValue == 'by-reference-unit'){
this.setPriceFromPriceByRefUnit();
this.setPriceWithTax();
//this.priceUpdated();
priceByRefUnitUpdated: function () {
if (this.priceByRefUnit) {
this.priceByRefUnit = formatNumber(this.priceByRefUnit, 4)
this.setPriceByRefUnitWithTax();
this.setMultiplyingFactor();
this.setPriceFromPriceByRefUnit();
this.setPriceWithTax();
}

// this.setBuyingPriceByRefUnit();
// this.setBuyingPriceByRefUnitWithTax();
},

//Toutes les fonctions ci-dessous ne font que mettre à jour les price et buyingPrice
buyingPriceWithTaxUpdated: function () {
this.buyingPriceWithTax = formatNumber(this.buyingPriceWithTax, 2)
this.setBuyingPriceFromBuyingPriceWithTax();
this.buyingPriceUpdated();
},
buyingPriceByRefUnitUpdated: function () {
this.setBuyingPriceFromBuyingPriceByRefUnit();
this.buyingPriceUpdated();
},
buyingPriceByRefUnitWithTaxUpdated: function () {
this.buyingPriceByRefUnitWithTax = formatNumber(this.buyingPriceByRefUnitWithTax, 2)

this.setBuyingPriceByRefUnitFromBuyingPriceByRefUnitWithTax();
this.buyingPriceByRefUnitUpdated();
},
multiplyingFactorUpdated: function () {
this.setPriceFromMultiplyingFactor();
this.priceUpdated();
},

priceWithTaxUpdated: function () {
this.priceWithTax = formatNumber(this.priceWithTax, 2);
this.setPriceFromPriceWithTax();
this.priceUpdated();
},
priceByRefUnitUpdated: function () {
this.setPriceFromPriceByRefUnit();
this.priceUpdated();
},

priceByRefUnitWithTaxUpdated: function () {
this.priceByRefUnitWithTax = formatNumber(this.priceByRefUnitWithTax, 2)
this.setPriceByRefUnitFromTax();
this.priceByRefUnitUpdated();
},


//SETTER
setBuyingPriceFromBuyingPriceByRefUnit:function(){
this.buyingPrice = parseFloat((this.buyingPriceByRefUnit * this.quantityValue) / this.unitCoefficient).toFixed(2);
unitUpdated: function () {
this.quantityUpdated();
},
quantityUpdated: function () {
this.quantity = formatNumberWithoutFixed(this.quantity)

if(this.quantity) {
if (this.behaviorPriceValue == 'by-piece') {
this.setBuyingPriceByRefUnit();
this.setBuyingPriceByRefUnitWithTax();
this.setPriceByRefUnit();
this.setPriceByRefUnitWithTax();
} else if (this.behaviorPriceValue == 'by-reference-unit') {
this.setPriceFromPriceByRefUnit();
this.setPriceWithTax();
this.setBuyingPriceFromBuyingPriceByRefUnit();
this.setBuyingPriceWithTax();
}
}
},
multiplyingFactorUpdated: function () {
this.multiplyingFactor = formatNumber(this.multiplyingFactor, 3)

if (this.behaviorPriceValue == 'by-piece') {
this.setPriceFromMultiplyingFactor();
this.setPriceWithTax();
} else if (this.behaviorPriceValue == 'by-reference-unit') {
this.setPriceByRefUnitFromMultiplyingFactor();
this.setPriceByRefUnitWithTax();
}
},
//NEW VERSION

setBuyingPriceFromBuyingPriceWithTax: function () {
if (this.buyingPriceWithTax) {
this.buyingPriceWithTax = parseFloat(this.buyingPriceWithTax.replace(',', '.')).toFixed(2);
this.buyingPrice = getPrice(this.buyingPriceWithTax, this.supplierTaxRateValue);
}
},
setBuyingPriceWithTax: function () {
if (this.buyingPrice) {
this.buyingPrice = parseFloat(this.buyingPrice.replace(',', '.')).toFixed(3);
this.buyingPriceWithTax = getPriceWithTax(this.buyingPrice, this.supplierTaxRateValue);
}
},

setPriceFromMultiplyingFactor: function () {
this.price = getPrice(this.buyingPriceValue * this.multiplyingFactor, this.taxRateValue);
},
setPriceWithTax() {
if (this.price) {
this.priceWithTax = getPriceWithTax(this.price, this.taxRateValue);
}
},

setPriceByRefUnitFromMultiplyingFactor: function () {
this.priceByRefUnit = getPrice(this.buyingPriceByRefUnitValue * this.multiplyingFactorValue, this.taxRateValue);
},

//SETTER
setBuyingPriceFromBuyingPriceByRefUnit: function () {
this.buyingPrice = parseFloat((this.buyingPriceByRefUnit * this.quantityValue) / this.unitCoefficient).toFixed(4);
},

setBuyingPriceByRefUnitFromBuyingPriceByRefUnitWithTax: function () {
if (this.buyingPriceByRefUnitWithTax) {
this.buyingPriceByRefUnitWithTax = parseFloat(this.buyingPriceByRefUnitWithTax.replace(',', '.')).toFixed(2);
this.buyingPriceByRefUnit = getPrice(this.buyingPriceByRefUnitWithTax, this.supplierTaxRateValue);
}
},
setBuyingPriceByRefUnit: function () {
if (this.unitCoefficient && this.quantityValue) {
this.buyingPriceByRefUnit = parseFloat((this.buyingPriceValue / this.quantityValue) * this.unitCoefficient).toFixed(2);
this.buyingPriceByRefUnit = parseFloat((this.buyingPriceValue / this.quantityValue) * this.unitCoefficient).toFixed(4);
}
},
setBuyingPriceByRefUnitWithTax: function () {
if (this.buyingPriceByRefUnit) {
this.buyingPriceByRefUnit = parseFloat(this.buyingPriceByRefUnit.replace(',', '.')).toFixed(3);
this.buyingPriceByRefUnitWithTax = getPriceWithTax(this.buyingPriceByRefUnit, this.supplierTaxRateValue);
}
},
setMultiplyingFactor: function () {
if (this.priceWithTax || this.buyingPrice) {
this.multiplyingFactor = parseFloat(this.priceWithTaxValue / this.buyingPriceValue).toFixed(3);
if (this.behaviorPriceValue == 'by-piece') {
if (this.priceWithTax || this.buyingPrice) {
this.multiplyingFactor = parseFloat(this.priceWithTaxValue / this.buyingPriceValue).toFixed(3);
}
} else if (this.behaviorPriceValue == 'by-reference-unit') {
if (this.priceByRefUnitWithTax || this.buyingPriceByRefUnit) {
this.multiplyingFactor = parseFloat(this.priceByRefUnitWithTaxValue / this.buyingPriceByRefUnitValue).toFixed(3);
}
}
},
setPriceByRefUnitFromTax: function () {
if (this.priceByRefUnitWithTax) {
this.priceByRefUnitWithTax = parseFloat(this.priceByRefUnitWithTax.replace(',', '.')).toFixed(2);
this.priceByRefUnit = getPrice(this.priceByRefUnitWithTax, this.taxRateValue);
}
},
setPriceByRefUnit: function () {
if (this.unitCoefficient && this.quantityValue) {
this.priceByRefUnit = parseFloat((this.priceValue / this.quantityValue) * this.unitCoefficient).toFixed(2);
this.priceByRefUnit = parseFloat((this.priceValue / this.quantityValue) * this.unitCoefficient).toFixed(4);
}
},
setPriceByRefUnitWithTax: function () {
if (this.unitCoefficient && this.quantityValue) {
this.priceByRefUnitWithTax = parseFloat((this.priceWithTaxValue / this.quantityValue) * this.unitCoefficient).toFixed(2);
setPriceByRefUnitWithTax() {
if (this.priceByRefUnit) {
this.priceByRefUnitWithTax = getPriceWithTax(this.priceByRefUnit, this.taxRateValue);
}
},

setPriceFromMultiplyingFactor: function () {
this.price = getPrice(this.buyingPriceValue * this.multiplyingFactor, this.taxRateValue);
},
setPriceFromPriceByRefUnit: function () {
this.price = parseFloat((this.priceByRefUnitValue * this.quantityValue) / this.unitCoefficient).toFixed(2);
this.price = parseFloat((this.priceByRefUnitValue * this.quantityValue) / this.unitCoefficient).toFixed(4);
},
setPriceFromPriceWithTax: function () {
if (typeof this.priceWithTax != "number") {
this.priceWithTax = parseFloat(this.priceWithTax.replace(',', '.'));
}
this.priceWithTax = this.priceWithTax.toFixed(2);
this.price = getPrice(this.priceWithTax, this.taxRateValue);
},
setPriceWithTax() {
if (this.price) {
this.price = parseFloat(this.price.replace(',', '.')).toFixed(3);
this.priceWithTax = getPriceWithTax(this.price, this.taxRateValue);
}
},
emptyPrice:function () {
this.price=null;
this.priceInherited = true;
}
},
watch: {}

@@ -280,4 +322,22 @@ let mixinTemplate = {
}
}
}
}
};


let mixinReduction = {
data() {
return Object.assign({
reductionActive: true,
reductionUnit:null,
reductionBehaviorTaxRate:null,
reductionValue:null,
reductionPermanent: true,
reductionUsersActive: false,
reductionGroupUsersActive: false,
reductionSuppliersActive: false,
reductionProductCategoriesActive: false,
reductionProductFamiliesActive:false
}, window.mixinReductionValues);
}
};

+ 140
- 63
ShopBundle/Resources/public/js/backend/script/productfamily/vuejs-product-family.js Ver arquivo

@@ -7,7 +7,7 @@ Vue.component('product-unit-price', {
props: ['template', 'keyForm'],
data() {
return Object.assign({
behaviorPrice:null,
behaviorPrice: 'by-piece',
activeProducts: false,
}, window.productUnitPriceValues);

@@ -19,12 +19,27 @@ Vue.component('product-unit-price', {
buyingPriceWithTaxValue: function () {
return this.buyingPriceWithTax;
},
buyingPriceByRefUnitValue:function(){
return this.buyingPriceByRefUnit;
},
buyingPriceByRefUnitWithTaxValue:function(){
return this.buyingPriceByRefUnitWithTax;
},
multiplyingFactorValue:function(){
return this.multiplyingFactor;
},
priceWithTaxValue: function () {
return this.priceWithTax;
},
priceValue: function () {
return this.price;
},
priceByRefUnitValue:function(){
return this.priceByRefUnit;
},
priceByRefUnitWithTaxValue:function(){
return this.priceByRefUnitWithTax;
},
quantityValue: function () {
return this.quantity;
},
@@ -33,7 +48,25 @@ Vue.component('product-unit-price', {
},
behaviorPriceValue:function(){
return this.behaviorPrice;
}
},
taxRateValue: function () {
if (this.taxRate) {
return this.taxRatesList[this.taxRate]['value'];
} else if (this.taxRate == null || this.taxRate == "undefined") {
return this.taxRatesList['default']['value'];
} else {
log('ERREUR : pas de taxRate')
}
},
supplierTaxRateValue: function () {
if (this.supplierTaxRate) {
return this.taxRatesList[this.supplierTaxRate]['value'];
} else if (this.supplierTaxRate == null || this.supplierTaxRate == "undefined") {
return this.taxRateValue;
} else {
log('ERREUR : pas de supplier taxRate')
}
},

},
mounted: function () {
@@ -42,12 +75,26 @@ Vue.component('product-unit-price', {
watch: {
taxRate: function () {
this.setBuyingPriceWithTax();
this.setBuyingPriceByRefUnitWithTax();
this.setPriceWithTax();
this.setPriceByRefUnitWithTax();
this.setMultiplyingFactor();
this.setPriceByUnitRefWithTax();
this.$parent.updateChild();
},
supplierTaxRate: function () {
this.setBuyingPriceWithTax();
this.setBuyingPriceByRefUnitWithTax();
},
differentSupplierTaxRate:function(){
this.supplierTaxRate = null;
},
activeProducts:function () {
this.$parent.updateActiveProducts();
},
behaviorPrice:function () {
if(this.behaviorPrice == 'by-reference-unit'){
this.quantity = 1;
}
}
}
});
@@ -56,11 +103,11 @@ Vue.component('product-form', {
mixins: [mixinUnit, mixinPrice, mixinTemplate],
props: ['template', 'keyForm', 'productFamily'],
computed: {
taxRate: function () {
return this.productFamily.taxRate;
taxRateValue: function () {
return this.productFamily.taxRateValue;
},
supplierTaxRate: function () {
return this.productFamily.supplierTaxRate;
supplierTaxRateValue: function () {
return this.productFamily.supplierTaxRateValue;
},
buyingPriceValue: function () {
if (this.buyingPrice) return this.buyingPrice;
@@ -70,6 +117,18 @@ Vue.component('product-form', {
if (this.buyingPriceWithTax) return this.buyingPriceWithTax;
else return this.productFamily.buyingPriceWithTax;
},
buyingPriceByRefUnitValue:function(){
if (this.buyingPriceByRefUnit) return this.buyingPriceByRefUnit;
else return this.productFamily.buyingPriceByRefUnit;
},
buyingPriceByRefUnitWithTaxValue:function(){
if (this.buyingPriceByRefUnitWithTax) return this.buyingPriceByRefUnitWithTax;
else return this.productFamily.buyingPriceByRefUnitWithTax;
},
multiplyingFactorValue:function(){
if (this.multiplyingFactor) return this.multiplyingFactor;
else return this.productFamily.multiplyingFactor;
},
priceWithTaxValue: function () {
if (this.priceWithTax) return this.priceWithTax;
else return this.productFamily.priceWithTax;
@@ -94,12 +153,15 @@ Vue.component('product-form', {
if (this.unit) return this.unit;
else return this.productFamily.unit;
},
propertyExpirationDateFormated: function () {
if (this.propertyExpirationDate) return getDateFormatted(this.propertyExpirationDate, '-')
else return getDateFormatted(this.productFamily.propertyExpirationDate, '-')
propertyExpirationDateValue: function () {
if (this.propertyExpirationDate) return this.propertyExpirationDate;
else return this.productFamily.propertyExpirationDate;
},
behaviorPriceValue:function(){
return this.productFamily.behaviorPrice;
},
finalPriceWithTax:function () {
return getPriceWithTax(parseFloat((this.priceByRefUnitValue * this.quantityValue) / this.unitCoefficient).toFixed(4), this.taxRateValue);
}
},
data() {
@@ -114,7 +176,6 @@ Vue.component('product-form', {
availableQuantityDefault: null,
availableQuantity: null,
propertyExpirationDate: null,

titleInherited: false,
priceInherited: false,
priceWithTaxInherited: false,
@@ -137,12 +198,12 @@ Vue.component('product-form', {
mounted: function () {
//INIT VAR
updateSortableProducts();
this.setUnitSelect2();
//this.setUnitSelect2();


//METHOD
this.updateProductForm();
this.updateProductView();
//this.updateProductForm();
//this.updateProductView();
},
methods: {
setUnitSelect2:function(){
@@ -154,30 +215,11 @@ Vue.component('product-form', {
availableQuantityUpdated:function(){},
availableQuantityDefaultUpdated:function(){},
propertyExpirationDateUpdated:function(){},
updateLine: function(){
this.init();
},

updateProductForm: function () {
this.init();
},

updateProductView: function () {


/*if (this.unitValue == 'piece') {
$('.priceByRefUnit').hide();
} else {
$('.priceByRefUnit').show();
}
if (this.productFamily.behaviorCountStock == 'by-product-family' || this.productFamily.behaviorCountStock == 'by-quantity') {
$('.products-collection-table').find('.stock').hide();
} else {
$('.products-collection-table').find('.stock').show();
$('#product-item-' + this.keyForm).find('.stock').html(this.availableQuantity + ' / ' + this.unitReference);
}*/
},
saveProductForm: function () {
this.updateProductView();
$('#form-product-modal-' + this.keyForm).modal('hide');
},
deleteProductForm: function () {
@@ -192,31 +234,64 @@ Vue.component('product-form', {

appProductFamily = new Vue({
el: '#lc-product-family-edit',
mixins: [mixinReduction],
delimiters: ['${', '}'],
computed: {
productFamily: function () {
return {
'title': this.title,
'behaviorCountStock': this.behaviorCountStock,
'behaviorPrice': this.$refs.productUnitPrice.behaviorPrice,
'unit': this.$refs.productUnitPrice.unit,
'unitWording': this.$refs.productUnitPrice.unitWording,
'quantity': this.$refs.productUnitPrice.quantity,
'price': this.$refs.productUnitPrice.price,
'priceWithTax': this.$refs.productUnitPrice.priceWithTax,
'buyingPrice': this.$refs.productUnitPrice.buyingPrice,
'buyingPriceWithTax': this.$refs.productUnitPrice.buyingPriceWithTax,
'buyingPriceByRefUnit': this.$refs.productUnitPrice.buyingPriceByRefUnit,
'buyingPriceByRefUnitWithTax': this.$refs.productUnitPrice.buyingPriceByRefUnitWithTax,
'priceByRefUnit': this.$refs.productUnitPrice.priceByRefUnit,
'priceByRefUnitWithTax': this.$refs.productUnitPrice.priceByRefUnitWithTax,
'taxRate': this.$refs.productUnitPrice.taxRate,
'supplierTaxRate': this.$refs.productUnitPrice.supplierTaxRate,
'multiplyingFactor': this.$refs.productUnitPrice.multiplyingFactor,
'taxRateValue': this.$refs.productUnitPrice.taxRateValue,
'propertyExpirationDate': this.propertyExpirationDate,
'behaviorExpirationDate': this.behaviorExpirationDate
};
if(this.isMounted) {
return {
'title': this.title,
'behaviorCountStock': this.behaviorCountStock,
'behaviorPrice': this.$refs.productUnitPrice.behaviorPrice,
'unit': this.$refs.productUnitPrice.unit, //this.getProductUnitPrice('unit'),
'unitWording': this.$refs.productUnitPrice.unitWording,
'quantity': this.$refs.productUnitPrice.quantity,
'price': this.$refs.productUnitPrice.price,
'priceWithTax': this.$refs.productUnitPrice.priceWithTax,
'buyingPrice': this.$refs.productUnitPrice.buyingPrice,
'buyingPriceWithTax': this.$refs.productUnitPrice.buyingPriceWithTax,
'buyingPriceByRefUnit': this.$refs.productUnitPrice.buyingPriceByRefUnit,
'buyingPriceByRefUnitWithTax': this.$refs.productUnitPrice.buyingPriceByRefUnitWithTax,
'priceByRefUnit': this.$refs.productUnitPrice.priceByRefUnit,
'priceByRefUnitWithTax': this.$refs.productUnitPrice.priceByRefUnitWithTax,
'taxRateValue': this.$refs.productUnitPrice.taxRateValue,
'supplierTaxRateValue': this.$refs.productUnitPrice.supplierTaxRateValue,

/*'taxRate': this.$refs.productUnitPrice.taxRate,
'supplierTaxRate': this.$refs.productUnitPrice.supplierTaxRate,
*/
'multiplyingFactor': this.$refs.productUnitPrice.multiplyingFactor,
'propertyExpirationDate': this.propertyExpirationDate,
'behaviorExpirationDate': this.behaviorExpirationDate,
'reductionActive': this.reductionActive,
'reductionUnit': this.reductionUnit,
'reductionValue': this.reductionValue,
'reductionBehaviorTaxRate': this.reductionBehaviorTaxRate
};
}else{
return {
'title': null,
'behaviorCountStock': null,
'behaviorPrice': null,
'unit': null,
'unitWording': null,
'quantity': null,
'price': null,
'priceWithTax':null,
'buyingPrice': null,
'buyingPriceWithTax': null,
'buyingPriceByRefUnit': null,
'buyingPriceByRefUnitWithTax': null,
'priceByRefUnit': null,
'priceByRefUnitWithTax': null,
'taxRate': null,
'supplierTaxRate': null,
'multiplyingFactor': null,
'taxRateValue': null,
'propertyExpirationDate': this.propertyExpirationDate,
'behaviorExpirationDate': this.behaviorExpirationDate
};
}
},
unitReference: function () {
this.getUnitReference();
@@ -226,6 +301,7 @@ appProductFamily = new Vue({

return Object.assign(
{
isMounted:false,
indexFormProduct: 0,
title: null,
isNovelty: null,
@@ -237,6 +313,7 @@ appProductFamily = new Vue({
propertyAllergens: null,
propertyOrganicLabelActive: false,
propertyNoveltyExpirationDateActive: false,
activeProducts:false,

formProductArray: [],
currentSection: 'general',
@@ -261,7 +338,10 @@ appProductFamily = new Vue({
name: 'property',
nameDisplay: 'Caractéristiques'
},

{
name: 'reduction',
nameDisplay: 'Réduction'
},
{
name: 'note',
nameDisplay: 'Note interne'
@@ -270,12 +350,12 @@ appProductFamily = new Vue({
}, window.appProductFamilyValues);
},
mounted: function () {
this.isMounted = true;
$(".vuejs-checkbox-switch input").each(function () {
setBootstrapSwitch($(this));
});
},
methods: {

changeSection: function (section) {
this.updateChild();
this.currentSection = section.name;
@@ -298,7 +378,6 @@ appProductFamily = new Vue({
if (typeof this.$refs.productForm !== 'undefined') {
for (i = 0; i < this.$refs.productForm.length; i++) {
this.$refs.productForm[i].updateProductForm();
this.$refs.productForm[i].updateProductView();
}
}
},
@@ -307,10 +386,8 @@ appProductFamily = new Vue({
return this.$refs.productUnitPrice.unitReference;
}
},
isProductsActice: function () {
if (typeof this.$refs.productUnitPrice !== 'undefined') {
return this.$refs.productUnitPrice.activeProducts;
}
updateActiveProducts: function () {
this.activeProducts = this.$refs.productUnitPrice.activeProducts;
},
getBehaviorPrice: function () {
if (typeof this.$refs.productUnitPrice !== 'undefined') {

+ 1
- 24
ShopBundle/Resources/public/js/backend/script/reductioncatalog/vuejs-reduction-catalog.js Ver arquivo

@@ -3,28 +3,5 @@
appProductFamily = new Vue({
el: '#lc-reduction-catalog-edit',
delimiters: ['${', '}'],
computed: {
},
data() {

return Object.assign(
{
permanent: true,
usersActive: false,
groupUsersActive: false,
suppliersActive: false,
productCategoriesActive: false,
productFamiliesActive:false

}, window.appReductionCatalogValues);
},
mounted: function () {

},
methods: {

},
watch: {

}
mixins: [mixinReduction]
});

+ 10
- 3
ShopBundle/Resources/translations/lcshop.fr.yaml Ver arquivo

@@ -24,7 +24,7 @@ group:
addresses: Livraisons & facturation
main: Général
products: Déclinaisons
price: Prix
priceAndUnit: Tarifs / Unités / Quantités
categories: Catégories
unit: Unité & quantité
tax: TVA
@@ -35,6 +35,7 @@ group:
propertySecondary: Caractéristiques secondaires
note: Note interne
parameters: Paramètres
initReduction: Réduction
ReductionCatalog:
info: Informations principal
conditions: Condictions d'application
@@ -130,6 +131,8 @@ field:
subscribeNewsletter: S'inscrire à la newsletter
send: Envoyer
isSent: Envoyée
behaviorTaxRate: Avec ou sans TVA
behaviorTaxRateHelp: Appliquer la réduction sur le prix HT ou le prix TTC
PointSale:
code: Code
codeHelp: Code utilisé pour retrouver l'ambassade dans le tunnel de commande (Non sensible à la casse)
@@ -142,7 +145,9 @@ field:
productsTypeHelp: 'Volume / Pods / Varieté / Parfum ...'
buyingPrice: Prix d'achat
multiplyingFactor: Coefficiant multiplicateur
multiplyingFactorHelp: La mise à jour de ce champ modifiera le prix de vente HT et TTC
priceByRefUnit: Prix de vente / unité de référence
buyingPriceByRefUnit: Prix d'achat / unité de référence
availableQuantity: Quantité disponible
availableQuantityDefault: Quantité disponible par défaut
quantity: Quantité
@@ -177,11 +182,10 @@ field:
behaviorAddToCartOptions:
simple: Simple
multiple: Multiple
activeReductionCatalog: Appliquer une réduction sur ce produit
ReductionCatalog:
fromQuantity: À partir de la quantité
fromQuantityHelp: Par défaut une réduction est apliqué à partir de 1
behaviorTaxRate: Avec ou sans TVA
behaviorTaxRateHelp: Appliquer la réduction sur le prix HT ou le prix TTC
unit: Unité
value: Montant ou valeur
permanent: Réduction permanante
@@ -201,6 +205,9 @@ field:
productFamiliesActive: Filtrer sur les produits
productFamilies: Appliquer aux produits

Address:
city: Commune

action:
new: Créer %entity_label%
switchMerchant: Votre hub

+ 128
- 3
ShopBundle/Resources/views/backend/default/block/macros.html.twig Ver arquivo

@@ -23,8 +23,8 @@

{% if fieldDisplay == false %}{% set fieldDisplay = fieldName %}{% endif %}

<td {{ attr|raw }} colspan="{{ colspan }}" class="{{ fieldName }}" v-on:click="{{ fieldName }}Inherited = true">
<div v-show="{{ fieldName }}Inherited == false">
<td {{ attr|raw }} colspan="{{ colspan }}" class="{{ fieldName }}">
<div class="value" v-show="{{ fieldName }}Inherited == false" v-on:click="{{ fieldName }}Inherited = true">
<div v-if="{{ fieldName }}">
{% verbatim %}{{ {% endverbatim %}{{ fieldDisplay }} {% verbatim %}}}{% endverbatim %}{{ displaySuffix }}
</div>
@@ -35,6 +35,8 @@
<div v-show="{{ fieldName }}Inherited == true">
{{ form_widget(field, {'attr' : {'v-model' : fieldName , 'v-on:focusout': fieldName~'Inherited = false', '@change' : fieldName~'Updated'}}) }}
</div>
<button v-show="{{ fieldName }}" v-on:click="{{ fieldName }} = null; {{ fieldName }}Inherited = false; "
class="btn btn-empty-field" type="button"><i class="fa fa-undo"></i></button>
</td>
{% endmacro %}

@@ -70,4 +72,127 @@
</div>
</div>

{% endmacro %}
{% endmacro %}

{% macro reductionCatalogForm(form) %}
{{ _self.startCard(6, 'ReductionCatalog.info') }}
<div class="col-12">
{{ form_row(form.title) }}
</div>
{# <div class="col-12">
{{ form_row(form.fromQuantity) }}
</div>
#}
<div class="col-12">
{{ form_row(form.behaviorTaxRate, {"attr" : {":required": "reductionActive", 'v-model' : 'reductionBehaviorTaxRate'}}) }}
</div>

<div class="col-12">
{{ form_row(form.unit, {"attr" : {":required": "reductionActive", 'v-model' : 'reductionUnit'}}) }}
</div>
<div class="col-12">
{{ form_row(form.value, {"attr" : {":required": "reductionActive", 'v-model' : 'reductionValue'}}) }}
</div>



{{ _self.endCard() }}


{{ _self.startCard(6, 'ReductionCatalog.conditions','success') }}
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.permanent, {"attr" : {'v-model' : 'reductionPermanent' } }) }}
</div>
<div class="input-group" v-show="reductionPermanent == false">
<div class="input-group-prepend">
<span class="input-group-text"><i class="far fa-clock"></i></span>
</div>
<input type="text" class="form-control float-right date-time-range">
<div class="hidden date-time-range-fields" style="display: none;">
{{ form_widget(form.dateStart, {"attr" : {'class' : 'date-start'}}) }}
{{ form_widget(form.dateEnd, {"attr" : {'class' : 'date-end'}}) }}
</div>
</div>

</div>
</div>
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.usersActive, {"attr" : {'v-model' : 'reductionUsersActive' } }) }}
</div>
<div class="form-widget" v-show="reductionUsersActive == true">
{{ form_widget(form.users) }}
</div>
</div>
</div>
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.groupUsersActive, {"attr" : {'v-model' : 'reductionGroupUsersActive' } }) }}
</div>
<div class="form-widget" v-show="reductionGroupUsersActive == true">
{{ form_widget(form.groupUsers) }}
</div>
</div>

</div>
{% if form.suppliers is defined %}
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.suppliersActive, {"attr" : {'v-model' : 'reductionSuppliersActive' } }) }}
</div>
<div class="form-widget" v-show="reductionSuppliersActive == true">
{{ form_widget(form.suppliers) }}
</div>
</div>
</div>
{% endif %}
{% if form.productCategories is defined %}
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.productCategoriesActive, {"attr" : {'v-model' : 'reductionProductCategoriesActive' } }) }}
</div>
<div class="form-widget" v-show="reductionProductCategoriesActive == true">
{{ form_widget(form.productCategories) }}
</div>
</div>
</div>
{% endif %}
{% if form.productFamilies is defined %}
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.productFamiliesActive, {"attr" : {'v-model' : 'reductionProductFamiliesActive' } }) }}
</div>
<div class="form-widget" v-show="reductionProductFamiliesActive == true">
{{ form_widget(form.productFamilies) }}
</div>
</div>
</div>
{% endif %}

{{ _self.endCard() }}

{% endmacro %}

{% macro reductionCatalogFormValues(formValues, isProductFamilyForm= false) %}
<script>
window.mixinReductionValues = {
{% if formValues.status == false and isProductFamilyForm %}reductionActive: false,{% endif %}
{% if formValues.permanent is not null and formValues.permanent == false %}reductionPermanent: false,{% endif %}
{% if formValues.behaviorTaxRate %}reductionBehaviorTaxRate: '{{ formValues.behaviorTaxRate }}',{% endif %}
{% if formValues.value %}reductionValue: parseFloat({{ formValues.value }}),{% endif %}
{% if formValues.unit %}reductionUnit: "{{ formValues.unit }}",{% endif %}
{% if formValues.users is not empty %}reductionUsersActive: true,{% endif %}
{% if formValues.groupUsers is not empty %}reductionGroupUsersActive: true,{% endif %}
{% if formValues.productFamilies is not empty %}reductionProductFamiliesActive: true,{% endif %}
{% if formValues.productCategories is not empty %}reductionProductCategoriesActive: true,{% endif %}
{% if formValues.suppliers is not empty %}reductionSuppliersActive: true,{% endif %}
}
</script>
{% endmacro %}

+ 1
- 0
ShopBundle/Resources/views/backend/default/list-fields/field_price.html.twig Ver arquivo

@@ -0,0 +1 @@
{{ priceUtils.getPriceWithTax(item) }}

+ 13
- 0
ShopBundle/Resources/views/backend/productfamily/edit.html.twig Ver arquivo

@@ -4,6 +4,19 @@
{% include '@LcShop/backend/productfamily/form.html.twig' %}
{% endblock entity_form %}


{% block head_stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="{{ asset('bundles/lcshop/css/backend/adminlte/plugins/daterange/daterangepicker.css') }}">
{% endblock %}

{% block plugin_javascript %}
{{ parent() }}

<script src="{{ asset('bundles/lcshop/js/backend/plugin/daterange/moment.min.js')}}"></script>
<script src="{{ asset('bundles/lcshop/js/backend/plugin/daterange/daterangepicker.js')}}"></script>
{% endblock %}

{% block script_javascript %}
{{ parent() }}
{% include '@LcShop/backend/default/block/script-vuejs.html.twig' %}

+ 12
- 2
ShopBundle/Resources/views/backend/productfamily/form.html.twig Ver arquivo

@@ -8,7 +8,7 @@
<ul class="nav nav-tabs" id="nav-params">
<li class="nav-item" v-for="section in sectionsArray">
<button type="button"
v-if="(section.name == 'products' && isProductsActice() == true) || (section.name != 'products')"
v-if="(section.name == 'products' && activeProducts == true) || (section.name != 'products')"
:class="'btn '+((currentSection == section.name) ? 'btn btn-primary' : 'btn ')"
@click="changeSection(section)">
${ section.nameDisplay }
@@ -41,16 +41,22 @@
{% if formValues.propertyNoveltyExpirationDate %}propertyNoveltyExpirationDateActive: true,{% endif %}
{% if formValues.typeExpirationDate %}typeExpirationDate: "{{ formValues.typeExpirationDate }}",{% endif %}
{% if formValues.behaviorExpirationDate %}behaviorExpirationDate: "{{ formValues.behaviorExpirationDate }}",{% endif %}
{% if formValues.propertyExpirationDate %}propertyExpirationDate: "{{ formValues.propertyExpirationDate|date('d/m/Y') }}",{% endif %}
{% if formValues.propertyExpirationDate %}propertyExpirationDate: "{{ formValues.propertyExpirationDate }}",{% endif %}
{% if formValues.activeProducts %}activeProducts: "{{ formValues.activeProducts }}",{% endif %}

};
multiplyingFactor = "{{ form.multiplyingFactor.vars.value }}"
window.productUnitPriceValues = {
{% if formValues.activeProducts %}activeProducts: "{{ formValues.activeProducts }}",{% endif %}
{% if formValues.behaviorPrice %}behaviorPrice: "{{ formValues.behaviorPrice }}",{% endif %}
{% if form.multiplyingFactor.vars.value %}multiplyingFactor: parseFloat(multiplyingFactor.replace(',', '.')),{% endif %}
{% if formValues.unit %}unit: parseInt({{ formValues.unit.id }}),{% endif %}
{% if formValues.quantity %}quantity: parseFloat({{ formValues.quantity }}),{% endif %}
{% if formValues.taxRate %}taxRate: parseInt({{ formValues.taxRate.id }}),{% endif %}
{% if formValues.price %}price: parseFloat({{ formValues.price }}).toFixed(3),{% endif %}
{% if formValues.priceByRefUnit %}priceByRefUnit: parseFloat({{ formValues.priceByRefUnit }}).toFixed(3),{% endif %}
{% if formValues.buyingPrice %}buyingPrice: parseFloat({{ formValues.buyingPrice }}).toFixed(3),{% endif %}
{% if formValues.buyingPriceByRefUnit %}buyingPriceByRefUnit: parseFloat({{ formValues.buyingPriceByRefUnit }}).toFixed(3),{% endif %}
{% if formValues.supplierTaxRate %}supplierTaxRate: parseInt({{ formValues.supplierTaxRate.id }}),{% endif %}
{% if form.supplierTaxRate.vars.value != 0 %}differentSupplierTaxRate: true{% endif %}
}
@@ -76,6 +82,10 @@
{% include '@LcShop/backend/productfamily/panel_property.html.twig' %}
</div>

<div v-show="currentSection == 'reduction'" class="panel panel-default">
{% include '@LcShop/backend/productfamily/panel_reduction.html.twig' %}
</div>


<div v-show="currentSection == 'note'" class="panel panel-default">
<div class="row">

+ 25
- 24
ShopBundle/Resources/views/backend/productfamily/panel_price.html.twig Ver arquivo

@@ -14,7 +14,7 @@
{{ form_row(form.behaviorAddToCart) }}
</div>

<div class="col-12 form-group">
<div class="col-12 form-group" v-show="activeProducts == true">
{{ form_label(form.behaviorPrice) }}
{% for field in form.behaviorPrice %}
{{ form_widget(field, {"attr" : {"v-model" : 'behaviorPrice'}}) }}
@@ -22,28 +22,6 @@
</div>
{{ macros.endCard(true) }}

{{ macros.startCard(0, 'ProductFamily.unit','light') }}
<div class="col-12">
{{ form_row(form.unit, {"attr":{'v-model': 'unit', '@change': "unitUpdated"}}) }}
</div>

<div class="col-12">
<div class="form-group field-weight">
{{ form_label(form.quantity) }}
<div class="form-widget">
<div class="input-group">
{{ form_widget(form.quantity, {'attr' : {'v-model': 'quantity', '@change': "quantityUpdated"}}) }}
<div class="input-group-append">
<span class="input-group-text">${ unitWording }</span>
</div>
</div>
{{ form_help(form.quantity) }}
</div>
</div>
</div>

{{ macros.endCard(true) }}

{{ macros.startCard(0, 'ProductFamily.tax','light') }}
<div class="col-12">
{{ form_row(form.taxRate, {'attr': {'v-model':'taxRate'}}) }}
@@ -57,8 +35,31 @@

{{ macros.endCard() }}

{{ macros.startCard(8, 'ProductFamily.price','light') }}
{{ macros.startCard(8, 'ProductFamily.priceAndUnit','light') }}


<div class="col-12 field-unit-quantity">
<div class="row">
<div class="col-6">
{{ form_row(form.unit, {"attr":{'v-model': 'unit', '@change': "unitUpdated"}}) }}
</div>

<div class="col-6" v-show="behaviorPrice=='by-piece'">
<div class="form-group field-weight">
{{ form_label(form.quantity) }}
<div class="form-widget">
<div class="input-group">
{{ form_widget(form.quantity, {'attr' : {'v-model': 'quantity', '@change': "quantityUpdated"}}) }}
<div class="input-group-append">
<span class="input-group-text">${ unitWording }</span>
</div>
</div>
{{ form_help(form.quantity) }}
</div>
</div>
</div>
</div>
</div>

{{ macros.priceField(form.buyingPrice, form.buyingPriceWithTax, 'buyingPrice', 'by-piece') }}


+ 66
- 6
ShopBundle/Resources/views/backend/productfamily/panel_products.html.twig Ver arquivo

@@ -45,14 +45,16 @@
{{ macros.productField(2, product.priceByRefUnitWithTax, 'priceByRefUnitWithTax',false, '€', 'v-show="productFamily.behaviorPrice == \'by-reference-unit\'"') }}

<td colspan="2" v-show="productFamily.behaviorPrice == 'by-reference-unit'">
{% verbatim %}{{ priceWithTaxValue }}{% endverbatim %}€
{% verbatim %}{{ finalPriceWithTax }}{% endverbatim %}€
</td>

{{ macros.productField(2, product.price, 'price', false, '€', 'v-show="productFamily.behaviorPrice == \'by-piece\'"') }}
{{ macros.productField(2, product.priceWithTax, 'priceWithTax', false, '€', 'v-show="productFamily.behaviorPrice == \'by-piece\'"') }}

{{ macros.productField(2, product.availableQuantity, 'availableQuantity',false, '', 'v-show="productFamily.behaviorCountStock== \'by-product\'"') }}
{{ macros.productField(2, product.availableQuantityDefault, 'availableQuantityDefault',false, '', 'v-show="productFamily.behaviorCountStock== \'by-product\'"') }}
{{ macros.productField(2, product.propertyExpirationDate, 'propertyExpirationDate','propertyExpirationDateFormated', '', 'v-show="productFamily.behaviorExpirationDate== \'by-product\'"') }}
{{ macros.productField(1, product.availableQuantity, 'availableQuantity',false, '', 'v-show="productFamily.behaviorCountStock== \'by-product\'"') }}
{{ macros.productField(1, product.availableQuantityDefault, 'availableQuantityDefault',false, '', 'v-show="productFamily.behaviorCountStock== \'by-product\'"') }}

{{ macros.productField(2, product.propertyExpirationDate, 'propertyExpirationDate','propertyExpirationDateValue', '', 'v-show="productFamily.behaviorExpirationDate== \'by-product\'"') }}

<td>
<button type="button" class="btn-remove-product btn btn-default" @click="deleteProductForm()">
@@ -115,7 +117,6 @@
PV TTC
</th>


<th v-show="behaviorCountStock== 'by-product'">
Stock
</th>
@@ -139,6 +140,62 @@
</template>

</tbody>
<tfoot>
<th>
Rappel
</th>
<th colspan="2" class="string">
${title}
</th>
<th colspan="1" class="string ">
${productFamily.quantity}
</th>
<th colspan="2" class="quantity">
${productFamily.unitWording}
</th>
<th v-show="getBehaviorPrice() == 'by-reference-unit'" colspan="2" class="buyingPriceByRefUnit">
${productFamily.buyingPriceByRefUnit}
</th>
<th v-show="getBehaviorPrice() == 'by-reference-unit'" colspan="2" class="priceByRefUnit">
${productFamily.buyingPriceByRefUnitWithTax}
</th>

<th colspan="2" class="price" v-show="getBehaviorPrice() =='by-piece'">
${productFamily.buyingPrice}
</th>
<th colspan="2" class="price" v-show="getBehaviorPrice() =='by-piece'">
${productFamily.buyingPriceWithTax}
</th>
<th colspan="2" class="">
${productFamily.multiplyingFactor}
</th>


<th v-show="getBehaviorPrice() == 'by-reference-unit'" colspan="2" class="">
${productFamily.priceByRefUnit}
</th>
<th v-show="getBehaviorPrice() == 'by-reference-unit'" colspan="2" class="price">
${productFamily.priceByRefUnitWithTax}
</th>

<th colspan="2" class="price" v-show="getBehaviorPrice() =='by-piece'">
${productFamily.price}
</th>
<th colspan="2" class="price">
${productFamily.priceWithTax}
</th>

<th v-show="behaviorCountStock== 'by-product'">
</th>
<th v-show="behaviorCountStock== 'by-product'">
</th>
<th colspan="2" class="" v-show="behaviorExpirationDate== 'by-product'">
${propertyExpirationDate}
</th>
<th class="">

</th>
</tfoot>
</table>
<button type="button" class="add_tag_link btn-add-product btn btn-default" @click="addProductForm"><span
class="fa fa-plus"></span> Ajouter une déclinaison
@@ -160,10 +217,13 @@
{% if product.vars.value.title %}title: "{{ product.vars.value.title }}",{% endif %}
{% if product.vars.value.quantity %}quantity: "{{ product.vars.value.quantity }}",{% endif %}
{% if product.vars.value.unit %}unit: {{ product.vars.value.unit.id }},{% endif %}
{% if product.vars.value.buyingPrice %}buyingPrice: "{{ product.vars.value.buyingPrice }}",{% endif %}
{% if product.vars.value.buyingPrice %}buyingPrice: parseFloat({{ product.vars.value.buyingPrice }}).toFixed(3),{% endif %}
{% if product.vars.value.buyingPriceByRefUnit %}buyingPriceByRefUnit: parseFloat({{ product.vars.value.buyingPriceByRefUnit }}).toFixed(3),{% endif %}
{% if product.vars.value.price %}price: parseFloat({{ product.vars.value.price }}).toFixed(3),{% endif %}
{% if product.vars.value.priceByRefUnit %}priceByRefUnit: parseFloat({{ product.vars.value.priceByRefUnit }}).toFixed(3),{% endif %}
{% if product.vars.value.availableQuantity %}availableQuantity: parseInt({{ product.vars.value.availableQuantity }}),{% endif %}
{% if product.vars.value.availableQuantityDefault %}availableQuantityDefault: parseInt({{ product.vars.value.availableQuantityDefault }}),{% endif %}
{% if product.vars.value.propertyExpirationDate %}propertyExpirationDate: "{{ product.vars.value.propertyExpirationDate }}",{% endif %}
{#{% if product.vars.value.expirationDate %}expirationDate: "{{ product.vars.value.expirationDate|date('d/m/Y') }}"{% endif %}#}
};
window.formProductTemplate[{{ keyForm }}] = '{{ formMacros.printProductRow(product)|replace({"\n":' ', "\r":' ', "'" : "\\'"})|raw }}';

+ 21
- 0
ShopBundle/Resources/views/backend/productfamily/panel_reduction.html.twig Ver arquivo

@@ -0,0 +1,21 @@
{% trans_default_domain 'lcshop' %}
{% import '@LcShop/backend/default/block/macros.html.twig' as macros %}

{% set formValues = form.reductionCatalog.vars.value %}

{{ macros.reductionCatalogFormValues(formValues, true) }}

<div class="row">
{{ macros.startCard(12, 'ProductFamily.initReduction', 'light') }}
<div class="col-12">
{{ form_row(form.activeReductionCatalog, {'attr': {'v-model' : 'reductionActive'}}) }}
</div>
{{ macros.endCard() }}

<div class="col-12">

<div class="row" v-show="reductionActive == true">
{{ macros.reductionCatalogForm(form.reductionCatalog) }}
</div>
</div>
</div>

+ 1
- 1
ShopBundle/Resources/views/backend/productfamily/panel_stock.html.twig Ver arquivo

@@ -9,7 +9,7 @@
{{ form_label(form.behaviorCountStock) }}
{% for field in form.behaviorCountStock %}
{% if field.vars.value == "by-product" %}
<div v-if="isProductsActice() == true">
<div v-if="activeProducts == true">
{{ form_widget(field, {"attr" : {"v-model" : 'behaviorCountStock'}}) }}
</div>
{% else %}

+ 2
- 108
ShopBundle/Resources/views/backend/reductioncatalog/form.html.twig Ver arquivo

@@ -3,116 +3,10 @@
{% import '@LcShop/backend/default/block/macros.html.twig' as macros %}

{% set formValues = form.vars.value %}
{{ macros.reductionCatalogFormValues(formValues) }}

<script>

window.appReductionCatalogValues = {
{% if formValues.permanent is not null and formValues.permanent == false %}permanent: false,{% endif %}
{% if formValues.users is not empty %}usersActive: true,{% endif %}
{% if formValues.groupUsers is not empty %}groupUsersActive: true,{% endif %}
{% if formValues.productFamilies is not empty %}productFamiliesActive: true,{% endif %}
{% if formValues.productCategories is not empty %}productCategoriesActive: true,{% endif %}
{% if formValues.suppliers is not empty %}suppliersActive: true,{% endif %}
}
</script>
<div id="lc-reduction-catalog-edit" class="row">

{{ macros.startCard(6, 'ReductionCatalog.info') }}
<div class="col-12">
{{ form_row(form.title) }}
</div>
{# <div class="col-12">
{{ form_row(form.fromQuantity) }}
</div>
#}
<div class="col-12">
{{ form_row(form.behaviorTaxRate) }}
</div>

<div class="col-12">
{{ form_row(form.unit) }}
</div>
<div class="col-12">
{{ form_row(form.value) }}
</div>



{{ macros.endCard() }}


{{ macros.startCard(6, 'ReductionCatalog.conditions','success') }}
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.permanent, {"attr" : {'v-model' : 'permanent' } }) }}
</div>
<div class="input-group" v-show="permanent == false">
<div class="input-group-prepend">
<span class="input-group-text"><i class="far fa-clock"></i></span>
</div>
<input type="text" class="form-control float-right date-time-range">
<div class="hidden date-time-range-fields" style="display: none;">
{{ form_widget(form.dateStart, {"attr" : {'class' : 'date-start'}}) }}
{{ form_widget(form.dateEnd, {"attr" : {'class' : 'date-end'}}) }}
</div>
</div>

</div>
</div>
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.usersActive, {"attr" : {'v-model' : 'usersActive' } }) }}
</div>
<div class="form-widget" v-show="usersActive == true">
{{ form_widget(form.users) }}
</div>
</div>
</div>
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.groupUsersActive, {"attr" : {'v-model' : 'groupUsersActive' } }) }}
</div>
<div class="form-widget" v-show="groupUsersActive == true">
{{ form_widget(form.groupUsers) }}
</div>
</div>

</div>
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.suppliersActive, {"attr" : {'v-model' : 'suppliersActive' } }) }}
</div>
<div class="form-widget" v-show="suppliersActive == true">
{{ form_widget(form.suppliers) }}
</div>
</div>
</div>
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.productCategoriesActive, {"attr" : {'v-model' : 'productCategoriesActive' } }) }}
</div>
<div class="form-widget" v-show="productCategoriesActive == true">
{{ form_widget(form.productCategories) }}
</div>
</div>
</div>
<div class="col-12">
<div class="form-group">
<div class="form-group">
{{ form_widget(form.productFamiliesActive, {"attr" : {'v-model' : 'productFamiliesActive' } }) }}
</div>
<div class="form-widget" v-show="productFamiliesActive == true">
{{ form_widget(form.productFamilies) }}
</div>
</div>
</div>

{{ macros.endCard() }}

{{ macros.reductionCatalogForm(form) }}
</div>
{{ form_end(form) }}

+ 68
- 30
ShopBundle/Services/OrderUtils.php Ver arquivo

@@ -2,9 +2,11 @@

namespace Lc\ShopBundle\Services ;

use App\Entity\OrderProductReductionCatalog;
use App\Entity\OrderShop;
use Doctrine\ORM\EntityManagerInterface;
use Lc\ShopBundle\Context\MerchantUtilsInterface;
use Lc\ShopBundle\Context\ProductFamilyUtilsInterface;
use Symfony\Component\Security\Core\Security;

class OrderUtils
@@ -14,14 +16,19 @@ class OrderUtils
protected $userUtils;
protected $merchantUtils;
private $orderShopRepo;
protected $priceUtils ;
protected $productFamilyUtils ;

public function __construct(EntityManagerInterface $em, Security $security, UserUtils $userUtils, MerchantUtilsInterface $merchantUtils)
public function __construct(EntityManagerInterface $em, Security $security, UserUtils $userUtils,
MerchantUtilsInterface $merchantUtils, PriceUtils $priceUtils, ProductFamilyUtilsInterface $productFamilyUtils)
{
$this->em = $em;
$this->security = $security;
$this->userUtils = $userUtils;
$this->merchantUtils = $merchantUtils;
$this->orderShopRepo = $this->em->getRepository(OrderShop::class);
$this->priceUtils = $priceUtils ;
$this->productFamilyUtils = $productFamilyUtils ;
}

public function getOrderShopCurrent()
@@ -84,24 +91,45 @@ class OrderUtils

public function addOrderProduct($orderShop, $orderProductAdd)
{
if ($orderProductAdd->getQuantity() > 0) {
if ($orderProductAdd->getQuantityOrder() > 0) {
$updated = false;

$orderProductAdd->setTitle($orderProductAdd->getTitleOrderShop());
$orderProductAdd->setPrice($orderProductAdd->getProduct()->getPriceInherited());
$orderProductAdd->setPrice($this->priceUtils->getPrice($orderProductAdd->getProduct()));
$orderProductAdd->setUnit($orderProductAdd->getProduct()->getUnitInherited());
$orderProductAdd->setTaxRate($orderProductAdd->getProduct()->getTaxRateInherited());
$orderProductAdd->setQuantityProduct($orderProductAdd->getProduct()->getQuantityInherited());

$productFamily = $this->productFamilyUtils->getProductFamilyBySlug($orderProductAdd->getProduct()->getProductFamily()->getSlug()) ;
$reductionCatalog = $productFamily->getReductionCatalog() ;
if($reductionCatalog) {
$orderProductReductionCatalog = new OrderProductReductionCatalog() ;
$orderProductReductionCatalog->setTitle($reductionCatalog->getTitle()) ;
$orderProductReductionCatalog->setValue($reductionCatalog->getValue()) ;
$orderProductReductionCatalog->setUnit($reductionCatalog->getUnit()) ;
$orderProductReductionCatalog->setBehaviorTaxRate($reductionCatalog->getBehaviorTaxRate()) ;

$orderProductAdd->setOrderProductReductionCatalog($orderProductReductionCatalog);
}

foreach($orderShop->getOrderProducts() as $orderProduct) {
if ($orderProduct->getProduct()->getId() == $orderProductAdd->getProduct()->getId()
&& $this->priceUtils->getPrice($orderProduct) == $this->priceUtils->getPrice($orderProductAdd)
&& $this->compareOrderProductReductionCatalog($orderProduct->getOrderProductReductionCatalog(), $orderProductAdd->getOrderProductReductionCatalog())) {

foreach ($orderShop->getOrderProducts() as $orderProduct) {
if ($orderProduct->getProduct()->getId() == $orderProductAdd->getProduct()->getId()) {
$updated = true;
$orderProduct->setQuantity($orderProduct->getQuantity() + $orderProductAdd->getQuantity());
$orderProduct->setQuantityOrder($orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder());
$this->em->persist($orderProduct);
}
}

if (!$updated) {
$orderShop->addOrderProduct($orderProductAdd);

if(isset($orderProductReductionCatalog)) {
$this->em->persist($orderProductReductionCatalog);
}

$this->em->persist($orderProductAdd);
$this->em->persist($orderShop);
}
@@ -110,6 +138,14 @@ class OrderUtils
}
}

public function compareOrderProductReductionCatalog($orderProductReductionCatalog1, $orderProductReductionCatalog2)
{
return $orderProductReductionCatalog1 && $orderProductReductionCatalog2
&& $orderProductReductionCatalog1->getUnit() == $orderProductReductionCatalog2->getUnit()
&& $orderProductReductionCatalog1->getValue() == $orderProductReductionCatalog2->getValue()
&& $orderProductReductionCatalog1->getBehaviorTaxRate() == $orderProductReductionCatalog2->getBehaviorTaxRate() ;
}

public function countQuantities($orderShop)
{
return $this->countQuantitiesByOrderProducts($orderShop->getOrderProducts());
@@ -120,29 +156,13 @@ class OrderUtils
$count = 0;

foreach ($orderProducts as $orderProduct) {
$count += $orderProduct->getQuantity();
$count += $orderProduct->getQuantityOrder();
}

return $count;
}

public function calculateTotalWithTax($orderShop)
{
return $this->calculateTotalWithTaxByOrderProducts($orderShop->getOrderProducts());
}

public function calculateTotalWithTaxByOrderProducts($orderProducts = [])
{
$totalWithTax = 0;

foreach ($orderProducts as $orderProduct) {
$totalWithTax += $orderProduct->getPriceWithTax() * $orderProduct->getQuantity();
}

return $totalWithTax;
}

public function orderProductsByParentCategory($orderShop = null)
public function getOrderProductsByParentCategory($orderShop = null)
{
$categoriesArray = [];
foreach ($orderShop->getOrderProducts() as $orderProduct) {
@@ -158,18 +178,36 @@ class OrderUtils
return $categoriesArray;
}

public function getDatasSummary($orderShop = null)
public function getOrderDatas($order = null)
{
if(!$orderShop) {
$orderShop = $this->getOrderShopCurrent() ;
if(!$order) {
$order = $this->getOrderShopCurrent() ;
}

$data = [] ;
$data['count'] = $this->countQuantities($orderShop) ;
$data['total_with_tax'] = $this->calculateTotalWithTax($orderShop) ;
$data['categories'] = $this->orderProductsByParentCategory($orderShop) ;
$data['order'] = $order ;
$data['count'] = $this->countQuantities($order) ;
$data['total_with_tax'] = $this->priceUtils->getTotalWithTaxAndReduction($order) ;
$data['order_products_by_category'] = $this->getOrderProductsByParentCategory($order) ;

return $data ;
}

public function getSummaryOrderProductReductionCatalog($orderProductReductionCatalog)
{
$text = '' ;

if($orderProductReductionCatalog) {
if($orderProductReductionCatalog->getUnit() == 'amount') {
$text .= '- '.$orderProductReductionCatalog->getValue().'&nbsp;€' ;
}

if($orderProductReductionCatalog->getUnit() == 'percent') {
$text .= '- '.$orderProductReductionCatalog->getValue().'&nbsp;%' ;
}
}

return $text ;
}

}

+ 242
- 0
ShopBundle/Services/PriceUtils.php Ver arquivo

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

namespace Lc\ShopBundle\Services ;

use Lc\ShopBundle\Context\OrderProductInterface;
use Lc\ShopBundle\Context\OrderShopInterface;
use Lc\ShopBundle\Context\ProductFamilyInterface;
use Lc\ShopBundle\Context\ProductInterface;
use Lc\ShopBundle\Context\ProductPropertyInterface;
use Lc\ShopBundle\Context\ReductionCatalogInterface;

class PriceUtils
{

public function getPrice($entity)
{
if($entity instanceof ProductPropertyInterface) {
if($entity->getBehaviorPriceInherited() == 'by-piece') {
return $entity->getPriceInherited() ;
}
elseif($entity->getBehaviorPriceInherited() == 'by-reference-unit') {
if($entity->getQuantityInherited() > 0) {
return $entity->getPriceByRefUnitInherited() * ($entity->getQuantityInherited() / $entity->getUnitInherited()->getCoefficient()) ;
}
}
}

if($entity instanceof OrderProductInterface) {
return $entity->getPrice() ;
}

return null ;
}

public function getPriceWithTax($entity)
{
return $this->applyTax(
$this->getPrice($entity),
$entity->getTaxRateInherited()->getValue()
) ;
}

public function getPriceWithTaxAndReduction($entity)
{
return $this->getPriceWithTaxAndReductionCatalog(
$entity,
$this->getPrice($entity),
$this->getPriceWithTax($entity)
);
}

public function getPriceByRefUnit($entity)
{
if($entity instanceof ProductPropertyInterface) {
if($entity->getBehaviorPriceInherited() == 'by-piece') {
return ($this->getPrice($entity) * $entity->getUnitInherited()->getCoefficient()) / $entity->getQuantityInherited() ;
}
elseif($entity->getBehaviorPriceInherited() == 'by-reference-unit') {
return $entity->getPriceByRefUnitInherited() ;
}
}

if($entity instanceof OrderProductInterface) {
return ($this->getPrice($entity) * $entity->getUnitInherited()->getCoefficient()) / $entity->getQuantityProduct() ;
}

return null ;
}

public function getPriceByRefUnitWithTax($entity)
{
return $this->applyTax(
$this->getPriceByRefUnit($entity),
$entity->getTaxRateInherited()->getValue()
) ;
}

public function getPriceByRefUnitWithTaxAndReduction($entity)
{
return $this->getPriceWithTaxAndReductionCatalog(
$entity,
$this->getPriceByRefUnit($entity),
$this->getPriceByRefUnitWithTax($entity)
);
}

public function getTotal($entity)
{
if($entity instanceof OrderProductInterface) {
return $entity->getQuantityOrder() * $this->getPrice($entity) ;
}
if($entity instanceof OrderShopInterface) {
$total = 0 ;
foreach($entity->getOrderProducts() as $orderProduct) {
$total += $this->getTotal($orderProduct) ;
}
return $total ;
}
return null ;
}

public function getTotalWithTax($entity)
{
if($entity instanceof OrderProductInterface) {
return $this->applyTax(
$this->getTotal($entity),
$entity->getTaxRateInherited()->getValue()
) ;
}
if($entity instanceof OrderShopInterface) {
$total = 0 ;
foreach($entity->getOrderProducts() as $orderProduct) {
$total += $this->getTotalWithTax($orderProduct) ;
}
return $total ;
}
if($entity instanceof OrderShopInterface) {
return $this->getTotalWithTaxByOrderProducts($entity->getOrderProducts()) ;
}
return null ;
}

public function getTotalWithTaxAndReduction($entity)
{
if($entity instanceof OrderProductInterface) {
return $this->getPriceWithTaxAndReductionCatalog(
$entity,
$this->getTotal($entity),
$this->getTotalWithTax($entity)
) ;
}

if($entity instanceof OrderShopInterface) {
return $this->getTotalWithTaxAndReductionByOrderProducts($entity->getOrderProducts()) ;
}
}

public function getTotalWithTaxByOrderProducts($orderProducts)
{
$totalWithTax = 0;

foreach ($orderProducts as $orderProduct) {
$totalWithTax += $this->getTotalWithTax($orderProduct);
}

return $totalWithTax;
}

public function getTotalWithTaxAndReductionByOrderProducts($orderProducts)
{
$totalWithTax = 0;

foreach ($orderProducts as $orderProduct) {
$totalWithTax += $this->getTotalWithTaxAndReduction($orderProduct);
}

return $totalWithTax;
}

public function getPriceWithTaxAndReductionCatalog($entity, $price, $priceWithTax, $reductionCatalog = null): ?float
{
if($reductionCatalog) {
$reductionCatalogValue = $reductionCatalog->getValue() ;
$reductionCatalogUnit = $reductionCatalog->getUnit() ;
$reductionCatalogBehaviorTaxRate = $reductionCatalog->getBehaviorTaxRate() ;
}
else {
if($entity instanceof ProductPropertyInterface) {
$reductionCatalog = $entity->getReductionCatalogInherited() ;

if($reductionCatalog) {
$reductionCatalogValue = $reductionCatalog->getValue() ;
$reductionCatalogUnit = $reductionCatalog->getUnit() ;
$reductionCatalogBehaviorTaxRate = $reductionCatalog->getBehaviorTaxRate() ;
}
}

if($entity instanceof OrderProductInterface) {
$orderProductReductionCatalog = $entity->getOrderProductReductionCatalog() ;
if($orderProductReductionCatalog) {
$reductionCatalogValue = $orderProductReductionCatalog->getValue() ;
$reductionCatalogUnit = $orderProductReductionCatalog->getUnit() ;
$reductionCatalogBehaviorTaxRate = $orderProductReductionCatalog->getBehaviorTaxRate() ;
}
}
}

if(isset($reductionCatalogValue) && isset($reductionCatalogUnit) && isset($reductionCatalogBehaviorTaxRate)) {
if ($reductionCatalogUnit == 'percent') {
return $this->applyReductionPercent(
$priceWithTax,
$reductionCatalogValue
);
}
elseif ($reductionCatalogUnit == 'amount') {
if($reductionCatalogBehaviorTaxRate == 'tax-excluded') {
return $this->applyTax(
$this->applyReductionAmount(
$price,
$reductionCatalogValue
),
$this->getTaxRateInherited()->getValue()
);
}
elseif($reductionCatalogBehaviorTaxRate == 'tax-included') {
return $this->applyReductionAmount(
$priceWithTax,
$reductionCatalogValue
);
}
}
}

return $priceWithTax ;
}

public function applyTax($price, $taxRateValue)
{
return $this->round($this->applyPercent($price, $taxRateValue)) ;
}

public function applyReductionPercent($price, $percentage)
{
return $this->applyPercent($price, -$percentage) ;
}

public function applyReductionAmount($price, $amount)
{
return $price - $amount ;
}

public function applyPercent($price, $percentage)
{
return $price * ($percentage / 100 + 1) ;
}

public function round($price)
{
return round((($price * 100)) / 100, 2);
}

}

+ 52
- 0
ShopBundle/Services/ProductFamilyUtils.php Ver arquivo

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

namespace Lc\ShopBundle\Services ;

class ProductFamilyUtils
{
protected $priceUtils ;

public function __construct(PriceUtils $priceUtils)
{
$this->priceUtils = $priceUtils ;
}

public function getCheapestProduct($productFamily)
{
$priceUtils = $this->priceUtils ;
return $this->getCheapestOrMostExpensiveProduct($productFamily->getProducts()->getValues(), function ($a, $b) use ($priceUtils) {
return $priceUtils->getPriceWithTaxAndReduction($a) > $priceUtils->getPriceWithTaxAndReduction($b) ;
}, true);
}

public function getCheapestProductByRefUnit($productFamily)
{
$priceUtils = $this->priceUtils ;
return $this->getCheapestOrMostExpensiveProduct($productFamily->getProducts()->getValues(), function ($a, $b) use ($priceUtils) {
return $priceUtils->getPriceByRefUnitWithTaxAndReduction($a) > $priceUtils->getPriceByRefUnitWithTaxAndReduction($b) ;
}, false);
}

public function getMostExpensiveProductByRefUnit($productFamily)
{
$priceUtils = $this->priceUtils ;
return $this->getCheapestOrMostExpensiveProduct($productFamily->getProducts()->getValues(), function ($a, $b) use ($priceUtils) {
return $priceUtils->getPriceByRefUnitWithTaxAndReduction($a) < $priceUtils->getPriceByRefUnitWithTaxAndReduction($b) ;
}, false);
}

private function getCheapestOrMostExpensiveProduct($products, $comparisonFunction, $returnSelfIfNotActiveProducts)
{
if (count($products) > 0) {
usort($products, $comparisonFunction);
return $products[0];
}
if ($returnSelfIfNotActiveProducts) {
return $this;
}
else {
return false;
}
}

}

Carregando…
Cancelar
Salvar