Merge branch '13.0' of git@github.com:Dolibarr/dolibarr.git into develop
Conflicts: htdocs/commande/class/commandestats.class.php htdocs/core/actions_massactions.inc.php htdocs/core/modules/propale/doc/pdf_cyan.modules.php htdocs/holiday/month_report.php htdocs/product/class/product.class.php htdocs/product/stock/class/mouvementstock.class.php htdocs/societe/list.php
This commit is contained in:
commit
2586fcd1a3
@ -561,9 +561,9 @@ class AccountancyExport
|
||||
$Tab['contrepartie'] = str_repeat(' ', 8);
|
||||
|
||||
// Force date format : %d%m%y
|
||||
if (!empty($data->date_echeance)) {
|
||||
//$Tab['date_echeance'] = dol_print_date($data->date_echeance, $conf->global->ACCOUNTING_EXPORT_DATE);
|
||||
$Tab['date_echeance'] = dol_print_date($data->date_echeance, '%d%m%y'); // Format must be ddmmyy
|
||||
if (!empty($data->date_lim_reglement)) {
|
||||
//$Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, $conf->global->ACCOUNTING_EXPORT_DATE);
|
||||
$Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, '%d%m%y'); // Format must be ddmmyy
|
||||
} else {
|
||||
$Tab['date_echeance'] = '000000';
|
||||
}
|
||||
@ -660,9 +660,9 @@ class AccountancyExport
|
||||
|
||||
$Tab['code_stat'] = str_repeat(' ', 4);
|
||||
|
||||
if (!empty($data->date_echeance)) {
|
||||
//$Tab['date_echeance'] = dol_print_date($data->date_echeance, $conf->global->ACCOUNTING_EXPORT_DATE);
|
||||
$Tab['date_echeance'] = dol_print_date($data->date_echeance, '%d%m%Y');
|
||||
if (!empty($data->date_lim_reglement)) {
|
||||
//$Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, $conf->global->ACCOUNTING_EXPORT_DATE);
|
||||
$Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, '%d%m%Y');
|
||||
} else {
|
||||
$Tab['date_echeance'] = dol_print_date($data->doc_date, '%d%m%Y');
|
||||
}
|
||||
|
||||
@ -91,7 +91,9 @@ print '<div class="div-table-responsive-no-min">';
|
||||
print '<table summary="more" class="noborder centpercent">';
|
||||
print '<tr class="liste_titre"><td class="titlefieldmiddle">'.$langs->trans("Parameter").'</td><td width="200px">'.$langs->trans("Value").'</td></tr>';
|
||||
|
||||
print '<tr class="oddeven"><td>'.$langs->trans("MAIN_GENERATE_PROPOSALS_WITH_PICTURE").'</td><td>';
|
||||
print '<tr class="oddeven"><td>'.$langs->trans("MAIN_GENERATE_PROPOSALS_WITH_PICTURE");
|
||||
print ' <span class="opacitymedium">('.$langs->trans("RandomlySelectedIfSeveral").')</span>';
|
||||
print '</td><td>';
|
||||
if ($conf->use_javascript_ajax) {
|
||||
print ajax_constantonoff('MAIN_GENERATE_PROPOSALS_WITH_PICTURE');
|
||||
} else {
|
||||
|
||||
@ -44,7 +44,10 @@ class CommandeStats extends Stats
|
||||
public $userid;
|
||||
|
||||
public $from;
|
||||
public $from_line;
|
||||
public $field;
|
||||
public $field_line;
|
||||
public $categ_link;
|
||||
public $where;
|
||||
public $join;
|
||||
|
||||
@ -77,6 +80,7 @@ class CommandeStats extends Stats
|
||||
$this->field = 'total_ht';
|
||||
$this->field_line = 'total_ht';
|
||||
//$this->where .= " c.fk_statut > 0"; // Not draft and not cancelled
|
||||
$this->categ_link = MAIN_DB_PREFIX.'categorie_societe';
|
||||
} elseif ($mode == 'supplier') {
|
||||
$object = new CommandeFournisseur($this->db);
|
||||
$this->from = MAIN_DB_PREFIX.$object->table_element." as c";
|
||||
@ -84,6 +88,7 @@ class CommandeStats extends Stats
|
||||
$this->field = 'total_ht';
|
||||
$this->field_line = 'total_ht';
|
||||
//$this->where .= " c.fk_statut > 2"; // Only approved & ordered
|
||||
$this->categ_link = MAIN_DB_PREFIX.'categorie_fournisseur';
|
||||
}
|
||||
//$this->where.= " AND c.fk_soc = s.rowid AND c.entity = ".$conf->entity;
|
||||
$this->where .= ($this->where ? ' AND ' : '').'c.entity IN ('.getEntity('commande').')';
|
||||
@ -104,7 +109,7 @@ class CommandeStats extends Stats
|
||||
}
|
||||
|
||||
if ($categid) {
|
||||
$this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_societe as cats ON cats.fk_soc = c.fk_soc';
|
||||
$this->join .= ' LEFT JOIN '.$this->categ_link.' as cats ON cats.fk_soc = c.fk_soc';
|
||||
$this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie as cat ON cat.rowid = cats.fk_categorie';
|
||||
$this->where .= ' AND cat.rowid = '.((int) $categid);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/* Copyright (C) 2015-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
|
||||
* Copyright (C) 2018-2021 Nicolas ZABOURI <info@inovea-conseil.com>
|
||||
* Copyright (C) 2018 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2019 Ferran Marcet <fmarcet@2byte.es>
|
||||
* Copyright (C) 2019-2021 Frédéric France <frederic.france@netlogic.fr>
|
||||
@ -1267,7 +1267,7 @@ if (!$error && $massaction == 'validate' && $permissiontoadd) {
|
||||
if ($nbok > 1) {
|
||||
setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
|
||||
setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
|
||||
}
|
||||
$db->commit();
|
||||
} else {
|
||||
@ -1330,7 +1330,7 @@ if (!$error && ($massaction == 'delete' || ($action == 'delete' && $confirm == '
|
||||
if ($nbok > 1) {
|
||||
setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs');
|
||||
setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
|
||||
}
|
||||
$db->commit();
|
||||
} else {
|
||||
|
||||
@ -434,13 +434,12 @@ class pdf_cyan extends ModelePDFPropales
|
||||
if (!empty($conf->global->MAIN_ADD_CREATOR_IN_NOTE) && $object->user_author_id > 0) {
|
||||
$tmpuser = new User($this->db);
|
||||
$tmpuser->fetch($object->user_author_id);
|
||||
$notetoshow .= $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs);
|
||||
if ($tmpuser->email) {
|
||||
$notetoshow .= ', Mail: '.$tmpuser->email;
|
||||
}
|
||||
if ($tmpuser->office_phone) {
|
||||
$notetoshow .= ', Tel: '.$tmpuser->office_phone;
|
||||
}
|
||||
|
||||
$creator_info = $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs);
|
||||
if ($tmpuser->email) $creator_info .= ', '.$langs->trans("EMail").': '.$tmpuser->email;
|
||||
if ($tmpuser->office_phone) $creator_info .= ', '.$langs->trans("Phone").': '.$tmpuser->office_phone;
|
||||
|
||||
$notetoshow = dol_concatdesc($notetoshow, $creator_info);
|
||||
}
|
||||
|
||||
$tab_height = $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter;
|
||||
|
||||
@ -245,7 +245,7 @@ class pdf_aurore extends ModelePDFSupplierProposal
|
||||
$pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/";
|
||||
$dir = $conf->product->dir_output.'/'.$pdir;
|
||||
} else {
|
||||
$pdir = get_exdir(0, 2, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/';
|
||||
$pdir = get_exdir(0, 0, 0, 0, $objphoto, 'product');
|
||||
$dir = $conf->product->dir_output.'/'.$pdir;
|
||||
}
|
||||
|
||||
|
||||
@ -125,6 +125,52 @@ class InterfaceLdapsynchro extends DolibarrTriggers
|
||||
$newparent = $object->_load_ldap_dn($info, 1);
|
||||
|
||||
$result = $ldap->update($dn, $info, $user, $olddn, $newrdn, $newparent);
|
||||
|
||||
if ($result > 0 && !empty($object->context['newgroupid'])) { // We are in context of adding a new group to user
|
||||
$usergroup = new Usergroup($this->db);
|
||||
|
||||
$usergroup->fetch($object->context['newgroupid']);
|
||||
|
||||
$oldinfo = $usergroup->_load_ldap_info();
|
||||
$olddn = $usergroup->_load_ldap_dn($oldinfo);
|
||||
|
||||
// Verify if entry exist
|
||||
$container = $usergroup->_load_ldap_dn($oldinfo, 1);
|
||||
$search = "(".$usergroup->_load_ldap_dn($oldinfo, 2).")";
|
||||
$records = $ldap->search($container, $search);
|
||||
if (count($records) && $records['count'] == 0)
|
||||
{
|
||||
$olddn = '';
|
||||
}
|
||||
|
||||
$info = $usergroup->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call)
|
||||
$dn = $usergroup->_load_ldap_dn($info);
|
||||
|
||||
$result = $ldap->update($dn, $info, $user, $olddn);
|
||||
}
|
||||
|
||||
if ($result > 0 && !empty($object->context['oldgroupid'])) { // We are in context of removing a group from user
|
||||
$usergroup = new Usergroup($this->db);
|
||||
|
||||
$usergroup->fetch($object->context['oldgroupid']);
|
||||
|
||||
$oldinfo = $usergroup->_load_ldap_info();
|
||||
$olddn = $usergroup->_load_ldap_dn($oldinfo);
|
||||
|
||||
// Verify if entry exist
|
||||
$container = $usergroup->_load_ldap_dn($oldinfo, 1);
|
||||
$search = "(".$usergroup->_load_ldap_dn($oldinfo, 2).")";
|
||||
$records = $ldap->search($container, $search);
|
||||
if (count($records) && $records['count'] == 0)
|
||||
{
|
||||
$olddn = '';
|
||||
}
|
||||
|
||||
$info = $usergroup->_load_ldap_info(); // Contains all members, except the old one (remove already done before trigger call)
|
||||
$dn = $usergroup->_load_ldap_dn($info);
|
||||
|
||||
$result = $ldap->update($dn, $info, $user, $olddn);
|
||||
}
|
||||
}
|
||||
|
||||
if ($result < 0) {
|
||||
|
||||
@ -2138,7 +2138,8 @@ if ($action == 'create') {
|
||||
// only show lot numbers from src warehouse when shipping from multiple warehouses
|
||||
$line->fetch($detail_batch->fk_expeditiondet);
|
||||
}
|
||||
print '<td>'.$formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $line->entrepot_id).'</td>';
|
||||
$entrepot_id = !empty($detail_batch->entrepot_id)?$detail_batch->entrepot_id:$lines[$i]->entrepot_id;
|
||||
print '<td>'.$formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $entrepot_id).'</td>';
|
||||
print '</tr>';
|
||||
}
|
||||
// add a 0 qty lot row to be able to add a lot
|
||||
|
||||
@ -1546,8 +1546,9 @@ if ($action == 'create') {
|
||||
// Validate
|
||||
if ($object->statut == Fichinter::STATUS_DRAFT && (count($object->lines) > 0 || !empty($conf->global->FICHINTER_DISABLE_DETAILS))) {
|
||||
if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->ficheinter_advance->validate)) {
|
||||
print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=validate"';
|
||||
print '>'.$langs->trans("Validate").'</a></div>';
|
||||
print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=validate">'.$langs->trans("Validate").'</a></div>';
|
||||
} else {
|
||||
print '<div class="inline-block divButActionRefused"><span class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Validate").'</span></div>';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1582,7 +1583,7 @@ if ($action == 'create') {
|
||||
}
|
||||
}
|
||||
|
||||
// create intervention model
|
||||
// Create intervention model
|
||||
if ($conf->global->MAIN_FEATURES_LEVEL >= 1 && $object->statut == Fichinter::STATUS_DRAFT && $user->rights->ficheinter->creer && (count($object->lines) > 0)) {
|
||||
print '<div class="inline-block divButAction">';
|
||||
print '<a class="butAction" href="'.DOL_URL_ROOT.'/fichinter/card-rec.php?id='.$object->id.'&action=create">'.$langs->trans("ChangeIntoRepeatableIntervention").'</a>';
|
||||
|
||||
@ -117,7 +117,7 @@ $search_month_end = GETPOST('search_month_end', 'int');
|
||||
$search_year_end = GETPOST('search_year_end', 'int');
|
||||
$search_employee = GETPOST('search_employee', 'int');
|
||||
$search_valideur = GETPOST('search_valideur', 'int');
|
||||
$search_status = GETPOST('search_statut', 'int');
|
||||
$search_status = GETPOST('search_status', 'int');
|
||||
$search_type = GETPOST('search_type', 'int');
|
||||
|
||||
// Initialize technical objects
|
||||
|
||||
@ -144,17 +144,17 @@ $sql .= " FROM ".MAIN_DB_PREFIX."holiday cp";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user u ON cp.fk_user = u.rowid";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_holiday_types ct ON cp.fk_type = ct.rowid";
|
||||
$sql .= " WHERE cp.rowid > 0";
|
||||
$sql .= " AND cp.statut = 3"; // 3 = Approved
|
||||
$sql .= " AND cp.statut = ".Holiday::STATUS_APPROVED;
|
||||
$sql .= " AND (date_format(cp.date_debut, '%Y-%m') = '".$db->escape($year_month)."' OR date_format(cp.date_fin, '%Y-%m') = '".$db->escape($year_month)."')";
|
||||
|
||||
if (!empty($search_ref)) {
|
||||
$sql .= natural_search('cp.ref', $search_ref);
|
||||
}
|
||||
if (!empty($search_employee)) {
|
||||
$sql .= " AND cp.fk_user = '".$db->escape($search_employee)."'";
|
||||
if (!empty($search_employee) && $search_employee > 0) {
|
||||
$sql .= " AND cp.fk_user = ".((int) $search_employee);
|
||||
}
|
||||
if (!empty($search_type)) {
|
||||
$sql .= ' AND cp.fk_type IN ('.$db->sanitize($search_type).')';
|
||||
if (!empty($search_type) && $search_type != '-1') {
|
||||
$sql .= ' AND cp.fk_type IN ('.$db->escape($search_type).')';
|
||||
}
|
||||
if (!empty($search_description)) {
|
||||
$sql .= natural_search('cp.description', $search_description);
|
||||
|
||||
@ -1987,7 +1987,7 @@ MAIN_PDF_MARGIN_RIGHT=Right margin on PDF
|
||||
MAIN_PDF_MARGIN_TOP=Top margin on PDF
|
||||
MAIN_PDF_MARGIN_BOTTOM=Bottom margin on PDF
|
||||
MAIN_DOCUMENTS_LOGO_HEIGHT=Height for logo on PDF
|
||||
MAIN_GENERATE_PROPOSALS_WITH_PICTURE=Add picture on proposal ligne
|
||||
MAIN_GENERATE_PROPOSALS_WITH_PICTURE=Add picture on proposal line
|
||||
MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING=Add electronic sign in PDF
|
||||
NothingToSetup=There is no specific setup required for this module.
|
||||
SetToYesIfGroupIsComputationOfOtherGroups=Set this to yes if this group is a computation of other groups
|
||||
@ -2140,4 +2140,5 @@ CheckForModuleUpdateHelp=This action will connect to editors of external modules
|
||||
ModuleUpdateAvailable=An update is available
|
||||
NoExternalModuleWithUpdate=No updates found for external modules
|
||||
SwaggerDescriptionFile=Swagger API description file (for use with redoc for example)
|
||||
YouEnableDeprecatedWSAPIsUseRESTAPIsInstead=You enabled deprecated WS API. You should use REST API instead.
|
||||
YouEnableDeprecatedWSAPIsUseRESTAPIsInstead=You enabled deprecated WS API. You should use REST API instead.
|
||||
RandomlySelectedIfSeveral=Randomly selected if several pictures are available
|
||||
@ -5422,11 +5422,11 @@ class Product extends CommonObject
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* Retourne tableau de toutes les photos du produit
|
||||
* Return an array with all photos of product found on disk. There is no sorting criteria.
|
||||
*
|
||||
* @param string $dir Repertoire a scanner
|
||||
* @param int $nbmax Nombre maximum de photos (0=pas de max)
|
||||
* @return array Tableau de photos
|
||||
* @param string $dir Directory to scan
|
||||
* @param int $nbmax Number maxium of photos (0=no maximum)
|
||||
* @return array Array of photos
|
||||
*/
|
||||
public function liste_photos($dir, $nbmax = 0)
|
||||
{
|
||||
@ -5447,9 +5447,10 @@ class Product extends CommonObject
|
||||
if (dol_is_file($dir.$file) && image_format_supported($file) >= 0) {
|
||||
$nbphoto++;
|
||||
|
||||
// On determine nom du fichier vignette
|
||||
// We forge name of thumb.
|
||||
$photo = $file;
|
||||
$photo_vignette = '';
|
||||
$regs = array();
|
||||
if (preg_match('/('.$this->regeximgext.')$/i', $photo, $regs)) {
|
||||
$photo_vignette = preg_replace('/'.$regs[0].'/i', '', $photo).'_small'.$regs[0];
|
||||
}
|
||||
@ -5467,7 +5468,7 @@ class Product extends CommonObject
|
||||
|
||||
$tabobj[$nbphoto - 1] = $obj;
|
||||
|
||||
// On continue ou on arrete de boucler ?
|
||||
// Do we have to continue with next photo ?
|
||||
if ($nbmax && $nbphoto >= $nbmax) {
|
||||
break;
|
||||
}
|
||||
@ -5482,9 +5483,9 @@ class Product extends CommonObject
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* Efface la photo du produit et sa vignette
|
||||
* Delete a photo and its thumbs
|
||||
*
|
||||
* @param string $file Chemin de l'image
|
||||
* @param string $file Path to image file
|
||||
* @return void
|
||||
*/
|
||||
public function delete_photo($file)
|
||||
|
||||
@ -370,8 +370,12 @@ class MouvementStock extends CommonObject
|
||||
if (!empty($conf->productbatch->enabled) && $product->hasbatch() && !$skip_batch) {
|
||||
$foundforbatch = 0;
|
||||
$qtyisnotenough = 0;
|
||||
|
||||
foreach ($product->stock_warehouse[$entrepot_id]->detail_batch as $batchcursor => $prodbatch) {
|
||||
if ($batch != $batchcursor) continue;
|
||||
if ((string) $batch != (string) $batchcursor) { // Lot '59' must be different than lot '59c'
|
||||
continue;
|
||||
}
|
||||
|
||||
$foundforbatch = 1;
|
||||
if ($prodbatch->qty < abs($qty)) $qtyisnotenough = $prodbatch->qty;
|
||||
break;
|
||||
|
||||
@ -45,7 +45,7 @@ if ($user->socid) {
|
||||
$result = restrictedArea($user, 'produit|service');
|
||||
|
||||
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
|
||||
$hookmanager->initHooks(array('stockreplenishlist'));
|
||||
$hookmanager->initHooks(array('stockatdate'));
|
||||
|
||||
//checks if a product has been ordered
|
||||
|
||||
|
||||
@ -1045,10 +1045,7 @@ if ($action == 'create') {
|
||||
print '<input type="hidden" name="productid'.$indiceAsked.'" value="'.$line->fk_product.'">';
|
||||
|
||||
// Show product and description
|
||||
$product_static->type = $line->fk_product_type;
|
||||
$product_static->id = $line->fk_product;
|
||||
$product_static->ref = $line->ref;
|
||||
$product_static->status_batch = $line->product_tobatch;
|
||||
$product_static = $product;
|
||||
|
||||
$text = $product_static->getNomUrl(1);
|
||||
$text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
|
||||
|
||||
@ -508,6 +508,10 @@ if ($search_sale == -2) {
|
||||
} elseif (!empty($search_sale) && $search_sale != '-1' || (empty($user->rights->societe->client->voir) && !$socid)) {
|
||||
$sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
|
||||
}
|
||||
// Add table from hooks
|
||||
$parameters = array();
|
||||
$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
|
||||
$sql .= $hookmanager->resPrint;
|
||||
$sql .= " WHERE s.entity IN (".getEntity('societe').")";
|
||||
//if (empty($user->rights->societe->client->voir) && (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || empty($user->rights->societe->client->readallthirdparties_advance)) && !$socid) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id;
|
||||
if (empty($user->rights->societe->client->voir) && !$socid) {
|
||||
@ -667,6 +671,10 @@ if (empty($reshook)) {
|
||||
}
|
||||
}
|
||||
$sql .= $hookmanager->resPrint;
|
||||
// Add GroupBy from hooks
|
||||
$parameters = array('all' => $all, 'fieldstosearchall' => $fieldstosearchall);
|
||||
$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook
|
||||
$sql .= $hookmanager->resPrint;
|
||||
|
||||
$sql .= $db->order($sortfield, $sortorder);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user