NEW Introduce mass action on product list ('delete' for the moment)

This commit is contained in:
Laurent Destailleur 2017-04-09 15:02:55 +02:00
parent 0a47245ba5
commit b054ca8267
10 changed files with 101 additions and 61 deletions

View File

@ -11,6 +11,8 @@ Following changes may create regression for some external modules, but were nece
* The trigger USER_SETINGROUP and USER_REMOVEFROMGROUP has been replaced with trigger USER_MODIFY. * The trigger USER_SETINGROUP and USER_REMOVEFROMGROUP has been replaced with trigger USER_MODIFY.
* The page societe/soc.php was renamed into societe/card.php to match page naming conventions. * The page societe/soc.php was renamed into societe/card.php to match page naming conventions.
* The page compta/facture.php was renamed into compta/facture/card.php to match page naming conventions. * The page compta/facture.php was renamed into compta/facture/card.php to match page naming conventions.
* The signature of method ->delete() of class Product and PriceExpression was changed from
->delete($id, notrigger) to ->delete(User, notrigger) to match standard dev rules.
***** ChangeLog for 5.0.1 compared to 5.0.0 ***** ***** ChangeLog for 5.0.1 compared to 5.0.0 *****

View File

@ -224,7 +224,7 @@ print '<div class="underbanner clearboth"></div>';
print '<table width="100%" class="border">'; print '<table width="100%" class="border">';
// Description // Description
print '<tr><td class="titlefield notopnoleft">'; print '<tr><td class="titlefield notopnoleft tdtop">';
print $langs->trans("Description").'</td><td>'; print $langs->trans("Description").'</td><td>';
print dol_htmlentitiesbr($object->description); print dol_htmlentitiesbr($object->description);
print '</td></tr>'; print '</td></tr>';

View File

@ -562,7 +562,7 @@ if (empty($reshook))
{ {
if (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->supprimer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->supprimer)) if (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->supprimer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->supprimer))
{ {
$result = $object->delete($object->id); $result = $object->delete(DolibarrApiAccess::$user);
} }
if ($result > 0) if ($result > 0)

View File

