Files
interblue.pl/modules/x13allegro/classes/php70/Sync/XAllegroSyncPrices.php
2024-10-25 14:16:28 +02:00

327 lines
13 KiB
PHP

<?php
use x13allegro\Json\JsonMapBuilder;
use x13allegro\Api\DataProvider\OfferFeesProvider;
use x13allegro\Api\Model\Command\PriceChange\ModificationType;
use x13allegro\Api\Model\Command\PriceChange\PriceChangeCommand;
use x13allegro\Api\Model\Offers\Enum\SellingModeType;
use x13allegro\Api\Model\Offers\Offer;
use x13allegro\SyncManager\Offer\Price\SyncPriceEnum;
final class XAllegroSyncPrices extends XAllegroSync
{
public static function syncPrices()
{
if (!self::checkPriceUpdate()) {
XAllegroLogger::getInstance()->config(['PRICE_UPDATE' => 'DISABLED']);
return;
}
$auctions = self::getSyncPricesData();
$context = Context::getContext();
foreach ($auctions as $auction)
{
if (!self::changeAccount($auction['id_xallegro_account'])) {
continue;
}
$accountConfiguration = new XAllegroConfigurationAccount($auction['id_xallegro_account']);
$productCustom = new XAllegroProductCustom($auction['id_xallegro_account'], $auction['id_product']);
$productCustom->useGlobalAccountsSettings(true);
$productCustom->setProductAttributeId($auction['id_product_attribute']);
$productCustom->setOriginalProductPrice(XAllegroProduct::getProductStaticPrice(
(int)$auction['id_product'],
(int)$auction['id_product_attribute'],
$context
));
$productCustom->calculatePrice();
if (!Validate::isLoadedObject($context->shop) || $context->shop->id != (int)$auction['id_shop']) {
$context->shop = new Shop($auction['id_shop']);
}
$product_price = XAllegroProduct::calculatePrice($productCustom, $accountConfiguration);
Hook::exec(
'actionX13AllegroProductPriceModifier',
array(
'id_product' => (int) $auction['id_product'],
'id_product_attribute' => (int) $auction['id_product_attribute'],
'id_xallegro_account' => (int) $auction['id_xallegro_account'],
'product_price' => &$product_price,
'auction' => $auction
)
);
if (!(float)$product_price) {
continue;
}
try {
/** @var Offer $offer */
$offer = (new JsonMapBuilder())->build(self::$api->sale()->offers()->getDetails($auction['id_auction']), Offer::class);
// @since 7.0.0
// backward compatibility
if (!$auction['selling_mode']) {
XAllegroAuction::updateAuctionSellingMode($offer->sellingMode->format, $offer->id);
}
}
catch (Exception $ex) {
if ($ex->getCode() == 404) {
XAllegroAuction::archiveAuctions([$auction['id_auction']]);
}
continue;
}
// if offer is in AUCTION mode, and price buy now is 0
// skip update
if ($offer->sellingMode->format != SellingModeType::BUY_NOW
&& (!$offer->sellingMode->price || $offer->sellingMode->price->amount == 0)
) {
continue;
}
// Update auction price if there is none
$auction_price = $auction['price_buy_now'];
if (!(float)$auction_price) {
$auction_price = $offer->sellingMode->price->amount;
}
// Check for auctions with special prices from Allegro,
// if there is ongoing campaign with special price
// for this product and this auction we should not change price
if ((int) $accountConfiguration->get('AUCTION_CHECK_BADGES', true)) {
$hasActiveCampaing = false;
try {
$offerCampaings = self::$api->sale()->badges()->getBadges($auction['id_auction']);
if (!empty($offerCampaings->badges)) {
foreach ($offerCampaings->badges as $offerCampaign) {
if ($offerCampaign->process->status == 'ACTIVE') {
$hasActiveCampaing = true;
break;
}
}
}
}
catch (Exception $ex) {
continue;
}
if ($hasActiveCampaing) {
continue;
}
}
if ($auction['account_sync_price'] === null) {
if ($auction['account_all_sync_price'] === null) {
$update = (int)$auction['configuration_sync_price'];
} else {
$update = (int)$auction['account_all_sync_price'];
}
} else {
$update = (int)$auction['account_sync_price'];
}
$auction_price -= $auction['fees'];
// Get fees
$calculatedFees = 0;
if (abs($auction_price - $product_price) > 0.000001) {
$offer->sellingMode->price->amount = $product_price;
$auctionCalculateFees = $accountConfiguration->get('AUCTION_CALCULATE_FEES', true);
if ($auctionCalculateFees == 1 || $auctionCalculateFees == 2 && !$productCustom->hasAnyPriceImpact()) {
$feesProvider = new OfferFeesProvider(self::$api, self::$account);
$calculatedFees = $feesProvider->getOfferFees($offer);
}
$product_price += $calculatedFees;
XAllegroAuction::updateAuctionFees($calculatedFees, $auction['id_auction']);
}
if (($update == SyncPriceEnum::FULL && abs($auction_price - $product_price) > 0.000001)
|| ($update == SyncPriceEnum::ONLY_UP && (float)$auction_price < (float)$product_price)
|| ($update == SyncPriceEnum::ONLY_DOWN && (float)$auction_price > (float)$product_price)
) {
self::changePrice($auction['id_auction'], (float)$auction_price, (float)$product_price, $calculatedFees);
}
}
}
private static function changePrice($id_auction, $auction_price, $product_price, $fees = 0)
{
/** @var PriceChangeCommand $object */
$object = (new JsonMapBuilder('Command/PriceChangeCommand'))->map(new PriceChangeCommand());
$object->offerCriteria()->offers($id_auction);
$object->modification->type = ModificationType::FIXED_PRICE;
$object->modification->price->amount = $product_price;
$targetProductPrice = $product_price;
if ($auction_price < $product_price) {
$diff = abs($auction_price - $product_price);
if ($auction_price <= 50 && $diff > 100) {
$object->modification->type = ModificationType::INCREASE_PRICE;
$object->modification->value->amount = 100;
$product_price = $auction_price + 100;
}
else if ($auction_price > 50 && $diff > $auction_price) {
$object->modification->type = ModificationType::INCREASE_PERCENTAGE;
$object->modification->percentage = 200;
$product_price = $auction_price + ($auction_price * 200 / 100);
}
}
if ($product_price > $targetProductPrice) {
if ($object->modification->type == ModificationType::INCREASE_PERCENTAGE) {
$object->modification->type = ModificationType::FIXED_PRICE;
$object->modification->price->amount = $targetProductPrice;
}
$product_price = $targetProductPrice;
}
$commandId = self::$api->generateUUID();
try {
self::$api
->sale()
->commands()
->priceChange()
->setCommand($object)
->executeCommand($commandId);
XAllegroLogger::getInstance()
->account(self::$account->id)
->offer($id_auction)
->api('put', 'price-change-command', [
'commandId' => $commandId,
'old' => $auction_price,
'old_with_fees' => $auction_price + $fees,
'new' => $product_price,
'fees' => $fees,
'modification' => $object->modification,
]);
$task = new XAllegroTask();
$task->id_xallegro_account = self::$account->id;
$task->id_command = self::$api->getLastUUID();
$task->id_auction = (float)$id_auction;
$task->type = XAllegroTask::TYPE_PRICE;
$task->method = XAllegroTask::METHOD_SYNC;
$task->value = $product_price;
$task->add();
}
catch (Exception $ex) {
if ($ex->getCode() == 404) {
XAllegroAuction::closeAuctions([$id_auction], 'offer-not-found');
}
}
}
private static function getSyncPricesData()
{
$count = XAllegroAuction::countActiveAuctions();
if (!$count) {
return array();
}
$offset = (int)XAllegroConfiguration::get('PRICE_UPDATE_OFFSET');
$limit = (int)XAllegroConfiguration::get('PRICE_UPDATE_CHUNK');
$result = Db::getInstance()->executeS('
SELECT
a.`id_xallegro_account`,
a.`id_auction`,
a.`id_shop`,
a.`id_product`,
a.`id_product_attribute`,
a.`selling_mode`,
a.`price_buy_now`,
a.`fees`,
xcp_single.`sync_price` as `account_sync_price`,
xcp_all.`sync_price` as `account_all_sync_price`,
configuration.`configuration_sync_price`
FROM `' . _DB_PREFIX_ . 'xallegro_auction` a
JOIN `' . _DB_PREFIX_ . 'xallegro_account` ac
ON (a.`id_xallegro_account` = ac.`id_xallegro_account`)
INNER JOIN (
SELECT xca.`id_account`,
CASE WHEN
xca.`value` = "' . pSQL(XAllegroConfigurationAccount::GLOBAL_OPTION) . '"
THEN (
SELECT xc.`value`
FROM `' . _DB_PREFIX_ . 'xallegro_configuration` xc
WHERE xc.`name` = "PRICE_UPDATE"
)
ELSE xca.`value` END as `configuration_sync_price`
FROM `' . _DB_PREFIX_ . 'xallegro_configuration_account` xca
JOIN `' . _DB_PREFIX_ . 'xallegro_account` ac
ON (ac.`id_xallegro_account` = xca.`id_account`)
WHERE xca.`name` = "PRICE_UPDATE"
AND ac.`active` = 1
) configuration
ON (configuration.`id_account` = a.`id_xallegro_account`)
LEFT JOIN `' . _DB_PREFIX_ . 'xallegro_custom_product` xcp_all
ON (a.`id_product` = xcp_all.`id_product`
AND xcp_all.`id_xallegro_account` = 0)
LEFT JOIN `' . _DB_PREFIX_ . 'xallegro_custom_product` xcp_single
ON (a.`id_product` = xcp_single.`id_product`
AND a.`id_xallegro_account` = xcp_single.`id_xallegro_account`)
LEFT JOIN `' . _DB_PREFIX_ . 'xallegro_task` xt
ON (a.`id_auction` = xt.`id_auction`)
WHERE a.`closed` = 0
AND a.`id_auction` > 0
AND a.`id_xallegro_account` > 0
AND ac.`active` = 1
AND (
CASE
WHEN xcp_single.`sync_price` IS NOT NULL THEN xcp_single.`sync_price`
WHEN xcp_all.`sync_price` IS NOT NULL THEN xcp_all.`sync_price`
ELSE configuration.`configuration_sync_price`
END
) > 0
AND ((xt.`type` != "' . pSQL(XAllegroTask::TYPE_PRICE) .'" AND xt.`type` != "' . pSQL(XAllegroTask::TYPE_PUBLICATION) .'")
OR xt.`id_xallegro_task` IS NULL)
GROUP BY a.`id_auction`
ORDER BY a.`id_xallegro_auction`
LIMIT ' . $offset . ', ' . $limit
);
$offset += $limit;
XAllegroConfiguration::updateValue('PRICE_UPDATE_OFFSET', ($offset >= $count ? 0 : $offset));
return $result ?: [];
}
/**
* @return bool
*/
private static function checkPriceUpdate()
{
$accountOption = (int)Db::getInstance()->getValue('
SELECT COUNT(*)
FROM `' . _DB_PREFIX_ . 'xallegro_configuration_account`
WHERE `name` = "PRICE_UPDATE"
AND `value` != "' . pSQL(XAllegroConfigurationAccount::GLOBAL_OPTION) . '"
AND `value` > 0'
);
$productOption = (int)Db::getInstance()->getValue('
SELECT COUNT(*)
FROM `' . _DB_PREFIX_ . 'xallegro_custom_product`
WHERE `sync_price` > 0'
);
return (int)XAllegroConfiguration::get('PRICE_UPDATE') || $accountOption || $productOption;
}
}