diff --git a/.stickler.yml b/.stickler.yml new file mode 100644 index 00000000000..b68804448b2 --- /dev/null +++ b/.stickler.yml @@ -0,0 +1,10 @@ +--- +linters: + phpcs: + standard: 'dev/setup/codesniffer/ruleset.xml' + extensions: 'php' + tab_width: 4 + fixer: true + +fixers: + enable: true diff --git a/ChangeLog b/ChangeLog index 6664dbe8941..c672c02a7a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,125 @@ English Dolibarr ChangeLog -------------------------------------------------------------- +***** ChangeLog for 8.0.6 compared to 8.0.5 ***** +FIX: #11244 +FIX: #11316 +FIX: Add missing end date of subscription in export +FIX: A user may read holiday and expense report without permissions +FIX: better syntax +FIX: condition +FIX: confirmation of mass email sending + option MAILING_NO_USING_PHPMAIL +FIX: crabe pdf: bad detailed VAT for situation invoices, in situations S2 and above +FIX: default value for duration of validity can be set from generic +FIX: do not include disabled modules tpl +FIX: do not include tpl from disabled modules +FIX: Error management when MAILING_NO_USING_PHPMAIL is set +FIX: Even with permission, can't validate leave once validator defined. +FIX: extrafield list search: SQL error when field is multiselect +FIX: if last char of customercode is accent making the truncate of first +FIX: in edit mode, dictionary inputs do not escape the string inside the 'value' attribute, causing errors if there are any double quotes +FIX: invalid link on user.fk_user +FIX: invoice class: bad SQL request if product type not set +FIX: mail presend: can overwrite a file previously uploaded +FIX: mail presend: can overwrite a file previously uploaded (Issue #11056) +FIX: mass send mail +FIX: missing compatibility with multicompany transverse mode +FIX: modulebuilder: hardcoded llx_ +FIX: Not showing Contract and Project columns on ficheinter list +FIX: remove isolated transaction commit +FIX: security (a user can read leave or holiday of other without perm. +FIX: situation invoices: bad detailed VAT in situations following the first one +FIX: situation invoices: block progress percentage change for discount lines +FIX: syntax error +FIX: try to use WHERE EXISTS instead DISTINCT +FIX: use dol_sanitizeFileName() function to remove double spaces in filenames, as well as done on document.php when we want to download pdf +FIX: var name +FIX: we need to fetch fourn invoice with ref in current entity +FIX: Wrong stock movement on supplier credit notes + +***** ChangeLog for 8.0.5 compared to 8.0.4 ***** +FIX: #10381 +FIX: #10460 compatibility with MariaDB 10.4 +FIX: #11025 +FIX: Accountancy - Add transaction with multicompany use all the time 1st entity +FIX: Accountancy - Format EBP import +FIX: actioncomm export: ORDER BY clause is in wrong export property + event type filter does not work +FIX: actioncomm: sort events by date after external calendars and hook +FIX: action list: add printFieldListSelect and printFieldListWhere hooks +FIX: add fk_unit on addline action +FIX: avoid php warning +FIX: bad sql request +FIX: better method +FIX: better test +FIX: better test on fetch +FIX: broken external authentication module feature and avoid warning +FIX: Can not create contract with numbering module without autogen rule +FIX: can't add lines on invoices +FIX: Can't generate invoice pdf +FIX: Can't insert if there is extrafields mandatory on another entity. +FIX: Can't insert if there is extrafields mandatory on another entity. FIX: Can't set default value of extrafield of type varchar +FIX: Check for old picture name if the new one was not found +FIX: Civility not saved when creating a member. +FIX: $conf->fournisseur->commande->enabled doesn't exist, we must use $conf->fournisseur->enabled +FIX: could not create several superadmin in transversal mode +FIX: credit note can have negative value +FIX: Default value on sales representative on third party creation +FIX: Don't show journal:getNomUrl without data +FIX: Erreur dans le Total +FIX: error messages not displayed +FIX: expedition: reset status on rollback + replace hardcoded status with const +FIX: Fix PHP warning "count(): Parameter must be an array..." +FIX: fk_default_warehouse missing in group by +FIX: function sendEmailsReminder isn't completely developed, then MAIN_FEATURES_LEVEL must be 2 to "use" it +FIX: holidays get natural_search if search params are set only +FIX: if empty error message, we just see "error" displayed +FIX: if(!method_exists(dol_loginfunction)) +FIX: If we build one invoice for several orders, we must put the ref of order on the line to not lose information. +FIX: in fact expensereport must be in $check array +FIX: Interface regression for bind people. Fix option MAIN_OPTIMIZEFORTEXTBROWSER +FIX: line edit template: keep fk_parent_line +FIX: Loan impossible to account +FIX: Mark credit note as available for credit note in other currency +FIX: missing access security checking with multicompany +FIX: missing entity filter and wrong var name +FIX: missing entity filter in function "build_filterField()" (export) +FIX: Missing field in import/export of users +FIX: missing hook completeTabsHead in margins module +FIX: missing $ismultientitymanaged for previous/next ref +FIX: Missing province in export of invoice +FIX: multicompany compatibility +FIX: must fetch member in current entity +FIX: need an order by in case we found other invoice with same number but not same date +FIX: need to round with 2 decimals to avoid movements not correctly balanced +FIX: no need to test anything to display documents tabs on expense report +FIX: positive values creating diff on addline rounding +FIX: problem with multicompany transverse mode +FIX: Product accountancey sell intra code must be visible if main feature level 1 +FIX: project_title for display of getNomUrl() +FIX: quick search for supplier orders +FIX: Remane of project +FIX: same thing here +FIX: Selection of email recipient with option MAIN_OPTIMIZEFORTEXTBROWSER +FIX: several hooks in shipping/delivery cards +FIX: shipping default warehouse if only one warehouse +FIX: SQL injection on rowid of dict.php +FIX: 'statut' is ignored when updating a user with the REST API. +FIX: supplier invoice payment total dont care about deposit or credit +FIX: supplier invoice product stats total ht is line total not invoice total +FIX: The minimum amount filter does not work in the VAT report per customer +FIX: Total per day shows 00:00 if the total time spent is equal to 12:00 +FIX: Update/delete currency on same languages +FIX: [URGENT] broken feature, "$usercancreate" is for Dolibarr 9 +FIX: useless join +FIX: we need to keep originline special_code +FIX: we want to be able to reopen fourn credit note +FIX: when 2 extra fields are mandatory in 2 different entities +FIX: when we add a payment on an invoice which already has payments with credit note or deposit amount, and then we get an excess received, discount amount must be $total_paiements + $total_creditnote_and_deposit - $object->total_ttc; +FIX: when we create deposit with multi tva, we mustn't add line if amount = 0 (example when we have a 100% reduc on one of origin invoice line) +FIX: wrong redirect link on holiday refuse +FIX: wrong test enabled +FIX: Wrong variable name +FIX: XSS ***** ChangeLog for 8.0.4 compared to 8.0.3 ***** FIX: #10030 better german chart diff --git a/build/generate_filelist_xml.php b/build/generate_filelist_xml.php index 0764d64b491..25f4af98207 100755 --- a/build/generate_filelist_xml.php +++ b/build/generate_filelist_xml.php @@ -121,6 +121,7 @@ else } print "Release : ".$release."\n"; +print "Working on files into : ".DOL_DOCUMENT_ROOT."\n"; print "Include custom in signature : ".$includecustom."\n"; print "Include constants in signature : "; foreach ($includeconstants as $countrycode => $tmp) diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 7ba988231cc..14d4924136a 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -22,7 +22,7 @@ $PUBLISHSTABLE="eldy,dolibarr\@frs.sourceforge.net:/home/frs/project/dolibarr"; $PUBLISHBETARC="dolibarr\@vmprod1.dolibarr.org:/home/dolibarr/dolibarr.org/httpdocs/files"; -#@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages +#@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","EXEDOLIWAMP","SNAPSHOT"); # Possible packages @LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","EXEDOLIWAMP","SNAPSHOT"); # Possible packages %REQUIREMENTPUBLISH=( "SF"=>"git ssh rsync", @@ -36,8 +36,8 @@ $PUBLISHBETARC="dolibarr\@vmprod1.dolibarr.org:/home/dolibarr/dolibarr.org/httpd "RPM_FEDORA"=>"rpmbuild", "RPM_MANDRIVA"=>"rpmbuild", "RPM_OPENSUSE"=>"rpmbuild", -"DEB"=>"dpkg", -"APS"=>"zip", +"DEB"=>"dpkg dpatch", +"FLATPACK"=>"flatpack", "EXEDOLIWAMP"=>"ISCC.exe", "SNAPSHOT"=>"tar" ); @@ -142,7 +142,6 @@ $FILENAMETGZ = "$PROJECT-$MAJOR.$MINOR.$BUILD"; $FILENAMEZIP = "$PROJECT-$MAJOR.$MINOR.$BUILD"; $FILENAMEXZ = "$PROJECT-$MAJOR.$MINOR.$BUILD"; $FILENAMEDEB = "see later"; -$FILENAMEAPS = "$PROJECT-$MAJOR.$MINOR.$BUILD.app"; $FILENAMEEXEDOLIWAMP = "DoliWamp-$MAJOR.$MINOR.$BUILD"; # For RPM $ARCH='noarch'; @@ -358,16 +357,16 @@ if ($nboftargetok) { } else { - print "ChangeLog for $MAJOR.$MINOR\.$BUILD was found into '$SOURCE/ChangeLog. But you can regenerate it with command:'\n"; + print "ChangeLog for $MAJOR.$MINOR\.$BUILD was found into '$SOURCE/ChangeLog. But you can regenerate it with command:\n"; } if (! $BUILD || $BUILD eq '0-rc') # For a major version { - print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log `git rev-list --boundary '.$MAJOR.'.'.$MINOR.'..origin/develop | grep ^- | cut -c2- | head -n 1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log `git rev-list --boundary '.$MAJOR.'.'.$MINOR.'..origin/develop | grep ^- | cut -c2- | head -n 1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\|CLOSE\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; } else # For a maintenance release { #print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log '.$MAJOR.'.'.$MINOR.'.'.($BUILD-1).'.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; - print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log '.$MAJOR.'.'.$MINOR.'.'.($BUILD-1).'.. | grep -v "Merge branch" | grep -v "Merge pull" | grep "^ " | sed -e "s/^[0-9a-z]* *//" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log '.$MAJOR.'.'.$MINOR.'.'.($BUILD-1).'.. | grep -v "Merge branch" | grep -v "Merge pull" | grep "^ " | sed -e "s/^[0-9a-z]* *//" | grep -e \'^FIX\|NEW\|CLOSE\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; } print "\n"; @@ -388,6 +387,7 @@ if ($nboftargetok) { #----------------------- if ($CHOOSEDTARGET{'-CHKSUM'}) { + chdir("$SOURCE"); print 'Create xml check file with md5 checksum with command php '.$SOURCE.'/build/generate_filelist_xml.php release='.$MAJOR.'.'.$MINOR.'.'.$BUILD."\n"; $ret=`php $SOURCE/build/generate_filelist_xml.php release=$MAJOR.$MINOR.$BUILD`; print $ret."\n"; @@ -536,6 +536,8 @@ if ($nboftargetok) { $ret=`find $BUILDROOT/$PROJECT/htdocs/custom/* -type l -exec rm -fr {} \\; >/dev/null 2>&1`; # For custom we want to remove all subdirs, even symbolic links, but not files # Removed known external modules to avoid any error when packaging from env where external modules are tested + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/abricot*`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/accountingexport*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/allscreens*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/ancotec*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/cabinetmed*`; @@ -550,11 +552,14 @@ if ($nboftargetok) { $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/multicompany*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/ndf*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/nltechno*`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/nomenclature*`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/of/`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/oscim*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/pos*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/teclib*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/timesheet*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/webmail*`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/workstation*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/accountingexport*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/themes/oblyon*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/themes/allscreen*`; @@ -586,6 +591,8 @@ if ($nboftargetok) { $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpoffice/phpexcel/Examples`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpoffice/phpexcel/unitTests`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpoffice/phpexcel/license.md`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/sabre/sabre/*/tests`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/stripe/tests`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/stripe/LICENSE`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tcpdf/fonts/dejavu-fonts-ttf-*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tcpdf/fonts/freefont-*`; @@ -692,7 +699,7 @@ if ($nboftargetok) { print "Go to directory $BUILDROOT\n"; $olddir=getcwd(); chdir("$BUILDROOT"); - $cmd= "xz -9 -r $BUILDROOT/$FILENAMEAPS.xz \*"; + $cmd= "xz -9 -r $BUILDROOT/$FILENAMEXZ.xz \*"; print $cmd."\n"; $ret= `$cmd`; chdir("$olddir"); @@ -1140,7 +1147,7 @@ if ($nboftargetok) { $ret=`cat "$SOURCE/build/exe/doliwamp/doliwamp.iss" | sed -e 's/__FILENAMEEXEDOLIWAMP__/$FILENAMEEXEDOLIWAMP/g' > "$SOURCE/build/exe/doliwamp/doliwamp.tmp.iss"`; print "Compil exe $FILENAMEEXEDOLIWAMP.exe file from iss file \"$SOURCEBACK\\build\\exe\\doliwamp\\doliwamp.tmp.iss\"\n"; - $cmd= "ISCC.exe \"Z:$SOURCEBACK\\build\\exe\\doliwamp\\doliwamp.tmp.iss\""; + $cmd= "wine ISCC.exe \"Z:$SOURCEBACK\\build\\exe\\doliwamp\\doliwamp.tmp.iss\""; print "$cmd\n"; $ret= `$cmd`; #print "$ret\n"; diff --git a/htdocs/accountancy/index.php b/htdocs/accountancy/index.php index 9a3767bd8e4..06e7b869344 100644 --- a/htdocs/accountancy/index.php +++ b/htdocs/accountancy/index.php @@ -1,6 +1,7 @@ * Copyright (C) 2016-2018 Alexandre Spangaro + * Copyright (C) 2019 Frédéric France * * 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 @@ -47,6 +48,7 @@ if ($user->societe_id > 0) llxHeader('', $langs->trans("AccountancyArea")); print load_fiche_titre($langs->trans("AccountancyArea"), '', 'title_accountancy'); +dol_fiche_head(); $step = 0; @@ -165,6 +167,7 @@ else { print $langs->trans("Module10Desc")."
\n"; } +dol_fiche_end(); llxFooter(); $db->close(); diff --git a/htdocs/adherents/admin/adherent.php b/htdocs/adherents/admin/adherent.php index 4511ee0e8a7..ad41dd1dff8 100644 --- a/htdocs/adherents/admin/adherent.php +++ b/htdocs/adherents/admin/adherent.php @@ -208,7 +208,7 @@ if ($conf->facture->enabled) { print ''.$langs->trans("ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS").''; print ''; - $form->select_produits($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS, 'ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS'); + $form->select_produits($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS, 'ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', '', 0); print ''; } print "\n"; diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index ac3e6890cf4..44aa788dd65 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -222,22 +222,22 @@ class Adherent extends CommonObject '__ID__'=>$this->id, '__MEMBER_ID__'=>$this->id, '__CIVILITY__'=>$this->getCivilityLabel(), - '__FIRSTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->firstname):$this->firstname, - '__LASTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->lastname):$this->lastname, + '__FIRSTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->firstname):($this->firstname?$this->firstname:''), + '__LASTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->lastname):($this->lastname?$this->lastname:''), '__FULLNAME__'=>$msgishtml?dol_htmlentitiesbr($this->getFullName($langs)):$this->getFullName($langs), - '__COMPANY__'=>$msgishtml?dol_htmlentitiesbr($this->societe):$this->societe, - '__ADDRESS__'=>$msgishtml?dol_htmlentitiesbr($this->address):$this->address, - '__ZIP__'=>$msgishtml?dol_htmlentitiesbr($this->zip):$this->zip, - '__TOWN__'=>$msgishtml?dol_htmlentitiesbr($this->town):$this->town, - '__COUNTRY__'=>$msgishtml?dol_htmlentitiesbr($this->country):$this->country, - '__EMAIL__'=>$msgishtml?dol_htmlentitiesbr($this->email):$this->email, - '__BIRTH__'=>$msgishtml?dol_htmlentitiesbr($birthday):$birthday, - '__PHOTO__'=>$msgishtml?dol_htmlentitiesbr($this->photo):$this->photo, - '__LOGIN__'=>$msgishtml?dol_htmlentitiesbr($this->login):$this->login, - '__PASSWORD__'=>$msgishtml?dol_htmlentitiesbr($this->pass):$this->pass, - '__PHONE__'=>$msgishtml?dol_htmlentitiesbr($this->phone):$this->phone, - '__PHONEPRO__'=>$msgishtml?dol_htmlentitiesbr($this->phone_perso):$this->phone_perso, - '__PHONEMOBILE__'=>$msgishtml?dol_htmlentitiesbr($this->phone_mobile):$this->phone_mobile, + '__COMPANY__'=>$msgishtml?dol_htmlentitiesbr($this->societe):($this->societe?$this->societe:''), + '__ADDRESS__'=>$msgishtml?dol_htmlentitiesbr($this->address):($this->address?$this->address:''), + '__ZIP__'=>$msgishtml?dol_htmlentitiesbr($this->zip):($this->zip?$this->zip:''), + '__TOWN__'=>$msgishtml?dol_htmlentitiesbr($this->town):($this->town?$this->town:''), + '__COUNTRY__'=>$msgishtml?dol_htmlentitiesbr($this->country):($this->country?$this->country:''), + '__EMAIL__'=>$msgishtml?dol_htmlentitiesbr($this->email):($this->email?$this->email:''), + '__BIRTH__'=>$msgishtml?dol_htmlentitiesbr($birthday):($birthday?$birthday:''), + '__PHOTO__'=>$msgishtml?dol_htmlentitiesbr($this->photo):($this->photo?$this->photo:''), + '__LOGIN__'=>$msgishtml?dol_htmlentitiesbr($this->login):($this->login?$this->login:''), + '__PASSWORD__'=>$msgishtml?dol_htmlentitiesbr($this->pass):($this->pass?$this->pass:''), + '__PHONE__'=>$msgishtml?dol_htmlentitiesbr($this->phone):($this->phone?$this->phone:''), + '__PHONEPRO__'=>$msgishtml?dol_htmlentitiesbr($this->phone_perso):($this->phone_perso?$this->phone_perso:''), + '__PHONEMOBILE__'=>$msgishtml?dol_htmlentitiesbr($this->phone_mobile):($this->phone_mobile?$this->phone_mobile:'') ); complete_substitutions_array($substitutionarray, $langs, $this); diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index e1e0c0d419e..07b8a9d7119 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -1976,7 +1976,7 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='') } if (! $transfound) { - print ''; + print ''; } print ''; } diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index b301a2c7a03..b8479735d18 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -49,15 +49,14 @@ $action = GETPOST('action', 'alpha'); if (preg_match('/set_([a-z0-9_\-]+)/i',$action,$reg)) { $code=$reg[1]; - $value=(GETPOST($code, 'alpha') ? GETPOST($code, 'alpha') : 1); + $value=GETPOST($code, 'alpha'); if (dolibarr_set_const($db, $code, $value, 'chaine', 0, '', $conf->entity) > 0) { - header("Location: ".$_SERVER["PHP_SELF"]); - exit; + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); } else { - dol_print_error($db); + setEventMessages($langs->trans("Error"), null, 'errors'); } } @@ -66,12 +65,11 @@ if (preg_match('/del_([a-z0-9_\-]+)/i',$action,$reg)) $code=$reg[1]; if (dolibarr_del_const($db, $code, 0) > 0) { - header("Location: ".$_SERVER["PHP_SELF"]); - exit; + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); } else { - dol_print_error($db); + setEventMessages($langs->trans("Error"), null, 'errors'); } } @@ -106,9 +104,7 @@ elseif ($action == 'update_currency') { $error = 0; - $submit = GETPOST('submit', 'alpha'); - - if ($submit == $langs->trans('Modify')) + if (GETPOST('updatecurrency', 'alpha')) { $fk_multicurrency = GETPOST('fk_multicurrency', 'int'); $rate = price2num(GETPOST('rate', 'alpha')); @@ -127,7 +123,7 @@ elseif ($action == 'update_currency') } } } - elseif ($submit == $langs->trans('Delete')) + elseif (GETPOST('deletecurrency', 'alpha')) { $fk_multicurrency = GETPOST('fk_multicurrency', 'int'); $currency = new MultiCurrency($db); @@ -334,8 +330,8 @@ foreach ($TCurrency as &$currency) print ''; print '1 '.$conf->currency.' = '; print ' '.$currency->code.' '; - print ' '; - print ''; + print ' '; + print ''; print ''; print ''; } diff --git a/htdocs/categories/index.php b/htdocs/categories/index.php index 9f41c0b016a..06b70616792 100644 --- a/htdocs/categories/index.php +++ b/htdocs/categories/index.php @@ -65,9 +65,12 @@ $arrayofcss=array('/includes/jquery/plugins/jquerytreeview/jquery.treeview.css') llxHeader('',$title,'','',0,0,$arrayofjs,$arrayofcss); -$newcardbutton = ''.$langs->trans("NewCategory").''; -$newcardbutton.= ''; -$newcardbutton.= ''; +$newcardbutton=''; +if (! empty($user->rights->categorie->creer)) { + $newcardbutton = ''.$langs->trans("NewCategory").''; + $newcardbutton.= ''; + $newcardbutton.= ''; +} print load_fiche_titre($title, $newcardbutton); diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 470a90c355f..8989807a645 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -7,6 +7,7 @@ * Copyright (C) 2013 Florian Henry * Copyright (C) 2014 Cedric GROSS * Copyright (C) 2015 Alexandre Spangaro + * Copyright (C) 2019 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 @@ -246,7 +247,10 @@ if ($action == 'add') { $object->label = $langs->transnoentitiesnoconv("Action".$object->type_code)."\n"; } - else $object->label = $cactioncomm->libelle; + else { + $cactioncomm->fetch($object->type_code); + $object->label = $cactioncomm->label; + } } } $object->fk_project = isset($_POST["projectid"])?$_POST["projectid"]:0; diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index c4d719b2e6f..9824334b325 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -1006,6 +1006,11 @@ if (! empty($hookmanager->resArray['eventarray'])) { } } +// Sort events +foreach($eventarray as $keyDate => &$dateeventarray) +{ + usort($dateeventarray, 'sort_events_by_date'); +} $maxnbofchar=0; @@ -1700,3 +1705,22 @@ function dol_color_minus($color, $minus, $minusunit = 16) } return $newcolor; } + + +/** + * Sort events by date + * + * @param object $a Event A + * @param object $b Event B + * @return int < 0 if event A should be before event B, > 0 otherwise, 0 if they have the exact same time slot + */ +function sort_events_by_date($a, $b) +{ + if($a->datep != $b->datep) + { + return $a->datep - $b->datep; + } + + // If both events have the same start time, longest first + return $b->datef - $a->datef; +} diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index ae411addb25..048308c9c20 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -87,7 +87,7 @@ $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); $page = GETPOST("page",'int'); -if ($page == -1 || $page == null) { $page = 0 ; } +if (empty($page) || $page == -1) { $page = 0 ; } $offset = $limit * $page ; if (! $sortorder) { diff --git a/htdocs/comm/action/rapport/index.php b/htdocs/comm/action/rapport/index.php index 7e4108b470b..703d35c8480 100644 --- a/htdocs/comm/action/rapport/index.php +++ b/htdocs/comm/action/rapport/index.php @@ -42,7 +42,7 @@ $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); $page = GETPOST("page",'int'); -if ($page == -1 || $page == null) { $page = 0 ; } +if (empty($page) || $page == -1) { $page = 0 ; } $offset = $limit * $page ; if (! $sortorder) $sortorder="DESC"; if (! $sortfield) $sortfield="a.datep"; diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index be60c4fa574..49a12f6c490 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -477,7 +477,7 @@ if ($object->id > 0) print ''; if ($action == 'editshipping') { - $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?socid='.$object->id,$object->shipping_method_id,'shipping_method_id'); + $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?socid='.$object->id,$object->shipping_method_id,'shipping_method_id', 1); } else { diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 97746ad9d82..048f938ea97 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -471,13 +471,13 @@ if (empty($reshook)) if ($result) { setEventMessages($langs->trans("MailSuccessfulySent",$mailfile->getValidAddress($object->email_from,2),$mailfile->getValidAddress($object->sendto,2)), null, 'mesgs'); + $action = ''; } else { setEventMessages($langs->trans("ResultKo").'
'.$mailfile->error.' '.$result, null, 'errors'); + $action = 'test'; } - - $action=''; } } @@ -870,7 +870,7 @@ else } $text.=$langs->trans('ConfirmSendingEmailing').'
'; $text.=$langs->trans('LimitSendingEmailing',$conf->global->MAILING_LIMIT_SENDBYWEB); - print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('SendMailing'),$text,'sendallconfirmed',$formquestion,'',1,300); + print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('SendMailing'), $text, 'sendallconfirmed', $formquestion, '', 1, 330, 600); } } diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index ba68e3324bb..8f186c0bc2e 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -320,7 +320,7 @@ if (empty($reshook)) $datep = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); $date_delivery = dol_mktime(12, 0, 0, GETPOST('date_livraisonmonth'), GETPOST('date_livraisonday'), GETPOST('date_livraisonyear')); - $duration = GETPOST('duree_validite'); + $duration = GETPOST('duree_validite', 'int'); if (empty($datep)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors'); @@ -1533,7 +1533,7 @@ if ($action == 'create') print ''; // Validaty duration - print '' . $langs->trans("ValidityDuration") . ' ' . $langs->trans("days") . ''; + print '' . $langs->trans("ValidityDuration") . ' ' . $langs->trans("days") . ''; // Terms of payment print '' . $langs->trans('PaymentConditionsShort') . ''; diff --git a/htdocs/comm/remx.php b/htdocs/comm/remx.php index a66e8e66500..eb1c14a4beb 100644 --- a/htdocs/comm/remx.php +++ b/htdocs/comm/remx.php @@ -1,7 +1,8 @@ - * Copyright (C) 2004-2012 Laurent Destailleur - * Copyright (C) 2008 Raphael Bertrand (Resultic) +/* Copyright (C) 2001-2004 Rodolphe Quiedeville + * Copyright (C) 2004-2012 Laurent Destailleur + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2019 Frédéric France * * 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 @@ -127,6 +128,8 @@ if ($action == 'confirm_split' && GETPOST("confirm") == 'yes') $db->begin(); $discount->fk_facture_source=0; // This is to delete only the require record (that we will recreate with two records) and not all family with same fk_facture_source + // This is to delete only the require record (that we will recreate with two records) and not all family with same fk_invoice_supplier_source + $discount->fk_invoice_supplier_source=0; $res=$discount->delete($user); $newid1=$newdiscount1->create($user); $newid2=$newdiscount2->create($user); diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index db497733863..81a0f3f9156 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -638,11 +638,12 @@ else print ''.$langs->trans("AccountancyJournal").''; print ''; - $accountingjournal = new AccountingJournal($db); - $accountingjournal->fetch($object->fk_accountancy_journal); - - print $accountingjournal->getNomUrl(0,1,1,'',1); + if ($object->fk_accountancy_journal > 0) { + $accountingjournal = new AccountingJournal($db); + $accountingjournal->fetch($object->fk_accountancy_journal); + print $accountingjournal->getNomUrl(0, 1, 1, '', 1); + } print ''; } diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index cc58f1e6dec..df6aa92ff54 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -1378,8 +1378,9 @@ if (empty($reshook)) { // Don't add lines with qty 0 when coming from a shipment including all order lines if($srcobject->element == 'shipping' && $conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS && $lines[$i]->qty == 0) continue; - // Don't add closed lines when coming from a contract - if($srcobject->element == 'contrat' && $lines[$i]->statut == 5) continue; + // Don't add closed lines when coming from a contract (Set constant to '0,5' to exclude also inactive lines) + if (! isset( $conf->global->CONTRACT_EXCLUDE_SERVICES_STATUS_FOR_INVOICE)) $conf->global->CONTRACT_EXCLUDE_SERVICES_STATUS_FOR_INVOICE = '5'; + if ($srcobject->element == 'contrat' && in_array($lines[$i]->statut, explode(',', $conf->global->CONTRACT_EXCLUDE_SERVICES_STATUS_FOR_INVOICE))) continue; $label=(! empty($lines[$i]->label)?$lines[$i]->label:''); $desc=(! empty($lines[$i]->desc)?$lines[$i]->desc:$lines[$i]->libelle); @@ -1537,14 +1538,16 @@ if (empty($reshook)) $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']); if (empty($datefacture)) { $error++; - $mesg = '
' . $langs->trans("ErrorFieldRequired", $langs->trans("Date")) . '
'; + $mesg = $langs->trans("ErrorFieldRequired", $langs->trans("Date")); + setEventMessages($mesg, null, 'errors'); } $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']); if (!($_POST['situations'] > 0)) { $error++; - $mesg = '
' . $langs->trans("ErrorFieldRequired", $langs->trans("InvoiceSituation")) . '
'; + $mesg = $langs->trans("ErrorFieldRequired", $langs->trans("InvoiceSituation")); + setEventMessages($mesg, null, 'errors'); } if (!$error) { @@ -2270,11 +2273,13 @@ if (empty($reshook)) if (!$object->fetch($id) > 0) dol_print_error($db); if (!is_null(GETPOST('all_progress')) && GETPOST('all_progress') != "") { + $all_progress = GETPOST('all_progress', 'int'); foreach ($object->lines as $line) { $percent = $line->get_prev_progress($object->id); - if (GETPOST('all_progress') < $percent) { - $mesg = '
' . $langs->trans("CantBeLessThanMinPercent") . '
'; + if (floatval($all_progress) < floatval($percent)) { + $mesg = $langs->trans("Line") . ' ' . $i . ' '. $line->ref .' : ' . $langs->trans("CantBeLessThanMinPercent"); + setEventMessages($mesg, null, 'warnings'); $result = -1; } else $object->update_percent($line, $_POST['all_progress']); diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index d303e6edf21..9f13313ffe1 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -875,7 +875,7 @@ class Facture extends CommonInvoice } elseif ($this->type == self::TYPE_SITUATION && !empty($conf->global->INVOICE_USE_SITUATION)) { - $this->fetchObjectLinked('', '', $facture->id, 'facture'); + $this->fetchObjectLinked('', '', $this->id, 'facture'); foreach ($this->linkedObjectsIds as $typeObject => $Tfk_object) { @@ -3031,6 +3031,12 @@ class Facture extends CommonInvoice { global $mysoc,$user; + // Progress should never be changed for discounts + if(($line->info_bits & 2) == 2) + { + return; + } + include_once(DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'); // Cap percentages to 100 @@ -3047,7 +3053,6 @@ class Facture extends CommonInvoice $line->multicurrency_total_ttc = $tabprice[18]; $line->update($user); $this->update_price(1); - $this->db->commit(); } /** @@ -4492,7 +4497,7 @@ class FactureLigne extends CommonInvoiceLine $sql.= " '".$this->db->escape($this->localtax1_type)."',"; $sql.= " '".$this->db->escape($this->localtax2_type)."',"; $sql.= ' '.(! empty($this->fk_product)?$this->fk_product:"null").','; - $sql.= " ".$this->product_type.","; + $sql.= " ".((int) $this->product_type).","; $sql.= " ".price2num($this->remise_percent).","; $sql.= " ".price2num($this->subprice).","; $sql.= ' '.(! empty($this->fk_remise_except)?$this->fk_remise_except:"null").','; diff --git a/htdocs/compta/facture/invoicetemplate_list.php b/htdocs/compta/facture/invoicetemplate_list.php index b7b985dd73c..c647ef00795 100644 --- a/htdocs/compta/facture/invoicetemplate_list.php +++ b/htdocs/compta/facture/invoicetemplate_list.php @@ -262,7 +262,7 @@ if ($search_month_date_when > 0) if ($search_year_date_when > 0 && empty($search_day_date_when)) $sql.= " AND f.date_when BETWEEN '".$db->idate(dol_get_first_day($search_year_date_when,$search_month_date_when,false))."' AND '".$db->idate(dol_get_last_day($search_year_date_when,$search_month_date_when,false))."'"; else if ($search_year_date_when > 0 && ! empty($search_day_date_when)) - $sql.= " AND f.date_date_when_reglement BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $search_month_date_when, $search_day_date_when, $search_year_date_when))."' AND '".$db->idate(dol_mktime(23, 59, 59, $search_month_date_when, $search_day_date_when, $search_year_date_when))."'"; + $sql.= " AND f.date_when BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $search_month_date_when, $search_day_date_when, $search_year_date_when))."' AND '".$db->idate(dol_mktime(23, 59, 59, $search_month_date_when, $search_day_date_when, $search_year_date_when))."'"; else $sql.= " AND date_format(f.date_when, '%m') = '".$db->escape($search_month_date_when)."'"; } diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index 805bdbdf79e..aa344c3df2e 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -530,7 +530,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie $sql = 'SELECT f.rowid as facid, f.facnumber, f.total_ttc, f.multicurrency_code, f.multicurrency_total_ttc, f.type,'; $sql.= ' f.datef as df, f.fk_soc as socid'; $sql.= ' FROM '.MAIN_DB_PREFIX.'facture as f'; - $sql.= ' WHERE f.entity IN ('.getEntity('facture', $conf->entity).')'; + $sql.= ' WHERE f.entity IN ('.getEntity('facture').')'; $sql.= ' AND (f.fk_soc = '.$facture->socid; // Can pay invoices of all child of parent company if(!empty($conf->global->FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS) && !empty($facture->thirdparty->parent)) { @@ -817,7 +817,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie */ if (! GETPOST('action','aZ09')) { - if ($page == -1) $page = 0 ; + if (empty($page) || $page == -1) $page = 0 ; $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; $offset = $limit * $page ; diff --git a/htdocs/compta/paiement_charge.php b/htdocs/compta/paiement_charge.php index fba8723d818..bec0e7fba47 100644 --- a/htdocs/compta/paiement_charge.php +++ b/htdocs/compta/paiement_charge.php @@ -71,7 +71,7 @@ if ($action == 'add_payment' || ($action == 'confirm_paiement' && $confirm=='yes $error++; $action = 'create'; } - if (! empty($conf->banque->enabled) && ! $_POST["accountid"] > 0) + if (! empty($conf->banque->enabled) && ! ($_POST["accountid"] > 0)) { setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentities("AccountToCredit")), null, 'errors'); $error++; diff --git a/htdocs/compta/prelevement/factures.php b/htdocs/compta/prelevement/factures.php index 2eabd64873d..defa9a345db 100644 --- a/htdocs/compta/prelevement/factures.php +++ b/htdocs/compta/prelevement/factures.php @@ -157,7 +157,7 @@ $sql.= " AND pl.fk_prelevement_bons = p.rowid"; $sql.= " AND f.fk_soc = s.rowid"; $sql.= " AND pf.fk_facture = f.rowid"; $sql.= " AND f.entity = ".$conf->entity; -if ($prev_id) $sql.= " AND p.rowid=".$prev_id; +if ($object->id) $sql.= " AND p.rowid=".$object->id; if ($socid) $sql.= " AND s.rowid = ".$socid; $sql.= $db->order($sortfield,$sortorder); diff --git a/htdocs/compta/sociales/class/chargesociales.class.php b/htdocs/compta/sociales/class/chargesociales.class.php index 62ac1dca49d..7e864521163 100644 --- a/htdocs/compta/sociales/class/chargesociales.class.php +++ b/htdocs/compta/sociales/class/chargesociales.class.php @@ -301,17 +301,17 @@ class ChargeSociales extends CommonObject $sql.= ", date_ech='".$this->db->idate($this->date_ech)."'"; $sql.= ", periode='".$this->db->idate($this->periode)."'"; $sql.= ", amount='".price2num($this->amount,'MT')."'"; - $sql.= ", fk_projet='".$this->db->escape($this->fk_project)."'"; + $sql.= ", fk_projet=".($this->fk_project>0?$this->db->escape($this->fk_project):"NULL"); $sql.= ", fk_user_modif=".$user->id; $sql.= " WHERE rowid=".$this->id; dol_syslog(get_class($this)."::update", LOG_DEBUG); $resql=$this->db->query($sql); - + if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } - + if (! $error) { if (! $notrigger) @@ -322,7 +322,7 @@ class ChargeSociales extends CommonObject // End call triggers } } - + // Commit or rollback if ($error) { @@ -339,8 +339,8 @@ class ChargeSociales extends CommonObject $this->db->commit(); return 1; } - - + + } /** diff --git a/htdocs/compta/sociales/document.php b/htdocs/compta/sociales/document.php index 490dbf3a1fe..36d51ff9f01 100644 --- a/htdocs/compta/sociales/document.php +++ b/htdocs/compta/sociales/document.php @@ -55,7 +55,7 @@ $result = restrictedArea($user, 'tax', $id, 'chargesociales','charges'); $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); $page = GETPOST("page",'int'); -if ($page == -1) { +if (empty($page) || $page == -1) { $page = 0; } $offset = $conf->liste_limit * $page; diff --git a/htdocs/compta/stats/byratecountry.php b/htdocs/compta/stats/byratecountry.php index 2c43db42d13..045f5e6429c 100644 --- a/htdocs/compta/stats/byratecountry.php +++ b/htdocs/compta/stats/byratecountry.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/expensereport/class/paymentexpensereport.class. // Load translation files required by the page $langs->loadLangs(array("other","compta","banks","bills","companies","product","trips","admin","accountancy")); -$modecompta = GETPOST('modecompta','alpha'); +$modecompta = (GETPOST('modecompta', 'alpha') ? GETPOST('modecompta', 'alpha') : $conf->global->ACCOUNTING_MODE); // Date range $year=GETPOST("year",'int'); diff --git a/htdocs/compta/tva/document.php b/htdocs/compta/tva/document.php index b83cad80bdd..1653cc28460 100644 --- a/htdocs/compta/tva/document.php +++ b/htdocs/compta/tva/document.php @@ -56,9 +56,10 @@ $result = restrictedArea($user, 'tax', $id, 'vat','charges'); $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); $page = GETPOST("page",'int'); -if ($page == -1) { +if (empty($page) || $page == -1) { $page = 0; } + $offset = $conf->liste_limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 52957d25343..e36327be432 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -78,6 +78,14 @@ $result = restrictedArea($user, 'contact', $id, 'socpeople&societe', '', '', 'ro // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('contactcard','globalcard')); +if ($id > 0) $object->fetch($id); + +if (! ($object->id > 0) && $action == 'view') +{ + $langs->load("errors"); + print($langs->trans('ErrorRecordNotFound')); + exit; +} /* * Actions diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php index b4255046ad4..c7b75a26ee1 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -3,7 +3,7 @@ * Copyright (C) 2004-2017 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2013 Cédric Salvador - * Copyright (C) 2014 Juanjo Menent + * Copyright (C) 2014-2019 Juanjo Menent * Copyright (C) 2015 Claudio Aschieri * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016-2018 Ferran Marcet @@ -45,14 +45,14 @@ $confirm=GETPOST('confirm','alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage= GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'contractlist'; // To manage different context of search -$search_name=GETPOST('search_name'); -$search_email=GETPOST('search_email'); +$search_name=GETPOST('search_name', 'alpha'); +$search_email=GETPOST('search_email', 'alpha'); $search_town=GETPOST('search_town','alpha'); $search_zip=GETPOST('search_zip','alpha'); $search_state=trim(GETPOST("search_state")); $search_country=GETPOST("search_country",'int'); $search_type_thirdparty=GETPOST("search_type_thirdparty",'int'); -$search_contract=GETPOST('search_contract'); +$search_contract=GETPOST('search_contract','alpha'); $search_ref_customer=GETPOST('search_ref_customer','alpha'); $search_ref_supplier=GETPOST('search_ref_supplier','alpha'); $sall=trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml')); diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 66c56e2a162..88ea8a08e28 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -4,6 +4,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2018 Ferran Marcet + * Copyright (C) 2019 Juanjo Menent * * 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 @@ -46,9 +47,9 @@ if (! $sortorder) $sortorder="ASC"; $mode = GETPOST("mode"); $filter=GETPOST("filter"); -$search_name=GETPOST("search_name"); -$search_contract=GETPOST("search_contract"); -$search_service=GETPOST("search_service"); +$search_name=GETPOST("search_name", 'alpha'); +$search_contract=GETPOST("search_contract", 'alpha'); +$search_service=GETPOST("search_service", 'alpha'); $search_status=GETPOST("search_status","alpha"); $statut=GETPOST('statut')?GETPOST('statut'):1; $search_product_category=GETPOST('search_product_category','int'); diff --git a/htdocs/core/actions_linkedfiles.inc.php b/htdocs/core/actions_linkedfiles.inc.php index 297f7821599..16ba1669337 100644 --- a/htdocs/core/actions_linkedfiles.inc.php +++ b/htdocs/core/actions_linkedfiles.inc.php @@ -118,8 +118,7 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes') { require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php'; $link = new Link($db); - $link->id = $linkid; - $link->fetch(); + $link->fetch($linkid); $res = $link->delete($user); $langs->load('link'); @@ -153,8 +152,7 @@ elseif ($action == 'confirm_updateline' && GETPOST('save','alpha') && GETPOST('l require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php'; $langs->load('link'); $link = new Link($db); - $link->id = GETPOST('linkid', 'int'); - $f = $link->fetch(); + $f = $link->fetch(GETPOST('linkid', 'int')); if ($f) { $link->url = GETPOST('link', 'alpha'); @@ -162,7 +160,7 @@ elseif ($action == 'confirm_updateline' && GETPOST('save','alpha') && GETPOST('l { $link->url = 'http://' . $link->url; } - $link->label = GETPOST('label', 'alpha'); + $link->label = GETPOST('label', 'alphanohtml'); $res = $link->update($user); if (!$res) { diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index f7208111d7a..2f5f03ee5a8 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -70,6 +70,8 @@ if (! $error && $massaction == 'confirm_presend') $listofobjectid=array(); $listofobjectthirdparties=array(); $listofobjectref=array(); + $attachedfilesThirdpartyObj=array(); + $oneemailperrecipient=(GETPOST('oneemailperrecipient')=='on'?1:0); if (! $error) { @@ -194,7 +196,6 @@ if (! $error && $massaction == 'confirm_presend') $sendtocc=implode(',',$tmparray); //var_dump($listofobjectref);exit; - $attachedfiles=array('paths'=>array(), 'names'=>array(), 'mimes'=>array()); $listofqualifiedobj=array(); $listofqualifiedref=array(); $thirdpartywithoutemail=array(); @@ -209,7 +210,7 @@ if (! $error && $massaction == 'confirm_presend') $resaction.='
'.$langs->trans('ErrorOnlyProposalNotDraftCanBeSentInMassAction',$objectobj->ref).'

