Finished product combinations edition

This commit is contained in:
Franck Allimant
2013-10-25 00:32:56 +02:00
parent 10f78b90a5
commit 06cc8ce1ea
11 changed files with 466 additions and 261 deletions

View File

@@ -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);
}

View File

@@ -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">

View File

@@ -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));

View File

@@ -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;
}
}

View File

@@ -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"]));

View File

@@ -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";

View File

@@ -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,
))
;
}

View File

@@ -192,6 +192,7 @@ class Product extends BaseProduct
->setNewness(0)
->setWeight($weight)
->setIsDefault($isDefault)
->setEanCode('')
->save($con)
;

View File

@@ -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();

View File

@@ -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>&nbsp;</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>

View File

@@ -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'));
}
});