Fix several regressions with variants creation

This commit is contained in:
Laurent Destailleur 2020-08-17 13:55:18 +02:00
parent 96d4eeb8be
commit 5be10f133c
3 changed files with 84 additions and 79 deletions

View File

@ -189,7 +189,7 @@ class ProductCombination
/** /**
* Retrieves combination price levels * Retrieves combination price levels
* *
* @param int $clean Levels off PRODUIT_MULTIPRICES_LIMIT * @param int $clean Levels of PRODUIT_MULTIPRICES_LIMIT
* @return int <0 KO, >0 OK * @return int <0 KO, >0 OK
*/ */
public function saveCombinationPriceLevels($clean = 1) public function saveCombinationPriceLevels($clean = 1)
@ -201,26 +201,26 @@ class ProductCombination
$staticProductCombinationLevel = new ProductCombinationLevel($this->db); $staticProductCombinationLevel = new ProductCombinationLevel($this->db);
// Delete all // Delete all
if (empty($this->combination_price_levels)){ if (empty($this->combination_price_levels)) {
return $staticProductCombinationLevel->deleteAllForCombination($this->id); return $staticProductCombinationLevel->deleteAllForCombination($this->id);
} }
// Clean not needed price levels // Clean not needed price levels (level higher than number max defined into setup)
if ($clean){ if ($clean) {
$res = $staticProductCombinationLevel->clean($this->id); $res = $staticProductCombinationLevel->clean($this->id);
if ($res < 0) {
if ($res<0){
$this->errors[] = 'Fail to clean not needed price levels'; $this->errors[] = 'Fail to clean not needed price levels';
return -1; return -1;
} }
} }
foreach ($this->combination_price_levels as $fk_price_level => $combination_price_level){ foreach ($this->combination_price_levels as $fk_price_level => $combination_price_level) {
$res = $combination_price_level->save(); $res = $combination_price_level->save();
if ($res<1){ if ($res < 1) {
$this->error = 'save combination price level '.$fk_price_level . ' '.$combination_price_level->error; $this->error = 'Error saving combination price level '.$fk_price_level . ' : '.$combination_price_level->error;
$this->errors[] = $this->error; $this->errors[] = $this->error;
$error++; $error++;
break;
} }
} }
@ -340,27 +340,29 @@ class ProductCombination
{ {
global $conf; global $conf;
$sql = "INSERT INTO ".MAIN_DB_PREFIX."product_attribute_combination /* $this->fk_product_child may be empty and will be filled later after subproduct has been created */
(fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_weight, entity)
VALUES (".(int) $this->fk_product_parent.", ".(int) $this->fk_product_child.",
".(float) $this->variation_price.", ".(int) $this->variation_price_percentage.",
".(float) $this->variation_weight.", ".(int) $this->entity.")";
$query = $this->db->query($sql); $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_attribute_combination";
$sql .= " (fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_weight, entity)";
$sql .= " VALUES (".((int) $this->fk_product_parent).", ".((int) $this->fk_product_child).",";
$sql .= (float) $this->variation_price.", ".(int) $this->variation_price_percentage.",";
$sql .= (float) $this->variation_weight.", ".(int) $this->entity.")";
if (!$query) { $resql = $this->db->query($sql);
if ($resql) {
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'product_attribute_combination');
} else {
$this->error = $this->db->lasterror();
return -1; return -1;
} }
if (!empty($conf->global->PRODUIT_MULTIPRICES)) { if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
$res = $this->saveCombinationPriceLevels(); $res = $this->saveCombinationPriceLevels();
if ($res<0){ if ($res < 0) {
return -2; return -2;
} }
} }
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'product_attribute_combination');
return 1; return 1;
} }
@ -374,21 +376,19 @@ class ProductCombination
{ {
global $conf; global $conf;
$sql = "UPDATE ".MAIN_DB_PREFIX."product_attribute_combination $sql = "UPDATE ".MAIN_DB_PREFIX."product_attribute_combination";
SET fk_product_parent = ".(int) $this->fk_product_parent.", fk_product_child = ".(int) $this->fk_product_child.", $sql .= " SET fk_product_parent = ".(int) $this->fk_product_parent.", fk_product_child = ".(int) $this->fk_product_child.",";
variation_price = ".(float) $this->variation_price.", variation_price_percentage = ".(int) $this->variation_price_percentage.", $sql .= " variation_price = ".(float) $this->variation_price.", variation_price_percentage = ".(int) $this->variation_price_percentage.",";
variation_weight = ".(float) $this->variation_weight." WHERE rowid = ".(int) $this->id; $sql .= " variation_weight = ".(float) $this->variation_weight." WHERE rowid = ".((int) $this->id);
$query = $this->db->query($sql); $resql = $this->db->query($sql);
if (! $resql) {
if (!$query) {
return -1; return -1;
} }
if (!empty($conf->global->PRODUIT_MULTIPRICES)) { if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
$res = $this->saveCombinationPriceLevels(); $res = $this->saveCombinationPriceLevels();
if ($res<0){ if ($res < 0) {
return -2; return -2;
} }
} }
@ -603,10 +603,10 @@ class ProductCombination
} }
/** /**
* Retrieves all unique attributres for a parent product * Retrieves all unique attributes for a parent product
* *
* @param int $productid Product rowid * @param int $productid Product rowid
* @return ProductAttribute[] * @return ProductAttribute[] Array of attributes
*/ */
public function getUniqueAttributesAndValuesByFkProductParent($productid) public function getUniqueAttributesAndValuesByFkProductParent($productid)
{ {
@ -616,13 +616,11 @@ class ProductCombination
$variants = array(); $variants = array();
//Attributes //Attributes
$sql = "SELECT DISTINCT fk_prod_attr, a.rang $sql = "SELECT DISTINCT fk_prod_attr, a.rang";
FROM ".MAIN_DB_PREFIX."product_attribute_combination2val c2v LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination c $sql .= " FROM ".MAIN_DB_PREFIX."product_attribute_combination2val c2v LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination c ON c2v.fk_prod_combination = c.rowid";
ON c2v.fk_prod_combination = c.rowid $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product p ON p.rowid = c.fk_product_child";
LEFT JOIN ".MAIN_DB_PREFIX."product p ON p.rowid = c.fk_product_child $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute a ON a.rowid = fk_prod_attr";
LEFT JOIN ".MAIN_DB_PREFIX."product_attribute a ON a.rowid = fk_prod_attr $sql .= " WHERE c.fk_product_parent = ".((int) $productid)." AND p.tosell = 1";
WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
$sql .= $this->db->order('a.rang', 'asc'); $sql .= $this->db->order('a.rang', 'asc');
$query = $this->db->query($sql); $query = $this->db->query($sql);
@ -651,7 +649,6 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
/** /**
* Creates a product combination. Check usages to find more about its use * Creates a product combination. Check usages to find more about its use
*
* Format of $combinations array: * Format of $combinations array:
* array( * array(
* 0 => array( * 0 => array(
@ -662,15 +659,15 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
* [...] * [...]
* ) * )
* *
* @param User $user Object user * @param User $user Object user
* @param Product $product Parent product * @param Product $product Parent product
* @param array $combinations Attribute and value combinations. * @param array $combinations Attribute and value combinations.
* @param array $variations Price and weight variations * @param array $variations Price and weight variations
* @param bool|array $price_var_percent Is the price variation a relative variation? * @param bool|array $price_var_percent Is the price variation a relative variation?
* @param bool|float $forced_pricevar If the price variation is forced * @param bool|float $forced_pricevar If the price variation is forced
* @param bool|float $forced_weightvar If the weight variation is forced * @param bool|float $forced_weightvar If the weight variation is forced
* @param bool|string $forced_refvar If the reference is forced * @param bool|string $forced_refvar If the reference is forced
* @return int <0 KO, >0 OK * @return int <0 KO, >0 OK
*/ */
public function createProductCombination(User $user, Product $product, array $combinations, array $variations, $price_var_percent = false, $forced_pricevar = false, $forced_weightvar = false, $forced_refvar = false) public function createProductCombination(User $user, Product $product, array $combinations, array $variations, $price_var_percent = false, $forced_pricevar = false, $forced_weightvar = false, $forced_refvar = false)
{ {
@ -705,7 +702,7 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
$weight_impact = (float) $forced_weightvar; // If false, return 0 $weight_impact = (float) $forced_weightvar; // If false, return 0
//Final price impact //Final price impact
if (!is_array($forced_pricevar)){ if (!is_array($forced_pricevar)) {
$price_impact[1] = (float) $forced_pricevar; // If false, return 0 $price_impact[1] = (float) $forced_pricevar; // If false, return 0
} }
else { else {
@ -719,7 +716,12 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
$newcomb = $existingCombination; $newcomb = $existingCombination;
} else { } else {
$newcomb->fk_product_parent = $product->id; $newcomb->fk_product_parent = $product->id;
if ($newcomb->create($user) < 0) { // Create 1 entry into product_attribute_combination (1 entry for all combinations)
// Create 1 entry into product_attribute_combination (1 entry for each combinations). This init also $newcomb->id
$result = $newcomb->create($user);
if ($result < 0) {
$this->error = $newcomb->error;
$this->errors = $newcomb->errors;
$db->rollback(); $db->rollback();
return -1; return -1;
} }
@ -743,6 +745,8 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
$tmp->fk_prod_combination = $newcomb->id; $tmp->fk_prod_combination = $newcomb->id;
if ($tmp->create($user) < 0) { // Create 1 entry into product_attribute_combination2val if ($tmp->create($user) < 0) { // Create 1 entry into product_attribute_combination2val
$this->error = $tmp->error;
$this->errors = $tmp->errors;
$db->rollback(); $db->rollback();
return -1; return -1;
} }
@ -786,7 +790,7 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
if ($conf->global->PRODUIT_MULTIPRICES){ if ($conf->global->PRODUIT_MULTIPRICES){
for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++){ for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++){
$productCombinationLevel = new ProductCombinationLevel($this->db); $productCombinationLevel = new ProductCombinationLevel($this->db);
$productCombinationLevel->fk_product_attribute_combination = 0; $productCombinationLevel->fk_product_attribute_combination = $newcomb->id;
$productCombinationLevel->fk_price_level = $i; $productCombinationLevel->fk_price_level = $i;
$productCombinationLevel->variation_price = $price_impact[$i]; $productCombinationLevel->variation_price = $price_impact[$i];
@ -799,6 +803,7 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
$newcomb->combination_price_levels[$i] = $productCombinationLevel; $newcomb->combination_price_levels[$i] = $productCombinationLevel;
} }
} }
//var_dump($newcomb->combination_price_levels);
$newproduct->weight += $weight_impact; $newproduct->weight += $weight_impact;
@ -867,6 +872,8 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
if ($newcomb->update($user) < 0) if ($newcomb->update($user) < 0)
{ {
$this->error = $newcomb->error;
$this->errors = $newcomb->errors;
$db->rollback(); $db->rollback();
return -1; return -1;
} }
@ -1096,27 +1103,25 @@ class ProductCombinationLevel
/** /**
* save * Save a price impact of a product combination for a price level
* *
* @return int <0 KO, >0 OK * @return int <0 KO, >0 OK
*/ */
public function save() public function save()
{ {
$error = 0; if (($this->id > 0 && empty($this->fk_product_attribute_combination)) || empty($this->fk_price_level)) {
if (empty($this->fk_product_attribute_combination) || empty($this->fk_price_level)){
return -1; return -1;
} }
// check if level exist in DB before add // Check if level exist in DB before add
if (empty($this->id)){ if ($this->fk_product_attribute_combination > 0 && empty($this->id)) {
$sql = "SELECT rowid id"; $sql = "SELECT rowid id";
$sql .= " FROM ".MAIN_DB_PREFIX . $this->table_element; $sql .= " FROM ".MAIN_DB_PREFIX . $this->table_element;
$sql .= " WHERE fk_product_attribute_combination = ".(int) $this->fk_product_attribute_combination; $sql .= " WHERE fk_product_attribute_combination = ".(int) $this->fk_product_attribute_combination;
$sql .= ' AND fk_price_level = '.intval($this->fk_price_level); $sql .= ' AND fk_price_level = '.intval($this->fk_price_level);
$existObj = $this->db->getRow($sql); $existObj = $this->db->getRow($sql);
if ($existObj){ if ($existObj) {
$this->id = $existObj->id; $this->id = $existObj->id;
} }
} }
@ -1128,17 +1133,15 @@ class ProductCombinationLevel
$sql .= ' WHERE rowid = '.((int) $this->id); $sql .= ' WHERE rowid = '.((int) $this->id);
$res = $this->db->query($sql); $res = $this->db->query($sql);
if ($res>0){ if ($res > 0) {
return $this->id; return $this->id;
} } else {
else {
$this->error = $this->db->error(); $this->error = $this->db->error();
$this->errors[] = $this->error; $this->errors[] = $this->error;
return -1; return -1;
} }
} } else {
else { // Add
// ADD
$sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " ("; $sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " (";
$sql .= "fk_product_attribute_combination, fk_price_level, variation_price, variation_price_percentage"; $sql .= "fk_product_attribute_combination, fk_price_level, variation_price, variation_price_percentage";
$sql .= ") VALUES ("; $sql .= ") VALUES (";
@ -1149,10 +1152,9 @@ class ProductCombinationLevel
$sql .= ")"; $sql .= ")";
$res = $this->db->query($sql); $res = $this->db->query($sql);
if ($res){ if ($res) {
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element); $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
} } else {
else {
$this->error = $this->db->error(); $this->error = $this->db->error();
$this->errors[] = $this->error; $this->errors[] = $this->error;
return -1; return -1;

View File

@ -127,7 +127,6 @@ if ($_POST) {
$level_price_impact_percent = array(1 => $price_impact_percent); $level_price_impact_percent = array(1 => $price_impact_percent);
} }
$sanit_features = array(); $sanit_features = array();
//First, sanitize //First, sanitize
@ -157,7 +156,6 @@ if ($_POST) {
// sanit_feature is an array with 1 (and only 1) value per attribute. // sanit_feature is an array with 1 (and only 1) value per attribute.
// For example: Color->blue, Size->Small, Option->2 // For example: Color->blue, Size->Small, Option->2
//var_dump($sanit_features); //var_dump($sanit_features);
if (!$prodcomb->fetchByProductCombination2ValuePairs($id, $sanit_features)) if (!$prodcomb->fetchByProductCombination2ValuePairs($id, $sanit_features))
{ {
$result = $prodcomb->createProductCombination($user, $object, $sanit_features, array(), $level_price_impact_percent, $level_price_impact, $weight_impact, $reference); $result = $prodcomb->createProductCombination($user, $object, $sanit_features, array(), $level_price_impact_percent, $level_price_impact, $weight_impact, $reference);
@ -171,7 +169,7 @@ if ($_POST) {
exit(); exit();
} else { } else {
$langs->load("errors"); $langs->load("errors");
setEventMessages('', $prodcomb->errors, 'errors'); setEventMessages($prodcomb->error, $prodcomb->errors, 'errors');
} }
} else { } else {
setEventMessages($langs->trans('ErrorRecordAlreadyExists'), null, 'errors'); setEventMessages($langs->trans('ErrorRecordAlreadyExists'), null, 'errors');
@ -599,29 +597,32 @@ if (!empty($id) || !empty($ref))
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
print '</table>'; print '</table>';
print '<hr>';
} }
if (is_array($productCombination2ValuePairs1)) { if (is_array($productCombination2ValuePairs1)) {
?> ?>
<hr>
<table class="border" style="width: 100%"> <table class="border" style="width: 100%">
<?php
// When in edit mode
if (is_array($productCombination2ValuePairs1) && count($productCombination2ValuePairs1))
{
?>
<tr> <tr>
<td class="titlefieldcreate fieldrequired tdtop"><label for="features"><?php echo $langs->trans('Combination') ?></label></td> <td class="titlefieldcreate tdtop"><label for="features"><?php echo $langs->trans('Combination') ?></label></td>
<td class="tdtop"> <td class="tdtop">
<div class="inline-block valignmiddle quatrevingtpercent"> <div class="inline-block valignmiddle quatrevingtpercent">
<?php <?php
if (is_array($productCombination2ValuePairs1))
{
foreach ($productCombination2ValuePairs1 as $key => $val) { foreach ($productCombination2ValuePairs1 as $key => $val) {
$result1 = $prodattr->fetch($val->fk_prod_attr); $result1 = $prodattr->fetch($val->fk_prod_attr);
$result2 = $prodattr_val->fetch($val->fk_prod_attr_val); $result2 = $prodattr_val->fetch($val->fk_prod_attr_val);
//print 'rr'.$result1.' '.$result2;
if ($result1 > 0 && $result2 > 0) if ($result1 > 0 && $result2 > 0)
{ {
print $prodattr->label.' - '.$prodattr_val->value.'<br>'; print $prodattr->label.' - '.$prodattr_val->value.'<br>';
// TODO Add delete link // TODO Add delete link
} }
} }
}
?> ?>
</div> </div>
<!-- <div class="inline-block valignmiddle"> <!-- <div class="inline-block valignmiddle">
@ -631,6 +632,9 @@ if (!empty($id) || !empty($ref))
<td> <td>
</td> </td>
</tr> </tr>
<?php
}
?>
<tr> <tr>
<td><label for="reference"><?php echo $langs->trans('Reference') ?></label></td> <td><label for="reference"><?php echo $langs->trans('Reference') ?></label></td>
<td><input type="text" id="reference" name="reference" value="<?php echo trim($reference) ?>"></td> <td><input type="text" id="reference" name="reference" value="<?php echo trim($reference) ?>"></td>
@ -862,7 +866,7 @@ if (!empty($id) || !empty($ref))
print '<td class="center">'.$prodstatic->getLibStatut(2, 0).'</td>'; print '<td class="center">'.$prodstatic->getLibStatut(2, 0).'</td>';
print '<td class="center">'.$prodstatic->getLibStatut(2, 1).'</td>'; print '<td class="center">'.$prodstatic->getLibStatut(2, 1).'</td>';
print '<td class="right">'; print '<td class="right">';
print '<a class="paddingleft paddingright" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=edit&valueid='.$currcomb->id.'">'.img_edit().'</a>'; print '<a class="paddingleft paddingright editfielda" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=edit&valueid='.$currcomb->id.'">'.img_edit().'</a>';
print '<a class="paddingleft paddingright" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=delete&valueid='.$currcomb->id.'">'.img_delete().'</a>'; print '<a class="paddingleft paddingright" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=delete&valueid='.$currcomb->id.'">'.img_delete().'</a>';
print '</td>'; print '</td>';
print '<td class="nowrap center">'; print '<td class="nowrap center">';

View File

@ -18,7 +18,6 @@
require '../main.inc.php'; require '../main.inc.php';
require DOL_DOCUMENT_ROOT.'/variants/class/ProductAttribute.class.php'; require DOL_DOCUMENT_ROOT.'/variants/class/ProductAttribute.class.php';
$id = GETPOST('id', 'int');
$action = GETPOST('action', 'aZ09'); $action = GETPOST('action', 'aZ09');
$object = new ProductAttribute($db); $object = new ProductAttribute($db);
@ -66,7 +65,7 @@ print load_fiche_titre($title, $newcardbutton, 'product');
$forcereloadpage = empty($conf->global->MAIN_FORCE_RELOAD_PAGE) ? 0 : 1; $forcereloadpage = empty($conf->global->MAIN_FORCE_RELOAD_PAGE) ? 0 : 1;
?> ?>
<script type="text/javascript"> <script>
$(document).ready(function(){ $(document).ready(function(){
$(".imgupforline, .imgdownforline").hide(); $(".imgupforline, .imgdownforline").hide();
$(".lineupdown").removeAttr('href'); $(".lineupdown").removeAttr('href');