【EC-CUBE4】価格を少数第二位まで登録する

スポンサーリンク
スポンサーリンク

卸価格で少数第二位まで使用する要件が上がった。

こんにちは!@vVv_kenshi_vVvです!

スポンサーリンク

実装できるか調査

dtb_product_classのprice02に小数点が登録できるのは把握していた。

通過設定を変更

プログラムを調査していると、envの設定を変更すれば登録できるようになる事がわかった。

デフォルト(未定義):ECCUBE_CURRENCY=JPY

ドルへ変更:ECCUBE_CURRENCY=USD

管理画面:商品登録で少数第二位まで登録可能になった。

price01, price02両方ともに影響する。

各所円マークがドルマークへ変更される

price02のみ使用したい

PriceTypeのSCALEで、小数点以下の桁数を制御しているのがわかった。

ProductClassTypeExtensionを作成

app/Customize/Form/Extension/Admin/ProductClassTypeExtension.php

PHP
<?php
/**
 * price02へWholesalePriceTypeを適用する
 */
namespace Customize\Form\Extension\Admin;
use Customize\Form\Type\WholesalePriceType;
use Eccube\Form\Type\Admin\ProductClassType;
use Symfony\Component\Form\AbstractTypeExtension;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Common\EccubeConfig;
use Eccube\Entity\ClassCategory;
use Eccube\Form\DataTransformer;
use Eccube\Form\Type\Master\DeliveryDurationType;
use Eccube\Form\Type\Master\SaleTypeType;
use Eccube\Form\Type\PriceType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
class ProductClassTypeExtension extends AbstractTypeExtension
{
    /**
     * @var EntityManagerInterface
     */
    protected $entityManager;
    /**
     * @var EccubeConfig
     */
    protected $eccubeConfig;
    /**
     * ProductClassType constructor.
     *
     * @param EntityManagerInterface $entityManager
     */
    public function __construct(
        EntityManagerInterface $entityManager,
        EccubeConfig $eccubeConfig
    ) {
        $this->entityManager = $entityManager;
        $this->eccubeConfig = $eccubeConfig;
    }
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('code', TextType::class, [
                'required' => false,
                'constraints' => [
                    new Assert\Length([
                        'max' => $this->eccubeConfig['eccube_stext_len'],
                    ]),
                ],
            ])
            ->add('stock', NumberType::class, [
                'required' => false,
                'constraints' => [
                    new Assert\Regex([
                        'pattern' => "/^\d+$/u",
                        'message' => 'form_error.numeric_only',
                    ]),
                ],
            ])
            ->add('stock_unlimited', CheckboxType::class, [
                'label' => 'admin.product.stock_unlimited__short',
                'value' => '1',
                'required' => false,
            ])
            ->add('sale_limit', NumberType::class, [
                'required' => false,
                'constraints' => [
                    new Assert\Length([
                        'max' => 10,
                    ]),
                    new Assert\GreaterThanOrEqual([
                        'value' => 1,
                    ]),
                    new Assert\Regex([
                        'pattern' => "/^\d+$/u",
                        'message' => 'form_error.numeric_only',
                    ]),
                ],
            ])
            ->add('price01', PriceType::class, [
                'required' => false,
            ])
            ->add('price02', WholesalePriceType::class, [
            ])
            ->add('tax_rate', TextType::class, [
                'required' => false,
                'constraints' => [
                    new Assert\Range(['min' => 0, 'max' => 100]),
                    new Assert\Regex([
                        'pattern' => "/^\d+(\.\d+)?$/",
                        'message' => 'form_error.float_only',
                    ]),
                ],
            ])
            ->add('delivery_fee', PriceType::class, [
                'required' => false,
            ])
            ->add('sale_type', SaleTypeType::class, [
                'multiple' => false,
                'expanded' => false,
                'constraints' => [
                    new Assert\NotBlank(),
                ],
            ])
            ->add('delivery_duration', DeliveryDurationType::class, [
                'required' => false,
                'placeholder' => 'common.select__unspecified',
            ])
            ->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
                $form = $event->getForm();
                $data = $form->getData();
                if (empty($data['stock_unlimited']) && is_null($data['stock'])) {
                    $form['stock_unlimited']->addError(new FormError(trans('admin.product.product_class_set_stock_quantity')));
                }
            });
        $transformer = new DataTransformer\EntityToIdTransformer($this->entityManager, ClassCategory::class);
        $builder
            ->add($builder->create('ClassCategory1', HiddenType::class)
                ->addModelTransformer($transformer)
            )
            ->add($builder->create('ClassCategory2', HiddenType::class)
                ->addModelTransformer($transformer)
            );
    }
    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'Eccube\Entity\ProductClass',
        ]);
    }
    /**
     * {@inheritdoc}
     */
    public static function getExtendedTypes(): iterable
    {
        return [ProductClassType::class];
    }
}

PriceTypeをコピーして、SCALEを定数で2に設定したWholesalePriceTypeを作成

ファイルパス:app/Customize/Form/Type/WholesalePriceType.php

PHP
<?php
/**
 * 卸価格:price02専用Formクラス
 * 小数点第2位まで、登録できるように調整
 * 通貨タイプ:デフォルトJPYの場合は、小数点の桁数は0に設定されている
 */
namespace Customize\Form\Type;
use Eccube\Common\EccubeConfig;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Range;
class WholesalePriceType extends AbstractType
{
    const SCALE = 2;
    /**
     * @var EccubeConfig
     */
    protected $eccubeConfig;
    /**
     * @var ContainerInterface
     */
    protected $container;
    /**
     * PriceType constructor.
     *
     * @param EccubeConfig $eccubeConfig
     */
    public function __construct(EccubeConfig $eccubeConfig, ContainerInterface $container)
    {
        $this->eccubeConfig = $eccubeConfig;
        $this->container = $container;
    }
    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $currency = $this->container->getParameter('currency');
        $scale = self::SCALE;
        $max = $this->eccubeConfig['eccube_price_max'];
        $min = -$max;
        $constraints = function (Options $options) use ($max, $min) {
            $constraints = [];
            // requiredがtrueに指定されている場合, NotBlankを追加
            if (isset($options['required']) && true === $options['required']) {
                $constraints[] = new NotBlank();
            }
            if (isset($options['accept_minus']) && true === $options['accept_minus']) {
                $constraints[] = new Range([
                    'min' => $min,
                    'max' => $max,
                ]);
            } else {
                $constraints[] = new Range(['min' => 0, 'max' => $max]);
            }
            return $constraints;
        };
        $resolver->setDefaults(
            [
                'currency' => $currency,
                'scale' => $scale,
                'grouping' => true,
                'constraints' => $constraints,
                'accept_minus' => false, // マイナス値を許容するかどうか
            ]
        );
    }
    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return MoneyType::class;
    }
    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'price';
    }
}
タイトルとURLをコピーしました