<?php
namespace App\Form\Subscriber;
use App\Entity\Company;
use App\Entity\CompanyGroup;
use App\Entity\Order;
use App\Entity\Product;
use App\Entity\User;
use App\Form\Validator\RodneCisloConstraint;
use App\Helper\EnumsHelper;
use App\Helper\EsfHelper;
use App\Repository\CompanyRepository;
use App\Repository\ProductRepository;
use PhpOffice\PhpWord\Shared\Text;
use PhpParser\Node\Expr\BinaryOp\GreaterOrEqual;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Event\PreSetDataEvent;
use Symfony\Component\Form\Event\PreSubmitEvent;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\PercentType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Validator\Constraints\GreaterThan;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
class OrderTypeSubscriber implements EventSubscriberInterface
{
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* @var CompanyRepository
*/
protected $_companyRepository;
/**
* OrderTypeSubscriber constructor.
*/
public function __construct(ProductRepository $productRepository, CompanyRepository $companyRepository)
{
$this->productRepository = $productRepository;
$this->_companyRepository = $companyRepository;
}
public static function getSubscribedEvents(): array
{
return [
FormEvents::PRE_SET_DATA => 'dependsOn',
FormEvents::PRE_SUBMIT => 'dependsOn',
FormEvents::POST_SUBMIT => 'postSubmit'
];
}
public function postSubmit(FormEvent $event)
{
/** @var Order $data */
$data = $event->getData();
if (!$data) return;
$this->reloadProductPrice($data);
}
public function dependsOn(FormEvent $event)
{
/** @var FormInterface $form */
$form = $event->getForm();
/** @var Order $data */
$data = $event->getData();
if (!$data) return;
if (isset($data['idType']) && $data['idType'] == EnumsHelper::OTHER_TYPES) {
$form->add('idTypeOther', TextType::class, [
'required' => true,
'attr' => [
'placeholder' => 'Typ dokladu'
],
'label' => false,
]);
}
$this->personTypeFields(@$data['personType'], $form);
$this->loadProduct($data, $form);
$this->loadCompany($data, $form);
if(isset($data['personType']) && $data['personType'] == 'PO'){
$form->remove('generateDigiSign');
$form->remove('politicallyExposedPerson');
}else{
$form->add('politicallyExposedPerson', CheckboxType::class, [
'label' => 'Jsem politicky exponovanou osobu',
'required' => false,
'attr' => [
// 'data-action' => 'change->order-form#politicallyExposedPerson',
'data-order-form-target' => 'politicallyExposedPerson'
]
]);
}
}
/**
* Set price after submit form - in the case of hack form
*
* @param Order $order
* @throws \Exception
*/
protected function reloadProductPrice(Order $order): void
{
/** @var Product $product */
$product = $order->getProduct();
if ($product && $product instanceof Product) {
$order->setProductPrice($product->getPrice());
$order->setProductTax($product->getTax());
if ($product->getProductType() === EnumsHelper::PRODUCT_TYPE_LOAN) {
} else {
$order->setDueDate($product->getDueDate());
$order->setProductInterest($product->getInterest());
$order->setProductPriceTotal($product->getPrice() * ((float)$order->getProductCount() > 0 ? (float)$order->getProductCount() : 1));
$order->setProductPriceTotalInWords(EsfHelper::convertByIntl($order->getProductPriceTotal()));
// akcie
if ($product->getProductType() === EnumsHelper::PRODUCT_TYPE_STOCK) {
$order->setProductPriceSecondaryTotal($product->getPriceSecondary() * ((float)$order->getProductCount() > 0 ? (float)$order->getProductCount() : 1));
$order->setProductPriceSecondaryTotalInWords(EsfHelper::convertByIntl($order->getProductPriceSecondaryTotal()));
}
}
}
}
/**
* @param Order $data
* @param FormInterface $form
* @throws \Exception
*/
protected function loadProduct($data, FormInterface $form): void
{
$productPriceOptions = [
'required' => false,
'disabled' => true,
'label' => 'Cena produktu'
];
$productInterestOptions = [
'required' => false,
'attr' => [
'placeholder' => 'Výnos'
],
'label' => false
];
$productTaxOptions = [
'required' => true,
'attr' => [
'placeholder' => 'Daň'
],
'label' => false
];
$productPriceTotal = [
'required' => true,
'disabled' => true,
'label' => 'Cena celkem'
];
$productPriceTotalWords = [
'required' => true,
'disabled' => true,
'label' => 'Cena celkem slovy'
];
$form->add('productTax', HiddenType::class, $productTaxOptions)
->add('productInterest', HiddenType::class, $productInterestOptions);
if (isset($data['product']) && false == is_null($data['product']) && $data['product'] != '') {
$product = $this->productRepository->findOneBy(['id' => $data['product']]);
if ($product instanceof Product) {
if ($product->getProductType() === EnumsHelper::PRODUCT_TYPE_LOAN) {
// zapujcka
$form->add('dueDate', DateType::class, [
'required' => false,
'label' => 'Splatnost',
'widget' => 'single_text',
'html5' => false,
'format' => 'dd.MM.yyyy',
'disabled' => false,
// 'data' => $product->getDueDate(),
// 'empty_data' => $product->getDueDate(),
'attr' => [
'placeholder' => 'Splatnost',
'class' => "bg-white",
'data-order-form-target' => 'dueDate',
]
]);
// do policka total ulozim celkove zadanou castku
$productInterestOptions['disabled'] = false;
$productInterestOptions['label'] = 'Úrok';
$productInterestOptions['attr']['placeholder'] = 'Úrok';
$productInterestOptions['attr']['data-action'] = 'input->order-form#percentsInput';
$productPriceTotal['label'] = 'Částka';
$productPriceTotal['disabled'] = false;
$form->add('productPriceTotal', TextType::class, $productPriceTotal)
// produkt interest se zobrazi jako textfield v zapujcce
->add('productInterest', TextType::class, $productInterestOptions)
->add('productCount', HiddenType::class, []);
} else {
$productCountParams = [
'required' => true,
'attr' => [
'placeholder' => '* Počet',
'data-action' => 'change->order-form#productCountChange',
'data-order-form-target' => 'productCount',
'data-min-count' => $product->getMinCount()
],
'label' => false,
];
if((float)$data['productCount'] <= $product->getMinCount()){
// $productCountParams['constraints'] = [];
$productCountParams['attr']['data-min-count'] = $product->getMinCount();
$productCountParams['data'] = $product->getMinCount();
$productCountParams['empty_data'] = $product->getMinCount();
$data['productCount'] = $product->getMinCount();
$productCountParams['constraints'] = [
new GreaterThanOrEqual([
'value' => $product->getMinCount(),
'message' => 'Min. počet je {{ compared_value }} ks'
])
];
}
// dluhopis - default
$productPriceOptions['empty_data'] = $product->getPrice() . EsfHelper::currencyExt($product); // neodeslany form
$productPriceOptions['data'] = $product->getPrice() . EsfHelper::currencyExt($product); // odeslany form
$productInterestOptions['empty_data'] = $product->getInterest();
$productInterestOptions['data'] = $product->getInterest();
$productTaxOptions['empty_data'] = $product->getTax();
$productTaxOptions['data'] = $product->getTax();
$productPriceTotal['empty_data'] = ($product->getPrice() * ((float)$data['productCount'] > 0 ? (float)$data['productCount'] : 1)) . EsfHelper::currencyExt($product);
$productPriceTotal['data'] = ($product->getPrice() * ((float)$data['productCount'] > 0 ? (float)$data['productCount'] : 1)) . EsfHelper::currencyExt($product);
$productPriceTotalWords['empty_data'] = EsfHelper::convertByIntl($productPriceTotal['empty_data']) . ' ' . EsfHelper::currencyExtText($product);
$productPriceTotalWords['data'] = EsfHelper::convertByIntl($productPriceTotal['empty_data']) . ' ' . EsfHelper::currencyExtText($product);
$form->add('productPriceTotalInWords', TextType::class, $productPriceTotalWords)
->add('productPrice', TextType::class, $productPriceOptions)
->add('productPriceTotal', TextType::class, $productPriceTotal);
$form->add('productCount', NumberType::class, $productCountParams);
}
if($product->isUseAdamna()){
$options = $form->getConfig()->getOptions();
$form->add('birthnumber', TextType::class, [
'required' => (boolean)@$options['check_required'],
'label' => false,
'attr' => [
'maxlength' => 11,
'placeholder' => '* Rodné číslo',
'data-order-form-target' => 'birthnumber'
]
]);
}
if($product->isGeneratorSigni() || $product->isUseAdamna()) {
$form->add('generateSigni', CheckboxType::class, [
'required' => false,
'mapped' => false,
'label' => 'Vygenerovat smlouvu a digitálně podepsat přes <a href="www.signi.com" target="_blank">Signi.com</a>',
'label_html' => true,
'attr' => [
'data-order-form-target' => 'generateSigni',
'data-action' => 'change->order-form#changeSigniVsPdf'
],
]);
}
if($product->isGeneratorDigiSign()) {
$form->add('generateDigiSign', CheckboxType::class, [
'required' => false,
'mapped' => false,
'label' => 'Vygenerovat smlouvu a digitálně podepsat přes <a href="www.digisign.org" target="_blank">DigiSign.org</a>',
'label_html' => true,
'attr' => [
'data-order-form-target' => 'generateDigiSign',
'data-action' => 'change->order-form#changeDigiSign'
],
]);
}
if($product->isGeneratorPdf()) {
$form->add('generatePdf', CheckboxType::class, [
'required' => false,
'mapped' => false,
'label' => "Vygenerovat smlouvu a uložit do PDF k manuálnímu podpisu",
'attr' => [
'data-order-form-target' => 'generatePdf',
'data-action' => 'change->order-form#changeSigniVsPdf'
],
]);
}
if($product->getCurrency() != EnumsHelper::CURRENCY_CZK) {
$this->makeFieldRequire($form, 'bankAccount', false);
$this->makeFieldRequire($form, 'bankCode', false, ChoiceType::class);
$this->makeFieldRequire($form, 'swift', true);
$this->makeFieldRequire($form, 'iban', true);
}
// kvuli Adamna IS, protoze potrebuje pro svuj chod rodne cislo, tak to musime osetrit
if($product->isUseAdamna() && $form->has('birthdate')){
// odebereme datum narozeni a misto neho dame rodne cislo
$form->remove('birthdate');
}
}
}
}
protected function makeFieldRequire(FormInterface $form, string $itemName, bool $isRequired, $type = TextType::class){
$options = $form->get($itemName)->getConfig()->getOptions();
if($type == TextType::class) {
$options['attr']['placeholder'] = str_replace('* ', '', $options['attr']['placeholder']);
if ($isRequired == true) {
$options['attr']['placeholder'] = '* ' . $options['attr']['placeholder'];
}
}
if($type == ChoiceType::class) {
$options['placeholder'] = str_replace('* ', '', $options['placeholder']);
if ($isRequired == true) {
$options['placeholder'] = '* ' . $options['placeholder'];
}
}
$options['required'] = $isRequired;
$form->remove($itemName)
->add($itemName, $type, $options);
}
/**
* @param Order $data
* @param FormInterface $form
*/
protected function loadCompany($data, FormInterface $form): void
{
$options = $form->getConfig()->getOptions();
if (isset($data['company']) && false == is_null($data['company']) && $data['company'] != '') {
$companyId = $data['company'];
if ($companyId instanceof Company) {
$companyId = $companyId->getId();
}
$companyRepository = $this->_companyRepository;
$form->add('product', EntityType::class, [
'class' => Product::class,
'label' => false,
'placeholder' => '* Vyberte produkt',
'attr' => [
'data-action' => 'change->order-form#productChange',
'data-order-form-target' => 'product'
],
'choice_label' => function (Product $product) {
return $product->getName();
},
'query_builder' => function (ProductRepository $er) use ($data, $companyId, $options, $companyRepository) {
$qb = $er->createQueryBuilder('pr');
$companyIds = [$companyId];
if(isset($companyId)) {
$companyEnt = $companyRepository->findOneBy(['id' => $companyId]);
if(isset($companyEnt)) {
$companyGroup = $companyEnt->getCompanyGroup();
if(isset($companyGroup)) {
$companiesByGroup = $companyRepository->findBy(['companyGroup' => $companyGroup->getId()]);
foreach ($companiesByGroup as $companyFromGroup) {
$companyIds[] = $companyFromGroup->getId();
}
}
}
}
// volanio api, nacitam pouze produkty pro dan ou spolecnost
$qb->andWhere($qb->expr()->in('pr.company', $companyIds));
$loggedUser = @$options['logged_user'];
// pokud se nejdena o admin, pridavam podminku pouze pro aktivni produkty a nesmazane
if(!(isset($loggedUser) && $loggedUser instanceof User && $loggedUser->hasRole(User::ROLE_ADMIN))){
// neadmin pouze aktivni
$qb->andWhere($qb->expr()->eq('pr.active', 1));
}
return $qb;
}
]);
if (isset($data['product']) && false == is_null($data['product']) && $data['product'] != '') {
$product = $data['product'];
if ($options['api_complete'] == true) {
$attr['data-action'] = 'change->order-form#reload';
$attr['data-order-form-target'] = 'company';
if ($product instanceof Product) {
$form->add('company', EntityType::class, [
'class' => Company::class,
'query_builder' => function (CompanyRepository $companyRepository) use ($product) {
$qb = $companyRepository->createQueryBuilder('c');
return $qb->select('c')
->andWhere($qb->expr()->in('c.id', $product->getCompany()->getId()));
},
'choice_label' => function (Company $company) {
return $company->getName();
},
'attr' => $attr,
'placeholder' => 'Vyberte společnost',
'label' => false,
]);
}
}
}
}
}
/**
* @param $personType
* @param FormInterface $form
*/
protected function personTypeFields($personType, FormInterface $form): void
{
$options = $form->getConfig()->getOptions();
if ($personType == 'FO' || is_null($personType)) {
$this->fPerson($form, $options);
if($form->has('businessmanRegistrationPlace')) { $form->remove('businessmanRegistrationPlace'); }
if($form->has('businessmanRegistrationNumber')) { $form->remove('businessmanRegistrationNumber'); }
if($form->has('ic')) { $form->remove('ic'); }
if($form->has('dic')) { $form->remove('dic'); }
if($form->has('companyRegistrationPlace')) { $form->remove('companyRegistrationPlace'); }
if($form->has('companyRegistrationNumber')) { $form->remove('companyRegistrationNumber'); }
if($form->has('companyRegistrationPartition')) { $form->remove('companyRegistrationPartition'); }
if($form->has('companyRegistrationInsertion')) { $form->remove('companyRegistrationInsertion'); }
if($form->has('companyRepresentantive')) { $form->remove('companyRepresentantive'); }
}
if ($personType == 'FP') {
$this->fPerson($form, $options);
$this->icDic($form, $options);
$this->businessmanRegistration($form, $options);
if($form->has('companyRegistrationPlace')) { $form->remove('companyRegistrationPlace'); }
if($form->has('companyRegistrationNumber')) { $form->remove('companyRegistrationNumber'); }
if($form->has('companyRegistrationPartition')) { $form->remove('companyRegistrationPartition'); }
if($form->has('companyRegistrationInsertion')) { $form->remove('companyRegistrationInsertion'); }
if($form->has('companyRepresentantive')) { $form->remove('companyRepresentantive'); }
}
if ($personType == 'PO') {
if($form->has('birthdate')) { $form->remove('birthdate'); }
if($form->has('birthnumber')) { $form->remove('birthnumber'); }
if($form->has('idType')) { $form->remove('idType'); }
if($form->has('idNumber')) { $form->remove('idNumber'); }
if($form->has('idAuthor')) { $form->remove('idAuthor'); }
if($form->has('idValidity')) { $form->remove('idValidity'); }
if($form->has('nationality')) { $form->remove('nationality'); }
if($form->has('businessmanRegistrationPlace')) { $form->remove('businessmanRegistrationPlace'); }
if($form->has('businessmanRegistrationNumber')) { $form->remove('businessmanRegistrationNumber'); }
$this->icDic($form, $options);
$this->companyRegistration($form, $options);
}
}
/**
* @param FormInterface $form
*/
private function icDic(FormInterface $form, array $options): void
{
$form->add('ic', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* IČO'
],
'label' => false
])
->add('dic', TextType::class, [
'required' => false,
'attr' => [
'placeholder' => '* DIČ'
],
'label' => false
]);
}
/**
* @param FormInterface $form
*/
private function businessmanRegistration(FormInterface $form, array $options): void
{
$form->add('businessmanRegistrationPlace', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Podnikatel zapsaný u'
],
'label' => false,
])
->add('businessmanRegistrationNumber', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Číslo zápisu'
],
'label' => false,
]);
}
/**
* @param FormInterface $form
*/
private function companyRegistration(FormInterface $form, array $options): void
{
$form->add('companyRegistrationPlace', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Společnost zapsaná v'
],
'label' => false,
])
->add('companyRegistrationNumber', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Číslo zápisu'
],
'label' => false,
])
->add('companyRegistrationPartition', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Oddíl'
],
'label' => false,
])
->add('companyRegistrationInsertion', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Vložka'
],
'label' => false,
])
->add('companyRepresentantive', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Společnost zastupuje'
],
'label' => false,
]);
}
/**
* @param FormInterface $form
*/
private function fPerson(FormInterface $form, array $options): void
{
$form->add('surname', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Příjmení',
'data-order-form-target' => 'surname'
],
'label' => false
])->add('birthdate', DateType::class, [
'required' => (boolean)@$options['check_required'],
'label' => false,
'widget' => 'single_text',
'html5' => false,
'format' => 'dd.MM.yyyy',
'attr' => [
'placeholder' => '* Datum narození',
'class' => "datepicker-input bg-white",
'data-order-form-target' => 'birthdate'
]
])->add('idType', ChoiceType::class, [
'required' => (boolean)@$options['check_required'],
'placeholder' => '* Typ dokladu',
'label' => false,
'choices' => EnumsHelper::idTypes(),
'attr' => [
'data-action' => 'change->order-form#reload',
'data-order-form-target' => 'idType'
]
])
->add('idNumber', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Číslo dokladu',
'data-order-form-target' => 'idNumber'
],
'label' => false,
])
->add('idAuthor', TextType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'placeholder' => '* Doklad vydal',
'data-order-form-target' => 'idAuthor'
],
'label' => false,
])
->add('idValidity', DateType::class, [
'required' => (boolean)@$options['check_required'],
'label' => false,
'widget' => 'single_text',
'html5' => false,
'format' => 'dd.MM.yyyy',
'attr' => [
'placeholder' => '* Platnost dokladu',
'class' => "datepicker-input bg-white",
'data-order-form-target' => 'idValidity'
],
])->add('nationality', ChoiceType::class, [
'required' => (boolean)@$options['check_required'],
'attr' => [
'data-order-form-target' => 'nationality'
],
'label' => false,
'choices' => EnumsHelper::countries(true),
'placeholder' => (boolean)@$options['api_call'] ? '* Země původu' : '* Národnost',
]);
}
}