Files
esun3d/app/code/Esun/Catalog/Model/MixStepPriceProvider.php
T
2026-09-15 10:35:56 +08:00

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