92 lines
2.7 KiB
PHP
92 lines
2.7 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\Catalog\Model;
|
|
|
|
use Esun\Catalog\Setup\Patch\Data\AddMixStepPricesAttribute;
|
|
use Magento\Catalog\Model\Product;
|
|
use Magento\Customer\Model\Group;
|
|
use Magento\Framework\Serialize\Serializer\Json;
|
|
|
|
class MixStepPriceProvider
|
|
{
|
|
public function __construct(private readonly Json $json)
|
|
{
|
|
}
|
|
|
|
public function getRules(Product $parentProduct, int $customerGroupId): array
|
|
{
|
|
$rows = $parentProduct->getData(AddMixStepPricesAttribute::ATTRIBUTE_CODE);
|
|
if (is_string($rows) && trim($rows) !== '') {
|
|
try {
|
|
$rows = $this->json->unserialize($rows);
|
|
} catch (\InvalidArgumentException) {
|
|
$rows = [];
|
|
}
|
|
}
|
|
if (!is_array($rows)) {
|
|
return [];
|
|
}
|
|
|
|
$rules = [];
|
|
foreach ($rows as $row) {
|
|
if (!is_array($row) || (isset($row['enabled']) && !(bool)$row['enabled'])) {
|
|
continue;
|
|
}
|
|
|
|
$ruleGroupId = (int)($row['customer_group_id'] ?? Group::CUST_GROUP_ALL);
|
|
if ($ruleGroupId !== Group::CUST_GROUP_ALL && $ruleGroupId !== $customerGroupId) {
|
|
continue;
|
|
}
|
|
|
|
$quantity = (int)($row['qty'] ?? 0);
|
|
$value = (float)($row['value'] ?? 0);
|
|
$priceType = (string)($row['price_type'] ?? 'percent');
|
|
if ($quantity < 2 || $value <= 0 || !in_array($priceType, ['percent', 'fixed'], true)) {
|
|
continue;
|
|
}
|
|
|
|
$specificity = $ruleGroupId === $customerGroupId ? 1 : 0;
|
|
if (isset($rules[$quantity]) && $rules[$quantity]['specificity'] > $specificity) {
|
|
continue;
|
|
}
|
|
$rules[$quantity] = [
|
|
'qty' => $quantity,
|
|
'price_type' => $priceType,
|
|
'value' => $value,
|
|
'specificity' => $specificity,
|
|
];
|
|
}
|
|
|
|
ksort($rules);
|
|
return array_map(static function (array $rule): array {
|
|
unset($rule['specificity']);
|
|
return $rule;
|
|
}, array_values($rules));
|
|
}
|
|
|
|
public function getActiveRule(array $rules, float $quantity): ?array
|
|
{
|
|
$activeRule = null;
|
|
foreach ($rules as $rule) {
|
|
if ($quantity >= (float)$rule['qty']) {
|
|
$activeRule = $rule;
|
|
}
|
|
}
|
|
|
|
return $activeRule;
|
|
}
|
|
|
|
public function calculateUnitPrice(float $basePrice, ?array $rule): float
|
|
{
|
|
if (!$rule) {
|
|
return max(0, $basePrice);
|
|
}
|
|
if (($rule['price_type'] ?? '') === 'fixed') {
|
|
return max(0, min($basePrice, (float)$rule['value']));
|
|
}
|
|
|
|
return max(0, $basePrice * (1 - ((float)$rule['value'] / 100)));
|
|
}
|
|
}
|