卸価格で少数第二位まで使用する要件が上がった。
[temp id=3]
実装できるか調査
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' ;
}
}