206 lines
7.5 KiB
PHP
206 lines
7.5 KiB
PHP
<?php
|
|
|
|
namespace KupShop\OrderingBundle\Util\Delivery;
|
|
|
|
use KupShop\CatalogBundle\Entity\Wrapper\ProductWrapper;
|
|
use KupShop\CatalogBundle\ProductList\ProductCollection;
|
|
use KupShop\ContentBundle\Entity\Wrapper\ProductUnifiedWrapper;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
use KupShop\OrderingBundle\Entity\Purchase\ProductPurchaseItem;
|
|
use KupShop\OrderingBundle\Entity\Purchase\PurchaseState;
|
|
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;
|
|
use Product;
|
|
use Variation;
|
|
|
|
class DeliveryDatesService
|
|
{
|
|
/**
|
|
* Return list of deliveries.
|
|
* Each delivery has new property `date`.
|
|
* Added date is minimum for that delivery computed across variations.
|
|
*/
|
|
public function calcTotalDeliveryListForVariations(array $activeDeliveries, $deliveriesDates): array
|
|
{
|
|
// I need to clone the list because its items are modified inside the loop
|
|
// and the input list needs to be untouched. (The modification is required by
|
|
// backward compatibility)
|
|
$deliveriesList = array_map(fn ($i) => clone $i, $activeDeliveries);
|
|
|
|
foreach ($deliveriesList as $deliveryId => $delivery) {
|
|
$minDeliveryDate = array_reduce($deliveriesDates, function ($min, $deliveries) use ($deliveryId) {
|
|
$delivery = $deliveries[$deliveryId];
|
|
$date = $delivery['date'];
|
|
|
|
return is_null($min)
|
|
? $date
|
|
: min($min, $date);
|
|
});
|
|
|
|
$delivery->date = $minDeliveryDate;
|
|
}
|
|
|
|
return $deliveriesList;
|
|
}
|
|
|
|
/**
|
|
* Returns array of three items:
|
|
* - Array of results for each variation. Result is array with the same structure as for the product.
|
|
* - Minimal in person date, computed across all variations
|
|
* - Minimal delivery date, computed across all variations.
|
|
*/
|
|
public function calcResultsForEachVariation(
|
|
array $deliveriesDates,
|
|
?array $deliveries,
|
|
$minDeliveryPrice,
|
|
array $variationResults,
|
|
$dateMinInPerson,
|
|
$dateMinDelivery,
|
|
): array {
|
|
foreach ($deliveriesDates as $variationId => $deliveriesDate) {
|
|
list($variationDateMinInPerson, $variationDateMinDelivery, $variationDeliveriesList) = $this->calcMinDeliveryDates($deliveries,
|
|
$deliveriesDate);
|
|
|
|
$variationResults[explode('/', $variationId)[1]] = [
|
|
'list' => $variationDeliveriesList,
|
|
'min' => [
|
|
'in_person' => $variationDateMinInPerson,
|
|
'delivery' => $variationDateMinDelivery,
|
|
'total' => min($variationDateMinInPerson, $variationDateMinDelivery),
|
|
'deliveryPrice' => $minDeliveryPrice,
|
|
],
|
|
];
|
|
|
|
$dateMinInPerson = is_null($dateMinInPerson)
|
|
? $variationDateMinInPerson
|
|
: min($dateMinInPerson, $variationDateMinInPerson);
|
|
|
|
$dateMinDelivery = is_null($dateMinDelivery)
|
|
? $variationDateMinDelivery
|
|
: min($dateMinDelivery, $variationDateMinDelivery);
|
|
}
|
|
|
|
return [$variationResults, $dateMinInPerson, $dateMinDelivery];
|
|
}
|
|
|
|
/**
|
|
* Returns array of three items:
|
|
* - Minimal in person date, computed across all in the person `deliveries`
|
|
* - Minimal delivery date, computed across all not in the person `deliveries`
|
|
* - List of all the deliveries with added property `date`. The date is minimum across all the deliveries.
|
|
*/
|
|
public function calcMinDeliveryDates(?array $deliveries, array $deliveriesDates): array
|
|
{
|
|
// I need to clone the list because its items are modified inside the loop
|
|
// and the input list needs to be untouched. (The modification is required by
|
|
// backward compatibility)
|
|
$deliveriesList = array_map(fn ($i) => clone $i, $deliveries);
|
|
|
|
$dateMinInPerson = null;
|
|
$dateMinDelivery = null;
|
|
$groupsByType = [];
|
|
|
|
foreach ($deliveriesList as $id => $delivery) {
|
|
$date = $deliveriesDates[$id]['date'];
|
|
if (!$date) {
|
|
continue;
|
|
}
|
|
|
|
if ($delivery->isInPerson()) {
|
|
$dateMinInPerson = is_null($dateMinInPerson)
|
|
? $date
|
|
: min($dateMinInPerson, $date);
|
|
} else {
|
|
$dateMinDelivery = is_null($dateMinDelivery)
|
|
? $date
|
|
: min($dateMinDelivery, $date);
|
|
}
|
|
|
|
$delivery->date = $date;
|
|
$groupsByType[$delivery->getType()][$id] = &$delivery;
|
|
unset($delivery);
|
|
}
|
|
|
|
return [$dateMinInPerson, $dateMinDelivery, $deliveriesList, $groupsByType];
|
|
}
|
|
|
|
public function calcMinDeliveryPrice(?array $deliveries)
|
|
{
|
|
return array_reduce($deliveries, function ($minDeliveryPrice, $delivery) {
|
|
if (!$delivery->isInPerson()
|
|
&& ($minDeliveryPrice === null || $delivery->getPrice()->getValue()->lowerThan($minDeliveryPrice->getValue()))) {
|
|
$minDeliveryPrice = $delivery->getPrice();
|
|
}
|
|
|
|
return $minDeliveryPrice;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param \Product|ProductWrapper $product
|
|
*/
|
|
public function initPurchaseState($product, $price): PurchaseState
|
|
{
|
|
$purchaseState = new PurchaseState([
|
|
new ProductPurchaseItem($product->id, $product->variationId ?? null, 1, $price, null),
|
|
]);
|
|
/** @var PurchaseUtil $purchaseUtil */
|
|
$purchaseUtil = ServiceContainer::getService(PurchaseUtil::class);
|
|
$purchaseUtil->recalculateTotalPrices($purchaseState);
|
|
|
|
return $purchaseState;
|
|
}
|
|
|
|
/**
|
|
* @param \Product|ProductWrapper|null $product
|
|
*/
|
|
public function initializeProductCollection($product, bool $variations): ProductCollection
|
|
{
|
|
$productList = new ProductCollection();
|
|
|
|
if ($product) {
|
|
if ($variations) {
|
|
$productList->setEntityType(\FilterParamsBase::ENTITY_VARIATION);
|
|
if ($product instanceof ProductUnifiedWrapper) {
|
|
$product = $product->getObject()->getProduct();
|
|
}
|
|
foreach ($product->variationsIds as $variationId) {
|
|
$variation = new \Variation($product->id, $variationId);
|
|
$variation->createFromDB();
|
|
$productList["{$product->id}/{$variationId}"] = $variation;
|
|
}
|
|
} else {
|
|
if ($product instanceof \Variation) {
|
|
$productList->setEntityType(\FilterParamsBase::ENTITY_VARIATION);
|
|
$productList["{$product->id}/{$product->variationId}"] = $product;
|
|
} else {
|
|
$productList[$product->id] = $product;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $productList;
|
|
}
|
|
|
|
public function filterDeliveries(?array $deliveries, bool $only_supported, $productPrice, ?PurchaseState $purchaseState): array
|
|
{
|
|
$activeDeliveries = [];
|
|
foreach ($deliveries as $id => $delivery) {
|
|
if ($only_supported) {
|
|
if (!$delivery->accept($productPrice, false)) {
|
|
continue;
|
|
}
|
|
if ($purchaseState) {
|
|
try {
|
|
$delivery->checkRestrictions($purchaseState);
|
|
} catch (\Exception $exception) {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
$activeDeliveries[$id] = $delivery;
|
|
}
|
|
|
|
return $activeDeliveries;
|
|
}
|
|
}
|