src/Repository/ProductVariantRepository.php line 83

Open in your IDE?
  1. <?php
  2. namespace App\Repository;
  3. use App\Entity\Gos\Country;
  4. use App\Entity\Gos\Product;
  5. use App\Entity\Gos\ProductAssociation;
  6. use App\Entity\Gos\ProductVariant;
  7. use App\Entity\Gos\ProductVariantPack;
  8. use App\Entity\Gos\Uniqskills\Course;
  9. use App\Enum\Product\ProductSourceSystem;
  10. use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
  11. use Doctrine\Common\Collections\Collection;
  12. use Doctrine\DBAL\Connection;
  13. use Doctrine\ORM\EntityRepository;
  14. use Doctrine\ORM\Query;
  15. use Doctrine\ORM\QueryBuilder;
  16. use Doctrine\Persistence\ManagerRegistry;
  17. /**
  18.  * ProductVariantRepository
  19.  *
  20.  * This class was generated by the Doctrine ORM. Add your own custom
  21.  * repository methods below.
  22.  */
  23. class ProductVariantRepository extends ServiceEntityRepository
  24. {
  25.     public function __construct(ManagerRegistry $registry)
  26.     {
  27.         parent::__construct($registryProductVariant::class);
  28.     }
  29.     private const WIDGETS_CACHE_RESULT_LIFETIME 300//5 minutes
  30.     public function findAllByCourseAndCountryCode($courseSlug$myCountryCode)
  31.     {
  32.         return $this
  33.             ->createQueryBuilder('pv')
  34.             ->leftJoin('pv.courses''course')
  35.             ->leftJoin('pv.country''country')
  36.             ->where('course.slug = :courseSlug')
  37.             ->setParameter('courseSlug'$courseSlug)
  38.             ->andWhere('country.alpha2 = :countryCode')
  39.             ->setParameter('countryCode'$myCountryCode)
  40.             ->getQuery()
  41.             ->getResult();
  42.     }
  43.     public function findProductVariantToAdd($arrayProductVariantNo)
  44.     {
  45.         return $this
  46.             ->createQueryBuilder('pv')
  47.             ->leftJoin('pv.physicalVariant''mpv')
  48.             ->where('pv.productVariantNoComplete IN (:pvnc)')
  49.             ->orWhere('mpv.productVariantNoComplete IN (:pvnc) AND pv.isAddition =:isAddition')
  50.             ->setParameter('pvnc'$arrayProductVariantNo)
  51.             ->setParameter('isAddition'true)
  52.             ->getQuery()
  53.             ->getResult();
  54.     }
  55.     public function findOneByIdAndProductVariantNoComplete($productVariantId$productVariantNoComplete)
  56.     {
  57.         return $this
  58.             ->createQueryBuilder('pv')
  59.             ->leftJoin('pv.physicalVariant''physicalVariant')
  60.             ->where('pv.id = :id')
  61.             ->setParameter('id'$productVariantId)
  62.             ->andWhere('physicalVariant.productVariantNoComplete = :physicalVariant')
  63.             ->setParameter('physicalVariant'$productVariantNoComplete)
  64.             ->getQuery()->setMaxResults(1)->getOneOrNullResult();
  65.     }
  66.     public function findTaxFreeForBudgetUnitIsTrue($productCart)
  67.     {
  68.         return $this
  69.             ->createQueryBuilder('pv')
  70.             ->leftJoin('pv.productCart''pc')
  71.             ->where('pc.id IN (:id)')
  72.             ->setParameter('id'$productCart)
  73.             ->andWhere('pv.taxFreeForBudgetUnit = true')
  74.             ->getQuery()->getResult();
  75.     }
  76.     public function findAllFiltered(QueryBuilder $qb$psId 0$number null$isEvent null$course null$country null$sourceSystem): QueryBuilder
  77.     {
  78.         $qb
  79.             ->distinct()
  80.             ->select('pv')
  81.             ->from(ProductVariant::class, 'pv');
  82.         if ($psId)
  83.         {
  84.             $qb
  85.                 ->leftJoin('pv.portalSettings''ps')
  86.                 ->where('ps.id = :portalSettingsId')
  87.                 ->setParameter('portalSettingsId'$psId);
  88.         }
  89.         if (!empty($number))
  90.         {
  91.             $qb
  92.                 ->andWhere('pv.productVariantNoComplete = :no')
  93.                 ->setParameter('no'$number);
  94.         }
  95.         if (!is_null($isEvent))
  96.         {
  97.             $qb
  98.                 ->leftJoin('pv.masterProduct''master_product')
  99.                 ->leftJoin('master_product.productGosType''product_gos_type');
  100.             if ($isEvent)
  101.             {
  102.                 $qb->where('product_gos_type.name = :productGosType')
  103.                     ->setParameter('productGosType''event');
  104.             }
  105.             else
  106.             {
  107.                 $qb->where('product_gos_type.name != :productGosType')
  108.                     ->setParameter('productGosType''event');
  109.             }
  110.         }
  111.         if ($course)
  112.         {
  113.             $qb
  114.                 ->leftJoin('pv.courses''c')
  115.                 ->andWhere('c.id = (:cid)')
  116.                 ->setParameter('cid'$course);
  117.         }
  118.         if ($country)
  119.         {
  120.             $qb
  121.                 ->leftJoin('pv.country''country')
  122.                 ->andWhere('country.id = (:countryid)')
  123.                 ->setParameter('countryid'$country);
  124.         }
  125.         if (!empty($sourceSystem))
  126.         {
  127.             $sourceSystem ProductSourceSystem::from($sourceSystem);
  128.             $qb
  129.                 ->innerJoin('pv.masterProduct''masterProduct')
  130.                 ->andWhere('masterProduct.sourceSystem = :sourceSystem')
  131.                 ->setParameter('sourceSystem'$sourceSystem);
  132.         }
  133.         return $qb;
  134.     }
  135.     public function findOnlyEvents($notAssignedToEventsEntity false$maximum null)
  136.     {
  137.         $qb $this->createQueryBuilder('e')
  138.                 ->leftJoin('e.masterProduct''mp')
  139.                 ->leftJoin('mp.productGosType''product_gos_type')
  140.                 ->where('product_gos_type.name = :productGosType')
  141.                 ->setParameter('productGosType''event');
  142.         if ($notAssignedToEventsEntity === true)
  143.         {
  144.             $qb
  145.                ->andWhere('e.events is null');
  146.         }
  147.         if (!is_null($maximum))
  148.         {
  149.             $qb->setMaxResults($maximum);
  150.         }
  151.         return $qb->getQuery()->getResult();
  152.     }
  153.     public function findForAjaxFilter($productVariantNoComplete, array $findIn null)
  154.     {
  155.         $form $this
  156.             ->createQueryBuilder('pv')
  157.             ->select("pv.id, COALESCE(pv.productVariantNoComplete, CONCAT(pv.id, ' ', pv.workingTitle)) as text");
  158.         if (!empty($productVariantNoComplete))
  159.         {
  160.             $form
  161.                 ->andWhere("COALESCE(pv.productVariantNoComplete, CONCAT(pv.id, ' ', pv.workingTitle)) LIKE :productVariantNoComplete")
  162.                 ->setParameter('productVariantNoComplete'$productVariantNoComplete '%');
  163.         }
  164.         if (is_iterable($findIn))
  165.         {
  166.             $form
  167.                 ->andWhere('pv.id IN (:findIn)')
  168.                 ->setParameter('findIn'$findIn)
  169.             ;
  170.         }
  171.         return $form->getQuery();
  172.     }
  173.     public function findForAjaxFilterBCOnly($productVariantNoComplete)
  174.     {
  175.         $form $this
  176.             ->createQueryBuilder('pv')
  177.             ->select("pv.id, COALESCE(pv.productVariantNoComplete, CONCAT(pv.id, ' ', pv.workingTitle)) as text")
  178.             ->innerJoin('pv.masterProduct''mp')
  179.             ->andWhere('mp.sourceSystem = :sourceSystem')
  180.             ->setParameter('sourceSystem'ProductSourceSystem::BC);
  181.         if (!empty($productVariantNoComplete)) {
  182.             $form
  183.                 ->andWhere("COALESCE(pv.productVariantNoComplete, CONCAT(pv.id, ' ', pv.workingTitle)) LIKE :productVariantNoComplete")
  184.                 ->setParameter('productVariantNoComplete'$productVariantNoComplete '%');
  185.         }
  186.         return $form->getQuery();
  187.     }
  188.     public function findByProductsVariantsNo($productsVariantsNumbers$isAddition$getPhysicalVariant true)
  189.     {
  190.         $query $this
  191.             ->createQueryBuilder('pv')
  192.             ->where('pv.productVariantNoComplete IN (:pvnc)');
  193.         if ($getPhysicalVariant)
  194.         {
  195.             $query
  196.                 ->leftJoin('pv.physicalVariant''mpv')
  197.                 ->orWhere('mpv.productVariantNoComplete IN (:pvnc) AND pv.isAddition =:isAddition')
  198.                 ->setParameter('isAddition'$isAddition);
  199.         }
  200.         return $query->setParameter('pvnc'$productsVariantsNumbers)->getQuery()->getResult();
  201.     }
  202.     public function findOneByProductVariantsNo($productsVariantsNumber$isAddition)
  203.     {
  204.         return $this
  205.             ->createQueryBuilder('pv')
  206.             ->leftJoin('pv.physicalVariant''mpv')
  207.             ->where('pv.productVariantNoComplete = :pvnc')
  208.             ->orWhere('mpv.productVariantNoComplete = :pvnc AND pv.isAddition =:isAddition')
  209.             ->setParameter('pvnc'$productsVariantsNumber)
  210.             ->setParameter('isAddition'$isAddition)
  211.             ->getQuery()
  212.             ->disableResultCache()
  213.             ->setMaxResults(1)->getOneOrNullResult();
  214.     }
  215.     // This method is used to find a product variant by its number with caching for widgets (e.g. show-price).
  216.     public function findOneByProductVariantsNoCacheable($productsVariantsNumber$isAddition)
  217.     {
  218.         return $this
  219.             ->createQueryBuilder('pv')
  220.             ->leftJoin('pv.physicalVariant''mpv')
  221.             ->where('pv.productVariantNoComplete = :pvnc')
  222.             ->orWhere('mpv.productVariantNoComplete = :pvnc AND pv.isAddition =:isAddition')
  223.             ->setParameter('pvnc'$productsVariantsNumber)
  224.             ->setParameter('isAddition'$isAddition)
  225.             ->getQuery()
  226.             ->enableResultCache(self::WIDGETS_CACHE_RESULT_LIFETIME'PV_' $productsVariantsNumber '_' . (int)$isAddition)
  227.             ->setMaxResults(1)->getOneOrNullResult();
  228.     }
  229.     // This method is used to find a product variant by its id with caching for widgets (e.g. show-price).
  230.     public function findOneCacheable($id)
  231.     {
  232.         return $this
  233.             ->createQueryBuilder('pv')
  234.             ->where('pv.id = :id')
  235.             ->setParameter('id'$id)
  236.             ->getQuery()
  237.             ->enableResultCache(self::WIDGETS_CACHE_RESULT_LIFETIME'PV_byId_' $id)
  238.             ->setMaxResults(1)
  239.             ->getOneOrNullResult();
  240.     }
  241.     // This method is used to find a product variant by its number with caching for widgets (e.g. show-price-omnibus, check-exclusive-pv-info).
  242.     public function findOneByProductVariantNoCompleteCacheable($productsVariantsNumber)
  243.     {
  244.         return $this
  245.             ->createQueryBuilder('pv')
  246.             ->where('pv.productVariantNoComplete = :pvnc')
  247.             ->setParameter('pvnc'$productsVariantsNumber)
  248.             ->getQuery()
  249.             ->enableResultCache(self::WIDGETS_CACHE_RESULT_LIFETIME'PV_byNoComplete_' $productsVariantsNumber)
  250.             ->setMaxResults(1)
  251.             ->getOneOrNullResult();
  252.     }
  253.     public function findMaxProductVariantId()
  254.     {
  255.         return $this->createQueryBuilder('pv')
  256.             ->select('MAX(pv.productVariantId) AS newId')
  257.             ->setMaxResults(1)
  258.             ->getQuery()
  259.             ->getOneOrNullResult();
  260.     }
  261.     public function findLastProductVariantNoComplete($masterProductId)
  262.     {
  263.         $sql 'SELECT pv.product_variant_no
  264.                 FROM product_variant pv 
  265.                 WHERE pv.master_product_id='.$masterProductId.
  266.                 ORDER BY CAST(pv.product_variant_no AS unsigned) DESC LIMIT 1';
  267.         return $this->getEntityManager()
  268.             ->getConnection()
  269.             ->prepare($sql)
  270.             ->executeQuery()
  271.             ->fetchAllAssociative();
  272.     }
  273.     public function findAllByCourseAndCountry($slugCourse$country)
  274.     {
  275.         return $this
  276.             ->createQueryBuilder('pv')
  277.             ->leftJoin("pv.country""country")
  278.             ->leftJoin("pv.courses"'course')
  279.             ->where('course.slug = :slugCourse')
  280.             ->setParameter('slugCourse'$slugCourse)
  281.             ->andWhere('country.name = :country')
  282.             ->setParameter('country'$country)
  283.             ->getQuery()
  284.             ->getResult();
  285.     }
  286.     public function findByVariantStateActiveOrTest()
  287.     {
  288.         return $this
  289.             ->createQueryBuilder('pv')
  290.             ->where('pv.variantState = :active')
  291.             ->setParameter('active''active')
  292.             ->orWhere('pv.variantState = :test')
  293.             ->setParameter('test''Product test')
  294.             ->getQuery()
  295.             ->getResult();
  296.     }
  297.     public function findOneEcoVariantFromProductAssociation(ProductAssociation $productAssociation): ?ProductVariant
  298.     {
  299.         return $this
  300.             ->createQueryBuilder('pv')
  301.             ->leftJoin('pv.productAssociation''pa')
  302.             ->where('pa.id = :paId')
  303.             ->setParameter('paId'$productAssociation->getId())
  304.             ->andWhere('pv.productVariantNoComplete NOT LIKE :premium or pv.productVariantNoComplete LIKE :startNumberWith68')
  305.             ->setParameter('startNumberWith68''68%')
  306.             ->setParameter('premium''6%')
  307.             ->andWhere('pv.productVariantNoComplete NOT LIKE :online')
  308.             ->setParameter('online''8%')
  309.             ->andWhere('pv.productVariantNoComplete NOT LIKE :event')
  310.             ->setParameter('event''7%')
  311.             ->addOrderBy('pv.priceGross''ASC')
  312.             ->setMaxResults(1)
  313.             ->getQuery()
  314.             ->getOneOrNullResult();
  315.     }
  316.     public function findAllEligibleToMakeGiftable($countries = [])
  317.     {
  318.         return $this
  319.             ->createQueryBuilder('pv')
  320.             ->leftJoin('pv.country''country')
  321.             ->leftJoin('pv.courses''course')
  322.             ->where('pv.isGiftable = false OR pv.isGiftable IS NULL')
  323.             ->andWhere('(country.slug IN (:countries)) OR (country.slug = :poland AND pv.productVariantNo = 1)')
  324.             ->setParameter('countries'$countries)
  325.             ->setParameter('poland''poland')
  326.             ->andWhere('course.id IS NOT NULL')
  327.             ->getQuery()
  328.             ->getResult();
  329.     }
  330.     public function findAllFromProductVariantPack(ProductVariantPack $productVariantPack)
  331.     {
  332.         $qb $this
  333.             ->createQueryBuilder('pv')
  334.             ->leftJoin('pv.productVariantPacks''pvp');
  335.         if (!$productVariantPack->getProductVariants()->isEmpty())
  336.         {
  337.             $variantsIds $productVariantPack->getProductVariants()->map(function($item) {return $item->getId();});
  338.             $qb
  339.                 ->where('pv.id IN (:variantsFromPack)')
  340.                 ->setParameter('variantsFromPack'$variantsIds);
  341.         }
  342.         if (!$productVariantPack->getCountries()->isEmpty())
  343.         {
  344.             $countriesIds $productVariantPack->getCountries()->map(function($item) {return $item->getId();});
  345.             $qb
  346.                 ->leftJoin('pv.country''country')
  347.                 ->andWhere('country.id IN (:countries)')
  348.                 ->setParameter('countries'$countriesIds);
  349.         }
  350.         if (!$productVariantPack->getPortalSettings()->isEmpty())
  351.         {
  352.             $portalSettingsIds $productVariantPack->getPortalSettings()->map(function($item) {return $item->getId();});
  353.             $qb
  354.                 ->leftJoin('pv.portalSettings''portalSettings')
  355.                 ->andWhere('portalSettings.id IN (:portalSettings)')
  356.                 ->setParameter('portalSettings'$portalSettingsIds);
  357.         }
  358.         if (!$productVariantPack->getClientTypes()->isEmpty())
  359.         {
  360.             $clientTypesIds $productVariantPack->getClientTypes()->map(function($item) {return $item->getId();});
  361.             $qb
  362.                 ->leftJoin('pv.clientType''clientType')
  363.                 ->andWhere('clientType.id IN (:clientTypes)')
  364.                 ->setParameter('clientTypes'$clientTypesIds);
  365.         }
  366.         return $qb->getQuery()->getResult();
  367.     }
  368.     public function findAllFromProductVariantPacks(Collection $productVariantPacks)
  369.     {
  370.         if ($productVariantPacks->isEmpty()) {
  371.             return [];
  372.         }
  373.         $productVariantPackIds $productVariantPacks->map(function (ProductVariantPack $productVariantPack) {
  374.             return $productVariantPack->getId();
  375.         })->toArray();
  376.         $sql '
  377.             SELECT
  378.                 pvp.id AS product_variant_pack_id,
  379.                 group_concat(DISTINCT pspv.portal_settings_id) AS product_variant_portal_settings_id, 
  380.                 group_concat(DISTINCT pvct.client_type_id) AS product_variant_client_type_id, 
  381.                 pv.*
  382.             FROM
  383.                 product_variant_pack pvp
  384.             JOIN product_variant_in_pack pvip ON
  385.                 pvip.product_variant_pack_id = pvp.id
  386.             JOIN product_variant pv ON
  387.                 pv.id = pvip.product_variant_id
  388.             LEFT JOIN portal_settings_product_variant pspv ON
  389.                 pspv.product_variant_id = pv.id
  390.             LEFT JOIN product_variant_client_type pvct ON
  391.                 pvct.product_variant_id = pv.id
  392.             WHERE
  393.                 pvp.id IN ( ' implode(", "array_fill(0count($productVariantPackIds), "?")) . ')
  394.             GROUP BY 
  395.                 pvp.id,
  396.                 pv.id
  397.         ';
  398.         $productVariants $this->getEntityManager()->getConnection()->executeQuery($sql$productVariantPackIds)->fetchAllAssociative();
  399.         $productVariantsByPack = [];
  400.         foreach ($productVariants as &$productVariantArray) {
  401.             $productVariantArray['product_variant_portal_settings_id'] = explode(','$productVariantArray['product_variant_portal_settings_id']);
  402.             $productVariantArray['product_variant_client_type_id'] = explode(','$productVariantArray['product_variant_client_type_id']);
  403.             if (!array_key_exists($productVariantArray['product_variant_pack_id'], $productVariantsByPack)) {
  404.                 $productVariantsByPack[$productVariantArray['product_variant_pack_id']] = [];
  405.             }
  406.             $productVariantsByPack[$productVariantArray['product_variant_pack_id']][] = $productVariantArray;
  407.         }
  408.         /** @var ProductVariantPack $productVariantPack */
  409.         foreach ($productVariantPacks as $productVariantPack)
  410.         {
  411.             if (!$productVariantPack->getCountries()->isEmpty() ||
  412.                 !$productVariantPack->getPortalSettings()->isEmpty() ||
  413.                 !$productVariantPack->getClientTypes()->isEmpty())
  414.             {
  415.                 if (!$productVariantPack->getCountries()->isEmpty())
  416.                 {
  417.                     $countriesIds $productVariantPack->getCountries()->map(function($item) { return $item->getId(); });
  418.                     array_filter($productVariantsByPack[$productVariantPack->getId()], function ($productVariant) use ($countriesIds) {
  419.                         return in_array($productVariant['country_id'], $countriesIds->toArray());
  420.                     });
  421.                 }
  422.                 if (!$productVariantPack->getPortalSettings()->isEmpty())
  423.                 {
  424.                     $portalSettingsIds $productVariantPack->getPortalSettings()->map(function($item) { return $item->getId(); });
  425.                     array_filter($productVariantsByPack[$productVariantPack->getId()], function ($productVariant) use ($portalSettingsIds) {
  426.                         return array_intersect($productVariant['product_variant_portal_settings_id'], $portalSettingsIds->toArray());
  427.                     });
  428.                 }
  429.                 if (!$productVariantPack->getClientTypes()->isEmpty())
  430.                 {
  431.                     $clientTypesIds $productVariantPack->getClientTypes()->map(function($item) { return $item->getId(); });
  432.                     array_filter($productVariantsByPack[$productVariantPack->getId()], function ($productVariant) use ($clientTypesIds) {
  433.                         return array_intersect($productVariant['product_variant_client_type_id'], $clientTypesIds->toArray());
  434.                     });
  435.                 }
  436.             }
  437.         }
  438.         return array_merge(...$productVariantsByPack);
  439.     }
  440.     public function findMainForCourse(Course $course$country null): ?ProductVariant
  441.     {
  442.         $qb $this
  443.             ->createQueryBuilder('pv')
  444.             ->leftJoin('pv.courses''course')
  445.             ->where('course.id = :courseId')
  446.             ->setParameter('courseId'$course->getId());
  447.         if (!is_null($country))
  448.         {
  449.             $qb
  450.                 ->andWhere('pv.country = :country')
  451.                 ->setParameter('country'$country);
  452.         }
  453.         return $qb->setMaxResults(1)->getQuery()->getOneOrNullResult();
  454.     }
  455.     public function findProlongation(ProductVariant $productVariantint $days): ?ProductVariant
  456.     {
  457.         $qb $this
  458.             ->createQueryBuilder('pv')
  459.             ->andWhere('pv.productVariantNoComplete LIKE :variantNumber');
  460.         if ($days === 30)
  461.         {
  462.             $qb->setParameter('variantNumber''2' $productVariant->getMasterProduct()->getProductNo() . '/1');
  463.         }
  464.         elseif ($days === 270)
  465.         {
  466.             $qb->setParameter('variantNumber''2' $productVariant->getMasterProduct()->getProductNo() . '/2');
  467.         }
  468.         else
  469.         {
  470.             return null;
  471.         }
  472.         return $qb->setMaxResults(1)->getQuery()->getOneOrNullResult();
  473.     }
  474.     public function findFullAccessForCourseAndCountry(Course $course, ?Country $country)
  475.     {
  476.         $qb $this->createQueryBuilder('pv')
  477.             ->leftJoin('pv.courses''course')
  478.             ->leftJoin('pv.country''country')
  479.             ->leftJoin('pv.packages''package')
  480.             ->where('course.id = :courseId')
  481.             ->andWhere('package.id IS NULL')
  482.             ->andWhere('pv.installmentAmount < 2 OR pv.installmentAmount IS NULL')
  483.             ->setParameter('courseId'$course->getId())
  484.             ->andWhere('course.isActive = true');
  485.         if ($country !== null)
  486.         {
  487.             $qb->andWhere('country.slug = :countrySlug')
  488.                 ->setParameter('countrySlug'$country->getSlug());
  489.         }
  490.         return $qb->setMaxResults(1)
  491.             ->getQuery()
  492.             ->getOneOrNullResult();
  493.     }
  494.     public function addToProductVariantPack($productPackId$countries)
  495.     {
  496.         $sql "INSERT INTO product_variant_in_pack
  497.         (
  498.             product_variant_pack_id,
  499.             product_variant_id
  500.         )
  501.         SELECT DISTINCT
  502.             ".$productPackId.",
  503.             pv.id
  504.         FROM
  505.             product_variant pv
  506.         LEFT JOIN 
  507.             payment_type pt ON pv.payment_type_id = pt.id
  508.         LEFT JOIN
  509.             relations_product_variant rpv ON rpv.physical_variant_id = pv.id
  510.         LEFT JOIN
  511.             product_variant vpv ON vpv.id = rpv.virtual_variant_id
  512.         LEFT JOIN
  513.             product_variant_course pvc ON pvc.product_variant_id = pv.id
  514.         INNER JOIN
  515.             product_variant_payment_method pvpm ON pvpm.product_variant_id = pv.id
  516.         WHERE
  517.         (pt.slug IS NULL OR pt.slug != 'partial-payment')
  518.         AND pvpm.product_variant_id IS NOT NULL
  519.             AND pv.state_is_availible = TRUE
  520.             AND (pv.quantity IS NULL OR pv.quantity = 0 OR pv.quantity > pv.order_quantity)
  521.         AND (vpv.state_is_availible = TRUE OR vpv.id IS NULL)
  522.         AND (vpv.quantity IS NULL OR vpv.quantity = 0 OR vpv.quantity > vpv.order_quantity)
  523.         AND NOT EXISTS (
  524.                 SELECT *
  525.                 FROM product_variant_in_pack pvip 
  526.                 WHERE pvip.product_variant_pack_id = ".$productPackId."
  527.                 AND pvip.product_variant_id = pv.id
  528.         )
  529.         AND pvc.product_variant_id IS NOT NULL
  530.         AND pv.country_id IN (".$countries.")";
  531.         $this->getEntityManager()
  532.             ->getConnection()
  533.             ->prepare($sql)
  534.             ->executeStatement();
  535.     }
  536.     public function getForProcessingFOResponse(?array $productVariantNoComplete)
  537.     {
  538.         return $this->createQueryBuilder('pv')
  539.             ->select("CASE WHEN (pgt.name = 'event') THEN true ELSE false END as isEvent, 
  540.                        pgt.name as gosType, pst.name as subscriptionType, pv.productVariantNoComplete")
  541.             ->innerJoin('pv.masterProduct''p')
  542.             ->leftJoin('p.productGosType''pgt')
  543.             ->leftJoin('pv.productSubscriptionType''pst')
  544.             ->andWhere('pv.productVariantNoComplete in (:productVariantNoComplete)')
  545.             ->setParameter('productVariantNoComplete'$productVariantNoComplete)
  546.             ->getQuery()
  547.             ->getResult();
  548.     }
  549.     public function getDataForBenefits(?array $productVariantNoComplete)
  550.     {
  551.         $conn $this->getEntityManager()->getConnection();
  552.         $sql  'SELECT 
  553.                     pst.slug as productSubscriptionType, 
  554.                     pgt.name as productGosType,
  555.                     p.product_No as productNumber, 
  556.                     pv.product_variant_no_complete AS productVariantNumber,
  557.                     group_concat(pa_products.id) as productAssociationsProduct, 
  558.                     group_concat(pa_product_variants.id) as productAssociationsProductVariant
  559.                  FROM
  560.                     product_variant pv
  561.                         INNER JOIN
  562.                     product p ON pv.master_product_id = p.id
  563.                         LEFT JOIN
  564.                     product_subscription_type pst ON pv.product_subscription_type_id = pst.id
  565.                         LEFT JOIN
  566.                     product_gos_type pgt ON p.product_gos_type_id = pgt.id
  567.                         LEFT JOIN
  568.                     product_association_product pap ON p.id = pap.product_id
  569.                         LEFT JOIN
  570.                     product_association pa_products ON pap.product_association_id = pa_products.id
  571.                         LEFT JOIN
  572.                     product_association_product_variant papv ON pv.id = papv.product_variant_id
  573.                         LEFT JOIN
  574.                     product_association pa_product_variants ON papv.product_association_id = pa_product_variants.id
  575.                     where pv.product_variant_no_complete in (:productVariantNoComplete)
  576.                  GROUP BY pv.product_variant_no_complete';
  577.         $stmt $conn->executeQuery($sql,
  578.                     ['productVariantNoComplete' => $productVariantNoComplete],
  579.                     ['productVariantNoComplete' => Connection::PARAM_STR_ARRAY]
  580.         );
  581.         return $stmt->fetchAll();
  582.     }
  583.     public function findAllForCalendarEvents(): ?array
  584.     {
  585.         return $this->createQueryBuilder('pv')
  586.             ->join('pv.calendarEvents''ce')
  587.             ->getQuery()
  588.             ->getResult();
  589.     }
  590.     public function findAllForPaymentReminder(): ?array
  591.     {
  592.         $conn $this->getEntityManager()->getConnection();
  593.         $sql  'SELECT prpv.product_variant_id FROM payment_reminders_product_variant prpv GROUP BY 1';
  594.         $stmt $conn->executeQuery($sql);
  595.         $all $stmt->fetchAll();
  596.         $result = [];
  597.         foreach ($all as $id$result[] = $id['product_variant_id'];
  598.         return $result;
  599.     }
  600.     public function selectProductVariantNoCompleteForAll($noVirtual false)
  601.     {
  602.         $qb $this->createQueryBuilder('pv')
  603.             ->select('pv.id, pv.productVariantNoComplete');
  604.         if ($noVirtual === true)
  605.         {
  606.             $qb->andWhere('pv.priceNet > 0');
  607.         }
  608.         return $qb->getQuery()->getResult();
  609.     }
  610.     public function findAllForOmnibus(QueryBuilder $qb)
  611.     {
  612.         $qb
  613.             ->distinct()
  614.             ->select('pv')
  615.             ->from(ProductVariant::class, 'pv')
  616.             ->leftJoin('pv.omnibus''o')
  617.             ->andWhere('pv.priceNet > 0')
  618.             ->andWhere('o.id IS NOT NULL');
  619.         return  $qb;
  620.     }
  621.     public function findOriginalProductsVariantWithDuplicate($productVariantNoComplete)
  622.     {
  623.         $qb $this->createQueryBuilder('pv');
  624.         if (!is_null($productVariantNoComplete))
  625.         {
  626.             $qb
  627.                 ->andWhere('pv.productVariantNoComplete IN (:productVariantNoComplete)')
  628.                 ->setParameter('productVariantNoComplete'$productVariantNoComplete);
  629.         }
  630.         $qb
  631.             ->groupBy('pv.productVariantNoComplete')
  632.             ->having('COUNT(pv.productVariantNoComplete) > 1');
  633.         return $qb->getQuery()->getResult();
  634.     }
  635.     public function findAllDuplicateByOriginal(ProductVariant $originalProductVariant)
  636.     {
  637.         return $this
  638.             ->createQueryBuilder('pv')
  639.             ->where('pv.productVariantNoComplete = :productVariantNoComplete')
  640.             ->andWhere('pv.id != :originalId' )
  641.             ->setParameter('productVariantNoComplete'$originalProductVariant->getProductVariantNoComplete())
  642.             ->setParameter('originalId'$originalProductVariant->getId())
  643.             ->getQuery()->getResult();
  644.     }
  645.     public function findLastForProduct(Product $product)
  646.     {
  647.         return $this
  648.             ->createQueryBuilder('pv')
  649.             ->leftJoin('pv.product''p')
  650.             ->where('p = :product')
  651.             ->setParameter('product'$product)
  652.             ->setMaxResults(1)
  653.             ->orderBy('pv.id''DESC')
  654.             ->getQuery()
  655.             ->getOneOrNullResult();
  656.     }
  657.     public function findOneByNoCompleteAndTaxNoComplete(string $noComplete)
  658.     {
  659.         return $this
  660.             ->createQueryBuilder('pv')
  661.             ->where('pv.productVariantNoComplete = :noComplete')
  662.             ->orWhere('pv.productNumberPartTax = :noComplete')
  663.             ->orWhere('pv.productNumberNoTax = :noComplete')
  664.             ->setParameter('noComplete'$noComplete)
  665.             ->setMaxResults(1)
  666.             ->getQuery()
  667.             ->getOneOrNullResult();
  668.     }
  669.     public function findWithoutNewClientType(?int $limit)
  670.     {
  671.         $qb $this->createQueryBuilder('pv')
  672.             ->leftJoin('pv.additionalOptionsByClientTypes''aobct')
  673.             ->leftJoin('pv.paymentMethod''pm')
  674.             ->leftJoin('pv.clientType''ct')
  675.             ->where('aobct.id IS NULL')
  676.             ->andWhere('pm.id IS NOT NULL')
  677.             ->andWhere('ct.id IS NOT NULL');
  678.         if (!is_null($limit))
  679.         {
  680.             $qb->setMaxResults($limit);
  681.         }
  682.         $qb->groupBy('pv.id');
  683.         return  $qb->getQuery()->getResult();
  684.     }
  685.     public function getProductVariantPriceGross(string $productVariantNoComplete): ?float
  686.     {
  687.         try
  688.         {
  689.             return $this->createQueryBuilder('pv')
  690.                 ->select('pv.priceGross')
  691.                 ->where('pv.productVariantNoComplete = :noComplete')
  692.                 ->setParameter('noComplete'$productVariantNoComplete)
  693.                 ->setMaxResults(1)
  694.                 ->getQuery()
  695.                 ->getSingleScalarResult();
  696.         }
  697.         catch (\Exception $e)
  698.         {
  699.             return null;
  700.         }
  701.     }
  702.     public function findByUserAccessForAjaxFilter($query, array $accessProductVariants = []): Query
  703.     {
  704.         $qb $this->createQueryBuilder('pv')
  705.             ->select("distinct pv.id, CONCAT(pv.tradeName, ' ', pv.productVariantNoComplete) as text")
  706.             ->leftJoin('pv.physicalVariant''physicalVariant')
  707.             ->andWhere('pv.productVariantNoComplete in (:accessProductVariants)')
  708.             ->andWhere('physicalVariant.id IS NULL')
  709.             ->setParameter('accessProductVariants'$accessProductVariants);
  710.         if (!empty($query)) {
  711.             $qb->andWhere('pv.tradeName like :enteredProductName')
  712.                 ->setParameter('enteredProductName''%'.$query.'%');
  713.         }
  714.         return $qb->getQuery();
  715.     }
  716.     public function findAllWithTargetVariant(): array
  717.     {
  718.         return $this->createQueryBuilder('pv')
  719.             ->where('pv.targetVariant IS NOT NULL')
  720.             ->getQuery()
  721.             ->getResult();
  722.     }
  723.     public function findByBcItemNoAndPositionType(string $bcItemNostring $bcPositionType): array
  724.     {
  725.         $itemEscaped    preg_quote($bcItemNonull);
  726.         $posTypeEscaped preg_quote($bcPositionTypenull);
  727.         $pattern '^' $itemEscaped '/([^/]+/)?' $posTypeEscaped '$';
  728.         return $this->createQueryBuilder('pv')
  729.             ->where('REGEXP(pv.productVariantNoComplete, :pattern) = 1')
  730.             ->setParameter('pattern'$pattern)
  731.             ->getQuery()
  732.             ->getResult();
  733.     }
  734. }