Finished product combinations edition
This commit is contained in:
@@ -215,10 +215,14 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface
|
||||
// If we just deleted the last PSE, create a default one
|
||||
$product->createDefaultProductSaleElement($con, 0, 0, $event->getCurrencyId(), true);
|
||||
}
|
||||
else if ($product->getDefaultSaleElements() == null) {
|
||||
else if ($pse->getIsDefault()) {
|
||||
|
||||
// If we deleted the default PSE, make the last created one the default
|
||||
$pse = ProductSaleElementsQuery::create()->filterByProductId($this->id)->orderByCreatedAt(Criteria::DESC)->findOne($con);
|
||||
$pse = ProductSaleElementsQuery::create()
|
||||
->filterByProductId($product->getId())
|
||||
->orderByCreatedAt(Criteria::DESC)
|
||||
->findOne($con)
|
||||
;
|
||||
|
||||
$pse->setIsDefault(true)->save($con);
|
||||
}
|
||||
|
||||
@@ -364,8 +364,8 @@
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::deleteProductSaleElementAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.product.combination.update" path="/admin/product/combination/update">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::updateProductSaleElementAction</default>
|
||||
<route id="admin.product.combination.update" path="/admin/product/combinations/update">
|
||||
<default key="_controller">Thelia\Controller\Admin\ProductController::updateProductSaleElementsAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.product.combination.defaut-price.update" path="/admin/product/default-price/update">
|
||||
|
||||
@@ -206,10 +206,14 @@ class ProductController extends AbstractCrudController
|
||||
}
|
||||
}
|
||||
|
||||
protected function appendValue(&$array, $key, $value) {
|
||||
if (! isset($array[$key])) $array[$key] = array();
|
||||
|
||||
$array[$key][] = $value;
|
||||
}
|
||||
|
||||
protected function hydrateObjectForm($object)
|
||||
{
|
||||
$defaultPseData = $combinationPseData = array();
|
||||
|
||||
// Find product's sale elements
|
||||
$saleElements = ProductSaleElementsQuery::create()
|
||||
->filterByProduct($object)
|
||||
@@ -218,6 +222,12 @@ class ProductController extends AbstractCrudController
|
||||
$defaultCurrency = Currency::getDefaultCurrency();
|
||||
$currentCurrency = $this->getCurrentEditionCurrency();
|
||||
|
||||
// Common parts
|
||||
$defaultPseData = $combinationPseData = array(
|
||||
"product_id" => $object->getId(),
|
||||
"tax_rule" => $object->getTaxRuleId()
|
||||
);
|
||||
|
||||
foreach($saleElements as $saleElement) {
|
||||
|
||||
// Get the product price for the current currency
|
||||
@@ -251,15 +261,12 @@ class ProductController extends AbstractCrudController
|
||||
// If this PSE has no combination -> this is the default one
|
||||
// affect it to the thelia.admin.product_sale_element.update form
|
||||
if ($isDefaultPse) {
|
||||
|
||||
$defaultPseData = array(
|
||||
"product_id" => $object->getId(),
|
||||
"product_sale_element_id" => $saleElement->getId(),
|
||||
"reference" => $saleElement->getRef(),
|
||||
"price" => $productPrice->getPrice(),
|
||||
"price_with_tax" => $this->computePrice($productPrice->getPrice(), 'without_tax', $object),
|
||||
"use_exchange_rate" => $productPrice->getFromDefaultCurrency() ? 1 : 0,
|
||||
"tax_rule" => $object->getTaxRuleId(),
|
||||
"currency" => $productPrice->getCurrencyId(),
|
||||
"weight" => $saleElement->getWeight(),
|
||||
"quantity" => $saleElement->getQuantity(),
|
||||
@@ -272,6 +279,25 @@ class ProductController extends AbstractCrudController
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
if ($saleElement->getIsDefault()) {
|
||||
$combinationPseData['default_pse'] = $saleElement->getId();
|
||||
$combinationPseData['currency'] = $currentCurrency->getId();
|
||||
$combinationPseData['use_exchange_rate'] = $productPrice->getFromDefaultCurrency() ? 1 : 0;
|
||||
}
|
||||
|
||||
$this->appendValue($combinationPseData, "product_sale_element_id" , $saleElement->getId());
|
||||
$this->appendValue($combinationPseData, "reference" , $saleElement->getRef());
|
||||
$this->appendValue($combinationPseData, "price" , $productPrice->getPrice());
|
||||
$this->appendValue($combinationPseData, "price_with_tax" , $this->computePrice($productPrice->getPrice(), 'without_tax', $object));
|
||||
$this->appendValue($combinationPseData, "weight" , $saleElement->getWeight());
|
||||
$this->appendValue($combinationPseData, "quantity" , $saleElement->getQuantity());
|
||||
$this->appendValue($combinationPseData, "sale_price" , $productPrice->getPromoPrice());
|
||||
$this->appendValue($combinationPseData, "sale_price_with_tax" , $this->computePrice($productPrice->getPromoPrice(), 'without_tax', $object));
|
||||
$this->appendValue($combinationPseData, "onsale" , $saleElement->getPromo() > 0 ? 1 : 0);
|
||||
$this->appendValue($combinationPseData, "isnew" , $saleElement->getNewness() > 0 ? 1 : 0);
|
||||
$this->appendValue($combinationPseData, "isdefault" , $saleElement->getIsDefault() > 0 ? 1 : 0);
|
||||
$this->appendValue($combinationPseData, "ean_code" , $saleElement->getEanCode());
|
||||
}
|
||||
|
||||
$defaultPseForm = new ProductDefaultSaleElementUpdateForm($this->getRequest(), "form", $defaultPseData);
|
||||
@@ -281,7 +307,7 @@ class ProductController extends AbstractCrudController
|
||||
$this->getParserContext()->addForm($combinationPseForm);
|
||||
}
|
||||
|
||||
// Prepare the data that will hydrate the form(s)
|
||||
// The "General" tab form
|
||||
$data = array(
|
||||
'id' => $object->getId(),
|
||||
'ref' => $object->getRef(),
|
||||
@@ -878,11 +904,47 @@ class ProductController extends AbstractCrudController
|
||||
$this->redirectToEditionTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single PSE update, using form data array.
|
||||
*
|
||||
* @param array $data the form data
|
||||
* @throws Exception is someting goes wrong.
|
||||
*/
|
||||
protected function processSingleProductSaleElementUpdate($data)
|
||||
{
|
||||
$event = new ProductSaleElementUpdateEvent(
|
||||
$this->getExistingObject(),
|
||||
$data['product_sale_element_id']
|
||||
);
|
||||
|
||||
$event
|
||||
->setReference($data['reference'])
|
||||
->setPrice($data['price'])
|
||||
->setCurrencyId($data['currency'])
|
||||
->setWeight($data['weight'])
|
||||
->setQuantity($data['quantity'])
|
||||
->setSalePrice($data['sale_price'])
|
||||
->setOnsale($data['onsale'])
|
||||
->setIsnew($data['isnew'])
|
||||
->setIsdefault($data['isdefault'])
|
||||
->setEanCode($data['ean_code'])
|
||||
->setTaxRuleId($data['tax_rule'])
|
||||
->setFromDefaultCurrency($data['use_exchange_rate'])
|
||||
;
|
||||
|
||||
$this->dispatch(TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT, $event);
|
||||
|
||||
// Log object modification
|
||||
if (null !== $changedObject = $event->getProductSaleElement()) {
|
||||
$this->adminLogAppend(sprintf("Product Sale Element (ID %s) for product reference %s modified", $changedObject->getId(), $event->getProduct()->getRef()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a product sale element
|
||||
*/
|
||||
protected function processProductSaleElementUpdate($changeForm) {
|
||||
|
||||
protected function processProductSaleElementUpdate($changeForm)
|
||||
{
|
||||
// Check current user authorization
|
||||
if (null !== $response = $this->checkAuth($this->resourceCode, AccessManager::UPDATE)) return $response;
|
||||
|
||||
@@ -896,31 +958,35 @@ class ProductController extends AbstractCrudController
|
||||
// Get the form field values
|
||||
$data = $form->getData();
|
||||
|
||||
$event = new ProductSaleElementUpdateEvent(
|
||||
$this->getExistingObject(),
|
||||
$data['product_sale_element_id']
|
||||
);
|
||||
if (is_array($data['product_sale_element_id'])) {
|
||||
|
||||
$event
|
||||
->setReference($data['reference'])
|
||||
->setPrice($data['price'])
|
||||
->setCurrencyId($data['currency'])
|
||||
->setWeight($data['weight'])
|
||||
->setQuantity($data['quantity'])
|
||||
->setSalePrice($data['sale_price'])
|
||||
->setOnsale($data['onsale'])
|
||||
->setIsnew($data['isnew'])
|
||||
->setIsdefault($data['isdefault'])
|
||||
->setEanCode($data['ean_code'])
|
||||
->setTaxRuleId($data['tax_rule'])
|
||||
->setFromDefaultCurrency($data['use_exchange_rate'])
|
||||
;
|
||||
// Common fields
|
||||
$tmp_data = array(
|
||||
'tax_rule' => $data['tax_rule'],
|
||||
'currency' => $data['currency'],
|
||||
'use_exchange_rate' => $data['use_exchange_rate'],
|
||||
);
|
||||
|
||||
$this->dispatch(TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT, $event);
|
||||
$count = count($data['product_sale_element_id']);
|
||||
|
||||
// Log object modification
|
||||
if (null !== $changedObject = $event->getProductSaleElement()) {
|
||||
$this->adminLogAppend(sprintf("Product Sale Element (ID %s) for product reference %s modified", $changedObject->getId(), $event->getProduct()->getRef()));
|
||||
for($idx = 0; $idx < $count; $idx++) {
|
||||
$tmp_data['product_sale_element_id'] = $pse_id = $data['product_sale_element_id'][$idx];
|
||||
$tmp_data['reference'] = $data['reference'][$idx];
|
||||
$tmp_data['price'] = $data['price'][$idx];
|
||||
$tmp_data['weight'] = $data['weight'][$idx];
|
||||
$tmp_data['quantity'] = $data['quantity'][$idx];
|
||||
$tmp_data['sale_price'] = $data['sale_price'][$idx];
|
||||
$tmp_data['onsale'] = isset($data['onsale'][$idx]) ? 1 : 0;
|
||||
$tmp_data['isnew'] = isset($data['isnew'][$idx]) ? 1 : 0;
|
||||
$tmp_data['isdefault'] = $data['default_pse'] == $pse_id;
|
||||
$tmp_data['ean_code'] = $data['ean_code'][$idx];
|
||||
|
||||
$this->processSingleProductSaleElementUpdate($tmp_data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No need to preprocess data
|
||||
$this->processSingleProductSaleElementUpdate($data);
|
||||
}
|
||||
|
||||
// If we have to stay on the same page, do not redirect to the succesUrl, just redirect to the edit page again.
|
||||
@@ -948,9 +1014,9 @@ class ProductController extends AbstractCrudController
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a product sale element attached to a combination
|
||||
* Process the change of product's PSE list.
|
||||
*/
|
||||
public function updateProductSaleElementAction() {
|
||||
public function updateProductSaleElementsAction() {
|
||||
return $this->processProductSaleElementUpdate(
|
||||
new ProductSaleElementUpdateForm($this->getRequest())
|
||||
);
|
||||
@@ -960,14 +1026,13 @@ class ProductController extends AbstractCrudController
|
||||
* Update default product sale element (not attached to any combination)
|
||||
*/
|
||||
public function updateProductDefaultSaleElementAction() {
|
||||
|
||||
return $this->processProductSaleElementUpdate(
|
||||
new ProductDefaultSaleElementUpdateForm($this->getRequest())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked through Ajax; this methow calculate the taxed price from the unaxed price, and
|
||||
* Invoked through Ajax; this method calculates the taxed price from the unaxed price, and
|
||||
* vice versa.
|
||||
*/
|
||||
public function priceCaclulator() {
|
||||
@@ -999,6 +1064,11 @@ class ProductController extends AbstractCrudController
|
||||
return new JsonResponse(array('result' => $return_price));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate all prices
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function loadConvertedPrices() {
|
||||
|
||||
$product_sale_element_id = intval($this->getRequest()->get('product_sale_element_id', 0));
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Controller\Admin;
|
||||
|
||||
use Thelia\Form\TestForm;
|
||||
/**
|
||||
* Manages variables
|
||||
*
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class TestController extends BaseAdminController
|
||||
{
|
||||
/**
|
||||
* Load a object for modification, and display the edit template.
|
||||
*
|
||||
* @return Symfony\Component\HttpFoundation\Response the response
|
||||
*/
|
||||
public function updateAction()
|
||||
{
|
||||
// Prepare the data that will hydrate the form
|
||||
$data = array(
|
||||
'title' => "test title",
|
||||
'test' => array('a', 'b', 'toto' => 'c')
|
||||
);
|
||||
|
||||
// Setup the object form
|
||||
$changeForm = new TestForm($this->getRequest(), "form", $data);
|
||||
|
||||
// Pass it to the parser
|
||||
$this->getParserContext()->addForm($changeForm);
|
||||
|
||||
return $this->render('test-form');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save changes on a modified object, and either go back to the object list, or stay on the edition page.
|
||||
*
|
||||
* @return Symfony\Component\HttpFoundation\Response the response
|
||||
*/
|
||||
public function processUpdateAction()
|
||||
{
|
||||
$error_msg = false;
|
||||
|
||||
// Create the form from the request
|
||||
$changeForm = new TestForm($this->getRequest());
|
||||
|
||||
try {
|
||||
|
||||
// Check the form against constraints violations
|
||||
$form = $this->validateForm($changeForm, "POST");
|
||||
|
||||
// Get the form field values
|
||||
$data = $form->getData();
|
||||
|
||||
echo "data=";
|
||||
|
||||
var_dump($data);
|
||||
}
|
||||
catch (FormValidationException $ex) {
|
||||
// Form cannot be validated
|
||||
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
|
||||
}
|
||||
catch (\Exception $ex) {
|
||||
// Any other error
|
||||
$error_msg = $ex->getMessage();
|
||||
}
|
||||
|
||||
echo "Error = $error_msg";
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ class Form extends AbstractSmartyPlugin
|
||||
}
|
||||
}
|
||||
|
||||
protected function assignFieldValues($template, $fieldName, $fieldValue, $fieldVars)
|
||||
protected function assignFieldValues($template, $fieldName, $fieldValue, $fieldVars, $total_value_count = 1)
|
||||
{
|
||||
$template->assign("name", $fieldName);
|
||||
|
||||
@@ -136,6 +136,8 @@ class Form extends AbstractSmartyPlugin
|
||||
|
||||
$template->assign('required', isset($fieldVars['required']) ? $fieldVars['required'] : false);
|
||||
|
||||
$template->assign('total_value_count', $total_value_count);
|
||||
|
||||
$errors = $fieldVars["errors"];
|
||||
|
||||
$template->assign("error", empty($errors) ? false : true);
|
||||
@@ -208,23 +210,19 @@ class Form extends AbstractSmartyPlugin
|
||||
$value = $formFieldView->vars["value"];
|
||||
|
||||
// We have a collection
|
||||
if (count($formFieldView->children) > 0) {
|
||||
if (0 < $value_count = count($formFieldView->children)) {
|
||||
|
||||
$key = $this->getParam($params, 'value_key');
|
||||
$key = $this->getParam($params, 'value_key', null);
|
||||
|
||||
if ($key != null) {
|
||||
if ($key !== null) {
|
||||
// If the field is not found, use an empty value
|
||||
$val = array_key_exists($key, $value) ? $value[$key] : '';
|
||||
|
||||
if (isset($value[$key])) {
|
||||
$name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key);
|
||||
|
||||
$name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key);
|
||||
$val = $value[$key];
|
||||
|
||||
$val = $value[$key];
|
||||
|
||||
$this->assignFieldValues($template, $name, $val, $formFieldView->vars);
|
||||
}
|
||||
else {
|
||||
throw new \LogicException(sprintf("Cannot find a value for key '%s' in field '%s'", $key, $formFieldView->vars["name"]));
|
||||
}
|
||||
$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"]));
|
||||
|
||||
@@ -22,8 +22,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 ProductDefaultSaleElementUpdateForm extends ProductSaleElementUpdateForm
|
||||
{
|
||||
use StandardDescriptionFieldsTrait;
|
||||
|
||||
protected function buildForm()
|
||||
{
|
||||
$this->formBuilder
|
||||
->add("product_id", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Product ID *"),
|
||||
"label_attr" => array("for" => "product_id_field"),
|
||||
"constraints" => array(new GreaterThan(array('value' => 0)))
|
||||
))
|
||||
->add("product_sale_element_id", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Product sale element ID *"),
|
||||
"label_attr" => array("for" => "product_sale_element_id_field")
|
||||
))
|
||||
->add("reference", "text", array(
|
||||
"label" => Translator::getInstance()->trans("Reference *"),
|
||||
"label_attr" => array("for" => "reference_field")
|
||||
))
|
||||
->add("price", "number", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Product price excluding taxes *"),
|
||||
"label_attr" => array("for" => "price_field")
|
||||
))
|
||||
->add("price_with_tax", "number", array(
|
||||
"label" => Translator::getInstance()->trans("Product price including taxes"),
|
||||
"label_attr" => array("for" => "price_with_tax_field")
|
||||
))
|
||||
->add("currency", "integer", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Price currency *"),
|
||||
"label_attr" => array("for" => "currency_field")
|
||||
))
|
||||
->add("tax_rule", "integer", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Tax rule for this product *"),
|
||||
"label_attr" => array("for" => "tax_rule_field")
|
||||
))
|
||||
->add("weight", "number", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Weight *"),
|
||||
"label_attr" => array("for" => "weight_field")
|
||||
))
|
||||
->add("quantity", "number", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Available quantity *"),
|
||||
"label_attr" => array("for" => "quantity_field")
|
||||
))
|
||||
->add("sale_price", "number", array(
|
||||
"label" => Translator::getInstance()->trans("Sale price without taxes"),
|
||||
"label_attr" => array("for" => "price_with_tax_field")
|
||||
))
|
||||
->add("sale_price_with_tax", "number", array(
|
||||
"label" => Translator::getInstance()->trans("Sale price including taxes"),
|
||||
"label_attr" => array("for" => "sale_price_with_tax_field")
|
||||
))
|
||||
->add("onsale", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("This product is on sale"),
|
||||
"label_attr" => array("for" => "onsale_field")
|
||||
))
|
||||
->add("isnew", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Advertise this product as new"),
|
||||
"label_attr" => array("for" => "isnew_field")
|
||||
))
|
||||
->add("isdefault", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Is it the default product sale element ?"),
|
||||
"label_attr" => array("for" => "isdefault_field")
|
||||
))
|
||||
->add("ean_code", "text", array(
|
||||
"label" => Translator::getInstance()->trans("EAN Code"),
|
||||
"label_attr" => array("for" => "ean_code_field")
|
||||
))
|
||||
->add("use_exchange_rate", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Apply exchange rates on price in %sym", array("%sym" => Currency::getDefaultCurrency()->getSymbol())),
|
||||
"label_attr" => array("for" => "use_exchange_rate_field")
|
||||
))
|
||||
;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return "thelia_product_default_sale_element_update_form";
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
namespace Thelia\Form;
|
||||
|
||||
use Symfony\Component\Validator\Constraints\GreaterThan;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Thelia\Model\Currency;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
|
||||
class ProductSaleElementUpdateForm extends BaseForm
|
||||
{
|
||||
@@ -34,76 +34,124 @@ class ProductSaleElementUpdateForm extends BaseForm
|
||||
protected function buildForm()
|
||||
{
|
||||
$this->formBuilder
|
||||
->add("tax_rule", "integer", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Tax rule for this product *"),
|
||||
"label_attr" => array("for" => "tax_rule_field")
|
||||
))
|
||||
->add("product_id", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Product ID *"),
|
||||
"label_attr" => array("for" => "product_id_field"),
|
||||
"constraints" => array(new GreaterThan(array('value' => 0)))
|
||||
"label" => Translator::getInstance()->trans("Product ID *"),
|
||||
"label_attr" => array("for" => "product_id_field"),
|
||||
"constraints" => array(new GreaterThan(array('value' => 0)))
|
||||
))
|
||||
->add("product_sale_element_id", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Product sale element ID *"),
|
||||
"label_attr" => array("for" => "product_sale_element_id_field")
|
||||
))
|
||||
->add("reference", "text", array(
|
||||
"label" => Translator::getInstance()->trans("Reference *"),
|
||||
"label_attr" => array("for" => "reference_field")
|
||||
))
|
||||
->add("price", "number", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Product price excluding taxes *"),
|
||||
"label_attr" => array("for" => "price_field")
|
||||
))
|
||||
->add("price_with_tax", "number", array(
|
||||
"label" => Translator::getInstance()->trans("Product price including taxes"),
|
||||
"label_attr" => array("for" => "price_with_tax_field")
|
||||
->add("default_pse", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Default product sale element"),
|
||||
"label_attr" => array("for" => "default_pse_field"),
|
||||
))
|
||||
->add("currency", "integer", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Price currency *"),
|
||||
"label_attr" => array("for" => "currency_field")
|
||||
))
|
||||
->add("tax_rule", "integer", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Tax rule for this product *"),
|
||||
"label_attr" => array("for" => "tax_rule_field")
|
||||
))
|
||||
->add("weight", "number", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Weight *"),
|
||||
"label_attr" => array("for" => "weight_field")
|
||||
))
|
||||
->add("quantity", "number", array(
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Available quantity *"),
|
||||
"label_attr" => array("for" => "quantity_field")
|
||||
))
|
||||
->add("sale_price", "number", array(
|
||||
"label" => Translator::getInstance()->trans("Sale price without taxes"),
|
||||
"label_attr" => array("for" => "price_with_tax_field")
|
||||
))
|
||||
->add("sale_price_with_tax", "number", array(
|
||||
"label" => Translator::getInstance()->trans("Sale price including taxes"),
|
||||
"label_attr" => array("for" => "sale_price_with_tax_field")
|
||||
))
|
||||
->add("onsale", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("This product is on sale"),
|
||||
"label_attr" => array("for" => "onsale_field")
|
||||
))
|
||||
->add("isnew", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Advertise this product as new"),
|
||||
"label_attr" => array("for" => "isnew_field")
|
||||
))
|
||||
->add("isdefault", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Is it the default product sale element ?"),
|
||||
"label_attr" => array("for" => "isdefault_field")
|
||||
))
|
||||
->add("ean_code", "text", array(
|
||||
"label" => Translator::getInstance()->trans("EAN Code"),
|
||||
"label_attr" => array("for" => "ean_code_field")
|
||||
"constraints" => array(new NotBlank()),
|
||||
"label" => Translator::getInstance()->trans("Price currency *"),
|
||||
"label_attr" => array("for" => "currency_field")
|
||||
))
|
||||
->add("use_exchange_rate", "integer", array(
|
||||
"label" => Translator::getInstance()->trans("Apply exchange rates on price in %sym", array("%sym" => Currency::getDefaultCurrency()->getSymbol())),
|
||||
"label_attr" => array("for" => "use_exchange_rate_field")
|
||||
))
|
||||
|
||||
// -- Collections
|
||||
|
||||
->add('product_sale_element_id', 'collection', array(
|
||||
'type' => 'integer',
|
||||
'label' => Translator::getInstance()->trans('Product sale element ID *'),
|
||||
'label_attr' => array('for' => 'product_sale_element_id_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
->add('reference', 'collection', array(
|
||||
'type' => 'text',
|
||||
'label' => Translator::getInstance()->trans('Reference *'),
|
||||
'label_attr' => array('for' => 'reference_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
->add('price', 'collection', array(
|
||||
'type' => 'number',
|
||||
'label' => Translator::getInstance()->trans('Product price excluding taxes *'),
|
||||
'label_attr' => array('for' => 'price_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
'options' => array(
|
||||
'constraints' => array(new NotBlank()),
|
||||
)
|
||||
))
|
||||
->add('price_with_tax', 'collection', array(
|
||||
'type' => 'number',
|
||||
'label' => Translator::getInstance()->trans('Product price including taxes'),
|
||||
'label_attr' => array('for' => 'price_with_tax_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
->add('weight', 'collection', array(
|
||||
'type' => 'number',
|
||||
'label' => Translator::getInstance()->trans('Weight *'),
|
||||
'label_attr' => array('for' => 'weight_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
'options' => array(
|
||||
'constraints' => array(new NotBlank()),
|
||||
)
|
||||
))
|
||||
->add('quantity', 'collection', array(
|
||||
'type' => 'number',
|
||||
'label' => Translator::getInstance()->trans('Available quantity *'),
|
||||
'label_attr' => array('for' => 'quantity_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
'options' => array(
|
||||
'constraints' => array(new NotBlank()),
|
||||
)
|
||||
))
|
||||
->add('sale_price', 'collection', array(
|
||||
'label' => Translator::getInstance()->trans('Sale price without taxes'),
|
||||
'label_attr' => array('for' => 'price_with_tax_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
->add('sale_price_with_tax', 'collection', array(
|
||||
'type' => 'number',
|
||||
'label' => Translator::getInstance()->trans('Sale price including taxes'),
|
||||
'label_attr' => array('for' => 'sale_price_with_tax_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
->add('onsale', 'collection', array(
|
||||
'type' => 'integer',
|
||||
'label' => Translator::getInstance()->trans('This product is on sale'),
|
||||
'label_attr' => array('for' => 'onsale_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
->add('isnew', 'collection', array(
|
||||
'type' => 'integer',
|
||||
'label' => Translator::getInstance()->trans('Advertise this product as new'),
|
||||
'label_attr' => array('for' => 'isnew_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
->add('isdefault', 'collection', array(
|
||||
'type' => 'integer',
|
||||
'label' => Translator::getInstance()->trans('Is it the default product sale element ?'),
|
||||
'label_attr' => array('for' => 'isdefault_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
->add('ean_code', 'collection', array(
|
||||
'type' => 'text',
|
||||
'label' => Translator::getInstance()->trans('EAN Code'),
|
||||
'label_attr' => array('for' => 'ean_code_field'),
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
))
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -192,6 +192,7 @@ class Product extends BaseProduct
|
||||
->setNewness(0)
|
||||
->setWeight($weight)
|
||||
->setIsDefault($isDefault)
|
||||
->setEanCode('')
|
||||
->save($con)
|
||||
;
|
||||
|
||||
|
||||
@@ -426,7 +426,7 @@ try {
|
||||
$stock->setNewness($faker->randomNumber(0,1));
|
||||
$stock->setWeight($faker->randomFloat(2, 100,10000));
|
||||
$stock->setIsDefault($i == 0);
|
||||
$stock->setEanCode(strtoupper($faker->text(13)));
|
||||
$stock->setEanCode(substr(str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 13));
|
||||
$stock->save();
|
||||
|
||||
$productPrice = new \Thelia\Model\ProductPrice();
|
||||
|
||||
@@ -257,37 +257,79 @@
|
||||
|
||||
{form name="thelia.admin.product_sale_element.update"}
|
||||
<form method="POST" action="{url path='/admin/product/combinations/update'}" {form_enctype form=$form}>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{include
|
||||
file = "includes/inner-form-toolbar.html"
|
||||
hide_submit_buttons = false
|
||||
show_currencies = true
|
||||
page_url = "{url path='/admin/products/update' product_id=$ID}"
|
||||
close_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}"
|
||||
}
|
||||
|
||||
{include
|
||||
file = "includes/inner-form-toolbar.html"
|
||||
hide_submit_buttons = false
|
||||
show_currencies = true
|
||||
page_url = "{url path='/admin/products/update' product_id=$ID}"
|
||||
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 *}
|
||||
<input type="hidden" name="product_id" value="{$product_id}" />
|
||||
|
||||
{if $form_error}<div class="alert alert-danger">{$form_error_message}</div>{/if}
|
||||
<input type="hidden" name="current_tab" value="details" />
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{form_field form=$form field='tax_rule'}
|
||||
<div class="form-group {if $error}has-error{/if}">
|
||||
<label for="tax_rule_field" class="control-label">{$label} : </label>
|
||||
<div class="form-group">
|
||||
<select id="tax_rule_field" required="required" name="{$name}" class="form-control">
|
||||
<option value="">{intl l="Select a tax tule"}</option>
|
||||
{loop name="tax" type="tax-rule" backend_context="1"}
|
||||
<option value="{$ID}" {if $ID == $TAX_RULE_ID}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{/form_field}
|
||||
</div>
|
||||
</div>
|
||||
{form_hidden_fields form=$form}
|
||||
|
||||
{form_field form=$form field='product_id'}
|
||||
<input type="hidden" name="{$name}" value="{$value}" />
|
||||
{/form_field}
|
||||
|
||||
{form_field form=$form field='success_url'}
|
||||
<input type="hidden" name="{$name}" value="{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}" />
|
||||
{/form_field}
|
||||
|
||||
{if $form_error}<div class="alert alert-danger">{$form_error_message}</div>{/if}
|
||||
|
||||
{loop type="currency" name="get-currency-symbol" id=$edit_currency_id backend_context="1"}
|
||||
{$currency_symbol = $SYMBOL}
|
||||
{$current_currency_is_default = $IS_DEFAULT}
|
||||
|
||||
{form_field form=$form field='currency'}
|
||||
<input type="hidden" name="{$name}" value="{$ID}" />
|
||||
{/form_field}
|
||||
{/loop}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{form_field form=$form field='tax_rule'}
|
||||
<div class="form-group {if $error}has-error{/if}">
|
||||
<label for="tax_rule_field" class="control-label">{$label} : </label>
|
||||
<div class="form-group">
|
||||
<select id="tax_rule_field" required="required" name="{$name}" class="form-control">
|
||||
<option value="">{intl l="Select a tax tule"}</option>
|
||||
{loop name="tax" type="tax-rule" backend_context="1"}
|
||||
<option value="{$ID}" {if $ID == $TAX_RULE_ID}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{/form_field}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{form_field form=$form field='use_exchange_rate'}
|
||||
{if $current_currency_is_default}
|
||||
<input type="hidden" name="{$name}" value="0">
|
||||
{$show_pricing_fields = true}
|
||||
{else}
|
||||
<div class="form-group {if $error}has-error{/if}">
|
||||
<label> </label>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" class="use_exchange_rate_box" name="{$name}" value="1" {if $value != 0}checked="checked"{/if}>
|
||||
{$label}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{$show_pricing_fields = ($value == 0)}
|
||||
{/if}
|
||||
{/form_field}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{module_include location='product_before_combinations'}
|
||||
|
||||
@@ -298,6 +340,9 @@
|
||||
{module_include location='product_combinations_list_caption'}
|
||||
|
||||
{loop type="auth" name="can_create" role="ADMIN" resource="admin.product" access="UPDATE"}
|
||||
<a class="btn btn-default btn-primary action-btn" title="{intl l='Quickly create combinations using the combination builder'}" href="#combination_generator_dialog" data-toggle="modal">
|
||||
{intl l='Combination builder'}
|
||||
</a>
|
||||
<a class="btn btn-default btn-primary action-btn" title="{intl l='Add a new combination'}" href="#combination_creation_dialog" data-toggle="modal">
|
||||
<span class="glyphicon glyphicon-plus-sign"></span>
|
||||
</a>
|
||||
@@ -322,43 +367,91 @@
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{loop name="product.sales.elements" type="product_sale_elements" product=$product_id currency=$edit_currency_id backend_context="1"}
|
||||
{* Get number of PSE defined, assumin the form have the same number of values for each fields *}
|
||||
|
||||
{form_field form=$form field='product_sale_element_id' value_key=0}
|
||||
{$pse_count = $total_value_count}
|
||||
{/form_field}
|
||||
|
||||
{for $idx = 0 to $total_value_count-1}
|
||||
<tr>
|
||||
<td colspan="12">
|
||||
{$ID}: {loop name="product.sales.elements.combinations" type="attribute_combination" product_sale_elements=$ID backend_context="1"}
|
||||
{if $LOOP_COUNT > 1} - {/if}{$ATTRIBUTE_TITLE}
|
||||
{/loop}
|
||||
|
||||
{form_field form=$form field='product_sale_element_id' value_key=$idx}
|
||||
<input type="hidden" name="{$name}" value="{$value}" />
|
||||
|
||||
{$current_pse_id = $value}
|
||||
|
||||
{$current_pse_id}: {loop name="product.sales.elements.combinations" type="attribute_combination" product_sale_elements=$current_pse_id backend_context="1"}
|
||||
{if $LOOP_COUNT > 1} - {/if}{$ATTRIBUTE_TITLE}
|
||||
{/loop}
|
||||
{/form_field}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td><input class="form-control text-right" type="text" name="quantity[{$ID}]" value="{$REF}" /></td>
|
||||
<td><input class="form-control text-right" type="text" name="quantity[{$ID}]" value="{$EAN_CODE}" /></td>
|
||||
<td><input class="form-control text-right" type="text" name="quantity[{$ID}]" value="{$QUANTITY}" /></td>
|
||||
<td><input class="form-control text-right" type="text" name="price_wo_taxes[{$ID}]" value="{format_number number=$PRICE}" /></td>
|
||||
<td><input class="form-control text-right" type="text" name="price_w_taxes[{$ID}]" value="{format_number number=$TAXED_PRICE}" /></td>
|
||||
<td><input class="form-control text-right col-lg-1" type="text" name="weight[{$ID}]" value="{$WEIGHT}" /></td>
|
||||
<tr>
|
||||
{form_field form=$form field='reference' value_key=$idx}
|
||||
<td {if $error}class="has-error"{/if}><input class="form-control" type="text" name="{$name}" value="{$value}" /></td>
|
||||
{/form_field}
|
||||
|
||||
<td class="text-center">
|
||||
<input class="form-control" type="radio" name="default" value="{$ID}" {if $IS_DEFAULT}checked="checked"{/if}/>
|
||||
{form_field form=$form field='ean_code' value_key=$idx}
|
||||
<td {if $error}class="has-error"{/if}><input class="form-control" type="text" name="{$name}" value="{$value}" /></td>
|
||||
{/form_field}
|
||||
|
||||
{form_field form=$form field='quantity' value_key=$idx}
|
||||
<td {if $error}class="has-error"{/if}>
|
||||
<input class="form-control text-right" required type="text" name="{$name}" value="{$value}" />
|
||||
</td>
|
||||
{/form_field}
|
||||
|
||||
<td class="text-center">
|
||||
<input class="form-control" type="checkbox" name="on_sale[{$ID}]" value="{$ID}" {if $IS_PROMO}checked="checked"{/if}/>
|
||||
</td>
|
||||
{form_field form=$form field='price' value_key=$idx}
|
||||
<td {if $error}class="has-error"{/if}><input {if !$show_pricing_fields}readonly{/if} required data-price-type="price-without-tax" data-rel-price="price_with_tax_{$idx}" id="price_without_tax_{$idx}" class="price_field automatic_price_field form-control text-right" required type="text" name="{$name}" value="{$value}" /></td>
|
||||
{/form_field}
|
||||
|
||||
<td class="text-center">
|
||||
<input class="form-control" type="checkbox" name="is_new[{$ID}]" value="{$ID}" {if $IS_NEW}checked="checked"{/if}/>
|
||||
</td>
|
||||
{form_field form=$form field='price_with_tax' value_key=$idx}
|
||||
<td {if $error}class="has-error"{/if}><input {if !$show_pricing_fields}readonly{/if} data-price-type="price-with-tax" data-rel-price="price_without_tax_{$idx}" id="price_with_tax_{$idx}" class="price_field automatic_price_field form-control text-right" type="text" name="{$name}" value="{$value}" /></td>
|
||||
{/form_field}
|
||||
|
||||
<td><input class="form-control text-right" type="text" name="sale_price_wo_taxes[{$ID}]" value="{format_number number=$PROMO_PRICE}" /></td>
|
||||
<td><input class="form-control text-right" type="text" name="sale_price_w_taxes[{$ID}]" value="{format_number number=$TAXED_PROMO_PRICE}" /></td>
|
||||
{form_field form=$form field='weight' value_key=$idx}
|
||||
<td {if $error}class="has-error"{/if}><input required class="form-control text-right" required type="text" name="{$name}" value="{$value}" /></td>
|
||||
{/form_field}
|
||||
|
||||
<td class="actions">
|
||||
<a class="btn btn-default btn-xs combination-delete" title="{intl l='Delete this combination'}" href="#combination_delete_dialog" data-id="{$ID}" data-toggle="modal"><i class="glyphicon glyphicon-trash"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{/loop}
|
||||
|
||||
{form_field form=$form field='default_pse'}
|
||||
<td class="{if $error}has-error {/if}text-center">
|
||||
<input class="form-control" type="radio" name="{$name}" value="{$current_pse_id}" {if $value == $current_pse_id}checked="checked"{/if}/>
|
||||
</td>
|
||||
{/form_field}
|
||||
|
||||
{form_field form=$form field='onsale' value_key=$idx}
|
||||
<td class="{if $error}has-error {/if}text-center">
|
||||
<input class="form-control" type="checkbox" name="{$name}" value="1" {if $value != 0}checked="checked"{/if}/>
|
||||
</td>
|
||||
{/form_field}
|
||||
|
||||
{form_field form=$form field='isnew' value_key=$idx}
|
||||
<td class="{if $error}has-error {/if}text-center">
|
||||
<input class="form-control" type="checkbox" name="{$name}" value="1" {if $value != 0}checked="checked"{/if}/>
|
||||
</td>
|
||||
{/form_field}
|
||||
|
||||
{form_field form=$form field='sale_price' value_key=$idx}
|
||||
<td {if $error}class="has-error"{/if}>
|
||||
<input {if !$show_pricing_fields}readonly{/if} required data-price-type="sale-price-without-tax" data-rel-price="sale_price_with_tax_{$idx}" id="sale_price_without_tax_{$idx}" class="price_field automatic_price_field form-control text-right" type="text" name="{$name}" value="{$value}" />
|
||||
</td>
|
||||
{/form_field}
|
||||
|
||||
{form_field form=$form field='sale_price_with_tax' value_key=$idx}
|
||||
<td {if $error}class="has-error"{/if}>
|
||||
<input {if !$show_pricing_fields}readonly{/if} data-price-type="sale-price-with-tax" data-rel-price="sale_price_without_tax_{$idx}" id="sale_price_with_tax_{$idx}" class="price_field automatic_price_field form-control text-right" type="text" name="{$name}" value="{$value}" />
|
||||
</td>
|
||||
{/form_field}
|
||||
|
||||
<td class="actions">
|
||||
<a class="btn btn-default btn-xs combination-delete" title="{intl l='Delete this combination'}" href="#combination_delete_dialog" data-id="{$current_pse_id}" data-toggle="modal"><i class="glyphicon glyphicon-trash"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{/for}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -348,7 +348,8 @@ $(function() {
|
||||
// will update the untaxed (resp. taxed) one
|
||||
$('.automatic_price_field').typeWatch({
|
||||
captureLength: 1,
|
||||
callback: function () {
|
||||
wait : 300,
|
||||
callback : function () {
|
||||
update_price($(this).val(), $(this).data('price-type'), $(this).data('rel-price'));
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user