namespace Lc\ShopBundle\Controller\Admin; | namespace Lc\ShopBundle\Controller\Admin; | ||||
use App\Entity\Product; | use App\Entity\Product; | ||||
use Doctrine\DBAL\Types\FloatType; | |||||
use Doctrine\ORM\EntityRepository; | use Doctrine\ORM\EntityRepository; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Event\EasyAdminEvents; | use EasyCorp\Bundle\EasyAdminBundle\Event\EasyAdminEvents; | ||||
use Lc\ShopBundle\Context\ProductCategoryInterface; | use Lc\ShopBundle\Context\ProductCategoryInterface; | ||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | ||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType; | use Symfony\Component\Form\Extension\Core\Type\CollectionType; | ||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType; | use Symfony\Component\Form\Extension\Core\Type\MoneyType; | ||||
use Symfony\Component\Form\Extension\Core\Type\NumberType; | |||||
use Symfony\Component\HttpFoundation\Response; | use Symfony\Component\HttpFoundation\Response; | ||||
class ProductFamilyController extends AdminController | class ProductFamilyController extends AdminController | ||||
{ | { | ||||
private $taxRateClass; | private $taxRateClass; | ||||
private $choicesTaxRateParam; | private $choicesTaxRateParam; | ||||
$class = $this->em->getClassMetadata(ProductCategoryInterface::class); | $class = $this->em->getClassMetadata(ProductCategoryInterface::class); | ||||
$this->taxRateClass = $this->em->getClassMetadata(TaxRateInterface::class); | $this->taxRateClass = $this->em->getClassMetadata(TaxRateInterface::class); | ||||
//$formBuilder = $this->get('form.factory')->createBuilder(ProductType::class, $entity);*/ | |||||
$formBuilder->add('price', MoneyType::class, array( | |||||
'block_prefix' => 'lc_tax_price', | |||||
'attr' => array( | |||||
'class' => 'lc-price' | |||||
) | |||||
)); | |||||
$formBuilder->add('priceWithTax', MoneyType::class, array( | |||||
'attr' => array( | |||||
'class' => 'lc-price-with-tax' | |||||
), | |||||
'required' => false, | |||||
'mapped' => false | |||||
)); | |||||
$formBuilder->add('productCategories', ProductFamilyCategoriesType::class) ; | |||||
//CHOICE qui permet de sélectionner une taxe | //CHOICE qui permet de sélectionner une taxe | ||||
//ça c'est du lourd fais très attention faudra refactorer | //ça c'est du lourd fais très attention faudra refactorer | ||||
$this->getUser()->getMerchant()->getTaxRate(); | $this->getUser()->getMerchant()->getTaxRate(); | ||||
$choicesTaxRate['TVA valeur par défaut'] = 0; | |||||
$choicesTaxRate['Valeur par défaut'] = 0; | |||||
foreach ($this->em->getRepository($this->taxRateClass->name)->findAll() as $tax) { | foreach ($this->em->getRepository($this->taxRateClass->name)->findAll() as $tax) { | ||||
$choicesTaxRate[$tax->getTitle()] = $tax->getId(); | $choicesTaxRate[$tax->getTitle()] = $tax->getId(); | ||||
$this->choicesTaxRateParam[$tax->getId()] = $tax->getValue(); | $this->choicesTaxRateParam[$tax->getId()] = $tax->getValue(); | ||||
//là mon ami je kiffe symfo !!!!! | //là mon ami je kiffe symfo !!!!! | ||||
$this->choicesTaxRateParam[0] = $this->getUser()->getMerchant()->getTaxRate()->getValue(); | $this->choicesTaxRateParam[0] = $this->getUser()->getMerchant()->getTaxRate()->getValue(); | ||||
$formBuilder->add('taxRate', ChoiceType::class, array( | $formBuilder->add('taxRate', ChoiceType::class, array( | ||||
'label' => 'TVA', | |||||
'choices' => $choicesTaxRate, | 'choices' => $choicesTaxRate, | ||||
'mapped' => false, | 'mapped' => false, | ||||
'choice_attr' => function ($choice, $key, $value) { | 'choice_attr' => function ($choice, $key, $value) { | ||||
)); | )); | ||||
$formBuilder->add('unit', ChoiceType::class, array( | $formBuilder->add('unit', ChoiceType::class, array( | ||||
'label' => 'Unité', | |||||
//'' | |||||
'choices' => array( | 'choices' => array( | ||||
'pièce' => 'piece', | 'pièce' => 'piece', | ||||
'g' => 'g', | 'g' => 'g', | ||||
'kg' => 'kg', | 'kg' => 'kg', | ||||
'ml' => 'mL', | |||||
'l' => 'L' | |||||
'ml' => 'ml', | |||||
'L' => 'L' | |||||
), | ), | ||||
)); | )); | ||||
$formBuilder->add('weight', NumberType::class, array( | |||||
'label' => 'Poids', | |||||
'attr' => [ | |||||
'append_html' => 'g' | |||||
] | |||||
)); | |||||
$formBuilder->add('step', NumberType::class, array( | |||||
'label' => 'Pas', | |||||
'help' => 'Quantité à incrémenter / décrémenter lors des mouvements de quantité', | |||||
)); | |||||
$formBuilder->add('price', NumberType::class, array( | |||||
'label' => 'Prix', | |||||
)); | |||||
$formBuilder->add('priceWithTax', NumberType::class, array( | |||||
'label' => 'Prix TTC', | |||||
'required' => false, | |||||
'mapped' => false | |||||
)); | |||||
$formBuilder->add('behaviorCountStock', ChoiceType::class, array( | $formBuilder->add('behaviorCountStock', ChoiceType::class, array( | ||||
'label' => 'Stock', | |||||
'choices' => array( | 'choices' => array( | ||||
'Gèrer le stock par déclinaison' => 'by-product', | 'Gèrer le stock par déclinaison' => 'by-product', | ||||
'Gèrer le stock par produit' => 'by-product-family' | 'Gèrer le stock par produit' => 'by-product-family' | ||||
'expanded' => true | 'expanded' => true | ||||
)); | )); | ||||
$formBuilder->add('productCategories', ProductFamilyCategoriesType::class) ; | |||||
$formBuilder->add('availableQuantity', NumberType::class, array( | |||||
'label' => 'Quantité disponible', | |||||
'required' => false, | |||||
)); | |||||
$formBuilder->add('products', CollectionType::class, array( | $formBuilder->add('products', CollectionType::class, array( | ||||
'label' => 'Catégories', | |||||
'label' => 'Déclinaisons', | |||||
'entry_type' => ProductType::class, | 'entry_type' => ProductType::class, | ||||
'entry_options' => ['label' => false], | |||||
'allow_add' => true, | 'allow_add' => true, | ||||
'prototype' => true | |||||
'allow_delete' => true, | |||||
'required' => true | |||||
) | ) | ||||
); | ); | ||||
$product->setTitle($entity->getTitle()) ; | $product->setTitle($entity->getTitle()) ; | ||||
$product->setCreatedBy($this->getUser()) ; | $product->setCreatedBy($this->getUser()) ; | ||||
$product->setUpdatedBy($this->getUser()) ; | $product->setUpdatedBy($this->getUser()) ; | ||||
$product->setProductFamily($entity) ; | |||||
$this->em->persist($product); | $this->em->persist($product); | ||||
$entity->addProduct($product) ; | $entity->addProduct($product) ; | ||||
} | } | ||||
else { | |||||
foreach($entity->getProducts() as $product) { | |||||
$product->setProductFamily($entity) ; | |||||
$product->setCreatedBy($this->getUser()) ; | |||||
$product->setUpdatedBy($this->getUser()) ; | |||||
} | |||||
} | |||||
} | } | ||||
protected function processCategories(ProductFamilyInterface $entity) | protected function processCategories(ProductFamilyInterface $entity) |
use Lc\ShopBundle\Context\ProductFamilyInterface; | use Lc\ShopBundle\Context\ProductFamilyInterface; | ||||
use Lc\ShopBundle\Context\ProductInterface; | use Lc\ShopBundle\Context\ProductInterface; | ||||
use Lc\ShopBundle\Context\TaxRateInterface; | use Lc\ShopBundle\Context\TaxRateInterface; | ||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType; | |||||
use Symfony\Component\Form\Extension\Core\Type\NumberType; | |||||
use function PHPSTORM_META\type; | use function PHPSTORM_META\type; | ||||
use Symfony\Component\Form\AbstractType; | use Symfony\Component\Form\AbstractType; | ||||
use Symfony\Component\Form\FormBuilderInterface; | use Symfony\Component\Form\FormBuilderInterface; | ||||
} | } | ||||
public function buildForm(FormBuilderInterface $builder, array $options) | public function buildForm(FormBuilderInterface $builder, array $options) | ||||
{ | { | ||||
$builder | |||||
->add('title') | |||||
->add('step') | |||||
->add('weight') | |||||
->add('step') | |||||
->add('price'); | |||||
$builder->add('title') ; | |||||
$builder->add('unit', ChoiceType::class, array( | |||||
'label' => 'Unité', | |||||
'choices' => array( | |||||
'pièce' => 'piece', | |||||
'g' => 'g', | |||||
'kg' => 'kg', | |||||
'ml' => 'ml', | |||||
'L' => 'L' | |||||
), | |||||
)); | |||||
$builder->add('weight', NumberType::class, array( | |||||
'label' => 'Poids', | |||||
'attr' => [ | |||||
'append_html' => 'g' | |||||
] | |||||
)); | |||||
$builder->add('step', NumberType::class, array( | |||||
'label' => 'Pas', | |||||
'help' => 'Quantité à incrémenter / décrémenter lors des mouvements de quantité', | |||||
)); | |||||
$builder->add('price', NumberType::class, array( | |||||
'label' => 'Prix', | |||||
)); | |||||
$builder->add('priceWithTax', NumberType::class, array( | |||||
'label' => 'Prix TTC', | |||||
'required' => false, | |||||
'mapped' => false | |||||
)); | |||||
$builder->add('availableQuantity', NumberType::class, array( | |||||
'label' => 'Quantité disponible', | |||||
'required' => false, | |||||
)); | |||||
} | } | ||||
public function configureOptions(OptionsResolver $resolver) | public function configureOptions(OptionsResolver $resolver) |
protected $productCategories; | protected $productCategories; | ||||
/** | /** | ||||
* @ORM\OneToMany(targetEntity="Lc\ShopBundle\Context\ProductInterface", mappedBy="productFamily", orphanRemoval=true) | |||||
* @ORM\OneToMany(targetEntity="Lc\ShopBundle\Context\ProductInterface", mappedBy="productFamily", orphanRemoval=true, cascade={"persist"}) | |||||
*/ | */ | ||||
protected $products; | protected $products; | ||||
/* Général */ | |||||
.input-group-text { | |||||
padding: 0.250rem .75rem ; | |||||
} | |||||
/* Switch merchant */ | |||||
#switch-merchant { | #switch-merchant { | ||||
width: 200px ; | width: 200px ; | ||||
width: 100% ; | width: 100% ; | ||||
} | } | ||||
/* Sortable */ | |||||
.ui-sortable-helper{ display: table;} | .ui-sortable-helper{ display: table;} | ||||
.ui-state-highlight{background: #eee} | .ui-state-highlight{background: #eee} | ||||
.lc-sortable div:last-child{display: none;} | .lc-sortable div:last-child{display: none;} | ||||
/* Ckfinder */ | |||||
.lc-ckfinder-wrap{width: 240px; height: 170px; position: relative;} | .lc-ckfinder-wrap{width: 240px; height: 170px; position: relative;} | ||||
.lc-ckfinder-wrap .lc-ckfinder-illu-wrap{position:relative; : 100%; height: 139px; display: flex; align-items: center; justify-content: center; background: #eee; background-size: contain;} | .lc-ckfinder-wrap .lc-ckfinder-illu-wrap{position:relative; : 100%; height: 139px; display: flex; align-items: center; justify-content: center; background: #eee; background-size: contain;} | ||||
.edit-productfamily #product-categories .children { | .edit-productfamily #product-categories .children { | ||||
margin-left: 20px ; | margin-left: 20px ; | ||||
width: 100% ; | width: 100% ; | ||||
} | |||||
} | |||||
.new-productfamily ul.products, | |||||
.edit-productfamily ul.products { | |||||
padding: 0px ; | |||||
list-style-type: none ; | |||||
} | |||||
.new-productfamily ul.products li.product, | |||||
.edit-productfamily ul.products li.product { | |||||
padding: 0px ; | |||||
margin-bottom: 20px ; | |||||
position: relative ; | |||||
} | |||||
.new-productfamily ul.products li.add, | |||||
.edit-productfamily ul.products li.add { | |||||
text-align: right ; | |||||
} | |||||
.new-productfamily .btn-remove-product, | |||||
.edit-productfamily .btn-remove-product { | |||||
position: absolute ; | |||||
top: 30px ; | |||||
right: 20px ; | |||||
} | |||||
custom_switch_merchants(); | custom_switch_merchants(); | ||||
initLcSortableList(); | initLcSortableList(); | ||||
initLcCkEditor(); | initLcCkEditor(); | ||||
initLcTaxPriceWidget() | |||||
}); | }); | ||||
function custom_switch_merchants() { | function custom_switch_merchants() { |
/** | |||||
* Created by fab on 30/12/17. | |||||
*/ | |||||
/* ProductFamily */ | |||||
function initLcTaxPriceWidget(){ | |||||
lcTaxPriceEvent() ; | |||||
$('#productfamily_price').change(lcTaxPriceEvent); | |||||
$('#productfamily_priceWithTax').change(lcTaxPriceEventWithTax); | |||||
/*function initLcTaxPriceWidget() { | |||||
lcTaxPriceInit() ; | |||||
$('#productfamily_price').change(lcTaxPriceEventPrice); | |||||
$('#productfamily_priceWithTax').change(lcTaxPriceEventPriceWithTax); | |||||
} | } | ||||
function lcTaxPriceEvent(){ | |||||
//Je ne suis pas forcémnet fan de l'appeler par l'id, à discuter | |||||
taxRate = $('#productfamily_taxRate').find('option:selected').data('tax-rate-value'); | |||||
if(typeof taxRate == 'undefined') { | |||||
taxRate = 0 ; | |||||
} | |||||
function lcTaxPriceInit() { | |||||
lcTaxPriceUpdate('priceWithTax') ; | |||||
$('#productfamily_price').val(parseFloat($('#productfamily_price').val()).toFixed(3)); | |||||
} | |||||
$('#productfamily_priceWithTax').val(getPriceWithTax($('#productfamily_price').val(), taxRate)); | |||||
function lcTaxPriceEventPrice() { | |||||
lcTaxPriceUpdate('priceWithTax') ; | |||||
} | |||||
function lcTaxPriceEventPriceWithTax() { | |||||
lcTaxPriceUpdate('price') ; | |||||
} | } | ||||
function lcTaxPriceEventWithTax() { | |||||
function lcTaxGetTaxRate() { | |||||
taxRate = $('#productfamily_taxRate').find('option:selected').data('tax-rate-value'); | taxRate = $('#productfamily_taxRate').find('option:selected').data('tax-rate-value'); | ||||
if(typeof taxRate == 'undefined') { | if(typeof taxRate == 'undefined') { | ||||
taxRate = 0 ; | taxRate = 0 ; | ||||
} | } | ||||
$('#productfamily_price').val(getPrice($('#productfamily_priceWithTax').val(), taxRate)); | |||||
return taxRate ; | |||||
} | } | ||||
/* | |||||
function opendistrib_products_event_price(){ | |||||
taxRateSelected = $('#product-id_tax_rate').find('option:selected').data('tax-rate-value'); | |||||
$('#product-price').val(getPrice($('#product-price-with-tax').val(), taxRateSelected)); | |||||
//formattage des prix | |||||
$('#product-price-with-tax').val(parseFloat($('#product-price-with-tax').val()).toFixed(2)); | |||||
} | |||||
*/ | |||||
function lcTaxPriceUpdate(priceType) { | |||||
var taxRate = lcTaxGetTaxRate() ; | |||||
if(priceType == 'priceWithTax') { | |||||
$('#productfamily_priceWithTax').val(getPriceWithTax($('#productfamily_price').val(), taxRate)); | |||||
} | |||||
else { | |||||
$('#productfamily_price').val(getPrice($('#productfamily_priceWithTax').val(), taxRate)); | |||||
} | |||||
}*/ | |||||
/* CKEditor */ | |||||
function initLcCkEditor(){ | function initLcCkEditor(){ | ||||
var elements = $( '.lc-ckeditor' ); | var elements = $( '.lc-ckeditor' ); | ||||
* @returns {string} | * @returns {string} | ||||
*/ | */ | ||||
function getPrice(priceWithTax, taxRate) { | function getPrice(priceWithTax, taxRate) { | ||||
return parseFloat(parseFloat(priceWithTax) / ((taxRate/100) + 1)).toFixed(2); | |||||
return parseFloat(parseFloat(priceWithTax) / ((taxRate/100) + 1)).toFixed(3); | |||||
} | } | ||||
/** | /** |
var app = new Vue({ | |||||
delimiters: ['${', '}'], | |||||
// Reference array sent to dynamic staticRenderFns | |||||
var staticRenderFns = []; | |||||
Vue.component('component-unit', { | |||||
props: ['template', 'keyForm', 'taxRateValue'], | |||||
data() { | |||||
return { | |||||
templateRender: null, | |||||
unit: null, | |||||
price: null, | |||||
priceWithTax: null | |||||
}; | |||||
}, | |||||
mounted: function() { | |||||
this.unit = $('#value-unit-'+this.keyForm).val() ; | |||||
this.price = parseFloat($('#value-price-'+this.keyForm).val()).toFixed(3) ; | |||||
this.priceUpdate('priceWithTax') ; | |||||
}, | |||||
methods: { | |||||
getUnitReference: function () { | |||||
if (this.unit == 'g') { | |||||
return 'kg'; | |||||
} else if (this.unit == 'ml') { | |||||
return 'L'; | |||||
} else { | |||||
return this.unit; | |||||
} | |||||
}, | |||||
changeTaxRate: function() { | |||||
this.$emit('tax-rate-change') ; | |||||
this.changePriceWithTax() ; | |||||
}, | |||||
changePrice: function() { | |||||
this.priceUpdate('price') ; | |||||
}, | |||||
changePriceWithTax: function() { | |||||
this.priceUpdate('priceWithTax') ; | |||||
}, | |||||
priceUpdate: function(priceType) { | |||||
var taxRate = this.getTaxRate() ; | |||||
if(priceType == 'priceWithTax') { | |||||
this.price = parseFloat(this.price.replace(',','.')).toFixed(3) ; | |||||
this.priceWithTax = getPriceWithTax(this.price, taxRate); | |||||
} | |||||
else { | |||||
this.priceWithTax = parseFloat(this.priceWithTax.replace(',','.')).toFixed(2) ; | |||||
this.price = getPrice(this.priceWithTax, taxRate) ; | |||||
} | |||||
}, | |||||
getTaxRate: function() { | |||||
var taxRate = this.taxRateValue ; | |||||
if(this.taxRateValue == -1) { | |||||
var taxRate = $('#productfamily_taxRate').find('option:selected').data('tax-rate-value'); | |||||
if(typeof taxRate == 'undefined') { | |||||
taxRate = 0 ; | |||||
} | |||||
} | |||||
return taxRate ; | |||||
} | |||||
}, | |||||
render(h) { | |||||
if (!this.templateRender) { | |||||
return h('div', 'loading...'); | |||||
} else { // If there is a template, I'll show it | |||||
return this.templateRender(); | |||||
} | |||||
}, | |||||
watch: { | |||||
taxRateValue: function(newVal, oldVal) { | |||||
this.changePriceWithTax() ; | |||||
}, | |||||
// Every time the template prop changes, I recompile it to update the DOM | |||||
template: { | |||||
immediate: true, // makes the watcher fire on first render, too. | |||||
handler() { | |||||
if (this.template) { | |||||
var res = Vue.compile(this.template); | |||||
this.templateRender = res.render; | |||||
// staticRenderFns belong into $options, | |||||
// appearantly | |||||
this.$options.staticRenderFns = [] | |||||
// clean the cache of static elements | |||||
// this is a cache with the results from the staticRenderFns | |||||
this._staticTrees = [] | |||||
// Fill it with the new staticRenderFns | |||||
for (var i in res.staticRenderFns) { | |||||
//staticRenderFns.push(res.staticRenderFns[i]); | |||||
this.$options.staticRenderFns.push(res.staticRenderFns[i]) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
}); | |||||
appProductFamily = new Vue({ | |||||
el: '#lc-product-family-edit', | el: '#lc-product-family-edit', | ||||
delimiters: ['${', '}'], | |||||
data: { | data: { | ||||
indexFormProduct: 0, | |||||
taxRateValue: -1, | |||||
formProductArray: [], | |||||
currentSection: 'general', | currentSection: 'general', | ||||
unit: null, | |||||
sectionsArray: [ | sectionsArray: [ | ||||
{ | { | ||||
name: 'general', | name: 'general', | ||||
}, | }, | ||||
{ | { | ||||
name: 'price', | name: 'price', | ||||
nameDisplay: 'Prix de commande' | |||||
nameDisplay: 'Prix / stock' | |||||
}, | }, | ||||
{ | { | ||||
name: 'product', | |||||
name: 'products', | |||||
nameDisplay: 'Déclinaisons' | nameDisplay: 'Déclinaisons' | ||||
} | } | ||||
] | ] | ||||
methods: { | methods: { | ||||
changeSection: function (section) { | changeSection: function (section) { | ||||
this.currentSection = section.name; | this.currentSection = section.name; | ||||
}, | |||||
setTaxRateValue: function() { | |||||
this.taxRateValue = $('#productfamily_taxRate').find('option:selected').data('tax-rate-value') ; | |||||
}, | |||||
addFormProduct: function() { | |||||
var collectionHolder = $('ul.products'); | |||||
var prototype = collectionHolder.data('prototype'); | |||||
var newForm = prototype; | |||||
newForm = newForm.replace(/__name__/g, this.indexFormProduct); | |||||
this.formProductArray.push(newForm) ; | |||||
this.indexFormProduct ++ ; | |||||
}, | |||||
deleteFormProduct: function(key) { | |||||
this.formProductArray.splice(key, 1) ; | |||||
} | } | ||||
}, | }, | ||||
mounted() { | mounted() { | ||||
//loadCkEditor(); | |||||
} | } | ||||
}); | }); | ||||
{{ form_start(form) }} | |||||
<div id="lc-product-edit"> | |||||
<div class="form"> | |||||
{{ form_row(form.title) }} | |||||
{{ form_row(form.unit, {"attr":{'v-model': 'unit'}}) }} | |||||
<div class="col-10"> | |||||
<div v-if="unit == 'piece'" class="form-group field-weight"> | |||||
{{ form_label(form.weight) }} | |||||
<div class="form-widget"> | |||||
<div class="input-group"> | |||||
{{ form_widget(form.weight) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">g</span> | |||||
</div> | |||||
</div> | |||||
{{ form_help(form.weight) }} | |||||
</div> | |||||
</div> | |||||
<div v-else class="form-group field-step"> | |||||
{{ form_label(form.step) }} | |||||
<div class="form-widget"> | |||||
<div class="input-group"> | |||||
{{ form_widget(form.step) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">${ unit }</span> | |||||
</div> | |||||
</div> | |||||
{{ form_help(form.step) }} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="col-10"> | |||||
<div class="form-group field-price"> | |||||
{{ form_label(form.price) }} | |||||
<div class="form-widget"> | |||||
<div class="input-group"> | |||||
{{ form_widget(form.price) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">€ HT / ${ getUnitReference() }</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="col-10"> | |||||
<div class="form-group field-price"> | |||||
<div class="form-widget"> | |||||
<div class="input-group"> | |||||
{{ form_widget(form.priceWithTax) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">€ TTC / ${ getUnitReference() }</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
{{ form_end(form) }} | |||||
:class="'btn '+((currentSection == section.name) ? 'btn-primary' : 'btn-default')" | :class="'btn '+((currentSection == section.name) ? 'btn-primary' : 'btn-default')" | ||||
@click="changeSection(section)"> | @click="changeSection(section)"> | ||||
${ section.nameDisplay } | ${ section.nameDisplay } | ||||
<span v-if="section.name == 'products'">({{ form.products|length }})</span> | |||||
<span class="glyphicon glyphicon-triangle-bottom"></span> | <span class="glyphicon glyphicon-triangle-bottom"></span> | ||||
</button> | </button> | ||||
</div> | </div> | ||||
<div class="form"> | <div class="form"> | ||||
<div v-show="currentSection == 'general'" class="panel panel-default"> | <div v-show="currentSection == 'general'" class="panel panel-default"> | ||||
<div class="row"> | <div class="row"> | ||||
<div class="field-group col-6"> | |||||
<div class="field-group col-8"> | |||||
<fieldset> | <fieldset> | ||||
<legend>Général</legend> | <legend>Général</legend> | ||||
<div class="row"> | <div class="row"> | ||||
</div> | </div> | ||||
</fieldset> | </fieldset> | ||||
</div> | </div> | ||||
<div class="field-group col-6" id="product-categories"> | |||||
<div class="field-group col-4" id="product-categories"> | |||||
<fieldset> | <fieldset> | ||||
<legend>Catégories</legend> | <legend>Catégories</legend> | ||||
<div class="row"> | <div class="row"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div v-show="currentSection == 'price'" class="panel panel-default"> | <div v-show="currentSection == 'price'" class="panel panel-default"> | ||||
{{ form_row(form.taxRate) }} | |||||
{{ form_row(form.unit, {"attr":{'v-model': 'unit'}}) }} | |||||
<div class="row" id="lc-app-unit"> | |||||
<div class="field-group col-6"> | |||||
<fieldset> | |||||
<legend>Prix</legend> | |||||
<component-unit inline-template key-form="productfamily" tax-rate-value="-1" v-on:tax-rate-change="setTaxRateValue"> | |||||
<div class="row"> | |||||
<div class="col-10"> | |||||
{{ form_row(form.taxRate, {'attr': {'@change':'changeTaxRate'}}) }} | |||||
</div> | |||||
<div class="col-10"> | |||||
{{ form_row(form.unit, {"attr":{'v-model': 'unit'}}) }} | |||||
{% if form.vars.value %} | |||||
<input type="hidden" :id="'value-unit-'+keyForm" value="{{ form.vars.value.unit }}" /> | |||||
{% endif %} | |||||
</div> | |||||
<div class="col-10"> | |||||
<div v-if="unit == 'piece'" class="form-group field-weight"> | |||||
{{ form_label(form.weight) }} | |||||
<div class="form-widget"> | |||||
<div class="input-group"> | |||||
{{ form_widget(form.weight) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">g</span> | |||||
</div> | |||||
</div> | |||||
{{ form_help(form.weight) }} | |||||
</div> | |||||
</div> | |||||
<div v-else class="form-group field-step"> | |||||
{{ form_label(form.step) }} | |||||
<div class="form-widget"> | |||||
<div class="input-group"> | |||||
{{ form_widget(form.step) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">${ unit }</span> | |||||
</div> | |||||
</div> | |||||
{{ form_help(form.step) }} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="col-10"> | |||||
<div class="form-group field-price"> | |||||
{{ form_label(form.price) }} | |||||
<div class="form-widget"> | |||||
<div class="input-group"> | |||||
{{ form_widget(form.price, {'attr' : {'v-model': 'price', '@change' : 'changePriceWithTax'}}) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">€ HT / ${ getUnitReference() }</span> | |||||
</div> | |||||
{% if form.vars.value %} | |||||
<input type="hidden" :id="'value-price-'+keyForm" value="{{ form.vars.value.price }}" /> | |||||
{% endif %} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div v-if="unit == 'piece'" class="form-group fiel-step"> | |||||
{{ form_label(form.weight) }} | |||||
<div class="form-widget"> | |||||
{{ form_widget(form.weight) }} | |||||
<div class="col-10"> | |||||
<div class="form-group field-price"> | |||||
<div class="form-widget"> | |||||
<div class="input-group"> | |||||
{{ form_widget(form.priceWithTax, {'attr' : {'v-model': 'priceWithTax', '@change' : 'changePrice'}}) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">€ TTC / ${ getUnitReference() }</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</component-unit> | |||||
</fieldset> | |||||
</div> | </div> | ||||
</div> | |||||
<div v-else class="form-group fiel-step"> | |||||
{{ form_label(form.step) }} | |||||
<div class="form-widget"> | |||||
{{ form_widget(form.step) }} | |||||
<div class="field-group col-6"> | |||||
<fieldset> | |||||
<legend>Stock</legend> | |||||
<div class="row"> | |||||
<div class="col-12"> | |||||
{{ form_row(form.behaviorCountStock) }} | |||||
{{ form_row(form.availableQuantity) }} | |||||
</div> | |||||
</div> | |||||
</fieldset> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{#{% do form.step.setRendered %}#} | |||||
</div> | |||||
<div v-show="currentSection == 'products'" class="panel panel-default"> | |||||
{% macro printProductRow(product) %} | |||||
<div :id="'form-product-'+ keyForm"> | |||||
<div class="field-group"> | |||||
<fieldset> | |||||
<legend>Déclinaison</legend> | |||||
<div class="form-group row"> | |||||
{{ form_label(product.title, null, {'label_attr': {'class': 'col-2 col-form-label text-right'}}) }} | |||||
<div class="form-widget col-10"> | |||||
{{ form_widget(product.title) }} | |||||
{{ form_help(product.title) }} | |||||
{% if product.vars.value %} | |||||
<input type="hidden" :id="'value-unit-'+keyForm" value="{{ product.vars.value.unit }}" /> | |||||
{% endif %} | |||||
</div> | |||||
</div> | |||||
<div class="form-group row"> | |||||
{{ form_label(product.unit, null, {'label_attr': {'class': 'col-2 col-form-label text-right'}}) }} | |||||
<div class="form-widget col-10"> | |||||
{{ form_widget(product.unit, {"attr":{'v-model': 'unit', 'class' : 'select-unit'}}) }} | |||||
{{ form_help(product.unit) }} | |||||
</div> | |||||
</div> | |||||
<div v-if="unit == 'piece'" class="form-group row field-weight"> | |||||
{{ form_label(product.weight, null, {'label_attr': {'class': 'col-2 col-form-label text-right'}}) }} | |||||
<div class="form-widget col-10"> | |||||
<div class="input-group"> | |||||
{{ form_widget(product.weight) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">g</span> | |||||
</div> | |||||
</div> | |||||
{{ form_help(product.weight) }} | |||||
</div> | |||||
</div> | |||||
<div v-else class="form-group row field-step"> | |||||
{{ form_label(product.step, null, {'label_attr': {'class': 'col-2 col-form-label text-right'}}) }} | |||||
<div class="form-widget col-8"> | |||||
<div class="input-group"> | |||||
{{ form_widget(product.step) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">{% verbatim %}{{ unit }}{% endverbatim %}</span> | |||||
</div> | |||||
</div> | |||||
{{ form_help(product.step) }} | |||||
</div> | |||||
</div> | |||||
<div class="form-group fiel-step"> | |||||
{{ form_label(form.price) }} | |||||
<div class="form-widget"> | |||||
<div class="row m-0"> | |||||
<div class="col-xs-6 mr-4"> | |||||
{{ form_label(form.price) }} | |||||
{{ form_widget(form.price) }} | |||||
</div> | |||||
<div class="col-xs-6 "> | |||||
{{ form_label(form.priceWithTax) }} | |||||
{{ form_widget(form.priceWithTax) }} | |||||
</div> | |||||
<div class="form-group row field-price"> | |||||
{{ form_label(product.price, null, {'label_attr': {'class': 'col-2 col-form-label text-right'}}) }} | |||||
<div class="form-widget col-10"> | |||||
<div class="input-group"> | |||||
{{ form_widget(product.price, {'attr' : {'v-model': 'price', '@change' : 'changePriceWithTax'}}) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">€ HT / {% verbatim %}{{ getUnitReference() }}{% endverbatim %}</span> | |||||
</div> | |||||
{% if product.vars.value %} | |||||
<input type="hidden" :id="'value-price-'+keyForm" value="{{ product.vars.value.price }}" /> | |||||
{% endif %} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="form-group row field-price"> | |||||
<div class="col-2"> </div> | |||||
<div class="form-widget col-10"> | |||||
<div class="input-group"> | |||||
{{ form_widget(product.priceWithTax, {'attr' : {'v-model': 'priceWithTax','@change' : 'changePrice'}}) }} | |||||
<div class="input-group-append"> | |||||
<span class="input-group-text">€ TTC / {% verbatim %}{{ getUnitReference() }}{% endverbatim %}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="form-group row field-available-quantity"> | |||||
{{ form_label(product.availableQuantity, null, {'label_attr': {'class': 'col-2 col-form-label text-right'}}) }} | |||||
<div class="form-widget col-10"> | |||||
{{ form_widget(product.availableQuantity) }} | |||||
</div> | |||||
</div> | |||||
</fieldset> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | |||||
</div> | |||||
{% endmacro %} | |||||
{% import _self as formMacros %} | |||||
{{ form_row(form.behaviorCountStock) }} | |||||
{{ form_row(form.productCategories) }} | |||||
</div> | |||||
<div v-show="currentSection == 'product'" class="panel panel-default"> | |||||
{{ form_row(form.products) }} | |||||
<ul class="products" :data-index="formProductArray.length" data-prototype="{{ formMacros.printProductRow(form.products.vars.prototype)|e('html_attr') }}"> | |||||
<li class="product" v-for="(formProduct, key) in formProductArray"> | |||||
<button type="button" class="btn-remove-product btn btn-default" @click="deleteFormProduct(key)"><i class="fa fa-trash"></i> Supprimer cette déclinaison</button> | |||||
<component-unit :template="formProduct" :key-form="key" :tax-rate-value="taxRateValue"></component-unit> | |||||
</li> | |||||
<li class="add"> | |||||
<button type="button" class="add_tag_link btn-add-product btn btn-default" @click="addFormProduct"><span class="fa fa-plus"></span> Ajouter une déclinaison</button> | |||||
</li> | |||||
{% for product in form.products %} | |||||
<script> | |||||
jQuery(document).ready(function() { | |||||
var formProduct = '{{ formMacros.printProductRow(product)|replace({"\n":' ', "\r":' ', "'" : "\\'"})|raw }}' ; | |||||
appProductFamily.formProductArray.push(formProduct) ; | |||||
appProductFamily.indexFormProduct ++ ; | |||||
}) ; | |||||
</script> | |||||
{% endfor %} | |||||
</ul> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{{ form_end(form) }} | {{ form_end(form) }} | ||||