Merge pull request #12501 from c3do/patch-3
NEW API to update purchase price. NEW Can force ref of a variant product
This commit is contained in:
commit
2492188de3
@ -380,3 +380,4 @@ ErrorProductCombinationNotFound=Product variant not found
|
||||
ActionAvailableOnVariantProductOnly=Action only available on the variant of product
|
||||
ProductsPricePerCustomer=Product prices per customers
|
||||
ProductSupplierExtraFields=Additional Attributes (Supplier Prices)
|
||||
DeleteLinkedProduct=Delete the child product linked to the combination
|
||||
@ -375,4 +375,4 @@ ErrorDestinationProductNotFound=Produit destination non trouvé
|
||||
ErrorProductCombinationNotFound=Variante du produit non trouvé
|
||||
ActionAvailableOnVariantProductOnly=Action disponible uniquement sur la variante du produit
|
||||
ProductsPricePerCustomer=Prix produit par clients
|
||||
ProductSupplierExtraFields=Attributs supplémentaires (Prix fournisseur)
|
||||
ProductSupplierExtraFields=Attributs supplémentaires (Prix fournisseur)
|
||||
@ -630,6 +630,73 @@ class Products extends DolibarrApi
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/Update purchase prices for a product.
|
||||
*
|
||||
* @param int $id ID of Product
|
||||
* @param float $qty Min quantity for which price is valid
|
||||
* @param float $buyprice Purchase price for the quantity min
|
||||
* @param string $price_base_type HT or TTC
|
||||
* @param int $fourn_id Supplier ID
|
||||
* @param int $availability Product availability
|
||||
* @param string $ref_fourn Supplier ref
|
||||
* @param float $tva_tx New VAT Rate (For example 8.5. Should not be a string)
|
||||
* @param string $charges costs affering to product
|
||||
* @param float $remise_percent Discount regarding qty (percent)
|
||||
* @param float $remise Discount regarding qty (amount)
|
||||
* @param int $newnpr Set NPR or not
|
||||
* @param int $delivery_time_days Delay in days for delivery (max). May be '' if not defined.
|
||||
* @param string $supplier_reputation Reputation with this product to the defined supplier (empty, FAVORITE, DONOTORDER)
|
||||
* @param array $localtaxes_array Array with localtaxes info array('0'=>type1,'1'=>rate1,'2'=>type2,'3'=>rate2) (loaded by getLocalTaxesFromRate(vatrate, 0, ...) function).
|
||||
* @param string $newdefaultvatcode Default vat code
|
||||
* @param float $multicurrency_buyprice Purchase price for the quantity min in currency
|
||||
* @param string $multicurrency_price_base_type HT or TTC in currency
|
||||
* @param float $multicurrency_tx Rate currency
|
||||
* @param string $multicurrency_code Currency code
|
||||
* @param string $desc_fourn Custom description for product_fourn_price
|
||||
* @param string $barcode Barcode
|
||||
* @param int $fk_barcode_type Barcode type
|
||||
* @return int
|
||||
*
|
||||
* @throws RestException 500
|
||||
* @throws RestException 401
|
||||
*
|
||||
* @url POST {id}/purchase_prices
|
||||
*/
|
||||
public function addPurchasePrice($id, $qty, $buyprice, $price_base_type, $fourn_id, $availability, $ref_fourn, $tva_tx, $charges = 0, $remise_percent = 0, $remise = 0, $newnpr = 0, $delivery_time_days = 0, $supplier_reputation = '', $localtaxes_array = array(), $newdefaultvatcode = '', $multicurrency_buyprice = 0, $multicurrency_price_base_type = 'HT', $multicurrency_tx = 1, $multicurrency_code = '', $desc_fourn = '', $barcode = '', $fk_barcode_type = null)
|
||||
{
|
||||
if(! DolibarrApiAccess::$user->rights->produit->creer) {
|
||||
throw new RestException(401);
|
||||
}
|
||||
|
||||
$result = $this->productsupplier->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Product not found');
|
||||
}
|
||||
|
||||
if (!DolibarrApi::_checkAccessToResource('product', $this->productsupplier->id)) {
|
||||
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
$result = $this->productsupplier->add_fournisseur(DolibarrApiAccess::$user, $fourn_id, $ref_fourn, $qty);
|
||||
if ($result < 0) {
|
||||
throw new RestException(500, "Error adding supplier to product : ".$this->db->lasterror());
|
||||
}
|
||||
|
||||
$fourn = new Fournisseur($this->db);
|
||||
$result = $fourn->fetch($fourn_id);
|
||||
if ($result <= 0) {
|
||||
throw new RestException(404, 'Supplier not found');
|
||||
}
|
||||
|
||||
$result = $this->productsupplier->update_buyprice($qty, $buyprice, DolibarrApiAccess::$user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges, $remise_percent, $remise, $newnpr, $delivery_time_days, $supplier_reputation, $localtaxes_array, $newdefaultvatcode, $multicurrency_buyprice, $multicurrency_price_base_type, $multicurrency_tx, $multicurrency_code, $desc_fourn, $barcode, $fk_barcode_type);
|
||||
|
||||
if ($result <= 0) {
|
||||
throw new RestException(500, "Error updating buy price : ".$this->db->lasterror());
|
||||
}
|
||||
return (int) $this->productsupplier->product_fourn_price_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete purchase price for a product
|
||||
*
|
||||
@ -1325,11 +1392,12 @@ class Products extends DolibarrApi
|
||||
*
|
||||
* "features" is a list of attributes pairs id_attribute=>id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)
|
||||
*
|
||||
* @param int $id ID of Product
|
||||
* @param float $weight_impact Weight impact of variant
|
||||
* @param float $price_impact Price impact of variant
|
||||
* @param bool $price_impact_is_percent Price impact in percent (true or false)
|
||||
* @param array $features List of attributes pairs id_attribute->id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)
|
||||
* @param int $id ID of Product
|
||||
* @param float $weight_impact Weight impact of variant
|
||||
* @param float $price_impact Price impact of variant
|
||||
* @param bool $price_impact_is_percent Price impact in percent (true or false)
|
||||
* @param array $features List of attributes pairs id_attribute->id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)
|
||||
* @param bool|string $reference Customized reference of variant
|
||||
* @return int
|
||||
*
|
||||
* @throws RestException 500
|
||||
@ -1338,7 +1406,7 @@ class Products extends DolibarrApi
|
||||
*
|
||||
* @url POST {id}/variants
|
||||
*/
|
||||
public function addVariant($id, $weight_impact, $price_impact, $price_impact_is_percent, $features)
|
||||
public function addVariant($id, $weight_impact, $price_impact, $price_impact_is_percent, $features, $reference = false)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->rights->produit->creer) {
|
||||
throw new RestException(401);
|
||||
@ -1368,17 +1436,13 @@ class Products extends DolibarrApi
|
||||
}
|
||||
|
||||
$prodcomb = new ProductCombination($this->db);
|
||||
if (!$prodcomb->fetchByProductCombination2ValuePairs($id, $features))
|
||||
|
||||
$result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact, $reference);
|
||||
if ($result > 0)
|
||||
{
|
||||
$result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact);
|
||||
if ($result > 0)
|
||||
{
|
||||
return $result;
|
||||
} else {
|
||||
throw new RestException(500, "Error creating new product variant");
|
||||
}
|
||||
return $result;
|
||||
} else {
|
||||
return $prodcomb->id;
|
||||
throw new RestException(500, "Error creating new product variant");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -502,9 +502,10 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
|
||||
* @param bool $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_weightvar If the weight variation is forced
|
||||
* @param bool|string $forced_refvar If the reference is forced
|
||||
* @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)
|
||||
public function createProductCombination(User $user, Product $product, array $combinations, array $variations, $price_var_percent = false, $forced_pricevar = false, $forced_weightvar = false, $forced_refvar = false)
|
||||
{
|
||||
global $db, $conf;
|
||||
|
||||
@ -513,7 +514,23 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
|
||||
|
||||
$db->begin();
|
||||
|
||||
$newproduct = clone $product;
|
||||
$forced_refvar = trim($forced_refvar);
|
||||
|
||||
if (!empty($forced_refvar) && $forced_refvar != $product->ref) {
|
||||
$existingProduct = new Product($db);
|
||||
$result = $existingProduct->fetch('', $forced_refvar);
|
||||
if ($result > 0) {
|
||||
$newproduct = $existingProduct;
|
||||
} else {
|
||||
$existingProduct = false;
|
||||
$newproduct = clone $product;
|
||||
$newproduct->ref = $forced_refvar;
|
||||
}
|
||||
} else {
|
||||
$forced_refvar = false;
|
||||
$existingProduct = false;
|
||||
$newproduct = clone $product;
|
||||
}
|
||||
|
||||
//Final weight impact
|
||||
$weight_impact = $forced_weightvar;
|
||||
@ -536,7 +553,6 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
|
||||
$newcomb = $existingCombination;
|
||||
} else {
|
||||
$newcomb->fk_product_parent = $product->id;
|
||||
|
||||
if ($newcomb->create($user) < 0) { // Create 1 entry into product_attribute_combination (1 entry for all combinations)
|
||||
$db->rollback();
|
||||
return -1;
|
||||
@ -573,10 +589,12 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
|
||||
$price_impact += (float) price2num($variations[$currcombattr][$currcombval]['price']);
|
||||
}
|
||||
|
||||
if (isset($conf->global->PRODUIT_ATTRIBUTES_SEPARATOR)) {
|
||||
$newproduct->ref .= $conf->global->PRODUIT_ATTRIBUTES_SEPARATOR . $prodattrval->ref;
|
||||
} else {
|
||||
$newproduct->ref .= '_'.$prodattrval->ref;
|
||||
if ($forced_refvar === false) {
|
||||
if (isset($conf->global->PRODUIT_ATTRIBUTES_SEPARATOR)) {
|
||||
$newproduct->ref .= $conf->global->PRODUIT_ATTRIBUTES_SEPARATOR . $prodattrval->ref;
|
||||
} else {
|
||||
$newproduct->ref .= '_'.$prodattrval->ref;
|
||||
}
|
||||
}
|
||||
|
||||
//The first one should not contain a linebreak
|
||||
@ -592,58 +610,65 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
|
||||
|
||||
$newproduct->weight += $weight_impact;
|
||||
|
||||
//To avoid wrong information in price history log
|
||||
$newproduct->price = 0;
|
||||
$newproduct->price_ttc = 0;
|
||||
$newproduct->price_min = 0;
|
||||
$newproduct->price_min_ttc = 0;
|
||||
|
||||
// A new variant must use a new barcode (not same product)
|
||||
$newproduct->barcode = -1;
|
||||
|
||||
// Now create the product
|
||||
//print 'Create prod '.$newproduct->ref.'<br>'."\n";
|
||||
$newprodid = $newproduct->create($user);
|
||||
if ($newprodid < 0)
|
||||
{
|
||||
//In case the error is not related with an already existing product
|
||||
if ($newproduct->error != 'ErrorProductAlreadyExists') {
|
||||
$this->error[] = $newproduct->error;
|
||||
$this->errors = $newproduct->errors;
|
||||
$db->rollback();
|
||||
return -1;
|
||||
}
|
||||
if ($existingProduct === false) {
|
||||
//To avoid wrong information in price history log
|
||||
$newproduct->price = 0;
|
||||
$newproduct->price_ttc = 0;
|
||||
$newproduct->price_min = 0;
|
||||
$newproduct->price_min_ttc = 0;
|
||||
|
||||
/**
|
||||
* If there is an existing combination, then we update the prices and weight
|
||||
* Otherwise, we try adding a random number to the ref
|
||||
*/
|
||||
// A new variant must use a new barcode (not same product)
|
||||
$newproduct->barcode = -1;
|
||||
$result = $newproduct->create($user);
|
||||
|
||||
if ($newcomb->fk_product_child) {
|
||||
$res = $newproduct->fetch($existingCombination->fk_product_child);
|
||||
} else {
|
||||
$orig_prod_ref = $newproduct->ref;
|
||||
$i = 1;
|
||||
if ($result < 0)
|
||||
{
|
||||
//In case the error is not related with an already existing product
|
||||
if ($newproduct->error != 'ErrorProductAlreadyExists') {
|
||||
$this->error[] = $newproduct->error;
|
||||
$this->errors = $newproduct->errors;
|
||||
$db->rollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
$newproduct->ref = $orig_prod_ref.$i;
|
||||
$res = $newproduct->create($user);
|
||||
/**
|
||||
* If there is an existing combination, then we update the prices and weight
|
||||
* Otherwise, we try adding a random number to the ref
|
||||
*/
|
||||
|
||||
if ($newproduct->error != 'ErrorProductAlreadyExists') {
|
||||
$this->errors[] = $newproduct->error;
|
||||
break;
|
||||
}
|
||||
if ($newcomb->fk_product_child) {
|
||||
$res = $newproduct->fetch($existingCombination->fk_product_child);
|
||||
} else {
|
||||
$orig_prod_ref = $newproduct->ref;
|
||||
$i = 1;
|
||||
|
||||
$i++;
|
||||
} while ($res < 0);
|
||||
}
|
||||
do {
|
||||
$newproduct->ref = $orig_prod_ref.$i;
|
||||
$res = $newproduct->create($user);
|
||||
|
||||
if ($res < 0) {
|
||||
$db->rollback();
|
||||
return -1;
|
||||
}
|
||||
if ($newproduct->error != 'ErrorProductAlreadyExists') {
|
||||
$this->errors[] = $newproduct->error;
|
||||
break;
|
||||
}
|
||||
|
||||
$newproduct->weight += $weight_impact;
|
||||
$i++;
|
||||
} while ($res < 0);
|
||||
}
|
||||
|
||||
if ($res < 0) {
|
||||
$db->rollback();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = $newproduct->update($newproduct->id, $user);
|
||||
if ($result < 0)
|
||||
{
|
||||
$db->rollback();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
$newcomb->fk_product_child = $newproduct->id;
|
||||
|
||||
@ -33,6 +33,7 @@ $ref = GETPOST('ref', 'alpha');
|
||||
$weight_impact = GETPOST('weight_impact', 'alpha');
|
||||
$price_impact = GETPOST('price_impact', 'alpha');
|
||||
$price_impact_percent = (bool) GETPOST('price_impact_percent');
|
||||
$reference = GETPOST('reference', 'alpha');
|
||||
$form = new Form($db);
|
||||
|
||||
$action = GETPOST('action', 'alpha');
|
||||
@ -41,6 +42,7 @@ $show_files = GETPOST('show_files', 'int');
|
||||
$confirm = GETPOST('confirm', 'alpha');
|
||||
$toselect = GETPOST('toselect', 'array');
|
||||
$cancel = GETPOST('cancel', 'alpha');
|
||||
$delete_product = GETPOST('delete_product', 'alpha');
|
||||
|
||||
// Security check
|
||||
$fieldvalue = (!empty($id) ? $id : $ref);
|
||||
@ -106,6 +108,10 @@ if ($_POST) {
|
||||
}
|
||||
else
|
||||
{
|
||||
$reference = trim($reference);
|
||||
if (empty($reference)) {
|
||||
$reference = false;
|
||||
}
|
||||
$weight_impact = price2num($weight_impact);
|
||||
$price_impact = price2num($price_impact);
|
||||
$sanit_features = array();
|
||||
@ -141,7 +147,7 @@ if ($_POST) {
|
||||
|
||||
if (!$prodcomb->fetchByProductCombination2ValuePairs($id, $sanit_features))
|
||||
{
|
||||
$result = $prodcomb->createProductCombination($user, $object, $sanit_features, array(), $price_impact_percent, $price_impact, $weight_impact);
|
||||
$result = $prodcomb->createProductCombination($user, $object, $sanit_features, array(), $price_impact_percent, $price_impact, $weight_impact, $reference);
|
||||
if ($result > 0)
|
||||
{
|
||||
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
||||
@ -242,7 +248,7 @@ if ($action === 'confirm_deletecombination') {
|
||||
if ($prodcomb->fetch($valueid) > 0) {
|
||||
$db->begin();
|
||||
|
||||
if ($prodcomb->delete($user) > 0 && $prodstatic->fetch($prodcomb->fk_product_child) > 0 && $prodstatic->delete($user) > 0) {
|
||||
if ($prodcomb->delete($user) > 0 && (empty($delete_product) || ($delete_product == 'on' && $prodstatic->fetch($prodcomb->fk_product_child) > 0 && $prodstatic->delete($user) > 0))) {
|
||||
$db->commit();
|
||||
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
||||
header('Location: '.dol_buildpath('/variants/combinations.php?id='.$object->id, 2));
|
||||
@ -590,6 +596,10 @@ if (!empty($id) || !empty($ref))
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="price_impact"><?php echo $langs->trans('PriceImpact') ?></label></td>
|
||||
<td><input type="text" id="price_impact" name="price_impact" value="<?php echo price($price_impact) ?>">
|
||||
@ -629,7 +639,7 @@ if (!empty($id) || !empty($ref))
|
||||
$langs->trans('Delete'),
|
||||
$langs->trans('ProductCombinationDeleteDialog', $prodstatic->ref),
|
||||
"confirm_deletecombination",
|
||||
'',
|
||||
array(array('label'=> $langs->trans('DeleteLinkedProduct'),'type'=> 'checkbox', 'name' => 'delete_product', 'value' => false)),
|
||||
0,
|
||||
1
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user