@@ -3,6 +3,7 @@ | |||
namespace Lc\ShopBundle\Controller\Admin; | |||
use App\Entity\Product; | |||
use Doctrine\DBAL\Types\FloatType; | |||
use Doctrine\ORM\EntityRepository; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\EasyAdminEvents; | |||
use Lc\ShopBundle\Context\ProductCategoryInterface; | |||
@@ -16,11 +17,11 @@ use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | |||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||
use Symfony\Component\Form\Extension\Core\Type\CollectionType; | |||
use Symfony\Component\Form\Extension\Core\Type\MoneyType; | |||
use Symfony\Component\Form\Extension\Core\Type\NumberType; | |||
use Symfony\Component\HttpFoundation\Response; | |||
class ProductFamilyController extends AdminController | |||
{ | |||
private $taxRateClass; | |||
private $choicesTaxRateParam; | |||
@@ -31,26 +32,12 @@ class ProductFamilyController extends AdminController | |||
$class = $this->em->getClassMetadata(ProductCategoryInterface::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 | |||
//ça c'est du lourd fais très attention faudra refactorer | |||
$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) { | |||
$choicesTaxRate[$tax->getTitle()] = $tax->getId(); | |||
$this->choicesTaxRateParam[$tax->getId()] = $tax->getValue(); | |||
@@ -58,8 +45,8 @@ class ProductFamilyController extends AdminController | |||
//là mon ami je kiffe symfo !!!!! | |||
$this->choicesTaxRateParam[0] = $this->getUser()->getMerchant()->getTaxRate()->getValue(); | |||
$formBuilder->add('taxRate', ChoiceType::class, array( | |||
'label' => 'TVA', | |||
'choices' => $choicesTaxRate, | |||
'mapped' => false, | |||
'choice_attr' => function ($choice, $key, $value) { | |||
@@ -68,16 +55,41 @@ class ProductFamilyController extends AdminController | |||
)); | |||
$formBuilder->add('unit', ChoiceType::class, array( | |||
'label' => 'Unité', | |||
//'' | |||
'choices' => array( | |||
'pièce' => 'piece', | |||
'g' => 'g', | |||
'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( | |||
'label' => 'Stock', | |||
'choices' => array( | |||
'Gèrer le stock par déclinaison' => 'by-product', | |||
'Gèrer le stock par produit' => 'by-product-family' | |||
@@ -86,13 +98,18 @@ class ProductFamilyController extends AdminController | |||
'expanded' => true | |||
)); | |||
$formBuilder->add('productCategories', ProductFamilyCategoriesType::class) ; | |||
$formBuilder->add('availableQuantity', NumberType::class, array( | |||
'label' => 'Quantité disponible', | |||
'required' => false, | |||
)); | |||
$formBuilder->add('products', CollectionType::class, array( | |||
'label' => 'Catégories', | |||
'label' => 'Déclinaisons', | |||
'entry_type' => ProductType::class, | |||
'entry_options' => ['label' => false], | |||
'allow_add' => true, | |||
'prototype' => true | |||
'allow_delete' => true, | |||
'required' => true | |||
) | |||
); | |||
@@ -131,10 +148,18 @@ class ProductFamilyController extends AdminController | |||
$product->setTitle($entity->getTitle()) ; | |||
$product->setCreatedBy($this->getUser()) ; | |||
$product->setUpdatedBy($this->getUser()) ; | |||
$product->setProductFamily($entity) ; | |||
$this->em->persist($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) |
@@ -8,6 +8,9 @@ use FOS\CKEditorBundle\Form\Type\CKEditorType; | |||
use Lc\ShopBundle\Context\ProductFamilyInterface; | |||
use Lc\ShopBundle\Context\ProductInterface; | |||
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 Symfony\Component\Form\AbstractType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
@@ -23,12 +26,47 @@ class ProductType extends AbstractType | |||
} | |||
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) |
@@ -24,7 +24,7 @@ abstract class ProductFamily extends AbstractDocumentEntity | |||
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; | |||
@@ -1,3 +1,10 @@ | |||
/* Général */ | |||
.input-group-text { | |||
padding: 0.250rem .75rem ; | |||
} | |||
/* Switch merchant */ | |||
#switch-merchant { | |||
width: 200px ; | |||
@@ -7,10 +14,13 @@ | |||
width: 100% ; | |||
} | |||
/* Sortable */ | |||
.ui-sortable-helper{ display: table;} | |||
.ui-state-highlight{background: #eee} | |||
.lc-sortable div:last-child{display: none;} | |||
/* Ckfinder */ | |||
.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;} | |||
@@ -47,4 +57,30 @@ | |||
.edit-productfamily #product-categories .children { | |||
margin-left: 20px ; | |||
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 ; | |||
} | |||
@@ -2,7 +2,6 @@ jQuery(document).ready(function () { | |||
custom_switch_merchants(); | |||
initLcSortableList(); | |||
initLcCkEditor(); | |||
initLcTaxPriceWidget() | |||
}); | |||
function custom_switch_merchants() { |
@@ -1,44 +1,45 @@ | |||
/** | |||
* 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'); | |||
if(typeof taxRate == 'undefined') { | |||
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(){ | |||
var elements = $( '.lc-ckeditor' ); | |||
@@ -56,7 +57,7 @@ function initLcCkEditor(){ | |||
* @returns {string} | |||
*/ | |||
function getPrice(priceWithTax, taxRate) { | |||
return parseFloat(parseFloat(priceWithTax) / ((taxRate/100) + 1)).toFixed(2); | |||
return parseFloat(parseFloat(priceWithTax) / ((taxRate/100) + 1)).toFixed(3); | |||
} | |||
/** |
@@ -1,9 +1,113 @@ | |||
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', | |||
delimiters: ['${', '}'], | |||
data: { | |||
indexFormProduct: 0, | |||
taxRateValue: -1, | |||
formProductArray: [], | |||
currentSection: 'general', | |||
unit: null, | |||
sectionsArray: [ | |||
{ | |||
name: 'general', | |||
@@ -11,10 +115,10 @@ var app = new Vue({ | |||
}, | |||
{ | |||
name: 'price', | |||
nameDisplay: 'Prix de commande' | |||
nameDisplay: 'Prix / stock' | |||
}, | |||
{ | |||
name: 'product', | |||
name: 'products', | |||
nameDisplay: 'Déclinaisons' | |||
} | |||
] | |||
@@ -22,12 +126,22 @@ var app = new Vue({ | |||
methods: { | |||
changeSection: function (section) { | |||
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() { | |||
//loadCkEditor(); | |||
} | |||
}); | |||
@@ -0,0 +1,63 @@ | |||
{{ 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) }} | |||
@@ -5,13 +5,14 @@ | |||
:class="'btn '+((currentSection == section.name) ? 'btn-primary' : 'btn-default')" | |||
@click="changeSection(section)"> | |||
${ section.nameDisplay } | |||
<span v-if="section.name == 'products'">({{ form.products|length }})</span> | |||
<span class="glyphicon glyphicon-triangle-bottom"></span> | |||
</button> | |||
</div> | |||
<div class="form"> | |||
<div v-show="currentSection == 'general'" class="panel panel-default"> | |||
<div class="row"> | |||
<div class="field-group col-6"> | |||
<div class="field-group col-8"> | |||
<fieldset> | |||
<legend>Général</legend> | |||
<div class="row"> | |||
@@ -30,7 +31,7 @@ | |||
</div> | |||
</fieldset> | |||
</div> | |||
<div class="field-group col-6" id="product-categories"> | |||
<div class="field-group col-4" id="product-categories"> | |||
<fieldset> | |||
<legend>Catégories</legend> | |||
<div class="row"> | |||
@@ -51,48 +52,206 @@ | |||
</div> | |||
</div> | |||
<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 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> | |||
{#{% 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> | |||
{% 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> | |||
{{ form_end(form) }} | |||