228 lines
6.7 KiB
PHP
228 lines
6.7 KiB
PHP
<?php
|
|
|
|
namespace External\VarioBundle\Synchronizers;
|
|
|
|
use KupShop\PricelistBundle\Util\PriceListWorker;
|
|
use Query\Operator;
|
|
|
|
class PriceSynchronizer extends BaseSynchronizer
|
|
{
|
|
protected static $type = 'otPrice';
|
|
protected static $batch = 100;
|
|
protected static $maxBatches = 50;
|
|
|
|
protected $logging = true;
|
|
|
|
protected $fields = [
|
|
'ProductID' => 'item',
|
|
];
|
|
|
|
/** @var PriceListWorker */
|
|
protected $priceListWorker;
|
|
|
|
/** @required */
|
|
public function setPriceListWorker(PriceListWorker $priceListWorker): void
|
|
{
|
|
$this->priceListWorker = $priceListWorker;
|
|
}
|
|
|
|
public function getEshopID($objectID)
|
|
{
|
|
if (!($productId = $this->helper->getMapping('vario_products', $objectID))) {
|
|
return null;
|
|
}
|
|
|
|
return (int) $productId;
|
|
}
|
|
|
|
public function syncItem($varioProductId, $productId, $column, \stdClass $item)
|
|
{
|
|
$this->helper->addDelayedUpdate(
|
|
$this->helper->trimVarioId($varioProductId),
|
|
ProductSynchronizer::getType()
|
|
);
|
|
}
|
|
|
|
public function syncPrices(array $items, int $productId): void
|
|
{
|
|
$prices = [];
|
|
// preprocess prices
|
|
foreach ($items as $item) {
|
|
if (!($variationId = $this->getVariationId($item))) {
|
|
$variationId = 0;
|
|
}
|
|
|
|
$prices[$this->helper->trimVarioId($item->PriceID)][$variationId] = $item;
|
|
}
|
|
|
|
$priceListsConfig = $this->config->getPriceLists();
|
|
|
|
// process default price
|
|
foreach ($this->getPricesData($productId, $priceListsConfig['default'], $prices) as $variationId => [$price, $discount]) {
|
|
$this->syncGlobalPrice($productId, $variationId, $price, $discount);
|
|
}
|
|
|
|
// process price list prices
|
|
foreach ($priceListsConfig['others'] ?? [] as $config) {
|
|
[$priceListVarioId, $_] = $config;
|
|
|
|
if (!($priceListId = $this->getPriceList($priceListVarioId))) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($this->getPricesData($productId, $config, $prices) as $variationId => [$price, $discount]) {
|
|
$this->priceListWorker->updatePriceList(
|
|
$priceListId,
|
|
$productId,
|
|
$variationId === 0 ? null : $variationId,
|
|
$price,
|
|
$discount
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function getPricesData(int $productId, array $config, array $prices): array
|
|
{
|
|
$priceList = $config[0];
|
|
$discountPriceList = $config[1];
|
|
$withVat = $config[2] ?? true;
|
|
|
|
$result = [];
|
|
foreach ($prices[$priceList] ?? [] as $variationId => $item) {
|
|
$price = toDecimal($item->Value);
|
|
|
|
$priceWithoutVat = $price;
|
|
if ($withVat) {
|
|
$priceWithoutVat = $price->removeVat(
|
|
$this->getProductVat($productId)
|
|
);
|
|
}
|
|
|
|
$discount = \DecimalConstants::zero();
|
|
if ($discountItem = ($prices[$discountPriceList][$variationId] ?? false)) {
|
|
$discountedPrice = toDecimal($discountItem->Value);
|
|
$discount = $price->sub($discountedPrice)->div($price)->mul(\DecimalConstants::hundred());
|
|
}
|
|
|
|
$result[$variationId] = [$priceWithoutVat, $discount];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
protected function getVariationId(\stdClass $item): ?int
|
|
{
|
|
$variationId = null;
|
|
if (!empty($item->VariantID)) {
|
|
$variationId = $this->helper->getMapping('vario_variations', $this->helper->trimVarioId($item->VariantID));
|
|
if (!$variationId) {
|
|
$variationId = null;
|
|
}
|
|
}
|
|
|
|
return $variationId ? (int) $variationId : null;
|
|
}
|
|
|
|
protected function syncGlobalPrice(int $productId, ?int $variationId, \Decimal $price, ?\Decimal $discount = null): void
|
|
{
|
|
if ($variationId) {
|
|
$this->updateSQL('products_variations', ['price' => $price], ['id' => $variationId]);
|
|
} else {
|
|
$update = ['price' => $price];
|
|
if ($discount) {
|
|
$update['discount'] = $discount;
|
|
}
|
|
|
|
$this->updateSQL('products', $update, ['id' => $productId]);
|
|
}
|
|
}
|
|
|
|
private function syncCommonPrice(int $productId, ?int $variationId, \Decimal $price): void
|
|
{
|
|
if ($variationId) {
|
|
$this->updateSQL('products_variations', ['price_common' => $price], ['id' => $variationId]);
|
|
} else {
|
|
$this->updateSQL('products', ['price_common' => $price], ['id' => $productId]);
|
|
}
|
|
}
|
|
|
|
private function calculateDiscount(\Decimal $price, ?\Decimal $priceCommon): \Decimal
|
|
{
|
|
$discount = toDecimal(0);
|
|
|
|
if ($price->isPositive() && $priceCommon && $priceCommon->isPositive()) {
|
|
if (!$price->equals($priceCommon)) {
|
|
$discount = $priceCommon->sub($price)->div($priceCommon)->mul(\DecimalConstants::hundred());
|
|
}
|
|
}
|
|
|
|
return $discount;
|
|
}
|
|
|
|
private function isPriceValid(object $price): bool
|
|
{
|
|
$now = new \DateTime();
|
|
|
|
$validFrom = new \DateTime((string) $price->ValidFrom);
|
|
$validTo = new \DateTime((string) $price->ValidTo);
|
|
|
|
if (($now >= $validFrom || empty($price->ValidFrom))
|
|
&& ($now <= $validTo || empty($price->ValidTo))) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected function getPriceList(string $varioId): ?int
|
|
{
|
|
static $priceLists = [];
|
|
|
|
if (!$priceLists) {
|
|
$priceLists = sqlFetchAll(sqlQueryBuilder()
|
|
->select('id_vario, id_pricelist')
|
|
->from('vario_pricelists')
|
|
->execute(),
|
|
['id_vario' => 'id_pricelist']);
|
|
}
|
|
|
|
if ($priceLists[$varioId] ?? false) {
|
|
return (int) $priceLists[$varioId];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function getProductVat(int $productId): float
|
|
{
|
|
static $vatCache = [];
|
|
|
|
if (!empty($vatCache[$productId])) {
|
|
return $vatCache[$productId];
|
|
}
|
|
|
|
$vat = sqlQueryBuilder()->select('v.vat')
|
|
->from('products', 'p')
|
|
->leftJoin('p', 'vats', 'v', 'v.id = p.vat')
|
|
->where(Operator::equals(['p.id' => $productId]))
|
|
->execute()->fetchColumn();
|
|
|
|
return $vatCache[$productId] = (float) ($vat ?? getVat());
|
|
}
|
|
|
|
protected function postprocess()
|
|
{
|
|
$this->helper->updateProductsPriceToMinFromVariations();
|
|
}
|
|
|
|
protected function getObjectID($item)
|
|
{
|
|
if (empty($item->Data)) {
|
|
return null;
|
|
}
|
|
|
|
return $this->helper->trimVarioId($item->Data->ProductID);
|
|
}
|
|
}
|