152 lines
5.0 KiB
PHP
152 lines
5.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace External\ZNZBundle\Overrides\Ordering;
|
|
|
|
use External\ZNZBundle\Util\Product\ZNZProductUtil;
|
|
use External\ZNZBundle\Util\ZNZConfiguration;
|
|
use KupShop\CatalogBundle\ProductList\ProductCollection;
|
|
use KupShop\StoresBundle\Utils\StoresInStore;
|
|
use Symfony\Contracts\Service\Attribute\Required;
|
|
|
|
class DeliveryInfo extends \KupShop\OrderingBundle\Util\Order\DeliveryInfo
|
|
{
|
|
#[Required]
|
|
public StoresInStore $storesInStore;
|
|
#[Required]
|
|
public ZNZProductUtil $productUtil;
|
|
#[Required]
|
|
public ZNZConfiguration $configuration;
|
|
|
|
protected function calculateCollectionDate(ProductCollection $productList, \Delivery $delivery, array &$cache): ?\DateTime
|
|
{
|
|
$deliveryDate = parent::calculateCollectionDate($productList, $delivery, $cache);
|
|
|
|
if ($deliveryDate && $delivery->isInPerson() && ($cache['inPersonMinInStore'] ?? false) !== false) {
|
|
if ($cache['inPersonMinInStore'] <= 0) {
|
|
$deliveryDate->add(new \DateInterval('P1D'));
|
|
}
|
|
} else {
|
|
if ($cache['supplierOrderingDate'] ?? null) {
|
|
$deliveryDate = clone $cache['supplierOrderingDate'];
|
|
}
|
|
|
|
if ($days = $this->configuration->getExpeditionClosedDays()) {
|
|
$deliveryDate->add(new \DateInterval('P'.$days.'D'));
|
|
}
|
|
}
|
|
|
|
$delivery->_znzFromDay = $deliveryDate;
|
|
|
|
return $deliveryDate;
|
|
}
|
|
|
|
protected function calculateDeliveryDays(\Delivery $delivery): int
|
|
{
|
|
return $delivery->getDeliveryDays($delivery->_znzFromDay ?? null)['min'] ?? 0;
|
|
}
|
|
|
|
protected function calculateInitialCache(ProductCollection $productList): array
|
|
{
|
|
if (!$productList->count()) {
|
|
return [];
|
|
}
|
|
|
|
$productList->fetchStoresInStore();
|
|
|
|
$stores = array_keys(array_filter($this->storesInStore->getStores(), fn ($x) => !empty($x['id_delivery'])));
|
|
|
|
$minInStore = null;
|
|
foreach ($productList as $product) {
|
|
foreach ($stores as $storeId) {
|
|
$inStore = (float) ($product->storesInStore[$storeId]['in_store'] ?? 0);
|
|
$minInStore = $minInStore ? min($inStore, $minInStore) : $inStore;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'inPersonMinInStore' => $minInStore,
|
|
'supplierOrderingDate' => $this->calculateSupplierOrderDate($productList),
|
|
];
|
|
}
|
|
|
|
private function calculateSupplierOrderDate(ProductCollection $products): ?\DateTime
|
|
{
|
|
$today = new \DateTime();
|
|
$todayIndex = (int) $today->format('N');
|
|
$todayHour = (int) $today->format('H');
|
|
$todayMinute = (int) $today->format('i');
|
|
|
|
$this->productUtil->fetchZNZSuppliersInfo($products);
|
|
|
|
$dates = [];
|
|
// spocitam nejblizsi mozny datum dodani pokud je produkt potreba objednat od dodavatele
|
|
foreach ($products as $product) {
|
|
// pokud nema zadny data o dodavateli, tak skipuju
|
|
if (empty($product->znz_suppliers_info)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($product->znz_suppliers_info as $info) {
|
|
if (empty($info)) {
|
|
continue;
|
|
}
|
|
|
|
$days = explode(',', $info['dnyVTydnu']);
|
|
[$hour, $minute, $_] = array_map('intval', explode(':', $info['prahObjednani']));
|
|
|
|
$orderingToday = false;
|
|
|
|
// zkontroluju, zda se stihne objednat jeste dnes
|
|
if (in_array($todayIndex, $days) && ($todayHour < $hour || ($todayHour == $hour && $todayMinute <= $minute))) {
|
|
$orderingToday = true;
|
|
}
|
|
|
|
// najdu dalsi nejblizsi den, kdy se bude objedavat
|
|
$nextOrderDate = clone $today;
|
|
if (!$orderingToday) {
|
|
$nextOrderDate = $this->getNextOrderDate($days);
|
|
}
|
|
|
|
$minutes = $info['dobaDodani'] * 60;
|
|
$dates[] = $nextOrderDate->modify("+{$minutes} minutes");
|
|
}
|
|
}
|
|
|
|
if (!empty($dates)) {
|
|
return max($dates);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function getNextOrderDate(array $days): \DateTime
|
|
{
|
|
// Get the current day (1 for Monday, 7 for Sunday)
|
|
$currentDay = date('N');
|
|
// Sort days to ensure they are in order
|
|
sort($days);
|
|
|
|
// Create a DateTime object for "now"
|
|
$date = (new \DateTime())->setTime(8, 0);
|
|
|
|
foreach ($days as $day) {
|
|
if ($day > $currentDay) {
|
|
// Calculate the difference in days
|
|
$dayDiff = $day - $currentDay;
|
|
// Modify the DateTime object to the next closest day
|
|
$date->modify("+{$dayDiff} days");
|
|
|
|
return $date;
|
|
}
|
|
}
|
|
|
|
// If the next day is not found in the current week, find the first day in the next week
|
|
$dayDiff = ($days[0] + 7) - $currentDay;
|
|
$date->modify("+{$dayDiff} days");
|
|
|
|
return $date;
|
|
}
|
|
}
|