diff --git a/ChangeLog b/ChangeLog index ef52f808ec71a..052b8bcaaf1e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,47 @@ Upgrading to any other version or any other database system is abolutely require make a Dolibarr upgrade. + +***** ChangeLog for 3.9.2 compared to 3.9.1 ***** +FIX: #4813 Won translation for the key OppStatusWON instead OppStatusWIN +FIX: #5008 SQL error when editing the reference of a supplier invoice that already exists +FIX: #5236 Cron module activated but "Modules tools" does not appear in the left menu. +FIX: Accountancy - 3.9 - Chart of accounts are limited on only one country +FIX: bug on email template +FIX: Can't create a stock transfer from product card +FIX: can't fetch by siret or siren because of first "if" +FIX: Check stock of product by warehouse if $entrepot_id defined on shippings +FIX: Compatible with multicompany +FIX: Creation of the second ressource type fails. +FIX: end of select when no fournprice +FIX: Filter on assigned to was preselected on current user on list "All events" (instead of no filtering) +FIX: Filter on category tag for suppliers +FIX: hook on group card called but not initialized +FIX: Infinite loop on menu tree output for edition +FIX: Can show tree of entries added by external modules using fk_mainmenu and fk_leftmenu instead of fk_menu. +FIX: init var at wrong place report incorrect "shippable" flag on draft order. +FIX: It doesn't check if there is enough stock to update the lines of orders/invoices +FIX: Menu statistics was not visible if module proposal was not enabled +FIX: Merge manually PR #5161 - Bad translation key +FIX: missing column when module was installed before standard integration +FIX: Missing number total of modules +FIX: Not filtering correctly when coming from dashboard +FIX: PROPAL_MERGE_PDF with PRODUCT_USE_OLD_PATH +FIX: Remove PHP Warning: Creating default object from empty value. +FIX: same page added several times on mergepropal option +FIX: search on date into supplier invoice list dont work because of status -1 +FIX: Search supplier ref on contract +FIX: Split of credit note into discount page generates records not correctly recognised as credit note. +FIX: SQL error function on getAvailableDiscounts function, on bill create mode if socid is empty +FIX: #5087 +FIX: #5108 +FIX: #5163 +FIX: #5195 +FIX: #5203 +FIX: #5207 +FIX: #5209 +FIX: #5230 + ***** ChangeLog for 3.9.1 compared to 3.9.* ***** FIX: #3815 Call to undefined function local_by_date() FIX: #4424 Missing email of user popup in supplier orders area diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index b8c4f2fb475c9..8a70ea73f2ccc 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -379,7 +379,7 @@ print 'Run git tag -a -m "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'" "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'"'."\n"; $ret=`git tag -a -m "$MAJOR.$MINOR.$BUILD" "$MAJOR.$MINOR.$BUILD" 2>&1`; - if ($ret =~ /already exists/) + if ($ret =~ /(already exists|existe déjà)/) { print "WARNING: Tag ".$MAJOR.'.'.$MINOR.'.'.$BUILD." already exists. Overwrite (y/N) ? "; $QUESTIONOVERWRITETAG=; diff --git a/htdocs/accountancy/admin/account.php b/htdocs/accountancy/admin/account.php index 3f251e0090b68..99b78ff7c5ca5 100644 --- a/htdocs/accountancy/admin/account.php +++ b/htdocs/accountancy/admin/account.php @@ -43,7 +43,9 @@ $search_pcgsubtype = GETPOST("search_pcgsubtype"); // Security check -if (! $user->admin) +if ($user->societe_id > 0) + accessforbidden(); +if (! $user->rights->accounting->chartofaccount) accessforbidden(); $sortfield = GETPOST("sortfield", 'alpha'); diff --git a/htdocs/accountancy/admin/fiscalyear.php b/htdocs/accountancy/admin/fiscalyear.php index 75411d6402f11..199e04bb856a5 100644 --- a/htdocs/accountancy/admin/fiscalyear.php +++ b/htdocs/accountancy/admin/fiscalyear.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2013-2016 Alexandre Spangaro * * 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 @@ -30,12 +30,15 @@ $langs->load("admin"); $langs->load("compta"); -if (! $user->admin) +// Security check +if ($user->societe_id > 0) + accessforbidden(); +if (! $user->rights->accounting->fiscalyear) accessforbidden(); $error = 0; -// List of statut +// List of status static $tmpstatut2label = array ( '0' => 'OpenFiscalYear', '1' => 'CloseFiscalYear' diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 03cb46adf0d6c..92b3ec7adc007 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -1,7 +1,7 @@ * Copyright (C) 2013-2014 Florian Henry - * Copyright (C) 2013-2015 Alexandre Spangaro + * Copyright (C) 2013-2016 Alexandre Spangaro * Copyright (C) 2014-2015 Ari Elbaz (elarifr) * Copyright (C) 2014 Marcos García * Copyright (C) 2014 Juanjo Menent @@ -202,10 +202,9 @@ print ""; print ''; -print ""; +//print "
"; +//print ''; +//print ""; print ''; print ''; @@ -261,7 +252,7 @@ // Build barcode on disk (not used, this is done to make debug easier) $result=$module->writeBarCode($obj->example,$obj->encoding,'Y'); // Generate on the fly and output barcode with generator - $url=DOL_URL_ROOT.'/viewimage.php?modulepart=barcode&generator='.urlencode($obj->coder).'&code='.urlencode($obj->example).'&encoding='.urlencode($obj->encoding); + $url=DOL_URL_ROOT.'/viewimage.php?modulepart=barcode&generator='.urlencode($obj->coder).'&code='.urlencode($obj->example).'&encoding='.urlencode($obj->encoding); //print $url; print ''; } @@ -296,7 +287,7 @@ // TODO Implement code behind action updateengine //print '
'; } -print ''; +//print ''; print "
"; @@ -331,9 +322,7 @@ $langs->load("errors"); print '
'.$langs->trans("ErrorFileNotFound",$conf->global->GENBARCODE_LOCATION).''; } - print ''; - print ''; - print ''; + print ''; } // Module products @@ -344,10 +333,7 @@ print ''; print '"; - print ''; + print ''; } // Module thirdparty @@ -358,13 +344,13 @@ print ''; print '"; - print ''; + print ''; } print "
'.$langs->trans("SetDefaultBarcodeTypeProducts").''; $formbarcode->select_barcode_type($conf->global->PRODUIT_DEFAULT_BARCODE_TYPE,"PRODUIT_DEFAULT_BARCODE_TYPE",1); - print ''; - print ''; - print "
'.$langs->trans("SetDefaultBarcodeTypeThirdParties").''; print $formbarcode->select_barcode_type($conf->global->GENBARCODE_BARCODETYPE_THIRDPARTY,"GENBARCODE_BARCODETYPE_THIRDPARTY",1); - print ''; - print ''; - print "
\n"; +print '
'; +print ''; +print "
"; print ''; print '
'; @@ -419,13 +405,13 @@ if ($conf->global->BARCODE_PRODUCT_ADDON_NUM == "$file") { - print ''; + print ''; print img_picto($langs->trans("Activated"),'switch_on'); print ''; } else { - print ''; + print ''; print img_picto($langs->trans("Disabled"),'switch_off'); print ''; } @@ -442,7 +428,7 @@ print "\n"; } -print ''; +//print ''; print "
"; diff --git a/htdocs/admin/menus/edit.php b/htdocs/admin/menus/edit.php index f4f1bbb96bf70..9941843cda18a 100644 --- a/htdocs/admin/menus/edit.php +++ b/htdocs/admin/menus/edit.php @@ -271,7 +271,7 @@ function init_topleft() '; print load_fiche_titre($langs->trans("NewMenu"),'','title_setup'); - + print '
'; print ''; @@ -281,7 +281,7 @@ function init_topleft() $parent_rowid = $_GET['menuId']; if ($_GET['menuId']) { - $sql = "SELECT m.rowid, m.mainmenu, m.level, m.langs FROM ".MAIN_DB_PREFIX."menu as m WHERE m.rowid = ".$_GET['menuId']; + $sql = "SELECT m.rowid, m.mainmenu, m.leftmenu, m.level, m.langs FROM ".MAIN_DB_PREFIX."menu as m WHERE m.rowid = ".$_GET['menuId']; $res = $db->query($sql); if ($res) { @@ -290,6 +290,7 @@ function init_topleft() { $parent_rowid = $menu['rowid']; $parent_mainmenu = $menu['mainmenu']; + $parent_leftmenu = $menu['leftmenu']; $parent_langs = $menu['langs']; $parent_level = $menu['level']; } @@ -340,7 +341,9 @@ function init_topleft() { print ''; } - print ''.$langs->trans('DetailMenuIdParent').''; + print ''.$langs->trans('DetailMenuIdParent'); + print ', '.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def'; + print ''; // Title print ''.$langs->trans('Title').''.$langs->trans('DetailTitre').''; @@ -418,7 +421,12 @@ function init_topleft() print ''.$langs->trans('MenuIdParent').''; //$menu_handler //print ''; - print ''.$menu->fk_menu.''; + print ''; + $valtouse=$menu->fk_menu; + if ($menu->fk_mainmenu) $valtouse='fk_mainmenu='.$menu->fk_mainmenu; + if ($menu->fk_leftmenu) $valtouse.='&fk_leftmenu='.$menu->fk_leftmenu; + print $valtouse; + print ''; print ''.$langs->trans('DetailMenuIdParent').''; // Niveau diff --git a/htdocs/admin/menus/index.php b/htdocs/admin/menus/index.php index 7da0673b196f1..27b8ab74a969f 100644 --- a/htdocs/admin/menus/index.php +++ b/htdocs/admin/menus/index.php @@ -289,17 +289,18 @@ - la chaine a afficher ie: data[]= array (index, index parent, chaine ) */ + //il faut d'abord declarer un element racine de l'arbre - $data[] = array('rowid'=>0,'fk_menu'=>-1,'title'=>"racine",'mainmenu'=>'','leftmenu'=>'','fk_mainmenu'=>'','fk_leftmenu'=>''); - + $data[] = array('rowid'=>0,'fk_menu'=>-1,'title'=>"racine",'mainmenu'=>'','leftmenu'=>'','fk_mainmenu'=>'','fk_leftmenu'=>''); + //puis tous les elements enfants - $sql = "SELECT m.rowid, m.titre, m.langs, m.mainmenu, m.leftmenu, m.fk_menu, m.fk_mainmenu, m.fk_leftmenu"; + $sql = "SELECT m.rowid, m.titre, m.langs, m.mainmenu, m.leftmenu, m.fk_menu, m.fk_mainmenu, m.fk_leftmenu, m.module"; $sql.= " FROM ".MAIN_DB_PREFIX."menu as m"; $sql.= " WHERE menu_handler = '".$menu_handler_to_search."'"; $sql.= " AND entity = ".$conf->entity; - $sql.= " AND fk_menu >= 0"; + //$sql.= " AND fk_menu >= 0"; $sql.= " ORDER BY m.position, m.rowid"; // Order is position then rowid (because we need a sort criteria when position is same) $res = $db->query($sql); @@ -314,9 +315,10 @@ $titre = $langs->trans($menu['titre']); $data[] = array( 'rowid'=>$menu['rowid'], + 'module'=>$menu['module'], 'fk_menu'=>$menu['fk_menu'], 'title'=>$titre, - 'mainmenu'=>$menu['mainmenu'], + 'mainmenu'=>$menu['mainmenu'], 'leftmenu'=>$menu['leftmenu'], 'fk_mainmenu'=>$menu['fk_mainmenu'], 'fk_leftmenu'=>$menu['fk_leftmenu'], @@ -334,17 +336,54 @@ } } + global $tree_recur_alreadyadded; // This var was def into tree_recur + // Appelle de la fonction recursive (ammorce) // avec recherche depuis la racine. //var_dump($data); - tree_recur($data,$data[0],0); + tree_recur($data, $data[0], 0, 'iddivjstree'); // $data[0] is virtual record 'racine' + print ''; - + print ''; - + print ''; - + + + // Process remaining records (records that are not linked to root by any path) + $remainingdata = array(); + foreach($data as $datar) + { + if (empty($datar['rowid']) || $tree_recur_alreadyadded[$datar['rowid']]) continue; + $remainingdata[] = $datar; + } + + if (count($remainingdata)) + { + print ''; + + print ''; + print ''; + print ''; + print ''; + + print ''; + print ''; + + print ''; + + print '
'.$langs->trans("NotTopTreeMenuPersonalized").'
'; + + foreach($remainingdata as $datar) + { + $father = array('rowid'=>$datar['rowid'],'title'=>"???",'mainmenu'=>$datar['fk_mainmenu'],'leftmenu'=>$datar['fk_leftmenu'],'fk_mainmenu'=>'','fk_leftmenu'=>''); + //print 'Start with rowid='.$datar['rowid'].' mainmenu='.$father ['mainmenu'].' leftmenu='.$father ['leftmenu'].'
'."\n"; + tree_recur($data, $father, 0, 'iddivjstree'.$datar['rowid'], 1, 1); + } + + print '
'; + } print ''; diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 3fbaddd0a3f6b..aa4c1b85caecf 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -223,7 +223,7 @@ //var_dump($modules); $nbofactivatedmodules=count($conf->modules); -$moreinfo=$langs->trans("TotalNumberOfActivatedModules",($nbofactivatedmodules-1)); +$moreinfo=$langs->trans("TotalNumberOfActivatedModules",($nbofactivatedmodules-1), count($modules)); if ($nbofactivatedmodules <= 1) $moreinfo .= ' '.img_warning($langs->trans("YouMustEnableOneModule")); print load_fiche_titre($langs->trans("ModulesSetup"),$moreinfo,'title_setup'); diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 62512562e9a0a..123189bdc87b4 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1173,7 +1173,7 @@ function init_repeat() // Clone event if($action == 'clone') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . GETPOST('id'), $langs->trans('CloneAction'), $langs->trans('ConfirmCloneAction', $object->label), 'confirm_clone', $formquestion, 'yes', 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . GETPOST('id'), $langs->trans('CloneAction'), $langs->trans('ConfirmCloneEvent', $object->label), 'confirm_clone', $formquestion, 'yes', 1); print $formconfirm; } diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index fe7b15c66feb2..cf2b475e10d71 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -48,7 +48,7 @@ $usergroup = GETPOST("usergroup","int",3); $showbirthday = empty($conf->use_javascript_ajax)?GETPOST("showbirthday","int"):1; -// If not choice done on calendar owner, we filter on user. +// If not choice done on calendar owner (like on left menu link "Agenda"), we filter on user. if (empty($filtert) && empty($conf->global->AGENDA_ALL_CALENDARS)) { $filtert=$user->id; diff --git a/htdocs/comm/action/listactions.php b/htdocs/comm/action/listactions.php index 447a247ad56b4..a9dd8d8f1e51c 100644 --- a/htdocs/comm/action/listactions.php +++ b/htdocs/comm/action/listactions.php @@ -1,7 +1,7 @@ * Copyright (C) 2003 Eric Seigne - * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2004-2016 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * * This program is free software; you can redistribute it and/or modify @@ -210,7 +210,7 @@ if ($filtert > 0 || $usergroup > 0) { $sql.= " AND ("; - if ($filtert > 0) $sql.= "(ar.fk_element = ".$filtert." OR a.fk_user_action=".$filtert.")"; + if ($filtert > 0) $sql.= "(ar.fk_element = ".$filtert." OR (ar.fk_element IS NULL AND a.fk_user_action=".$filtert."))"; // The OR is for backward compatibility if ($usergroup > 0) $sql.= ($filtert>0?" OR ":"")." ugu.fk_usergroup = ".$usergroup; $sql.= ")"; } @@ -350,7 +350,7 @@ $actionstatic->type_code=$obj->type_code; $actionstatic->type_label=$obj->type_label; $actionstatic->label=$obj->label; - print $actionstatic->getNomUrl(1,28); + print $actionstatic->getNomUrl(1,36); print ''; if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) diff --git a/htdocs/comm/propal.php b/htdocs/comm/propal.php index 51057ec3af425..29b57839d56eb 100644 --- a/htdocs/comm/propal.php +++ b/htdocs/comm/propal.php @@ -562,15 +562,6 @@ } } - // Reopen proposal - else if ($action == 'confirm_reopen' && $user->rights->propal->cloturer && ! GETPOST('cancel')) - { - // prevent browser refresh from reopening proposal several times - if ($object->statut == Propal::STATUS_SIGNED || $object->statut == Propal::STATUS_NOTSIGNED || $object->statut == Propal::STATUS_BILLED) { - $object->reopen($user, 1); - } - } - // Close proposal else if ($action == 'setstatut' && $user->rights->propal->cloturer && ! GETPOST('cancel')) { @@ -591,17 +582,6 @@ } } - // Classify billed - else if ($action == 'classifybilled' && $user->rights->propal->cloturer) - { - $result=$object->cloture($user, 4, ''); - if ($result < 0) - { - setEventMessages($object->error, $object->errors, 'errors'); - $error++; - } - } - // Reopen proposal else if ($action == 'confirm_reopen' && $user->rights->propal->cloturer && ! GETPOST('cancel')) { @@ -617,20 +597,6 @@ } } - // Close proposal - else if ($action == 'setstatut' && $user->rights->propal->cloturer && ! GETPOST('cancel')) - { - if (! GETPOST('statut')) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CloseAs")), null, 'errors'); - $action = 'statut'; - } else { - // prevent browser refresh from closing proposal several times - if ($object->statut == Propal::STATUS_VALIDATED) { - $object->cloture($user, GETPOST('statut'), GETPOST('note')); - } - } - } - include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 63bf3b86c56c7..112dbf792ff0f 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2505,7 +2505,7 @@ function load_board($user,$mode) $response = new WorkboardResponse(); $response->warning_delay = $delay_warning/60/60/24; $response->label = $label; - $response->url = DOL_URL_ROOT.'/comm/propal/list.php?viewstatut='.$statut; + $response->url = DOL_URL_ROOT.'/comm/propal/list.php?viewstatut='.$statut.'&mainmenu=commercial&leftmenu=propals'; $response->img = img_object($langs->trans("Propals"),"propal"); // This assignment in condition is not a bug. It allows walking the results. diff --git a/htdocs/comm/remx.php b/htdocs/comm/remx.php index 07989b457dea6..a4aff6d71c145 100644 --- a/htdocs/comm/remx.php +++ b/htdocs/comm/remx.php @@ -341,22 +341,22 @@ $var = !$var; print ""; print ''.dol_print_date($db->jdate($obj->dc),'dayhour').''; - if ($obj->description == '(CREDIT_NOTE)') + if (preg_match('/\(CREDIT_NOTE\)/',$obj->description)) { print ''; $facturestatic->id=$obj->fk_facture_source; $facturestatic->ref=$obj->ref; $facturestatic->type=$obj->type; - print $langs->trans("CreditNote").' '.$facturestatic->getNomURl(1); + print preg_replace('/\(CREDIT_NOTE\)/',$langs->trans("CreditNote"),$obj->description).' '.$facturestatic->getNomURl(1); print ''; } - elseif ($obj->description == '(DEPOSIT)') + elseif (preg_match('/\(DEPOSIT\)/',$obj->description)) { print ''; $facturestatic->id=$obj->fk_facture_source; $facturestatic->ref=$obj->ref; $facturestatic->type=$obj->type; - print $langs->trans("InvoiceDeposit").' '.$facturestatic->getNomURl(1); + print preg_replace('/\(DEPOSIT\)/',$langs->trans("InvoiceDeposit"),$obj->description).' '.$facturestatic->getNomURl(1); print ''; } else @@ -500,22 +500,22 @@ $var = !$var; print ""; print ''.dol_print_date($db->jdate($obj->dc),'dayhour').''; - if ($obj->description == '(CREDIT_NOTE)') + if (preg_match('/\(CREDIT_NOTE\)/',$obj->description)) { print ''; $facturestatic->id=$obj->fk_facture_source; $facturestatic->ref=$obj->ref; $facturestatic->type=$obj->type; - print $langs->trans("CreditNote").' '.$facturestatic->getNomURl(1); + print preg_replace('/\(CREDIT_NOTE\)/',$langs->trans("CreditNote"),$obj->description).' '.$facturestatic->getNomURl(1); print ''; } - elseif ($obj->description == '(DEPOSIT)') + elseif (preg_match('/\(DEPOSIT\)/',$obj->description)) { print ''; $facturestatic->id=$obj->fk_facture_source; $facturestatic->ref=$obj->ref; $facturestatic->type=$obj->type; - print $langs->trans("InvoiceDeposit").' '.$facturestatic->getNomURl(1); + print preg_replace('/\(DEPOSIT\)/',$langs->trans("InvoiceDeposit"),$obj->description).' '.$facturestatic->getNomURl(1); print ''; } else diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 4dbc60569bbd1..ee576ed48e5f2 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -445,7 +445,15 @@ setEventMessages($object->error, $object->errors, 'errors'); } } - + else if ($action == 'classifyunbilled' && $user->rights->commande->creer) + { + $ret=$object->classifyUnBilled(); + + if ($ret < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } + } + // Positionne ref commande client else if ($action == 'set_ref_client' && $user->rights->commande->creer) { $object->set_ref_client($user, GETPOST('ref_client')); @@ -1900,8 +1908,8 @@ // invoice $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice } else { - $filterabsolutediscount = "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description='(DEPOSIT)')"; - $filtercreditnote = "fk_facture_source IS NOT NULL AND description <> '(DEPOSIT)'"; + $filterabsolutediscount = "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description LIKE '(DEPOSIT)%')"; + $filtercreditnote = "fk_facture_source IS NOT NULL AND description NOT LIKE '(DEPOSIT)%'"; } // Relative and absolute discounts @@ -2373,7 +2381,11 @@ print ''; } } - + if ($object->statut > Commande::STATUS_DRAFT && $object->billed) { + if ($user->rights->commande->creer && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { + print ''; + } + } // Clone if ($user->rights->commande->creer) { print ''; diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index af73be2330d5d..30d22e7588ea4 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -9,6 +9,7 @@ * Copyright (C) 2012 Cedric Salvador * Copyright (C) 2013 Florian Henry * Copyright (C) 2014-2015 Marcos García + * Copyright (C) 2016 Ferran Marcet * * 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 @@ -2419,7 +2420,57 @@ function classer_facturee() return $this->classifyBilled(); } - + /** + * Classify the order as not invoiced + * + * @return int <0 if ko, >0 if ok + */ + function classifyUnBilled() + { + global $conf, $user, $langs; + $error = 0; + + $this->db->begin(); + + $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande SET facture = 0'; + $sql.= ' WHERE rowid = '.$this->id.' AND fk_statut > '.self::STATUS_DRAFT; + + dol_syslog(get_class($this)."::classifyUnBilled", LOG_DEBUG); + if ($this->db->query($sql)) + { + // Call trigger + $result=$this->call_trigger('ORDER_CLASSIFY_UNBILLED',$user); + if ($result < 0) $error++; + // End call triggers + + if (! $error) + { + $this->facturee=0; // deprecated + $this->billed=0; + + $this->db->commit(); + return 1; + } + else + { + foreach($this->errors as $errmsg) + { + dol_syslog(get_class($this)."::classifyUnBilled ".$errmsg, LOG_ERR); + $this->error.=($this->error?', '.$errmsg:$errmsg); + } + $this->db->rollback(); + return -1*$error; + } + } + else + { + $this->error=$this->db->error(); + $this->db->rollback(); + return -1; + } + } + + /** * Update a line in database * @@ -2448,7 +2499,7 @@ function classer_facturee() */ function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1=0.0,$txlocaltax2=0.0, $price_base_type='HT', $info_bits=0, $date_start='', $date_end='', $type=0, $fk_parent_line=0, $skip_update_total=0, $fk_fournprice=null, $pa_ht=0, $label='', $special_code=0, $array_options=0, $fk_unit=null) { - global $conf, $mysoc; + global $conf, $mysoc, $langs; dol_syslog(get_class($this)."::updateline id=$rowid, desc=$desc, pu=$pu, qty=$qty, remise_percent=$remise_percent, txtva=$txtva, txlocaltax1=$txlocaltax1, txlocaltax2=$txlocaltax2, price_base_type=$price_base_type, info_bits=$info_bits, date_start=$date_start, date_end=$date_end, type=$type, fk_parent_line=$fk_parent_line, pa_ht=$pa_ht, special_code=$special_code"); include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; @@ -2504,6 +2555,26 @@ function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocalt $line = new OrderLine($this->db); $line->fetch($rowid); + if (!empty($line->fk_product)) + { + $product=new Product($this->db); + $result=$product->fetch($line->fk_product); + $product_type=$product->type; + + if (! empty($conf->global->STOCK_MUST_BE_ENOUGH_FOR_ORDER) && $product_type == 0 && $product->stock_reel < $qty) + { + $this->error=$langs->trans('ErrorStockIsNotEnough'); + dol_syslog(get_class($this)."::addline error=Product ".$product->ref.": ".$this->error, LOG_ERR); + $this->db->rollback(); + unset($_POST['productid']); + unset($_POST['tva_tx']); + unset($_POST['price_ht']); + unset($_POST['qty']); + unset($_POST['buying_price']); + return self::STOCK_NOT_ENOUGH_FOR_ORDER; + } + } + $staticline = clone $line; $line->oldline = $staticline; @@ -2854,7 +2925,7 @@ function load_board($user) $response = new WorkboardResponse(); $response->warning_delay=$conf->commande->client->warning_delay/60/60/24; $response->label=$langs->trans("OrdersToProcess"); - $response->url=DOL_URL_ROOT.'/commande/list.php?viewstatut=-3'; + $response->url=DOL_URL_ROOT.'/commande/list.php?viewstatut=-3&mainmenu=commercial&leftmenu=orders'; $response->img=img_object($langs->trans("Orders"),"order"); $generic_commande = new Commande($this->db); diff --git a/htdocs/commande/class/commandestats.class.php b/htdocs/commande/class/commandestats.class.php index 1ab418a9daa59..e38097e4e3ad0 100644 --- a/htdocs/commande/class/commandestats.class.php +++ b/htdocs/commande/class/commandestats.class.php @@ -206,7 +206,7 @@ function getAllByProduct($year) $sql = "SELECT product.ref, COUNT(product.ref) as nb, SUM(tl.".$this->field_line.") as total, AVG(tl.".$this->field_line.") as avg"; $sql.= " FROM ".$this->from.", ".$this->from_line.", ".MAIN_DB_PREFIX."product as product"; - //if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE ".$this->where; $sql.= " AND c.rowid = tl.fk_commande AND tl.fk_product = product.rowid"; $sql.= " AND c.date_commande BETWEEN '".$this->db->idate(dol_get_first_day($year,1,false))."' AND '".$this->db->idate(dol_get_last_day($year,12,false))."'"; diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index d26c5dea5dd0e..cfb8486be6f7c 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -429,15 +429,15 @@ // Show shippable Icon (create subloop, so may be slow) if ($conf->stock->enabled) { + $notshippable=0; + $warning = 0; + $text_info=''; + $text_warning=''; + $nbprod=0; + $langs->load("stocks"); if (($objp->fk_statut > 0) && ($objp->fk_statut < 3)) { - $notshippable=0; - $warning = 0; - $text_info=''; - $text_warning=''; - $nbprod=0; - $numlines = count($generic_commande->lines); // Loop on each line of order for ($lig=0; $lig < $numlines; $lig++) { diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 9747703c58fbf..7058647fae6ab 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -7,6 +7,7 @@ * Copyright (C) 2013 Florian Henry * Copyright (C) 2015 Marcos García * Copyright (C) 2015 Alexandre Spangaro + * Copyright (C) 2016 Ferran Marcet * * 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 @@ -986,6 +987,7 @@ public static function countAccountToReconcile() $sql = "SELECT COUNT(ba.rowid) as nb"; $sql.= " FROM ".MAIN_DB_PREFIX."bank_account as ba"; $sql.= " WHERE ba.rappro > 0 and ba.clos = 0"; + $sql.= " AND ba.entity IN (".getEntity('bank_account', 1).")"; if (empty($conf->global->BANK_CAN_RECONCILIATE_CASHACCOUNT)) $sql.= " AND ba.courant != 2"; $resql=$db->query($sql); if ($resql) diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index 79045fe54b944..04951cbb6cd4b 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -392,21 +392,22 @@ // Check parameters - // Check for mandatory prof id - for($i = 1; $i < 6; $i ++) + // Check for mandatory prof id (but only if country is than than ours) + if ($mysoc->country_id > 0 && $object->thirdparty->country_id == $mysoc->country_id) { - $idprof_mandatory = 'SOCIETE_IDPROF' . ($i) . '_INVOICE_MANDATORY'; - $idprof = 'idprof' . $i; - if (! $object->thirdparty->$idprof && ! empty($conf->global->$idprof_mandatory)) - { - if (! $error) - $langs->load("errors"); - $error ++; - - setEventMessages($langs->trans('ErrorProdIdIsMandatory', $langs->transcountry('ProfId' . $i, $object->thirdparty->country_code)), null, 'errors'); - } + for ($i = 1; $i <= 6; $i++) + { + $idprof_mandatory = 'SOCIETE_IDPROF' . ($i) . '_INVOICE_MANDATORY'; + $idprof = 'idprof' . $i; + if (! $object->thirdparty->$idprof && ! empty($conf->global->$idprof_mandatory)) + { + if (! $error) $langs->load("errors"); + $error++; + setEventMessages($langs->trans('ErrorProdIdIsMandatory', $langs->transcountry('ProfId' . $i, $object->thirdparty->country_code)), null, 'errors'); + } + } } - + $qualified_for_stock_change = 0; if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) { $qualified_for_stock_change = $object->hasProductsOrServices(2); @@ -1954,7 +1955,7 @@ $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice); // Do not set 0 here (0 for a date is 1970) } - $absolute_discount = $soc->getAvailableDiscounts(); + if(!empty($soc->id)) $absolute_discount = $soc->getAvailableDiscounts(); if (! empty($conf->use_javascript_ajax)) { @@ -2563,8 +2564,8 @@ $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice } else { - $filterabsolutediscount = "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description='(DEPOSIT)')"; - $filtercreditnote = "fk_facture_source IS NOT NULL AND description <> '(DEPOSIT)'"; + $filterabsolutediscount = "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description LIKE '(DEPOSIT)%')"; + $filtercreditnote = "fk_facture_source IS NOT NULL AND description NOT LIKE '(DEPOSIT)%'"; } $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount); @@ -2982,9 +2983,9 @@ // Remise dispo de type avoir if (! $absolute_discount) print '
'; - // $form->form_remise_dispo($_SERVER["PHP_SELF"].'?facid='.$object->id, 0, 'remise_id_for_payment', $soc->id, $absolute_creditnote, - // $filtercreditnote, $resteapayer); - $form->form_remise_dispo($_SERVER["PHP_SELF"] . '?facid=' . $object->id, 0, 'remise_id_for_payment', $soc->id, $absolute_creditnote, $filtercreditnote, 0); // We allow credit note even if amount is higher + // $form->form_remise_dispo($_SERVER["PHP_SELF"].'?facid='.$object->id, 0, 'remise_id_for_payment', $soc->id, $absolute_creditnote, $filtercreditnote, $resteapayer + $more=' ('.$addcreditnote.')'; + $form->form_remise_dispo($_SERVER["PHP_SELF"] . '?facid=' . $object->id, 0, 'remise_id_for_payment', $soc->id, $absolute_creditnote, $filtercreditnote, 0, $more); // We allow credit note even if amount is higher } } if (! $absolute_discount && ! $absolute_creditnote) { diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 23239f6b0ebff..af53302329701 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -14,6 +14,7 @@ * Copyright (C) 2012-2014 Raphaël Doursenaud * Copyright (C) 2013 Cedric Gross * Copyright (C) 2013 Florian Henry + * Copyright (C) 2016 Ferran Marcet * * 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 @@ -2335,6 +2336,19 @@ function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $dat $line = new FactureLigne($this->db); $line->fetch($rowid); + if (!empty($line->fk_product)) + { + $product=new Product($this->db); + $result=$product->fetch($line->fk_product); + $product_type=$product->type; + + if (! empty($conf->global->STOCK_MUST_BE_ENOUGH_FOR_INVOICE) && $product_type == 0 && $product->stock_reel < $qty) { + $this->error=$langs->trans('ErrorStockIsNotEnough'); + $this->db->rollback(); + return -3; + } + } + $staticline = clone $line; $line->oldline = $staticline; @@ -3213,7 +3227,7 @@ function load_board($user) $response = new WorkboardResponse(); $response->warning_delay=$conf->facture->client->warning_delay/60/60/24; $response->label=$langs->trans("CustomerBillsUnpaid"); - $response->url=DOL_URL_ROOT.'/compta/facture/list.php?search_status=1'; + $response->url=DOL_URL_ROOT.'/compta/facture/list.php?search_status=1&mainmenu=accountancy&leftmenu=customers_bills'; $response->img=img_object($langs->trans("Bills"),"bill"); $generic_facture = new Facture($this->db); diff --git a/htdocs/compta/index.php b/htdocs/compta/index.php index ea154303d2092..379995677380e 100644 --- a/htdocs/compta/index.php +++ b/htdocs/compta/index.php @@ -2,7 +2,7 @@ /* Copyright (C) 2001-2005 Rodolphe Quiedeville * Copyright (C) 2004-2013 Laurent Destailleur * Copyright (C) 2005-2015 Regis Houssin - * Copyright (C) 2015 Juanjo Menent + * Copyright (C) 2015-2016 Juanjo Menent * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Marcos García @@ -877,7 +877,7 @@ if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; if ($socid) $sql.= " AND ff.fk_soc = ".$socid; $sql.= " GROUP BY ff.rowid, ff.ref, ff.fk_statut, ff.libelle, ff.total_ht, ff.tva, ff.total_tva, ff.total_ttc, ff.paye,"; - $sql.= " s.nom, s.rowid, s.code_client, s.code_fournisseur"; + $sql.= " s.nom, s.rowid, s.code_client, s.code_fournisseur, ff.date_lim_reglement"; $sql.= " ORDER BY ff.date_lim_reglement ASC"; $resql=$db->query($sql); diff --git a/htdocs/compta/stats/cabyprodserv.php b/htdocs/compta/stats/cabyprodserv.php index e995b06aa6b89..07727b02a812d 100644 --- a/htdocs/compta/stats/cabyprodserv.php +++ b/htdocs/compta/stats/cabyprodserv.php @@ -177,6 +177,8 @@ // SQL request $catotal=0; +$catotal_ht=0; +$qtytotal=0; if ($modecompta == 'CREANCES-DETTES') { @@ -386,6 +388,8 @@ // Total print ''; print ''.$langs->trans("Total").''; + print ''.price($qtytotal).''; + print ' '; print ''.price($catotal_ht).''; print ''.price($catotal).''; print ' '; diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 7b8f1d1d29308..f7b18696993f5 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -326,8 +326,7 @@ $label = $lines[$i]->product_label; } - if ($conf->global->PRODUIT_DESC_IN_FORM) - $desc .= ($lines[$i]->desc && $lines[$i]->desc!=$lines[$i]->libelle)?dol_htmlentitiesbr($lines[$i]->desc):''; + $desc .= ($lines[$i]->desc && $lines[$i]->desc!=$lines[$i]->libelle)?dol_htmlentitiesbr($lines[$i]->desc):''; } else { $desc = dol_htmlentitiesbr($lines[$i]->desc); @@ -358,7 +357,6 @@ $error++; break; } - } } } @@ -1027,7 +1025,7 @@ $projectid = (!empty($objectsrc->fk_project)?$objectsrc->fk_project:''); - $soc = $objectsrc->client; + $soc = $objectsrc->thirdparty; $note_private = (! empty($objectsrc->note_private) ? $objectsrc->note_private : ''); $note_public = (! empty($objectsrc->note_public) ? $objectsrc->note_public : ''); diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php index e8c722dcab322..23df8a06593a1 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -245,7 +245,7 @@ print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; diff --git a/htdocs/core/ajax/ajaxdirpreview.php b/htdocs/core/ajax/ajaxdirpreview.php index 997e27adb2030..f1352f8e93399 100644 --- a/htdocs/core/ajax/ajaxdirpreview.php +++ b/htdocs/core/ajax/ajaxdirpreview.php @@ -240,7 +240,10 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; $useglobalvars=1; $form = new Form($db); - $formquestion=array('urlfile'=>array('type'=>'hidden','value'=>$urlfile,'name'=>'urlfile')); + $formquestion=array( + 'urlfile'=>array('type'=>'hidden','value'=>$urlfile,'name'=>'urlfile'), + 'section'=>array('type'=>'hidden','value'=>$section,'name'=>'section') + ); print $form->formconfirm($url,$langs->trans("DeleteFile"),$langs->trans("ConfirmDeleteFile"),'confirm_deletefile',$formquestion,"no",($useajax?'deletefile':0)); } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 716a462f440df..c314011874552 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4246,7 +4246,7 @@ public function defineBuyPrice($unitPrice = 0, $discountPercent = 0, $fk_product $productFournisseur = new ProductFournisseur($this->db); if (($result = $productFournisseur->find_min_price_product_fournisseur($fk_product)) > 0) { - $buyPrice = $productFournisseur->fourn_price; + $buyPrice = $productFournisseur->fourn_unitprice; } else if ($result < 0) { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9a4fb17fa9c23..64ec3d4afdda9 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1128,8 +1128,8 @@ function select_remises($selected, $htmlname, $filter, $socid, $maxvalue=0) { $obj = $this->db->fetch_object($resql); $desc=dol_trunc($obj->description,40); - if ($desc=='(CREDIT_NOTE)') $desc=$langs->trans("CreditNote"); - if ($desc=='(DEPOSIT)') $desc=$langs->trans("Deposit"); + if (preg_match('/\(CREDIT_NOTE\)/', $desc)) $desc=preg_replace('/\(CREDIT_NOTE\)/', $langs->trans("CreditNote"), $desc); + if (preg_match('/\(DEPOSIT\)/', $desc)) $desc=preg_replace('/\(DEPOSIT\)/', $langs->trans("Deposit"), $desc); $selectstring=''; if ($selected > 0 && $selected == $obj->rowid) $selectstring=' selected'; @@ -2278,7 +2278,7 @@ function select_product_fourn_price($productid,$htmlname='productfournpriceid') $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid"; - $sql.= " WHERE p.entity IN (".getEntity('product', 1).")"; + $sql.= " WHERE p.entity IN (".getEntity('productprice', 1).")"; $sql.= " AND p.tobuy = 1"; $sql.= " AND s.fournisseur = 1"; $sql.= " AND p.rowid = ".$productid; @@ -2351,10 +2351,10 @@ function select_product_fourn_price($productid,$htmlname='productfournpriceid') $form.= $opt; $i++; } - $form.= ''; - - $this->db->free($result); } + + $form.= ''; + $this->db->free($result); return $form; } else @@ -3762,7 +3762,7 @@ function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter } else { - if (! $filter || $filter=="fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description='(DEPOSIT)')") print $langs->trans("CompanyHasAbsoluteDiscount",price($amount,0,$langs,0,0,-1,$conf->currency)).': '; + if (! $filter || $filter=="fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description LIKE '(DEPOSIT)%')") print $langs->trans("CompanyHasAbsoluteDiscount",price($amount,0,$langs,0,0,-1,$conf->currency)).': '; else print $langs->trans("CompanyHasCreditNote",price($amount,0,$langs,0,0,-1,$conf->currency)).': '; } $newfilter='fk_facture IS NULL AND fk_facture_line IS NULL'; // Remises disponibles @@ -3773,7 +3773,7 @@ function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter if ($nbqualifiedlines > 0) { print '   '; } if ($more) print $more; diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index 078dc01d96fa6..d5ce5679dd3c8 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -805,6 +805,7 @@ function select_dayofweek($selected='',$htmlname='weekid',$useempty=0) $select_week .= ''; } $select_week .= ''; return $select_week; @@ -844,6 +845,7 @@ function select_month($selected='',$htmlname='monthid',$useempty=0,$longlabel=0) $select_month .= ''; } $select_month .= ''; return $select_month; diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 8ea3221c64860..1d3fbc3a154d2 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -162,68 +162,52 @@ function connect_bind() return -1; } - if (! function_exists('ldap_connect')) + if (! function_exists("ldap_connect")) { - $this->error='Your PHP need extension ldap'; + $this->error='LDAPFunctionsNotAvailableOnPHP'; dol_syslog(get_class($this)."::connect_bind ".$this->error, LOG_WARNING); - return -1; + $return=-1; } - - // Loop on each ldap server - foreach ($this->server as $key => $host) - { - if ($connected) break; - if (empty($host)) continue; - - if (preg_match('/^ldap/',$host)) - { - $this->connection = ldap_connect($host); - } - else - { - $this->connection = ldap_connect($host,$this->serverPort); - } - if (is_resource($this->connection)) + if (empty($this->error)) + { + // Loop on each ldap server + foreach ($this->server as $key => $host) { - // Begin TLS if requested by the configuration - if (! empty($conf->global->LDAP_SERVER_USE_TLS)) - { - if (! ldap_start_tls($this->connection)) - { - dol_syslog(get_class($this)."::connect_bind failed to start tls", LOG_WARNING); - $connected = 0; - $this->close(); - } - } - - // Execute the ldap_set_option here (after connect and before bind) - $this->setVersion(); - ldap_set_option($this->connection, LDAP_OPT_SIZELIMIT, 0); // no limit here. should return true. - - - if ($this->serverType == "activedirectory") + if ($connected) break; + if (empty($host)) continue; + + if (preg_match('/^ldap/',$host)) { - $result=$this->setReferrals(); - dol_syslog(get_class($this)."::connect_bind try bindauth for activedirectory on ".$host." user=".$this->searchUser." password=".preg_replace('/./','*',$this->searchPassword),LOG_DEBUG); - $this->result=$this->bindauth($this->searchUser,$this->searchPassword); - if ($this->result) - { - $this->bind=$this->result; - $connected=2; - break; - } - else - { - $this->error=ldap_errno($this->connection).' '.ldap_error($this->connection); - } + $this->connection = ldap_connect($host); } else { - // Try in auth mode - if ($this->searchUser && $this->searchPassword) + $this->connection = ldap_connect($host,$this->serverPort); + } + + if (is_resource($this->connection)) + { + // Begin TLS if requested by the configuration + if (! empty($conf->global->LDAP_SERVER_USE_TLS)) + { + if (! ldap_start_tls($this->connection)) + { + dol_syslog(get_class($this)."::connect_bind failed to start tls", LOG_WARNING); + $connected = 0; + $this->close(); + } + } + + // Execute the ldap_set_option here (after connect and before bind) + $this->setVersion(); + ldap_set_option($this->connection, LDAP_OPT_SIZELIMIT, 0); // no limit here. should return true. + + + if ($this->serverType == "activedirectory") { - dol_syslog(get_class($this)."::connect_bind try bindauth on ".$host." user=".$this->searchUser." password=".preg_replace('/./','*',$this->searchPassword),LOG_DEBUG); + $result=$this->setReferrals(); + dol_syslog(get_class($this)."::connect_bind try bindauth for activedirectory on ".$host." user=".$this->searchUser." password=".preg_replace('/./','*',$this->searchPassword),LOG_DEBUG); $this->result=$this->bindauth($this->searchUser,$this->searchPassword); if ($this->result) { @@ -236,26 +220,45 @@ function connect_bind() $this->error=ldap_errno($this->connection).' '.ldap_error($this->connection); } } - // Try in anonymous - if (! $this->bind) + else { - dol_syslog(get_class($this)."::connect_bind try bind on ".$host,LOG_DEBUG); - $result=$this->bind(); - if ($result) + // Try in auth mode + if ($this->searchUser && $this->searchPassword) { - $this->bind=$this->result; - $connected=1; - break; + dol_syslog(get_class($this)."::connect_bind try bindauth on ".$host." user=".$this->searchUser." password=".preg_replace('/./','*',$this->searchPassword),LOG_DEBUG); + $this->result=$this->bindauth($this->searchUser,$this->searchPassword); + if ($this->result) + { + $this->bind=$this->result; + $connected=2; + break; + } + else + { + $this->error=ldap_errno($this->connection).' '.ldap_error($this->connection); + } } - else + // Try in anonymous + if (! $this->bind) { - $this->error=ldap_errno($this->connection).' '.ldap_error($this->connection); + dol_syslog(get_class($this)."::connect_bind try bind on ".$host,LOG_DEBUG); + $result=$this->bind(); + if ($result) + { + $this->bind=$this->result; + $connected=1; + break; + } + else + { + $this->error=ldap_errno($this->connection).' '.ldap_error($this->connection); + } } } } + + if (! $connected) $this->close(); } - - if (! $connected) $this->close(); } if ($connected) diff --git a/htdocs/core/class/menubase.class.php b/htdocs/core/class/menubase.class.php index cb370e31d96dd..bb842bab1aa52 100644 --- a/htdocs/core/class/menubase.class.php +++ b/htdocs/core/class/menubase.class.php @@ -264,6 +264,8 @@ function fetch($id, $user=null) $sql.= " t.mainmenu,"; $sql.= " t.leftmenu,"; $sql.= " t.fk_menu,"; + $sql.= " t.fk_mainmenu,"; + $sql.= " t.fk_leftmenu,"; $sql.= " t.position,"; $sql.= " t.url,"; $sql.= " t.target,"; @@ -293,6 +295,8 @@ function fetch($id, $user=null) $this->mainmenu = $obj->mainmenu; $this->leftmenu = $obj->leftmenu; $this->fk_menu = $obj->fk_menu; + $this->fk_mainmenu = $obj->fk_mainmenu; + $this->fk_leftmenu = $obj->fk_leftmenu; $this->position = $obj->position; $this->url = $obj->url; $this->target = $obj->target; diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index 234a23485900f..4d02acc992513 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -1032,12 +1032,12 @@ function price2numjs(amount) { if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") { $thousand = $langs->transnoentitiesnoconv("SeparatorThousand"); } - print "var dec='" . $dec . "'; var thousand='" . $thousand . "';\n"; // Set var in javascript + print "var dec='" . dol_escape_js($dec) . "'; var thousand='" . dol_escape_js($thousand) . "';\n"; // Set var in javascript ?> - var main_max_dec_shown = global->MAIN_MAX_DECIMALS_SHOWN); ?>; - var main_rounding_unit = global->MAIN_MAX_DECIMALS_UNIT; ?>; - var main_rounding_tot = global->MAIN_MAX_DECIMALS_TOT; ?>; + var main_max_dec_shown = global->MAIN_MAX_DECIMALS_SHOWN); ?>; + var main_rounding_unit = global->MAIN_MAX_DECIMALS_UNIT; ?>; + var main_rounding_tot = global->MAIN_MAX_DECIMALS_TOT; ?>; var amount = amount.toString(); diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 5c6b9613c17e4..ffb09b2b3ab35 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -732,17 +732,24 @@ function activateModule($value,$withdeps=1) if (isset($objMod->depends) && is_array($objMod->depends) && ! empty($objMod->depends)) { // Activation des modules dont le module depend + $TError=array(); $num = count($objMod->depends); for ($i = 0; $i < $num; $i++) { + $activate = false; foreach ($modulesdir as $dir) { if (file_exists($dir.$objMod->depends[$i].".class.php")) { activateModule($objMod->depends[$i]); + $activate = true; } } + + if (!$activate) $TError[] = $langs->trans('activateModuleDependNotSatisfied', $objMod->name, $objMod->depends[$i]); } + + setEventMessages('', $TError, 'errors'); } if (isset($objMod->conflictwith) && is_array($objMod->conflictwith) && ! empty($objMod->conflictwith)) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 3e7a3a40a75f1..066f97c142d26 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -436,7 +436,7 @@ function dol_size($size,$type='') */ function dol_sanitizeFileName($str,$newstr='_',$unaccent=1) { - $filesystem_forbidden_chars = array('<','>',':','/','\\','?','*','|','"'); + $filesystem_forbidden_chars = array('<','>',':','/','\\','?','*','|','"','°'); return dol_string_nospecial($unaccent?dol_string_unaccent($str):$str, $newstr, $filesystem_forbidden_chars); } diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index d354721332a54..fa3967284d968 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -970,7 +970,7 @@ function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks= $sql2.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc"; $sql2.= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet"; $sql2.= " WHERE p.rowid IN (".join(',',$arrayidofprojects).")"; - $sql2.= " GROUP BY p.rowid, p.ref, p.title, p.fk_soc, p.fk_user_creat, p.public, p.fk_statut, p.fk_opp_status, p.opp_amount"; + $sql2.= " GROUP BY p.rowid, p.ref, p.title, p.fk_soc, s.nom, p.fk_user_creat, p.public, p.fk_statut, p.fk_opp_status, p.opp_amount"; $sql2.= " ORDER BY p.title, p.ref"; $var=true; diff --git a/htdocs/core/lib/treeview.lib.php b/htdocs/core/lib/treeview.lib.php index e900931037ea3..6fc0c9f013f7f 100644 --- a/htdocs/core/lib/treeview.lib.php +++ b/htdocs/core/lib/treeview.lib.php @@ -109,11 +109,17 @@ function tree_showpad(&$fulltree,$key,$silent=0) * @param int $pere Array with parent ids ('rowid'=>,'mainmenu'=>,'leftmenu'=>,'fk_mainmenu=>,'fk_leftmenu=>) * @param int $rang Level of element * @param string $iddivjstree Id to use for parent ul element + * @param int $donoresetalreadyloaded Do not reset global array $donoresetalreadyloaded used to avoid to go down on an aleady processed record + * @param int $showfk Show fk links to parent into label * @return void */ -function tree_recur($tab, $pere, $rang, $iddivjstree='iddivjstree') +function tree_recur($tab, $pere, $rang, $iddivjstree='iddivjstree', $donoresetalreadyloaded=0, $showfk=0) { - if (empty($pere['rowid'])) + global $tree_recur_alreadyadded; + + if ($rang == 0 && empty($donoresetalreadyloaded)) $tree_recur_alreadyadded=array(); + + if ($rang == 0) { // Test also done with jstree and dynatree (not able to have inside label) print '