@ -339,7 +339,7 @@ class ProductApi extends DolibarrApi
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
} }
return $this->product->delete($id); return $this->product->delete(DolibarrApiAccess::$user);
} }
/** /**

View File

@ -246,7 +246,7 @@ class Products extends DolibarrApi
global $user; global $user;
$user = DolibarrApiAccess::$user; $user = DolibarrApiAccess::$user;
return $this->product->delete($id); return $this->product->delete(DolibarrApiAccess::$user);
} }
/** /**

View File

@ -1012,18 +1012,18 @@ class Product extends CommonObject
/** /**
* Delete a product from database (if not used) * Delete a product from database (if not used)
* *
* @param int $id Product id (usage of this is deprecated, delete should be called without parameters on a fetched object) * @param User $user Product id (usage of this is deprecated, delete should be called without parameters on a fetched object)
* @param int $notrigger Do not execute trigger * @param int $notrigger Do not execute trigger
* @return int < 0 if KO, 0 = Not possible, > 0 if OK * @return int < 0 if KO, 0 = Not possible, > 0 if OK
*/ */
function delete($id=0, $notrigger=0) function delete(User $user, $notrigger=0)
{ {
// Deprecation warning // Deprecation warning
if ($id > 0) { if ($id > 0) {
dol_syslog(__METHOD__ . " with parameter is deprecated", LOG_WARNING); dol_syslog(__METHOD__ . " with parameter is deprecated", LOG_WARNING);
} }
global $conf,$user,$langs; global $conf, $langs;
require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
$error=0; $error=0;

View File

@ -283,15 +283,16 @@ class PriceExpression
/** /**
* Delete object in database * Delete object in database
* *
* @param int $rowid Row id of expression
* @param User $user User that deletes * @param User $user User that deletes
* @param int $notrigger 0=launch triggers after, 1=disable triggers * @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK * @return int <0 if KO, >0 if OK
*/ */
function delete($rowid, $user, $notrigger=0) function delete(User $user, $notrigger=0)
{ {
$error=0; $error=0;
$rowid = $this->id;
$this->db->begin(); $this->db->begin();
if (! $error) if (! $error)

View File

@ -149,7 +149,8 @@ if ($action == 'delete')
{ {
if ($eid != 0) if ($eid != 0)
{ {
$result = $price_expression->delete($eid, $user); $price_expression->fetch($eid);
$result = $price_expression->delete($user);
if ($result < 0) if ($result < 0)
{ {
setEventMessages("delete: ".$price_expression->error, $price_expression->errors, 'errors'); setEventMessages("delete: ".$price_expression->error, $price_expression->errors, 'errors');

View File

@ -45,7 +45,12 @@ $langs->load("suppliers");
$langs->load("companies"); $langs->load("companies");
if (! empty($conf->productbatch->enabled)) $langs->load("productbatch"); if (! empty($conf->productbatch->enabled)) $langs->load("productbatch");
$action = GETPOST('action'); $action=GETPOST('action','alpha');
$massaction=GETPOST('massaction','alpha');
$show_files=GETPOST('show_files','int');
$confirm=GETPOST('confirm','alpha');
$toselect = GETPOST('toselect', 'array');
$sref=GETPOST("sref"); $sref=GETPOST("sref");
$sbarcode=GETPOST("sbarcode"); $sbarcode=GETPOST("sbarcode");
$snom=GETPOST("snom"); $snom=GETPOST("snom");
@ -69,6 +74,8 @@ if (!$_POST) {
$search_hidechildproducts = GETPOST('search_hidechildproducts'); $search_hidechildproducts = GETPOST('search_hidechildproducts');
} }
$diroutputmassaction=$conf->product->dir_output . '/temp/massgeneration/'.$user->id;
$limit = GETPOST("limit")?GETPOST("limit","int"):$conf->liste_limit; $limit = GETPOST("limit")?GETPOST("limit","int"):$conf->liste_limit;
$sortfield = GETPOST("sortfield",'alpha'); $sortfield = GETPOST("sortfield",'alpha');
$sortorder = GETPOST("sortorder",'alpha'); $sortorder = GETPOST("sortorder",'alpha');
@ -209,6 +216,16 @@ if (empty($reshook))
$search_accountancy_code_buy=''; $search_accountancy_code_buy='';
$search_array_options=array(); $search_array_options=array();
} }
// Mass actions
$objectclass='Product';
if ((string) $type == '1') { $objectlabel='Services'; }
if ((string) $type == '0') { $objectlabel='Products'; }
$permtoread = $user->rights->produit->lire;
$permtodelete = $user->rights->produit->supprimer;
$uploaddir = $conf->product->dir_output;
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
} }
@ -340,6 +357,8 @@ else
{ {
$num = $db->num_rows($resql); $num = $db->num_rows($resql);
$arrayofselected=is_array($toselect)?$toselect:array();
if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $sall) if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $sall)
{ {
$obj = $db->fetch_object($resql); $obj = $db->fetch_object($resql);
@ -394,6 +413,15 @@ else
if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val); if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val);
} }
// List of mass actions available
$arrayofmassactions = array(
//'presend'=>$langs->trans("SendByMail"),
//'builddoc'=>$langs->trans("PDFMerge"),
);
if ($user->rights->produit->supprimer) $arrayofmassactions['delete']=$langs->trans("Delete");
if ($massaction == 'presend' || $massaction == 'createbills') $arrayofmassactions=array();
$massactionbutton=$form->selectMassAction('', $arrayofmassactions);
print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">'; print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">';
if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">'; if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'; print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
@ -403,7 +431,7 @@ else
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">'; print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
print '<input type="hidden" name="type" value="'.$type.'">'; print '<input type="hidden" name="type" value="'.$type.'">';
print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_products.png', 0, '', '', $limit); print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_products.png', 0, '', '', $limit);
if (! empty($catid)) if (! empty($catid))
{ {
@ -470,6 +498,7 @@ else
$varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
$selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
if ($massactionbutton) $selectedfields.=$form->showCheckAddButtons('checkforselect', 1);
print '<div class="div-table-responsive">'; print '<div class="div-table-responsive">';
print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n"; print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
@ -581,8 +610,8 @@ else
print $form->selectarray('tobuy', array('0'=>$langs->trans('ProductStatusNotOnBuyShort'),'1'=>$langs->trans('ProductStatusOnBuyShort')),$tobuy,1); print $form->selectarray('tobuy', array('0'=>$langs->trans('ProductStatusNotOnBuyShort'),'1'=>$langs->trans('ProductStatusOnBuyShort')),$tobuy,1);
print '</td>'; print '</td>';
} }
print '<td class="liste_titre" align="right">'; print '<td class="liste_titre" align="middle">';
$searchpitco=$form->showFilterAndCheckAddButtons(0); $searchpitco=$form->showFilterButtons();
print $searchpitco; print $searchpitco;
print '</td>'; print '</td>';
@ -632,14 +661,14 @@ else
$i = 0; $i = 0;
while ($i < min($num,$limit)) while ($i < min($num,$limit))
{ {
$objp = $db->fetch_object($resql); $obj = $db->fetch_object($resql);
// Multilangs // Multilangs
if (! empty($conf->global->MAIN_MULTILANGS)) // si l'option est active if (! empty($conf->global->MAIN_MULTILANGS)) // si l'option est active
{ {
$sql = "SELECT label"; $sql = "SELECT label";
$sql.= " FROM ".MAIN_DB_PREFIX."product_lang"; $sql.= " FROM ".MAIN_DB_PREFIX."product_lang";
$sql.= " WHERE fk_product=".$objp->rowid; $sql.= " WHERE fk_product=".$obj->rowid;
$sql.= " AND lang='". $langs->getDefaultLang() ."'"; $sql.= " AND lang='". $langs->getDefaultLang() ."'";
$sql.= " LIMIT 1"; $sql.= " LIMIT 1";
@ -647,22 +676,22 @@ else
if ($result) if ($result)
{ {
$objtp = $db->fetch_object($result); $objtp = $db->fetch_object($result);
if (! empty($objtp->label)) $objp->label = $objtp->label; if (! empty($objtp->label)) $obj->label = $objtp->label;
} }
} }
$product_static->id = $objp->rowid; $product_static->id = $obj->rowid;
$product_static->ref = $objp->ref; $product_static->ref = $obj->ref;
$product_static->ref_fourn = $objp->ref_supplier; $product_static->ref_fourn = $obj->ref_supplier;
$product_static->label = $objp->label; $product_static->label = $obj->label;
$product_static->type = $objp->fk_product_type; $product_static->type = $obj->fk_product_type;
$product_static->status_buy = $objp->tobuy; $product_static->status_buy = $obj->tobuy;
$product_static->status = $objp->tosell; $product_static->status = $obj->tosell;
$product_static->entity = $objp->entity; $product_static->entity = $obj->entity;
if (! empty($conf->stock->enabled) && $user->rights->stock->lire && $type != 1) // To optimize call of load_stock if (! empty($conf->stock->enabled) && $user->rights->stock->lire && $type != 1) // To optimize call of load_stock
{ {
if ($objp->fk_product_type != 1) // Not a service if ($obj->fk_product_type != 1) // Not a service
{ {
$product_static->load_stock('nobatch'); // Load stock_reel + stock_warehouse. This also call load_virtual_stock() $product_static->load_stock('nobatch'); // Load stock_reel + stock_warehouse. This also call load_virtual_stock()
} }
@ -688,27 +717,27 @@ else
// Label // Label
if (! empty($arrayfields['p.label']['checked'])) if (! empty($arrayfields['p.label']['checked']))
{ {
print '<td>'.dol_trunc($objp->label,40).'</td>'; print '<td>'.dol_trunc($obj->label,40).'</td>';
} }
// Barcode // Barcode
if (! empty($arrayfields['p.barcode']['checked'])) if (! empty($arrayfields['p.barcode']['checked']))
{ {
print '<td>'.$objp->barcode.'</td>'; print '<td>'.$obj->barcode.'</td>';
} }
// Duration // Duration
if (! empty($arrayfields['p.duration']['checked'])) if (! empty($arrayfields['p.duration']['checked']))
{ {
print '<td align="center">'; print '<td align="center">';
if (preg_match('/([0-9]+)[a-z]/i',$objp->duration)) if (preg_match('/([0-9]+)[a-z]/i',$obj->duration))
{ {
if (preg_match('/([0-9]+)y/i',$objp->duration,$regs)) print $regs[1].' '.$langs->trans("DurationYear"); if (preg_match('/([0-9]+)y/i',$obj->duration,$regs)) print $regs[1].' '.$langs->trans("DurationYear");
elseif (preg_match('/([0-9]+)m/i',$objp->duration,$regs)) print $regs[1].' '.$langs->trans("DurationMonth"); elseif (preg_match('/([0-9]+)m/i',$obj->duration,$regs)) print $regs[1].' '.$langs->trans("DurationMonth");
elseif (preg_match('/([0-9]+)w/i',$objp->duration,$regs)) print $regs[1].' '.$langs->trans("DurationWeek"); elseif (preg_match('/([0-9]+)w/i',$obj->duration,$regs)) print $regs[1].' '.$langs->trans("DurationWeek");
elseif (preg_match('/([0-9]+)d/i',$objp->duration,$regs)) print $regs[1].' '.$langs->trans("DurationDay"); elseif (preg_match('/([0-9]+)d/i',$obj->duration,$regs)) print $regs[1].' '.$langs->trans("DurationDay");
//elseif (preg_match('/([0-9]+)h/i',$objp->duration,$regs)) print $regs[1].' '.$langs->trans("DurationHour"); //elseif (preg_match('/([0-9]+)h/i',$obj->duration,$regs)) print $regs[1].' '.$langs->trans("DurationHour");
else print $objp->duration; else print $obj->duration;
} }
print '</td>'; print '</td>';
} }
@ -717,10 +746,10 @@ else
if (! empty($arrayfields['p.sellprice']['checked'])) if (! empty($arrayfields['p.sellprice']['checked']))
{ {
print '<td align="right">'; print '<td align="right">';
if ($objp->tosell) if ($obj->tosell)
{ {
if ($objp->price_base_type == 'TTC') print price($objp->price_ttc).' '.$langs->trans("TTC"); if ($obj->price_base_type == 'TTC') print price($obj->price_ttc).' '.$langs->trans("TTC");
else print price($objp->price).' '.$langs->trans("HT"); else print price($obj->price).' '.$langs->trans("HT");
} }
print '</td>'; print '</td>';
} }
@ -729,10 +758,10 @@ else
if (! empty($arrayfields['p.minbuyprice']['checked'])) if (! empty($arrayfields['p.minbuyprice']['checked']))
{ {
print '<td align="right">'; print '<td align="right">';
if ($objp->tobuy && $objp->minsellprice != '') if ($obj->tobuy && $obj->minsellprice != '')
{ {
//print price($objp->minsellprice).' '.$langs->trans("HT"); //print price($obj->minsellprice).' '.$langs->trans("HT");
if ($product_fourn->find_min_price_product_fournisseur($objp->rowid) > 0) if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0)
{ {
if ($product_fourn->product_fourn_price_id > 0) if ($product_fourn->product_fourn_price_id > 0)
{ {
@ -752,9 +781,9 @@ else
if (! empty($arrayfields['p.seuil_stock_alerte']['checked'])) if (! empty($arrayfields['p.seuil_stock_alerte']['checked']))
{ {
print '<td align="right">'; print '<td align="right">';
if ($objp->fk_product_type != 1) if ($obj->fk_product_type != 1)
{ {
print $objp->seuil_stock_alerte; print $obj->seuil_stock_alerte;
} }
print '</td>'; print '</td>';
} }
@ -762,9 +791,9 @@ else
if (! empty($arrayfields['p.desiredstock']['checked'])) if (! empty($arrayfields['p.desiredstock']['checked']))
{ {
print '<td align="right">'; print '<td align="right">';
if ($objp->fk_product_type != 1) if ($obj->fk_product_type != 1)
{ {
print $objp->desiredstock; print $obj->desiredstock;
} }
print '</td>'; print '</td>';
} }
@ -772,9 +801,9 @@ else
if (! empty($arrayfields['p.stock']['checked'])) if (! empty($arrayfields['p.stock']['checked']))
{ {
print '<td align="right">'; print '<td align="right">';
if ($objp->fk_product_type != 1) if ($obj->fk_product_type != 1)
{ {
if ($objp->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $objp->seuil_stock_alerte) print img_warning($langs->trans("StockTooLow")).' '; if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) print img_warning($langs->trans("StockTooLow")).' ';
print $product_static->stock_reel; print $product_static->stock_reel;
} }
print '</td>'; print '</td>';
@ -783,9 +812,9 @@ else
if (! empty($arrayfields['stock_virtual']['checked'])) if (! empty($arrayfields['stock_virtual']['checked']))
{ {
print '<td align="right">'; print '<td align="right">';
if ($objp->fk_product_type != 1) if ($obj->fk_product_type != 1)
{ {
if ($objp->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $objp->seuil_stock_alerte) print img_warning($langs->trans("StockTooLow")).' '; if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) print img_warning($langs->trans("StockTooLow")).' ';
print $product_static->stock_theorique; print $product_static->stock_theorique;
} }
print '</td>'; print '</td>';
@ -794,13 +823,13 @@ else
if (! empty($arrayfields['p.tobatch']['checked'])) if (! empty($arrayfields['p.tobatch']['checked']))
{ {
print '<td align="center">'; print '<td align="center">';
print yn($objp->tobatch); print yn($obj->tobatch);
print '</td>'; print '</td>';
} }
// Accountancy code sell // Accountancy code sell
if (! empty($arrayfields['p.accountancy_code_sell']['checked'])) print '<td>'.$objp->accountancy_code_sell.'</td>'; if (! empty($arrayfields['p.accountancy_code_sell']['checked'])) print '<td>'.$obj->accountancy_code_sell.'</td>';
// Accountancy code sell // Accountancy code sell
if (! empty($arrayfields['p.accountancy_code_buy']['checked'])) print '<td>'.$objp->accountancy_code_buy.'</td>'; if (! empty($arrayfields['p.accountancy_code_buy']['checked'])) print '<td>'.$obj->accountancy_code_buy.'</td>';
// Extra fields // Extra fields
if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
{ {
@ -813,7 +842,7 @@ else
if ($align) print ' align="'.$align.'"'; if ($align) print ' align="'.$align.'"';
print '>'; print '>';
$tmpkey='options_'.$key; $tmpkey='options_'.$key;
print $extrafields->showOutputField($key, $objp->$tmpkey, '', 1); print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1);
print '</td>'; print '</td>';
} }
} }
@ -826,14 +855,14 @@ else
if (! empty($arrayfields['p.datec']['checked'])) if (! empty($arrayfields['p.datec']['checked']))
{ {
print '<td align="center">'; print '<td align="center">';
print dol_print_date($objp->date_creation, 'dayhour'); print dol_print_date($obj->date_creation, 'dayhour');
print '</td>'; print '</td>';
} }
// Date modification // Date modification
if (! empty($arrayfields['p.tms']['checked'])) if (! empty($arrayfields['p.tms']['checked']))
{ {
print '<td align="center">'; print '<td align="center">';
print dol_print_date($objp->date_update, 'dayhour'); print dol_print_date($obj->date_update, 'dayhour');
print '</td>'; print '</td>';
} }
@ -844,7 +873,7 @@ else
if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell');
} else { } else {
print $product_static->LibStatut($objp->tosell,5,0); print $product_static->LibStatut($obj->tosell,5,0);
} }
print '</td>'; print '</td>';
} }
@ -855,12 +884,19 @@ else
if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy');
} else { } else {
print $product_static->LibStatut($objp->tobuy,5,1); print $product_static->LibStatut($obj->tobuy,5,1);
} }
print '</td>'; print '</td>';
} }
// Action // Action
print '<td>&nbsp;</td>'; print '<td class="nowrap" align="center">';
if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
{
$selected=0;
if (in_array($obj->rowid, $arrayofselected)) $selected=1;
print '<input id="cb'.$obj->rowid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->rowid.'"'.($selected?' checked="checked"':'').'>';
}
print '</td>';
print "</tr>\n"; print "</tr>\n";
$i++; $i++;