diff --git a/core/lib/Thelia/Action/Attribute.php b/core/lib/Thelia/Action/Attribute.php
index 7db04518a..30ceea0e8 100644
--- a/core/lib/Thelia/Action/Attribute.php
+++ b/core/lib/Thelia/Action/Attribute.php
@@ -63,7 +63,7 @@ class Attribute extends BaseAction implements EventSubscriberInterface
// Add atribute to all product templates if required
if ($event->getAddToAllTemplates() != 0) {
- // TODO: add to all product template
+ $this->doAddToAllTemplates($attribute);
}
}
diff --git a/core/lib/Thelia/Action/Feature.php b/core/lib/Thelia/Action/Feature.php
index 6ae7645e3..36853f444 100644
--- a/core/lib/Thelia/Action/Feature.php
+++ b/core/lib/Thelia/Action/Feature.php
@@ -63,7 +63,7 @@ class Feature extends BaseAction implements EventSubscriberInterface
// Add atribute to all product templates if required
if ($event->getAddToAllTemplates() != 0) {
- // TODO: add to all product template
+ $this->doAddToAllTemplates($feature);
}
}
diff --git a/core/lib/Thelia/Action/ProductSaleElement.php b/core/lib/Thelia/Action/ProductSaleElement.php
index 8349eb1bf..9c40025d8 100644
--- a/core/lib/Thelia/Action/ProductSaleElement.php
+++ b/core/lib/Thelia/Action/ProductSaleElement.php
@@ -40,6 +40,8 @@ use Thelia\Model\AttributeAvQuery;
use Thelia\Model\Currency;
use Thelia\Model\Map\AttributeCombinationTableMap;
use Propel\Runtime\ActiveQuery\Criteria;
+use Thelia\Core\Event\Product\ProductCombinationGenerationEvent;
+use Propel\Runtime\Connection\ConnectionInterface;
class ProductSaleElement extends BaseAction implements EventSubscriberInterface
{
@@ -65,7 +67,7 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface
if ($salesElement == null) {
// Create a new default product sale element
- $salesElement = $event->getProduct()->createDefaultProductSaleElement($con, 0, 0, $event->getCurrencyId(), true);
+ $salesElement = $event->getProduct()->createDefaultProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true);
} else {
// This (new) one is the default
$salesElement->setIsDefault(true)->save($con);
@@ -87,7 +89,7 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface
->setAttributeAvId($attributeAvId)
->setAttribute($attributeAv->getAttribute())
->setProductSaleElements($salesElement)
- ->save();
+ ->save($con);
}
}
}
@@ -206,8 +208,9 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface
if ($product->countSaleElements() <= 0) {
// If we just deleted the last PSE, create a default one
- $product->createDefaultProductSaleElement($con, 0, 0, $event->getCurrencyId(), true);
- } elseif ($pse->getIsDefault()) {
+ $product->createProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true);
+ }
+ elseif ($pse->getIsDefault()) {
// If we deleted the default PSE, make the last created one the default
$pse = ProductSaleElementsQuery::create()
@@ -230,6 +233,83 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface
}
}
+ /**
+ * Generate combinations. All existing combinations for the product are deleted.
+ *
+ * @param ProductCombinationGenerationEvent $event
+ */
+ public function generateCombinations(ProductCombinationGenerationEvent $event) {
+
+ $con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME);
+
+ $con->beginTransaction();
+
+ try {
+
+ // Delete all product's productSaleElement
+ ProductSaleElementsQuery::create()->filterByProductId($event->product->getId())->delete();
+
+ $isDefault = true;
+
+ // Create all combinations
+ foreach($event->getCombinations() as $combinationAttributesAvIds) {
+
+ // Create the PSE
+ $saleElement = $event->getProduct()->createProductSaleElement(
+ $con,
+ $event->getWeight(),
+ $event->getPrice(),
+ $event->getSalePrice(),
+ $event->getCurrencyId(),
+ $isDefault,
+ $event->getOnsale(),
+ $event->getIsnew(),
+ $event->getQuantity(),
+ $event->getEanCode(),
+ $event->getReference()
+ );
+
+ $isDefault = false;
+
+ $this->createCombination($con, $saleElement, $combinationAttributesAvIds);
+ }
+
+ // Store all the stuff !
+ $con->commit();
+ }
+ catch (\Exception $ex) {
+
+ $con->rollback();
+
+ throw $ex;
+ }
+ }
+
+ /**
+ * Create a combination for a given product sale element
+ *
+ * @param ConnectionInterface $con the Propel connection
+ * @param ProductSaleElement $salesElement the product sale element
+ * @param unknown $combinationAttributes an array oif attributes av IDs
+ */
+ protected function createCombination(ConnectionInterface $con, ProductSaleElements $salesElement, $combinationAttributes)
+ {
+ foreach ($combinationAttributes as $attributeAvId) {
+
+ $attributeAv = AttributeAvQuery::create()->findPk($attributeAvId);
+
+ if ($attributeAv !== null) {
+ $attributeCombination = new AttributeCombination();
+
+ $attributeCombination
+ ->setAttributeAvId($attributeAvId)
+ ->setAttribute($attributeAv->getAttribute())
+ ->setProductSaleElements($salesElement)
+ ->save($con);
+ }
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -239,6 +319,8 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface
TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT => array("create", 128),
TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT => array("update", 128),
TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT => array("delete", 128),
+ TheliaEvents::PRODUCT_COMBINATION_GENERATION => array("generateCombinations", 128),
+
);
}
}
diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml
index c0af99896..84e9ef92e 100755
--- a/core/lib/Thelia/Config/Resources/config.xml
+++ b/core/lib/Thelia/Config/Resources/config.xml
@@ -90,6 +90,8 @@
+
+
diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml
index dc5a2c522..64bf37541 100755
--- a/core/lib/Thelia/Config/Resources/routing/admin.xml
+++ b/core/lib/Thelia/Config/Resources/routing/admin.xml
@@ -372,6 +372,10 @@
Thelia\Controller\Admin\ProductController::updateProductSaleElementsAction
+
+ Thelia\Controller\Admin\ProductController::buildCombinationsAction
+
+
Thelia\Controller\Admin\ProductController::updateProductDefaultSaleElementAction
diff --git a/core/lib/Thelia/Controller/Admin/FeatureController.php b/core/lib/Thelia/Controller/Admin/FeatureController.php
index 7696b9c6e..1be5dfeec 100644
--- a/core/lib/Thelia/Controller/Admin/FeatureController.php
+++ b/core/lib/Thelia/Controller/Admin/FeatureController.php
@@ -157,23 +157,6 @@ class FeatureController extends AbstractCrudController
'postscriptum' => $object->getPostscriptum()
);
- // Setup features values
- /*
- * FIXME : doesn't work. "We get a This form should not contain extra fields." error
- $attr_av_list = FeatureAvQuery::create()
- ->joinWithI18n($this->getCurrentEditionLocale())
- ->filterByFeatureId($object->getId())
- ->find();
-
- $attr_array = array();
-
- foreach ($attr_av_list as $attr_av) {
- $attr_array[$attr_av->getId()] = $attr_av->getTitle();
- }
-
- $data['feature_values'] = $attr_array;
- */
-
// Setup the object form
return new FeatureModificationForm($this->getRequest(), "form", $data);
}
diff --git a/core/lib/Thelia/Controller/Admin/ProductController.php b/core/lib/Thelia/Controller/Admin/ProductController.php
index 84e16815d..5540c529b 100644
--- a/core/lib/Thelia/Controller/Admin/ProductController.php
+++ b/core/lib/Thelia/Controller/Admin/ProductController.php
@@ -64,6 +64,8 @@ use Thelia\Model\Country;
use Thelia\Tools\NumberFormat;
use Thelia\Model\Product;
use Thelia\Model\CurrencyQuery;
+use Thelia\Form\ProductCombinationGenerationForm;
+use Thelia\Core\Event\Product\ProductCombinationGenerationEvent;
/**
* Manages products
@@ -1025,6 +1027,108 @@ class ProductController extends AbstractCrudController
);
}
+ // Create combinations
+ protected function combine($input, &$output, &$tmp) {
+ $current = array_shift($input);
+
+ if (count($input) > 0) {
+ foreach($current as $element) {
+ $tmp[] = $element;
+ $this->combine($input, $output, $tmp);
+ array_pop($tmp);
+ }
+ } else {
+ foreach($current as $element) {
+ $tmp[] = $element;
+ $output[] = $tmp;
+ array_pop($tmp);
+ }
+ }
+ }
+
+ /**
+ * Build combinations from the combination output builder
+ */
+ public function buildCombinationsAction() {
+
+ // Check current user authorization
+ if (null !== $response = $this->checkAuth($this->resourceCode, AccessManager::UPDATE)) return $response;
+
+ $error_msg = false;
+
+ $changeForm = new ProductCombinationGenerationForm($this->getRequest());
+
+ try {
+
+ // Check the form against constraints violations
+ $form = $this->validateForm($changeForm, "POST");
+
+ // Get the form field values
+ $data = $form->getData();
+
+ // Rework attributes_av array, to build an array which contains all combinations,
+ // in the form combination[] = array of combination attributes av IDs
+ //
+ // First, create an array of attributes_av ID in the form $attributes_av_list[$attribute_id] = array of attributes_av ID
+ // from the list of attribute_id:attributes_av ID from the form.
+ $combinations = $attributes_av_list = array();
+
+ foreach($data['attribute_av'] as $item) {
+ list($attribute_id, $attribute_av_id) = explode(':', $item);
+
+ if (! isset($attributes_av_list[$attribute_id]))
+ $attributes_av_list[$attribute_id] = array();
+
+
+ $attributes_av_list[$attribute_id][] = $attribute_av_id;
+ }
+
+ // Next, recursively combine array
+ $combinations = $tmp = array();
+
+ $this->combine($attributes_av_list, $combinations, $tmp);
+
+ // Create event
+ $event = new ProductCombinationGenerationEvent(
+ $this->getExistingObject(),
+ $data['currency'],
+ $combinations
+ );
+
+ $event
+ ->setReference($data['reference'] == null ? '' : $data['reference'])
+ ->setPrice($data['price'] == null ? 0 : $data['price'])
+ ->setWeight($data['weight'] == null ? 0 : $data['weight'])
+ ->setQuantity($data['quantity'] == null ? 0 : $data['quantity'])
+ ->setSalePrice($data['sale_price'] == null ? 0 : $data['sale_price'])
+ ->setOnsale($data['onsale'] == null ? false : $data['onsale'])
+ ->setIsnew($data['isnew'] == null ? false : $data['isnew'])
+ ->setEanCode($data['ean_code'] == null ? '' : $data['ean_code'])
+ ;
+
+ $this->dispatch(TheliaEvents::PRODUCT_COMBINATION_GENERATION, $event);
+
+ // Log object modification
+ $this->adminLogAppend(sprintf("Combination generation for product reference %s", $event->getProduct()->getRef()));
+
+ // Redirect to the success URL
+ $this->redirect($changeForm->getSuccessUrl());
+
+ } catch (FormValidationException $ex) {
+ // Form cannot be validated
+ $error_msg = $this->createStandardFormValidationErrorMessage($ex);
+ } catch (\Exception $ex) {
+ // Any other error
+ $error_msg = $ex->getMessage();
+ }
+
+ $this->setupFormErrorContext(
+ $this->getTranslator()->trans("Combination builder"), $error_msg, $changeForm, $ex);
+
+ // At this point, the form has errors, and should be redisplayed.
+ return $this->renderEditionTemplate();
+ }
+
/**
* Invoked through Ajax; this method calculates the taxed price from the unaxed price, and
* vice versa.
diff --git a/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php b/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php
new file mode 100644
index 000000000..05b55d733
--- /dev/null
+++ b/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php
@@ -0,0 +1,159 @@
+. */
+/* */
+/*************************************************************************************/
+
+namespace Thelia\Core\Event\Product;
+use Thelia\Model\Product;
+
+class ProductCombinationGenerationEvent extends ProductEvent
+{
+ protected $reference;
+ protected $price;
+ protected $currency_id;
+ protected $weight;
+ protected $quantity;
+ protected $sale_price;
+ protected $onsale;
+ protected $isnew;
+ protected $ean_code;
+ protected $combinations;
+
+ public function __construct(Product $product, $currency_id, $combinations)
+ {
+ parent::__construct($product);
+
+ $this->setCombinations($combinations);
+ $this->setCurrencyId($currency_id);
+ }
+
+ public function getCurrencyId()
+ {
+ return $this->currency_id;
+ }
+
+ public function setCurrencyId($currency_id)
+ {
+ $this->currency_id = $currency_id;
+
+ return $this;
+ }
+
+ public function getReference()
+ {
+ return $this->reference;
+ }
+
+ public function setReference($reference)
+ {
+ $this->reference = $reference;
+ return $this;
+ }
+
+ public function getPrice()
+ {
+ return $this->price;
+ }
+
+ public function setPrice($price)
+ {
+ $this->price = $price;
+ return $this;
+ }
+
+ public function getWeight()
+ {
+ return $this->weight;
+ }
+
+ public function setWeight($weight)
+ {
+ $this->weight = $weight;
+ return $this;
+ }
+
+ public function getQuantity()
+ {
+ return $this->quantity;
+ }
+
+ public function setQuantity($quantity)
+ {
+ $this->quantity = $quantity;
+ return $this;
+ }
+
+ public function getSalePrice()
+ {
+ return $this->sale_price;
+ }
+
+ public function setSalePrice($sale_price)
+ {
+ $this->sale_price = $sale_price;
+ return $this;
+ }
+
+ public function getOnsale()
+ {
+ return $this->onsale;
+ }
+
+ public function setOnsale($onsale)
+ {
+ $this->onsale = $onsale;
+ return $this;
+ }
+
+ public function getIsnew()
+ {
+ return $this->isnew;
+ }
+
+ public function setIsnew($isnew)
+ {
+ $this->isnew = $isnew;
+ return $this;
+ }
+
+ public function getEanCode()
+ {
+ return $this->ean_code;
+ }
+
+ public function setEanCode($ean_code)
+ {
+ $this->ean_code = $ean_code;
+ return $this;
+ return $this;
+ }
+
+ public function getCombinations()
+ {
+ return $this->combinations;
+ }
+
+ public function setCombinations($combinations)
+ {
+ $this->combinations = $combinations;
+ return $this;
+ }
+}
\ No newline at end of file
diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php
index 42b20d8cd..dfd2d27aa 100755
--- a/core/lib/Thelia/Core/Event/TheliaEvents.php
+++ b/core/lib/Thelia/Core/Event/TheliaEvents.php
@@ -285,6 +285,8 @@ final class TheliaEvents
const PRODUCT_DELETE_PRODUCT_SALE_ELEMENT = "action.deleteProductSaleElement";
const PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT = "action.updateProductSaleElement";
+ const PRODUCT_COMBINATION_GENERATION = "action.productCombineationGeneration";
+
const PRODUCT_SET_TEMPLATE = "action.productSetTemplate";
const PRODUCT_ADD_ACCESSORY = "action.productAddProductAccessory";
diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php
index e9a7d9eb8..10c1dda00 100755
--- a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php
+++ b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php
@@ -128,14 +128,17 @@ class AttributeAvailability extends BaseI18nLoop
foreach ($attributesAv as $attributeAv) {
$loopResultRow = new LoopResultRow($loopResult, $attributeAv, $this->versionable, $this->timestampable, $this->countable);
- $loopResultRow->set("ID", $attributeAv->getId())
- ->set("IS_TRANSLATED",$attributeAv->getVirtualColumn('IS_TRANSLATED'))
- ->set("LOCALE",$locale)
- ->set("TITLE",$attributeAv->getVirtualColumn('i18n_TITLE'))
- ->set("CHAPO", $attributeAv->getVirtualColumn('i18n_CHAPO'))
- ->set("DESCRIPTION", $attributeAv->getVirtualColumn('i18n_DESCRIPTION'))
- ->set("POSTSCRIPTUM", $attributeAv->getVirtualColumn('i18n_POSTSCRIPTUM'))
- ->set("POSITION", $attributeAv->getPosition());
+ $loopResultRow
+ ->set("ID" , $attributeAv->getId())
+ ->set("ATTRIBUTE_ID" , $attributeAv->getAttributeId())
+ ->set("IS_TRANSLATED", $attributeAv->getVirtualColumn('IS_TRANSLATED'))
+ ->set("LOCALE" , $locale)
+ ->set("TITLE" , $attributeAv->getVirtualColumn('i18n_TITLE'))
+ ->set("CHAPO" , $attributeAv->getVirtualColumn('i18n_CHAPO'))
+ ->set("DESCRIPTION" , $attributeAv->getVirtualColumn('i18n_DESCRIPTION'))
+ ->set("POSTSCRIPTUM" , $attributeAv->getVirtualColumn('i18n_POSTSCRIPTUM'))
+ ->set("POSITION" , $attributeAv->getPosition())
+ ;
$loopResult->addRow($loopResultRow);
}
diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php
index 494e219eb..ee49fe1ec 100755
--- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php
+++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php
@@ -199,30 +199,29 @@ class Form extends AbstractSmartyPlugin
{
if ($repeat) {
- $formFieldView = $this->getFormFieldView($params);
- $formFieldConfig = $this->getFormFieldConfig($params);
+ $formFieldView = $this->getFormFieldView($params);
+ $formFieldConfig = $this->getFormFieldConfig($params);
- $this->assignFormTypeValues($template, $formFieldConfig, $formFieldView);
+ $this->assignFormTypeValues($template, $formFieldConfig, $formFieldView);
$value = $formFieldView->vars["value"];
- // We have a collection
- if (0 < $value_count = count($formFieldView->children)) {
+ $key = $this->getParam($params, 'value_key', null);
- $key = $this->getParam($params, 'value_key', null);
+ // We (may) have a collection
+ if ($key !== null) {
- if ($key !== null) {
- // If the field is not found, use an empty value
- $val = array_key_exists($key, $value) ? $value[$key] : '';
+ // Force array
+ if (! is_array($value)) $value = array();
- $name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key);
+ // If the field is not found, use an empty value
+ $val = array_key_exists($key, $value) ? $value[$key] : '';
- $val = $value[$key];
+ $name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key);
- $this->assignFieldValues($template, $name, $val, $formFieldView->vars, $value_count);
- } else {
- throw new \InvalidArgumentException(sprintf("Missing or empty parameter 'value_key' for field '%s'", $formFieldView->vars["name"]));
- }
+ $val = $value[$key];
+
+ $this->assignFieldValues($template, $name, $val, $formFieldView->vars, count($formFieldView->children));
} else {
$this->assignFieldValues($template, $formFieldView->vars["full_name"], $formFieldView->vars["value"], $formFieldView->vars);
}
diff --git a/core/lib/Thelia/Form/ProductCombinationGenerationForm.php b/core/lib/Thelia/Form/ProductCombinationGenerationForm.php
new file mode 100644
index 000000000..8e4b155b9
--- /dev/null
+++ b/core/lib/Thelia/Form/ProductCombinationGenerationForm.php
@@ -0,0 +1,91 @@
+. */
+/* */
+/*************************************************************************************/
+namespace Thelia\Form;
+
+use Symfony\Component\Validator\Constraints\GreaterThan;
+use Symfony\Component\Validator\Constraints\NotBlank;
+use Thelia\Model\Currency;
+use Thelia\Core\Translation\Translator;
+
+class ProductCombinationGenerationForm extends BaseForm
+{
+ protected function buildForm()
+ {
+ $this->formBuilder
+ ->add('product_id', 'integer', array(
+ 'label' => Translator::getInstance()->trans('Product ID'),
+ 'label_attr' => array('for' => 'combination_builder_id_field'),
+ 'constraints' => array(new GreaterThan(array('value' => 0)))
+ ))
+ ->add('currency', 'integer', array(
+ 'label' => Translator::getInstance()->trans('Price currency *'),
+ 'label_attr' => array('for' => 'combination_builder_currency_field'),
+ 'constraints' => array(new GreaterThan(array('value' => 0)))
+ ))
+ ->add('reference', 'text', array(
+ 'label' => Translator::getInstance()->trans('Reference'),
+ 'label_attr' => array('for' => 'combination_builder_reference_field')
+ ))
+ ->add('price', 'number', array(
+ 'label' => Translator::getInstance()->trans('Product price excluding taxes'),
+ 'label_attr' => array('for' => 'combination_builder_price_field')
+ ))
+ ->add('weight', 'number', array(
+ 'label' => Translator::getInstance()->trans('Weight'),
+ 'label_attr' => array('for' => 'combination_builder_weight_field')
+ ))
+ ->add('quantity', 'number', array(
+ 'label' => Translator::getInstance()->trans('Available quantity'),
+ 'label_attr' => array('for' => 'combination_builder_quantity_field')
+ ))
+ ->add('sale_price', 'number', array(
+ 'label' => Translator::getInstance()->trans('Sale price excluding taxes'),
+ 'label_attr' => array('for' => 'combination_builder_price_with_tax_field')
+ ))
+ ->add('onsale', 'integer', array(
+ 'label' => Translator::getInstance()->trans('This product is on sale'),
+ 'label_attr' => array('for' => 'combination_builder_onsale_field')
+ ))
+ ->add('isnew', 'integer', array(
+ 'label' => Translator::getInstance()->trans('Advertise this product as new'),
+ 'label_attr' => array('for' => 'combination_builder_isnew_field')
+ ))
+ ->add('ean_code', 'text', array(
+ 'label' => Translator::getInstance()->trans('EAN Code'),
+ 'label_attr' => array('for' => 'combination_builder_ean_code_field')
+ ))
+ ->add('attribute_av', 'collection', array(
+ 'type' => 'text',
+ 'label' => Translator::getInstance()->trans('Attribute ID:Attribute AV ID'),
+ 'label_attr' => array('for' => 'combination_builder_attribute_av_id'),
+ 'allow_add' => true,
+ 'allow_delete' => true,
+ ))
+ ;
+ }
+
+ public function getName()
+ {
+ return 'thelia_product_combination_generation_form';
+ }
+}
\ No newline at end of file
diff --git a/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php b/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php
index 2643692a2..54fb2fdc1 100644
--- a/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php
+++ b/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php
@@ -29,8 +29,6 @@ use Thelia\Core\Translation\Translator;
class ProductDefaultSaleElementUpdateForm extends ProductSaleElementUpdateForm
{
- use StandardDescriptionFieldsTrait;
-
protected function buildForm()
{
$this->formBuilder
@@ -77,7 +75,7 @@ class ProductDefaultSaleElementUpdateForm extends ProductSaleElementUpdateForm
"label_attr" => array("for" => "quantity_field")
))
->add("sale_price", "number", array(
- "label" => Translator::getInstance()->trans("Sale price without taxes"),
+ "label" => Translator::getInstance()->trans("Sale price excluding taxes"),
"label_attr" => array("for" => "price_with_tax_field")
))
->add("sale_price_with_tax", "number", array(
diff --git a/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php b/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php
index da831545a..cda72cc72 100644
--- a/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php
+++ b/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php
@@ -29,8 +29,6 @@ use Thelia\Core\Translation\Translator;
class ProductSaleElementUpdateForm extends BaseForm
{
- use StandardDescriptionFieldsTrait;
-
protected function buildForm()
{
$this->formBuilder
@@ -112,7 +110,7 @@ class ProductSaleElementUpdateForm extends BaseForm
)
))
->add('sale_price', 'collection', array(
- 'label' => Translator::getInstance()->trans('Sale price without taxes'),
+ 'label' => Translator::getInstance()->trans('Sale price excluding taxes'),
'label_attr' => array('for' => 'price_with_tax_field'),
'allow_add' => true,
'allow_delete' => true,
diff --git a/core/lib/Thelia/Model/Attribute.php b/core/lib/Thelia/Model/Attribute.php
index 615fa643e..3439cac06 100755
--- a/core/lib/Thelia/Model/Attribute.php
+++ b/core/lib/Thelia/Model/Attribute.php
@@ -20,7 +20,7 @@ class Attribute extends BaseAttribute {
$this->dispatchEvent(TheliaEvents::BEFORE_CREATEATTRIBUTE, new AttributeEvent($this));
// Set the current position for the new object
- //$this->setPosition($this->getNextPosition());
+ $this->setPosition($this->getNextPosition());
return true;
}
diff --git a/core/lib/Thelia/Model/Feature.php b/core/lib/Thelia/Model/Feature.php
index 800ff832a..2627d5190 100755
--- a/core/lib/Thelia/Model/Feature.php
+++ b/core/lib/Thelia/Model/Feature.php
@@ -20,7 +20,7 @@ class Feature extends BaseFeature {
$this->dispatchEvent(TheliaEvents::BEFORE_CREATEFEATURE, new FeatureEvent($this));
// Set the current position for the new object
- //$this->setPosition($this->getNextPosition());
+ $this->setPosition($this->getNextPosition());
return true;
}
diff --git a/core/lib/Thelia/Model/Product.php b/core/lib/Thelia/Model/Product.php
index f16a8a776..1b3f1eefa 100755
--- a/core/lib/Thelia/Model/Product.php
+++ b/core/lib/Thelia/Model/Product.php
@@ -167,7 +167,7 @@ class Product extends BaseProduct
$this->setTaxRuleId($taxRuleId);
// Create the default product sale element of this product
- $sale_elements = $this->createDefaultProductSaleElement($con, $baseWeight, $basePrice, $priceCurrencyId, true);
+ $sale_elements = $this->createProductSaleElement($con, $baseWeight, $basePrice, $basePrice, $priceCurrencyId, true);
// Store all the stuff !
$con->commit();
@@ -185,19 +185,20 @@ class Product extends BaseProduct
/**
* Create a basic product sale element attached to this product.
*/
- public function createDefaultProductSaleElement(ConnectionInterface $con, $weight, $basePrice, $currencyId, $isDefault) {
+ public function createProductSaleElement(ConnectionInterface $con, $weight, $basePrice, $salePrice, $currencyId, $isDefault, $isPromo = false, $isNew = false, $quantity = 0, $eanCode = '', $ref = false) {
// Create an empty product sale element
$sale_elements = new ProductSaleElements();
$sale_elements
->setProduct($this)
- ->setRef($this->getRef())
- ->setPromo(0)
- ->setNewness(0)
+ ->setRef($ref == false ? $this->getRef() : $ref)
+ ->setPromo($isPromo)
+ ->setNewness($isNew)
->setWeight($weight)
->setIsDefault($isDefault)
- ->setEanCode('')
+ ->setEanCode($eanCode)
+ ->setQuantity($quantity)
->save($con)
;
@@ -206,7 +207,7 @@ class Product extends BaseProduct
$product_price
->setProductSaleElements($sale_elements)
- ->setPromoPrice($basePrice)
+ ->setPromoPrice($salePrice)
->setPrice($basePrice)
->setCurrencyId($currencyId)
->save($con)
diff --git a/templates/admin/default/assets/less/thelia/modals.less b/templates/admin/default/assets/less/thelia/modals.less
index 2d371e6c0..ee6b3c662 100755
--- a/templates/admin/default/assets/less/thelia/modals.less
+++ b/templates/admin/default/assets/less/thelia/modals.less
@@ -9,7 +9,22 @@
}
}
+.modal-header {
+ h3 {
+ margin-bottom: 0;
+ }
+}
+
// Body (where all modal content resides)
.modal-body {
max-height: none;
+ .scrollable {
+ border: 1px solid @input-border;
+ border-radius: @input-border-radius;
+ height: 458px;
+ overflow: auto;
+ padding-bottom: 5px;
+ padding-left: 10px;
+ padding-top: 5px;
+ }
}
\ No newline at end of file
diff --git a/templates/admin/default/includes/generic-js-dialog.html b/templates/admin/default/includes/generic-js-dialog.html
index 891bb0957..f12a64664 100644
--- a/templates/admin/default/includes/generic-js-dialog.html
+++ b/templates/admin/default/includes/generic-js-dialog.html
@@ -30,6 +30,13 @@ $('#{$dialog_id}').on('hidden.bs.modal', function() {
// Clear error status
$("#{$dialog_id} .error").removeClass('error');
+ $('#{$dialog_id} .form-group').removeClass('has-error')
+
// Empty field values
$("#{$dialog_id} input[type=text], #{$dialog_id} select").val('');
+
+ // Uncheck boxes
+ $("#{$dialog_id} input[type=checkbox]").removeAttr('checked');
+
+ {$additionnal_js_code|default:''}
});
\ No newline at end of file
diff --git a/templates/admin/default/includes/product-details-tab.html b/templates/admin/default/includes/product-details-tab.html
index 67b20ab77..096b0a7e7 100644
--- a/templates/admin/default/includes/product-details-tab.html
+++ b/templates/admin/default/includes/product-details-tab.html
@@ -26,9 +26,8 @@
close_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}"
}
- {* Be sure to get the product ID, even if the form could not be validated *}
+ {* Be sure to get the product ID and current tab, even if the form could not be validated *}
-
{form_hidden_fields form=$form}
@@ -177,8 +176,6 @@
{/form_field}
- {module_include location='product_details_shipping_form'}
-
{form_field form=$form field='quantity'}
@@ -189,7 +186,7 @@
{/form_field}
- {module_include location='product_details_quantity_form'}
+ {module_include location='product_details_details_form'}
@@ -268,9 +265,8 @@
close_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}"
}
- {* Be sure to get the product ID, even if the form could not be validated *}
+ {* Be sure to get the product ID and current tab, even if the form could not be validated *}
-
{form_hidden_fields form=$form}
@@ -340,7 +336,7 @@
{module_include location='product_combinations_list_caption'}
{loop type="auth" name="can_create" role="ADMIN" resource="admin.product" access="UPDATE"}
-
+
{intl l='Combination builder'}
@@ -358,8 +354,8 @@
- {intl
- l='This product has no combination. The default price is used. Click here to create a new combination'
- url='#combination_creation_dialog'
- }
+
{intl
+ l='This product has no combination. The default price is used. Click here to create a new combination.'
+ url='#combination_creation_dialog'
+ }
+
+ {intl
+ l='You may also quickly create combinations from products attributes using the Combination Builder.'
+ url='#combination_builder_dialog'
+ }
+
@@ -494,7 +498,7 @@
@@ -583,3 +587,184 @@
form_action = {url path='/admin/product/combination/delete'}
form_content = {$smarty.capture.combination_delete_dialog nofilter}
}
+
+{* -- Combination builder dialog -------------------------------------------- *}
+
+{* Capture the dialog body, to pass it to the generic dialog *}
+
+{form name="thelia.admin.product_combination.build"}
+
+{capture "combination_builder_dialog"}
+
+ {* Be sure to get the product ID and current tab, even if the form could not be validated *}
+
+
+
+ {form_hidden_fields form=$form}
+
+ {form_field form=$form field='product_id'}
+
+ {/form_field}
+
+ {if $form_error}