'; continue; // Payment done or started or canceled } - if ($objectclass == 'Commande' && $objectoj->statut == Commande::STATUS_DRAFT) + if ($objectclass == 'Commande' && $objectobj->statut == Commande::STATUS_DRAFT) { $langs->load("errors"); $nbignored++; @@ -257,19 +258,30 @@ if (! $error && $massaction == 'confirm_presend') { // TODO Use future field $objectobj->fullpathdoc to know where is stored default file // TODO If not defined, use $objectobj->modelpdf (or defaut invoice config) to know what is template to use to regenerate doc. - $filename=dol_sanitizeFileName($objectobj->ref).'.pdf'; - $filedir=$uploaddir . '/' . dol_sanitizeFileName($objectobj->ref); + $filename = dol_sanitizeFileName($objectobj->ref).'.pdf'; + $subdir = ''; + // TODO Set subdir to be compatible with multi levels dir trees + // $subdir = get_exdir($objectobj->id, 2, 0, 0, $objectobj, $objectobj->element) + $filedir = $uploaddir . '/' . $subdir . dol_sanitizeFileName($objectobj->ref); $file = $filedir . '/' . $filename; + + // For supplier invoices, we use the file provided by supplier, not the one we generate + if ($objectobj->element == 'invoice_supplier') + { + $fileparams = dol_most_recent_file($uploaddir . '/' . get_exdir($objectobj->id,2,0,0,$objectobj,$objectobj->element).$objectobj->ref, preg_quote($objectobj->ref,'/').'([^\-])+'); + $file = $fileparams['fullname']; + } + $mime = dol_mimetype($file); if (dol_is_file($file)) { - // Create form object - $attachedfiles=array( - 'paths'=>array_merge($attachedfiles['paths'],array($file)), - 'names'=>array_merge($attachedfiles['names'],array($filename)), - 'mimes'=>array_merge($attachedfiles['mimes'],array($mime)) - ); + // Create form object + $attachedfilesThirdpartyObj[$thirdpartyid][$objectid]=array( + 'paths'=>array($file), + 'names'=>array($filename), + 'mimes'=>array($mime) + ); } else { @@ -335,7 +347,7 @@ if (! $error && $massaction == 'confirm_presend') if ($objectclass == 'FactureFournisseur') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO)); // $listofqualifiedobj is array with key = object id and value is instance of qualified objects, for the current thirdparty (but thirdparty property is not loaded yet) - $oneemailperrecipient=(GETPOST('oneemailperrecipient')=='on'?1:0); + $looparray=array(); if (! $oneemailperrecipient) { @@ -352,8 +364,9 @@ if (! $error && $massaction == 'confirm_presend') $looparray[0]=$objectforloop; } //var_dump($looparray);exit; - - foreach ($looparray as $objecttmp) // $objecttmp is a real object or an empty object if we choose to send one email per thirdparty instead of one per record + dol_syslog("We have set an array of ".count($looparray)." emails to send. oneemailperrecipient=".$oneemailperrecipient); + //var_dump($oneemailperrecipient); var_dump($listofqualifiedobj); var_dump($listofqualifiedref); + foreach ($looparray as $objectid => $objecttmp) // $objecttmp is a real object or an empty object if we choose to send one email per thirdparty instead of one per object { // Make substitution in email content $substitutionarray=getCommonSubstitutionArray($langs, 0, null, $objecttmp); @@ -373,18 +386,44 @@ if (! $error && $massaction == 'confirm_presend') complete_substitutions_array($substitutionarray, $langs, $objecttmp, $parameters); - $subject=make_substitutions($subject, $substitutionarray); - $message=make_substitutions($message, $substitutionarray); + $subjectreplaced=make_substitutions($subject, $substitutionarray); + $messagereplaced=make_substitutions($message, $substitutionarray); + + + $attachedfiles=array('paths'=>array(), 'names'=>array(), 'mimes'=>array()); + if($oneemailperrecipient) + { + // if "one email per recipient" isn't check we must collate $attachedfiles by thirdparty + if(is_array($attachedfilesThirdpartyObj[$thirdparty->id]) && count($attachedfilesThirdpartyObj[$thirdparty->id])) + { + foreach ($attachedfilesThirdpartyObj[$thirdparty->id] as $keyObjId => $objAttachedFiles){ + // Create form object + $attachedfiles=array( + 'paths'=>array_merge($attachedfiles['paths'], $objAttachedFiles['paths']), + 'names'=>array_merge($attachedfiles['names'], $objAttachedFiles['names']), + 'mimes'=>array_merge($attachedfiles['mimes'], $objAttachedFiles['mimes']) + ); + } + } + } + elseif(!empty($attachedfilesThirdpartyObj[$thirdparty->id][$objectid])){ + // Create form object + // if "one email per recipient" isn't check we must separate $attachedfiles by object + $attachedfiles=$attachedfilesThirdpartyObj[$thirdparty->id][$objectid]; + } $filepath = $attachedfiles['paths']; $filename = $attachedfiles['names']; $mimetype = $attachedfiles['mimes']; + + + //var_dump($filepath); // Send mail (substitutionarray must be done just before this) - require_once(DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'); - $mailfile = new CMailFile($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,$sendtobcc,$deliveryreceipt,-1); + require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; + $mailfile = new CMailFile($subjectreplaced, $sendto, $from, $messagereplaced, $filepath, $mimetype, $filename, $sendtocc, $sendtobcc, $deliveryreceipt, -1); if ($mailfile->error) { $resaction.='
'.$mailfile->error.'
'; @@ -399,8 +438,12 @@ if (! $error && $massaction == 'confirm_presend') $error=0; // Insert logs into agenda - foreach($listofqualifiedobj as $objid => $objectobj) + foreach($listofqualifiedobj as $objid2 => $objectobj2) { + if ((! $oneemailperrecipient) && $objid2 != $objectid) continue; // We discard this pass to avoid duplicate with other pass in looparray at higher level + + dol_syslog("Try to insert email event into agenda for objid=".$objid2." => objectobj=".get_class($objectobj2)); + /*if ($objectclass == 'Propale') $actiontypecode='AC_PROP'; if ($objectclass == 'Commande') $actiontypecode='AC_COM'; if ($objectclass == 'Facture') $actiontypecode='AC_FAC'; @@ -412,18 +455,18 @@ if (! $error && $massaction == 'confirm_presend') if ($message) { if ($sendtocc) $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc') . ": " . $sendtocc); - $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic') . ": " . $subject); + $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic') . ": " . $subjectreplaced); $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":"); - $actionmsg = dol_concatdesc($actionmsg, $message); + $actionmsg = dol_concatdesc($actionmsg, $messagereplaced); } $actionmsg2=''; // Initialisation donnees - $objectobj->sendtoid = 0; - $objectobj->actionmsg = $actionmsg; // Long text - $objectobj->actionmsg2 = $actionmsg2; // Short text - $objectobj->fk_element = $objid; - $objectobj->elementtype = $objectobj->element; + $objectobj2->sendtoid = 0; + $objectobj2->actionmsg = $actionmsg; // Long text + $objectobj2->actionmsg2 = $actionmsg2; // Short text + $objectobj2->fk_element = $objid2; + $objectobj2->elementtype = $objectobj2->element; $triggername = strtoupper(get_class($objectobj)) .'_SENTBYMAIL'; if ($triggername == 'SOCIETE_SENTBYMAIL') $triggername = 'COMPANY_SENTBYEMAIL'; @@ -438,9 +481,9 @@ if (! $error && $massaction == 'confirm_presend') if (! empty($triggername)) { // Appel des triggers - include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php"); + include_once DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php"; $interface=new Interfaces($db); - $result=$interface->run_triggers($triggername, $objectobj, $user, $langs, $conf); + $result=$interface->run_triggers($triggername, $objectobj2, $user, $langs, $conf); if ($result < 0) { $error++; $errors=$interface->errors; } // Fin appel triggers @@ -451,7 +494,7 @@ if (! $error && $massaction == 'confirm_presend') } } - $nbsent++; + $nbsent++; // Nb of record sent } } else @@ -525,7 +568,7 @@ if ($massaction == 'confirm_createbills') $objecttmp->cond_reglement_id = $cmd->cond_reglement_id; $objecttmp->mode_reglement_id = $cmd->mode_reglement_id; $objecttmp->fk_project = $cmd->fk_project; - + $objecttmp->multicurrency_code = $cmd->multicurrency_code; $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']); if (empty($datefacture)) { @@ -725,7 +768,7 @@ if ($massaction == 'confirm_createbills') if (! $error) { $db->commit(); - setEventMessage($langs->trans('BillCreated', $nb_bills_created)); + setEventMessages($langs->trans('BillCreated', $nb_bills_created), null, 'mesgs'); // Make a redirect to avoid to bill twice if we make a refresh or back $param=''; diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index da31b9dee96..a2d7eb83a10 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -43,7 +43,7 @@ if (GETPOST('addfile','alpha')) $vardir=$conf->user->dir_output."/".$user->id; $upload_dir_tmp = $vardir.'/temp'; // TODO Add $keytoavoidconflict in upload_dir path - dol_add_file_process($upload_dir_tmp, 0, 0, 'addedfile', '', null, $trackid, 0); + dol_add_file_process($upload_dir_tmp, 1, 0, 'addedfile', '', null, $trackid, 0); $action='presend'; } @@ -468,7 +468,7 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO $mesg='
'; if ($mailfile->error) { - $mesg.=$langs->trans('ErrorFailedToSendMail',$from,$sendto); + $mesg.=$langs->transnoentities('ErrorFailedToSendMail',dol_escape_htmltag($from),dol_escape_htmltag($sendto)); $mesg.='
'.$mailfile->error; } else diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index facc8104740..4ac221d8111 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -517,6 +517,31 @@ class CMailFile return true; } + $sendingmode = $this->sendmode; + if ($this->context == 'emailing' && ! empty($conf->global->MAILING_NO_USING_PHPMAIL) && $sendingmode == 'mail') + { + // List of sending methods + $listofmethods=array(); + $listofmethods['mail']='PHP mail function'; + //$listofmethods['simplemail']='Simplemail class'; + $listofmethods['smtps']='SMTP/SMTPS socket library'; + + // EMailing feature may be a spam problem, so when you host several users/instance, having this option may force each user to use their own SMTP agent. + // You ensure that every user is using its own SMTP server when using the mass emailing module. + $linktoadminemailbefore=''; + $linktoadminemailend=''; + $this->error = $langs->trans("MailSendSetupIs", $listofmethods[$sendingmode]); + $this->errors[] = $langs->trans("MailSendSetupIs", $listofmethods[$sendingmode]); + $this->error .= '
'.$langs->trans("MailSendSetupIs2", $linktoadminemailbefore, $linktoadminemailend, $langs->transnoentitiesnoconv("MAIN_MAIL_SENDMODE"), $listofmethods['smtps']); + $this->errors[] = $langs->trans("MailSendSetupIs2", $linktoadminemailbefore, $linktoadminemailend, $langs->transnoentitiesnoconv("MAIN_MAIL_SENDMODE"), $listofmethods['smtps']); + if (! empty($conf->global->MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS)) + { + $this->error .= '
'.$langs->trans("MailSendSetupIs3", $conf->global->MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS); + $this->errors[] = $langs->trans("MailSendSetupIs3", $conf->global->MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS); + } + return false; + } + // Check number of recipient is lower or equal than MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL if (empty($conf->global->MAIL_MAX_NB_OF_RECIPIENTS_TO_IN_SAME_EMAIL)) $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_TO_IN_SAME_EMAIL=10; $tmparray1 = explode(',', $this->addr_to); diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 3aa8eb4e1ab..35ec6ad283e 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -195,6 +195,29 @@ abstract class CommonInvoice extends CommonObject } } + /** + * Return amount (with tax) of all converted amount for this credit note + * + * @param int $multicurrency Return multicurrency_amount instead of amount + * @return int <0 if KO, Sum of credit notes and deposits amount otherwise + */ + function getSumFromThisCreditNotesNotUsed($multicurrency=0) + { + require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php'; + + $discountstatic=new DiscountAbsolute($this->db); + $result=$discountstatic->getSumFromThisCreditNotesNotUsed($this, $multicurrency); + if ($result >= 0) + { + return $result; + } + else + { + $this->error=$discountstatic->error; + return -1; + } + } + /** * Renvoie tableau des ids de facture avoir issus de la facture * diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index f0fe7bf437c..32dd6fbd361 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -12,7 +12,7 @@ * Copyright (C) 2015 Alexandre Spangaro * Copyright (C) 2016 Bahfir abbes * Copyright (C) 2017 ATM Consulting - * Copyright (C) 2017 Nicolas ZABOURI + * Copyright (C) 2017-2019 Nicolas ZABOURI * Copyright (C) 2017 Rui Strecht * Copyright (C) 2018 Frederic France * @@ -2615,7 +2615,7 @@ abstract class CommonObject $MODULE = ""; if ($this->element == 'propal') $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_PROPOSAL"; - elseif ($this->element == 'order') + elseif ($this->element == 'commande' || $this->element == 'order') $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_ORDER"; elseif ($this->element == 'facture') $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_INVOICE"; @@ -3715,10 +3715,11 @@ abstract class CommonObject // Output template part (modules that overwrite templates must declare this into descriptor) // Use global variables + $dateSelector + $seller and $buyer - $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl')); + $dirtpls=array_merge($conf->modules_parts['tpl'], array('/core/tpl')); foreach($dirtpls as $reldir) { $tpl = dol_buildpath($reldir.'/objectline_create.tpl.php'); + if (empty($conf->file->strict_mode)) { $res=@include $tpl; } else { @@ -3967,10 +3968,11 @@ abstract class CommonObject // Output template part (modules that overwrite templates must declare this into descriptor) // Use global variables + $dateSelector + $seller and $buyer - $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl')); + $dirtpls=array_merge($conf->modules_parts['tpl'], array('/core/tpl')); foreach($dirtpls as $reldir) { $tpl = dol_buildpath($reldir.'/objectline_view.tpl.php'); + if (empty($conf->file->strict_mode)) { $res=@include $tpl; } else { @@ -3990,10 +3992,11 @@ abstract class CommonObject // Output template part (modules that overwrite templates must declare this into descriptor) // Use global variables + $dateSelector + $seller and $buyer - $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl')); + $dirtpls=array_merge($conf->modules_parts['tpl'], array('/core/tpl')); foreach($dirtpls as $reldir) { $tpl = dol_buildpath($reldir.'/objectline_edit.tpl.php'); + if (empty($conf->file->strict_mode)) { $res=@include $tpl; } else { @@ -4186,10 +4189,11 @@ abstract class CommonObject // Output template part (modules that overwrite templates must declare this into descriptor) // Use global variables + $dateSelector + $seller and $buyer - $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl')); + $dirtpls=array_merge($conf->modules_parts['tpl'], array('/core/tpl')); foreach($dirtpls as $reldir) { $tpl = dol_buildpath($reldir.'/originproductline.tpl.php'); + if (empty($conf->file->strict_mode)) { $res=@include $tpl; } else { diff --git a/htdocs/core/class/discount.class.php b/htdocs/core/class/discount.class.php index cfe7ac24dea..d464e986c32 100644 --- a/htdocs/core/class/discount.class.php +++ b/htdocs/core/class/discount.class.php @@ -91,7 +91,7 @@ class DiscountAbsolute $sql.= " FROM ".MAIN_DB_PREFIX."societe_remise_except as sr"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON sr.fk_facture_source = f.rowid"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."facture as fsup ON sr.fk_invoice_supplier_source = fsup.rowid"; - $sql.= " WHERE sr.entity = " . $conf->entity; + $sql.= " WHERE sr.entity IN (".getEntity('invoice').")"; if ($rowid) $sql.= " AND sr.rowid=".$rowid; if ($fk_facture_source) $sql.= " AND sr.fk_facture_source=".$fk_facture_source; if ($fk_invoice_supplier_source) $sql.= " AND sr.fk_invoice_supplier_source=".$fk_invoice_supplier_source; @@ -568,6 +568,49 @@ class DiscountAbsolute return -1; } } + /** + * Return amount (with tax) of all converted amount for this credit note + * + * @param CommonInvoice $invoice Object invoice + * @param int $multicurrency Return multicurrency_amount instead of amount + * @return int <0 if KO, Sum of credit notes and deposits amount otherwise + */ + function getSumFromThisCreditNotesNotUsed($invoice, $multicurrency=0) + { + dol_syslog(get_class($this)."::getSumCreditNotesUsed", LOG_DEBUG); + + if ($invoice->element == 'facture' || $invoice->element == 'invoice') + { + $sql = 'SELECT sum(rc.amount_ttc) as amount, sum(rc.multicurrency_amount_ttc) as multicurrency_amount'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'societe_remise_except as rc'; + $sql.= ' WHERE rc.fk_facture IS NULL AND rc.fk_facture_source = '.$invoice->id; + } + else if ($invoice->element == 'invoice_supplier') + { + $sql = 'SELECT sum(rc.amount_ttc) as amount, sum(rc.multicurrency_amount_ttc) as multicurrency_amount'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'societe_remise_except as rc'; + $sql.= ' WHERE rc.fk_invoice_supplier IS NULL AND rc.fk_invoice_supplier_source = '.$invoice->id; + } + else + { + $this->error=get_class($this)."::getSumCreditNotesUsed was called with a bad object as a first parameter"; + dol_print_error($this->error); + return -1; + } + + $resql=$this->db->query($sql); + if ($resql) + { + $obj = $this->db->fetch_object($resql); + if ($multicurrency) return $obj->multicurrency_amount; + else return $obj->amount; + } + else + { + $this->error = $this->db->lasterror(); + return -1; + } + } /** * Return clickable ref of object (with picto or not) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index f8ae333935e..5b171d70bfb 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1194,13 +1194,14 @@ class ExtraFields if ($value == $obj->rowid) { - foreach ($fields_label as $field_toshow) - { - $translabel=$langs->trans($obj->$field_toshow); - if ($translabel!=$obj->$field_toshow) { - $labeltoshow=dol_trunc($translabel,18).' '; - }else { - $labeltoshow=dol_trunc($obj->$field_toshow,18).' '; + if (! $notrans) { + foreach ($fields_label as $field_toshow) { + $translabel = $langs->trans($obj->$field_toshow); + if ($translabel != $obj->$field_toshow) { + $labeltoshow = dol_trunc($translabel, 18) . ' '; + } else { + $labeltoshow = dol_trunc($obj->$field_toshow, 18) . ' '; + } } } $out.=''; @@ -1829,7 +1830,7 @@ class ExtraFields function setOptionalsFromPost($extralabels, &$object, $onlykey='') { global $_POST, $langs; - $nofillrequired='';// For error when required field left blank + $nofillrequired=0;// For error when required field left blank $error_field_required = array(); if (is_array($this->attributes[$object->table_element]['label'])) $extralabels=$this->attributes[$object->table_element]['label']; @@ -1860,8 +1861,9 @@ class ExtraFields if ($this->attributes[$object->table_element]['required'][$key]) // Value is required { // Check if empty without using GETPOST, value can be alpha, int, array, etc... - if ((! is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $_POST["options_".$key] != '0') - || (is_array($_POST["options_".$key]) && empty($_POST["options_".$key]))) + if ((! is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] != 'select' && $_POST["options_".$key] != '0') + || (! is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'select') + || (is_array($_POST["options_".$key]) && empty($_POST["options_".$key]))) { //print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key]; $nofillrequired++; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 8f0af0a5004..ac92e93751c 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1785,6 +1785,15 @@ class Form $price_level = (! empty($price_level) ? $price_level : 0); + if(strval($filtertype) === '' && (!empty($conf->product->enabled) || !empty($conf->service->enabled))){ + if(!empty($conf->product->enabled) && empty($conf->service->enabled)){ + $filtertype = '0'; + } + elseif(empty($conf->product->enabled) && !empty($conf->service->enabled)){ + $filtertype = '1'; + } + } + if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) { $placeholder=''; diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index c7288aa63d3..a198fba4f98 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -761,7 +761,7 @@ class FormFile $out.= 'trans("File").': '.$file["name"]); $out.= dol_trunc($file["name"], 150); $out.= ''."\n"; @@ -1757,7 +1757,7 @@ class FormFile print $langs->trans('Link') . ': '; print ''; print ''; - print $langs->trans('Label') . ': '; + print $langs->trans('Label') . ': '; print ''; print '' . dol_print_date(dol_now(), "dayhour", "tzuser") . ''; print ''; @@ -1771,7 +1771,7 @@ class FormFile print ''; print img_picto('', 'object_globe').' '; print ''; - print $link->label; + print dol_escape_htmltag($link->label); print ''; print ''."\n"; print ''; diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index e8693af943a..db758f6c614 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -359,6 +359,7 @@ class FormMail extends Form if ($this->param['models'] != 'none') { $result = $this->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs); + if ($result < 0) { setEventMessages($this->error, $this->errors, 'errors'); @@ -991,7 +992,6 @@ class FormMail extends Form $defaultmessage=preg_replace("/^(
)+/","",$defaultmessage); $defaultmessage=preg_replace("/^\n+/","",$defaultmessage); } - $out.= ''; $out.= ''; $out.=$form->textwithpicto($langs->trans('MailText'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfrombody'); diff --git a/htdocs/core/class/html.formmargin.class.php b/htdocs/core/class/html.formmargin.class.php index da8acce83d4..72352bc5bdb 100644 --- a/htdocs/core/class/html.formmargin.class.php +++ b/htdocs/core/class/html.formmargin.class.php @@ -91,7 +91,7 @@ class FormMargin $line->pa_ht = $line->subprice * (1 - ($line->remise_percent / 100)); } - $pv = $line->qty * $line->subprice * (1 - $line->remise_percent / 100); + $pv = $line->total_ht; $pa_ht = ($pv < 0 ? - $line->pa_ht : $line->pa_ht); // We choosed to have line->pa_ht always positive in database, so we guess the correct sign $pa = $line->qty * $pa_ht; diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index 69fe03ecaa1..3d19bfb5b0d 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -374,9 +374,9 @@ class FormOther * @param string $morecss More CSS * @return string Html combo list code */ - function select_salesrepresentatives($selected,$htmlname,$user,$showstatus=0,$showempty=1,$morecss='') + function select_salesrepresentatives($selected, $htmlname, $user, $showstatus=0, $showempty=1, $morecss='') { - global $conf,$langs; + global $conf, $langs; $langs->load('users'); $out = ''; @@ -398,17 +398,44 @@ class FormOther // Get list of users allowed to be viewed $sql_usr = "SELECT u.rowid, u.lastname, u.firstname, u.statut, u.login"; $sql_usr.= " FROM ".MAIN_DB_PREFIX."user as u"; - $sql_usr.= " WHERE u.entity IN (0,".$conf->entity.")"; + + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + if (! empty($user->admin) && empty($user->entity) && $conf->entity == 1) { + $sql_usr.= " WHERE u.entity IS NOT NULL"; // Show all users + } else { + $sql_usr.= " WHERE EXISTS (SELECT ug.fk_user FROM ".MAIN_DB_PREFIX."usergroup_user as ug WHERE u.rowid = ug.fk_user AND ug.entity IN (".getEntity('user')."))"; + $sql_usr.= " OR u.entity = 0"; // Show always superadmin + } + } + else + { + $sql_usr.= " WHERE u.entity IN (".getEntity('user').")"; + } + if (empty($user->rights->user->user->lire)) $sql_usr.=" AND u.rowid = ".$user->id; - if (! empty($user->societe_id)) $sql_usr.=" AND u.fk_soc = ".$user->societe_id; + if (! empty($user->socid)) $sql_usr.=" AND u.fk_soc = ".$user->socid; // Add existing sales representatives of thirdparty of external user - if (empty($user->rights->user->user->lire) && $user->societe_id) + if (empty($user->rights->user->user->lire) && $user->socid) { $sql_usr.=" UNION "; $sql_usr.= "SELECT u2.rowid, u2.lastname, u2.firstname, u2.statut, u2.login"; $sql_usr.= " FROM ".MAIN_DB_PREFIX."user as u2, ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql_usr.= " WHERE u2.entity IN (0,".$conf->entity.")"; - $sql_usr.= " AND u2.rowid = sc.fk_user AND sc.fk_soc=".$user->societe_id; + + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + if (! empty($user->admin) && empty($user->entity) && $conf->entity == 1) { + $sql_usr.= " WHERE u2.entity IS NOT NULL"; // Show all users + } else { + $sql_usr.= " WHERE EXISTS (SELECT ug2.fk_user FROM ".MAIN_DB_PREFIX."usergroup_user as ug2 WHERE u2.rowid = ug2.fk_user AND ug2.entity IN (".getEntity('user')."))"; + } + } + else + { + $sql_usr.= " WHERE u2.entity IN (".getEntity('user').")"; + } + + $sql_usr.= " AND u2.rowid = sc.fk_user AND sc.fk_soc=".$user->socid; } $sql_usr.= " ORDER BY statut DESC, lastname ASC"; // Do not use 'ORDER BY u.statut' here, not compatible with the UNION. //print $sql_usr;exit; diff --git a/htdocs/core/class/interfaces.class.php b/htdocs/core/class/interfaces.class.php index 655969d73f6..2960d4cf327 100644 --- a/htdocs/core/class/interfaces.class.php +++ b/htdocs/core/class/interfaces.class.php @@ -151,6 +151,8 @@ class Interfaces $i++; } } + + closedir($handle); } } diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index ae22728f06d..f8bb58a05fb 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -329,6 +329,7 @@ class Notify $sql.= " ".MAIN_DB_PREFIX."societe as s"; $sql.= " WHERE n.fk_contact = c.rowid AND a.rowid = n.fk_action"; $sql.= " AND n.fk_soc = s.rowid"; + $sql.= " AND c.statut = 1"; if (is_numeric($notifcode)) $sql.= " AND n.fk_action = ".$notifcode; // Old usage else $sql.= " AND a.code = '".$notifcode."'"; // New usage $sql .= " AND s.rowid = ".$object->socid; @@ -342,6 +343,7 @@ class Notify $sql.= " ".MAIN_DB_PREFIX."c_action_trigger as a,"; $sql.= " ".MAIN_DB_PREFIX."notify_def as n"; $sql.= " WHERE n.fk_user = c.rowid AND a.rowid = n.fk_action"; + $sql.= " AND c.statut = 1"; if (is_numeric($notifcode)) $sql.= " AND n.fk_action = ".$notifcode; // Old usage else $sql.= " AND a.code = '".$notifcode."'"; // New usage diff --git a/htdocs/core/extrafieldsinexport.inc.php b/htdocs/core/extrafieldsinexport.inc.php index 13b2d1ae520..78dbba9934e 100644 --- a/htdocs/core/extrafieldsinexport.inc.php +++ b/htdocs/core/extrafieldsinexport.inc.php @@ -34,6 +34,15 @@ if ($resql) // This can fail when class is used on old database (during migra case 'boolean': $typeFilter="Boolean"; break; + case 'select': + if (! empty($conf->global->EXPORT_LABEL_FOR_SELECT)) + { + $tmpparam=unserialize($obj->param); // $tmpparam may be array with 'options' = array(key1=>val1, key2=>val2 ...) + if ($tmpparam['options'] && is_array($tmpparam['options'])) { + $typeFilter="Select:".$obj->param; + } + } + break; case 'sellist': $tmp=''; $tmpparam=unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null diff --git a/htdocs/core/js/timesheet.js b/htdocs/core/js/timesheet.js index aaec6971e2f..4eae63154d4 100644 --- a/htdocs/core/js/timesheet.js +++ b/htdocs/core/js/timesheet.js @@ -91,17 +91,11 @@ function parseTime(timeStr, dt) dt = new Date(); } - var time = timeStr.match(/(\d+)(?::(\d\d))?\s*(p?)/i); + var time = timeStr.match(/(\d+)(?::(\d\d))?/i); if (!time) { return -1; } var hours = parseInt(time[1], 10); - if (hours == 12 && !time[3]) { - hours = 0; - } - else { - hours += (hours < 12 && time[3]) ? 12 : 0; - } dt.setHours(hours); dt.setMinutes(parseInt(time[2], 10) || 0); diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index c00d4469b05..68ad744dee2 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -818,7 +818,7 @@ function show_projects($conf, $langs, $db, $object, $backtopage='', $nocreatelin } else { - print ''.$langs->trans("None").''; + print ''.$langs->trans("None").''; } $db->free($result); } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 210626f461c..e003b74f3e6 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1557,6 +1557,11 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio $info = pathinfo($destfile); $destfile = dol_sanitizeFileName($info['filename'].'.'.strtolower($info['extension'])); + // We apply dol_string_nohtmltag also to clean file names (this remove duplicate spaces) because + // this function is also applied when we make try to download file (by the GETPOST(filename, 'alphanohtml') call). + $destfile = dol_string_nohtmltag($destfile); + $destfull = dol_string_nohtmltag($destfull); + $resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destfull, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles); if (is_numeric($resupload) && $resupload > 0) // $resupload can be 'ErrorFileAlreadyExists' @@ -1838,10 +1843,15 @@ function dol_convert_file($fileinput, $ext='png', $fileoutput='') if (empty($fileoutput)) $fileoutput=$fileinput.".".$ext; $count = $image->getNumberImages(); - if (! dol_is_file($fileoutput) || is_writeable($fileoutput)) { - $ret = $image->writeImages($fileoutput, true); + try { + $ret = $image->writeImages($fileoutput, true); + } + catch(Exception $e) + { + dol_syslog($e->getMessage(), LOG_WARNING); + } } else { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 6da863e54ef..8d301275b5e 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1436,6 +1436,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r { if (empty($conf->global->MAIN_DISABLE_PDF_THUMBS)) // If you experienc trouble with pdf thumb generation and imagick, you can disable here. { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $ret = dol_convert_file($file, 'png', $fileimage); if ($ret < 0) $error++; } @@ -6233,6 +6234,8 @@ function make_substitutions($text, $substitutionarray, $outputlangs=null) // Make substitition for array $substitutionarray foreach ($substitutionarray as $key => $value) { + if (! isset($value)) continue; // If value is null, it same than not having substitution key at all into array, we do not replace. + if ($key == '__SIGNATURE__' && (! empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN))) $value=''; // Protection if ($key == '__USER_SIGNATURE__' && (! empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN))) $value=''; // Protection diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index 41ff14b011a..5d0f25892c8 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -716,8 +716,8 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m global $conf,$user; if (! is_object($objsoc)) $valueforccc=$objsoc; - else if ($table == "commande_fournisseur" || $table == "facture_fourn" ) $valueforccc=$objsoc->code_fournisseur; - else $valueforccc=$objsoc->code_client; + else if ($table == "commande_fournisseur" || $table == "facture_fourn" ) $valueforccc=dol_string_unaccent($objsoc->code_fournisseur); + else $valueforccc=dol_string_unaccent($objsoc->code_client); $sharetable = $table; if ($table == 'facture' || $table == 'invoice') $sharetable = 'invoicenumber'; // for getEntity function @@ -965,6 +965,7 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m // Define $maskLike $maskLike = dol_string_nospecial($mask); $maskLike = str_replace("%","_",$maskLike); + // Replace protected special codes with matching number of _ as wild card caracter $maskLike = preg_replace('/\{yyyy\}/i','____',$maskLike); $maskLike = preg_replace('/\{yy\}/i','__',$maskLike); @@ -1140,7 +1141,7 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m // Now we replace the refclient if ($maskrefclient) { - //print "maskrefclient=".$maskrefclient." maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode."\n
"; + //print "maskrefclient=".$maskrefclient." maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode." maskrefclient_clientcode=".$maskrefclient_clientcode."\n
";exit; $maskrefclient_maskbefore='{'.$maskrefclient.'}'; $maskrefclient_maskafter=$maskrefclient_clientcode.str_pad($maskrefclient_counter,dol_strlen($maskrefclient_maskcounter),"0",STR_PAD_LEFT); $numFinal = str_replace($maskrefclient_maskbefore,$maskrefclient_maskafter,$numFinal); @@ -1250,6 +1251,10 @@ function check_value($mask,$value) if (! empty($reg[3]) && preg_match('/^@/',$reg[3])) $maskraz=preg_replace('/^@/','',$reg[3]); if ($maskraz >= 0) { + if ($maskraz == 99) { + $maskraz = date('m'); + $resetEveryMonth = true; + } if ($maskraz > 12) return 'ErrorBadMaskBadRazMonth'; // Define reg diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index 81989d0aaa1..efe0dbb52bd 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -144,8 +144,8 @@ function user_prepare_head($object) if ((! empty($conf->salaries->enabled) && ! empty($user->rights->salaries->read)) || (! empty($conf->hrm->enabled) && ! empty($user->rights->hrm->employee->read)) - || (! empty($conf->expensereport->enabled) && ! empty($user->rights->expensereport->lire) && $user->id == $object->id) - || (! empty($conf->holiday->enabled) && ! empty($user->rights->holiday->read) && $user->id == $object->id ) + || (! empty($conf->expensereport->enabled) && ! empty($user->rights->expensereport->lire) && ($user->id == $object->id || $user->rights->expensereport->readall)) + || (! empty($conf->holiday->enabled) && ! empty($user->rights->holiday->read) && ($user->id == $object->id || $user->rights->holiday->read_all)) ) { // Bank diff --git a/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php b/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php index 73fc323c198..f8ba1d3e6eb 100644 --- a/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php +++ b/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php @@ -396,7 +396,11 @@ class doc_generic_shipment_odt extends ModelePdfExpedition } } // Make substitutions into odt of thirdparty - $tmparray=$this->get_substitutionarray_thirdparty($socobject,$outputlangs); + if ($socobject->element == 'contact') { + $tmparray = $this->get_substitutionarray_contact($socobject, $outputlangs); + } else { + $tmparray = $this->get_substitutionarray_thirdparty($socobject, $outputlangs); + } foreach($tmparray as $key=>$value) { try { diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 91d20d4830b..d6fbed744ee 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1211,24 +1211,6 @@ class pdf_crabe extends ModelePDFFactures //} // VAT - // Situations totals migth be wrong on huge amounts - if ($object->situation_cycle_ref && $object->situation_counter > 1) { - - $sum_pdf_tva = 0; - foreach($this->tva as $tvakey => $tvaval){ - $sum_pdf_tva+=$tvaval; // sum VAT amounts to compare to object - } - - if($sum_pdf_tva!=$object->total_tva) { // apply coef to recover the VAT object amount (the good one) - $coef_fix_tva = $object->total_tva / $sum_pdf_tva; - - foreach($this->tva as $tvakey => $tvaval) { - $this->tva[$tvakey]=$tvaval * $coef_fix_tva; - } - } - - } - foreach($this->tva as $tvakey => $tvaval) { if ($tvakey != 0) // On affiche pas taux 0 diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index a6473eaeb8e..e0ec89379af 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -493,15 +493,24 @@ class ImportCsv extends ModeleImports if (! empty($objimport->array_import_regex[0][$val]) && ($newval != '')) { // If test is "Must exist in a field@table" - if (preg_match('/^(.*)@(.*)$/',$objimport->array_import_regex[0][$val],$reg)) + if (preg_match('/^(.+)@([^:]+)(:.+)?$/',$objimport->array_import_regex[0][$val],$reg)) { $field=$reg[1]; $table=$reg[2]; + $filter=!empty($reg[3])?substr($reg[3], 1):''; + + $cachekey = $field.'@'.$table; + if(! empty($filter)) $cachekey.= ':'.$filter; // Load content of field@table into cache array - if (! is_array($this->cachefieldtable[$field.'@'.$table])) // If content of field@table not already loaded into cache + if (! is_array($this->cachefieldtable[$cachekey])) // If content of field@table not already loaded into cache { $sql="SELECT ".$field." as aliasfield FROM ".$table; + if(! empty($filter)) + { + $sql.= ' WHERE ' . $filter; + } + $resql=$this->db->query($sql); if ($resql) { @@ -510,7 +519,7 @@ class ImportCsv extends ModeleImports while ($i < $num) { $obj=$this->db->fetch_object($resql); - if ($obj) $this->cachefieldtable[$field.'@'.$table][]=$obj->aliasfield; + if ($obj) $this->cachefieldtable[$cachekey][]=$obj->aliasfield; $i++; } } @@ -521,9 +530,11 @@ class ImportCsv extends ModeleImports } // Now we check cache is not empty (should not) and key is into cache - if (! is_array($this->cachefieldtable[$field.'@'.$table]) || ! in_array($newval,$this->cachefieldtable[$field.'@'.$table])) + if (! is_array($this->cachefieldtable[$cachekey]) || ! in_array($newval,$this->cachefieldtable[$cachekey])) { - $this->errors[$error]['lib']=$langs->transnoentitiesnoconv('ErrorFieldValueNotIn',$key,$newval,$field,$table); + $tableforerror = $table; + if(! empty($filter)) $tableforerror.= ':'.$filter; + $this->errors[$error]['lib']=$langs->transnoentitiesnoconv('ErrorFieldValueNotIn',$key,$newval,$field,$tableforerror); $this->errors[$error]['type']='FOREIGNKEY'; $errorforthistable++; $error++; diff --git a/htdocs/core/modules/import/import_xlsx.modules.php b/htdocs/core/modules/import/import_xlsx.modules.php index 7f222f523ca..7d850ccfb8b 100644 --- a/htdocs/core/modules/import/import_xlsx.modules.php +++ b/htdocs/core/modules/import/import_xlsx.modules.php @@ -519,15 +519,24 @@ class ImportXlsx extends ModeleImports if (! empty($objimport->array_import_regex[0][$val]) && ($newval != '')) { // If test is "Must exist in a field@table" - if (preg_match('/^(.*)@(.*)$/',$objimport->array_import_regex[0][$val],$reg)) + if (preg_match('/^(.+)@([^:]+)(:.+)?$/',$objimport->array_import_regex[0][$val],$reg)) { $field=$reg[1]; $table=$reg[2]; + $filter=!empty($reg[3])?substr($reg[3], 1):''; + + $cachekey = $field.'@'.$table; + if(! empty($filter)) $cachekey.= ':'.$filter; // Load content of field@table into cache array - if (! is_array($this->cachefieldtable[$field.'@'.$table])) // If content of field@table not already loaded into cache + if (! is_array($this->cachefieldtable[$cachekey])) // If content of field@table not already loaded into cache { $sql="SELECT ".$field." as aliasfield FROM ".$table; + if(! empty($filter)) + { + $sql.= ' WHERE ' . $filter; + } + $resql=$this->db->query($sql); if ($resql) { @@ -536,7 +545,7 @@ class ImportXlsx extends ModeleImports while ($i < $num) { $obj=$this->db->fetch_object($resql); - if ($obj) $this->cachefieldtable[$field.'@'.$table][]=$obj->aliasfield; + if ($obj) $this->cachefieldtable[$cachekey][]=$obj->aliasfield; $i++; } } @@ -547,9 +556,11 @@ class ImportXlsx extends ModeleImports } // Now we check cache is not empty (should not) and key is into cache - if (! is_array($this->cachefieldtable[$field.'@'.$table]) || ! in_array($newval,$this->cachefieldtable[$field.'@'.$table])) + if (! is_array($this->cachefieldtable[$cachekey]) || ! in_array($newval,$this->cachefieldtable[$cachekey])) { - $this->errors[$error]['lib']=$langs->transnoentitiesnoconv('ErrorFieldValueNotIn',$key,$newval,$field,$table); + $tableforerror = $table; + if(! empty($filter)) $tableforerror.= ':'.$filter; + $this->errors[$error]['lib']=$langs->transnoentitiesnoconv('ErrorFieldValueNotIn',$key,$newval,$field,$tableforerror); $this->errors[$error]['type']='FOREIGNKEY'; $errorforthistable++; $error++; diff --git a/htdocs/core/modules/modAdherent.class.php b/htdocs/core/modules/modAdherent.class.php index 3acd162bb03..76ff02b588b 100644 --- a/htdocs/core/modules/modAdherent.class.php +++ b/htdocs/core/modules/modAdherent.class.php @@ -273,20 +273,22 @@ class modAdherent extends DolibarrModules 'a.phone'=>"PhonePro",'a.phone_perso'=>"PhonePerso",'a.phone_mobile'=>"PhoneMobile",'a.email'=>"Email",'a.birth'=>"Birthday",'a.statut'=>"Status", 'a.photo'=>"Photo",'a.note_public'=>"NotePublic",'a.note_private'=>"NotePrivate",'a.datec'=>'DateCreation','a.datevalid'=>'DateValidation', 'a.tms'=>'DateLastModification','a.datefin'=>'DateEndSubscription','ta.rowid'=>'MemberTypeId','ta.libelle'=>'MemberTypeLabel', - 'c.rowid'=>'SubscriptionId','c.dateadh'=>'DateSubscription','c.subscription'=>'Amount' + 'c.rowid'=>'SubscriptionId','c.dateadh'=>'DateSubscription','c.datef'=>'DateEndSubscription','c.subscription'=>'Amount' ); $this->export_TypeFields_array[$r]=array( 'a.civility'=>"Text",'a.lastname'=>"Text",'a.firstname'=>"Text",'a.login'=>"Text",'a.morphy'=>'Text','a.societe'=>'Text','a.address'=>"Text", 'a.zip'=>"Text",'a.town'=>"Text",'d.nom'=>"Text",'co.code'=>'Text','co.label'=>"Text",'a.phone'=>"Text",'a.phone_perso'=>"Text",'a.phone_mobile'=>"Text", 'a.email'=>"Text",'a.birth'=>"Date",'a.statut'=>"Status",'a.note_public'=>"Text",'a.note_private'=>"Text",'a.datec'=>'Date','a.datevalid'=>'Date', - 'a.tms'=>'Date','a.datefin'=>'Date','ta.rowid'=>'List:adherent_type:libelle::member_type','ta.libelle'=>'Text','c.rowid'=>'Numeric','c.dateadh'=>'Date','c.subscription'=>'Numeric' + 'a.tms'=>'Date','a.datefin'=>'Date','ta.rowid'=>'List:adherent_type:libelle::member_type','ta.libelle'=>'Text', + 'c.rowid'=>'Numeric','c.dateadh'=>'Date','c.datef'=>'Date','c.subscription'=>'Numeric' ); $this->export_entities_array[$r]=array( 'a.rowid'=>'member','a.civility'=>"member",'a.lastname'=>"member",'a.firstname'=>"member",'a.login'=>"member",'a.morphy'=>'member', 'a.societe'=>'member','a.address'=>"member",'a.zip'=>"member",'a.town'=>"member",'d.nom'=>"member",'co.code'=>"member",'co.label'=>"member", 'a.phone'=>"member",'a.phone_perso'=>"member",'a.phone_mobile'=>"member",'a.email'=>"member",'a.birth'=>"member",'a.statut'=>"member", 'a.photo'=>"member",'a.note_public'=>"member",'a.note_private'=>"member",'a.datec'=>'member','a.datevalid'=>'member','a.tms'=>'member', - 'a.datefin'=>'member','ta.rowid'=>'member_type','ta.libelle'=>'member_type','c.rowid'=>'subscription','c.dateadh'=>'subscription','c.subscription'=>'subscription' + 'a.datefin'=>'member','ta.rowid'=>'member_type','ta.libelle'=>'member_type', + 'c.rowid'=>'subscription','c.dateadh'=>'subscription','c.datef'=>'subscription','c.subscription'=>'subscription' ); // Add extra fields $keyforselect='adherent'; $keyforelement='member'; $keyforaliasextra='extra'; diff --git a/htdocs/core/modules/modCategorie.class.php b/htdocs/core/modules/modCategorie.class.php index 50074779955..668b0ac9014 100644 --- a/htdocs/core/modules/modCategorie.class.php +++ b/htdocs/core/modules/modCategorie.class.php @@ -422,8 +422,8 @@ class modCategorie extends DolibarrModules $this->import_icon[$r]=$this->picto; $this->import_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon $this->import_tables_array[$r]=array('cp'=>MAIN_DB_PREFIX.'categorie_product'); - $this->import_fields_array[$r]=array('cp.fk_categorie'=>"Category*",'cp.fk_product'=>"Product*" - ); + $this->import_fields_array[$r]=array('cp.fk_categorie'=>"Category*",'cp.fk_product'=>"Product*"); + $this->import_regex_array[$r]=array('cp.fk_categorie'=>'rowid@'.MAIN_DB_PREFIX.'categorie:type=0'); $this->import_convertvalue_array[$r]=array( 'cp.fk_categorie'=>array('rule'=>'fetchidfromref','classfile'=>'/categories/class/categorie.class.php','class'=>'Categorie','method'=>'fetch','element'=>'category'), @@ -441,7 +441,10 @@ class modCategorie extends DolibarrModules $this->import_icon[$r]=$this->picto; $this->import_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon $this->import_tables_array[$r]=array('cs'=>MAIN_DB_PREFIX.'categorie_societe'); - $this->import_fields_array[$r]=array('cs.fk_categorie'=>"Category*",'cs.fk_soc'=>"ThirdParty*" + $this->import_fields_array[$r]=array('cs.fk_categorie'=>"Category*",'cs.fk_soc'=>"ThirdParty*"); + $this->import_regex_array[$r]=array( + 'cs.fk_categorie'=>'rowid@'.MAIN_DB_PREFIX.'categorie:type=2', + 'cs.fk_soc'=>'rowid@'.MAIN_DB_PREFIX.'societe:client>0' ); $this->import_convertvalue_array[$r]=array( @@ -460,7 +463,10 @@ class modCategorie extends DolibarrModules $this->import_icon[$r]=$this->picto; $this->import_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon $this->import_tables_array[$r]=array('cs'=>MAIN_DB_PREFIX.'categorie_fournisseur'); - $this->import_fields_array[$r]=array('cs.fk_categorie'=>"Category*",'cs.fk_soc'=>"Supplier*" + $this->import_fields_array[$r]=array('cs.fk_categorie'=>"Category*",'cs.fk_soc'=>"Supplier*"); + $this->import_regex_array[$r]=array( + 'cs.fk_categorie'=>'rowid@'.MAIN_DB_PREFIX.'categorie:type=1', + 'cs.fk_soc'=>'rowid@'.MAIN_DB_PREFIX.'societe:fournisseur>0' ); $this->import_convertvalue_array[$r]=array( diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php index 220827843a9..f5ad9948a6a 100644 --- a/htdocs/core/modules/modProjet.class.php +++ b/htdocs/core/modules/modProjet.class.php @@ -246,8 +246,8 @@ class modProjet extends DolibarrModules $keyforselect='projet'; $keyforelement='project'; $keyforaliasextra='extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; // Add fields for tasks - $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('pt.rowid'=>'RefTask','pt.label'=>'LabelTask','pt.dateo'=>"TaskDateStart",'pt.datee'=>"TaskDateEnd",'pt.duration_effective'=>"DurationEffective",'pt.planned_workload'=>"PlannedWorkload",'pt.progress'=>"Progress",'pt.description'=>"TaskDescription")); - $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('pt.rowid'=>'projecttask','pt.label'=>'projecttask','pt.dateo'=>"projecttask",'pt.datee'=>"projecttask",'pt.duration_effective'=>"projecttask",'pt.planned_workload'=>"projecttask",'pt.progress'=>"projecttask",'pt.description'=>"projecttask")); + $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('pt.rowid'=>'TaskId', 'pt.ref'=>'RefTask', 'pt.label'=>'LabelTask','pt.dateo'=>"TaskDateStart",'pt.datee'=>"TaskDateEnd",'pt.duration_effective'=>"DurationEffective",'pt.planned_workload'=>"PlannedWorkload",'pt.progress'=>"Progress",'pt.description'=>"TaskDescription")); + $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('pt.rowid'=>'projecttask', 'pt.ref'=>'projecttask', 'pt.label'=>'projecttask','pt.dateo'=>"projecttask",'pt.datee'=>"projecttask",'pt.duration_effective'=>"projecttask",'pt.planned_workload'=>"projecttask",'pt.progress'=>"projecttask",'pt.description'=>"projecttask")); // Add extra fields for task $keyforselect='projet_task'; $keyforelement='projecttask'; $keyforaliasextra='extra2'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; diff --git a/htdocs/core/modules/modReceiptPrinter.class.php b/htdocs/core/modules/modReceiptPrinter.class.php index 19df7ca0726..9f5a9065c54 100644 --- a/htdocs/core/modules/modReceiptPrinter.class.php +++ b/htdocs/core/modules/modReceiptPrinter.class.php @@ -136,8 +136,8 @@ class modReceiptPrinter extends DolibarrModules // Clean before activation $this->remove($options); $sql = array( - "CREATE TABLE IF NOT EXISTS llx_printer_receipt (rowid integer AUTO_INCREMENT PRIMARY KEY, name varchar(128), fk_type integer, fk_profile integer, parameter varchar(128), entity integer) ENGINE=innodb;", - "CREATE TABLE IF NOT EXISTS llx_printer_receipt_template (rowid integer AUTO_INCREMENT PRIMARY KEY, name varchar(128), template text, entity integer) ENGINE=innodb;", + "CREATE TABLE IF NOT EXISTS ".MAIN_DB_PREFIX."printer_receipt (rowid integer AUTO_INCREMENT PRIMARY KEY, name varchar(128), fk_type integer, fk_profile integer, parameter varchar(128), entity integer) ENGINE=innodb;", + "CREATE TABLE IF NOT EXISTS ".MAIN_DB_PREFIX."printer_receipt_template (rowid integer AUTO_INCREMENT PRIMARY KEY, name varchar(128), template text, entity integer) ENGINE=innodb;", ); return $this->_init($sql,$options); } diff --git a/htdocs/core/modules/modStock.class.php b/htdocs/core/modules/modStock.class.php index 8f884c46646..b034fcd8ef4 100644 --- a/htdocs/core/modules/modStock.class.php +++ b/htdocs/core/modules/modStock.class.php @@ -343,7 +343,7 @@ class modStock extends DolibarrModules 'ps.fk_product'=>"PREF123456",'ps.fk_entrepot'=>"ALM001",'ps.reel'=>"10" ); $this->import_run_sql_after_array[$r]=array( // Because we may change data that are denormalized, we must update dernormalized data after. - 'UPDATE llx_product p SET p.stock= (SELECT SUM(ps.reel) FROM llx_product_stock ps WHERE ps.fk_product = p.rowid);' + 'UPDATE '.MAIN_DB_PREFIX.'product p SET p.stock= (SELECT SUM(ps.reel) FROM '.MAIN_DB_PREFIX.'product_stock ps WHERE ps.fk_product = p.rowid);' ); } diff --git a/htdocs/core/modules/project/doc/pdf_beluga.modules.php b/htdocs/core/modules/project/doc/pdf_beluga.modules.php index d7cae4726c5..562f6a093dc 100644 --- a/htdocs/core/modules/project/doc/pdf_beluga.modules.php +++ b/htdocs/core/modules/project/doc/pdf_beluga.modules.php @@ -273,7 +273,7 @@ class pdf_beluga extends ModelePDFProjects 'table'=>'commande', 'datefieldname'=>'date_commande', 'test'=>$conf->commande->enabled && $user->rights->commande->lire, - 'lang'=>'order'), + 'lang'=>'orders'), 'invoice'=>array( 'name'=>"CustomersInvoices", 'title'=>"ListInvoicesAssociatedProject", diff --git a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php index 8492160c185..bdaf963b4f5 100644 --- a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php @@ -27,6 +27,7 @@ if (! empty($extrafieldsobjectkey)) // $extrafieldsobject is the $object->table_ if (in_array($typ, array('int','double','real'))) $mode_search=1; // Search on a numeric if (in_array($typ, array('sellist','link')) && $crit != '0' && $crit != '-1') $mode_search=2; // Search on a foreign key int if (in_array($typ, array('chkbxlst','checkbox'))) $mode_search=4; // Search on a multiselect field with sql type = text + if (is_array($crit)) $crit = implode(' ', $crit); // natural_search() expects a string $sql .= natural_search('ef.'.$tmpkey, $crit, $mode_search); } diff --git a/htdocs/core/tpl/massactions_pre.tpl.php b/htdocs/core/tpl/massactions_pre.tpl.php index a66e9ba270e..a5d7883f3e5 100644 --- a/htdocs/core/tpl/massactions_pre.tpl.php +++ b/htdocs/core/tpl/massactions_pre.tpl.php @@ -44,7 +44,7 @@ if ($massaction == 'presend') $listofselectedid = array(); $listofselectedthirdparties = array(); $listofselectedref = array(); - + if (! GETPOST('cancel', 'alpha')) { foreach ($arrayofselected as $toselectid) @@ -111,8 +111,9 @@ if ($massaction == 'presend') } else { $formmail->withtoreadonly = 1; } - - $formmail->withoptiononeemailperrecipient = (count($listofselectedref) == 1 || empty($liste))? 0 : ((GETPOST('oneemailperrecipient')=='on')?1:-1); + + $formmail->withoptiononeemailperrecipient = ((count($listofselectedref) == 1 && count(reset($listofselectedref)) == 1) || empty($liste)) ? 0 : ((GETPOST('oneemailperrecipient')=='on')?1:-1); + $formmail->withto = empty($liste)?(GETPOST('sendto','alpha')?GETPOST('sendto','alpha'):array()):$liste; $formmail->withtofree = empty($liste)?1:0; $formmail->withtocc = 1; @@ -131,6 +132,7 @@ if ($massaction == 'presend') // Make substitution in email content $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object); + $substitutionarray['__EMAIL__'] = $sendto; $substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '' : ''; $substitutionarray['__PERSONALIZED__'] = ''; // deprecated diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index e478e265652..8c849f5fa40 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -105,8 +105,8 @@ class InterfaceWorkflowManager extends DolibarrTriggers if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht; } dol_syslog( "Amount of linked proposals = ".$totalonlinkedelements.", of order = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) ); - if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) ) - { + if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) + { foreach($object->linkedObjects['propal'] as $element) { $ret=$element->classifyBilled($user); @@ -121,7 +121,8 @@ class InterfaceWorkflowManager extends DolibarrTriggers if ($action == 'BILL_VALIDATE') { dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id ); - + $ret = 0; + // First classify billed the order to allow the proposal classify process if (! empty($conf->commande->enabled) && ! empty($conf->workflow->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER)) { @@ -134,7 +135,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) $totalonlinkedelements += $element->total_ht; } dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) ); - if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) ) + if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) { foreach($object->linkedObjects['commande'] as $element) { @@ -142,7 +143,6 @@ class InterfaceWorkflowManager extends DolibarrTriggers } } } - return $ret; } // Second classify billed the proposal. @@ -157,16 +157,17 @@ class InterfaceWorkflowManager extends DolibarrTriggers if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht; } dol_syslog( "Amount of linked proposals = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) ); - if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) ) - { + if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) + { foreach($object->linkedObjects['propal'] as $element) { $ret=$element->classifyBilled($user); } } } - return $ret; } + + return $ret; } // classify billed order & billed propososal @@ -186,8 +187,8 @@ class InterfaceWorkflowManager extends DolibarrTriggers if ($element->statut == CommandeFournisseur::STATUS_ACCEPTED || $element->statut == CommandeFournisseur::STATUS_ORDERSENT || $element->statut == CommandeFournisseur::STATUS_RECEIVED_PARTIALLY || $element->statut == CommandeFournisseur::STATUS_RECEIVED_COMPLETELY) $totalonlinkedelements += $element->total_ht; } dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) ); - if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) ) - { + if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) + { foreach($object->linkedObjects['order_supplier'] as $element) { $ret=$element->classifyBilled($user); @@ -209,8 +210,8 @@ class InterfaceWorkflowManager extends DolibarrTriggers if ($element->statut == SupplierProposal::STATUS_SIGNED || $element->statut == SupplierProposal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht; } dol_syslog( "Amount of linked supplier proposals = ".$totalonlinkedelements.", of supplier invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) ); - if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) ) - { + if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) + { foreach($object->linkedObjects['supplier_proposal'] as $element) { $ret=$element->classifyBilled($user); @@ -237,7 +238,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) $totalonlinkedelements += $element->total_ht; } dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) ); - if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) ) + if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) { foreach($object->linkedObjects['commande'] as $element) { @@ -310,4 +311,23 @@ class InterfaceWorkflowManager extends DolibarrTriggers return 0; } + /** + * @param Object $conf Dolibarr settings object + * @param float $totalonlinkedelements Sum of total amounts (excl VAT) of + * invoices linked to $object + * @param float $object_total_ht The total amount (excl VAT) of the object + * (an order, a proposal, a bill, etc.) + * @return bool True if the amounts are equal (rounded on total amount) + * True if the module is configured to skip the amount equality check + * False otherwise. + */ + private function shouldClassify($conf, $totalonlinkedelements, $object_total_ht) + { + // if the configuration allows unmatching amounts, allow classification anyway + if (!empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) { + return true; + } + // if the amount are same, allow classification, else deny + return (price2num($totalonlinkedelements, 'MT') == price2num($object_total_ht, 'MT')); + } } diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index aa85132b243..c8ebeb5be57 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -468,7 +468,8 @@ if (empty($reshook)) else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->expedition->supprimer) { - $result = $object->delete(); + $also_update_stock = GETPOST('alsoUpdateStock', 'alpha') ?: 0; + $result = $object->delete($also_update_stock); if ($result > 0) { header("Location: ".DOL_URL_ROOT.'/expedition/index.php'); @@ -551,6 +552,7 @@ if (empty($reshook)) header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id); exit(); } + setEventMessages($object->error, $object->errors, 'errors'); } elseif ($action == 'classifyclosed') @@ -561,6 +563,7 @@ if (empty($reshook)) header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id); exit(); } + setEventMessages($object->error, $object->errors, 'errors'); } /* @@ -1648,7 +1651,26 @@ else if ($id || $ref) // Confirm deleteion if ($action == 'delete') { - $formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('DeleteSending'),$langs->trans("ConfirmDeleteSending",$object->ref),'confirm_delete','',0,1); + $formquestion = array(); + if ($object->statut == Expedition::STATUS_CLOSED && !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) { + $formquestion = array( + array( + 'label' => $langs->trans('ShipmentIncrementStockOnDelete'), + 'name' => 'alsoUpdateStock', + 'type' => 'checkbox', + 'value' => 0 + ), + ); + } + $formconfirm=$form->formconfirm( + $_SERVER['PHP_SELF'].'?id='.$object->id, + $langs->trans('DeleteSending'), + $langs->trans("ConfirmDeleteSending",$object->ref), + 'confirm_delete', + $formquestion, + 0, + 1 + ); } // Confirmation validation diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 3ab96fed1fa..ea6e003d326 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -1073,13 +1073,15 @@ class Expedition extends CommonObject } } - /** - * Delete shipment. - * Warning, do not delete a shipment if a delivery is linked to (with table llx_element_element) - * - * @return int >0 if OK, 0 if deletion done but failed to delete files, <0 if KO - */ - function delete() + /** + * Delete shipment. + * Warning, do not delete a shipment if a delivery is linked to (with table llx_element_element) + * + * @param bool $also_update_stock true if the stock should be increased back (false by default) + * @return int >0 if OK, 0 if deletion done but failed to delete files, <0 if KO + * @throws Exception + */ + function delete($also_update_stock = false) { global $conf, $langs, $user; @@ -1111,7 +1113,9 @@ class Expedition extends CommonObject } // Stock control - if (! $error && $conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_SHIPMENT && $this->statut > self::STATUS_DRAFT) + if (! $error && $conf->stock->enabled && + (($conf->global->STOCK_CALCULATE_ON_SHIPMENT && $this->statut > self::STATUS_DRAFT) || + ($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE && $this->statut == self::STATUS_CLOSED && $also_update_stock))) { require_once(DOL_DOCUMENT_ROOT."/product/stock/class/mouvementstock.class.php"); diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index bbf990f2ec6..c92962357b2 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -894,7 +894,7 @@ if ($id > 0 || ! empty($ref)) print $langs->trans("WarehouseSource"); //print ''; //print ''; - print $formproduct->selectWarehouses(! empty($object->warehouse_id)?$object->warehouse_id:-1, 'entrepot_id', '', 1, 0, 0, '', 0, 0, array(), 'minwidth200'); + print $formproduct->selectWarehouses(! empty($object->warehouse_id)?$object->warehouse_id:'ifone', 'entrepot_id', '', 1, 0, 0, '', 0, 0, array(), 'minwidth200'); if (count($formproduct->cache_warehouses) <= 0) { print '   '.$langs->trans("WarehouseSourceNotDefined").' '.$langs->trans("AddOne").''; diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index e623a76c87c..22410ee4085 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -62,6 +62,8 @@ $comments=GETPOST('comments','none'); $fk_c_type_fees=GETPOST('fk_c_type_fees','int'); $socid = GETPOST('socid','int')?GETPOST('socid','int'):GETPOST('socid_id','int'); +$childids = $user->getAllChildIds(1); + // Security check $id=GETPOST("id",'int'); if ($user->societe_id) $socid=$user->societe_id; @@ -105,7 +107,17 @@ $permissionnote = $user->rights->expensereport->creer; // Used by the include $permissiondellink = $user->rights->expensereport->creer; // Used by the include of actions_dellink.inc.php $permissionedit = $user->rights->expensereport->creer; // Used by the include of actions_lineupdown.inc.php - +if ($object->id > 0) +{ + // Check current user can read this expense report + $canread = 0; + if (! empty($user->rights->expensereport->readall)) $canread=1; + if (! empty($user->rights->expensereport->lire) && in_array($object->fk_user_author, $childids)) $canread=1; + if (! $canread) + { + accessforbidden(); + } +} /* @@ -955,6 +967,34 @@ if (empty($reshook)) } } + if ($action == 'set_unpaid' && $id > 0 && $user->rights->expensereport->to_paid) + { + $object = new ExpenseReport($db); + $object->fetch($id); + + $result = $object->set_unpaid($user); + + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + } + if ($action == 'set_paid' && $id > 0 && $user->rights->expensereport->to_paid) { $object = new ExpenseReport($db); @@ -1892,7 +1932,7 @@ else if ($resql) { $num = $db->num_rows($resql); - $i = 0; $total = 0; + $i = 0; $totalpaid = 0; while ($i < $num) { $objp = $db->fetch_object($resql); @@ -2337,8 +2377,8 @@ if ($action != 'create' && $action != 'edit') } - // If status is Appoved - // -------------------- + // If status is Approved + // --------------------- if ($user->rights->expensereport->approve && $object->fk_statut == 5) { @@ -2382,9 +2422,15 @@ if ($action != 'create' && $action != 'edit') print ''; } + if ($user->rights->expensereport->to_paid && $object->paid && $object->fk_statut == ExpenseReport::STATUS_CLOSED) + { + // Set unpaid + print ''; + } + // Clone if ($user->rights->expensereport->creer) { - print ''; + print ''; } /* If draft, validated, cancel, and user can create, he can always delete its card before it is approved */ diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 3f5029c4ef6..b9e60ed50d5 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -106,6 +106,11 @@ class ExpenseReport extends CommonObject */ const STATUS_VALIDATED = 2; + /** + * Classified canceled + */ + const STATUS_CANCELED = 4; + /** * Classified approved */ @@ -1205,10 +1210,10 @@ class ExpenseReport extends CommonObject $this->date_debut = $this->db->jdate($objp->date_debut); - if ($this->fk_statut != 2) + if ($this->fk_statut != self::STATUS_VALIDATED) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_statut = 2"; + $sql.= " SET fk_statut = ".self::STATUS_VALIDATED; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_save_from_refuse sql=".$sql, LOG_DEBUG); @@ -1243,12 +1248,12 @@ class ExpenseReport extends CommonObject // date approval $this->date_approve = $now; - if ($this->fk_statut != 5) + if ($this->fk_statut != self::STATUS_APPROVED) { $this->db->begin(); $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET ref = '".$this->db->escape($this->ref)."', fk_statut = 5, fk_user_approve = ".$fuser->id.","; + $sql.= " SET ref = '".$this->db->escape($this->ref)."', fk_statut = ".self::STATUS_APPROVED.", fk_user_approve = ".$fuser->id.","; $sql.= " date_approve='".$this->db->idate($this->date_approve)."'"; $sql.= ' WHERE rowid = '.$this->id; if ($this->db->query($sql)) @@ -1304,10 +1309,10 @@ class ExpenseReport extends CommonObject $error = 0; // date de refus - if ($this->fk_statut != 99) + if ($this->fk_statut != self::STATUS_REFUSED) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET ref = '".$this->db->escape($this->ref)."', fk_statut = 99, fk_user_refuse = ".$fuser->id.","; + $sql.= " SET ref = '".$this->db->escape($this->ref)."', fk_statut = ".self::STATUS_REFUSED.", fk_user_refuse = ".$fuser->id.","; $sql.= " date_refuse='".$this->db->idate($now)."',"; $sql.= " detail_refuse='".$this->db->escape($details)."',"; $sql.= " fk_user_approve = NULL"; @@ -1366,12 +1371,12 @@ class ExpenseReport extends CommonObject { $error = 0; - if ($this->fk_c_deplacement_statuts != 5) + if ($this->paid) { $this->db->begin(); $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_statut = 5"; + $sql.= " SET paid = 0, fk_statut = ".self::STATUS_APPROVED; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_unpaid sql=".$sql, LOG_DEBUG); @@ -1426,12 +1431,12 @@ class ExpenseReport extends CommonObject { $error = 0; $this->date_cancel = $this->db->idate(gmmktime()); - if ($this->fk_statut != 4) + if ($this->fk_statut != self::STATUS_CANCELED) { $this->db->begin(); $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_statut = 4, fk_user_cancel = ".$fuser->id; + $sql.= " SET fk_statut = ".self::STATUS_CANCELED.", fk_user_cancel = ".$fuser->id; $sql.= ", date_cancel='".$this->db->idate($this->date_cancel)."'"; $sql.= " ,detail_cancel='".$this->db->escape($detail)."'"; $sql.= ' WHERE rowid = '.$this->id; diff --git a/htdocs/expensereport/list.php b/htdocs/expensereport/list.php index e576889d363..db36aacf542 100644 --- a/htdocs/expensereport/list.php +++ b/htdocs/expensereport/list.php @@ -4,6 +4,7 @@ * Copyright (C) 2004 Eric Seigne * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2015 Alexandre Spangaro + * Copyright (C) 2019 Juanjo Menent * Copyright (C) 2018 Ferran Marcet * * This program is free software; you can redistribute it and/or modify @@ -45,10 +46,25 @@ $confirm=GETPOST('confirm','alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage=GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'expensereportlist'; +$childids = $user->getAllChildIds(1); + // Security check $socid = GETPOST('socid','int'); if ($user->societe_id) $socid=$user->societe_id; $result = restrictedArea($user, 'expensereport','',''); +$id = GETPOST('id', 'int'); +// If we are on the view of a specific user +if ($id > 0) +{ + $canread=0; + if ($id == $user->id) $canread=1; + if (! empty($user->rights->expensereport->readall)) $canread=1; + if (! empty($user->rights->expensereport->lire) && in_array($id, $childids)) $canread=1; + if (! $canread) + { + accessforbidden(); + } +} $diroutputmassaction=$conf->expensereport->dir_output . '/temp/massgeneration/'.$user->id; @@ -65,10 +81,9 @@ $pagenext = $page + 1; if (!$sortorder) $sortorder="DESC"; if (!$sortfield) $sortfield="d.date_debut"; -$id = GETPOST('id', 'int'); $sall = trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml')); -$search_ref = GETPOST('search_ref'); +$search_ref = GETPOST('search_ref', 'alpha'); $search_user = GETPOST('search_user','int'); $search_amount_ht = GETPOST('search_amount_ht','alpha'); $search_amount_vat = GETPOST('search_amount_vat','alpha'); @@ -257,7 +272,7 @@ $sql = "SELECT d.rowid, d.ref, d.fk_user_author, d.total_ht, d.total_tva, d.tota $sql.= " d.date_debut, d.date_fin, d.date_create, d.tms as date_modif, d.date_valid, d.date_approve, d.note_private, d.note_public,"; $sql.= " u.rowid as id_user, u.firstname, u.lastname, u.login, u.email, u.statut, u.photo"; // Add fields from extrafields -foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : ''); +foreach ($extrafields->attributes['expensereport']['type'] as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : ''); // Add fields from hooks $parameters=array(); $reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook diff --git a/htdocs/fichinter/list.php b/htdocs/fichinter/list.php index 96a1199255c..d5226795140 100644 --- a/htdocs/fichinter/list.php +++ b/htdocs/fichinter/list.php @@ -5,7 +5,7 @@ * Copyright (C) 2011-2012 Juanjo Menent * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2015 Jean-François Ferry - * Copyright (C) 2018 Ferran Marcet + * Copyright (C) 2018-2019 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 @@ -32,23 +32,31 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +if ($conf->projet->enabled) { + require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php'; +} +if ($conf->contrat->enabled) { + require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php'; +} + + // Load translation files required by the page -$langs->loadLangs(array('companies', 'bills', 'interventions')); +$langs->loadLangs(array('companies', 'bills', 'interventions', 'exports')); -$action=GETPOST('action','alpha'); -$massaction=GETPOST('massaction','alpha'); -$show_files=GETPOST('show_files','int'); -$confirm=GETPOST('confirm','alpha'); +$action=GETPOST('action', 'alpha'); +$massaction=GETPOST('massaction', 'alpha'); +$show_files=GETPOST('show_files', 'int'); +$confirm=GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); -$contextpage=GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'interventionlist'; +$contextpage=GETPOST('contextpage', 'aZ')?GETPOST('contextpage', 'aZ'):'interventionlist'; -$search_ref=GETPOST('search_ref')?GETPOST('search_ref','alpha'):GETPOST('search_inter','alpha'); -$search_company=GETPOST('search_company','alpha'); -$search_desc=GETPOST('search_desc','alpha'); -$search_status=GETPOST('search_status'); +//$search_ref=GETPOST('search_ref')?GETPOST('search_ref','alpha'):GETPOST('search_inter','alpha'); +//$search_company=GETPOST('search_company','alpha'); +//$search_desc=GETPOST('search_desc','alpha'); +//$search_status=GETPOST('search_status'); $sall=trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml')); -$optioncss = GETPOST('optioncss','alpha'); +//$optioncss = GETPOST('optioncss','alpha'); $socid=GETPOST('socid','int'); // Security check @@ -79,6 +87,8 @@ $search_company=GETPOST('search_company','alpha'); $search_desc=GETPOST('search_desc','alpha'); $search_status=GETPOST('search_status'); $optioncss = GETPOST('optioncss','alpha'); +$search_project=GETPOST('search_project','alpha'); +$search_contract=GETPOST('search_contract','alpha'); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $object = new Fichinter($db); @@ -103,10 +113,10 @@ if (! empty($conf->global->FICHINTER_DISABLE_DETAILS)) unset($fieldstosearchall[ $arrayfields=array( 'f.ref'=>array('label'=>$langs->trans("Ref"), 'checked'=>1), 's.nom'=>array('label'=>$langs->trans("ThirdParty"), 'checked'=>1), - 'f.fk_project'=>array('label'=>$langs->trans("Project"), 'checked'=>1), + 'f.fk_projet'=>array('label'=>$langs->trans("Project"), 'checked'=>1), 'f.fk_contrat'=>array('label'=>$langs->trans("Contract"), 'checked'=>1), 'f.description'=>array('label'=>$langs->trans("Description"), 'checked'=>1), - 'fd.description'=>array('label'=>"xx", 'checked'=>1, 'enabled'=>empty($conf->global->FICHINTER_DISABLE_DETAILS)?1:0), + 'fd.description'=>array('label'=>$langs->trans("LineDescription"), 'checked'=>1, 'enabled'=>empty($conf->global->FICHINTER_DISABLE_DETAILS)?1:0), 'fd.date'=>array('label'=>$langs->trans("Date"), 'checked'=>1, 'enabled'=>empty($conf->global->FICHINTER_DISABLE_DETAILS)?1:0), 'fd.duree'=>array('label'=>$langs->trans("Duration"), 'checked'=>1, 'enabled'=>empty($conf->global->FICHINTER_DISABLE_DETAILS)?1:0), 'f.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), @@ -173,6 +183,12 @@ $form = new Form($db); $formfile = new FormFile($db); $objectstatic=new Fichinter($db); $companystatic=new Societe($db); +if ($conf->projet->enabled) { + $projectstatic = new Project($db); +} +if ($conf->contrat->enabled) { + $contratstatic = new Contrat($db); +} $title=$langs->trans("ListOfInterventions"); llxHeader('', $title); @@ -182,6 +198,12 @@ $sql = "SELECT"; $sql.= " f.ref, f.rowid, f.fk_statut, f.description, f.datec as date_creation, f.tms as date_update, f.note_private,"; if (empty($conf->global->FICHINTER_DISABLE_DETAILS)) $sql.= " fd.description as descriptiondetail, fd.date as dp, fd.duree,"; $sql.= " s.nom as name, s.rowid as socid, s.client"; +if (! empty($arrayfields['f.fk_projet']['checked'])){ + $sql.= " ,p.rowid as projectid, p.ref as projectref, p.title as projecttitle"; +} +if (! empty($arrayfields['f.fk_contrat']['checked'])){ + $sql.= " ,c.rowid as contractid, c.ref as contractref"; +} // Add fields from extrafields foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : ''); // Add fields from hooks @@ -189,6 +211,12 @@ $parameters=array(); $reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook $sql.=$hookmanager->resPrint; $sql.= " FROM ".MAIN_DB_PREFIX."fichinter as f"; +if (! empty($arrayfields['f.fk_projet']['checked'])){ + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."projet as p ON f.fk_projet = p.rowid"; +} +if (! empty($arrayfields['f.fk_contrat']['checked'])){ + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."contrat as c ON f.fk_contrat = c.rowid"; +} if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."fichinter_extrafields as ef on (f.rowid = ef.fk_object)"; if (empty($conf->global->FICHINTER_DISABLE_DETAILS)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."fichinterdet as fd ON fd.fk_fichinter = f.rowid"; if (! $user->rights->societe->client->voir && empty($socid)) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -212,6 +240,12 @@ if (! $user->rights->societe->client->voir && empty($socid)) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; if ($socid) $sql.= " AND s.rowid = " . $socid; +if ($search_project) { + $sql .= natural_search('p.ref', $search_project); +} +if ($search_contract) { + $sql .= natural_search('c.ref', $search_contract); +} if ($sall) { $sql .= natural_search(array_keys($fieldstosearchall), $sall); } @@ -262,6 +296,8 @@ if ($resql) if ($search_company) $param.="&search_company=".urlencode($search_company); if ($search_desc) $param.="&search_desc=".urlencode($search_desc); if ($search_status != '' && $search_status > -1) $param.="&search_status=".urlencode($search_status); + if ($search_project) $param.="&search_project=".urlencode($search_project); + if ($search_contract) $param.="&search_contract=".urlencode($search_contract); if ($show_files) $param.='&show_files=' .$show_files; if ($optioncss != '') $param.='&optioncss='.$optioncss; // Add $param from extra fields @@ -343,6 +379,18 @@ if ($resql) print ''; print ''; } + if (! empty($arrayfields['f.fk_projet']['checked'])) + { + print ''; + print ''; + print ''; + } + if (! empty($arrayfields['f.fk_contrat']['checked'])) + { + print ''; + print ''; + print ''; + } if (! empty($arrayfields['f.description']['checked'])) { print ''; @@ -399,21 +447,23 @@ if ($resql) print "\n"; print ''; - if (! empty($arrayfields['f.ref']['checked'])) print_liste_field_titre("Ref",$_SERVER["PHP_SELF"],"f.ref","",$param,'',$sortfield,$sortorder); - if (! empty($arrayfields['s.nom']['checked'])) print_liste_field_titre("ThirdParty",$_SERVER["PHP_SELF"],"s.nom","",$param,'',$sortfield,$sortorder); - if (! empty($arrayfields['f.description']['checked'])) print_liste_field_titre("Description",$_SERVER["PHP_SELF"],"f.description","",$param,'',$sortfield,$sortorder); - if (! empty($arrayfields['fd.description']['checked'])) print_liste_field_titre('',$_SERVER["PHP_SELF"],''); - if (! empty($arrayfields['fd.date']['checked'])) print_liste_field_titre("Date",$_SERVER["PHP_SELF"],"fd.date","",$param,'align="center"',$sortfield,$sortorder); - if (! empty($arrayfields['fd.duree']['checked'])) print_liste_field_titre("Duration",$_SERVER["PHP_SELF"],"fd.duree","",$param,'align="right"',$sortfield,$sortorder); + if (! empty($arrayfields['f.ref']['checked'])) print_liste_field_titre($arrayfields['f.ref']['label'],$_SERVER["PHP_SELF"],"f.ref","",$param,'',$sortfield,$sortorder); + if (! empty($arrayfields['s.nom']['checked'])) print_liste_field_titre($arrayfields['s.nom']['label'],$_SERVER["PHP_SELF"],"s.nom","",$param,'',$sortfield,$sortorder); + if (! empty($arrayfields['f.fk_projet']['checked'])) print_liste_field_titre($arrayfields['f.fk_projet']['label'],$_SERVER["PHP_SELF"],"p.ref","",$param,'',$sortfield,$sortorder); + if (! empty($arrayfields['f.fk_contrat']['checked'])) print_liste_field_titre($arrayfields['f.fk_contrat']['label'],$_SERVER["PHP_SELF"],"p.ref","",$param,'',$sortfield,$sortorder); + if (! empty($arrayfields['f.description']['checked'])) print_liste_field_titre($arrayfields['f.description']['label'],$_SERVER["PHP_SELF"],"f.description","",$param,'',$sortfield,$sortorder); + if (! empty($arrayfields['fd.description']['checked'])) print_liste_field_titre($arrayfields['fd.description']['label'],$_SERVER["PHP_SELF"],''); + if (! empty($arrayfields['fd.date']['checked'])) print_liste_field_titre($arrayfields['fd.date']['label'],$_SERVER["PHP_SELF"],"fd.date","",$param,'align="center"',$sortfield,$sortorder); + if (! empty($arrayfields['fd.duree']['checked'])) print_liste_field_titre($arrayfields['fd.duree']['label'],$_SERVER["PHP_SELF"],"fd.duree","",$param,'align="right"',$sortfield,$sortorder); // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; // Hook fields $parameters=array('arrayfields'=>$arrayfields,'param'=>$param,'sortfield'=>$sortfield,'sortorder'=>$sortorder); $reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; - if (! empty($arrayfields['f.datec']['checked'])) print_liste_field_titre("DateCreationShort",$_SERVER["PHP_SELF"],"f.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); - if (! empty($arrayfields['f.tms']['checked'])) print_liste_field_titre("DateModificationShort",$_SERVER["PHP_SELF"],"f.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); - if (! empty($arrayfields['f.fk_statut']['checked'])) print_liste_field_titre("Status",$_SERVER["PHP_SELF"],"f.fk_statut","",$param,'align="right"',$sortfield,$sortorder); + if (! empty($arrayfields['f.datec']['checked'])) print_liste_field_titre($arrayfields['f.datec']['label'],$_SERVER["PHP_SELF"],"f.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); + if (! empty($arrayfields['f.tms']['checked'])) print_liste_field_titre($arrayfields['f.tms']['label'],$_SERVER["PHP_SELF"],"f.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); + if (! empty($arrayfields['f.fk_statut']['checked'])) print_liste_field_titre($arrayfields['f.fk_statut']['label'],$_SERVER["PHP_SELF"],"f.fk_statut","",$param,'align="right"',$sortfield,$sortorder); print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch '); print "\n"; @@ -477,6 +527,29 @@ if ($resql) print ''; if (! $i) $totalarray['nbfield']++; } + if (! empty($arrayfields['f.fk_projet']['checked'])) + { + print ''; + if ($obj->projectid > 0) { + $projectstatic->ref = $obj->projectref; + $projectstatic->id = $obj->projectid; + $projectstatic->title = $obj->projecttitle; + print $projectstatic->getNomUrl(1, '', 44); + } + print ''; + if (! $i) $totalarray['nbfield']++; + } + if (! empty($arrayfields['f.fk_contrat']['checked'])) + { + print ''; + if ($obj->contractid > 0) { + $contratstatic->ref = $obj->contractref; + $contratstatic->id = $obj->contractid; + print $contratstatic->getNomUrl(1, '', 44); + } + print ''; + if (! $i) $totalarray['nbfield']++; + } if (! empty($arrayfields['f.description']['checked'])) { print ''.dol_trunc(dolGetFirstLineOfText($obj->description),48).''; diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index 3981de21751..5a71e94c2d4 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -31,7 +31,7 @@ */ if (! defined('DOL_APPLICATION_TITLE')) define('DOL_APPLICATION_TITLE','Dolibarr'); -if (! defined('DOL_VERSION')) define('DOL_VERSION','8.0.5'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c +if (! defined('DOL_VERSION')) define('DOL_VERSION','8.0.7'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c if (! defined('EURO')) define('EURO',chr(128)); diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 9198cf3ac22..eed1bbf9eda 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1485,7 +1485,7 @@ class CommandeFournisseur extends CommonOrder $desc=trim($desc); // Check parameters - if ($qty < 1 && ! $fk_product) + if ($qty < 0 && ! $fk_product) { $this->error=$langs->trans("ErrorFieldRequired",$langs->trans("Product")); return -1; @@ -3363,6 +3363,8 @@ class CommandeFournisseurLigne extends CommonOrderLine $error=0; + $this->db->begin(); + // Mise a jour ligne en base $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET"; $sql.= " description='".$this->db->escape($this->desc)."'"; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 3a27690e7ac..ad143e6a091 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -9,7 +9,7 @@ * Copyright (C) 2013 Florian Henry * Copyright (C) 2014-2016 Marcos García * Copyright (C) 2015 Bahfir Abbes - * Copyright (C) 2015 Ferran Marcet + * Copyright (C) 2015-2019 Ferran Marcet * Copyright (C) 2016 Alexandre Spangaro * Copyright (C) 2018 Nicolas ZABOURI * @@ -555,7 +555,7 @@ class FactureFournisseur extends CommonInvoice $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as p ON t.fk_mode_reglement = p.id"; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON t.fk_incoterms = i.rowid'; if ($id) $sql.= " WHERE t.rowid=".$id; - if ($ref) $sql.= " WHERE t.ref='".$this->db->escape($ref)."'"; + if ($ref) $sql.= " WHERE t.ref='".$this->db->escape($ref)."' AND t.entity IN (".getEntity('supplier_invoice').")"; dol_syslog(get_class($this)."::fetch", LOG_DEBUG); $resql=$this->db->query($sql); @@ -1318,7 +1318,8 @@ class FactureFournisseur extends CommonInvoice // We increase stock for product $up_ht_disc=$this->lines[$i]->pu_ht; if (! empty($this->lines[$i]->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP)) $up_ht_disc=price2num($up_ht_disc * (100 - $this->lines[$i]->remise_percent) / 100, 'MU'); - $result=$mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $up_ht_disc, $langs->trans("InvoiceValidatedInDolibarr",$num)); + if ($this->type == FactureFournisseur::TYPE_CREDIT_NOTE) $result=$mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $up_ht_disc, $langs->trans("InvoiceValidatedInDolibarr",$num)); + else $result=$mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $up_ht_disc, $langs->trans("InvoiceValidatedInDolibarr",$num)); if ($result < 0) { $error++; } unset($this->line); } @@ -1441,7 +1442,8 @@ class FactureFournisseur extends CommonInvoice $mouvP = new MouvementStock($this->db); $mouvP->origin = &$this; // We increase stock for product - $result=$mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans("InvoiceBackToDraftInDolibarr", $this->ref)); + if ($this->type == FactureFournisseur::TYPE_CREDIT_NOTE) $result=$mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans("InvoiceBackToDraftInDolibarr", $this->ref)); + else $result=$mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans("InvoiceBackToDraftInDolibarr", $this->ref)); } } } @@ -2579,6 +2581,27 @@ class FactureFournisseur extends CommonInvoice return ($this->statut == self::STATUS_VALIDATED) && ($this->date_echeance < ($now - $conf->facture->fournisseur->warning_delay)); } + + /** + * Is credit note used + * + * @return bool + */ + public function isCreditNoteUsed() + { + global $db; + + $isUsed = false; + + $sql = "SELECT fk_invoice_supplier FROM ".MAIN_DB_PREFIX."societe_remise_except WHERE fk_invoice_supplier_source=".$this->id; + $resql = $db->query($sql); + if(!empty($resql)){ + $obj = $db->fetch_object($resql); + if(!empty($obj->fk_invoice_supplier))$isUsed=true; + } + + return $isUsed; + } } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 41a6d030e16..4143cd0246e 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -2391,14 +2391,11 @@ elseif (! empty($object->id)) } // Create bill - if (! empty($conf->facture->enabled)) + if (! empty($conf->fournisseur->enabled) && ($object->statut >= 2 && $object->statut != 7 && $object->billed != 1)) // statut 2 means approved, 7 means canceled { - if (! empty($conf->fournisseur->enabled) && ($object->statut >= 2 && $object->statut != 7 && $object->billed != 1)) // statut 2 means approved, 7 means canceled + if ($user->rights->fournisseur->facture->creer) { - if ($user->rights->fournisseur->facture->creer) - { - print ''.$langs->trans("CreateBill").''; - } + print ''.$langs->trans("CreateBill").''; } } diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 77fd4b1aa69..dd6fd76a46a 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -245,7 +245,7 @@ if ($action == 'dispatch' && $user->rights->fournisseur->commande->receptionner) // We ask to move a qty if (GETPOST($qty) != 0) { if (! (GETPOST($ent, 'int') > 0)) { - dol_syslog('No dispatch for line ' . $key . ' as no warehouse choosed'); + dol_syslog('No dispatch for line ' . $key . ' as no warehouse was chosen.'); $text = $langs->transnoentities('Warehouse') . ', ' . $langs->transnoentities('Line') . ' ' . ($numline); setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors'); $error ++; @@ -282,7 +282,7 @@ if ($action == 'dispatch' && $user->rights->fournisseur->commande->receptionner) // We ask to move a qty if (GETPOST($qty) > 0) { if (! (GETPOST($ent, 'int') > 0)) { - dol_syslog('No dispatch for line ' . $key . ' as no warehouse choosed'); + dol_syslog('No dispatch for line ' . $key . ' as no warehouse was chosen.'); $text = $langs->transnoentities('Warehouse') . ', ' . $langs->transnoentities('Line') . ' ' . ($numline) . '-' . ($reg[1] + 1); setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors'); $error ++; diff --git a/htdocs/fourn/commande/orderstoinvoice.php b/htdocs/fourn/commande/orderstoinvoice.php index 4c229518eba..82058d087b5 100644 --- a/htdocs/fourn/commande/orderstoinvoice.php +++ b/htdocs/fourn/commande/orderstoinvoice.php @@ -216,7 +216,7 @@ if (($action == 'create' || $action == 'add') && ! $error) { $fk_parent_line = 0; } // FIXME Missing $lines[$i]->ref_supplier and $lines[$i]->label into addline and updateline methods. They are filled when coming from order for example. - $result = $object->addline($desc, $lines[$i]->subprice, $lines[$i]->tva_tx, $lines[$i]->localtax1_tx, $lines[$i]->localtax2_tx, $lines[$i]->qty, $lines[$i]->fk_product, $lines[$i]->remise_percent, $date_start, $date_end, 0, $lines[$i]->info_bits, 'HT', $product_type, -1, false, 0, $lines[$i]->fk_unit); + $result = $object->addline($desc, $lines[$i]->subprice, $lines[$i]->tva_tx, $lines[$i]->localtax1_tx, $lines[$i]->localtax2_tx, $lines[$i]->qty, $lines[$i]->fk_product, $lines[$i]->remise_percent, $date_start, $date_end, 0, $lines[$i]->info_bits, 'HT', $product_type, -1, false, 0, $lines[$i]->fk_unit, $line[$i]->id); if ($result > 0) { $lineid = $result; diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index a294cf3c6ad..9933217a8bb 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -906,7 +906,7 @@ if (empty($reshook)) // FIXME Missing special_code into addline and updateline methods $object->special_code = $lines[$i]->special_code; - + // FIXME Missing $lines[$i]->ref_supplier and $lines[$i]->label into addline and updateline methods. They are filled when coming from order for example. $result = $object->addline( $desc, @@ -2642,11 +2642,14 @@ else else $calculationrule=(empty($conf->global->MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND)?'totalofround':'roundoftotal'); if ($calculationrule == 'totalofround') $calculationrulenum=1; else $calculationrulenum=2; - $s=$langs->trans("ReCalculate").' '; - $s.=''.$langs->trans("Mode1").''; - $s.=' / '; - $s.=''.$langs->trans("Mode2").''; - print $form->textwithtooltip($s, $langs->trans("CalculationRuleDesc",$calculationrulenum).'
'.$langs->trans("CalculationRuleDescSupplier"), 2, 1, img_picto('','help')); + + if ($object->getVentilExportCompta() == 0) { + $s=$langs->trans("ReCalculate").' '; + $s.=''.$langs->trans("Mode1").''; + $s.=' / '; + $s.=''.$langs->trans("Mode2").''; + print $form->textwithtooltip($s, $langs->trans("CalculationRuleDesc",$calculationrulenum).'
'.$langs->trans("CalculationRuleDescSupplier"), 2, 1, img_picto('','help')); + } print '
'; // Amount Local Taxes diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 4b208a99af7..1204d2b50f4 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -496,7 +496,7 @@ if ($resql) print_barre_liste($langs->trans("BillsSuppliers").($socid?' '.$soc->name:''), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit); $topicmail="SendBillRef"; - $modelmail="supplier_invoice_send"; + $modelmail="invoice_supplier_send"; $objecttmp=new FactureFournisseur($db); $trackid='sinv'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; @@ -833,6 +833,7 @@ if ($resql) $facturestatic->date_echeance = $db->jdate($obj->datelimite); $facturestatic->statut = $obj->fk_statut; + $thirdparty->id=$obj->socid; $thirdparty->name=$obj->name; $thirdparty->client=$obj->client; @@ -850,6 +851,14 @@ if ($resql) $totalpay = $paiement + $totalcreditnotes + $totaldeposits; $remaintopay = $obj->total_ttc - $totalpay; + //If invoice has been converted and the conversion has been used, we dont have remain to pay on invoice + if($facturestatic->type == FactureFournisseur::TYPE_CREDIT_NOTE) { + + if($facturestatic->isCreditNoteUsed()){ + $remaintopay=-$facturestatic->getSumFromThisCreditNotesNotUsed(); + } + } + print ''; if (! empty($arrayfields['f.ref']['checked'])) { diff --git a/htdocs/fourn/facture/paiement.php b/htdocs/fourn/facture/paiement.php index 57ca70dfa98..3a47b496394 100644 --- a/htdocs/fourn/facture/paiement.php +++ b/htdocs/fourn/facture/paiement.php @@ -753,7 +753,7 @@ if (empty($action)) $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); $page=GETPOST("page",'int'); - if ($page == -1 || $page == null) { $page = 0 ; } + if (empty($page) || $page == -1) { $page = 0 ; } $offset = $limit * $page ; $pageprev = $page - 1; $pagenext = $page + 1; diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index 2ac212527b3..6de04c5aeed 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -62,15 +62,35 @@ if (! empty($user->rights->holiday->delete)) $candelete=1; $morefilter = 'AND employee = 1'; if (! empty($conf->global->HOLIDAY_FOR_NON_SALARIES_TOO)) $morefilter = ''; +$object = new Holiday($db); +if ($id > 0) +{ + $object->fetch($id); + + // Check current user can read this leave request + $canread = 0; + if (! empty($user->rights->holiday->read_all)) $canread=1; + if (! empty($user->rights->holiday->read) && in_array($object->fk_user, $childids)) $canread=1; + if (! $canread) + { + accessforbidden(); + } +} + + /* * Actions */ +if (GETPOST('cancel', 'alpha')) +{ + $action = ''; +} + // If create a request if ($action == 'create') { - $object = new Holiday($db); // If no right to create a request if (! $cancreate) @@ -82,6 +102,8 @@ if ($action == 'create') if (! $error) { + $object = new Holiday($db); + $db->begin(); $date_debut = dol_mktime(0, 0, 0, GETPOST('date_debut_month'), GETPOST('date_debut_day'), GETPOST('date_debut_year')); @@ -189,7 +211,34 @@ if ($action == 'create') } } -if ($action == 'update') +if ($action == 'update' && GETPOSTISSET('savevalidator') && ! empty($user->rights->holiday->approve)) +{ + $object->fetch($id); + + $object->oldcopy = dol_clone($object); + + $object->fk_validator = GETPOST('valideur', 'int'); + + if ($object->fk_validator != $object->oldcopy->fk_validator) + { + $verif = $object->update($user); + + if ($verif <= 0) + { + setEventMessages($object->error, $object->errors, 'warnings'); + $action='editvalidator'; + } + else + { + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit; + } + } + + $action = ''; +} + +if ($action == 'update' && ! GETPOSTISSET('savevalidator')) { $date_debut = dol_mktime(0, 0, 0, GETPOST('date_debut_month'), GETPOST('date_debut_day'), GETPOST('date_debut_year')); $date_fin = dol_mktime(0, 0, 0, GETPOST('date_fin_month'), GETPOST('date_fin_day'), GETPOST('date_fin_year')); @@ -209,7 +258,6 @@ if ($action == 'update') exit; } - $object = new Holiday($db); $object->fetch($id); // If under validation @@ -293,7 +341,6 @@ if ($action == 'confirm_delete' && GETPOST('confirm') == 'yes' && $user->rights- $db->begin(); - $object = new Holiday($db); $object->fetch($id); // If this is a rough draft, approved, canceled or refused @@ -327,7 +374,6 @@ if ($action == 'confirm_delete' && GETPOST('confirm') == 'yes' && $user->rights- // Si envoi de la demande if ($action == 'confirm_send') { - $object = new Holiday($db); $object->fetch($id); // Si brouillon et créateur @@ -430,7 +476,6 @@ if ($action == 'confirm_send') // Si Validation de la demande if ($action == 'confirm_valid') { - $object = new Holiday($db); $object->fetch($id); // Si statut en attente de validation et valideur = utilisateur @@ -525,7 +570,6 @@ if ($action == 'confirm_refuse' && GETPOST('confirm','alpha') == 'yes') { if (! empty($_POST['detail_refuse'])) { - $object = new Holiday($db); $object->fetch($id); // Si statut en attente de validation et valideur = utilisateur @@ -610,7 +654,6 @@ if ($action == 'confirm_draft' && GETPOST('confirm') == 'yes') { $error = 0; - $object = new Holiday($db); $object->fetch($id); $oldstatus = $object->statut; @@ -641,7 +684,6 @@ if ($action == 'confirm_cancel' && GETPOST('confirm') == 'yes') { $error = 0; - $object = new Holiday($db); $object->fetch($id); // Si statut en attente de validation et valideur = valideur ou utilisateur, ou droits de faire pour les autres @@ -1047,9 +1089,9 @@ else { $head=holiday_prepare_head($object); - if ($action == 'edit' && $object->statut == 1) + if (($action == 'edit' && $object->statut == 1) || ($action == 'editvalidator')) { - $edit = true; + if ($action == 'edit' && $object->statut == 1) $edit = true; print '
'."\n"; print ''."\n"; print ''."\n"; @@ -1089,7 +1131,7 @@ else $starthalfday=($object->halfday == -1 || $object->halfday == 2)?'afternoon':'morning'; $endhalfday=($object->halfday == 1 || $object->halfday == 2)?'morning':'afternoon'; - if(!$edit) + if (!$edit) { print ''; print ''.$langs->trans('DateDebCP').' ('.$langs->trans("FirstDayOfHoliday").')'; @@ -1188,25 +1230,40 @@ else } // Validator - if (!$edit) { + if (!$edit && $action != 'editvalidator') { print ''; print ''; if ($object->statut == 3 || $object->statut == 4) print $langs->trans('ApprovedBy'); else print $langs->trans('ReviewedByCP'); print ''; - print ''.$valideur->getNomUrl(-1).''; + print ''.$valideur->getNomUrl(-1); + $include_users = $object->fetch_users_approver_holiday(); + if (in_array($user->id, $include_users) && $object->statut == Holiday::STATUS_VALIDATED) + { + print ''.img_edit($langs->trans("Edit")).''; + } + print ''; print ''; } else { print ''; print ''.$langs->trans('ReviewedByCP').''; print ''; $include_users = $object->fetch_users_approver_holiday(); + if (! in_array($object->fk_validator, $include_users)) // Add the current validator to the list to not lose it when editing. + { + $include_users[]=$object->fk_validator; + } if (empty($include_users)) print img_warning().' '.$langs->trans("NobodyHasPermissionToValidateHolidays"); else { - $s=$form->select_dolusers($object->fk_validator, "valideur", 1, ($user->admin ? '' : array($user->id)), 0, $include_users); + $s=$form->select_dolusers($object->fk_validator, "valideur", (($action == 'editvalidator') ? 0 : 1), ($user->admin ? '' : array($user->id)), 0, $include_users); print $form->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); } + if ($action == 'editvalidator') + { + print ''; + print ''; + } print ''; print ''; } @@ -1285,20 +1342,21 @@ else print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleSetToDraft"),$langs->trans("ConfirmSetToDraft"),"confirm_draft", '', 1, 1); } - - if ($action == 'edit' && $object->statut == 1) + if (($action == 'edit' && $object->statut == 1) || ($action == 'editvalidator')) { - print '
'; - if ($cancreate && $object->statut == 1) + if ($action == 'edit' && $object->statut == 1) { - print ''; + print '
'; + if ($cancreate && $object->statut == 1) + { + print ''; + } + print '
'; } - print '
'; print '
'; } - if (! $edit) { print '
'; diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 03b2491ab59..db5ca0cf593 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -1132,45 +1132,30 @@ class Holiday extends CommonObject $result = $this->db->query($sql); $typeleaves=$this->getTypes(1,1); - foreach($typeleaves as $key => $val) - { - // On ajoute x jours à chaque utilisateurs - $nb_holiday = $val['newByMonth']; - if (empty($nb_holiday)) $nb_holiday=0; - if ($nb_holiday > 0) + // Update each user counter + foreach ($users as $userCounter) { + $nbDaysToAdd = $typeleaves[$userCounter['type']]['newByMonth']; + if(empty($nbDaysToAdd)) continue; + + dol_syslog("We update leave type id ".$userCounter['type']." for user id ".$userCounter['rowid'], LOG_DEBUG); + + $nowHoliday = $userCounter['nb_holiday']; + $newSolde = $nowHoliday + $nbDaysToAdd; + + // We add a log for each user + $this->addLogCP($user->id, $userCounter['rowid'], $langs->trans('HolidaysMonthlyUpdate'), $newSolde, $userCounter['type']); + + $result = $this->updateSoldeCP($userCounter['rowid'], $newSolde, $userCounter['type'], $langs->trans('HolidaysMonthlyUpdate')); + + if ($result < 0) { - dol_syslog("We update leavefor everybody for type ".$key, LOG_DEBUG); - - $i = 0; - while ($i < $nbUser) - { - $now_holiday = $this->getCPforUser($users[$i]['rowid'], $val['rowid']); - $new_solde = $now_holiday + $nb_holiday; - - // We add a log for each user - $this->addLogCP($user->id, $users[$i]['rowid'], $langs->trans('HolidaysMonthlyUpdate'), $new_solde, $val['rowid']); - - $i++; - } - - // Now we update counter for all users at once - $sql2 = "UPDATE ".MAIN_DB_PREFIX."holiday_users SET"; - $sql2.= " nb_holiday = nb_holiday + ".$nb_holiday; - $sql2.= " WHERE fk_type = ".$val['rowid']; - - $result= $this->db->query($sql2); - - if (! $result) - { - dol_print_error($this->db); - break; - } + $error++; + break; } - else dol_syslog("No change for leave of type ".$key, LOG_DEBUG); } - if ($result) + if (! $error) { $this->db->commit(); return 1; @@ -1495,7 +1480,7 @@ class Holiday extends CommonObject $obj = $this->db->fetch_object($resql); - $tab_result[$i]['rowid'] = $obj->rowid; + $tab_result[$i]['rowid'] = $obj->rowid; // rowid of user $tab_result[$i]['name'] = $obj->lastname; // deprecated $tab_result[$i]['lastname'] = $obj->lastname; $tab_result[$i]['firstname'] = $obj->firstname; @@ -1503,7 +1488,7 @@ class Holiday extends CommonObject $tab_result[$i]['status'] = $obj->statut; $tab_result[$i]['employee'] = $obj->employee; $tab_result[$i]['photo'] = $obj->photo; - $tab_result[$i]['fk_user'] = $obj->fk_user; + $tab_result[$i]['fk_user'] = $obj->fk_user; // rowid of manager //$tab_result[$i]['type'] = $obj->type; //$tab_result[$i]['nb_holiday'] = $obj->nb_holiday; @@ -1522,7 +1507,7 @@ class Holiday extends CommonObject else { // List of vacation balance users - $sql = "SELECT cpu.fk_user, cpu.fk_type, cpu.nb_holiday, u.lastname, u.firstname, u.gender, u.photo, u.employee, u.statut, u.fk_user"; + $sql = "SELECT cpu.fk_user as rowid, cpu.fk_type, cpu.nb_holiday, u.lastname, u.firstname, u.gender, u.photo, u.employee, u.statut, u.fk_user"; $sql.= " FROM ".MAIN_DB_PREFIX."holiday_users as cpu, ".MAIN_DB_PREFIX."user as u"; $sql.= " WHERE cpu.fk_user = u.rowid"; if ($filters) $sql.=$filters; @@ -1541,7 +1526,7 @@ class Holiday extends CommonObject { $obj = $this->db->fetch_object($resql); - $tab_result[$i]['rowid'] = $obj->fk_user; + $tab_result[$i]['rowid'] = $obj->rowid; // rowid of user $tab_result[$i]['name'] = $obj->lastname; // deprecated $tab_result[$i]['lastname'] = $obj->lastname; $tab_result[$i]['firstname'] = $obj->firstname; @@ -1549,9 +1534,9 @@ class Holiday extends CommonObject $tab_result[$i]['status'] = $obj->statut; $tab_result[$i]['employee'] = $obj->employee; $tab_result[$i]['photo'] = $obj->photo; - $tab_result[$i]['fk_user'] = $obj->fk_user; + $tab_result[$i]['fk_user'] = $obj->fk_user; // rowid of manager - $tab_result[$i]['type'] = $obj->type; + $tab_result[$i]['type'] = $obj->fk_type; $tab_result[$i]['nb_holiday'] = $obj->nb_holiday; $i++; diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index 5df3fdb314b..d07ec98ca4c 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -60,6 +60,18 @@ if ($user->societe_id > 0) // Protection if external user } $result = restrictedArea($user, 'holiday', $id, ''); $id = GETPOST('id','int'); +// If we are on the view of a specific user +if ($id > 0) +{ + $canread=0; + if ($id == $user->id) $canread=1; + if (! empty($user->rights->holiday->read_all)) $canread=1; + if (! empty($user->rights->holiday->read) && in_array($id, $childids)) $canread=1; + if (! $canread) + { + accessforbidden(); + } +} // Load variable for pagination $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; diff --git a/htdocs/hrm/admin/admin_establishment.php b/htdocs/hrm/admin/admin_establishment.php index 996ddd58ed3..d28323240dd 100644 --- a/htdocs/hrm/admin/admin_establishment.php +++ b/htdocs/hrm/admin/admin_establishment.php @@ -54,7 +54,7 @@ $sortfield = GETPOST("sortfield"); if (!$sortorder) $sortorder="DESC"; if (!$sortfield) $sortfield="e.rowid"; -if ($page == -1) { +if (empty($page) || $page == -1) { $page = 0 ; } diff --git a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql index cee3a17e061..380c64c28fc 100644 --- a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql +++ b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql @@ -560,3 +560,5 @@ UPDATE llx_advtargetemailing SET fk_element = fk_mailing, type_element='mailing' ALTER TABLE llx_advtargetemailing DROP COLUMN fk_mailing; DROP TABLE llx_ticket_logs; + +ALTER TABLE llx_actioncomm MODIFY COLUMN code varchar(50); diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 22409441eac..dc9fcc86df6 100755 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -199,6 +199,15 @@ delete from llx_element_element where sourcetype='commande' and fk_source not in DELETE FROM llx_actioncomm_resources WHERE fk_actioncomm not in (select id from llx_actioncomm); +-- Fix link on parent that were removed +DROP table tmp_user; +CREATE TABLE tmp_user as (select * from llx_user); +UPDATE llx_user SET fk_user = NULL where fk_user NOT IN (select rowid from tmp_user); + + +update llx_user set fk_user = null where fk_user not in (select rowid from llx_user); + + UPDATE llx_product SET canvas = NULL where canvas = 'default@product'; UPDATE llx_product SET canvas = NULL where canvas = 'service@product'; diff --git a/htdocs/install/mysql/tables/llx_actioncomm.sql b/htdocs/install/mysql/tables/llx_actioncomm.sql index 72321e19db5..231dd3bad1a 100644 --- a/htdocs/install/mysql/tables/llx_actioncomm.sql +++ b/htdocs/install/mysql/tables/llx_actioncomm.sql @@ -29,7 +29,7 @@ create table llx_actioncomm datep2 datetime, -- date end fk_action integer, -- type of action (optional link with id in llx_c_actioncomm or null) - code varchar(32) NULL, -- code of action for automatic action ('AC_OTH_AUTO' for automatic actions, 'AC_EMAILIN_AUTO' for email input, 'AC_xxx' for manual action...) + code varchar(50) NULL, -- code of action for automatic action ('AC_OTH_AUTO' for automatic actions, 'AC_EMAILIN_AUTO' for email input, 'AC_xxx' for manual action...) datec datetime, -- date creation tms timestamp, -- date modification diff --git a/htdocs/install/repair.php b/htdocs/install/repair.php index 1fbda8e8abb..a9ca2f5f321 100644 --- a/htdocs/install/repair.php +++ b/htdocs/install/repair.php @@ -774,7 +774,7 @@ if ($ok && GETPOST('clean_product_stock_batch','alpha')) if ($resql2) { // We update product_stock, so we must field stock into product too. - $sql3='UPDATE llx_product p SET p.stock= (SELECT SUM(ps.reel) FROM llx_product_stock ps WHERE ps.fk_product = p.rowid)'; + $sql3='UPDATE '.MAIN_DB_PREFIX.'product p SET p.stock= (SELECT SUM(ps.reel) FROM '.MAIN_DB_PREFIX.'product_stock ps WHERE ps.fk_product = p.rowid)'; $resql3=$db->query($sql3); if (! $resql3) { diff --git a/htdocs/install/step2.php b/htdocs/install/step2.php index 30b3ff7d64f..a53e5f07ee7 100644 --- a/htdocs/install/step2.php +++ b/htdocs/install/step2.php @@ -451,6 +451,11 @@ if ($action == "set") $buffer=trim($buffer); if ($buffer) { + // Replace the prefix in table names + if ($dolibarr_main_db_prefix != 'llx_') + { + $buffer=preg_replace('/llx_/i',$dolibarr_main_db_prefix,$buffer); + } dolibarr_install_syslog("step2: request: " . $buffer); print "\n"; $resql=$db->query($buffer,0,'dml'); diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 9315769d756..e982b657044 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -691,8 +691,8 @@ function migrate_paiements_orphelins_1($db,$langs,$conf) $sql = "SELECT distinct p.rowid, p.datec, p.amount as pamount, bu.fk_bank, b.amount as bamount,"; $sql.= " bu2.url_id as socid"; $sql.= " FROM (".MAIN_DB_PREFIX."paiement as p, ".MAIN_DB_PREFIX."bank_url as bu, ".MAIN_DB_PREFIX."bank as b)"; - $sql.= " LEFT JOIN llx_paiement_facture as pf ON pf.fk_paiement = p.rowid"; - $sql.= " LEFT JOIN llx_bank_url as bu2 ON (bu.fk_bank=bu2.fk_bank AND bu2.type = 'company')"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON pf.fk_paiement = p.rowid"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."bank_url as bu2 ON (bu.fk_bank=bu2.fk_bank AND bu2.type = 'company')"; $sql.= " WHERE pf.rowid IS NULL AND (p.rowid=bu.url_id AND bu.type='payment') AND bu.fk_bank = b.rowid"; $sql.= " AND b.rappro = 1"; $sql.= " AND (p.fk_facture = 0 OR p.fk_facture IS NULL)"; @@ -818,8 +818,8 @@ function migrate_paiements_orphelins_2($db,$langs,$conf) $sql = "SELECT distinct p.rowid, p.datec, p.amount as pamount, bu.fk_bank, b.amount as bamount,"; $sql.= " bu2.url_id as socid"; $sql.= " FROM (".MAIN_DB_PREFIX."paiement as p, ".MAIN_DB_PREFIX."bank_url as bu, ".MAIN_DB_PREFIX."bank as b)"; - $sql.= " LEFT JOIN llx_paiement_facture as pf ON pf.fk_paiement = p.rowid"; - $sql.= " LEFT JOIN llx_bank_url as bu2 ON (bu.fk_bank = bu2.fk_bank AND bu2.type = 'company')"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON pf.fk_paiement = p.rowid"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."bank_url as bu2 ON (bu.fk_bank = bu2.fk_bank AND bu2.type = 'company')"; $sql.= " WHERE pf.rowid IS NULL AND (p.fk_bank = bu.fk_bank AND bu.type = 'payment') AND bu.fk_bank = b.rowid"; $sql.= " AND (p.fk_facture = 0 OR p.fk_facture IS NULL)"; @@ -1135,7 +1135,7 @@ function migrate_contracts_date1($db,$langs,$conf) print '
'; print ''.$langs->trans('MigrationContractsEmptyDatesUpdate')."
\n"; - $sql="update llx_contrat set date_contrat=tms where date_contrat is null"; + $sql="update ".MAIN_DB_PREFIX."contrat set date_contrat=tms where date_contrat is null"; dolibarr_install_syslog("upgrade2::migrate_contracts_date1"); $resql = $db->query($sql); if (! $resql) dol_print_error($db); @@ -1144,7 +1144,7 @@ function migrate_contracts_date1($db,$langs,$conf) else print $langs->trans('MigrationContractsEmptyDatesNothingToUpdate')."
\n"; - $sql="update llx_contrat set datec=tms where datec is null"; + $sql="update ".MAIN_DB_PREFIX."contrat set datec=tms where datec is null"; dolibarr_install_syslog("upgrade2::migrate_contracts_date1"); $resql = $db->query($sql); if (! $resql) dol_print_error($db); @@ -1235,7 +1235,7 @@ function migrate_contracts_date3($db,$langs,$conf) print '
'; print ''.$langs->trans('MigrationContractsIncoherentCreationDateUpdate')."
\n"; - $sql="update llx_contrat set datec=date_contrat where datec is null or datec > date_contrat"; + $sql="update ".MAIN_DB_PREFIX."contrat set datec=date_contrat where datec is null or datec > date_contrat"; dolibarr_install_syslog("upgrade2::migrate_contracts_date3"); $resql = $db->query($sql); if (! $resql) dol_print_error($db); @@ -1262,7 +1262,7 @@ function migrate_contracts_open($db,$langs,$conf) print '
'; print ''.$langs->trans('MigrationReopeningContracts')."
\n"; - $sql = "SELECT c.rowid as cref FROM llx_contrat as c, llx_contratdet as cd"; + $sql = "SELECT c.rowid as cref FROM ".MAIN_DB_PREFIX."contrat as c, ".MAIN_DB_PREFIX."contratdet as cd"; $sql.= " WHERE cd.statut = 4 AND c.statut=2 AND c.rowid=cd.fk_contrat"; dolibarr_install_syslog("upgrade2::migrate_contracts_open"); $resql = $db->query($sql); @@ -1995,7 +1995,7 @@ function migrate_modeles($db,$langs,$conf) if (count($modellist)==0) { // Aucun model par defaut. - $sql=" insert into llx_document_model(nom,type) values('crabe','invoice')"; + $sql=" insert into ".MAIN_DB_PREFIX."document_model(nom,type) values('crabe','invoice')"; $resql = $db->query($sql); if (! $resql) dol_print_error($db); } @@ -2008,7 +2008,7 @@ function migrate_modeles($db,$langs,$conf) if (count($modellist)==0) { // Aucun model par defaut. - $sql=" insert into llx_document_model(nom,type) values('einstein','order')"; + $sql=" insert into ".MAIN_DB_PREFIX."document_model(nom,type) values('einstein','order')"; $resql = $db->query($sql); if (! $resql) dol_print_error($db); } @@ -2021,7 +2021,7 @@ function migrate_modeles($db,$langs,$conf) if (count($modellist)==0) { // Aucun model par defaut. - $sql=" insert into llx_document_model(nom,type) values('rouget','shipping')"; + $sql=" insert into ".MAIN_DB_PREFIX."document_model(nom,type) values('rouget','shipping')"; $resql = $db->query($sql); if (! $resql) dol_print_error($db); } diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index 4a7ab99ca77..022588139c7 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -83,6 +83,11 @@ InvoiceDeleted=Invoice deleted PRODUCT_CREATEInDolibarr=Product %s created PRODUCT_MODIFYInDolibarr=Product %s modified PRODUCT_DELETEInDolibarr=Product %s deleted +HOLIDAY_CREATEInDolibarr=Request for leave %s created +HOLIDAY_MODIFYInDolibarr=Request for leave %s modified +HOLIDAY_APPROVEInDolibarr=Request for leave %s approved +HOLIDAY_VALIDATEDInDolibarr=Request for leave %s validated +HOLIDAY_DELETEInDolibarr=Request for leave %s deleted EXPENSE_REPORT_CREATEInDolibarr=Expense report %s created EXPENSE_REPORT_VALIDATEInDolibarr=Expense report %s validated EXPENSE_REPORT_APPROVEInDolibarr=Expense report %s approved diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index fae0f88fcc5..02bddd4b923 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -94,6 +94,7 @@ PaymentHigherThanReminderToPay=Payment higher than reminder to pay HelpPaymentHigherThanReminderToPay=Attention, the payment amount of one or more bills is higher than the rest to pay.
Edit your entry, otherwise confirm and think about creating a credit note of the excess received for each overpaid invoices. HelpPaymentHigherThanReminderToPaySupplier=Attention, the payment amount of one or more bills is higher than the rest to pay.
Edit your entry, otherwise confirm and think about creating a credit note of the excess paid for each overpaid invoice. ClassifyPaid=Classify 'Paid' +ClassifyUnPaid=Classify 'Unpaid' ClassifyPaidPartially=Classify 'Paid partially' ClassifyCanceled=Classify 'Abandoned' ClassifyClosed=Classify 'Closed' diff --git a/htdocs/langs/fr_FR/bills.lang b/htdocs/langs/fr_FR/bills.lang index 4b088f8dea2..cbdcd3aefaf 100644 --- a/htdocs/langs/fr_FR/bills.lang +++ b/htdocs/langs/fr_FR/bills.lang @@ -95,6 +95,7 @@ HelpPaymentHigherThanReminderToPay=Attention, le montant de paiement pour une ou HelpPaymentHigherThanReminderToPaySupplier=Attention, le montant de paiement pour une ou plusieurs factures est supérieur au reste à payer.
Corrigez votre saisie, sinon, confirmez et pensez à créer un avoir pour l'excédent pour chaque facture surpayée. ClassifyPaid=Classer 'Payée' ClassifyPaidPartially=Classer 'Payée partiellement' +ClassifyUnPaid=Classer 'Non payée' ClassifyCanceled=Classer 'Abandonnée' ClassifyClosed=Classer 'Fermée' ClassifyUnBilled=Classer 'Non facturée' diff --git a/htdocs/langs/fr_FR/sendings.lang b/htdocs/langs/fr_FR/sendings.lang index 1071d5f23f9..4f4bfc514e2 100644 --- a/htdocs/langs/fr_FR/sendings.lang +++ b/htdocs/langs/fr_FR/sendings.lang @@ -60,6 +60,8 @@ NoProductToShipFoundIntoStock=Aucun produit à expédier n'a été trouver dans WeightVolShort=Poids/vol. ValidateOrderFirstBeforeShipment=Vous devez d'abord valider la commande pour pouvoir créer une expédition. +ShipmentIncrementStockOnDelete=Remettre en stock les éléments de cette expédition + # Sending methods # ModelDocument DocumentModelTyphon=Modèle de bon de réception/livraison complet (logo…) diff --git a/htdocs/langs/fr_FR/stocks.lang b/htdocs/langs/fr_FR/stocks.lang index 5898f7384e5..df9f738f4d8 100644 --- a/htdocs/langs/fr_FR/stocks.lang +++ b/htdocs/langs/fr_FR/stocks.lang @@ -65,7 +65,7 @@ RuleForStockManagementIncrease=Règle de gestion des incrémentations de stock ( DeStockOnBill=Décrémenter les stocks physiques sur validation des factures/avoirs clients DeStockOnValidateOrder=Décrémenterr les stocks physiques sur validation des commandes clients DeStockOnShipment=Décrémenter les stocks physiques sur validation des expéditions -DeStockOnShipmentOnClosing=Décrémenter les stocks phisiques au classement "clôturée" de l'expédition +DeStockOnShipmentOnClosing=Décrémenter les stocks physiques au classement "clôturée" de l'expédition ReStockOnBill=Incrémenter les stocks physiques sur validation des factures/avoirs fournisseurs ReStockOnValidateOrder=Incrémenter les stocks physiques sur approbation des commandes fournisseurs ReStockOnDispatchOrder=Incrémenter les stocks physiques sur ventilation manuelle dans les entrepôts, après réception de la marchandise diff --git a/htdocs/livraison/card.php b/htdocs/livraison/card.php index 2e1c9cb47c1..13a6196d3a3 100644 --- a/htdocs/livraison/card.php +++ b/htdocs/livraison/card.php @@ -570,7 +570,7 @@ else } // Other attributes - if ($action = 'create_delivery') { + if ($action == 'create_delivery') { // copy from expedition $expeditionExtrafields = new Extrafields($db); $expeditionExtrafieldLabels = $expeditionExtrafields->fetch_name_optionals_label($expedition->table_element); @@ -675,7 +675,7 @@ else $mode = ($object->statut == 0) ? 'edit' : 'view'; $line = new LivraisonLigne($db); $line->fetch_optionals($object->lines[$i]->id); - if ($action = 'create_delivery') { + if ($action == 'create_delivery') { $srcLine = new ExpeditionLigne($db); $expeditionLineExtrafields = new Extrafields($db); $expeditionLineExtrafieldLabels = $expeditionLineExtrafields->fetch_name_optionals_label($srcLine->table_element); diff --git a/htdocs/loan/document.php b/htdocs/loan/document.php index f9d17c563fa..69050a5e10d 100644 --- a/htdocs/loan/document.php +++ b/htdocs/loan/document.php @@ -47,7 +47,7 @@ $result = restrictedArea($user, 'loan', $id, '',''); $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); $page = GETPOST("page",'int'); -if ($page == -1) { +if (empty($page) || $page == -1) { $page = 0; } $offset = $conf->liste_limit * $page; diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index ca182c7b337..c73daa011a5 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -383,13 +383,19 @@ if ((! defined('NOCSRFCHECK') && empty($dolibarr_nocsrfcheck) && ! empty($conf-> if (GETPOST('disablemodules','alpha')) $_SESSION["disablemodules"]=GETPOST('disablemodules','alpha'); if (! empty($_SESSION["disablemodules"])) { - $disabled_modules=explode(',',$_SESSION["disablemodules"]); + $modulepartkeys = array('css', 'js', 'tabs', 'triggers', 'login', 'substitutions', 'menus', 'theme', 'sms', 'tpl', 'barcode', 'models', 'societe', 'hooks', 'dir', 'syslog', 'tpllinkable', 'contactelement', 'moduleforexternal'); + + $disabled_modules=explode(',',$_SESSION["disablemodules"]); foreach($disabled_modules as $module) { if ($module) { - if (empty($conf->$module)) $conf->$module=new stdClass(); + if (empty($conf->$module)) $conf->$module=new stdClass(); // To avoid warnings $conf->$module->enabled=false; + foreach($modulepartkeys as $modulepartkey) + { + unset($conf->modules_parts[$modulepartkey][$module]); + } if ($module == 'fournisseur') // Special case { $conf->supplier_order->enabled=0; diff --git a/htdocs/margin/lib/margins.lib.php b/htdocs/margin/lib/margins.lib.php index e1c2d59b7b8..e6089c00d01 100644 --- a/htdocs/margin/lib/margins.lib.php +++ b/htdocs/margin/lib/margins.lib.php @@ -96,6 +96,9 @@ function marges_prepare_head() $head[$h][2] = 'checkMargins'; } + complete_head_from_modules($conf,$langs,null,$head,$h,'margins','remove'); + complete_head_from_modules($conf,$langs,null,$head,$h,'margins'); + return $head; } diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 12f31439985..7593d0c550e 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -90,7 +90,7 @@ class MyObject extends CommonObject 'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), //'date_valid' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>502), - 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>510, 'foreignkey'=>'llx_user.rowid'), + 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>510, 'foreignkey'=>'user.rowid'), 'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'position'=>511), //'fk_user_valid' =>array('type'=>'integer', 'label'=>'UserValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>512), 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'index'=>0, 'position'=>1000), diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 1fe43240305..3eb3847f971 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -12,7 +12,6 @@ * Copyright (C) 2014 Cédric Gross * Copyright (C) 2014-2015 Ferran Marcet * Copyright (C) 2015 Jean-François Ferry - * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Charlie Benke * Copyright (C) 2016 Meziane Sof * @@ -1614,7 +1613,9 @@ else { // TODO change for compatibility with edit in place $typeformat='select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); - print ''.$form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat).''; + print ''; + print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat) : $langs->trans('Type'); + print ''; print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat); print ''; } diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 66f7e288efa..fce619094dc 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3584,8 +3584,10 @@ class Product extends CommonObject { include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; $label.= '
' . $langs->trans('ProductAccountancySellCode') . ': '. length_accountg($this->accountancy_code_sell); - $label.= '
' . $langs->trans('ProductAccountancySellIntraCode') . ': '. length_accountg($this->accountancy_code_sell_export); - $label.= '
' . $langs->trans('ProductAccountancySellExportCode') . ': '. length_accountg($this->accountancy_code_sell_intra); + if(!empty($conf->global->MAIN_FEATURES_LEVEL)) { + $label.= '
' . $langs->trans('ProductAccountancySellIntraCode') . ': '. length_accountg($this->accountancy_code_sell_export); + $label.= '
' . $langs->trans('ProductAccountancySellExportCode') . ': '. length_accountg($this->accountancy_code_sell_intra); + } } if (! empty($conf->accounting->enabled) && $this->status_buy) { diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 7c7619fe0d5..ce829e6b442 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -3,7 +3,7 @@ * Copyright (C) 2004-2018 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2012-2016 Marcos García - * Copyright (C) 2013-2016 Juanjo Menent + * Copyright (C) 2013-2019 Juanjo Menent * Copyright (C) 2013-2015 Raphaël Doursenaud * Copyright (C) 2013 Jean Heimburger * Copyright (C) 2013 Cédric Salvador @@ -50,11 +50,11 @@ $confirm=GETPOST('confirm','alpha'); $toselect = GETPOST('toselect', 'array'); $sall=trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml')); -$search_ref=GETPOST("search_ref"); -$search_barcode=GETPOST("search_barcode"); -$search_label=GETPOST("search_label"); +$search_ref=GETPOST("search_ref",'alpha'); +$search_barcode=GETPOST("search_barcode",'alpha'); +$search_label=GETPOST("search_label", 'alpha'); $search_type = GETPOST("search_type",'int'); -$search_sale = GETPOST("search_sale"); +$search_sale = GETPOST("search_sale", 'int'); $search_categ = GETPOST("search_categ",'int'); $search_tosell = GETPOST("search_tosell", 'int'); $search_tobuy = GETPOST("search_tobuy", 'int'); @@ -159,9 +159,13 @@ $arrayfields=array( //'pfp.ref_fourn'=>array('label'=>$langs->trans("RefSupplier"), 'checked'=>1, 'enabled'=>(! empty($conf->barcode->enabled))), 'p.label'=>array('label'=>$langs->trans("Label"), 'checked'=>1), 'p.fk_product_type'=>array('label'=>$langs->trans("Type"), 'checked'=>0, 'enabled'=>(! empty($conf->produit->enabled) && ! empty($conf->service->enabled))), - 'p.barcode'=>array('label'=>$langs->trans("Gencod"), 'checked'=>($contextpage != 'servicelist'), 'enabled'=>(! empty($conf->barcode->enabled))), + 'p.barcode'=>array('label'=>$langs->trans("Gencod"), 'checked'=>1, 'enabled'=>(! empty($conf->barcode->enabled))), 'p.duration'=>array('label'=>$langs->trans("Duration"), 'checked'=>($contextpage != 'productlist'), 'enabled'=>(! empty($conf->service->enabled))), - 'p.sellprice'=>array('label'=>$langs->trans("SellingPrice"), 'checked'=>1, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES)), + 'p.weight'=>array('label'=>$langs->trans("Weight"), 'checked'=>0, 'enabled'=>(! empty($conf->produit->enabled))), + 'p.length'=>array('label'=>$langs->trans("Length"), 'checked'=>0, 'enabled'=>(! empty($conf->produit->enabled))), + 'p.surface'=>array('label'=>$langs->trans("Surface"), 'checked'=>0, 'enabled'=>(! empty($conf->produit->enabled))), + 'p.volume'=>array('label'=>$langs->trans("Volume"), 'checked'=>0, 'enabled'=>(! empty($conf->produit->enabled))), + 'p.sellprice'=>array('label'=>$langs->trans("SellingPrice"), 'checked'=>1, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES)), 'p.minbuyprice'=>array('label'=>$langs->trans("BuyingPriceMinShort"), 'checked'=>1, 'enabled'=>(! empty($user->rights->fournisseur->lire))), 'p.numbuyprice'=>array('label'=>$langs->trans("BuyingPriceNumShort"), 'checked'=>0, 'enabled'=>(! empty($user->rights->fournisseur->lire))), 'p.pmp'=>array('label'=>$langs->trans("PMPValueShort"), 'checked'=>0, 'enabled'=>(! empty($user->rights->fournisseur->lire))), @@ -261,7 +265,7 @@ else } $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.fk_product_type, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,'; -$sql.= ' p.fk_product_type, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,'; +$sql.= ' p.fk_product_type, p.duration, p.weight, p.length, p.surface, p.volume, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,'; $sql.= ' p.tobatch, p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export, p.accountancy_code_buy,'; $sql.= ' p.datec as date_creation, p.tms as date_update, p.pmp,'; $sql.= ' MIN(pfp.unitprice) as minsellprice'; @@ -316,7 +320,7 @@ $parameters=array(); $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook $sql.=$hookmanager->resPrint; $sql.= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,"; -$sql.= " p.fk_product_type, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,"; +$sql.= " p.fk_product_type, p.duration, p.weight, p.length, p.surface, p.volume, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,"; $sql.= ' p.datec, p.tms, p.entity, p.tobatch, p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export, p.accountancy_code_buy, p.pmp'; if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($search_type === 0)) $sql .= ', pac.rowid'; // Add fields from extrafields @@ -552,9 +556,32 @@ if ($resql) if (! empty($arrayfields['p.duration']['checked'])) { print ''; - print ' '; print ''; } + // Weight + if (! empty($arrayfields['p.weight']['checked'])) + { + print ''; + print ''; + } + // Length + if (! empty($arrayfields['p.length']['checked'])) + { + print ''; + print ''; + } + // Surface + if (! empty($arrayfields['p.surface']['checked'])) + { + print ''; + print ''; + } + // Volume + if (! empty($arrayfields['p.volume']['checked'])) + { + print ''; + print ''; + } // Sell price if (! empty($arrayfields['p.sellprice']['checked'])) { @@ -650,6 +677,10 @@ if ($resql) if (! empty($arrayfields['p.fk_product_type']['checked'])) print_liste_field_titre($arrayfields['p.fk_product_type']['label'], $_SERVER["PHP_SELF"],"p.fk_product_type","",$param,"",$sortfield,$sortorder); if (! empty($arrayfields['p.barcode']['checked'])) print_liste_field_titre($arrayfields['p.barcode']['label'], $_SERVER["PHP_SELF"],"p.barcode","",$param,"",$sortfield,$sortorder); if (! empty($arrayfields['p.duration']['checked'])) print_liste_field_titre($arrayfields['p.duration']['label'], $_SERVER["PHP_SELF"],"p.duration","",$param,'align="center"',$sortfield,$sortorder); + if (! empty($arrayfields['p.weight']['checked'])) print_liste_field_titre($arrayfields['p.weight']['label'], $_SERVER["PHP_SELF"], "p.weight", "", $param, 'align="center"', $sortfield, $sortorder); + if (! empty($arrayfields['p.length']['checked'])) print_liste_field_titre($arrayfields['p.length']['label'], $_SERVER["PHP_SELF"], "p.length", "", $param, 'align="center"', $sortfield, $sortorder); + if (! empty($arrayfields['p.surface']['checked'])) print_liste_field_titre($arrayfields['p.surface']['label'], $_SERVER["PHP_SELF"], "p.surface", "", $param, 'align="center"', $sortfield, $sortorder); + if (! empty($arrayfields['p.volume']['checked'])) print_liste_field_titre($arrayfields['p.volume']['label'], $_SERVER["PHP_SELF"], "p.volume", "", $param, 'align="center"', $sortfield, $sortorder); if (! empty($arrayfields['p.sellprice']['checked'])) print_liste_field_titre($arrayfields['p.sellprice']['label'], $_SERVER["PHP_SELF"],"","",$param,'align="right"',$sortfield,$sortorder); if (! empty($arrayfields['p.minbuyprice']['checked'])) print_liste_field_titre($arrayfields['p.minbuyprice']['label'], $_SERVER["PHP_SELF"],"","",$param,'align="right"',$sortfield,$sortorder); if (! empty($arrayfields['p.numbuyprice']['checked'])) print_liste_field_titre($arrayfields['p.numbuyprice']['label'], $_SERVER["PHP_SELF"],"","",$param,'align="right"',$sortfield,$sortorder); @@ -746,7 +777,7 @@ if ($resql) // Label if (! empty($arrayfields['p.label']['checked'])) { - print ''.dol_trunc($obj->label,40).''; + print ''.dol_trunc($obj->label, 40).''; if (! $i) $totalarray['nbfield']++; } @@ -781,6 +812,39 @@ if ($resql) if (! $i) $totalarray['nbfield']++; } + // Weight + if (! empty($arrayfields['p.weight']['checked'])) + { + print ''; + print $obj->weight; + print ''; + if (! $i) $totalarray['nbfield']++; + } + // Length + if (! empty($arrayfields['p.length']['checked'])) + { + print ''; + print $obj->length; + print ''; + if (! $i) $totalarray['nbfield']++; + } + // Surface + if (! empty($arrayfields['p.surface']['checked'])) + { + print ''; + print $obj->surface; + print ''; + if (! $i) $totalarray['nbfield']++; + } + // Volume + if (! empty($arrayfields['p.volume']['checked'])) + { + print ''; + print $obj->volume; + print ''; + if (! $i) $totalarray['nbfield']++; + } + // Sell price if (! empty($arrayfields['p.sellprice']['checked'])) { diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index 9ee9ab0aead..40793b13153 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -4,6 +4,7 @@ * Copyright (C) 2005-2018 Regis Houssin * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2015 Raphaël Doursenaud + * Copyright (C) 2019 Juanjo Menent * * 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 @@ -40,11 +41,11 @@ $result=restrictedArea($user,'produit|service'); $action=GETPOST('action','alpha'); -$sref=GETPOST("sref"); -$snom=GETPOST("snom"); +$sref=GETPOST("sref", 'alpha'); +$snom=GETPOST("snom", 'alpha'); $sall=trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml')); $type=GETPOST("type","int"); -$search_barcode=GETPOST("search_barcode"); +$search_barcode=GETPOST("search_barcode", 'alpha'); $catid=GETPOST('catid','int'); $toolowstock=GETPOST('toolowstock'); $tosell = GETPOST("tosell"); diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index 3a58924108d..caf17bb6681 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -5,6 +5,7 @@ * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Ferran Marcet + * Copyright (C) 2019 Juanjo Menent * * 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 @@ -42,8 +43,8 @@ $result=restrictedArea($user,'produit|service'); $action=GETPOST('action','alpha'); -$sref=GETPOST("sref"); -$snom=GETPOST("snom"); +$sref=GETPOST("sref", 'alpha'); +$snom=GETPOST("snom", 'alpha'); $sall=trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml')); $type=GETPOST("type","int"); $search_barcode=GETPOST("search_barcode",'alpha'); diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index ecb6a1e385e..0bd7f95373b 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -137,7 +137,6 @@ if ($action == 'order' && isset($_POST['valid'])) if ($qty) { //might need some value checks - $obj = $db->fetch_object($resql); $line = new CommandeFournisseurLigne($db); $line->qty = $qty; $line->fk_product = $idprod; @@ -176,7 +175,7 @@ if ($action == 'order' && isset($_POST['valid'])) $error=$db->lasterror(); dol_print_error($db); } - $db->free($resql); + unset($_POST['fourn' . $i]); } unset($_POST[$i]); @@ -301,6 +300,12 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entre } $sql.= ' '.$sqldesiredtock.' as desiredstockcombined, '.$sqlalertstock.' as seuil_stock_alertecombined,'; $sql.= ' SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").') as stock_physique'; + +// Add fields from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; + $sql.= ' FROM ' . MAIN_DB_PREFIX . 'product as p'; $sql.= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product_stock as s'; $sql.= ' ON (p.rowid = s.fk_product AND s.fk_entrepot IN (SELECT ent.rowid FROM '.MAIN_DB_PREFIX.'entrepot AS ent WHERE ent.entity IN('.getEntity('stock').')))'; @@ -310,6 +315,12 @@ if ($fk_supplier > 0) { if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_warehouse_properties AS pse ON (p.rowid = pse.fk_product AND pse.fk_entrepot = '.$fk_entrepot.')'; } + +// Add fields from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListJoin',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; + $sql.= ' WHERE p.entity IN (' . getEntity('product') . ')'; if ($sall) $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall); // if the type is not 1, we show all products (type = 0,2,3) @@ -390,6 +401,11 @@ if ($usevirtualstock) } } +// Add where from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; + $sql.= $db->order($sortfield,$sortorder); $sql.= $db->plimit($limit + 1, $offset); @@ -453,9 +469,15 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) print '
'; print $langs->trans('Supplier').' '.$form->select_company($fk_supplier, 'fk_supplier', 'fournisseur=1', 1); print '
'; + +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldPreListTitle',$parameters); // Note that $action and $object may have been modified by hook +if (empty($reshook)) print $hookmanager->resPrint; + print '
'; print ''; print '
'; + print ''; if ($sref || $snom || $sall || $salert || $draftorder || GETPOST('search', 'alpha')) { @@ -537,6 +559,12 @@ print '' . $langs->trans('AlertOnly') . '& print '' . $langs->trans('IncludeAlsoDraftOrders') . ' '; print ' '; print ''; + +// Fields from hook +$parameters=array('param'=>$param,'sortfield'=>$sortfield,'sortorder'=>$sortorder); +$reshook=$hookmanager->executeHooks('printFieldListOption',$parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + $searchpicto=$form->showFilterAndCheckAddButtons(0); print $searchpicto; print ''; @@ -554,6 +582,12 @@ print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], 'stock_physique', $pa print_liste_field_titre('Ordered', $_SERVER["PHP_SELF"], '', $param, '', 'align="right"', $sortfield, $sortorder); print_liste_field_titre('StockToBuy', $_SERVER["PHP_SELF"], '', $param, '', 'align="right"', $sortfield, $sortorder); print_liste_field_titre('SupplierRef', $_SERVER["PHP_SELF"], '', $param, '', 'align="right"', $sortfield, $sortorder); + +// Hook fields +$parameters=array('param'=>$param,'sortfield'=>$sortfield,'sortorder'=>$sortorder); +$reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + print "\n"; while ($i < ($limit ? min($num, $limit) : $num)) @@ -680,6 +714,11 @@ while ($i < ($limit ? min($num, $limit) : $num)) // Supplier print ''. $form->select_product_fourn_price($prod->id, 'fourn'.$i, $fk_supplier).''; + // Fields from hook + $parameters=array( 'objp'=>$objp); + $reshook=$hookmanager->executeHooks('printFieldListValue',$parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + print ''; } $i++; diff --git a/htdocs/product/stock/replenishorders.php b/htdocs/product/stock/replenishorders.php index 942ca82bc04..34dfc2d9d6e 100644 --- a/htdocs/product/stock/replenishorders.php +++ b/htdocs/product/stock/replenishorders.php @@ -2,6 +2,7 @@ /* * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2014 Regis Houssin + * Copyright (C) 2019 Juanjo Menent * * 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 @@ -152,7 +153,9 @@ if (GETPOST('statut', 'int')) { $sql .= ' GROUP BY cf.rowid, cf.ref, cf.date_creation, cf.fk_statut'; $sql .= ', cf.total_ttc, cf.fk_user_author, u.login, s.rowid, s.nom'; $sql .= $db->order($sortfield, $sortorder); -$sql .= $db->plimit($limit+1, $offset); +if (! $sproduct) { + $sql .= $db->plimit($limit+1, $offset); +} $resql = $db->query($sql); if ($resql) @@ -268,7 +271,7 @@ if ($resql) $userstatic = new User($db); - while ($i < min($num,$conf->liste_limit)) + while ($i < min($num,$sproduct?$num:$conf->liste_limit)) { $obj = $db->fetch_object($resql); diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php index 3d2e1c99e9b..4a9f23301a8 100644 --- a/htdocs/product/stock/tpl/stockcorrection.tpl.php +++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php @@ -100,7 +100,7 @@ if (empty($conf) || ! is_object($conf)) { print ''.$langs->trans('Project').''; print ''; - $formproject->select_projects(0, '', 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, 'maxwidth300'); + $formproject->select_projects(-1, '', 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, 'maxwidth300'); print ''; } print ''; diff --git a/htdocs/projet/activity/perday.php b/htdocs/projet/activity/perday.php index 26b7179b74c..473558f9606 100644 --- a/htdocs/projet/activity/perday.php +++ b/htdocs/projet/activity/perday.php @@ -37,6 +37,8 @@ require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; // Load translation files required by the page $langs->loadLangs(array('projects','users','companies')); +$hookmanager->initHooks(array('timesheetperdaycard')); + $action=GETPOST('action','aZ09'); $mode=GETPOST("mode",'alpha'); $id=GETPOST('id','int'); diff --git a/htdocs/projet/activity/perweek.php b/htdocs/projet/activity/perweek.php index bf6a95c9e0e..d1434e5e3fb 100644 --- a/htdocs/projet/activity/perweek.php +++ b/htdocs/projet/activity/perweek.php @@ -37,6 +37,8 @@ require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; // Load translation files required by the page $langs->loadLangs(array('projects','users','companies')); +$hookmanager->initHooks(array('timesheetperweekcard')); + $action=GETPOST('action','aZ09'); $mode=GETPOST("mode",'alpha'); $id=GETPOST('id','int'); diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index a704c7d641e..9caa873f170 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -338,7 +338,7 @@ class Project extends CommonObject if (file_exists($olddir)) { include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; - $res=dol_move($olddir, $newdir); + $res=@rename($olddir, $newdir); if (! $res) { $langs->load("errors"); @@ -537,7 +537,7 @@ class Project extends CommonObject } elseif ($type == 'project_task') { - $sql = "SELECT DISTINCT pt.rowid FROM " . MAIN_DB_PREFIX . "projet_task as pt, " . MAIN_DB_PREFIX . "projet_task_time as ptt WHERE pt.rowid = ptt.fk_task AND pt.fk_projet IN (". $ids .")"; + $sql = "SELECT DISTINCT pt.rowid FROM " . MAIN_DB_PREFIX . "projet_task as pt WHERE pt.fk_projet IN (". $ids .")"; } elseif ($type == 'project_task_time') // Case we want to duplicate line foreach user { @@ -723,10 +723,10 @@ class Project extends CommonObject return -1; } } - + /** * Delete tasks with no children first, then task with children recursively - * + * * @param User $user User * @return int <0 if KO, 1 if OK */ @@ -754,7 +754,7 @@ class Project extends CommonObject { if (count($this->lines)) $this->deleteTasks($this->lines); } - + return 1; } diff --git a/htdocs/projet/index.php b/htdocs/projet/index.php index 906cb3783f1..3ca6296f81d 100644 --- a/htdocs/projet/index.php +++ b/htdocs/projet/index.php @@ -57,7 +57,7 @@ $form=new Form($db); $formfile=new FormFile($db); $projectset = ($mine?$mine:(empty($user->rights->projet->all->lire)?0:2)); -$projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, $projetset, 1); +$projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, $projectset, 1); //var_dump($projectsListId); @@ -258,7 +258,7 @@ $sql = "SELECT COUNT(p.rowid) as nb, SUM(p.opp_amount)"; $sql.= ", s.nom as name, s.rowid as socid"; $sql.= " FROM ".MAIN_DB_PREFIX."projet as p"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid"; -$sql.= " WHERE p.entity IN (".getEntity('project', $conf->entity).")"; +$sql.= " WHERE p.entity IN (".getEntity('project').")"; $sql.= " AND p.fk_statut = 1"; if ($mine || empty($user->rights->projet->all->lire)) $sql.= " AND p.rowid IN (".$projectsListId.")"; // If we have this test true, it also means projectset is not 2 if ($socid) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")"; diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 37caf6f4e69..e806580ffea 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -6,6 +6,7 @@ * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2015 Claudio Aschieri * Copyright (C) 2018 Ferran Marcet + * Copyright (C) 2019 Juanjo Menent * * 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 @@ -72,9 +73,9 @@ $pagenext = $page + 1; $search_all=GETPOST('search_all', 'alphanohtml') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'); $search_categ=GETPOST("search_categ",'alpha'); -$search_ref=GETPOST("search_ref"); -$search_label=GETPOST("search_label"); -$search_societe=GETPOST("search_societe"); +$search_ref=GETPOST("search_ref",'alpha'); +$search_label=GETPOST("search_label",'alpha'); +$search_societe=GETPOST("search_societe",'alpha'); $search_year=GETPOST("search_year"); $search_status=GETPOST("search_status",'int'); $search_opp_status=GETPOST("search_opp_status",'alpha'); @@ -709,8 +710,8 @@ while ($i < min($num,$limit)) // Title if (! empty($arrayfields['p.title']['checked'])) { - print ''; - print dol_trunc($obj->title,80); + print ''; + print dol_trunc($obj->title, 80); print ''; if (! $i) $totalarray['nbfield']++; } diff --git a/htdocs/resource/class/dolresource.class.php b/htdocs/resource/class/dolresource.class.php index 7c3999db7c9..43e697a101a 100644 --- a/htdocs/resource/class/dolresource.class.php +++ b/htdocs/resource/class/dolresource.class.php @@ -530,13 +530,13 @@ class Dolresource extends CommonObject if ($limit) $sql.= $this->db->plimit($limit, $offset); dol_syslog(get_class($this)."::fetch_all", LOG_DEBUG); + $this->lines=array(); $resql=$this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); if ($num) { - $this->lines=array(); while ($obj = $this->db->fetch_object($resql)) { $line = new Dolresource($this->db); @@ -829,6 +829,8 @@ class Dolresource extends CommonObject $sql .= ' ORDER BY resource_type'; dol_syslog(get_class($this)."::getElementResources", LOG_DEBUG); + + $resources = array(); $resql = $this->db->query($sql); if ($resql) { @@ -879,7 +881,7 @@ class Dolresource extends CommonObject { global $langs; - if (count($this->cache_code_type_resource)) return 0; // Cache deja charge + if (is_array($this->cache_code_type_resource) && count($this->cache_code_type_resource)) return 0; // Cache deja charge $sql = "SELECT rowid, code, label, active"; $sql.= " FROM ".MAIN_DB_PREFIX."c_type_resource"; diff --git a/htdocs/resource/class/html.formresource.class.php b/htdocs/resource/class/html.formresource.class.php index 19bed957f74..06d253493c0 100644 --- a/htdocs/resource/class/html.formresource.class.php +++ b/htdocs/resource/class/html.formresource.class.php @@ -85,8 +85,6 @@ class FormResource $out = '
'; $out.= ''; } - //$out.= ''; - //$out.= ''; if ($resourcestat) { diff --git a/htdocs/resource/list.php b/htdocs/resource/list.php index 68f91327f6d..f6e81b89773 100644 --- a/htdocs/resource/list.php +++ b/htdocs/resource/list.php @@ -97,8 +97,7 @@ if (empty($arch)) $arch = 0; $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; $page = GETPOST("page"); -$page = is_numeric($page) ? $page : 0; -$page = $page == -1 ? 0 : $page; +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 $offset = $limit * $page ; $pageprev = $page - 1; $pagenext = $page + 1; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 412bf46b082..87c4956e48e 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3727,7 +3727,7 @@ class Societe extends CommonObject $alreadypayed=price2num($paiement + $creditnotes + $deposits,'MT'); $remaintopay=price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits,'MT'); */ - if ($mode == 'supplier') $sql = "SELECT rowid, total_ht as total_ht, total_ttc, paye, fk_statut, close_code FROM ".MAIN_DB_PREFIX.$table." as f"; + if ($mode == 'supplier') $sql = "SELECT rowid, total_ht as total_ht, total_ttc, paye, type, fk_statut, close_code FROM ".MAIN_DB_PREFIX.$table." as f"; else $sql = "SELECT rowid, total as total_ht, total_ttc, paye, fk_statut, close_code FROM ".MAIN_DB_PREFIX.$table." as f"; $sql .= " WHERE fk_soc = ". $this->id; if ($mode == 'supplier') { @@ -3754,7 +3754,11 @@ class Societe extends CommonObject $tmpobject=new Facture($this->db); } while($obj=$this->db->fetch_object($resql)) { - $tmpobject->id=$obj->rowid; + $tmpobject->id=$obj->rowid; + + + + if ($obj->fk_statut != 0 // Not a draft && ! ($obj->fk_statut == 3 && $obj->close_code == 'replaced') // Not a replaced invoice ) @@ -3771,8 +3775,14 @@ class Societe extends CommonObject $paiement = $tmpobject->getSommePaiement(); $creditnotes = $tmpobject->getSumCreditNotesUsed(); $deposits = $tmpobject->getSumDepositsUsed(); + $outstandingOpened+=$obj->total_ttc - $paiement - $creditnotes - $deposits; } + + //if credit note is converted but not used + if($mode == 'supplier' && $obj->type == FactureFournisseur::TYPE_CREDIT_NOTE && $tmpobject->isCreditNoteUsed())$outstandingOpened-=$tmpobject->getSumFromThisCreditNotesNotUsed(); + + } return array('opened'=>$outstandingOpened, 'total_ht'=>$outstandingTotal, 'total_ttc'=>$outstandingTotalIncTax); // 'opened' is 'incl taxes' } diff --git a/htdocs/societe/notify/index.php b/htdocs/societe/notify/index.php index 3326e431178..c1d99620b89 100644 --- a/htdocs/societe/notify/index.php +++ b/htdocs/societe/notify/index.php @@ -42,7 +42,7 @@ if ($sortfield == "") $sortfield="s.nom"; } -if ($page == -1 || $page == null) { $page = 0 ; } +if (empty($page) || $page == -1) { $page = 0 ; } $offset = $conf->liste_limit * $page ; $pageprev = $page - 1; diff --git a/htdocs/user/card.php b/htdocs/user/card.php index adcf094e7a4..460e345131c 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -309,12 +309,12 @@ if (empty($reshook)) { { $error = 0; - if (!$_POST["lastname"]) { + if (! GETPOST("lastname", 'alpha')) { setEventMessages($langs->trans("NameNotDefined"), null, 'errors'); $action = "edit"; // Go back to create page $error ++; } - if (!$_POST["login"]) { + if (! GETPOST("login", 'alpha')) { setEventMessages($langs->trans("LoginNotDefined"), null, 'errors'); $action = "edit"; // Go back to create page $error ++; diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index c3d18b889e7..f05dd0723b4 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -844,8 +844,10 @@ class Website extends CommonObject } foreach($listofpages as $pageid => $objectpageold) { - $line = 'INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, title, description, keyword, status, date_creation, tms, lang, import_key, grabbed_from, content)'; - $line.= " VALUES("; + // Warning: We must keep llx_ here. It is a generic SQL. + $line = 'INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, title, description, keyword, status, date_creation, tms, lang, import_key, grabbed_from, content)'; + + $line.= " VALUES("; $line.= $objectpageold->newid."+__MAXROWID__, "; $line.= ($objectpageold->newfk_page ? $this->db->escape($objectpageold->newfk_page)."+__MAXROWID__" : "null").", "; $line.= "__WEBSITE_ID__, ";