Files
kupshop/bundles/External/FlexiBeeBundle/Synchronizers/PriceListSynchronizer.php
2025-08-02 16:30:27 +02:00

146 lines
4.5 KiB
PHP

<?php
declare(strict_types=1);
namespace External\FlexiBeeBundle\Synchronizers;
use External\FlexiBeeBundle\AbraFlexiTypes\Odberatel;
use KupShop\PricelistBundle\Util\PriceListWorker;
use Query\Operator;
use Symfony\Contracts\Service\Attribute\Required;
class PriceListSynchronizer extends BaseSynchronizer
{
protected static string $type = 'pricelist';
protected static ?string $evidenceClass = Odberatel::class;
protected PriceListWorker $priceListWorker;
#[Required]
final public function setPriceListWorker(PriceListWorker $priceListWorker): void
{
$this->priceListWorker = $priceListWorker;
}
public function syncSingleItem(int $id, ?int $flexiId = null): void
{
$flexiId ??= $this->flexiBeeUtil->getProductFlexiId($id);
if (!$flexiId) {
return;
}
foreach ($this->flexiBeeApi->getPricelistPrices(flexiProductIds: [$flexiId]) as $item) {
$this->processItem($item);
}
}
protected function processItem(array $item): void
{
// zajimaji nas jen zaznamy s nastavenou Cenikovou skupinou, protoze bez toho nepozname o ktery cenik se jedna
if (empty($item['skupCen']) || empty($item['skupCen']->ref)) {
return;
}
$flexiId = $this->flexiBeeUtil->getFlexiIdFromRef($item['skupCen']->ref);
if (!in_array($flexiId, $this->configuration->getEnabledPricelists())
&& !in_array(0, $this->configuration->getEnabledPricelists())) {
return;
}
if (!($priceListId = $this->flexiBeeUtil->getMapping(static::getType(), $flexiId))) {
$priceListId = $this->createOrAssignPriceList($flexiId, $item);
}
$this->updateProductPriceListPrice($priceListId, $this->getInfo($item, 'cenik'), $item['prodejCena']);
}
protected function getItems(?int $lastSyncTime = null): iterable
{
if ($this->mode === self::MODE_NORMAL) {
return parent::getItems($lastSyncTime);
}
if ($this->mode === self::MODE_FULL) {
return $this->flexiBeeApi->getPricelistPrices();
}
return [];
}
protected function createOrAssignPriceList(int $id, array $item): int
{
$name = $this->getInfo($item, 'skupCen');
$currencyCode = $this->flexiBeeUtil->parseFlexiCode($item['mena']?->value) ?? 'CZK';
$priceList = $this->priceListWorker->findPriceList($name, $currencyCode);
if (!$priceList) {
return sqlGetConnection()->transactional(function () use ($id, $name, $currencyCode) {
sqlQueryBuilder()
->insert('pricelists')
->directValues(
[
'name' => $name,
'price_history' => 0,
'currency' => $currencyCode,
]
)
->execute();
$priceListId = (int) sqlInsertId();
$this->flexiBeeUtil->createMapping(static::getType(), $id, $priceListId);
return $priceListId;
});
}
$this->flexiBeeUtil->createMapping(static::getType(), $id, $priceList);
return $priceList;
}
protected function getInfo(array $item, string $key): string
{
return explode(':', $item[$key]->value, 2)[1];
}
protected function updateProductPriceListPrice(int $priceListId, string $productCode, float $price, bool $removeVat = true): void
{
static $productVatCache = [];
if (!($mapping = $this->flexiBeeUtil->findItemByCode($productCode))) {
return;
}
[$productId, $variationId] = $mapping;
$price = \Decimal::create($price, 4);
if ($removeVat) {
if (!($productVatCache[$productId] ?? false)) {
$vat = sqlQueryBuilder()
->select('v.vat')
->from('products', 'p')
->join('p', 'vats', 'v', 'v.id = p.vat')
->where(Operator::equals(['p.id' => $productId]))
->sendToMaster()
->execute()->fetchOne();
if ($vat === false) {
$vat = getVat();
}
$productVatCache[$productId] = toDecimal((float) $vat);
}
$price = $price->removeVat($productVatCache[$productId]);
}
$this->priceListWorker->updatePriceList($priceListId, $productId, $variationId, $price, withDiscountUpdate: false);
}
}