Files
2025-08-02 16:30:27 +02:00

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;
}
}