From 8a786758b7d9fb7e3abb50044f8da0a9605ff37c Mon Sep 17 00:00:00 2001 From: John BOTELLA Date: Thu, 4 Apr 2019 11:45:54 +0200 Subject: [PATCH 001/324] NEW browser mobil app support --- htdocs/main.inc.php | 13 ++++ .../theme/common/appli_dolibarr_256x256.png | Bin 0 -> 4008 bytes htdocs/theme/eldy/manifest.json.php | 57 ++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 htdocs/theme/common/appli_dolibarr_256x256.png create mode 100644 htdocs/theme/eldy/manifest.json.php diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 74069429043..25a64966b79 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1234,6 +1234,19 @@ function top_htmlhead($head, $title = '', $disablejs = 0, $disablehead = 0, $arr //if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print ''."\n"; //if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print ''."\n"; + // Mobile appli like icon + $manifest=dol_buildpath('/theme/'.$conf->theme.'/manifest.json.php', 1, 1); + if(!empty($manifest)){ + print ''."\n"; + } + + if(!empty($conf->global->THEME_ELDY_TOPMENU_BACK1)) { + // TODO: use auto theme color switch + print '' . "\n"; + } + + + // Auto refresh page if (GETPOST('autorefresh', 'int') > 0) print ''; diff --git a/htdocs/theme/common/appli_dolibarr_256x256.png b/htdocs/theme/common/appli_dolibarr_256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..970f841001bbd165a955f094f6505a75fe7b5fb6 GIT binary patch literal 4008 zcmYk92{hDS8^`aA8OzMr*C9-0mu#sJ1|v(BtXU%aHpsptHKc^>dm)9iShAC7?1U5% z*(S2r*t7Fa@Bjav^Pcm&zx&*KzUQ8M?sJ##C;FFe@@e2E(XMj>sSs!8zo-#J14CZ>FyMennE3sTh75Q}gY2&)2f z>M0GJq1pBAE<{m5A<>-{Se^;7%%VJi(Q%Cnmp7eoPxUGTP#G z6>sA(#C>KX9pE@1p$Ul#zYDUd_}`k}-f8j)~7prZz805WYsA_Ncs zNDQI-sYVa`r$H)%sloror1Ml5ILL()elT8zLMY2f%%{Q9!)zlUSUMQEiv}AiSZV-- zxc(0GkAfn?_%Q++uyejS*g)*B?w^@a{*pqO>&@n(hRrDh&kM%ti(RbGX0(b{%&~>u zd8?RhJ;8vlof#+^b-$41c{x^(t(?v09t;~I3}Yp>%4&W*QuMB8bH)cXj1EuQdCFLt z9+Rk+$T8IuN@;&!x1@%((=%(_O9I2>M!__Bw{(tpHWS|7vez$fYR+%!fYcy0 z+nsH?G@UFyo{!%hf*egQ1f5WD840U+U+@mDbdTksV&>DPhFK!J(PdS5_E z&JA9%$=d}Z9@Y6)XPpQQiIAOUgEHO}79Rt%*B@$Y-ZxFy&sbBBAlptWEA&wr4_-L* zX zi|TulIqp`SVN$z(em)NdRoV#+Rk}MBS=}?w@WG=WE{rCW(&@)Bs8ZMEM#6%pj8l{M$)( z&ZV%+2r3eemCSywvvm;0`n2BVgdcnr5R5q{AJ_PHpDVd6AqmMlfHVq;hb=5Q$%ef@ zS0Nga2*L7u`q=O68}!p{4s|=TcWKnvReccYS4sr5#P zho|@PAR*vReVDGAt~tgm{4K0al#-GkqZbBk;HSKd32j;O3epN+`GvSvAHz&O(zrYl z;NhEO8NKk1_fta6+@Jc4A+fkTvYUIF+134!Q26dLRak)Pojt(M%X4a-TxH>qGP%DL z9Mw(@(c)`pt@rxowymG29&zwo?J%E)26ul)SOZ?vPM^M)GIuR+5V0ZjqWJjF85k(V zv02OY2@S_{njT}K3%W?mYj#F9A)j zqpRcgH!K=cvrb5d;C^lP!nFB2IMCB73UbplNyZ<6x$DW|9 zRobmBX*cZ~h{=w-^8!K(>cX?1FKLK3?RfXlxi$8t%A;@b0U8HwSusQZl8N-tD&lHJ z`(VC0mB2}Y^s6MxxEM4KB^i7OF>Zd#-S(`3TiUocgNUr|q$(ZEz&=4s2)H*o{;HA) zoqrM*GMoGvJFF*NaElR*<-p?t=VOmY0!SY4!>gT)MO$-z*~qUdjM&oX=R5left+UN zSU8EFn<1)4x3ZD2@r3HJwO=%2PrmoH&79C!wBdtc#4YvG*_XGCIkD4BI#BHH=_tfP zXCO(pJ$^3dzxwZ#-tfCDb-A@G;iQ_tnFl${|SXA$_ozR_<0#t zPo4zfn~*A;1R+&F`IYB+Lv{k^{ahS%qI`e^uL(R)I0@o?HvQ7TfSfEA`2|JF|7NtH z?Fh0QepL;ibj4rVMTB>jk395>9(32DCDhOfg`SCwgxUUnfzHe`YlcxJ3~B@zpVPs3 zD_s?fZo1Q zoFNEI1k#v=6FSi>zYJuhSmSD6r~w(_Q;{#hBWIS{m*t!$#zV7Ah?ra<9nS(pkj5l&(9ZK8TUl1zj{QRh-bY5Q0<3S1uoARmqVT@Z=v{EQp z+sJV0asiLe`IpyO3HIbjJ4c5%FY)=l=S2`s7Rh}4$_jEZ9>KE#CAd@J;Ai)=V#nvc z<dp!?SG*`xzqQnRrvOZS6oLnF>L-yg#6p)eOxb=t*aUl@ilRYXOsQ!6yvvTJ#5 z93NN>$QnNv(agN@1zW^ejt~%sqxgRAkGFKU`I)F%P~|A&=mhvTZ60qwZG6)8s^?pa zbI{L>p}}YxXd<0hq3`U#XsbO9Yr@9neajaRH9lZ<(vgXs=deuqoTt0sCX8}U9w zVeAH`Tg;TCgIvw?OrS?+%S;5$&$Li!$%v_zSf0ag4k9bM$lLG5LJh17{^XpZ(n@g4 z((aeYKB2zlwvGSdRLS30R=~jy!=O`jG=}wjuFS>tYsIJ9A56{JV5$KEqD6f(XRfq( zb80-7S-jff*tbbJ(?Ckh<9;4bTA7XF>|7+;A-VE$+fo&`HomTAG}YJ@vvVJDwgr)= zaHPbQk)W?ABW-VDguATsbs<%RKJME~RCXWDhDNeDStQ&`z@tv{0d*TaT}%QhK7m&M z5la6d%J5C9OoMKe@p#<|s&51Xw)5D(_D`tHzCO06vJ|J~R&9UbH$0NZ|8s@+XOYWO z%X-~am40%zy~2DR7UVJ$E+3M5bvIj0cOAcJSCrdb5LrD_B>6R4qU1E?RbU-Y$h+Qn zc>1cy@a=#|-+9s@ATtZTTYF8(81E%3eR;K1Eb-n!j^1$<#ex=HG`)UkZ6gW;b!XVD zW7v!ygx)W58!| zihJY>@lRtR*|3R5#a@!hh&Z(PcEo1ado12TWBo`b2|_gOl6({Dyp>@}|GVOY5rlE$ zB>XzVo4{euo)EuQn}*iz)}Uw4k38g*DTYVSbOHz19=Q%(4ZwzEW5am|qISTXb%ZM7;Oqe8qi!H7-rBfmH6Y<$*tPhl7MAo#elI5UT=auf1 z<@DSmBw-V2zncCv{D*hURIbR8|8{r&?rd;^xULihKH|2F+fA()=2tFSinPxl458si zB>xzX@fFI-9BSElRxOJ1#-aMEvq2%83^}5*StSchwAi^3-cR=GGo!K9^%`ly zF{p~$SC~$0n>bb0?C2P#(6ERs*Rchz;qa9l>IN}{mX0=3S$&x62kyi6rd=Ad;e9?0&t{*;dI9kQ2%AdyMIN0<61Nj1sEzo zbfYF7F#bCVg)%8biKRg0Rp>JSy&Vcf01-y@FK_-OJw9+#8!pvMvAB1EN!SA}-vI+V Q3RVMc4Sigxnr*~?0Ios=rvLx| literal 0 HcmV?d00001 diff --git a/htdocs/theme/eldy/manifest.json.php b/htdocs/theme/eldy/manifest.json.php new file mode 100644 index 00000000000..ef5459cf600 --- /dev/null +++ b/htdocs/theme/eldy/manifest.json.php @@ -0,0 +1,57 @@ + + * Copyright (C) 2006 Rodolphe Quiedeville + * Copyright (C) 2007-2017 Regis Houssin + * Copyright (C) 2011 Philippe Grand + * Copyright (C) 2012 Juanjo Menent + * Copyright (C) 2018 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FI8TNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/theme/eldy/manifest.json.php + * \brief File for The Web App + */ + +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // Not disabled because need to load personalized language +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); // Not disabled to increase speed. Language code is found on url. +if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Not disabled because need to do translations +if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', 1); +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', 1); +if (! defined('NOLOGIN')) define('NOLOGIN', 1); // File must be accessed by logon page so without login +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU',1); // We need top menu content +if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', 1); +if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); + +require_once __DIR__.'/../../main.inc.php'; + +$appli=constant('DOL_APPLICATION_TITLE'); +if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE; + +?> +{ + "name": "", + "icons": [ + { + "src": "", + "sizes": "256x256", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} From 788e7a40a8f784e221b1f2f3204408af6a9f8977 Mon Sep 17 00:00:00 2001 From: John BOTELLA Date: Thu, 4 Apr 2019 11:47:07 +0200 Subject: [PATCH 002/324] remove space --- htdocs/main.inc.php | 2 -- htdocs/theme/eldy/manifest.json.php | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 25a64966b79..9b12f892ea9 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1245,8 +1245,6 @@ function top_htmlhead($head, $title = '', $disablejs = 0, $disablehead = 0, $arr print '' . "\n"; } - - // Auto refresh page if (GETPOST('autorefresh', 'int') > 0) print ''; diff --git a/htdocs/theme/eldy/manifest.json.php b/htdocs/theme/eldy/manifest.json.php index ef5459cf600..afaa3a4258c 100644 --- a/htdocs/theme/eldy/manifest.json.php +++ b/htdocs/theme/eldy/manifest.json.php @@ -54,4 +54,4 @@ if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_AP "theme_color": "#ffffff", "background_color": "#ffffff", "display": "standalone" -} +} \ No newline at end of file From face07ece1577311119b2df0bf2243003a62f9ba Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Wed, 1 May 2019 15:15:20 +0200 Subject: [PATCH 003/324] new constant PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC --- htdocs/product/class/product.class.php | 87 +++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 3796f5b022e..6afd42e3aae 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2410,6 +2410,28 @@ class Product extends CommonObject $this->stats_propale['nb']=$obj->nb; $this->stats_propale['rows']=$obj->nb_rows; $this->stats_propale['qty']=$obj->qty?$obj->qty:0; + + // if it's a virtual product, maybe it is in proposal by extension + if (! empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) { + $TFather = $this->getFather(); + if (is_array($TFather) && !empty($TFather)) { + foreach($TFather as &$fatherData) { + $pFather = new Product($this->db); + $pFather->id = $fatherData['id']; + $qtyCoef = $fatherData['qty']; + + if ($fatherData['incdec']) { + $pFather->load_stats_propale($socid); + + $this->stats_propale['customers']+=$pFather->stats_propale['customers']; + $this->stats_propale['nb']+=$pFather->stats_propale['nb']; + $this->stats_propale['rows']+=$pFather->stats_propale['rows']; + $this->stats_propale['qty']+=$pFather->stats_propale['qty'] * $qtyCoef; + } + } + } + } + return 1; } else @@ -2512,7 +2534,7 @@ class Product extends CommonObject $this->stats_commande['qty']=$obj->qty?$obj->qty:0; // if it's a virtual product, maybe it is in order by extension - if (! empty($conf->global->ORDER_ADD_ORDERS_WITH_PARENT_PROD_IF_INCDEC)) { + if (! empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) { $TFather = $this->getFather(); if (is_array($TFather) && !empty($TFather)) { foreach($TFather as &$fatherData) { @@ -2665,6 +2687,27 @@ class Product extends CommonObject $this->stats_expedition['nb']=$obj->nb; $this->stats_expedition['rows']=$obj->nb_rows; $this->stats_expedition['qty']=$obj->qty?$obj->qty:0; + + // if it's a virtual product, maybe it is in sending by extension + if (! empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) { + $TFather = $this->getFather(); + if (is_array($TFather) && !empty($TFather)) { + foreach($TFather as &$fatherData) { + $pFather = new Product($this->db); + $pFather->id = $fatherData['id']; + $qtyCoef = $fatherData['qty']; + + if ($fatherData['incdec']) { + $pFather->load_stats_sending($socid, $filtrestatut, $forVirtualStock); + + $this->stats_expedition['customers']+=$pFather->stats_expedition['customers']; + $this->stats_expedition['nb']+=$pFather->stats_expedition['nb']; + $this->stats_expedition['rows']+=$pFather->stats_expedition['rows']; + $this->stats_expedition['qty']+=$pFather->stats_expedition['qty'] * $qtyCoef; + } + } + } + } return 1; } else @@ -2762,6 +2805,27 @@ class Product extends CommonObject $this->stats_contrat['nb']=$obj->nb; $this->stats_contrat['rows']=$obj->nb_rows; $this->stats_contrat['qty']=$obj->qty?$obj->qty:0; + + // if it's a virtual product, maybe it is in contract by extension + if (! empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) { + $TFather = $this->getFather(); + if (is_array($TFather) && !empty($TFather)) { + foreach($TFather as &$fatherData) { + $pFather = new Product($this->db); + $pFather->id = $fatherData['id']; + $qtyCoef = $fatherData['qty']; + + if ($fatherData['incdec']) { + $pFather->load_stats_contrat($socid); + + $this->stats_contrat['customers']+=$pFather->stats_contrat['customers']; + $this->stats_contrat['nb']+=$pFather->stats_contrat['nb']; + $this->stats_contrat['rows']+=$pFather->stats_contrat['rows']; + $this->stats_contrat['qty']+=$pFather->stats_contrat['qty'] * $qtyCoef; + } + } + } + } return 1; } else @@ -2811,6 +2875,27 @@ class Product extends CommonObject $this->stats_facture['nb']=$obj->nb; $this->stats_facture['rows']=$obj->nb_rows; $this->stats_facture['qty']=$obj->qty?$obj->qty:0; + + // if it's a virtual product, maybe it is in invoice by extension + if (! empty($conf->global->PRODUCT_STATS_WITH_PARENT_PROD_IF_INCDEC)) { + $TFather = $this->getFather(); + if (is_array($TFather) && !empty($TFather)) { + foreach($TFather as &$fatherData) { + $pFather = new Product($this->db); + $pFather->id = $fatherData['id']; + $qtyCoef = $fatherData['qty']; + + if ($fatherData['incdec']) { + $pFather->load_stats_facture($socid); + + $this->stats_facture['customers']+=$pFather->stats_facture['customers']; + $this->stats_facture['nb']+=$pFather->stats_facture['nb']; + $this->stats_facture['rows']+=$pFather->stats_facture['rows']; + $this->stats_facture['qty']+=$pFather->stats_facture['qty'] * $qtyCoef; + } + } + } + } return 1; } else From d993d80a130f72efdcb4d067645951b9966a3bb9 Mon Sep 17 00:00:00 2001 From: ATM John BOTELLA Date: Sat, 18 May 2019 16:27:57 +0200 Subject: [PATCH 004/324] FIX url --- htdocs/main.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index da077045cdc..e386a4ad2cf 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1227,7 +1227,7 @@ function top_htmlhead($head, $title = '', $disablejs = 0, $disablehead = 0, $arr print ''."\n"; // Favicon - $favicon=dol_buildpath('/theme/'.$conf->theme.'/img/favicon.ico', 1); + $favicon = DOL_MAIN_URL_ROOT . '/theme/'.$conf->theme.'/img/favicon.ico'; if (! empty($conf->global->MAIN_FAVICON_URL)) $favicon=$conf->global->MAIN_FAVICON_URL; if (empty($conf->dol_use_jmobile)) print ''."\n"; // Not required into an Android webview //if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print ''."\n"; @@ -1235,7 +1235,7 @@ function top_htmlhead($head, $title = '', $disablejs = 0, $disablehead = 0, $arr //if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print ''."\n"; // Mobile appli like icon - $manifest=dol_buildpath('/theme/'.$conf->theme.'/manifest.json.php', 1, 1); + $manifest = DOL_MAIN_URL_ROOT . '/theme/'.$conf->theme.'/manifest.json.php'; if(!empty($manifest)){ print ''."\n"; } From b6615eab36be93a520550536803cd3feaa1a335e Mon Sep 17 00:00:00 2001 From: ATM John BOTELLA Date: Sat, 18 May 2019 23:47:22 +0200 Subject: [PATCH 005/324] FIX travis --- htdocs/public/payment/newpayment.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 51b4c0580e0..49ca337f800 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1947,7 +1947,7 @@ if (preg_match('/^dopayment/', $action)) { print info_admin($langs->trans("ErrorModuleSetupNotComplete", "stripe"), 0, 0, 'error'); } - else + else { print ''."\n"; From c6ab092af18efd3e75a72ccf082a48630cc08e48 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 14 Jun 2019 09:12:53 +0200 Subject: [PATCH 006/324] add capacity value for product --- htdocs/install/mysql/tables/llx_product.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/install/mysql/tables/llx_product.sql b/htdocs/install/mysql/tables/llx_product.sql index fb6e4cf5f1a..953a087f189 100755 --- a/htdocs/install/mysql/tables/llx_product.sql +++ b/htdocs/install/mysql/tables/llx_product.sql @@ -69,6 +69,8 @@ create table llx_product accountancy_code_sell_export varchar(32), -- Selling accountancy code for vat export accountancy_code_buy varchar(32), -- Buying accountancy code partnumber varchar(32), -- Part/Serial number. TODO To use it into screen if not a duplicate of barcode. + capacity float DEFAULT NULL, + capcity_units tinyint DEFAULT NULL, weight float DEFAULT NULL, weight_units tinyint DEFAULT NULL, length float DEFAULT NULL, From 695a00f21caf4f797f8fd928cd3cbd7311b08536 Mon Sep 17 00:00:00 2001 From: Abbes Bahfir Date: Wed, 19 Jun 2019 14:04:01 +0100 Subject: [PATCH 007/324] New:Show labels of countries in modulebuilder --- htdocs/core/class/ccountry.class.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/ccountry.class.php b/htdocs/core/class/ccountry.class.php index a97d992bf89..d5a929be0dd 100644 --- a/htdocs/core/class/ccountry.class.php +++ b/htdocs/core/class/ccountry.class.php @@ -30,7 +30,7 @@ /** * Class to manage dictionary Countries (used by imports) */ -class Ccountry // extends CommonObject +class Ccountry extends CommonObject { /** * @var DoliDB Database handler. @@ -332,4 +332,19 @@ class Ccountry // extends CommonObject return 1; } } + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + function getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1) + { + global $langs; + return $langs->trans($this->label); + } } From 7f34a03034e835e2e7344b67cfdc648ca48a4eac Mon Sep 17 00:00:00 2001 From: Bahfir Abbes Date: Thu, 20 Jun 2019 20:55:48 +0100 Subject: [PATCH 008/324] It's just a mistake. In order to declare a getnomUrl method, Ccountry does not need to extend Commonobject --- htdocs/core/class/ccountry.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/ccountry.class.php b/htdocs/core/class/ccountry.class.php index d5a929be0dd..71df0784fba 100644 --- a/htdocs/core/class/ccountry.class.php +++ b/htdocs/core/class/ccountry.class.php @@ -30,7 +30,7 @@ /** * Class to manage dictionary Countries (used by imports) */ -class Ccountry extends CommonObject +class Ccountry// extends CommonObject { /** * @var DoliDB Database handler. From f7134340e8946fcc32ff14674a4431d95b1b3cfb Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 4 Aug 2019 13:22:01 +0200 Subject: [PATCH 009/324] Update llx_product.sql --- htdocs/install/mysql/tables/llx_product.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_product.sql b/htdocs/install/mysql/tables/llx_product.sql index 953a087f189..1603ee52eff 100755 --- a/htdocs/install/mysql/tables/llx_product.sql +++ b/htdocs/install/mysql/tables/llx_product.sql @@ -70,7 +70,7 @@ create table llx_product accountancy_code_buy varchar(32), -- Buying accountancy code partnumber varchar(32), -- Part/Serial number. TODO To use it into screen if not a duplicate of barcode. capacity float DEFAULT NULL, - capcity_units tinyint DEFAULT NULL, + capacity_units tinyint DEFAULT NULL, weight float DEFAULT NULL, weight_units tinyint DEFAULT NULL, length float DEFAULT NULL, From f5f6882583398a27c45861c86794d552a3c703b4 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 4 Aug 2019 13:42:50 +0200 Subject: [PATCH 010/324] Update product.class.php --- htdocs/product/class/product.class.php | 158 ++++++++++++++++++------- 1 file changed, 114 insertions(+), 44 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index de0d28cee83..7d323ebadcf 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -59,7 +59,10 @@ class Product extends CommonObject */ public $fk_element='fk_product'; - protected $childtables=array('supplier_proposaldet', 'propaldet','commandedet','facturedet','contratdet','facture_fourn_det','commande_fournisseurdet'); // To test if we can delete object + /** + * @var array List of child tables. To test if we can delete object. + */ + protected $childtables=array('supplier_proposaldet', 'propaldet', 'commandedet', 'facturedet', 'contratdet', 'facture_fourn_det', 'commande_fournisseurdet'); /** * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe @@ -254,6 +257,8 @@ class Product extends CommonObject public $url; //! Unites de mesure + public $capacity; + public $capacity_units; public $weight; public $weight_units; public $length; @@ -269,13 +274,26 @@ class Product extends CommonObject public $accountancy_code_buy; /** - * Main barcode - * barcode value + * Main Barcode value * * @var string */ public $barcode; + /** + * Main Barcode type ID + * + * @var int + */ + public $barcode_type; + + /** + * Main Barcode type code + * + * @var string + */ + public $barcode_type_code; + /** * Additional barcodes (Some products have different barcodes according to the country of origin of manufacture) * @@ -291,7 +309,7 @@ class Product extends CommonObject public $multilangs=array(); - //! Taille de l'image + //! Size of image public $imgWidth; public $imgHeight; @@ -345,16 +363,7 @@ class Product extends CommonObject public $fields = array( - 'rowid' => array( - 'type'=>'integer', - 'label'=>'TechnicalID', - 'enabled'=>1, - 'visible'=>-2, - 'notnull'=>1, - 'index'=>1, - 'position'=>1, - 'comment'=>'Id', - ), + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'), 'ref' =>array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20), 'note_public' =>array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>61), @@ -799,6 +808,8 @@ class Product extends CommonObject $this->label = trim($this->label); $this->description = trim($this->description); $this->note = (isset($this->note) ? trim($this->note) : null); + $this->capacity = price2num($this->capacity); + $this->capacity_units = trim($this->capacity_units); $this->weight = price2num($this->weight); $this->weight_units = trim($this->weight_units); $this->length = price2num($this->length); @@ -945,6 +956,8 @@ class Product extends CommonObject $sql.= ", tobuy = " . (int) $this->status_buy; $sql.= ", tobatch = " . ((empty($this->status_batch) || $this->status_batch < 0) ? '0' : (int) $this->status_batch); $sql.= ", finished = " . ((! isset($this->finished) || $this->finished < 0) ? "null" : (int) $this->finished); + $sql.= ", capacity = " . ($this->capacity!='' ? "'".$this->db->escape($this->capacity)."'" : 'null'); + $sql.= ", capacity_units = " . ($this->capacity_units!='' ? "'".$this->db->escape($this->capacityt_units)."'": 'null'); $sql.= ", weight = " . ($this->weight!='' ? "'".$this->db->escape($this->weight)."'" : 'null'); $sql.= ", weight_units = " . ($this->weight_units!='' ? "'".$this->db->escape($this->weight_units)."'": 'null'); $sql.= ", length = " . ($this->length!='' ? "'".$this->db->escape($this->length)."'" : 'null'); @@ -2101,6 +2114,8 @@ class Product extends CommonObject $this->duration_value = substr($obj->duration, 0, dol_strlen($obj->duration)-1); $this->duration_unit = substr($obj->duration, -1); $this->canvas = $obj->canvas; + $this->capacity = $obj->capacity; + $this->capacity_units = $obj->capacity_units; $this->weight = $obj->weight; $this->weight_units = $obj->weight_units; $this->length = $obj->length; @@ -3246,6 +3261,57 @@ class Product extends CommonObject return $this->_get_stats($sql, $mode, $year); } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return nb of units or orders in which product is included + * + * @param int $socid Limit count on a particular third party id + * @param string $mode 'byunit'=number of unit, 'bynumber'=nb of entities + * @param int $filteronproducttype 0=To filter on product only, 1=To filter on services only + * @param int $year Year (0=last 12 month) + * @param string $morefilter More sql filters + * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 + */ + public function get_nb_contract($socid, $mode, $filteronproducttype = -1, $year = 0, $morefilter = '') + { + // phpcs:enable + global $conf, $user; + + $sql = "SELECT sum(d.qty), date_format(c.date_contrat, '%Y%m')"; + if ($mode == 'bynumber') { + $sql.= ", count(DISTINCT c.rowid)"; + } + $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as d, ".MAIN_DB_PREFIX."contrat as c, ".MAIN_DB_PREFIX."societe as s"; + if ($filteronproducttype >= 0) { + $sql.=", ".MAIN_DB_PREFIX."product as p"; + } + if (!$user->rights->societe->client->voir && !$socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql.= " WHERE c.rowid = d.fk_contrat"; + if ($this->id > 0) { + $sql.= " AND d.fk_product =".$this->id; + } else { + $sql.=" AND d.fk_product > 0"; + } + if ($filteronproducttype >= 0) { + $sql.= " AND p.rowid = d.fk_product AND p.fk_product_type =".$filteronproducttype; + } + $sql.= " AND c.fk_soc = s.rowid"; + $sql.= " AND c.entity IN (".getEntity('contract').")"; + if (!$user->rights->societe->client->voir && !$socid) { + $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; + } + if ($socid > 0) { + $sql.= " AND c.fk_soc = ".$socid; + } + $sql.=$morefilter; + $sql.= " GROUP BY date_format(c.date_contrat,'%Y%m')"; + $sql.= " ORDER BY date_format(c.date_contrat,'%Y%m') DESC"; + + return $this->_get_stats($sql, $mode, $year); + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Link a product/service to a parent product/service @@ -3662,7 +3728,7 @@ class Product extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Fonction recursive uniquement utilisee par get_arbo_each_prod, recompose l'arborescence des sousproduits - * Define value of this->res + * Define value of this->res * * @param array $prod Products array * @param string $compl_path Directory path of parents to add before @@ -3676,7 +3742,7 @@ class Product extends CommonObject // phpcs:enable global $conf,$langs; - $product = new Product($this->db); + $tmpproduct = null; //var_dump($prod); foreach($prod as $id_product => $desc_pere) // $id_product is 0 (first call starting with root top) or an id of a sub_product { @@ -3692,23 +3758,26 @@ class Product extends CommonObject } //print "XXX We add id=".$id." - label=".$label." - nb=".$nb." - multiply=".$multiply." fullpath=".$compl_path.$label."\n"; - $this->fetch($id); // Load product - $this->load_stock('nobatch,novirtual'); // Load stock to get true this->stock_reel + if (is_null($tmpproduct)) $tmpproduct = new Product($this->db); // So we initialize tmpproduct only once for all loop. + $tmpproduct->fetch($id); // Load product to get ->ref + $tmpproduct->load_stock('nobatch,novirtual'); // Load stock to get true ->stock_reel + //$this->fetch($id); // Load product to get ->ref + //$this->load_stock('nobatch,novirtual'); // Load stock to get true ->stock_reel $this->res[]= array( - 'id'=>$id, // Id product - 'id_parent'=>$id_parent, - 'ref'=>$this->ref, // Ref product - 'nb'=>$nb, // Nb of units that compose parent product - 'nb_total'=>$nb*$multiply, // Nb of units for all nb of product - 'stock'=>$this->stock_reel, // Stock - 'stock_alert'=>$this->seuil_stock_alerte, // Stock alert - 'label'=>$label, - 'fullpath'=>$compl_path.$label, // Label - 'type'=>$type, // Nb of units that compose parent product - 'desiredstock'=>$this->desiredstock, - 'level'=>$level, - 'incdec'=>$incdec, - 'entity'=>$this->entity + 'id'=>$id, // Id product + 'id_parent'=>$id_parent, + 'ref'=>$tmpproduct->ref, // Ref product + 'nb'=>$nb, // Nb of units that compose parent product + 'nb_total'=>$nb*$multiply, // Nb of units for all nb of product + 'stock'=>$tmpproduct->stock_reel, // Stock + 'stock_alert'=>$tmpproduct->seuil_stock_alerte, // Stock alert + 'label'=>$label, + 'fullpath'=>$compl_path.$label, // Label + 'type'=>$type, // Nb of units that compose parent product + 'desiredstock'=>$tmpproduct->desiredstock, + 'level'=>$level, + 'incdec'=>$incdec, + 'entity'=>$tmpproduct->entity ); // Recursive call if there is childs to child @@ -4030,14 +4099,11 @@ class Product extends CommonObject } $linkclose.= ' title="'.dol_escape_htmltag($label, 1, 1).'"'; - $linkclose.= ' class="classfortooltip"'; - - /* - $hookmanager->initHooks(array('productdao')); - $parameters=array('id'=>$this->id); - $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks - if ($reshook > 0) $linkclose = $hookmanager->resPrint; - */ + $linkclose.= ' class="nowraponall classfortooltip"'; + } + else + { + $linkclose = ' class="nowraponall"'; } if ($option == 'supplier' || $option == 'category') { @@ -4066,9 +4132,11 @@ class Product extends CommonObject $result.=$linkstart; if ($withpicto) { - if ($this->type == Product::TYPE_PRODUCT) { $result.=(img_object(($notooltip?'':$label), 'product', ($notooltip?'class="paddingright"':'class="paddingright classfortooltip"'), 0, 0, $notooltip?0:1)); + if ($this->type == Product::TYPE_PRODUCT) { + $result.=(img_object(($notooltip?'':$label), 'product', ($notooltip?'class="paddingright"':'class="paddingright classfortooltip"'), 0, 0, $notooltip?0:1)); } - if ($this->type == Product::TYPE_SERVICE) { $result.=(img_object(($notooltip?'':$label), 'service', ($notooltip?'class="paddinright"':'class="paddingright classfortooltip"'), 0, 0, $notooltip?0:1)); + if ($this->type == Product::TYPE_SERVICE) { + $result.=(img_object(($notooltip?'':$label), 'service', ($notooltip?'class="paddinright"':'class="paddingright classfortooltip"'), 0, 0, $notooltip?0:1)); } } $result.= $newref; @@ -4078,8 +4146,10 @@ class Product extends CommonObject $hookmanager->initHooks(array('productdao')); $parameters=array('id'=>$this->id, 'getnomurl'=>$result); $reshook=$hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks - if ($reshook > 0) { $result = $hookmanager->resPrint; - } else { $result .= $hookmanager->resPrint; + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; } return $result; From c9e481d6f7b60a3a28edbea0b63ed3a1876782d5 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 4 Aug 2019 14:09:59 +0200 Subject: [PATCH 011/324] Update product.class.php --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 7d323ebadcf..8cebf3a2ce4 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -957,7 +957,7 @@ class Product extends CommonObject $sql.= ", tobatch = " . ((empty($this->status_batch) || $this->status_batch < 0) ? '0' : (int) $this->status_batch); $sql.= ", finished = " . ((! isset($this->finished) || $this->finished < 0) ? "null" : (int) $this->finished); $sql.= ", capacity = " . ($this->capacity!='' ? "'".$this->db->escape($this->capacity)."'" : 'null'); - $sql.= ", capacity_units = " . ($this->capacity_units!='' ? "'".$this->db->escape($this->capacityt_units)."'": 'null'); + $sql.= ", capacity_units = " . ($this->capacity_units!='' ? "'".$this->db->escape($this->capacity_units)."'": 'null'); $sql.= ", weight = " . ($this->weight!='' ? "'".$this->db->escape($this->weight)."'" : 'null'); $sql.= ", weight_units = " . ($this->weight_units!='' ? "'".$this->db->escape($this->weight_units)."'": 'null'); $sql.= ", length = " . ($this->length!='' ? "'".$this->db->escape($this->length)."'" : 'null'); From 2d77bfd873df6cc3b382f2dd0c8f2d2830c81a26 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 4 Aug 2019 14:50:25 +0200 Subject: [PATCH 012/324] Update product.class.php --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 8cebf3a2ce4..bdc4fa9be51 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2050,7 +2050,7 @@ class Product extends CommonObject $sql = "SELECT rowid, ref, ref_ext, label, description, url, note as note_private, customcode, fk_country, price, price_ttc,"; $sql.= " price_min, price_min_ttc, price_base_type, cost_price, default_vat_code, tva_tx, recuperableonly as tva_npr, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, tosell,"; - $sql.= " tobuy, fk_product_type, duration, fk_default_warehouse, seuil_stock_alerte, canvas, weight, weight_units,"; + $sql.= " tobuy, fk_product_type, duration, fk_default_warehouse, seuil_stock_alerte, canvas, capacity, capacity_units, weight, weight_units,"; $sql.= " length, length_units, width, width_units, height, height_units,"; $sql.= " surface, surface_units, volume, volume_units, barcode, fk_barcode_type, finished,"; $sql.= " accountancy_code_buy, accountancy_code_sell, accountancy_code_sell_intra, accountancy_code_sell_export, stock, pmp,"; From d22c2960b7878e4eee53fc6242d6b6c0bca0abc5 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Tue, 6 Aug 2019 00:14:19 +0200 Subject: [PATCH 013/324] Update product.class.php --- htdocs/product/class/product.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index bdc4fa9be51..09038866e45 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -258,7 +258,7 @@ class Product extends CommonObject //! Unites de mesure public $capacity; - public $capacity_units; + public $capacity_units; public $weight; public $weight_units; public $length; @@ -957,7 +957,7 @@ class Product extends CommonObject $sql.= ", tobatch = " . ((empty($this->status_batch) || $this->status_batch < 0) ? '0' : (int) $this->status_batch); $sql.= ", finished = " . ((! isset($this->finished) || $this->finished < 0) ? "null" : (int) $this->finished); $sql.= ", capacity = " . ($this->capacity!='' ? "'".$this->db->escape($this->capacity)."'" : 'null'); - $sql.= ", capacity_units = " . ($this->capacity_units!='' ? "'".$this->db->escape($this->capacity_units)."'": 'null'); + $sql.= ", capacity_units = " . ($this->capacity_units!='' ? "'".$this->db->escape($this->capacity_units)."'": 'null'); $sql.= ", weight = " . ($this->weight!='' ? "'".$this->db->escape($this->weight)."'" : 'null'); $sql.= ", weight_units = " . ($this->weight_units!='' ? "'".$this->db->escape($this->weight_units)."'": 'null'); $sql.= ", length = " . ($this->length!='' ? "'".$this->db->escape($this->length)."'" : 'null'); From 1b4788c6d0d33a9fa6890f0c4a1a39b8cd74e4d3 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 24 Aug 2019 14:21:41 +0200 Subject: [PATCH 014/324] Update product.class.php --- htdocs/product/class/product.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 09038866e45..6b1877d0b51 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3288,7 +3288,8 @@ class Product extends CommonObject if (!$user->rights->societe->client->voir && !$socid) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; } - $sql.= " WHERE c.rowid = d.fk_contrat"; + $sql.= " WHERE c.entity IN (".getEntity('contract').")"; + $sql.= " AND c.rowid = d.fk_contrat"; if ($this->id > 0) { $sql.= " AND d.fk_product =".$this->id; } else { @@ -3298,7 +3299,6 @@ class Product extends CommonObject $sql.= " AND p.rowid = d.fk_product AND p.fk_product_type =".$filteronproducttype; } $sql.= " AND c.fk_soc = s.rowid"; - $sql.= " AND c.entity IN (".getEntity('contract').")"; if (!$user->rights->societe->client->voir && !$socid) { $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; } From b535bc0cb96c919312d26ed7b203f87f143ad936 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 2 Sep 2019 11:27:04 +0200 Subject: [PATCH 015/324] start dev --- htdocs/core/lib/company.lib.php | 1 + .../install/mysql/migration/10.0.0-11.0.0.sql | 17 +++++++++-- .../mysql/tables/llx_societe_contact.key.sql | 22 ++++++++++++++ .../mysql/tables/llx_societe_contact.sql | 29 +++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 htdocs/install/mysql/tables/llx_societe_contact.key.sql create mode 100644 htdocs/install/mysql/tables/llx_societe_contact.sql diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 2f6c474e632..8d862d3a9af 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -896,6 +896,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') 't.name'=>array('label'=>"Name", 'checked'=>1, 'position'=>10), 't.poste'=>array('label'=>"PostOrFunction", 'checked'=>1, 'position'=>20), 't.address'=>array('label'=>(empty($conf->dol_optimize_smallscreen) ? $langs->trans("Address").' / '.$langs->trans("Phone").' / '.$langs->trans("Email") : $langs->trans("Address")), 'checked'=>1, 'position'=>30), + 't.address'=>array('label'=>(empty($conf->dol_optimize_smallscreen) ? $langs->trans("Address").' / '.$langs->trans("Phone").' / '.$langs->trans("Email") : $langs->trans("Address")), 'checked'=>1, 'position'=>30), 't.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>40, 'class'=>'center'), ); // Extra fields diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 8efe44db103..5bc114c2294 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -89,5 +89,18 @@ ALTER TABLE llx_projet ADD COLUMN usage_organize_event integer DEFAULT 0; UPDATE llx_projet set usage_opportunity = 1 WHERE fk_opp_status > 0; - - \ No newline at end of file +create table llx_societe_contact +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + datec datetime NULL, -- date de creation de l'enregistrement + statut smallint DEFAULT 5, -- 5 inactif, 4 actif + + element_id int NOT NULL, -- la reference de l'element. + fk_c_type_contact int NOT NULL, -- nature du contact. + fk_socpeople integer NOT NULL +)ENGINE=innodb; + +ALTER TABLE llx_societe_contact ADD UNIQUE INDEX idx_societe_contact_idx1 (element_id, fk_c_type_contact, fk_socpeople); + +ALTER TABLE llx_societe_contact ADD CONSTRAINT fk_societe_contact_fk_c_type_contact FOREIGN KEY (fk_c_type_contact) REFERENCES llx_c_type_contact(rowid); +ALTER TABLE llx_societe_contact ADD CONSTRAINT fk_societe_contact_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); diff --git a/htdocs/install/mysql/tables/llx_societe_contact.key.sql b/htdocs/install/mysql/tables/llx_societe_contact.key.sql new file mode 100644 index 00000000000..1409e7edc24 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_societe_contact.key.sql @@ -0,0 +1,22 @@ +-- ======================================================================== +-- Copyright (C) 2019 Florian HENRY +-- +-- 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 +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- ======================================================================== + +ALTER TABLE llx_societe_contact ADD UNIQUE INDEX idx_societe_contact_idx1 (element_id, fk_c_type_contact, fk_socpeople); + +ALTER TABLE llx_societe_contact ADD CONSTRAINT fk_societe_contact_fk_c_type_contact FOREIGN KEY (fk_c_type_contact) REFERENCES llx_c_type_contact(rowid); +ALTER TABLE llx_societe_contact ADD CONSTRAINT fk_societe_contact_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); diff --git a/htdocs/install/mysql/tables/llx_societe_contact.sql b/htdocs/install/mysql/tables/llx_societe_contact.sql new file mode 100644 index 00000000000..040f8ded124 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_societe_contact.sql @@ -0,0 +1,29 @@ +-- ======================================================================== +-- Copyright (C) 2019 Florian HENRY +-- +-- 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 +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- ======================================================================== + + +create table llx_societe_contact +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + datec datetime NULL, -- date de creation de l'enregistrement + statut smallint DEFAULT 5, -- 5 inactif, 4 actif + + element_id int NOT NULL, -- la reference de l'element. + fk_c_type_contact int NOT NULL, -- nature du contact. + fk_socpeople integer NOT NULL +)ENGINE=innodb; From 405c92640c077c4fbda99604123f4574681b1816 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 2 Sep 2019 14:47:32 +0200 Subject: [PATCH 016/324] on going --- htdocs/contact/class/contact.class.php | 50 +++++++++++++- htdocs/core/class/commonobject.class.php | 69 +++++++++++++++++++ htdocs/core/lib/company.lib.php | 44 ++++++++++-- .../install/mysql/migration/10.0.0-11.0.0.sql | 23 ++++--- ...t.key.sql => llx_societe_contacts.key.sql} | 8 +-- ...e_contact.sql => llx_societe_contacts.sql} | 17 ++--- htdocs/langs/en_US/main.lang | 14 +++- 7 files changed, 195 insertions(+), 30 deletions(-) rename htdocs/install/mysql/tables/{llx_societe_contact.key.sql => llx_societe_contacts.key.sql} (61%) rename htdocs/install/mysql/tables/{llx_societe_contact.sql => llx_societe_contacts.sql} (69%) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index e064b93504d..db6ab29b802 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -82,7 +82,7 @@ class Contact extends CommonObject public $civility_id; // In fact we store civility_code public $civility_code; - public $civility; + public $civility; public $address; public $zip; public $town; @@ -139,6 +139,8 @@ class Contact extends CommonObject public $oldcopy; // To contains a clone of this when we need to save old properties of object + public $roles=array(); + /** * Constructor @@ -1449,4 +1451,50 @@ class Contact extends CommonObject return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + + /** + * Fetch Role for a contact + * + * @return float|int + * @throws Exception + */ + public function fetchRole() + { + + global $langs; + $error= 0; + $num=0; + + $sql ="SELECT tc.rowid, tc.element, tc.source, tc.code, tc.libelle"; + $sql.=" FROM ".MAIN_DB_PREFIX."societe_contacts as sc "; + $sql.=" INNER JOIN ".MAIN_DB_PREFIX."c_type_contact as tc"; + $sql.=" ON tc.rowid = sc.fk_c_type_contact"; + $sql.=" AND sc.fk_socpeople = ". $this->id; + $sql.=" AND tc.source = 'external' AND tc.active=1"; + $sql.=" AND sc.entity IN (".getEntity('societe').')'; + + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + + $this->roles=array(); + $resql=$this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num > 0) { + while ($obj = $this->db->fetch_object($resql)) { + $transkey="TypeContact_".$obj->element."_".$obj->source."_".$obj->code; + $this->roles[$this->id]=array('id'=>$obj->rowid,'element'=>$obj->element,'source'=>$obj->source,'code'=>$obj->code,'label'=>($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle)); + } + } + } else { + $error++; + $this->errors[]=$this->db->lasterror(); + } + + if (empty($error)) { + return $num; + } else { + return $error * -1; + } + } + } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index c57148124be..0eea968ecd2 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1210,6 +1210,75 @@ abstract class CommonObject } } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return array with list of possible values for type of contacts + * + * @param string $source 'internal', 'external' or 'all' + * @param int $option 0=Return array id->label, 1=Return array code->label + * @param int $activeonly 0=all status of contact, 1=only the active + * @param string $code Type of contact (Example: 'CUSTOMER', 'SERVICE') + * @param string $element Filter Element Type + * @return array Array list of type of contacts (id->label if option=0, code->label if option=1) + */ + public function listeTypeContacts($source = 'internal', $option = 0, $activeonly = 0, $code = '', $element = '') + { + // phpcs:enable + global $langs; + + if (empty($order)) $order='position'; + if ($order == 'position') $order.=',code'; + + $tab = array(); + $sql = "SELECT DISTINCT tc.rowid, tc.code, tc.libelle, tc.position, tc.element"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact as tc"; + + $sqlWhere=array(); + if (!empty($element)) + $sqlWhere[]=" tc.element='".$this->db->escape($element)."'"; + + if ($activeonly == 1) + $sqlWhere[]=" tc.active=1"; // only the active types + + if (! empty($source) && $source != 'all') + $sqlWhere[]=" tc.source='".$this->db->escape($source)."'"; + + if (! empty($code)) + $sqlWhere[]=" tc.code='".$this->db->escape($code)."'"; + + if (count($sqlWhere)>0) { + $sql .= " WHERE ". implode(' AND ', $sqlWhere); + } + + $sql.= $this->db->order('tc.element, tc.position', 'ASC'); + + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $num=$this->db->num_rows($resql); + $i=0; + while ($i < $num) + { + $obj = $this->db->fetch_object($resql); + + $libelle_element = $langs->trans('ContactDefault_'.ucfirst($obj->element)); + $transkey="TypeContact_".$this->element."_".$source."_".$obj->code; + $libelle_type=($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle); + if (empty($option)) $tab[$obj->rowid]=$libelle_element.' - '.$libelle_type; + else $tab[$obj->code]=$libelle_element.' - '.$libelle_type; + $i++; + } + return $tab; + } + else + { + $this->error=$this->db->lasterror(); + //dol_print_error($this->db); + return null; + } + } + /** * Return id of contacts for a source and a contact code. * Example: contact client de facturation ('external', 'BILLING') diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 8d862d3a9af..cfc1fcfb30f 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -869,6 +869,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if ($search_status=='') $search_status=1; // always display active customer first $search_name = GETPOST("search_name", 'alpha'); $search_addressphone = GETPOST("search_addressphone", 'alpha'); + $search_role = GETPOST("search_role", 'array'); if (! $sortorder) $sortorder="ASC"; if (! $sortfield) $sortfield="t.lastname"; @@ -887,7 +888,8 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') 'name' =>array('type'=>'varchar(128)', 'label'=>'Name', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1), 'poste' =>array('type'=>'varchar(128)', 'label'=>'PostOfFunction', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>20), 'address' =>array('type'=>'varchar(128)', 'label'=>'Address', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>30), - 'statut' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>40, 'arrayofkeyval'=>array(0=>$contactstatic->LibStatut(0, 1), 1=>$contactstatic->LibStatut(1, 1))), + 'role' =>array('type'=>'checkbox', 'label'=>'Role', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>40), + 'statut' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>50, 'arrayofkeyval'=>array(0=>$contactstatic->LibStatut(0, 1), 1=>$contactstatic->LibStatut(1, 1))), ); // Definition of fields for list @@ -896,8 +898,8 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') 't.name'=>array('label'=>"Name", 'checked'=>1, 'position'=>10), 't.poste'=>array('label'=>"PostOrFunction", 'checked'=>1, 'position'=>20), 't.address'=>array('label'=>(empty($conf->dol_optimize_smallscreen) ? $langs->trans("Address").' / '.$langs->trans("Phone").' / '.$langs->trans("Email") : $langs->trans("Address")), 'checked'=>1, 'position'=>30), - 't.address'=>array('label'=>(empty($conf->dol_optimize_smallscreen) ? $langs->trans("Address").' / '.$langs->trans("Phone").' / '.$langs->trans("Email") : $langs->trans("Address")), 'checked'=>1, 'position'=>30), - 't.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>40, 'class'=>'center'), + 'sc.role'=>array('label'=>"Role", 'checked'=>1, 'position'=>40), + 't.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>50, 'class'=>'center'), ); // Extra fields if (is_array($extrafields->attributes[$contactstatic->table_element]['label']) && count($extrafields->attributes[$contactstatic->table_element]['label'])) @@ -927,6 +929,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') { $search_status = ''; $search_name = ''; + $search_role = ''; $search_addressphone = ''; $search_array_options=array(); @@ -968,6 +971,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $param="socid=".urlencode($object->id); if ($search_status != '') $param.='&search_status='.urlencode($search_status); + if (count($search_role)>0) $param.=implode('&search_role[]=', $search_role); if ($search_name != '') $param.='&search_name='.urlencode($search_name); if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); // Add $param from extra fields @@ -978,9 +982,15 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $sql .= " t.civility as civility_id, t.address, t.zip, t.town"; $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as t"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople_extrafields as ef on (t.rowid = ef.fk_object)"; + if (count($search_role)>0) { + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe_contacts as sc on (sc.fk_socpeople = t.rowid)"; + } $sql .= " WHERE t.fk_soc = ".$object->id; if ($search_status!='' && $search_status != '-1') $sql .= " AND t.statut = ".$db->escape($search_status); if ($search_name) $sql .= natural_search(array('t.lastname', 't.firstname'), $search_name); + if (count($search_role)>0) { + $sql .= ' AND sc.fk_c_type_contact IN ('.implode(',',$search_role).')'; + } // Add where from extra fields $extrafieldsobjectkey=$contactstatic->table_element; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; @@ -993,6 +1003,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $num = $db->num_rows($result); + // Fields title search // -------------------------------------------------------------------- print ''; @@ -1002,11 +1013,16 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center'; if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; if ($key == 'status' || $key == 'statut') $align.=($align?' ':'').'center'; - if (! empty($arrayfields['t.'.$key]['checked'])) + if (! empty($arrayfields['t.'.$key]['checked']) || ! empty($arrayfields['sc.'.$key]['checked'])) { + print ''; if (in_array($key, array('lastname','name'))) print ''; elseif (in_array($key, array('statut'))) print $form->selectarray('search_status', array('-1'=>'','0'=>$contactstatic->LibStatut(0, 1),'1'=>$contactstatic->LibStatut(1, 1)), $search_status); + elseif (in_array($key, array('role'))) { + $contactType=$contactstatic->listeTypeContacts('external', '', 1); + print $form->multiselectarray('search_role', $contactType, $search_role); + } print ''; } } @@ -1035,7 +1051,10 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center'; if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; if ($key == 'status' || $key == 'statut') $align.=($align?' ':'').'center'; - if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; + if ($key == 'role') $align.=($align?' ':'').'center'; + if (! empty($arrayfields['t.'.$key]['checked']) || ! empty($arrayfields['sc.'.$key]['checked'])) { + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; + } } // Extra fields $extrafieldsobjectkey=$contactstatic->table_element; @@ -1082,6 +1101,11 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $contactstatic->setGenderFromCivility(); $contactstatic->fetch_optionals(); + $resultRole=$contactstatic->fetchRole(); + if ($resultRole<0) { + setEventMessages(null, $contactstatic->errors,'errors'); + } + if (is_array($contactstatic->array_options)) { foreach($contactstatic->array_options as $key => $val) @@ -1125,6 +1149,16 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') print ''; } + // Role + if (! empty($arrayfields['sc.role']['checked'])) + { + print ''; + foreach($contactstatic->roles as $key=>$val) { + print '
    '.implode(' ', $val['label']).'
'; + } + print ''; + } + // Status if (! empty($arrayfields['t.statut']['checked'])) { diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 5bc114c2294..1b705133a19 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -89,18 +89,19 @@ ALTER TABLE llx_projet ADD COLUMN usage_organize_event integer DEFAULT 0; UPDATE llx_projet set usage_opportunity = 1 WHERE fk_opp_status > 0; -create table llx_societe_contact +create table llx_societe_contacts ( rowid integer AUTO_INCREMENT PRIMARY KEY, - datec datetime NULL, -- date de creation de l'enregistrement - statut smallint DEFAULT 5, -- 5 inactif, 4 actif - - element_id int NOT NULL, -- la reference de l'element. - fk_c_type_contact int NOT NULL, -- nature du contact. - fk_socpeople integer NOT NULL + entity integer DEFAULT 1 NOT NULL, + date_creation datetime NOT NULL, + fk_soc integer NOT NULL, + fk_c_type_contact int NOT NULL, + fk_socpeople integer NOT NULL, + tms TIMESTAMP, + import_key VARCHAR(14) )ENGINE=innodb; -ALTER TABLE llx_societe_contact ADD UNIQUE INDEX idx_societe_contact_idx1 (element_id, fk_c_type_contact, fk_socpeople); - -ALTER TABLE llx_societe_contact ADD CONSTRAINT fk_societe_contact_fk_c_type_contact FOREIGN KEY (fk_c_type_contact) REFERENCES llx_c_type_contact(rowid); -ALTER TABLE llx_societe_contact ADD CONSTRAINT fk_societe_contact_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); +ALTER TABLE llx_societe_contacts ADD UNIQUE INDEX idx_societe_contacts_idx1 (entity, fk_soc, fk_c_type_contact, fk_socpeople); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_c_type_contact FOREIGN KEY (fk_c_type_contact) REFERENCES llx_c_type_contact(rowid); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); diff --git a/htdocs/install/mysql/tables/llx_societe_contact.key.sql b/htdocs/install/mysql/tables/llx_societe_contacts.key.sql similarity index 61% rename from htdocs/install/mysql/tables/llx_societe_contact.key.sql rename to htdocs/install/mysql/tables/llx_societe_contacts.key.sql index 1409e7edc24..2b2eae8b2ca 100644 --- a/htdocs/install/mysql/tables/llx_societe_contact.key.sql +++ b/htdocs/install/mysql/tables/llx_societe_contacts.key.sql @@ -16,7 +16,7 @@ -- -- ======================================================================== -ALTER TABLE llx_societe_contact ADD UNIQUE INDEX idx_societe_contact_idx1 (element_id, fk_c_type_contact, fk_socpeople); - -ALTER TABLE llx_societe_contact ADD CONSTRAINT fk_societe_contact_fk_c_type_contact FOREIGN KEY (fk_c_type_contact) REFERENCES llx_c_type_contact(rowid); -ALTER TABLE llx_societe_contact ADD CONSTRAINT fk_societe_contact_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); +ALTER TABLE llx_societe_contacts ADD UNIQUE INDEX idx_societe_contacts_idx1 (entity, fk_soc, fk_c_type_contact, fk_socpeople); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_c_type_contact FOREIGN KEY (fk_c_type_contact) REFERENCES llx_c_type_contact(rowid); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid); +ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); diff --git a/htdocs/install/mysql/tables/llx_societe_contact.sql b/htdocs/install/mysql/tables/llx_societe_contacts.sql similarity index 69% rename from htdocs/install/mysql/tables/llx_societe_contact.sql rename to htdocs/install/mysql/tables/llx_societe_contacts.sql index 040f8ded124..31d82f3003d 100644 --- a/htdocs/install/mysql/tables/llx_societe_contact.sql +++ b/htdocs/install/mysql/tables/llx_societe_contacts.sql @@ -17,13 +17,14 @@ -- ======================================================================== -create table llx_societe_contact +create table llx_societe_contacts ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - datec datetime NULL, -- date de creation de l'enregistrement - statut smallint DEFAULT 5, -- 5 inactif, 4 actif - - element_id int NOT NULL, -- la reference de l'element. - fk_c_type_contact int NOT NULL, -- nature du contact. - fk_socpeople integer NOT NULL + rowid integer AUTO_INCREMENT PRIMARY KEY, + entity integer DEFAULT 1 NOT NULL, + date_creation datetime NOT NULL, + fk_soc integer NOT NULL, + fk_c_type_contact int NOT NULL, + fk_socpeople integer NOT NULL, + tms TIMESTAMP, + import_key VARCHAR(14) )ENGINE=innodb; diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 5c3e30967de..2b92ed783fe 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -989,4 +989,16 @@ ToApprove=To approve GlobalOpenedElemView=Global view NoArticlesFoundForTheKeyword=No article found for the keyword '%s' NoArticlesFoundForTheCategory=No article found for the category -ToAcceptRefuse=To accept | refuse \ No newline at end of file +ToAcceptRefuse=To accept | refuse +ContactDefault_agenda=Event +ContactDefault_commande=Order +ContactDefault_contrat=Contract +ContactDefault_facture=Invoice +ContactDefault_fichinter=Intervention +ContactDefault_invoice_supplier=Supplier Invoice +ContactDefault_order_supplier=Supplier Order +ContactDefault_project=Project +ContactDefault_project_task=Task +ContactDefault_propal=Proposal +ContactDefault_supplier_proposal=Supplier Proposal +ContactDefault_ticketsup=Ticket From d811de4da2e7028d4ffd4150532dcd95ffeb5548 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 2 Sep 2019 22:01:48 +0200 Subject: [PATCH 017/324] let only triggers part --- htdocs/contact/card.php | 28 ++++++- htdocs/contact/class/contact.class.php | 93 +++++++++++++++++++++++- htdocs/contact/list.php | 10 +++ htdocs/core/class/commonobject.class.php | 7 +- htdocs/core/class/html.form.class.php | 40 ++++++++++ htdocs/core/lib/company.lib.php | 29 ++++---- 6 files changed, 179 insertions(+), 28 deletions(-) diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 76d0e3911b5..20a61ec4e3e 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -371,6 +371,7 @@ if (empty($reshook)) $object->priv = GETPOST("priv", 'int'); $object->note_public = GETPOST("note_public", 'none'); $object->note_private = GETPOST("note_private", 'none'); + $object->roles = GETPOST("roles", 'array'); // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost($extralabels, $object); @@ -474,9 +475,6 @@ else // Si edition contact deja existant $object = new Contact($db); $res=$object->fetch($id, $user); - if ($res < 0) { dol_print_error($db, $object->error); exit; } - $res=$object->fetch_optionals(); - if ($res < 0) { dol_print_error($db, $object->error); exit; } // Show tabs $head = contact_prepare_head($object); @@ -724,6 +722,15 @@ else print ""; } + //Role + if (!empty($socid)) { + print '' . $langs->trans("Role") . ''; + print ''; + $contactType = $object->listeTypeContacts('external', '', 1); + print $form->multiselectarray('roles', $contactType); + print ''; + } + // Other attributes $parameters=array('socid' => $socid, 'objsoc' => $objsoc, 'colspan' => ' colspan="3"', 'cols' => 3); $reshook=$hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -1040,6 +1047,14 @@ else print ""; } + //Role + if (!empty($object->socid)) { + print '' . $langs->trans("Role") . ''; + print ''; + print $form->showRoles("roles", $object, 'edit' ,$object->roles); + print ''; + } + // Other attributes $parameters=array('colspan' => ' colspan="3"', 'cols'=>3); $reshook=$hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -1238,6 +1253,13 @@ else print ''; } + if (!empty($object->socid)) { + print '' . $langs->trans("Roles") . ''; + print ''; + print $form->showRoles("roles", $object, 'view'); + print ''; + } + // Other attributes $cols = 3; $parameters=array('socid'=>$socid); diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index db6ab29b802..d718a898f2d 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -399,6 +399,14 @@ class Contact extends CommonObject } } + if (! $error) { + $result=$this->updateRoles(); + if ($result < 0) + { + $error++; + } + } + if (! $error && $this->user_id > 0) { $tmpobj = new User($this->db); @@ -861,6 +869,11 @@ class Contact extends CommonObject // fetch optionals attributes and labels $this->fetch_optionals(); + $resultRole=$this->fetchRoles(); + if ($resultRole<0) { + return $resultRole; + } + return 1; } else @@ -995,6 +1008,20 @@ class Contact extends CommonObject } } + if (! $error) + { + // Remove Roles + $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_contacts WHERE fk_socpeople = ".$this->id; + dol_syslog(get_class($this)."::delete", LOG_DEBUG); + $resql=$this->db->query($sql); + if (! $resql) + { + $error++; + $this->error .= $this->db->lasterror(); + $errorflag=-1; + } + } + if (! $error) { // Remove category @@ -1458,14 +1485,13 @@ class Contact extends CommonObject * @return float|int * @throws Exception */ - public function fetchRole() + public function fetchRoles() { - global $langs; $error= 0; $num=0; - $sql ="SELECT tc.rowid, tc.element, tc.source, tc.code, tc.libelle"; + $sql ="SELECT tc.rowid, tc.element, tc.source, tc.code, tc.libelle, sc.rowid as contactroleid"; $sql.=" FROM ".MAIN_DB_PREFIX."societe_contacts as sc "; $sql.=" INNER JOIN ".MAIN_DB_PREFIX."c_type_contact as tc"; $sql.=" ON tc.rowid = sc.fk_c_type_contact"; @@ -1482,11 +1508,13 @@ class Contact extends CommonObject if ($num > 0) { while ($obj = $this->db->fetch_object($resql)) { $transkey="TypeContact_".$obj->element."_".$obj->source."_".$obj->code; - $this->roles[$this->id]=array('id'=>$obj->rowid,'element'=>$obj->element,'source'=>$obj->source,'code'=>$obj->code,'label'=>($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle)); + $libelle_element = $langs->trans('ContactDefault_'.$obj->element); + $this->roles[$obj->contactroleid]=array('id'=>$obj->rowid,'element'=>$obj->element,'source'=>$obj->source,'code'=>$obj->code,'label'=>$libelle_element. ' - '.($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle)); } } } else { $error++; + $this->error=$this->db->lasterror(); $this->errors[]=$this->db->lasterror(); } @@ -1497,4 +1525,61 @@ class Contact extends CommonObject } } + /** + * Updates Roles + * + * @return float|int + * @throws Exception + */ + public function updateRoles() + { + global $conf; + + $error=0; + + $this->db->begin(); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_contacts WHERE fk_soc=".$this->socid; + + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + $result = $this->db->query($sql); + if (!$result) { + $this->errors[]=$this->db->lasterror().' sql='.$sql; + $error++; + } else { + if (count($this->roles)>0) { + foreach ($this->roles as $keyRoles => $valRoles) { + $sql = "INSERT INTO " . MAIN_DB_PREFIX . "societe_contacts"; + $sql .= " (entity,"; + $sql .= "date_creation,"; + $sql .= "fk_soc,"; + $sql .= "fk_c_type_contact,"; + $sql .= "fk_socpeople) "; + $sql .= " VALUES (" . $conf->entity . ","; + $sql .= "'" . $this->db->idate(dol_now()) . "',"; + $sql .= $this->socid . ", "; + $sql .= $valRoles . " , " ; + $sql .= $this->id; + $sql .= ")"; + dol_syslog(get_class($this) . "::".__METHOD__, LOG_DEBUG); + + $result = $this->db->query($sql); + if (!$result) + { + $this->errors[]=$this->db->lasterror().' sql='.$sql; + $error++; + } + } + } + } + if (empty($error)) { + $this->db->commit(); + return 1; + } else { + $this->error=implode(' ', $this->errors); + $this->db->rollback(); + return $error*-1; + } + } + } diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index b0db8b0affb..585d6db499d 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -84,6 +84,7 @@ $search_zip=GETPOST('search_zip', 'alpha'); $search_town=GETPOST('search_town', 'alpha'); $search_import_key=GETPOST("search_import_key", "alpha"); $search_country=GETPOST("search_country", 'intcomma'); +$search_roles=GETPOST("search_roles", 'array'); if ($search_status=='') $search_status=1; // always display active customer first @@ -242,6 +243,7 @@ if (empty($reshook)) $search_import_key=''; $toselect=''; $search_array_options=array(); + $search_roles=array(); } // Mass actions @@ -334,6 +336,9 @@ if (strlen($search_linkedin)) $sql.= natural_search('p.linkedin', $search_ if (strlen($search_email)) $sql.= natural_search('p.email', $search_email); if (strlen($search_zip)) $sql.= natural_search("p.zip", $search_zip); if (strlen($search_town)) $sql.= natural_search("p.town", $search_town); +if (count($search_roles)>0) { + $sql .= " AND p.rowid IN (SELECT sc.fk_socpeople FROM ".MAIN_DB_PREFIX."societe_contacts as sc WHERE sc.fk_c_type_contact IN (".implode(',', $search_roles)."))"; +} if ($search_no_email != '' && $search_no_email >= 0) $sql.= " AND p.no_email = ".$db->escape($search_no_email); if ($search_status != '' && $search_status >= 0) $sql.= " AND p.statut = ".$db->escape($search_status); @@ -438,6 +443,7 @@ if ($search_status != '') $param.='&search_status='.urlencode($search_status if ($search_priv == '0' || $search_priv == '1') $param.="&search_priv=".urlencode($search_priv); if ($search_import_key != '') $param.='&search_import_key='.urlencode($search_import_key); if ($optioncss != '') $param.='&optioncss='.$optioncss; +if (count($search_roles)>0) $param.=implode('&search_roles[]=', $search_roles); // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; @@ -510,6 +516,10 @@ if (! empty($conf->categorie->enabled)) $moreforfilter.=$formother->select_categories(Categorie::TYPE_SUPPLIER, $search_categ_supplier, 'search_categ_supplier', 1); $moreforfilter.=''; } + $moreforfilter.='
'; + $moreforfilter.=$langs->trans('Roles'). ': '; + $moreforfilter.=$form->showRoles("search_roles", $objecttmp, 'edit', $search_roles); + $moreforfilter.='
'; } if ($moreforfilter) { diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 0eea968ecd2..716b615f503 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1226,9 +1226,6 @@ abstract class CommonObject // phpcs:enable global $langs; - if (empty($order)) $order='position'; - if ($order == 'position') $order.=',code'; - $tab = array(); $sql = "SELECT DISTINCT tc.rowid, tc.code, tc.libelle, tc.position, tc.element"; $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact as tc"; @@ -1262,11 +1259,11 @@ abstract class CommonObject { $obj = $this->db->fetch_object($resql); - $libelle_element = $langs->trans('ContactDefault_'.ucfirst($obj->element)); + $libelle_element = $langs->trans('ContactDefault_'.$obj->element); $transkey="TypeContact_".$this->element."_".$source."_".$obj->code; $libelle_type=($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle); if (empty($option)) $tab[$obj->rowid]=$libelle_element.' - '.$libelle_type; - else $tab[$obj->code]=$libelle_element.' - '.$libelle_type; + else $tab[$obj->rowid]=$libelle_element.' - '.$libelle_type; $i++; } return $tab; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 5ee969a73a0..4eca1ef0f85 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6484,6 +6484,46 @@ class Form return 'ErrorBadValueForParameterRenderMode'; // Should not happened } + /** + * showContactRoles on view and edit mode + * + * @param string $htmlname Html component name and id + * @param Contact $contact Contact Obejct + * @param string $rendermode view, edit + * @param array $selected $key=>$val $val is selected Roles for input mode + * @return string String with contacts roles + */ + public function showRoles($htmlname = '', Contact $contact, $rendermode = 'view', $selected = array()) + { + if ($rendermode === 'view') { + $toprint = array(); + foreach ($contact->roles as $key => $val) { + $toprint[] = '
  • ' . $val['label'] . '
  • '; + } + return '
      ' . implode(' ', $toprint) . '
    '; + } + + if ($rendermode === 'edit') + { + $contactType=$contact->listeTypeContacts('external', '', 1); + + if (count($selected)>0) { + $newselected=array(); + foreach($selected as $key=>$val) { + if (is_array($val) && array_key_exists('id', $val) && in_array($val['id'], array_keys($contactType))) { + $newselected[]=$val['id']; + } else { + break; + } + } + if (count($newselected)>0) $selected=$newselected; + } + return $this->multiselectarray($htmlname, $contactType, $selected); + } + + return 'ErrorBadValueForParameterRenderMode'; // Should not happened + } + /** * Show linked object block. diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index cfc1fcfb30f..14b20bbe46b 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -869,7 +869,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if ($search_status=='') $search_status=1; // always display active customer first $search_name = GETPOST("search_name", 'alpha'); $search_addressphone = GETPOST("search_addressphone", 'alpha'); - $search_role = GETPOST("search_role", 'array'); + $search_roles = GETPOST("search_roles", 'array'); if (! $sortorder) $sortorder="ASC"; if (! $sortfield) $sortfield="t.lastname"; @@ -898,7 +898,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') 't.name'=>array('label'=>"Name", 'checked'=>1, 'position'=>10), 't.poste'=>array('label'=>"PostOrFunction", 'checked'=>1, 'position'=>20), 't.address'=>array('label'=>(empty($conf->dol_optimize_smallscreen) ? $langs->trans("Address").' / '.$langs->trans("Phone").' / '.$langs->trans("Email") : $langs->trans("Address")), 'checked'=>1, 'position'=>30), - 'sc.role'=>array('label'=>"Role", 'checked'=>1, 'position'=>40), + 'sc.role'=>array('label'=>"Roles", 'checked'=>1, 'position'=>40), 't.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>50, 'class'=>'center'), ); // Extra fields @@ -929,7 +929,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') { $search_status = ''; $search_name = ''; - $search_role = ''; + $search_roles = array(); $search_addressphone = ''; $search_array_options=array(); @@ -971,7 +971,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $param="socid=".urlencode($object->id); if ($search_status != '') $param.='&search_status='.urlencode($search_status); - if (count($search_role)>0) $param.=implode('&search_role[]=', $search_role); + if (count($search_roles)>0) $param.=implode('&search_roles[]=', $search_roles); if ($search_name != '') $param.='&search_name='.urlencode($search_name); if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); // Add $param from extra fields @@ -982,14 +982,11 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $sql .= " t.civility as civility_id, t.address, t.zip, t.town"; $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as t"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople_extrafields as ef on (t.rowid = ef.fk_object)"; - if (count($search_role)>0) { - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe_contacts as sc on (sc.fk_socpeople = t.rowid)"; - } $sql .= " WHERE t.fk_soc = ".$object->id; if ($search_status!='' && $search_status != '-1') $sql .= " AND t.statut = ".$db->escape($search_status); if ($search_name) $sql .= natural_search(array('t.lastname', 't.firstname'), $search_name); - if (count($search_role)>0) { - $sql .= ' AND sc.fk_c_type_contact IN ('.implode(',',$search_role).')'; + if (count($search_roles)>0) { + $sql .= " AND t.rowid IN (SELECT sc.fk_socpeople FROM ".MAIN_DB_PREFIX."societe_contacts as sc WHERE sc.fk_c_type_contact IN (".implode(',', $search_roles)."))"; } // Add where from extra fields $extrafieldsobjectkey=$contactstatic->table_element; @@ -1020,8 +1017,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (in_array($key, array('lastname','name'))) print ''; elseif (in_array($key, array('statut'))) print $form->selectarray('search_status', array('-1'=>'','0'=>$contactstatic->LibStatut(0, 1),'1'=>$contactstatic->LibStatut(1, 1)), $search_status); elseif (in_array($key, array('role'))) { - $contactType=$contactstatic->listeTypeContacts('external', '', 1); - print $form->multiselectarray('search_role', $contactType, $search_role); + print $form->showRoles("search_roles", $contactstatic, 'edit', $search_roles); } print ''; } @@ -1052,9 +1048,12 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; if ($key == 'status' || $key == 'statut') $align.=($align?' ':'').'center'; if ($key == 'role') $align.=($align?' ':'').'center'; - if (! empty($arrayfields['t.'.$key]['checked']) || ! empty($arrayfields['sc.'.$key]['checked'])) { + if (! empty($arrayfields['t.'.$key]['checked'])) { print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; } + if (! empty($arrayfields['sc.'.$key]['checked'])) { + print getTitleFieldOfList($arrayfields['sc.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 'sc.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; + } } // Extra fields $extrafieldsobjectkey=$contactstatic->table_element; @@ -1101,7 +1100,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $contactstatic->setGenderFromCivility(); $contactstatic->fetch_optionals(); - $resultRole=$contactstatic->fetchRole(); + $resultRole=$contactstatic->fetchRoles(); if ($resultRole<0) { setEventMessages(null, $contactstatic->errors,'errors'); } @@ -1153,9 +1152,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (! empty($arrayfields['sc.role']['checked'])) { print ''; - foreach($contactstatic->roles as $key=>$val) { - print '
      '.implode(' ', $val['label']).'
    '; - } + print $form->showRoles("roles", $contactstatic, 'view'); print ''; } From 6c20fbafdf0c5811a5802da2c11468b0798a0359 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Tue, 3 Sep 2019 17:04:42 +0200 Subject: [PATCH 018/324] add trigger files --- htdocs/contact/card.php | 4 +- htdocs/contact/class/contact.class.php | 43 +++++++ htdocs/contact/list.php | 4 +- htdocs/core/class/commonobject.class.php | 42 +++--- htdocs/core/class/html.form.class.php | 41 ------ htdocs/core/class/html.formcompany.class.php | 64 +++++++--- htdocs/core/lib/company.lib.php | 6 +- ...rface_90_modSociete_ContactRoles.class.php | 120 ++++++++++++++++++ 8 files changed, 241 insertions(+), 83 deletions(-) create mode 100644 htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 20a61ec4e3e..5861cc71d38 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -1051,7 +1051,7 @@ else if (!empty($object->socid)) { print '' . $langs->trans("Role") . ''; print ''; - print $form->showRoles("roles", $object, 'edit' ,$object->roles); + print $formcompany->showRoles("roles", $object, 'edit' ,$object->roles); print ''; } @@ -1256,7 +1256,7 @@ else if (!empty($object->socid)) { print '' . $langs->trans("Roles") . ''; print ''; - print $form->showRoles("roles", $object, 'view'); + print $formcompany->showRoles("roles", $object, 'view'); print ''; } diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index d718a898f2d..6b46e32f532 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1525,6 +1525,49 @@ class Contact extends CommonObject } } + /** + * Get Contact roles for a thirdparty + * + * @param string $element element type + * @return array|int + * @throws Exception + */ + public function getContactRoles($element = '') + { + $tab=array(); + + $sql = "SELECT sc.fk_socpeople as id, sc.fk_c_type_contact"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact tc"; + $sql.= ", ".MAIN_DB_PREFIX."societe_contacts sc"; + $sql.= " WHERE sc.fk_soc =".$this->socid; + $sql.= " AND sc.fk_c_type_contact=tc.rowid"; + $sql.= " AND tc.element='".$element."'"; + $sql.= " AND tc.active=1"; + + dol_syslog(get_class($this)."::liste_contact", LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $num=$this->db->num_rows($resql); + $i=0; + while ($i < $num) + { + $obj = $this->db->fetch_object($resql); + $tab[]=array('fk_socpeople'=>$obj->id, 'type_contact'=>$obj->fk_c_type_contact); + + $i++; + } + + return $tab; + } + else + { + $this->error=$this->db->error(); + dol_print_error($this->db); + return -1; + } + } + /** * Updates Roles * diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 585d6db499d..6b595a05860 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -36,6 +36,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; // Load translation files required by the page $langs->loadLangs(array("companies", "suppliers", "categories")); @@ -264,6 +265,7 @@ if ($search_priv < 0) $search_priv=''; $form=new Form($db); $formother=new FormOther($db); +$formcompany=new FormCompany($db); $contactstatic=new Contact($db); $title = (! empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); @@ -518,7 +520,7 @@ if (! empty($conf->categorie->enabled)) } $moreforfilter.='
    '; $moreforfilter.=$langs->trans('Roles'). ': '; - $moreforfilter.=$form->showRoles("search_roles", $objecttmp, 'edit', $search_roles); + $moreforfilter.=$formcompany->showRoles("search_roles", $objecttmp, 'edit', $search_roles); $moreforfilter.='
    '; } if ($moreforfilter) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 716b615f503..1a1b5c597ce 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1224,9 +1224,10 @@ abstract class CommonObject public function listeTypeContacts($source = 'internal', $option = 0, $activeonly = 0, $code = '', $element = '') { // phpcs:enable - global $langs; + global $langs, $conf; $tab = array(); + $sql = "SELECT DISTINCT tc.rowid, tc.code, tc.libelle, tc.position, tc.element"; $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact as tc"; @@ -1251,27 +1252,36 @@ abstract class CommonObject dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $resql=$this->db->query($sql); - if ($resql) - { - $num=$this->db->num_rows($resql); - $i=0; - while ($i < $num) - { - $obj = $this->db->fetch_object($resql); - - $libelle_element = $langs->trans('ContactDefault_'.$obj->element); - $transkey="TypeContact_".$this->element."_".$source."_".$obj->code; - $libelle_type=($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle); - if (empty($option)) $tab[$obj->rowid]=$libelle_element.' - '.$libelle_type; - else $tab[$obj->rowid]=$libelle_element.' - '.$libelle_type; - $i++; + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num > 0) { + while ($obj = $this->db->fetch_object($resql)) { + if (strpos($obj->element, 'project')!==false) { + $element='projet'; + } elseif($obj->element=='contrat') { + $element='contract'; + } elseif(strpos($obj->element, 'supplier')!==false && $obj->element!='supplier_proposal') { + $element='fournisseur'; + } elseif(strpos($obj->element, 'supplier')!==false && $obj->element!='supplier_proposal') { + $element='fournisseur'; + } else { + $element=$obj->element; + } + if ($conf->{$element}->enabled) { + $libelle_element = $langs->trans('ContactDefault_' . $obj->element); + $transkey = "TypeContact_" . $this->element . "_" . $source . "_" . $obj->code; + $libelle_type = ($langs->trans($transkey) != $transkey ? $langs->trans($transkey) : $obj->libelle); + if (empty($option)) + $tab[$obj->rowid] = $libelle_element . ' - ' . $libelle_type; + else $tab[$obj->rowid] = $libelle_element . ' - ' . $libelle_type; + } + } } return $tab; } else { $this->error=$this->db->lasterror(); - //dol_print_error($this->db); return null; } } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 4eca1ef0f85..f351a361d14 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6484,47 +6484,6 @@ class Form return 'ErrorBadValueForParameterRenderMode'; // Should not happened } - /** - * showContactRoles on view and edit mode - * - * @param string $htmlname Html component name and id - * @param Contact $contact Contact Obejct - * @param string $rendermode view, edit - * @param array $selected $key=>$val $val is selected Roles for input mode - * @return string String with contacts roles - */ - public function showRoles($htmlname = '', Contact $contact, $rendermode = 'view', $selected = array()) - { - if ($rendermode === 'view') { - $toprint = array(); - foreach ($contact->roles as $key => $val) { - $toprint[] = '
  • ' . $val['label'] . '
  • '; - } - return '
      ' . implode(' ', $toprint) . '
    '; - } - - if ($rendermode === 'edit') - { - $contactType=$contact->listeTypeContacts('external', '', 1); - - if (count($selected)>0) { - $newselected=array(); - foreach($selected as $key=>$val) { - if (is_array($val) && array_key_exists('id', $val) && in_array($val['id'], array_keys($contactType))) { - $newselected[]=$val['id']; - } else { - break; - } - } - if (count($newselected)>0) $selected=$newselected; - } - return $this->multiselectarray($htmlname, $contactType, $selected); - } - - return 'ErrorBadValueForParameterRenderMode'; // Should not happened - } - - /** * Show linked object block. * diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 2207ab8ab2b..81b87b6f340 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -29,28 +29,11 @@ * Class to build HTML component for third parties management * Only common components are here. */ -class FormCompany + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; + +class FormCompany extends Form { - /** - * @var DoliDB Database handler. - */ - public $db; - - /** - * @var string Error code (or message) - */ - public $error=''; - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct($db) - { - $this->db = $db; - } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** @@ -763,6 +746,45 @@ class FormCompany } } + /** + * showContactRoles on view and edit mode + * + * @param string $htmlname Html component name and id + * @param Contact $contact Contact Obejct + * @param string $rendermode view, edit + * @param array $selected $key=>$val $val is selected Roles for input mode + * @return string String with contacts roles + */ + public function showRoles($htmlname = '', Contact $contact, $rendermode = 'view', $selected = array()) + { + if ($rendermode === 'view') { + $toprint = array(); + foreach ($contact->roles as $key => $val) { + $toprint[] = '
  • ' . $val['label'] . '
  • '; + } + return '
      ' . implode(' ', $toprint) . '
    '; + } + + if ($rendermode === 'edit') + { + $contactType=$contact->listeTypeContacts('external', '', 1); + if (count($selected)>0) { + $newselected=array(); + foreach($selected as $key=>$val) { + if (is_array($val) && array_key_exists('id', $val) && in_array($val['id'], array_keys($contactType))) { + $newselected[]=$val['id']; + } else { + break; + } + } + if (count($newselected)>0) $selected=$newselected; + } + return $this->multiselectarray($htmlname, $contactType, $selected); + } + + return 'ErrorBadValueForParameterRenderMode'; // Should not happened + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return a select list with zip codes and their town diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 14b20bbe46b..331b03bacc4 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -859,6 +859,8 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') global $user,$conf,$extrafields,$hookmanager; global $contextpage; + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + $formcompany = new FormCompany($db); $form = new Form($db); $optioncss = GETPOST('optioncss', 'alpha'); @@ -1017,7 +1019,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (in_array($key, array('lastname','name'))) print ''; elseif (in_array($key, array('statut'))) print $form->selectarray('search_status', array('-1'=>'','0'=>$contactstatic->LibStatut(0, 1),'1'=>$contactstatic->LibStatut(1, 1)), $search_status); elseif (in_array($key, array('role'))) { - print $form->showRoles("search_roles", $contactstatic, 'edit', $search_roles); + print $formcompany->showRoles("search_roles", $contactstatic, 'edit', $search_roles); } print ''; } @@ -1152,7 +1154,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (! empty($arrayfields['sc.role']['checked'])) { print ''; - print $form->showRoles("roles", $contactstatic, 'view'); + print $formcompany->showRoles("roles", $contactstatic, 'view'); print ''; } diff --git a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php new file mode 100644 index 00000000000..8fba51e7a69 --- /dev/null +++ b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php @@ -0,0 +1,120 @@ + + * Copyright (C) 2009-2017 Regis Houssin + * Copyright (C) 2011-2014 Juanjo Menent + * Copyright (C) 2013 Cedric GROSS + * Copyright (C) 2014 Marcos García + * Copyright (C) 2015 Bahfir Abbes + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php + * \ingroup agenda + * \brief Trigger file for agenda module + */ + +require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php'; + + +/** + * Class of triggered functions for agenda module + */ +class InterfaceContactRoles extends DolibarrTriggers +{ + public $family = 'agenda'; + public $description = "Triggers of this module add actions in agenda according to setup made in agenda setup."; + + /** + * Version of the trigger + * @var string + */ + public $version = self::VERSION_DOLIBARR; + + /** + * @var string Image of the trigger + */ + public $picto = 'action'; + + /** + * Function called when a Dolibarrr business event is done. + * All functions "runTrigger" are triggered if file is inside directory htdocs/core/triggers or htdocs/module/code/triggers (and declared) + * + * Following properties may be set before calling trigger. The may be completed by this trigger to be used for writing the event into database: + * $object->actiontypecode (translation action code: AC_OTH, ...) + * $object->actionmsg (note, long text) + * $object->actionmsg2 (label, short text) + * $object->sendtoid (id of contact or array of ids) + * $object->socid (id of thirdparty) + * $object->fk_project + * $object->fk_element + * $object->elementtype + * + * @param string $action Event action code + * @param Object $object Object + * @param User $user Object user + * @param Translate $langs Object langs + * @param conf $conf Object conf + * @return int <0 if KO, 0 if no triggered ran, >0 if OK + */ + public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) + { + // Lors de la création d'un document, récupération des contacts et rôle associés à la société et association avec le document + if ($action === 'PROPAL_CREATE' || $action === 'ORDER_CREATE' || $action === 'BILL_CREATE' || $action === 'ORDER_SUPPLIER_CREATE' || $action === 'BILL_SUPPLIER_CREATE' + || $action === 'CONTRACT_CREATE' || $action === 'FICHINTER_CREATE' || $action === 'PROJECT_CREATE' || $action === 'TICKET_CREATE' || $action === 'ACTION_CREATE') { + + if(!empty($object->socid) && $object->socid != '-1') { + global $db, $langs; + + $contactdefault = new Contact($this->db); + $contactdefault->socid=$object->socid; + $TContact = $contactdefault->getContactRoles(); + + // Le trigger est appelé avant que le core n'ajoute lui-même des contacts (contact propale, clone), il ne faut pas les associer avant sinon bug + $TContactAlreadyLinked = array(); + if ($object->id > 0) + { + $class = get_class($object); + $cloneFrom = new $class($db); + $r = $cloneFrom->fetch($object->id); + + if (!empty($cloneFrom->id)) $TContactAlreadyLinked = array_merge($cloneFrom->liste_contact(-1,'external'), $cloneFrom->liste_contact(-1,'internal')); + } + + foreach($TContact as $i => $infos) { + // Gestion du cas du clone + foreach ($TContactAlreadyLinked as $contactData) { + if($contactData['id'] == $infos['fk_socpeople'] && $contactData['fk_c_type_contact'] == $infos['type_contact']) unset($TContact[$i]); + } + } + + $nb = 0; + foreach($TContact as $infos) { + // Gestion du cas spécifique de la création de propale avec sélection du contact, cela créé un bug si le contact est ajouté par le module contactdefault + $res = $object->add_contact($infos['fk_socpeople'], $infos['type_contact']); + if($res > 0) $nb++; + } + + if($nb > 0) { + setEventMessage($langs->trans('ContactAddedAutomatically', $nb)); + } + } + + dol_syslog( + "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id + ); + } + } +} From d50114df649a0d7752f4a549e5d541da1dc27eeb Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Fri, 6 Sep 2019 09:20:18 +0200 Subject: [PATCH 019/324] mostlyDone --- htdocs/contact/class/contact.class.php | 2 +- ...rface_90_modSociete_ContactRoles.class.php | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 6b46e32f532..fad72d69637 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1544,7 +1544,7 @@ class Contact extends CommonObject $sql.= " AND tc.element='".$element."'"; $sql.= " AND tc.active=1"; - dol_syslog(get_class($this)."::liste_contact", LOG_DEBUG); + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $resql=$this->db->query($sql); if ($resql) { diff --git a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php index 8fba51e7a69..36a8274c602 100644 --- a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php +++ b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php @@ -71,16 +71,20 @@ class InterfaceContactRoles extends DolibarrTriggers */ public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) { - // Lors de la création d'un document, récupération des contacts et rôle associés à la société et association avec le document + if ($action === 'PROPAL_CREATE' || $action === 'ORDER_CREATE' || $action === 'BILL_CREATE' || $action === 'ORDER_SUPPLIER_CREATE' || $action === 'BILL_SUPPLIER_CREATE' || $action === 'CONTRACT_CREATE' || $action === 'FICHINTER_CREATE' || $action === 'PROJECT_CREATE' || $action === 'TICKET_CREATE' || $action === 'ACTION_CREATE') { - if(!empty($object->socid) && $object->socid != '-1') { - global $db, $langs; + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + $socid=(property_exists($object, 'socid')?$object->socid:$object->fk_soc); + + if(!empty($socid) && $socid != '-1') { + global $db, $langs; + var_dump($socid); $contactdefault = new Contact($this->db); - $contactdefault->socid=$object->socid; - $TContact = $contactdefault->getContactRoles(); + $contactdefault->socid=$socid; + $TContact = $contactdefault->getContactRoles($object->element); // Le trigger est appelé avant que le core n'ajoute lui-même des contacts (contact propale, clone), il ne faut pas les associer avant sinon bug $TContactAlreadyLinked = array(); @@ -90,7 +94,7 @@ class InterfaceContactRoles extends DolibarrTriggers $cloneFrom = new $class($db); $r = $cloneFrom->fetch($object->id); - if (!empty($cloneFrom->id)) $TContactAlreadyLinked = array_merge($cloneFrom->liste_contact(-1,'external'), $cloneFrom->liste_contact(-1,'internal')); + if (!empty($cloneFrom->id)) $TContactAlreadyLinked = array_merge($cloneFrom->liste_contact(-1, 'external'), $cloneFrom->liste_contact(-1, 'internal')); } foreach($TContact as $i => $infos) { @@ -111,10 +115,6 @@ class InterfaceContactRoles extends DolibarrTriggers setEventMessage($langs->trans('ContactAddedAutomatically', $nb)); } } - - dol_syslog( - "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id - ); } } } From e55c7bc378295bd6db964434bb6e8b604484f814 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 6 Sep 2019 11:22:22 +0200 Subject: [PATCH 020/324] Update llx_facture.sql --- htdocs/install/mysql/tables/llx_facture.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_facture.sql b/htdocs/install/mysql/tables/llx_facture.sql index 742c63d0a6e..3c678699a7e 100644 --- a/htdocs/install/mysql/tables/llx_facture.sql +++ b/htdocs/install/mysql/tables/llx_facture.sql @@ -41,6 +41,7 @@ create table llx_facture date_pointoftax date DEFAULT NULL, -- date point of tax (for GB) date_valid date, -- date validation tms timestamp, -- date creation/modification + date_cloture datetime, -- date de cloture paye smallint DEFAULT 0 NOT NULL, amount double(24,8) DEFAULT 0 NOT NULL, remise_percent real DEFAULT 0, -- remise relative @@ -62,7 +63,8 @@ create table llx_facture fk_user_author integer, -- user making creation fk_user_modif integer, -- user making last change fk_user_valid integer, -- user validating - + fk_user_cloture integer, -- user closing + module_source varchar(32), -- name of module when invoice generated by a dedicated module (POS, ...) pos_source varchar(32), -- name of POS station when invoice is generated by a POS module fk_fac_rec_source integer, -- facture rec source From ead8d29ed32ecd8cc65ad90254e912a2dc8cf097 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 6 Sep 2019 11:32:46 +0200 Subject: [PATCH 021/324] Update 10.0.0-11.0.0.sql --- htdocs/install/mysql/migration/10.0.0-11.0.0.sql | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 64de0364139..065104164c9 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -47,7 +47,8 @@ ALTER TABLE llx_entrepot_extrafields ADD INDEX idx_entrepot_extrafields (fk_obje ALTER TABLE llx_facture ADD COLUMN retained_warranty real DEFAULT NULL after situation_final; ALTER TABLE llx_facture ADD COLUMN retained_warranty_date_limit date DEFAULT NULL after retained_warranty; ALTER TABLE llx_facture ADD COLUMN retained_warranty_fk_cond_reglement integer DEFAULT NULL after retained_warranty_date_limit; - +ALTER TABLE llx_facture ADD COLUMN date_cloture datetime DEFAULT NULL after date_valid; +ALTER TABLE llx_facture ADD COLUMN fk_user_cloture integer DEFAULT NULL after fk_user_valid; ALTER TABLE llx_c_shipment_mode ADD COLUMN entity integer DEFAULT 1 NOT NULL; @@ -105,4 +106,4 @@ create table llx_c_hrm_public_holiday )ENGINE=innodb; - \ No newline at end of file + From fc75d72290578cb488ba1480b75c1ed51122dbba Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 6 Sep 2019 11:35:52 +0200 Subject: [PATCH 022/324] Update list.php --- htdocs/compta/facture/list.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index ad9e2295d6d..54f0fdb6d08 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -180,6 +180,7 @@ $arrayfields=array( 'rtp'=>array('label'=>"Rest", 'checked'=>0), 'f.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>500), 'f.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>500), + 'f.date_cloture'=>array('label'=>"DateClosing", 'checked'=>0, 'position'=>500), 'f.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000), ); @@ -381,7 +382,7 @@ $sql.= ' f.rowid as id, f.ref, f.ref_client, f.type, f.note_private, f.note_publ $sql.= ' f.localtax1 as total_localtax1, f.localtax2 as total_localtax2,'; $sql.= ' f.datef as df, f.date_lim_reglement as datelimite,'; $sql.= ' f.paye as paye, f.fk_statut,'; -$sql.= ' f.datec as date_creation, f.tms as date_update,'; +$sql.= ' f.datec as date_creation, f.tms as date_update, f.date_cloture as date_cloture,'; if($conf->global->INVOICE_USE_SITUATION && $conf->global->INVOICE_USE_SITUATION_RETAINED_WARRANTY) { $sql.= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final,f.situation_cycle_ref,f.situation_counter,'; @@ -495,7 +496,7 @@ if (! $sall) $sql.= ' f.localtax1, f.localtax2,'; $sql.= ' f.datef, f.date_lim_reglement,'; $sql.= ' f.paye, f.fk_statut,'; - $sql.= ' f.datec, f.tms,'; + $sql.= ' f.datec, f.tms, f.date_cloture,'; $sql.= ' s.rowid, s.nom, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; $sql.= ' typent.code,'; $sql.= ' state.code_departement, state.nom,'; @@ -864,6 +865,12 @@ if ($resql) print ''; print ''; } + if (! empty($arrayfields['f.date_cloture']['checked'])) + { + print ''; + print ''; + } + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; @@ -930,6 +937,7 @@ if ($resql) print $hookmanager->resPrint; 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.date_cloture']['checked'])) print_liste_field_titre($arrayfields['f.date_cloture']['label'], $_SERVER["PHP_SELF"], "f.date_cloture", "", $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,f.paye,f.type,dynamount_payed", "", $param, 'class="right"', $sortfield, $sortorder); print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); print "\n"; @@ -1260,6 +1268,14 @@ if ($resql) print ''; if (! $i) $totalarray['nbfield']++; } + // Date cloture + if (! empty($arrayfields['f.date_cloture']['checked'])) + { + print ''; + print dol_print_date($db->jdate($obj->date_cloture), 'dayhour', 'tzuser'); + print ''; + if (! $i) $totalarray['nbfield']++; + } // Status if (! empty($arrayfields['f.fk_statut']['checked'])) { From 5d81b0271d6a6eedae203ddaaefcf6c598aaa16c Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 6 Sep 2019 11:40:26 +0200 Subject: [PATCH 023/324] Update facture.class.php --- htdocs/compta/facture/class/facture.class.php | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 131f0ee90fd..73323235448 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -2136,6 +2136,8 @@ class Facture extends CommonInvoice if ($this->paye != 1) { $this->db->begin(); + + $now=dol_now(); dol_syslog(get_class($this)."::set_paid rowid=".$this->id, LOG_DEBUG); @@ -2144,6 +2146,8 @@ class Facture extends CommonInvoice if (! $close_code) $sql.= ', paye=1'; if ($close_code) $sql.= ", close_code='".$this->db->escape($close_code)."'"; if ($close_note) $sql.= ", close_note='".$this->db->escape($close_note)."'"; + $sql.= ', fk_user_cloture = '.$user->id; + $sql.= ", date_cloture = '".$this->db->idate($now)."'"; $sql.= ' WHERE rowid = '.$this->id; $resql = $this->db->query($sql); @@ -2196,6 +2200,8 @@ class Facture extends CommonInvoice $sql = 'UPDATE '.MAIN_DB_PREFIX.'facture'; $sql.= ' SET paye=0, fk_statut='.self::STATUS_VALIDATED.', close_code=null, close_note=null'; + $sql.= ' date_cloture as datecloture,'; + $sql.= ' fk_user_author, fk_user_valid, fk_user_cloture'; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_unpaid", LOG_DEBUG); @@ -3521,7 +3527,8 @@ class Facture extends CommonInvoice public function info($id) { $sql = 'SELECT c.rowid, datec, date_valid as datev, tms as datem,'; - $sql.= ' fk_user_author, fk_user_valid'; + $sql.= ' date_cloture as datecloture,'; + $sql.= ' fk_user_author, fk_user_valid, fk_user_cloture'; $sql.= ' FROM '.MAIN_DB_PREFIX.'facture as c'; $sql.= ' WHERE c.rowid = '.$id; @@ -3536,7 +3543,7 @@ class Facture extends CommonInvoice { $cuser = new User($this->db); $cuser->fetch($obj->fk_user_author); - $this->user_creation = $cuser; + $this->user_creation = $cuser; } if ($obj->fk_user_valid) { @@ -3544,9 +3551,17 @@ class Facture extends CommonInvoice $vuser->fetch($obj->fk_user_valid); $this->user_validation = $vuser; } + if ($obj->fk_user_cloture) + { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + $this->date_creation = $this->db->jdate($obj->datec); $this->date_modification = $this->db->jdate($obj->datem); - $this->date_validation = $this->db->jdate($obj->datev); // Should be in log table + $this->date_validation = $this->db->jdate($obj->datev); + $this->date_cloture = $this->db->jdate($obj->datecloture); } $this->db->free($result); } From 2d3b0a7d43b529913dce11579207d4b34c50a9f2 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 8 Sep 2019 20:05:13 +0200 Subject: [PATCH 024/324] Update adherent.class.php --- htdocs/adherents/class/adherent.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 1b516e1c94e..28667cb047f 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -581,6 +581,7 @@ class Adherent extends CommonObject $sql.= ", fk_adherent_type = ".$this->db->escape($this->typeid); $sql.= ", morphy = '".$this->db->escape($this->morphy)."'"; $sql.= ", birth = ".($this->birth?"'".$this->db->idate($this->birth)."'":"null"); + if ($this->socid) $sql.= ", fk_soc = '".$this->db->escape($this->socid)."'"; // Must be modified only when creating from a thirdpart if ($this->datefin) $sql.= ", datefin = '".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription if ($this->datevalid) $sql.= ", datevalid = '".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member $sql.= ", fk_user_mod = ".($user->id>0?$user->id:'null'); // Can be null because member can be create by a guest From a83c0670811683075c684ff07d92dbeccb79475e Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 8 Sep 2019 20:08:32 +0200 Subject: [PATCH 025/324] Update card.php --- htdocs/adherents/card.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 5836bf48332..d443eb6e462 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -866,6 +866,18 @@ else $object->country_code=$tmparray['code']; $object->country=$tmparray['label']; } + + if (!empty($socid)) { +$object = new Societe($db); +if ($socid > 0) $object->fetch($socid); + +if (! ($object->id > 0)) +{ + $langs->load("errors"); + print($langs->trans('ErrorRecordNotFound')); + exit; +} + } $adht = new AdherentType($db); @@ -905,6 +917,7 @@ else print '
    '; print ''; print ''; + print ''; if ($backtopage) print ''; dol_fiche_head(''); From 1368236d29c060e59235ef88b9c30f2ff7ac2ae5 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 8 Sep 2019 20:15:05 +0200 Subject: [PATCH 026/324] Update card.php --- htdocs/societe/card.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index ab224245de8..2d26747df32 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -2664,6 +2664,16 @@ else { print ''."\n"; } + + if (! empty($conf->adherent->enabled)) + { + $adh = new Adherent($db); + $result=$adh->fetch('','',$object->id); + if (!$result && $object->client == 1) + { + print ''.$langs->trans("NewMember").''; + } + } if ($user->rights->societe->supprimer) { From e37875f70a597e011514b233d5dcaded2a0851be Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 8 Sep 2019 20:16:05 +0200 Subject: [PATCH 027/324] Update card.php --- htdocs/societe/card.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 2d26747df32..ee6ca0288ef 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -47,7 +47,8 @@ require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; if (! empty($conf->adherent->enabled)) require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; -$langs->loadLangs(array("companies","commercial","bills","banks","users")); +$langs->loadLangs(array("companies", "commercial", "bills", "banks", "users")); +if (! empty($conf->adherent->enabled)) $langs->load("members"); if (! empty($conf->categorie->enabled)) $langs->load("categories"); if (! empty($conf->incoterm->enabled)) $langs->load("incoterm"); if (! empty($conf->notification->enabled)) $langs->load("mails"); From 2e63e7bc27ffcd53e9c3c89764244613451ed019 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 8 Sep 2019 18:17:51 +0000 Subject: [PATCH 028/324] Fixing style errors. --- htdocs/societe/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index ee6ca0288ef..8c1db93c53b 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -2669,11 +2669,11 @@ else if (! empty($conf->adherent->enabled)) { $adh = new Adherent($db); - $result=$adh->fetch('','',$object->id); + $result=$adh->fetch('', '', $object->id); if (!$result && $object->client == 1) { print ''.$langs->trans("NewMember").''; - } + } } if ($user->rights->societe->supprimer) From 617e430998034d71b59b5b864f5a7e0911be9b9a Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 9 Sep 2019 12:31:17 +0200 Subject: [PATCH 029/324] fix stravis and sticker --- htdocs/core/class/html.formcompany.class.php | 2 +- htdocs/install/mysql/migration/10.0.0-11.0.0.sql | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 81b87b6f340..c7467922da5 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -755,7 +755,7 @@ class FormCompany extends Form * @param array $selected $key=>$val $val is selected Roles for input mode * @return string String with contacts roles */ - public function showRoles($htmlname = '', Contact $contact, $rendermode = 'view', $selected = array()) + public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array()) { if ($rendermode === 'view') { $toprint = array(); diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index ec124c8a1a1..2caf438b471 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -175,4 +175,5 @@ INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, m INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('IN-REPUBLICDAY', 0, 117, '', 0, 1, 26, 1); INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('IN-GANDI', 0, 117, '', 0, 10, 2, 1); - +ALTER TABLE llx_supplier_proposaldet ADD COLUMN date_start datetime DEFAULT NULL AFTER product_type; +ALTER TABLE llx_supplier_proposaldet ADD COLUMN date_end datetime DEFAULT NULL AFTER date_start; From 42b3640a5a0cdb0ffc463e720c5f6e0a04fe9c15 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 9 Sep 2019 14:12:28 +0200 Subject: [PATCH 030/324] fix travis --- .../triggers/interface_90_modSociete_ContactRoles.class.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php index 36a8274c602..8d2418a8a94 100644 --- a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php +++ b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php @@ -81,12 +81,11 @@ class InterfaceContactRoles extends DolibarrTriggers if(!empty($socid) && $socid != '-1') { global $db, $langs; - var_dump($socid); + require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; $contactdefault = new Contact($this->db); $contactdefault->socid=$socid; $TContact = $contactdefault->getContactRoles($object->element); - // Le trigger est appelé avant que le core n'ajoute lui-même des contacts (contact propale, clone), il ne faut pas les associer avant sinon bug $TContactAlreadyLinked = array(); if ($object->id > 0) { @@ -98,7 +97,6 @@ class InterfaceContactRoles extends DolibarrTriggers } foreach($TContact as $i => $infos) { - // Gestion du cas du clone foreach ($TContactAlreadyLinked as $contactData) { if($contactData['id'] == $infos['fk_socpeople'] && $contactData['fk_c_type_contact'] == $infos['type_contact']) unset($TContact[$i]); } @@ -106,7 +104,6 @@ class InterfaceContactRoles extends DolibarrTriggers $nb = 0; foreach($TContact as $infos) { - // Gestion du cas spécifique de la création de propale avec sélection du contact, cela créé un bug si le contact est ajouté par le module contactdefault $res = $object->add_contact($infos['fk_socpeople'], $infos['type_contact']); if($res > 0) $nb++; } From ee931d0f25dfe42fa9138b180815a9beca1f7ceb Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 9 Sep 2019 14:53:23 +0200 Subject: [PATCH 031/324] fix travis --- .../interface_90_modSociete_ContactRoles.class.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php index 8d2418a8a94..e9bf9d38a50 100644 --- a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php +++ b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php @@ -53,14 +53,8 @@ class InterfaceContactRoles extends DolibarrTriggers * All functions "runTrigger" are triggered if file is inside directory htdocs/core/triggers or htdocs/module/code/triggers (and declared) * * Following properties may be set before calling trigger. The may be completed by this trigger to be used for writing the event into database: - * $object->actiontypecode (translation action code: AC_OTH, ...) - * $object->actionmsg (note, long text) - * $object->actionmsg2 (label, short text) - * $object->sendtoid (id of contact or array of ids) - * $object->socid (id of thirdparty) - * $object->fk_project - * $object->fk_element - * $object->elementtype + * $object->socid or $object->fk_soc(id of thirdparty) + * $object->element (element type of object) * * @param string $action Event action code * @param Object $object Object @@ -113,5 +107,6 @@ class InterfaceContactRoles extends DolibarrTriggers } } } - } + return 0; + } } From ad92efaee14e8ad5e8523fd6064928ad917cee7a Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 9 Sep 2019 14:58:29 +0200 Subject: [PATCH 032/324] add trans --- htdocs/langs/en_US/main.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index c4611836a51..04f45f8de4b 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1004,3 +1004,4 @@ ContactDefault_project_task=Task ContactDefault_propal=Proposal ContactDefault_supplier_proposal=Supplier Proposal ContactDefault_ticketsup=Ticket +ContactAddedAutomatically=Contact added from contact thirdparty roles From 95417d4c86129b1a55283d097ebece7857b87265 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Tue, 10 Sep 2019 16:24:04 +0200 Subject: [PATCH 033/324] allow standalone credit note even if no invoice --- htdocs/compta/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index d81467d64e4..3d363b60bb2 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3047,7 +3047,7 @@ if ($action == 'create') { print '
    '; $tmp='global->INVOICE_CREDIT_NOTE_STANDALONE) ) $tmp.=' disabled'; $tmp.= '> '; // Show credit note options only if we checked credit note print ''; + } + + $ret.= ''."\n"; + + return $ret; +} \ No newline at end of file diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index ce8b1d6027e..1584bded9f7 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1606,6 +1606,12 @@ function top_menu($head, $title = '', $target = '', $disablejs = 0, $disablehead print '