From d4ee1836629331109721bcd3f8eba1917a2d7fe0 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 4 Nov 2015 18:21:59 +0100 Subject: [PATCH 001/138] FIX : 3880 --- htdocs/fourn/facture/card.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index c39128218d5..cd3d0763f13 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -84,6 +84,7 @@ $extralabels=$extrafields->fetch_name_optionals_label($object->table_element); if ($id > 0 || ! empty($ref)) { $ret=$object->fetch($id, $ref); + $object->fetch_thirdparty(); } $permissionnote=$user->rights->fournisseur->facture->creer; // Used by the include of actions_setnotes.inc.php @@ -2097,10 +2098,10 @@ else global $forceall, $senderissupplier, $dateSelector, $inputalsopricewithtax; $forceall=1; $senderissupplier=1; $dateSelector=0; $inputalsopricewithtax=1; - + // Show object lines if (! empty($object->lines)) - $ret = $object->printObjectLines($action, $soc, $mysoc, $lineid, 1); + $ret = $object->printObjectLines($action, $societe, $mysoc, $lineid, 1); $num=count($object->lines); From 876ab4bb592204a9dc112f88abee1e0fd9928de1 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 4 Nov 2015 18:30:09 +0100 Subject: [PATCH 002/138] FIX : #3882 --- htdocs/fourn/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index cd3d0763f13..21aab088fd0 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1520,7 +1520,7 @@ if ($action == 'create') if ($cntinvoice>=1) { setEventMessage('WarningBillExist','warnings'); - echo ' ('.$langs->trans('LatestRelatedBill').end($objectsrc->linkedObjects['facture'])->getNomUrl(1).')'; + echo ' ('.$langs->trans('LatestRelatedBill').end($objectsrc->linkedObjects['invoice_supplier'])->getNomUrl(1).')'; } echo ''; print ''.$langs->trans('TotalHT').''.price($objectsrc->total_ht).''; From c534f5bcd51485747c808c76128b22b60e7cc9f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Doursenaud?= Date: Wed, 4 Nov 2015 20:34:18 +0100 Subject: [PATCH 003/138] Fix #3805 Enhanced Facture::is_last_in_cycle() --- htdocs/compta/facture/class/facture.class.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index eee909645d7..cfbb0491be2 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3672,11 +3672,16 @@ class Facture extends CommonInvoice /** * Checks if the invoice is the last in its cycle * - * @return int 0 or 1 if OK, -1 if error + * @return bool Last of the cycle status * */ function is_last_in_cycle() { + if (empty($this->situation_cycle_ref)) { + // No point in testing anything if we're not inside a cycle + return false; + } + $sql = 'SELECT max(situation_counter) FROM ' . MAIN_DB_PREFIX . 'facture WHERE situation_cycle_ref = ' . $this->situation_cycle_ref; $resql = $this->db->query($sql); @@ -3687,8 +3692,7 @@ class Facture extends CommonInvoice } else { $this->error = $this->db->lasterror(); dol_syslog(get_class($this) . "::select Error " . $this->error, LOG_ERR); - $this->db->rollback(); - return -1; + return false; } } From f319976e5df84c248123ff6ef3bba9896005a11b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 5 Nov 2015 03:02:31 +0100 Subject: [PATCH 004/138] FIX #3878 Storing and deleting files on emailing was done at wrong place Conflicts: htdocs/comm/mailing/card.php --- htdocs/comm/mailing/card.php | 14 +++++++++++--- htdocs/core/lib/functions.lib.php | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index b7d4f909fa7..e1d357b6c3a 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -544,7 +544,7 @@ if (empty($reshook)) require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - dol_remove_file_process($_POST['removedfile'],0); + dol_remove_file_process($_POST['removedfile'],0,0); // We really delete file linked to mailing $action="edit"; } @@ -1093,7 +1093,10 @@ else } print ''; - print ""; + + dol_fiche_end(); + + print "\n"; print '
'."\n"; @@ -1103,6 +1106,9 @@ else // Print mail content print_fiche_titre($langs->trans("EMail"),'',''); + + dol_fiche_head(); + print ''; // Subject @@ -1168,7 +1174,9 @@ else print '
'; - print '
'; + dol_fiche_end(); + + print '
'; print ''; print '     '; print ''; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index df6b3d325c5..8c71b882d21 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3762,7 +3762,7 @@ function get_exdir($num,$level,$alpha,$withoutslash,$object,$modulepart) $path = ''; - if (! empty($level) && in_array($modulepart, array('cheque','user','category','holiday','shipment', 'member','don','donation','supplier_invoice','invoice_supplier'))) + if (! empty($level) && in_array($modulepart, array('cheque','user','category','holiday','shipment', 'member','don','donation','supplier_invoice','invoice_supplier','mailing'))) { // This part should be removed once all code is using "get_exdir" to forge path, with all parameters provided if (empty($alpha)) $num = preg_replace('/([^0-9])/i','',$num); From 015dedc3abcc27dc9f271d23ff68e19200d9f8b1 Mon Sep 17 00:00:00 2001 From: fmarcet Date: Thu, 5 Nov 2015 11:53:45 +0100 Subject: [PATCH 005/138] FIX: Show category selector if we have permission to view products or services --- htdocs/comm/propal/list.php | 2 +- htdocs/commande/list.php | 2 +- htdocs/compta/facture/list.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 1004986ffe5..3f4f692bdcd 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -284,7 +284,7 @@ if ($result) $moreforfilter.='
'; } // If the user can view prospects other than his' - if ($conf->categorie->enabled && $user->rights->produit->lire) + if ($conf->categorie->enabled && ($user->rights->produit->lire || $user->rights->service->lire)) { include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $moreforfilter.='
'; diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index db11df409f6..517cd95e536 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -281,7 +281,7 @@ if ($resql) $moreforfilter.='
'; } // If the user can view prospects other than his' - if ($conf->categorie->enabled && $user->rights->produit->lire) + if ($conf->categorie->enabled && ($user->rights->produit->lire || $user->rights->service->lire)) { include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $moreforfilter.='
'; diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 93874ac5e80..2581bb382ca 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -296,7 +296,7 @@ if ($resql) $moreforfilter.='
'; } // If the user can view prospects other than his' - if ($conf->categorie->enabled && $user->rights->produit->lire) + if ($conf->categorie->enabled && ($user->rights->produit->lire || $user->rights->service->lire)) { include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $moreforfilter.='
'; From e78ebf041a78f8b228392eb8bf4ec074ed4c7192 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 6 Nov 2015 02:02:57 +0100 Subject: [PATCH 006/138] Fix deprecated code not working in jcrop. $.browser.msie and $.browser is no more available in jquery 1.9+. --- htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.js | 9 +++------ .../includes/jquery/plugins/jcrop/js/jquery.Jcrop.min.js | 9 ++++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.js b/htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.js index ad261f97aec..a31a0a10592 100755 --- a/htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.js +++ b/htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.js @@ -43,13 +43,11 @@ $.Jcrop = function(obj,opt) // Some on-the-fly fixes for MSIE...sigh if (!('trackDocument' in opt)) { - opt.trackDocument = $.browser.msie ? false : true; - if ($.browser.msie && $.browser.version.split('.')[0] == '8') - opt.trackDocument = true; + opt.trackDocument = true; } if (!('keySupport' in opt)) - opt.keySupport = $.browser.msie ? false : true; + opt.keySupport = true; // }}} // Extend the default options {{{ @@ -416,7 +414,7 @@ $.Jcrop = function(obj,opt) if (options.drawBorders) { borders = { top: insertBorder('hline') - .css('top',$.browser.msie?px(-1):px(0)), + .css('top',px(0)), bottom: insertBorder('hline'), left: insertBorder('vline'), right: insertBorder('vline') @@ -965,7 +963,6 @@ $.Jcrop = function(obj,opt) function newTracker() { var trk = $('
').addClass(cssClass('tracker')); - $.browser.msie && trk.css({ opacity: 0, backgroundColor: 'white' }); return trk; }; diff --git a/htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.min.js b/htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.min.js index 9002b9787f2..c3c932b8349 100755 --- a/htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.min.js +++ b/htdocs/includes/jquery/plugins/jcrop/js/jquery.Jcrop.min.js @@ -8,10 +8,9 @@ (function($){$.Jcrop=function(obj,opt) {var obj=obj,opt=opt;if(typeof(obj)!=='object')obj=$(obj)[0];if(typeof(opt)!=='object')opt={};if(!('trackDocument'in opt)) -{opt.trackDocument=$.browser.msie?false:true;if($.browser.msie&&$.browser.version.split('.')[0]=='8') -opt.trackDocument=true;} +{opt.trackDocument=true;} if(!('keySupport'in opt)) -opt.keySupport=$.browser.msie?false:true;var defaults={trackDocument:false,baseClass:'jcrop',addClass:null,bgColor:'black',bgOpacity:.6,borderOpacity:.4,handleOpacity:.5,handlePad:5,handleSize:9,handleOffset:5,edgeMargin:14,aspectRatio:0,keySupport:true,cornerHandles:true,sideHandles:true,drawBorders:true,dragEdges:true,boxWidth:0,boxHeight:0,boundary:8,animationDelay:20,swingSpeed:3,allowSelect:true,allowMove:true,allowResize:true,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){}};var options=defaults;setOptions(opt);var $origimg=$(obj);var $img=$origimg.clone().removeAttr('id').css({position:'absolute'});$img.width($origimg.width());$img.height($origimg.height());$origimg.after($img).hide();presize($img,options.boxWidth,options.boxHeight);var boundx=$img.width(),boundy=$img.height(),$div=$('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({position:'relative',backgroundColor:options.bgColor}).insertAfter($origimg).append($img);;if(options.addClass)$div.addClass(options.addClass);var $img2=$('').attr('src',$img.attr('src')).css('position','absolute').width(boundx).height(boundy);var $img_holder=$('
').width(pct(100)).height(pct(100)).css({zIndex:310,position:'absolute',overflow:'hidden'}).append($img2);var $hdl_holder=$('
').width(pct(100)).height(pct(100)).css('zIndex',320);var $sel=$('
').css({position:'absolute',zIndex:300}).insertBefore($img).append($img_holder,$hdl_holder);var bound=options.boundary;var $trk=newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)).css({position:'absolute',top:px(-bound),left:px(-bound),zIndex:290}).mousedown(newSelection);var xlimit,ylimit,xmin,ymin;var xscale,yscale,enabled=true;var docOffset=getPos($img),btndown,lastcurs,dimmed,animating,shift_down;var Coords=function() +opt.keySupport=true;var defaults={trackDocument:false,baseClass:'jcrop',addClass:null,bgColor:'black',bgOpacity:.6,borderOpacity:.4,handleOpacity:.5,handlePad:5,handleSize:9,handleOffset:5,edgeMargin:14,aspectRatio:0,keySupport:true,cornerHandles:true,sideHandles:true,drawBorders:true,dragEdges:true,boxWidth:0,boxHeight:0,boundary:8,animationDelay:20,swingSpeed:3,allowSelect:true,allowMove:true,allowResize:true,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){}};var options=defaults;setOptions(opt);var $origimg=$(obj);var $img=$origimg.clone().removeAttr('id').css({position:'absolute'});$img.width($origimg.width());$img.height($origimg.height());$origimg.after($img).hide();presize($img,options.boxWidth,options.boxHeight);var boundx=$img.width(),boundy=$img.height(),$div=$('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({position:'relative',backgroundColor:options.bgColor}).insertAfter($origimg).append($img);;if(options.addClass)$div.addClass(options.addClass);var $img2=$('').attr('src',$img.attr('src')).css('position','absolute').width(boundx).height(boundy);var $img_holder=$('
').width(pct(100)).height(pct(100)).css({zIndex:310,position:'absolute',overflow:'hidden'}).append($img2);var $hdl_holder=$('
').width(pct(100)).height(pct(100)).css('zIndex',320);var $sel=$('
').css({position:'absolute',zIndex:300}).insertBefore($img).append($img_holder,$hdl_holder);var bound=options.boundary;var $trk=newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)).css({position:'absolute',top:px(-bound),left:px(-bound),zIndex:290}).mousedown(newSelection);var xlimit,ylimit,xmin,ymin;var xscale,yscale,enabled=true;var docOffset=getPos($img),btndown,lastcurs,dimmed,animating,shift_down;var Coords=function() {var x1=0,y1=0,x2=0,y2=0,ox,oy;function setPressed(pos) {var pos=rebound(pos);x2=x1=pos[0];y2=y1=pos[1];};function setCurrent(pos) {var pos=rebound(pos);ox=pos[0]-x2;oy=pos[1]-y2;x2=pos[0];y2=pos[1];};function getOffset() @@ -57,7 +56,7 @@ if(x1>boundx){var delta=x1-boundy;y2-=delta;y1-=delta;} if(y1>boundy){var delta=y1-boundy;y2-=delta;y1-=delta;} return makeObj(flipCoords(x1,y1,x2,y2));};function makeObj(a) {return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]};};return{flipCoords:flipCoords,setPressed:setPressed,setCurrent:setCurrent,getOffset:getOffset,moveOffset:moveOffset,getCorner:getCorner,getFixed:getFixed};}();var Selection=function() -{var start,end,dragmode,awake,hdep=370;var borders={};var handle={};var seehandles=false;var hhs=options.handleOffset;if(options.drawBorders){borders={top:insertBorder('hline').css('top',$.browser.msie?px(-1):px(0)),bottom:insertBorder('hline'),left:insertBorder('vline'),right:insertBorder('vline')};} +{var start,end,dragmode,awake,hdep=370;var borders={};var handle={};var seehandles=false;var hhs=options.handleOffset;if(options.drawBorders){borders={top:insertBorder('hline').css('top',px(0)),bottom:insertBorder('hline'),left:insertBorder('vline'),right:insertBorder('vline')};} if(options.dragEdges){handle.t=insertDragbar('n');handle.b=insertDragbar('s');handle.r=insertDragbar('e');handle.l=insertDragbar('w');} options.sideHandles&&createHandles(['n','s','e','w']);options.cornerHandles&&createHandles(['sw','nw','ne','se']);function insertBorder(type) {var jq=$('
').css({position:'absolute',opacity:options.borderOpacity}).addClass(cssClass(type));$img_holder.append(jq);return jq;};function dragDiv(ord,zi) @@ -134,7 +133,7 @@ else Tracker.setCursor(options.allowSelect?'crosshair':'default');};function newSelection(e) {if(options.disabled)return false;if(!options.allowSelect)return false;btndown=true;docOffset=getPos($img);Selection.disableHandles();myCursor('crosshair');var pos=mouseAbs(e);Coords.setPressed(pos);Tracker.activateHandlers(selectDrag,doneSelect);KeyManager.watchKeys();Selection.update();e.stopPropagation();e.preventDefault();return false;};function selectDrag(pos) {Coords.setCurrent(pos);Selection.update();};function newTracker() -{var trk=$('
').addClass(cssClass('tracker'));$.browser.msie&&trk.css({opacity:0,backgroundColor:'white'});return trk;};function animateTo(a) +{var trk=$('
').addClass(cssClass('tracker'));return trk;};function animateTo(a) {var x1=a[0]/xscale,y1=a[1]/yscale,x2=a[2]/xscale,y2=a[3]/yscale;if(animating)return;var animto=Coords.flipCoords(x1,y1,x2,y2);var c=Coords.getFixed();var animat=initcr=[c.x,c.y,c.x2,c.y2];var interv=options.animationDelay;var x=animat[0];var y=animat[1];var x2=animat[2];var y2=animat[3];var ix1=animto[0]-initcr[0];var iy1=animto[1]-initcr[1];var ix2=animto[2]-initcr[2];var iy2=animto[3]-initcr[3];var pcent=0;var velocity=options.swingSpeed;Selection.animMode(true);var animator=function() {return function() {pcent+=(100-pcent)/velocity;animat[0]=x+((pcent/100)*ix1);animat[1]=y+((pcent/100)*iy1);animat[2]=x2+((pcent/100)*ix2);animat[3]=y2+((pcent/100)*iy2);if(pcent<100)animateStart();else Selection.done();if(pcent>=99.8)pcent=100;setSelectRaw(animat);};}();function animateStart() From 8d829dca320ca0a9c864a9052447a8d55043d483 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 6 Nov 2015 09:49:02 +0100 Subject: [PATCH 007/138] FIX : only active customer should be return into new invoice creation select list --- htdocs/compta/facture.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index a69b35c9559..4e05be21c01 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -1855,7 +1855,7 @@ if ($action == 'create') else { print ''; - print $form->select_company('', 'socid', 's.client = 1 OR s.client = 3', 1); + print $form->select_company('', 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 1); print ''; } print '' . "\n"; From 4d11205a01f056dd1a0dd2baf1223e35ef953d60 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 6 Nov 2015 09:51:33 +0100 Subject: [PATCH 008/138] FIX: change object statut on close shipping and remove erratic db commit --- htdocs/expedition/class/expedition.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index e68b063d7d2..106befda596 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -1542,8 +1542,8 @@ class Expedition extends CommonObject if ($this->db->query($sql) ) { //TODO: Option to set order billed if 100% of order is shipped + $this->statut=2; $this->billed=1; - $this->db->commit(); return 1; } else From 126b5d6ecae5b74f5395638f8de109c7cab62a4f Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 6 Nov 2015 10:19:10 +0100 Subject: [PATCH 009/138] FIX : only active customer should be available into select list thirdparty on invoice creation --- htdocs/compta/facture.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index 9608bd87a0c..191a45831fc 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -1957,7 +1957,7 @@ if ($action == 'create') else { print ''; - print $form->select_company('', 'socid', 's.client = 1 OR s.client = 3', 1); + print $form->select_company('', 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 1); print ''; } print '' . "\n"; From 121d2beb8067fd224d440c90d646f9371fb4398d Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 6 Nov 2015 10:34:18 +0100 Subject: [PATCH 010/138] fix spacing --- htdocs/compta/facture.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index 191a45831fc..fb6548c3e87 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -1957,7 +1957,7 @@ if ($action == 'create') else { print ''; - print $form->select_company('', 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 1); + print $form->select_company('', 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 1); print ''; } print '' . "\n"; From f6b8c3a13030fad347b4dc52df9e0ffa7d59056a Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 6 Nov 2015 10:50:08 +0100 Subject: [PATCH 011/138] FIX : #3912 --- htdocs/install/mysql/migration/3.7.0-3.8.0.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 2241c35f00d..d31a8853a36 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -476,7 +476,7 @@ ALTER TABLE llx_societe_extrafields DROP INDEX idx_societe_extrafields; ALTER TABLE llx_societe_extrafields ADD UNIQUE INDEX uk_societe_extrafields (fk_object); -- Module Donation -ALTER TABLE llx_don ADD COLUMN fk_country integer NOT NULL after country; +ALTER TABLE llx_don ADD COLUMN fk_country integer NOT NULL DEFAULT 0 after country; ALTER TABLE llx_don CHANGE COLUMN fk_paiement fk_payment integer; ALTER TABLE llx_don ADD COLUMN paid smallint default 0 NOT NULL after fk_payment; ALTER TABLE llx_don CHANGE COLUMN fk_don_projet fk_projet integer NULL; From b0be2b04c7bee60c2f65eb6fde3f2c511ba81d80 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 6 Nov 2015 10:53:33 +0100 Subject: [PATCH 012/138] FIX : #3912 --- .../install/mysql/migration/3.7.0-3.8.0.sql | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index d31a8853a36..965704f5309 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -14,7 +14,7 @@ -- To make pk to be auto increment (mysql): VMYSQL4.3 ALTER TABLE llx_c_shipment_mode CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; -- To make pk to be auto increment (postgres): VPGSQL8.2 NOT POSSIBLE. MUST DELETE/CREATE TABLE -- To set a field as NULL: VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL; --- To set a field as default NULL: VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; +-- To set a field as DEFAULT NULL: VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; -- To delete orphelins: VMYSQL4.1 DELETE FROM llx_usergroup_user WHERE fk_usergroup NOT IN (SELECT rowid from llx_usergroup); -- To delete orphelins: VPGSQL8.2 DELETE FROM llx_usergroup_user WHERE fk_user NOT IN (SELECT rowid from llx_user); @@ -30,8 +30,8 @@ insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,localtax1,localtax1_typ -- Taiwan VAT Rates insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 2131, 213, '5', '0', 'VAT 5%', 1); -ALTER TABLE llx_societe_rib ADD COLUMN rum varchar(32) after default_rib; -ALTER TABLE llx_societe_rib ADD COLUMN frstrecur varchar(16) default 'FRST' after rum; +ALTER TABLE llx_societe_rib ADD COLUMN rum varchar(32) AFTER default_rib; +ALTER TABLE llx_societe_rib ADD COLUMN frstrecur varchar(16) DEFAULT 'FRST' AFTER rum; ALTER TABLE llx_cronjob ADD COLUMN entity integer DEFAULT 0; ALTER TABLE llx_cronjob MODIFY COLUMN params text NULL; @@ -45,16 +45,16 @@ create table llx_loan tms timestamp, label varchar(80) NOT NULL, fk_bank integer, - capital real default 0 NOT NULL, + capital real DEFAULT 0 NOT NULL, datestart date, dateend date, nbterm real, rate double NOT NULL, note_private text, note_public text, - capital_position real default 0, + capital_position real DEFAULT 0, date_position date, - paid smallint default 0 NOT NULL, + paid smallint DEFAULT 0 NOT NULL, accountancy_account_capital varchar(32), accountancy_account_insurance varchar(32), accountancy_account_interest varchar(32), @@ -83,10 +83,10 @@ create table llx_payment_loan )ENGINE=innodb; ALTER TABLE llx_extrafields ADD COLUMN fieldrequired integer DEFAULT 0; -ALTER TABLE llx_extrafields ADD COLUMN perms varchar(255) after fieldrequired; -ALTER TABLE llx_extrafields ADD COLUMN list integer DEFAULT 0 after perms; +ALTER TABLE llx_extrafields ADD COLUMN perms varchar(255) AFTER fieldrequired; +ALTER TABLE llx_extrafields ADD COLUMN list integer DEFAULT 0 AFTER perms; -ALTER TABLE llx_payment_salary ADD COLUMN salary real after datev; +ALTER TABLE llx_payment_salary ADD COLUMN salary real AFTER datev; ALTER TABLE llx_payment_salary ADD INDEX idx_payment_salary_ref (num_payment); ALTER TABLE llx_payment_salary ADD INDEX idx_payment_salary_user (fk_user, entity); @@ -98,7 +98,7 @@ ALTER TABLE llx_payment_salary ADD CONSTRAINT fk_payment_salary_user FOREIGN KEY UPDATE llx_projet_task_time SET task_datehour = task_date where task_datehour IS NULL; -ALTER TABLE llx_projet_task_time ADD COLUMN task_date_withhour integer DEFAULT 0 after task_datehour; +ALTER TABLE llx_projet_task_time ADD COLUMN task_date_withhour integer DEFAULT 0 AFTER task_datehour; ALTER TABLE llx_projet_task MODIFY COLUMN duration_effective real DEFAULT 0 NULL; ALTER TABLE llx_projet_task MODIFY COLUMN planned_workload real DEFAULT 0 NULL; @@ -129,8 +129,8 @@ ALTER TABLE llx_product_fournisseur_price ADD COLUMN fk_supplier_price_expressio ALTER TABLE llx_product ADD COLUMN fk_price_expression integer DEFAULT NULL; ALTER TABLE llx_product_price ADD COLUMN fk_price_expression integer DEFAULT NULL; -ALTER TABLE llx_product ADD COLUMN fifo double(24,8) after pmp; -ALTER TABLE llx_product ADD COLUMN lifo double(24,8) after fifo; +ALTER TABLE llx_product ADD COLUMN fifo double(24,8) AFTER pmp; +ALTER TABLE llx_product ADD COLUMN lifo double(24,8) AFTER fifo; --create table for user conf of printing driver @@ -244,7 +244,7 @@ CREATE TABLE llx_expensereport ( fk_user_cancel integer DEFAULT NULL, fk_statut integer NOT NULL, -- 1=brouillon, 2=validé (attente approb), 4=annulé, 5=approuvé, 6=payed, 99=refusé fk_c_paiement integer DEFAULT NULL, - paid smallint default 0 NOT NULL, + paid smallint DEFAULT 0 NOT NULL, note_public text, note_private text, detail_refuse varchar(255) DEFAULT NULL, @@ -330,15 +330,15 @@ ALTER TABLE llx_facture_fourn_det_extrafields ADD INDEX idx_facture_fourn_det_ex ALTER TABLE llx_facture_fourn_det ADD COLUMN special_code integer DEFAULT 0; ALTER TABLE llx_facture_fourn_det ADD COLUMN rang integer DEFAULT 0; -ALTER TABLE llx_facture_fourn_det ADD COLUMN fk_parent_line integer NULL after fk_facture_fourn; +ALTER TABLE llx_facture_fourn_det ADD COLUMN fk_parent_line integer NULL AFTER fk_facture_fourn; ALTER TABLE llx_commande_fournisseurdet ADD COLUMN special_code integer DEFAULT 0; ALTER TABLE llx_commande_fournisseurdet ADD COLUMN rang integer DEFAULT 0; -ALTER TABLE llx_commande_fournisseurdet ADD COLUMN fk_parent_line integer NULL after fk_commande; +ALTER TABLE llx_commande_fournisseurdet ADD COLUMN fk_parent_line integer NULL AFTER fk_commande; ALTER TABLE llx_projet ADD COLUMN date_close datetime DEFAULT NULL; ALTER TABLE llx_projet ADD COLUMN fk_user_close integer DEFAULT NULL; -ALTER TABLE llx_projet ADD COLUMN fk_opp_status integer DEFAULT NULL after fk_statut; +ALTER TABLE llx_projet ADD COLUMN fk_opp_status integer DEFAULT NULL AFTER fk_statut; ALTER TABLE llx_projet ADD COLUMN opp_amount double(24,8) DEFAULT NULL; @@ -430,8 +430,8 @@ CREATE TABLE llx_askpricesupplierdet_extrafields ( -- End Module AskPriceSupplier -- -ALTER TABLE llx_commande_fournisseur ADD COLUMN date_approve2 datetime after date_approve; -ALTER TABLE llx_commande_fournisseur ADD COLUMN fk_user_approve2 integer after fk_user_approve; +ALTER TABLE llx_commande_fournisseur ADD COLUMN date_approve2 datetime AFTER date_approve; +ALTER TABLE llx_commande_fournisseur ADD COLUMN fk_user_approve2 integer AFTER fk_user_approve; ALTER TABLE llx_societe ADD COLUMN fk_incoterms integer; ALTER TABLE llx_societe ADD COLUMN location_incoterms varchar(255); @@ -476,9 +476,9 @@ ALTER TABLE llx_societe_extrafields DROP INDEX idx_societe_extrafields; ALTER TABLE llx_societe_extrafields ADD UNIQUE INDEX uk_societe_extrafields (fk_object); -- Module Donation -ALTER TABLE llx_don ADD COLUMN fk_country integer NOT NULL DEFAULT 0 after country; +ALTER TABLE llx_don ADD COLUMN fk_country integer NOT NULL DEFAULT 0 AFTER country; ALTER TABLE llx_don CHANGE COLUMN fk_paiement fk_payment integer; -ALTER TABLE llx_don ADD COLUMN paid smallint default 0 NOT NULL after fk_payment; +ALTER TABLE llx_don ADD COLUMN paid smallint DEFAULT 0 NOT NULL AFTER fk_payment; ALTER TABLE llx_don CHANGE COLUMN fk_don_projet fk_projet integer NULL; ALTER TABLE llx_don CHANGE COLUMN fk_project fk_projet integer NULL; @@ -569,7 +569,7 @@ create table llx_c_price_global_variable_updater )ENGINE=innodb; ALTER TABLE llx_adherent CHANGE COLUMN note note_private text DEFAULT NULL; -ALTER TABLE llx_adherent ADD COLUMN note_public text DEFAULT NULL after note_private; +ALTER TABLE llx_adherent ADD COLUMN note_public text DEFAULT NULL AFTER note_private; CREATE TABLE IF NOT EXISTS llx_propal_merge_pdf_product ( rowid integer NOT NULL auto_increment PRIMARY KEY, @@ -607,28 +607,28 @@ INSERT INTO llx_c_units ( code, label, short_label, active) VALUES ('M2','square INSERT INTO llx_c_units ( code, label, short_label, active) VALUES ('M3','cubic meter','m3', 1); INSERT INTO llx_c_units ( code, label, short_label, active) VALUES ('L','liter','l', 1); -alter table llx_product add fk_unit integer default NULL; +alter table llx_product add fk_unit integer DEFAULT NULL; ALTER TABLE llx_product ADD CONSTRAINT fk_product_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid); -alter table llx_facturedet_rec add fk_unit integer default NULL; +alter table llx_facturedet_rec add fk_unit integer DEFAULT NULL; ALTER TABLE llx_facturedet_rec ADD CONSTRAINT fk_facturedet_rec_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid); -alter table llx_facturedet add fk_unit integer default NULL; +alter table llx_facturedet add fk_unit integer DEFAULT NULL; ALTER TABLE llx_facturedet ADD CONSTRAINT fk_facturedet_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid); -alter table llx_propaldet add fk_unit integer default NULL; +alter table llx_propaldet add fk_unit integer DEFAULT NULL; ALTER TABLE llx_propaldet ADD CONSTRAINT fk_propaldet_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid); -alter table llx_commandedet add fk_unit integer default NULL; +alter table llx_commandedet add fk_unit integer DEFAULT NULL; ALTER TABLE llx_commandedet ADD CONSTRAINT fk_commandedet_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid); -alter table llx_contratdet add fk_unit integer default NULL; +alter table llx_contratdet add fk_unit integer DEFAULT NULL; ALTER TABLE llx_contratdet ADD CONSTRAINT fk_contratdet_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid); -alter table llx_commande_fournisseurdet add fk_unit integer default NULL; +alter table llx_commande_fournisseurdet add fk_unit integer DEFAULT NULL; ALTER TABLE llx_commande_fournisseurdet ADD CONSTRAINT fk_commande_fournisseurdet_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid); -alter table llx_facture_fourn_det add fk_unit integer default NULL; +alter table llx_facture_fourn_det add fk_unit integer DEFAULT NULL; ALTER TABLE llx_facture_fourn_det ADD CONSTRAINT fk_facture_fourn_det_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid); From f52ae35dc6eeb9b5cd56271d4a3443ec6d10de8d Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 6 Nov 2015 16:14:00 +0100 Subject: [PATCH 013/138] NEW FEATURE PROPOSAL: on propale, order or invoice creation from scratch, reload page after customer selection so its informations can be loaded --- htdocs/comm/propal.php | 13 ++++++++++++- htdocs/commande/card.php | 15 +++++++++++++-- htdocs/compta/facture.php | 11 +++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal.php b/htdocs/comm/propal.php index 08d4e31ec6b..5b60e0ec273 100644 --- a/htdocs/comm/propal.php +++ b/htdocs/comm/propal.php @@ -1276,7 +1276,7 @@ if ($action == 'create') // Ref customer print '' . $langs->trans('RefCustomer') . ''; - print ''; + print ''; print ''; // Third party @@ -1290,6 +1290,17 @@ if ($action == 'create') } else { print ''; print $form->select_company('', 'socid', '(s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1', 1); + // reload page to retrieve customer informations + print ''; print ''; } print '' . "\n"; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 4d7456af1fd..bbc255e0227 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1338,10 +1338,10 @@ if ($action == 'create' && $user->rights->commande->creer) // Reference client print '' . $langs->trans('RefCustomer') . ''; - if (!empty($conf->global->MAIN_USE_PROPAL_REFCLIENT_FOR_ORDER)) + if (!empty($conf->global->MAIN_USE_PROPAL_REFCLIENT_FOR_ORDER) && ! empty($origin) && ! empty($originid)) print ''; else - print ''; + print ''; print ''; // Client @@ -1355,6 +1355,17 @@ if ($action == 'create' && $user->rights->commande->creer) } else { print ''; print $form->select_company('', 'socid', 's.client = 1 OR s.client = 3', 1); + // reload page to retrieve customer informations + print ''; print ''; } print '' . "\n"; diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index 983331bd412..fd9f730fe09 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -1959,6 +1959,17 @@ if ($action == 'create') { print ''; print $form->select_company('', 'socid', 's.client = 1 OR s.client = 3', 1); + // reload page to retrieve customer informations + print ''; print ''; } print '' . "\n"; From ef3c7f927ea3226b028733736b8a78ab9d6af684 Mon Sep 17 00:00:00 2001 From: Gauthier Date: Fri, 6 Nov 2015 16:38:26 +0100 Subject: [PATCH 014/138] FIX : wrong coma in llx_opensurvey_sondage.sql creation script --- htdocs/install/mysql/tables/llx_opensurvey_sondage.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql b/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql index 16e8a624e72..b728702db79 100644 --- a/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql +++ b/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql @@ -29,5 +29,5 @@ CREATE TABLE llx_opensurvey_sondage ( allow_comments tinyint NOT NULL DEFAULT 1, allow_spy tinyint NOT NULL DEFAULT 1, tms TIMESTAMP, - sujet TEXT, -- Not filled if format = 'F'. Question are into table llx_opensurvey_formquestions + sujet TEXT -- Not filled if format = 'F'. Question are into table llx_opensurvey_formquestions ) ENGINE=InnoDB; From becce332dd84c91e2105d08235cd115ca9e28392 Mon Sep 17 00:00:00 2001 From: frederic34 Date: Sat, 7 Nov 2015 09:49:25 +0100 Subject: [PATCH 015/138] allow chaining and remove header exit --- htdocs/fourn/class/fournisseur.commande.class.php | 8 ++++++++ htdocs/fourn/commande/card.php | 7 +++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 6a83aab0155..6246b47dcd3 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -946,16 +946,24 @@ class CommandeFournisseur extends CommonOrder dol_syslog(get_class($this)."::commande", LOG_DEBUG); if ($this->db->query($sql)) { + $this->statut = 3; + $this->methode_commande_id = $methode; + $this->date_commande = $this->db->idate($date); $result = 1; $this->log($user, 3, $date, $comment); } else { + $this->error = $this->db->lasterror(); + $this->errors[] = $this->db->lasterror(); $result = -1; } } else { + $result = -1; + $this->error = 'Not Authorized'; + $this->errors[] = 'Not Authorized'; dol_syslog(get_class($this)."::commande User not Authorized", LOG_ERR); } return $result ; diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index cb1754fa8d3..8078665c321 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -704,15 +704,14 @@ if (empty($reshook)) if ($action == 'confirm_commande' && $confirm == 'yes' && $user->rights->fournisseur->commande->commander) { - $result = $object->commande($user, $_REQUEST["datecommande"], $_REQUEST["methode"], $_REQUEST['comment']); + $result = $object->commande($user, $_REQUEST["datecommande"], $_REQUEST["methode"], $_REQUEST['comment']); if ($result > 0) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); } - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); - exit; - } + $action = ''; + } else { setEventMessages($object->error, $object->errors, 'errors'); From a597d6c3793c525483b0a57a752a4e7e196e7fa6 Mon Sep 17 00:00:00 2001 From: frederic34 Date: Sat, 7 Nov 2015 10:23:56 +0100 Subject: [PATCH 016/138] allow chaining --- htdocs/fourn/class/fournisseur.commande.class.php | 3 +++ htdocs/fourn/commande/card.php | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 6246b47dcd3..d64ebe263d1 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1837,6 +1837,7 @@ class CommandeFournisseur extends CommonOrder if ($resql) { $result = 0; + $this->statut = $statut; $result=$this->log($user, $statut, $date, $comment); $this->db->commit(); @@ -1851,6 +1852,8 @@ class CommandeFournisseur extends CommonOrder } else { + $this->error = 'Not Authorized'; + $this->errors[] = 'Not Authorized'; dol_syslog(get_class($this)."::Livraison Not Authorized"); $result = -3; } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 8078665c321..904cd5b3133 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -766,15 +766,15 @@ if (empty($reshook)) { $date_liv = dol_mktime(GETPOST('rehour'),GETPOST('remin'),GETPOST('resec'),GETPOST("remonth"),GETPOST("reday"),GETPOST("reyear")); - $result = $object->Livraison($user, $date_liv, GETPOST("type"), GETPOST("comment")); + $result = $object->Livraison($user, $date_liv, GETPOST("type"), GETPOST("comment")); if ($result > 0) { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); - exit; - } + setEventMessages($langs->trans("DeliveryStateSaved"), null); + $action = ''; + } else if($result == -3) { - setEventMessage($langs->trans("NotAuthorized"), 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } else { From 7349862b6464e95af3c783cd89684a212960bf2f Mon Sep 17 00:00:00 2001 From: frederic34 Date: Sat, 7 Nov 2015 11:13:58 +0100 Subject: [PATCH 017/138] translations --- htdocs/fourn/class/fournisseur.commande.class.php | 14 ++++++++------ htdocs/langs/en_US/main.lang | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index d64ebe263d1..e988893dbb4 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -481,7 +481,7 @@ class CommandeFournisseur extends CommonOrder } else { - $this->error='Not Authorized'; + $this->error='NotAuthorized'; dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR); return -1; } @@ -936,6 +936,7 @@ class CommandeFournisseur extends CommonOrder */ function commande($user, $date, $methode, $comment='') { + global $langs; dol_syslog(get_class($this)."::commande"); $result = 0; if ($user->rights->fournisseur->commande->commander) @@ -962,8 +963,8 @@ class CommandeFournisseur extends CommonOrder else { $result = -1; - $this->error = 'Not Authorized'; - $this->errors[] = 'Not Authorized'; + $this->error = $langs->trans('NotAuthorized'); + $this->errors[] = $lanfs->trans('NotAuthorized'); dol_syslog(get_class($this)."::commande User not Authorized", LOG_ERR); } return $result ; @@ -1770,7 +1771,7 @@ class CommandeFournisseur extends CommonOrder */ function Livraison($user, $date, $type, $comment) { - global $conf; + global $conf, $langs; $result = 0; $error = 0; @@ -1852,8 +1853,8 @@ class CommandeFournisseur extends CommonOrder } else { - $this->error = 'Not Authorized'; - $this->errors[] = 'Not Authorized'; + $this->error = $langs->trans('NotAuthorized'); + $this->errors[] = $langs->trans('NotAuthorized'); dol_syslog(get_class($this)."::Livraison Not Authorized"); $result = -3; } @@ -2003,6 +2004,7 @@ class CommandeFournisseur extends CommonOrder if (! $error) { + $this->statut = $status; $this->db->commit(); return 1; } diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 796c14af15e..a05b2b7c06e 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -59,6 +59,7 @@ ErrorCantLoadUserFromDolibarrDatabase=Failed to find user %s in Dolibarr ErrorNoVATRateDefinedForSellerCountry=Error, no vat rates defined for country '%s'. ErrorNoSocialContributionForSellerCountry=Error, no social/fiscal taxes type defined for country '%s'. ErrorFailedToSaveFile=Error, failed to save file. +NotAuthorized=You are not authorized to do that. SetDate=Set date SelectDate=Select a date SeeAlso=See also %s From 09fb87e47da412f13871c7b1f1da1ea2b999ae91 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 11:40:31 +0100 Subject: [PATCH 018/138] Prepare tables for categories/tags on projects. Looking for a dev to implement categories/tags on projects ! --- .../install/mysql/migration/3.8.0-3.9.0.sql | 22 +++++++++++++++- .../install/mysql/tables/llx_budget_lines.sql | 18 ++++++------- .../tables/llx_categorie_project.key.sql | 24 ++++++++++++++++++ .../mysql/tables/llx_categorie_project.sql | 25 +++++++++++++++++++ 4 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 htdocs/install/mysql/tables/llx_categorie_project.key.sql create mode 100644 htdocs/install/mysql/tables/llx_categorie_project.sql diff --git a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql index 1f34377e6ec..0705512893e 100755 --- a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql +++ b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql @@ -226,7 +226,7 @@ create table llx_budget_lines ( rowid integer AUTO_INCREMENT PRIMARY KEY, fk_budget integer NOT NULL, - fk_project integer NOT NULL, + fk_project_ids varchar(255) NOT NULL, -- List of project ids related to this budget. If budget is dedicated to projects not yet started, we recommand to create a project "Projects to come". amount double(24,8) NOT NULL, datec datetime, tms timestamp, @@ -287,3 +287,23 @@ CREATE TABLE llx_opensurvey_user_formanswers ( ) ENGINE=InnoDB; + + +create table llx_categorie_project +( + fk_categorie integer NOT NULL, + fk_project integer NOT NULL, + import_key varchar(14) +)ENGINE=innodb; + +ALTER TABLE llx_categorie_project ADD PRIMARY KEY pk_categorie_project (fk_categorie, fk_project); +ALTER TABLE llx_categorie_project ADD INDEX idx_categorie_project_fk_categorie (fk_categorie); +ALTER TABLE llx_categorie_project ADD INDEX idx_categorie_project_fk_project (fk_project); + +ALTER TABLE llx_categorie_project ADD CONSTRAINT fk_categorie_project_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid); +ALTER TABLE llx_categorie_project ADD CONSTRAINT fk_categorie_project_fk_project FOREIGN KEY (fk_project) REFERENCES llx_project (rowid); + + + + + diff --git a/htdocs/install/mysql/tables/llx_budget_lines.sql b/htdocs/install/mysql/tables/llx_budget_lines.sql index c5d3d3a4bf2..11b68f68fc4 100644 --- a/htdocs/install/mysql/tables/llx_budget_lines.sql +++ b/htdocs/install/mysql/tables/llx_budget_lines.sql @@ -18,13 +18,13 @@ create table llx_budget_lines ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - fk_budget integer NOT NULL, - fk_project integer NOT NULL, - amount double(24,8) NOT NULL, - datec datetime, - tms timestamp, - fk_user_creat integer, - fk_user_modif integer, - import_key integer + rowid integer AUTO_INCREMENT PRIMARY KEY, + fk_budget integer NOT NULL, + fk_project_ids varchar(255) NOT NULL, -- 'IDS:x,y' = List of project ids related to this budget. If budget is dedicated to projects not yet started, we recommand to create a project "Projects to come". 'FILTER:x=y' = Can also be a dynamic rule to select projects. + amount double(24,8) NOT NULL, + datec datetime, + tms timestamp, + fk_user_creat integer, + fk_user_modif integer, + import_key integer )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_categorie_project.key.sql b/htdocs/install/mysql/tables/llx_categorie_project.key.sql new file mode 100644 index 00000000000..12532b6eb09 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_categorie_project.key.sql @@ -0,0 +1,24 @@ +-- ============================================================================ +-- Copyright (C) 2007 Patrick Raguin +-- +-- 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_categorie_project ADD PRIMARY KEY pk_categorie_project (fk_categorie, fk_project); +ALTER TABLE llx_categorie_project ADD INDEX idx_categorie_project_fk_categorie (fk_categorie); +ALTER TABLE llx_categorie_project ADD INDEX idx_categorie_project_fk_project (fk_project); + +ALTER TABLE llx_categorie_project ADD CONSTRAINT fk_categorie_project_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid); +ALTER TABLE llx_categorie_project ADD CONSTRAINT fk_categorie_project_fk_project FOREIGN KEY (fk_project) REFERENCES llx_project (rowid); diff --git a/htdocs/install/mysql/tables/llx_categorie_project.sql b/htdocs/install/mysql/tables/llx_categorie_project.sql new file mode 100644 index 00000000000..ca536822ac2 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_categorie_project.sql @@ -0,0 +1,25 @@ +-- ============================================================================ +-- Copyright (C) 2007 Patrick Raguin +-- Copyright (C) 2012 Juanjo Menent +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- 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_categorie_project +( + fk_categorie integer NOT NULL, + fk_project integer NOT NULL, + import_key varchar(14) +)ENGINE=innodb; From 99f52110703a22810f854c60645050c414dbffbe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 11:48:35 +0100 Subject: [PATCH 019/138] NEW Can use the * as a joker characters into search boxes of lists --- htdocs/core/lib/functions.lib.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index db59c8d966d..013217a9f57 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5193,6 +5193,10 @@ function natural_search($fields, $value, $mode=0, $nofirstand=0) { global $db,$langs; + if ($mode == 0) + { + $value=preg_replace('/\*/','%',$value); // Replace * with % + } if ($mode == 1) { $value=preg_replace('/([<>=]+)\s+([0-9'.preg_quote($langs->trans("DecimalSeparator"),'/').'\-])/','\1\2',$value); // Clean string '< 10' into '<10' so we can the explode on space to get all tests to do From 6611cc70189688ff7e058fc91e34aa99784f93a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 12:19:48 +0100 Subject: [PATCH 020/138] NEW #3767 Allow changing multiple prices of a product at once --- htdocs/product/class/product.class.php | 11 ++ htdocs/product/price.php | 228 ++++++++++++++----------- 2 files changed, 137 insertions(+), 102 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index ba4dc432d36..1ebd94b383f 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -4073,4 +4073,15 @@ class Product extends CommonObject return 1; } + + public function getRights() + { + global $user; + + if ($this->isproduct()) { + return $user->rights->produit; + } else { + return $user->rights->service; + } + } } diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 69802f51d57..1e03780995f 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -113,86 +113,108 @@ if (empty($reshook)) $action=''; } - if (($action == 'update_price') && !$cancel && ($user->rights->produit->creer || $user->rights->service->creer)) + if (($action == 'update_price') && !$cancel && $object->getRights()->creer) { - $newprice = ''; - $newprice_min = ''; - $newpricebase = ''; - $newvat = ''; - + $error = 0; + $pricestoupdate = array(); + + $psq = GETPOST('psqflag'); + $psq = empty($newpsq) ? 0 : $newpsq; $maxpricesupplier = $object->min_recommended_price(); - $object->fk_price_expression = empty($eid) ? 0 : $eid; //0 discards expression - // MultiPrix - if (!empty($conf->global->PRODUIT_MULTIPRICES)) { - - //Shall we generate prices using price rules? - $object->price_autogen = GETPOST('usePriceRules') == 'on' ? true : false; - $object->update($object->id, $user); - - for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i ++) { - if (isset($_POST ["price_".$i])) { - $level = $i; - $newprice = price2num($_POST ["price_".$i], 'MU'); - $newprice_min = price2num($_POST ["price_min_".$i], 'MU'); - $newpricebase = $_POST ["multiprices_base_type_".$i]; - $newnpr = (preg_match('/\*/', $_POST ["tva_tx_".$i]) ? 1 : 0); - $newvat = str_replace('*', '', $_POST ["tva_tx_".$i]); - $newpsq = GETPOST('psqflag'); - $newpsq = empty($newpsq) ? 0 : $newpsq; - break; // We found submited price - } - } - } else { - $level = 0; - $newprice = price2num($_POST ["price"], 'MU'); - $newprice_min = price2num($_POST ["price_min"], 'MU'); - $newpricebase = $_POST ["price_base_type"]; - $newnpr = (preg_match('/\*/', $_POST ["tva_tx"]) ? 1 : 0); - $newvat = str_replace('*', '', $_POST ["tva_tx"]); - $newpsq = GETPOST('psqflag'); - $newpsq = empty($newpsq) ? 0 : $newpsq; - } - - if (!empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE) && $newprice_min < $maxpricesupplier) { - setEventMessage($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, - 1, - 1, 'auto')), 'errors'); - $error ++; - $action = 'edit_price'; - } - - if ($newprice < $newprice_min && !empty($object->fk_price_expression)) { - $newprice = $newprice_min; //Set price same as min, the user will not see the - } - - $res = $object->updatePrice($newprice, $newpricebase, $user, $newvat, $newprice_min, $level, $newnpr, $newpsq); - - if ($res) { + if (!empty($conf->dynamicprices->enabled)) { + $object->fk_price_expression = empty($eid) ? 0 : $eid; //0 discards expression if ($object->fk_price_expression != 0) { //Check the expression validity by parsing it $priceparser = new PriceParser($db); - $price_result = $priceparser->parseProduct($object); - if ($price_result < 0) { //Expression is not valid + + if ($priceparser->parseProduct($object) < 0) { $error ++; - $action = 'edit_price'; setEventMessage($priceparser->translatedError(), 'errors'); } } - if (empty($error) && !empty($conf->dynamicprices->enabled)) { - $ret = $object->setPriceExpression($object->fk_price_expression); - if ($ret < 0) { - $error ++; - $action = 'edit_price'; - setEventMessage($object->error, 'errors'); + } + + // Multiprices + if (!$error && !empty($conf->global->PRODUIT_MULTIPRICES)) { + + $newprice = GETPOST('price', 'array'); + $newprice_min = GETPOST('price_min', 'array'); + $newpricebase = GETPOST('multiprices_base_type', 'array'); + $newvattx = GETPOST('tva_tx', 'array'); + + //Shall we generate prices using price rules? + $object->price_autogen = GETPOST('usePriceRules') == 'on' ? true : false; + + for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i ++) { + + if (!isset($newprice[$i])) { + continue; } - } - if (empty($error)) { - $action = ''; - setEventMessage($langs->trans("RecordSaved")); + + $newnpr = (preg_match('/\*/', $newvattx[$i] ? 1 : 0)); + $newvat = str_replace('*', '', $newvattx[$i]); + + $pricestoupdate[$i] = array( + 'price' => $newprice[$i], + 'price_min' => $newprice_min[$i], + 'price_base_type' => $newpricebase[$i], + 'vat_tx' => $newvat, + 'npr' => $newnpr + ); } } else { - $action = 'edit_price'; + $pricestoupdate[0] = array( + 'price' => $_POST ["price"], + 'price_min' => $_POST ["price_min"], + 'price_base_type' => $_POST ["price_base_type"], + 'vat_tx' => str_replace('*', '', $_POST ["tva_tx"]), + 'npr' => preg_match('/\*/', $_POST ["tva_tx"]) ? 1 : 0 + ); + } + + if (!$error && $object->update($object->id, $user) < 1) { + $error++; setEventMessage($object->error, 'errors'); + $action = 'edit_price'; + } + + if (!$error) { + foreach ($pricestoupdate as $key => $val) { + + $newprice = $val['price']; + + if ($val['price'] < $val['price_min'] && !empty($object->fk_price_expression)) { + $newprice = $val['price_min']; //Set price same as min, the user will not see the + } + + $newprice = price2num($newprice, 'MU'); + $newprice_min = price2num($val['price_min'], 'MU'); + + if (!empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE) && $newprice_min < $maxpricesupplier) { + setEventMessage($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, - 1, - 1, 'auto')), 'errors'); + $error ++; + break; + } + + $res = $object->updatePrice($newprice, $val['price_base_type'], $user, $val['vat_tx'], $newprice_min, $key, $val['npr'], $psq); + + if ($res < 0) { + $error ++; + setEventMessage($object->error, 'errors'); + break; + } + } + } + + if (empty($error)) { + $action = ''; + setEventMessage($langs->trans("RecordSaved")); + $db->commit(); + } else { + $action = 'edit_price'; + $db->rollback(); } } @@ -444,13 +466,13 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) // Selling price print '' . $langs->trans("SellingPrice") . ''; print ''; - if ($object->multiprices_base_type["$soc->price_level"] == 'TTC') { - print price($object->multiprices_ttc["$soc->price_level"]); + if ($object->multiprices_base_type[$soc->price_level] == 'TTC') { + print price($object->multiprices_ttc[$soc->price_level]); } else { - print price($object->multiprices["$soc->price_level"]); + print price($object->multiprices[$soc->price_level]); } - if ($object->multiprices_base_type["$soc->price_level"]) { - print ' ' . $langs->trans($object->multiprices_base_type["$soc->price_level"]); + if ($object->multiprices_base_type[$soc->price_level]) { + print ' ' . $langs->trans($object->multiprices_base_type[$soc->price_level]); } else { print ' ' . $langs->trans($object->price_base_type); } @@ -458,18 +480,18 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) // Price min print '' . $langs->trans("MinPrice") . ''; - if ($object->multiprices_base_type["$soc->price_level"] == 'TTC') + if ($object->multiprices_base_type[$soc->price_level] == 'TTC') { - print price($object->multiprices_min_ttc["$soc->price_level"]) . ' ' . $langs->trans($object->multiprices_base_type["$soc->price_level"]); + print price($object->multiprices_min_ttc[$soc->price_level]) . ' ' . $langs->trans($object->multiprices_base_type[$soc->price_level]); } else { - print price($object->multiprices_min["$soc->price_level"]) . ' ' . $langs->trans(empty($object->multiprices_base_type["$soc->price_level"])?'HT':$object->multiprices_base_type["$soc->price_level"]); + print price($object->multiprices_min[$soc->price_level]) . ' ' . $langs->trans(empty($object->multiprices_base_type[$soc->price_level])?'HT':$object->multiprices_base_type[$soc->price_level]); } print ''; if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // using this option is a bug. kept for backward compatibility { // TVA - print '' . $langs->trans("VATRate") . '' . vatrate($object->multiprices_tva_tx["$soc->price_level"], true) . ''; + print '' . $langs->trans("VATRate") . '' . vatrate($object->multiprices_tva_tx[$soc->price_level], true) . ''; } else { @@ -503,28 +525,28 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) if (! empty($conf->global->$keyforlabel)) print ' - '.$langs->trans($conf->global->$keyforlabel); print ''; - if ($object->multiprices_base_type ["$i"] == 'TTC') { - print '' . price($object->multiprices_ttc["$i"]); + if ($object->multiprices_base_type [$i] == 'TTC') { + print '' . price($object->multiprices_ttc[$i]); } else { - print '' . price($object->multiprices["$i"]); + print '' . price($object->multiprices[$i]); } - if ($object->multiprices_base_type["$i"]) { - print ' '.$langs->trans($object->multiprices_base_type ["$i"]).'';; + if ($object->multiprices_base_type[$i]) { + print ' '.$langs->trans($object->multiprices_base_type [$i]).''; } else { - print ' '.$langs->trans($object->price_base_type).'';; + print ' '.$langs->trans($object->price_base_type).''; } // Prix min print ''; - if (empty($object->multiprices_base_type["$i"])) $object->multiprices_base_type["$i"]="HT"; - if ($object->multiprices_base_type["$i"] == 'TTC') + if (empty($object->multiprices_base_type[$i])) $object->multiprices_base_type[$i]="HT"; + if ($object->multiprices_base_type[$i] == 'TTC') { - print price($object->multiprices_min_ttc["$i"]) . ' ' . $langs->trans($object->multiprices_base_type["$i"]); + print price($object->multiprices_min_ttc[$i]) . ' ' . $langs->trans($object->multiprices_base_type[$i]); } else { - print price($object->multiprices_min["$i"]) . ' ' . $langs->trans($object->multiprices_base_type["$i"]); + print price($object->multiprices_min[$i]) . ' ' . $langs->trans($object->multiprices_base_type[$i]); } print ''; @@ -914,11 +936,12 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> id . '" method="POST">'; + for($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i ++) { - - print ''; - if ($i > 1) print '
'; + + if ($i > 1) print '
'; elseif (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($conf->global->PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL)) { print $langs->trans('UseMultipriceRules'). ' price_autogen ? 'checked' : '').'>

'; } @@ -927,7 +950,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> print ''; if (empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { - print ''; + print ''; } print ''; @@ -936,7 +959,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // This option is kept for backward compatibility but has no sense { print ''; } @@ -945,22 +968,22 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> $text = $langs->trans('SellingPrice') . ' ' . $i; print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); print ''; // Min price print ''; - print ''; - print '
' . $langs->trans("VATRate") . ''; - print $form->load_tva("tva_tx_" . $i, $object->multiprices_tva_tx["$i"], $mysoc, '', $object->id); + print $form->load_tva("tva_tx[" . $i.']', $object->multiprices_tva_tx[$i], $mysoc, '', $object->id); print '
'; - if ($object->multiprices_base_type ["$i"] == 'TTC') { - print ''; + if ($object->multiprices_base_type [$i] == 'TTC') { + print ''; } else { - print ''; + print ''; } - print $form->selectPriceBaseType($object->multiprices_base_type ["$i"], "multiprices_base_type_" . $i); + print $form->selectPriceBaseType($object->multiprices_base_type [$i], "multiprices_base_type[" . $i."]"); print '
'; $text = $langs->trans('MinPrice') . ' ' . $i; print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); - if ($object->multiprices_base_type ["$i"] == 'TTC') { - print ''; + if ($object->multiprices_base_type [$i] == 'TTC') { + print ''; } else { - print ''; + print ''; } if ( !empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE)) { @@ -968,15 +991,16 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> } print '
'; - print '   '; - print '
'; - print ''; } - + + print '
'; + print ''; + print '   '; + print '
'; + print ''; + dol_fiche_end(); } } From 45b4122a95bd91d7b197fc8dec6880db77ee72f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 12:19:48 +0100 Subject: [PATCH 021/138] NEW #3767 Allow changing multiple prices of a product at once --- htdocs/product/class/product.class.php | 11 ++ htdocs/product/price.php | 235 ++++++++++++++----------- 2 files changed, 144 insertions(+), 102 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index ba4dc432d36..1ebd94b383f 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -4073,4 +4073,15 @@ class Product extends CommonObject return 1; } + + public function getRights() + { + global $user; + + if ($this->isproduct()) { + return $user->rights->produit; + } else { + return $user->rights->service; + } + } } diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 69802f51d57..056455a3fff 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -113,86 +113,115 @@ if (empty($reshook)) $action=''; } - if (($action == 'update_price') && !$cancel && ($user->rights->produit->creer || $user->rights->service->creer)) + if (($action == 'update_price') && !$cancel && $object->getRights()->creer) { - $newprice = ''; - $newprice_min = ''; - $newpricebase = ''; - $newvat = ''; - + $error = 0; + $pricestoupdate = array(); + + $psq = GETPOST('psqflag'); + $psq = empty($newpsq) ? 0 : $newpsq; $maxpricesupplier = $object->min_recommended_price(); - $object->fk_price_expression = empty($eid) ? 0 : $eid; //0 discards expression - // MultiPrix - if (!empty($conf->global->PRODUIT_MULTIPRICES)) { - - //Shall we generate prices using price rules? - $object->price_autogen = GETPOST('usePriceRules') == 'on' ? true : false; - $object->update($object->id, $user); - - for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i ++) { - if (isset($_POST ["price_".$i])) { - $level = $i; - $newprice = price2num($_POST ["price_".$i], 'MU'); - $newprice_min = price2num($_POST ["price_min_".$i], 'MU'); - $newpricebase = $_POST ["multiprices_base_type_".$i]; - $newnpr = (preg_match('/\*/', $_POST ["tva_tx_".$i]) ? 1 : 0); - $newvat = str_replace('*', '', $_POST ["tva_tx_".$i]); - $newpsq = GETPOST('psqflag'); - $newpsq = empty($newpsq) ? 0 : $newpsq; - break; // We found submited price - } - } - } else { - $level = 0; - $newprice = price2num($_POST ["price"], 'MU'); - $newprice_min = price2num($_POST ["price_min"], 'MU'); - $newpricebase = $_POST ["price_base_type"]; - $newnpr = (preg_match('/\*/', $_POST ["tva_tx"]) ? 1 : 0); - $newvat = str_replace('*', '', $_POST ["tva_tx"]); - $newpsq = GETPOST('psqflag'); - $newpsq = empty($newpsq) ? 0 : $newpsq; - } - - if (!empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE) && $newprice_min < $maxpricesupplier) { - setEventMessage($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, - 1, - 1, 'auto')), 'errors'); - $error ++; - $action = 'edit_price'; - } - - if ($newprice < $newprice_min && !empty($object->fk_price_expression)) { - $newprice = $newprice_min; //Set price same as min, the user will not see the - } - - $res = $object->updatePrice($newprice, $newpricebase, $user, $newvat, $newprice_min, $level, $newnpr, $newpsq); - - if ($res) { + if (!empty($conf->dynamicprices->enabled)) { + $object->fk_price_expression = empty($eid) ? 0 : $eid; //0 discards expression if ($object->fk_price_expression != 0) { //Check the expression validity by parsing it $priceparser = new PriceParser($db); - $price_result = $priceparser->parseProduct($object); - if ($price_result < 0) { //Expression is not valid + + if ($priceparser->parseProduct($object) < 0) { $error ++; - $action = 'edit_price'; setEventMessage($priceparser->translatedError(), 'errors'); } } - if (empty($error) && !empty($conf->dynamicprices->enabled)) { - $ret = $object->setPriceExpression($object->fk_price_expression); - if ($ret < 0) { - $error ++; - $action = 'edit_price'; - setEventMessage($object->error, 'errors'); + } + + // Multiprices + if (!$error && !empty($conf->global->PRODUIT_MULTIPRICES)) { + + $newprice = GETPOST('price', 'array'); + $newprice_min = GETPOST('price_min', 'array'); + $newpricebase = GETPOST('multiprices_base_type', 'array'); + $newvattx = GETPOST('tva_tx', 'array'); + + //Shall we generate prices using price rules? + $object->price_autogen = GETPOST('usePriceRules') == 'on' ? true : false; + + for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i ++) { + + if (!isset($newprice[$i])) { + continue; + } + + $newnpr = (preg_match('/\*/', $newvattx[$i] ? 1 : 0)); + $newvat = str_replace('*', '', $newvattx[$i]); + + $pricestoupdate[$i] = array( + 'price' => $newprice[$i], + 'price_min' => $newprice_min[$i], + 'price_base_type' => $newpricebase[$i], + 'vat_tx' => $newvat, + 'npr' => $newnpr + ); + + //If autogeneration is enabled, then we only set the first level + if ($object->price_autogen) { + break; } } - if (empty($error)) { - $action = ''; - setEventMessage($langs->trans("RecordSaved")); + } else { + $pricestoupdate[0] = array( + 'price' => $_POST ["price"], + 'price_min' => $_POST ["price_min"], + 'price_base_type' => $_POST ["price_base_type"], + 'vat_tx' => str_replace('*', '', $_POST ["tva_tx"]), + 'npr' => preg_match('/\*/', $_POST ["tva_tx"]) ? 1 : 0 + ); + } + + if (!$error && $object->update($object->id, $user) < 1) { + $error++; + setEventMessage($object->error, 'errors'); + $action = 'edit_price'; + } + + if (!$error) { + $db->begin(); + + foreach ($pricestoupdate as $key => $val) { + + $newprice = $val['price']; + + if ($val['price'] < $val['price_min'] && !empty($object->fk_price_expression)) { + $newprice = $val['price_min']; //Set price same as min, the user will not see the + } + + $newprice = price2num($newprice, 'MU'); + $newprice_min = price2num($val['price_min'], 'MU'); + + if (!empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE) && $newprice_min < $maxpricesupplier) { + setEventMessage($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, - 1, - 1, 'auto')), 'errors'); + $error ++; + break; + } + + $res = $object->updatePrice($newprice, $val['price_base_type'], $user, $val['vat_tx'], $newprice_min, $key, $val['npr'], $psq); + + if ($res < 0) { + $error ++; + setEventMessage($object->error, 'errors'); + break; + } } + } + + if (empty($error)) { + $action = ''; + setEventMessage($langs->trans("RecordSaved")); + $db->commit(); } else { $action = 'edit_price'; - setEventMessage($object->error, 'errors'); + $db->rollback(); } } @@ -444,13 +473,13 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) // Selling price print '' . $langs->trans("SellingPrice") . ''; print ''; - if ($object->multiprices_base_type["$soc->price_level"] == 'TTC') { - print price($object->multiprices_ttc["$soc->price_level"]); + if ($object->multiprices_base_type[$soc->price_level] == 'TTC') { + print price($object->multiprices_ttc[$soc->price_level]); } else { - print price($object->multiprices["$soc->price_level"]); + print price($object->multiprices[$soc->price_level]); } - if ($object->multiprices_base_type["$soc->price_level"]) { - print ' ' . $langs->trans($object->multiprices_base_type["$soc->price_level"]); + if ($object->multiprices_base_type[$soc->price_level]) { + print ' ' . $langs->trans($object->multiprices_base_type[$soc->price_level]); } else { print ' ' . $langs->trans($object->price_base_type); } @@ -458,18 +487,18 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) // Price min print '' . $langs->trans("MinPrice") . ''; - if ($object->multiprices_base_type["$soc->price_level"] == 'TTC') + if ($object->multiprices_base_type[$soc->price_level] == 'TTC') { - print price($object->multiprices_min_ttc["$soc->price_level"]) . ' ' . $langs->trans($object->multiprices_base_type["$soc->price_level"]); + print price($object->multiprices_min_ttc[$soc->price_level]) . ' ' . $langs->trans($object->multiprices_base_type[$soc->price_level]); } else { - print price($object->multiprices_min["$soc->price_level"]) . ' ' . $langs->trans(empty($object->multiprices_base_type["$soc->price_level"])?'HT':$object->multiprices_base_type["$soc->price_level"]); + print price($object->multiprices_min[$soc->price_level]) . ' ' . $langs->trans(empty($object->multiprices_base_type[$soc->price_level])?'HT':$object->multiprices_base_type[$soc->price_level]); } print ''; if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // using this option is a bug. kept for backward compatibility { // TVA - print '' . $langs->trans("VATRate") . '' . vatrate($object->multiprices_tva_tx["$soc->price_level"], true) . ''; + print '' . $langs->trans("VATRate") . '' . vatrate($object->multiprices_tva_tx[$soc->price_level], true) . ''; } else { @@ -503,28 +532,28 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) if (! empty($conf->global->$keyforlabel)) print ' - '.$langs->trans($conf->global->$keyforlabel); print ''; - if ($object->multiprices_base_type ["$i"] == 'TTC') { - print '' . price($object->multiprices_ttc["$i"]); + if ($object->multiprices_base_type [$i] == 'TTC') { + print '' . price($object->multiprices_ttc[$i]); } else { - print '' . price($object->multiprices["$i"]); + print '' . price($object->multiprices[$i]); } - if ($object->multiprices_base_type["$i"]) { - print ' '.$langs->trans($object->multiprices_base_type ["$i"]).'';; + if ($object->multiprices_base_type[$i]) { + print ' '.$langs->trans($object->multiprices_base_type [$i]).''; } else { - print ' '.$langs->trans($object->price_base_type).'';; + print ' '.$langs->trans($object->price_base_type).''; } // Prix min print ''; - if (empty($object->multiprices_base_type["$i"])) $object->multiprices_base_type["$i"]="HT"; - if ($object->multiprices_base_type["$i"] == 'TTC') + if (empty($object->multiprices_base_type[$i])) $object->multiprices_base_type[$i]="HT"; + if ($object->multiprices_base_type[$i] == 'TTC') { - print price($object->multiprices_min_ttc["$i"]) . ' ' . $langs->trans($object->multiprices_base_type["$i"]); + print price($object->multiprices_min_ttc[$i]) . ' ' . $langs->trans($object->multiprices_base_type[$i]); } else { - print price($object->multiprices_min["$i"]) . ' ' . $langs->trans($object->multiprices_base_type["$i"]); + print price($object->multiprices_min[$i]) . ' ' . $langs->trans($object->multiprices_base_type[$i]); } print ''; @@ -894,7 +923,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> id . '" method="POST">'; + for($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i ++) { - - print '
'; - if ($i > 1) print '
'; + + if ($i > 1) print '
'; elseif (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($conf->global->PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL)) { print $langs->trans('UseMultipriceRules'). ' price_autogen ? 'checked' : '').'>

'; } @@ -927,7 +957,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> print ''; if (empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { - print ''; + print ''; } print ''; @@ -936,7 +966,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // This option is kept for backward compatibility but has no sense { print ''; } @@ -945,22 +975,22 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> $text = $langs->trans('SellingPrice') . ' ' . $i; print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); print ''; // Min price print ''; - print ''; - print '
' . $langs->trans("VATRate") . ''; - print $form->load_tva("tva_tx_" . $i, $object->multiprices_tva_tx["$i"], $mysoc, '', $object->id); + print $form->load_tva("tva_tx[" . $i.']', $object->multiprices_tva_tx[$i], $mysoc, '', $object->id); print '
'; - if ($object->multiprices_base_type ["$i"] == 'TTC') { - print ''; + if ($object->multiprices_base_type [$i] == 'TTC') { + print ''; } else { - print ''; + print ''; } - print $form->selectPriceBaseType($object->multiprices_base_type ["$i"], "multiprices_base_type_" . $i); + print ' '.$form->selectPriceBaseType($object->multiprices_base_type [$i], "multiprices_base_type[" . $i."]"); print '
'; $text = $langs->trans('MinPrice') . ' ' . $i; print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); - if ($object->multiprices_base_type ["$i"] == 'TTC') { - print ''; + if ($object->multiprices_base_type [$i] == 'TTC') { + print ''; } else { - print ''; + print ''; } if ( !empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE)) { @@ -968,15 +998,16 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> } print '
'; - print '   '; - print '
'; - print '
'; } - + + print '
'; + print ''; + print '   '; + print '
'; + print ''; + dol_fiche_end(); } } From 350ef610e99d931cbe1d2b3a27a4fbf36efa2b1a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 12:36:34 +0100 Subject: [PATCH 022/138] Fix beluga pdf for projects. Add missing expense reports. --- .../project/doc/pdf_beluga.modules.php | 57 +++++++++++++------ htdocs/langs/en_US/projects.lang | 1 + htdocs/projet/admin/project.php | 2 +- htdocs/projet/card.php | 14 +++-- htdocs/projet/class/project.class.php | 5 +- 5 files changed, 56 insertions(+), 23 deletions(-) diff --git a/htdocs/core/modules/project/doc/pdf_beluga.modules.php b/htdocs/core/modules/project/doc/pdf_beluga.modules.php index 4a8839ef865..11b1d378981 100644 --- a/htdocs/core/modules/project/doc/pdf_beluga.modules.php +++ b/htdocs/core/modules/project/doc/pdf_beluga.modules.php @@ -94,8 +94,8 @@ class pdf_beluga extends ModelePDFProjects $this->posxref=$this->marge_gauche+1; $this->posxdate=$this->marge_gauche+25; $this->posxsociety=$this->marge_gauche+45; - $this->posxamountht=$this->marge_gauche+115; - $this->posxamountttc=$this->marge_gauche+140; + $this->posxamountht=$this->marge_gauche+110; + $this->posxamountttc=$this->marge_gauche+135; $this->posxstatut=$this->marge_gauche+165; } @@ -231,14 +231,16 @@ class pdf_beluga extends ModelePDFProjects 'class'=>'Propal', 'table'=>'propal', 'datefieldname'=>'datep', - 'test'=>$conf->propal->enabled && $user->rights->propale->lire), + 'test'=>$conf->propal->enabled && $user->rights->propale->lire, + 'lang'=>'propal'), 'order'=>array( 'name'=>"CustomersOrders", 'title'=>"ListOrdersAssociatedProject", 'class'=>'Commande', 'table'=>'commande', 'datefieldname'=>'date_commande', - 'test'=>$conf->commande->enabled && $user->rights->commande->lire), + 'test'=>$conf->commande->enabled && $user->rights->commande->lire, + 'lang'=>'order'), 'invoice'=>array( 'name'=>"CustomersInvoices", 'title'=>"ListInvoicesAssociatedProject", @@ -246,21 +248,24 @@ class pdf_beluga extends ModelePDFProjects 'margin'=>'add', 'table'=>'facture', 'datefieldname'=>'datef', - 'test'=>$conf->facture->enabled && $user->rights->facture->lire), + 'test'=>$conf->facture->enabled && $user->rights->facture->lire, + 'lang'=>'bills'), 'invoice_predefined'=>array( 'name'=>"PredefinedInvoices", 'title'=>"ListPredefinedInvoicesAssociatedProject", 'class'=>'FactureRec', 'table'=>'facture_rec', 'datefieldname'=>'datec', - 'test'=>$conf->facture->enabled && $user->rights->facture->lire), + 'test'=>$conf->facture->enabled && $user->rights->facture->lire, + 'lang'=>'bills'), 'order_supplier'=>array( 'name'=>"SuppliersOrders", 'title'=>"ListSupplierOrdersAssociatedProject", 'class'=>'CommandeFournisseur', 'table'=>'commande_fournisseur', 'datefieldname'=>'date_commande', - 'test'=>$conf->fournisseur->enabled && $user->rights->fournisseur->commande->lire), + 'test'=>$conf->fournisseur->enabled && $user->rights->fournisseur->commande->lire, + 'lang'=>'orders'), 'invoice_supplier'=>array( 'name'=>"BillsSuppliers", 'title'=>"ListSupplierInvoicesAssociatedProject", @@ -268,14 +273,16 @@ class pdf_beluga extends ModelePDFProjects 'margin'=>'minus', 'table'=>'facture_fourn', 'datefieldname'=>'datef', - 'test'=>$conf->fournisseur->enabled && $user->rights->fournisseur->facture->lire), + 'test'=>$conf->fournisseur->enabled && $user->rights->fournisseur->facture->lire, + 'lang'=>'bills'), 'contract'=>array( 'name'=>"Contracts", 'title'=>"ListContractAssociatedProject", 'class'=>'Contrat', 'table'=>'contrat', 'datefieldname'=>'date_contrat', - 'test'=>$conf->contrat->enabled && $user->rights->contrat->lire), + 'test'=>$conf->contrat->enabled && $user->rights->contrat->lire, + 'lang'=>'contract'), 'intervention'=>array( 'name'=>"Interventions", 'title'=>"ListFichinterAssociatedProject", @@ -283,7 +290,8 @@ class pdf_beluga extends ModelePDFProjects 'table'=>'fichinter', 'datefieldname'=>'date_valid', 'disableamount'=>1, - 'test'=>$conf->ficheinter->enabled && $user->rights->ficheinter->lire), + 'test'=>$conf->ficheinter->enabled && $user->rights->ficheinter->lire, + 'lang'=>'interventions'), 'trip'=>array( 'name'=>"TripsAndExpenses", 'title'=>"ListTripAssociatedProject", @@ -292,7 +300,18 @@ class pdf_beluga extends ModelePDFProjects 'datefieldname'=>'dated', 'margin'=>'minus', 'disableamount'=>1, - 'test'=>$conf->deplacement->enabled && $user->rights->deplacement->lire), + 'test'=>$conf->deplacement->enabled && $user->rights->deplacement->lire, + 'lang'=>'trip'), + 'expensereport'=>array( + 'name'=>"ExpensesReports", + 'title'=>"ListTripAssociatedProject", + 'class'=>'ExpenseReport', + 'table'=>'expensereport', + 'datefieldname'=>'dated', + 'margin'=>'minus', + 'disableamount'=>1, + 'test'=>$conf->expensereport->enabled && $user->rights->expensereport->lire, + 'lang'=>'trip'), 'agenda'=>array( 'name'=>"Agenda", 'title'=>"ListActionsAssociatedProject", @@ -300,7 +319,8 @@ class pdf_beluga extends ModelePDFProjects 'table'=>'actioncomm', 'datefieldname'=>'datep', 'disableamount'=>1, - 'test'=>$conf->agenda->enabled && $user->rights->agenda->allactions->lire) + 'test'=>$conf->agenda->enabled && $user->rights->agenda->allactions->read, + 'lang'=>'agenda') ); @@ -311,12 +331,17 @@ class pdf_beluga extends ModelePDFProjects $tablename=$value['table']; $datefieldname=$value['datefieldname']; $qualified=$value['test']; + $langstoload=$value['lang']; + $langs->load($langstoload); if ($qualified) { + //var_dump("$key, $tablename, $datefieldname, $dates, $datee"); $elementarray = $object->get_element_list($key, $tablename, $datefieldname, $dates, $datee); + //var_dump($elementarray); + $num = count($elementarray); - if ($num > 0) + if ($num >= 0) { $nexY = $pdf->GetY() + 5; $curY = $nexY; @@ -334,9 +359,9 @@ class pdf_beluga extends ModelePDFProjects $pdf->MultiCell($this->posxamountht - $this->posxsociety, 3, $outputlangs->transnoentities("ThirdParty"), 1, 'L'); if (empty($value['disableamount'])) { $pdf->SetXY($this->posxamountht, $curY); - $pdf->MultiCell($this->posxamountttc - $this->posxamountht, 3, $outputlangs->transnoentities("AmountHT"), 1, 'R'); + $pdf->MultiCell($this->posxamountttc - $this->posxamountht, 3, $outputlangs->transnoentities("AmountHTShort"), 1, 'R'); $pdf->SetXY($this->posxamountttc, $curY); - $pdf->MultiCell($this->posxstatut - $this->posxamountttc, 3, $outputlangs->transnoentities("AmountTTC"), 1, 'R'); + $pdf->MultiCell($this->posxstatut - $this->posxamountttc, 3, $outputlangs->transnoentities("AmountTTCShort"), 1, 'R'); } else { $pdf->SetXY($this->posxamountht, $curY); $pdf->MultiCell($this->posxstatut - $this->posxamountht, 3, "", 1, 'R'); @@ -434,8 +459,6 @@ class pdf_beluga extends ModelePDFProjects } } - - /* * Pied de page */ diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 4ed6ccfc2f5..505f6bce8e5 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -176,6 +176,7 @@ ProjectOpenedProjectByOppStatus=Opened project/lead by opportunity status ProjectsStatistics=Statistics on projects/leads TaskAssignedToEnterTime=Task assigned. Entering time on this task should be possible. IdTaskTime=Id task time +YouCanCompleteRef=If you want to complete the ref with some information (to use it as search filters), it is recommanded to add a - character to separate it, so the automatic numbering will still work correctly for next projects. For example %s-ABC. You may also prefer to add search keys into label. OpenedProjectsByThirdparties=Opened projects by thirdparties OpportunityTotalAmount=Opportunities total amount OpportunityPonderatedAmount=Opportunities weighted amount diff --git a/htdocs/projet/admin/project.php b/htdocs/projet/admin/project.php index 686e764978a..f42fc7c4720 100644 --- a/htdocs/projet/admin/project.php +++ b/htdocs/projet/admin/project.php @@ -104,7 +104,7 @@ else if ($action == 'specimen') $project = new Project($db); $project->initAsSpecimen(); - + // Search template files $file=''; $classname=''; $filefound=0; $dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']); diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 748f91dbefe..c05cb6948a5 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -450,10 +450,13 @@ if ($action == 'create' && $user->rights->projet->creer) if (is_numeric($defaultref) && $defaultref <= 0) $defaultref=''; // Ref - print ''.$langs->trans("Ref").''; + $suggestedref=($_POST["ref"]?$_POST["ref"]:$defaultref); + print ''.$langs->trans("Ref").''; + print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref)); + print ''; // Label - print ''.$langs->trans("Label").''; + print ''.$langs->trans("Label").''; // Thirdparty print ''.$langs->trans("ThirdParty").''; @@ -617,12 +620,15 @@ else print ''; // Ref + $suggestedref=$object->ref; print ''; - print ''; + print ''; // Label print ''; - print ''; + print ''; // Thirdparty print ''; + print ''; } - print '
'; + print '
'.$langs->trans("Ref").'
'; + print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref)); + print '
'.$langs->trans("Label").'
'.$langs->trans("ThirdParty").''; diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 7ac7fa66cea..aca5fe67d0d 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -453,7 +453,9 @@ class Project extends CommonObject function get_element_list($type, $tablename, $datefieldname='', $dates='', $datee='') { $elements = array(); - + + if ($this->id <= 0) return $elements; + if ($type == 'agenda') { $sql = "SELECT id as rowid FROM " . MAIN_DB_PREFIX . "actioncomm WHERE fk_project=" . $this->id; @@ -929,6 +931,7 @@ class Project extends CommonObject $this->date_c = $now; $this->date_m = $now; $this->date_start = $now; + $this->date_end = $now + (3600 * 24 * 365); $this->note_public = 'SPECIMEN'; $this->fk_ele = 20000; $this->opp_amount = 20000; From 439e4a483df61da1801eb857d5e27124ba4b1b0e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 12:37:05 +0100 Subject: [PATCH 023/138] Doc comment --- htdocs/install/mysql/tables/llx_budget.sql | 2 +- htdocs/install/mysql/tables/llx_budget_lines.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_budget.sql b/htdocs/install/mysql/tables/llx_budget.sql index aeb60cd1ce5..908bfc1337c 100644 --- a/htdocs/install/mysql/tables/llx_budget.sql +++ b/htdocs/install/mysql/tables/llx_budget.sql @@ -20,7 +20,7 @@ create table llx_budget ( rowid integer AUTO_INCREMENT PRIMARY KEY, entity integer NOT NULL DEFAULT 1, - label varchar(255) NOT NULL, + label varchar(255) NOT NULL, -- For example 'Global budget for year' or 'Budget for each project' status integer, note text, date_start date, diff --git a/htdocs/install/mysql/tables/llx_budget_lines.sql b/htdocs/install/mysql/tables/llx_budget_lines.sql index 11b68f68fc4..aba5c7f53ee 100644 --- a/htdocs/install/mysql/tables/llx_budget_lines.sql +++ b/htdocs/install/mysql/tables/llx_budget_lines.sql @@ -20,7 +20,7 @@ create table llx_budget_lines ( rowid integer AUTO_INCREMENT PRIMARY KEY, fk_budget integer NOT NULL, - fk_project_ids varchar(255) NOT NULL, -- 'IDS:x,y' = List of project ids related to this budget. If budget is dedicated to projects not yet started, we recommand to create a project "Projects to come". 'FILTER:x=y' = Can also be a dynamic rule to select projects. + fk_project_ids varchar(255) NOT NULL, -- 'IDS:x,y' = List of project ids related to this budget. If budget is dedicated to projects not yet started, we recommand to create a project "Projects to come". 'FILTER:ref=*ABC' = Can also be a dynamic rule to select projects. amount double(24,8) NOT NULL, datec datetime, tms timestamp, From b4c3804c911d458d575ab0ce559e2acbf521ae6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 13:21:03 +0100 Subject: [PATCH 024/138] FIX #3928 Creating a Customer order and a Customer invoice from a project, does not inherit payment conditions and method of payment of customer card --- htdocs/commande/fiche.php | 32 ++++++++++++++++++++++---------- htdocs/compta/facture.php | 23 ++++++++++++++++------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/htdocs/commande/fiche.php b/htdocs/commande/fiche.php index 9a844b0a5d5..78370bad2cb 100644 --- a/htdocs/commande/fiche.php +++ b/htdocs/commande/fiche.php @@ -1366,6 +1366,9 @@ if ($action == 'create' && $user->rights->commande->creer) { if ($socid > 0) $res = $soc->fetch($socid); + $projectid = 0; + $remise_absolue = 0; + if (! empty($origin) && ! empty($originid)) { // Parse element/subelement (ex: project_task) $element = $subelement = $origin; @@ -1423,17 +1426,26 @@ if ($action == 'create' && $user->rights->commande->creer) { $srccontactslist = $objectsrc->liste_contact(- 1, 'external', 1); } } - else - { - $cond_reglement_id = $soc->cond_reglement_id; - $mode_reglement_id = $soc->mode_reglement_id; - $availability_id = $soc->availability_id; - $demand_reason_id = $soc->demand_reason_id; - $remise_percent = $soc->remise_percent; - $remise_absolue = 0; - $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''; - $projectid = 0; + + if (!$cond_reglement_id) { + $cond_reglement_id = $soc->cond_reglement_id; } + if (!$mode_reglement_id) { + $mode_reglement_id = $soc->mode_reglement_id; + } + if (!$availability_id) { + $availability_id = $soc->availability_id; + } + if (!$demand_reason_id) { + $demand_reason_id = $soc->demand_reason_id; + } + if (!$remise_percent) { + $remise_percent = $soc->remise_percent; + } + if (!$dateinvoice) { + $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ? - 1 : ''; + } + $absolute_discount=$soc->getAvailableDiscounts(); $nbrow = 10; diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index af28d80b9e9..0d06394ab69 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -1860,6 +1860,8 @@ if ($action == 'create') if ($socid > 0) $res = $soc->fetch($socid); + $remise_absolue = 0; + if (! empty($origin) && ! empty($originid)) { // Parse element/subelement (ex: project_task) @@ -1916,14 +1918,21 @@ if ($action == 'create') } $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ? -1 : ''; // Dot not set 0 here (0 for a date is 1970) } - else - { - $cond_reglement_id = $soc->cond_reglement_id; - $mode_reglement_id = $soc->mode_reglement_id; - $remise_percent = $soc->remise_percent; - $remise_absolue = 0; - $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice); // Do not set 0 here (0 for a date is 1970) + + if (!$cond_reglement_id) { + $cond_reglement_id = $soc->cond_reglement_id; } + if (!$mode_reglement_id) { + $mode_reglement_id = $soc->mode_reglement_id; + } + if (!$remise_percent) { + $remise_percent = $soc->remise_percent; + } + if (!$dateinvoice) { + // Do not set 0 here (0 for a date is 1970) + $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice); + } + $absolute_discount = $soc->getAvailableDiscounts(); if (! empty($conf->use_javascript_ajax)) From c0872d690e7dc56b4c6b077bf766c38395df3b1b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 13:32:14 +0100 Subject: [PATCH 025/138] Use new banner for other tabs of product --- htdocs/margin/tabs/productMargins.php | 35 +-- htdocs/margin/tabs/thirdpartyMargins.php | 32 +-- htdocs/product/document.php | 30 +-- htdocs/product/fournisseurs.php | 31 +-- htdocs/product/price.php | 41 +--- htdocs/product/stock/product.php | 213 ++++++++---------- .../product/stock/tpl/stockcorrection.tpl.php | 4 +- .../product/stock/tpl/stocktransfer.tpl.php | 6 +- htdocs/product/traduction.php | 128 +++++------ 9 files changed, 231 insertions(+), 289 deletions(-) diff --git a/htdocs/margin/tabs/productMargins.php b/htdocs/margin/tabs/productMargins.php index 934be1f5a41..3b952b099ef 100644 --- a/htdocs/margin/tabs/productMargins.php +++ b/htdocs/margin/tabs/productMargins.php @@ -82,28 +82,13 @@ if ($id > 0 || ! empty($ref)) $picto=($object->type== Product::TYPE_SERVICE?'service':'product'); dol_fiche_head($head, 'margin', $titre, 0, $picto); - print ''; - - // Reference - print ''; - print ''; - print ''; - - // Libelle - print ''; - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + + print '
'; + + print '
'; + print '
'.$langs->trans("Ref").''; - print $form->showrefnav($object,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$object->label.'
'.$langs->trans("Status").' ('.$langs->trans("Sell").')'; - print $object->getLibStatut(2,0); - print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; - print $object->getLibStatut(2,1); - print '
'; // Total Margin print '
'.$langs->trans("TotalMargin").''; @@ -125,7 +110,11 @@ if ($id > 0 || ! empty($ref)) } print "
"; - print ''; + + print ''; + print '
'; + + dol_fiche_end(); if ($user->rights->facture->lire) { diff --git a/htdocs/margin/tabs/thirdpartyMargins.php b/htdocs/margin/tabs/thirdpartyMargins.php index bd2730edda0..9f2f745ad0c 100644 --- a/htdocs/margin/tabs/thirdpartyMargins.php +++ b/htdocs/margin/tabs/thirdpartyMargins.php @@ -73,21 +73,21 @@ if ($socid > 0) dol_fiche_head($head, 'margin', $langs->trans("ThirdParty"),0,'company'); - print ''; - - print ''; - print ''; - - if (! empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field - { - print ''; - } + dol_banner_tab($object, 'socid', '', ($user->societe_id?0:1), 'rowid', 'nom'); + + print '
'; + + print '
'; + print '
'.$langs->trans('ThirdPartyName').''; - print $form->showrefnav($object,'socid','',($user->societe_id?0:1),'rowid','nom'); - print '
'.$langs->trans('Prefix').''.$object->prefix_comm.'
'; + + // Alias names (commercial, trademark or alias names) + print '"; if ($object->client) { - print ''; @@ -123,7 +123,11 @@ if ($socid > 0) } print "
'.$langs->trans('AliasNames').''; + print $object->name_alias; + print "
'; + print '
'; print $langs->trans('CustomerCode').''; print $object->code_client; if ($object->check_codeclient() <> 0) print ' ('.$langs->trans("WrongCustomerCode").')'; @@ -96,7 +96,7 @@ if ($socid > 0) if ($object->fournisseur) { - print '
'; + print '
'; print $langs->trans('SupplierCode').''; print $object->code_fournisseur; if ($object->check_codefournisseur() <> 0) print ' ('.$langs->trans("WrongSupplierCode").')'; @@ -104,7 +104,7 @@ if ($socid > 0) } // Total Margin - print '
'.$langs->trans("TotalMargin").''; + print '
'.$langs->trans("TotalMargin").''; print ''; // set by jquery (see below) print '
"; + + dol_fiche_end(); + print ''; + print '
'; $sql = "SELECT distinct s.nom, s.rowid as socid, s.code_client,"; diff --git a/htdocs/product/document.php b/htdocs/product/document.php index baf736b47e5..93a5c21862d 100644 --- a/htdocs/product/document.php +++ b/htdocs/product/document.php @@ -195,33 +195,21 @@ if ($object->id) } - print ''; - - // Ref - print ''; - print ''; - print ''; - - // Label - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
'.$langs->trans("Ref").''; - print $form->showrefnav($object,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$object->label.'
'.$langs->trans("Status").' ('.$langs->trans("Sell").')'; - print $object->getLibStatut(2,0); - print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; - print $object->getLibStatut(2,1); - print '
'; print ''; print ''; print '
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; print ''; + print '
'; + + dol_fiche_end(); $modulepart = 'produit'; $permission = (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->creer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->creer)); diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index 526b67b123c..dfbd5679ac4 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -264,21 +264,15 @@ if ($id > 0 || $ref) $picto=($object->type== Product::TYPE_SERVICE?'service':'product'); dol_fiche_head($head, 'suppliers', $titre, 0, $picto); - - print ''; - - // Reference - print ''; - print ''; - print ''; - - // Label - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
'.$langs->trans("Ref").''; - print $form->showrefnav($object,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$object->label.'
'; // Minimum Price - print ''; + print ''; print ''; - // Status (to buy) - print ''; - print '
'.$langs->trans("BuyingPriceMin").'
'.$langs->trans("BuyingPriceMin").''; $product_fourn = new ProductFournisseur($db); if ($product_fourn->find_min_price_product_fournisseur($object->id) > 0) @@ -288,14 +282,13 @@ if ($id > 0 || $ref) } print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; - print $object->getLibStatut(2,1); - print '
'; - print "\n"; + print ''; + print '
'; + + dol_fiche_end(); + // Form to add or update a price if (($action == 'add_price' || $action == 'updateprice' ) && ($user->rights->produit->creer || $user->rights->service->creer)) diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 69802f51d57..e1e1eeab0fe 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -402,34 +402,13 @@ $titre = $langs->trans("CardProduct" . $object->type); $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product'); dol_fiche_head($head, 'price', $titre, 0, $picto); -print ''; +dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); -// Ref -print ''; -print ''; -print ''; -// Label -print ''; +print '
'; -$isphoto = $object->is_photo_available($conf->product->multidir_output [$object->entity]); - -$nblignes = 5; -if ($isphoto) { - // Photo - print '
'; -} - -print ''; - -// Status (to sell) -print ''; +print '
'; +print '
' . $langs->trans("Ref") . ''; -print $form->showrefnav($object, 'ref', '', 1, 'ref'); -print '
' . $langs->trans("Label") . '' . $object->label . ''; - print $object->show_photos($conf->product->multidir_output [$object->entity], 1, 1, 0, 0, 0, 80); - print '
' . $langs->trans("Status") . ' (' . $langs->trans("Sell") . ')'; -print $object->getLibStatut(2, 0); -print '
'; // MultiPrix if (! empty($conf->global->PRODUIT_MULTIPRICES)) @@ -442,7 +421,7 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) $soc->fetch($socid); // Selling price - print '' . $langs->trans("SellingPrice") . ''; + print ''; print ''; + print ''; } else { // TVA - print ''; + print ''; } print ''; @@ -605,7 +584,7 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) else { // TVA - print ''; + print ''; // Price print '
' . $langs->trans("SellingPrice") . ''; if ($object->multiprices_base_type["$soc->price_level"] == 'TTC') { print price($object->multiprices_ttc["$soc->price_level"]); @@ -483,12 +462,12 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // using this option is a bug. kept for backward compatibility { // We show only vat for level 1 - print '
' . $langs->trans("VATRate") . '' . vatrate($object->multiprices_tva_tx [1], true) . '
' . $langs->trans("VATRate") . '' . vatrate($object->multiprices_tva_tx [1], true) . '
' . $langs->trans("VATRate") . '' . vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true) . '
' . $langs->trans("VATRate") . '' . vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true) . '
'.$langs->trans("PriceLevel").''.$langs->trans("SellingPrice").''.$langs->trans("MinPrice").'
' . $langs->trans("VATRate") . '' . vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true) . '
' . $langs->trans("VATRate") . '' . vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true) . '
' . $langs->trans("SellingPrice") . ''; @@ -703,6 +682,10 @@ else print "
\n"; +print ''; +print '
'; + + dol_fiche_end(); diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index dfa0cf0c55c..c37424e548b 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -72,24 +72,24 @@ if ($cancel) $action=''; // Set stock limit if ($action == 'setstocklimit') { - $product = new Product($db); - $result=$product->fetch($id); - $product->seuil_stock_alerte=$stocklimit; - $result=$product->update($product->id,$user,0,'update'); + $object = new Product($db); + $result=$object->fetch($id); + $object->seuil_stock_alerte=$stocklimit; + $result=$object->update($object->id,$user,0,'update'); if ($result < 0) - setEventMessage($product->error, 'errors'); + setEventMessage($object->error, 'errors'); $action=''; } // Set desired stock if ($action == 'setdesiredstock') { - $product = new Product($db); - $result=$product->fetch($id); - $product->desiredstock=$desiredstock; - $result=$product->update($product->id,$user,0,'update'); + $object = new Product($db); + $result=$object->fetch($id); + $object->desiredstock=$desiredstock; + $result=$object->update($object->id,$user,0,'update'); if ($result < 0) - setEventMessage($product->error, 'errors'); + setEventMessage($object->error, 'errors'); $action=''; } @@ -112,10 +112,10 @@ if ($action == "correct_stock" && ! $cancel) if (! empty($conf->productbatch->enabled)) { - $product = new Product($db); - $result=$product->fetch($id); + $object = new Product($db); + $result=$object->fetch($id); - if ($product->hasbatch() && (! GETPOST("sellby")) && (! GETPOST("eatby")) && (! GETPOST("batch_number"))) { + if ($object->hasbatch() && (! GETPOST("sellby")) && (! GETPOST("eatby")) && (! GETPOST("batch_number"))) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("atleast1batchfield")), null, 'errors'); $error++; $action='correction'; @@ -127,13 +127,13 @@ if ($action == "correct_stock" && ! $cancel) $priceunit=price2num(GETPOST("unitprice")); if (is_numeric(GETPOST("nbpiece")) && $id) { - if (empty($product)) { - $product = new Product($db); - $result=$product->fetch($id); + if (empty($object)) { + $object = new Product($db); + $result=$object->fetch($id); } - if ($product->hasbatch()) + if ($object->hasbatch()) { - $result=$product->correct_stock_batch( + $result=$object->correct_stock_batch( $user, GETPOST("id_entrepot"), GETPOST("nbpiece"), @@ -148,7 +148,7 @@ if ($action == "correct_stock" && ! $cancel) } else { - $result=$product->correct_stock( + $result=$object->correct_stock( $user, GETPOST("id_entrepot"), GETPOST("nbpiece"), @@ -168,13 +168,13 @@ if ($action == "correct_stock" && ! $cancel) } else { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$product->id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); exit; } } else { - setEventMessage($product->error,'errors'); + setEventMessage($object->error,'errors'); $action='correction'; } } @@ -207,20 +207,20 @@ if ($action == "transfert_stock" && ! $cancel) { if ($id) { - $product = new Product($db); - $result=$product->fetch($id); + $object = new Product($db); + $result=$object->fetch($id); $db->begin(); - $product->load_stock(); // Load array product->stock_warehouse + $object->load_stock(); // Load array product->stock_warehouse // Define value of products moved $pricesrc=0; - //if (isset($product->stock_warehouse[GETPOST("id_entrepot_source")]->pmp)) $pricesrc=$product->stock_warehouse[GETPOST("id_entrepot_source")]->pmp; - if (isset($product->pmp)) $pricesrc=$product->pmp; + //if (isset($object->stock_warehouse[GETPOST("id_entrepot_source")]->pmp)) $pricesrc=$object->stock_warehouse[GETPOST("id_entrepot_source")]->pmp; + if (isset($object->pmp)) $pricesrc=$object->pmp; $pricedest=$pricesrc; - if ($product->hasbatch()) + if ($object->hasbatch()) { $pdluo = new Productbatch($db); @@ -251,7 +251,7 @@ if ($action == "transfert_stock" && ! $cancel) if (! $error) { // Remove stock - $result1=$product->correct_stock_batch( + $result1=$object->correct_stock_batch( $user, $srcwarehouseid, GETPOST("nbpiece",'int'), @@ -262,7 +262,7 @@ if ($action == "transfert_stock" && ! $cancel) GETPOST('inventorycode') ); // Add stock - $result2=$product->correct_stock_batch( + $result2=$object->correct_stock_batch( $user, GETPOST("id_entrepot_destination",'int'), GETPOST("nbpiece",'int'), @@ -277,7 +277,7 @@ if ($action == "transfert_stock" && ! $cancel) else { // Remove stock - $result1=$product->correct_stock( + $result1=$object->correct_stock( $user, GETPOST("id_entrepot_source"), GETPOST("nbpiece"), @@ -288,7 +288,7 @@ if ($action == "transfert_stock" && ! $cancel) ); // Add stock - $result2=$product->correct_stock( + $result2=$object->correct_stock( $user, GETPOST("id_entrepot_destination"), GETPOST("nbpiece"), @@ -309,13 +309,13 @@ if ($action == "transfert_stock" && ! $cancel) } else { - header("Location: product.php?id=".$product->id); + header("Location: product.php?id=".$object->id); exit; } } else { - setEventMessages($product->error, $product->errors, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $db->rollback(); $action='transfert'; } @@ -370,70 +370,45 @@ if ($action == 'updateline' && GETPOST('save') == $langs->trans('Save')) * View */ +$form = new Form($db); $formproduct=new FormProduct($db); if ($id > 0 || $ref) { - $product = new Product($db); - $result = $product->fetch($id,$ref); - $product->load_stock(); + $object = new Product($db); + $result = $object->fetch($id,$ref); + $object->load_stock(); $help_url='EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; - llxHeader("",$langs->trans("CardProduct".$product->type),$help_url); + llxHeader("",$langs->trans("CardProduct".$object->type),$help_url); if ($result > 0) { - $head=product_prepare_head($product); - $titre=$langs->trans("CardProduct".$product->type); - $picto=($product->type==Product::TYPE_SERVICE?'service':'product'); + $head=product_prepare_head($object); + $titre=$langs->trans("CardProduct".$object->type); + $picto=($object->type==Product::TYPE_SERVICE?'service':'product'); dol_fiche_head($head, 'stock', $titre, 0, $picto); dol_htmloutput_events(); - $form = new Form($db); - - print ''; - - // Ref - print ''; - print ''; - print ''; - - // Label - print ''; - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; - + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
'.$langs->trans("Ref").''; - print $form->showrefnav($product,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$product->label.'
'.$langs->trans("Status").' ('.$langs->trans("Sell").')'; - if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { - print ajax_object_onoff($product, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); - } else { - print $product->getLibStatut(2,0); - } - print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; - if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { - print ajax_object_onoff($product, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); - } else { - print $product->getLibStatut(2,1); - } - print '
'; + if ($conf->productbatch->enabled) { print ''; } // PMP print ''; print ''; print ''; @@ -441,14 +416,13 @@ if ($id > 0 || $ref) print ''; print ''; - $object = $product; if (empty($conf->global->PRODUIT_MULTIPRICES)) { // Price @@ -483,17 +457,17 @@ if ($id > 0 || $ref) } // Stock alert threshold - print ''; // Desired stock - print ''; // Real stock - $product->load_stock(); + $object->load_stock(); $text_stock_options = ''; $text_stock_options.= (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)?$langs->trans("DeStockOnShipment").'
':''); $text_stock_options.= (! empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER)?$langs->trans("DeStockOnValidateOrder").'
':''); @@ -504,15 +478,15 @@ if ($id > 0 || $ref) print ''; - print ''; print ''; // Calculating a theorical value print ''; - print "'; @@ -528,36 +502,36 @@ if ($id > 0 || $ref) if (! empty($conf->commande->enabled)) { if ($found) print '
'; else $found=1; - print $langs->trans("ProductQtyInCustomersOrdersRunning").': '.$product->stats_commande['qty']; - $result=$product->load_stats_commande(0,'0'); - if ($result < 0) dol_print_error($db,$product->error); - print ' ('.$langs->trans("ProductQtyInDraft").': '.$product->stats_commande['qty'].')'; + print $langs->trans("ProductQtyInCustomersOrdersRunning").': '.$object->stats_commande['qty']; + $result=$object->load_stats_commande(0,'0'); + if ($result < 0) dol_print_error($db,$object->error); + print ' ('.$langs->trans("ProductQtyInDraft").': '.$object->stats_commande['qty'].')'; } // Number of product from customer order already sent (partial shipping) if (! empty($conf->expedition->enabled)) { if ($found) print '
'; else $found=1; - $result=$product->load_stats_sending(0,'2'); - print $langs->trans("ProductQtyInShipmentAlreadySent").': '.$product->stats_expedition['qty']; + $result=$object->load_stats_sending(0,'2'); + print $langs->trans("ProductQtyInShipmentAlreadySent").': '.$object->stats_expedition['qty']; } // Number of supplier order running if (! empty($conf->fournisseur->enabled)) { if ($found) print '
'; else $found=1; - $result=$product->load_stats_commande_fournisseur(0,'3,4'); - print $langs->trans("ProductQtyInSuppliersOrdersRunning").': '.$product->stats_commande_fournisseur['qty']; - $result=$product->load_stats_commande_fournisseur(0,'0,1,2'); - if ($result < 0) dol_print_error($db,$product->error); - print ' ('.$langs->trans("ProductQtyInDraftOrWaitingApproved").': '.$product->stats_commande_fournisseur['qty'].')'; + $result=$object->load_stats_commande_fournisseur(0,'3,4'); + print $langs->trans("ProductQtyInSuppliersOrdersRunning").': '.$object->stats_commande_fournisseur['qty']; + $result=$object->load_stats_commande_fournisseur(0,'0,1,2'); + if ($result < 0) dol_print_error($db,$object->error); + print ' ('.$langs->trans("ProductQtyInDraftOrWaitingApproved").': '.$object->stats_commande_fournisseur['qty'].')'; } // Number of product from supplier order already received (partial receipt) if (! empty($conf->fournisseur->enabled)) { if ($found) print '
'; else $found=1; - print $langs->trans("ProductQtyInSuppliersShipmentAlreadyRecevied").': '.$product->stats_reception['qty']; + print $langs->trans("ProductQtyInSuppliersShipmentAlreadyRecevied").': '.$object->stats_reception['qty']; } print ''; @@ -565,7 +539,7 @@ if ($id > 0 || $ref) // Last movement $sql = "SELECT max(m.datem) as datem"; $sql.= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m"; - $sql.= " WHERE m.fk_product = '".$product->id."'"; + $sql.= " WHERE m.fk_product = '".$object->id."'"; $resqlbis = $db->query($sql); if ($resqlbis) { @@ -580,18 +554,21 @@ if ($id > 0 || $ref) if ($lastmovementdate) { print dol_print_date($lastmovementdate,'dayhour').' '; - print '('.$langs->trans("FullList").')'; + print '('.$langs->trans("FullList").')'; } else { - print ''.$langs->trans("None").''; + print ''.$langs->trans("None").''; } print ""; print "
'.$langs->trans("ManageLotSerial").''; - print $product->getLibStatut(0,2); + print $object->getLibStatut(0,2); print '
'.$langs->trans("AverageUnitPricePMP").''; - if ($product->pmp > 0) print price($product->pmp).' '.$langs->trans("HT"); + if ($object->pmp > 0) print price($object->pmp).' '.$langs->trans("HT"); print '
'.$langs->trans("BuyingPriceMin").''; $product_fourn = new ProductFournisseur($db); - if ($product_fourn->find_min_price_product_fournisseur($product->id) > 0) + if ($product_fourn->find_min_price_product_fournisseur($object->id) > 0) { if ($product_fourn->product_fourn_price_id > 0) print $product_fourn->display_price_product_fournisseur(); else print $langs->trans("NotDefined"); } print '
'.$form->editfieldkey("StockLimit",'stocklimit',$product->seuil_stock_alerte,$product,$user->rights->produit->creer).''; - print $form->editfieldval("StockLimit",'stocklimit',$product->seuil_stock_alerte,$product,$user->rights->produit->creer); + print '
'.$form->editfieldkey("StockLimit",'stocklimit',$object->seuil_stock_alerte,$object,$user->rights->produit->creer).''; + print $form->editfieldval("StockLimit",'stocklimit',$object->seuil_stock_alerte,$object,$user->rights->produit->creer); print '
'.$form->editfieldkey("DesiredStock",'desiredstock',$product->desiredstock,$product,$user->rights->produit->creer).''; - print $form->editfieldval("DesiredStock",'desiredstock',$product->desiredstock,$product,$user->rights->produit->creer); + print '
'.$form->editfieldkey("DesiredStock",'desiredstock',$object->desiredstock,$object,$user->rights->produit->creer).''; + print $form->editfieldval("DesiredStock",'desiredstock',$object->desiredstock,$object,$user->rights->produit->creer); print '
'; print $form->textwithtooltip($langs->trans("PhysicalStock"), $text_stock_options, 2, 1, img_picto('', 'info'), '', 2); print ''.$product->stock_reel; - if ($product->seuil_stock_alerte && ($product->stock_reel < $product->seuil_stock_alerte)) print ' '.img_warning($langs->trans("StockLowerThanLimit")); + print ''.$object->stock_reel; + if ($object->seuil_stock_alerte && ($object->stock_reel < $object->seuil_stock_alerte)) print ' '.img_warning($langs->trans("StockLowerThanLimit")); print '
'.$langs->trans("VirtualStock").'".(empty($product->stock_theorique)?0:$product->stock_theorique); - if ($product->stock_theorique < $product->seuil_stock_alerte) { + print "".(empty($object->stock_theorique)?0:$object->stock_theorique); + if ($object->stock_theorique < $object->seuil_stock_alerte) { print ' '.img_warning($langs->trans("StockLowerThanLimit")); } print '
"; + print ''; + print '
'; + + dol_fiche_end(); } - print ''; /* * Correct stock @@ -618,7 +595,7 @@ if ($id > 0 || $ref) if ($_GET["action"] == "definir") { print load_fiche_titre($langs->trans("SetStock")); - print "
id\" method=\"post\">\n"; + print "id\" method=\"post\">\n"; print ''; print ''; print ''; @@ -645,19 +622,19 @@ else /* ************************************************************************** */ -if (empty($action) && $product->id) +if (empty($action) && $object->id) { print "
\n"; if ($user->rights->stock->mouvement->creer) { - print ''.$langs->trans("StockCorrection").''; + print ''.$langs->trans("StockCorrection").''; } - //if (($user->rights->stock->mouvement->creer) && ! $product->hasbatch()) + //if (($user->rights->stock->mouvement->creer) && ! $object->hasbatch()) if ($user->rights->stock->mouvement->creer) { - print ''.$langs->trans("StockMovement").''; + print ''.$langs->trans("StockMovement").''; } print '
'; @@ -678,7 +655,7 @@ print ''; print ''; print ''; print ''; -if ((! empty($conf->productbatch->enabled)) && $product->hasbatch()) +if ((! empty($conf->productbatch->enabled)) && $object->hasbatch()) { print ''; print ''; @@ -695,7 +672,7 @@ $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = ps.fk_product"; $sql.= " WHERE ps.reel != 0"; $sql.= " AND ps.fk_entrepot = e.rowid"; $sql.= " AND e.entity IN (".getEntity('stock', 1).")"; -$sql.= " AND ps.fk_product = ".$product->id; +$sql.= " AND ps.fk_product = ".$object->id; $sql.= " ORDER BY e.label"; $entrepotstatic=new Entrepot($db); @@ -718,25 +695,25 @@ if ($resql) print ''; print ''; // PMP - print ''; + print ''; // Value purchase - print ''; + print ''; // Sell price print ''; // Value sell print ''; + if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($object->price*$obj->reel,'MT'),1).''; else print $langs->trans("Variable"); print ''; ; $total += $obj->reel; - if (price2num($product->pmp)) $totalwithpmp += $obj->reel; - $totalvalue = $totalvalue + ($product->pmp*$obj->reel); - $totalvaluesell = $totalvaluesell + ($product->price*$obj->reel); + if (price2num($object->pmp)) $totalwithpmp += $obj->reel; + $totalvalue = $totalvalue + ($object->pmp*$obj->reel); + $totalvaluesell = $totalvaluesell + ($object->price*$obj->reel); //Batch Detail - if ((! empty($conf->productbatch->enabled)) && $product->hasbatch()) + if ((! empty($conf->productbatch->enabled)) && $object->hasbatch()) { $details=Productbatch::findAll($db,$obj->product_stock_id); if ($details<0) dol_print_error($db); @@ -762,7 +739,7 @@ if ($resql) { print "\n".'"; print ""; - if ($obj->total_ttc < 0) { print ""; }; + if ($obj->total_ttc < 0) { print ""; }; if ($obj->total_ttc >= 0) { print ""; }; print ''; print ""; From 01854b32597022f0a7c595154809a9b2ba0e6930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 13:51:09 +0100 Subject: [PATCH 028/138] FIX #3679 Error when deleting a Localtax2 special payment --- htdocs/compta/localtax/card.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/localtax/card.php b/htdocs/compta/localtax/card.php index 1b16064ed9e..27990a021cb 100644 --- a/htdocs/compta/localtax/card.php +++ b/htdocs/compta/localtax/card.php @@ -1,5 +1,6 @@ + * Copyright (C) 2015 Marcos García * * 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 @@ -104,7 +105,7 @@ if ($_GET["action"] == 'delete') if ($result > 0) { $db->commit(); - header("Location: ".DOL_URL_ROOT.'/compta/localtax/reglement.php'); + header("Location: ".DOL_URL_ROOT.'/compta/localtax/reglement.php?localTaxType='.$localtax->ltt); exit; } else From 8ccb8c92e000b8f39811858eb16d7b28287b8d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 14:29:38 +0100 Subject: [PATCH 029/138] FIX #3897 Incorrect colspan in tr#tablelines > tr#trlinefordates Close #3897 --- htdocs/core/tpl/objectline_create.tpl.php | 36 +++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index edb065c9d9b..ee70101318b 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -5,6 +5,7 @@ * Copyright (C) 2012 Cédric Salvador * Copyright (C) 2014 Florian Henry * Copyright (C) 2014 Raphaël Doursenaud + * Copyright (C) 2015 Marcos García * * 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 @@ -315,14 +316,39 @@ else { service->enabled) || ($object->element == 'contrat')) && $dateSelector && GETPOST('type') != '0') // We show date field if required { - if(! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) $colspan = 10; - else $colspan = 9; - if($this->situation_cycle_ref) $colspan++; - if (! empty($inputalsopricewithtax)) $colspan++; // We add 1 if col total ttc - if (in_array($object->element,array('propal','askpricesupplier','facture','invoice','commande','order','order_supplier','invoice_supplier'))) $colspan++; // With this, there is a column move button + $colspan = 6; + + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { + $colspan++; + } + if ($this->situation_cycle_ref) { + $colspan++; + } + // We add 1 if col total ttc + if (!empty($inputalsopricewithtax)) { + $colspan++; + } if ($conf->global->PRODUCT_USE_UNITS) { $colspan++; } + if (count($object->lines)) { + //There will be an edit and a delete button + $colspan += 2; + + // With this, there is a column move button ONLY if lines > 1 + if (in_array($object->element, array( + 'propal', + 'askpricesupplier', + 'facture', + 'invoice', + 'commande', + 'order', + 'order_supplier', + 'invoice_supplier' + ))) { + $colspan++; + } + } if (! empty($usemargins)) { From 0451cc1e734ce3244b505edd0d7a2a6f25d14e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 14:31:12 +0100 Subject: [PATCH 030/138] FIX #3931 [Insight] Logical operators should be avoided - in htdocs/core/class/extrafields.class.php, line 261 Close #3931 --- htdocs/core/class/extrafields.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index c53d1b793f3..645b50cb8bc 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -258,7 +258,7 @@ class ExtraFields if (! empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname) && ! is_numeric($attrname)) { - if(is_array($param) and count($param) > 0) + if(is_array($param) && count($param) > 0) { $params = $this->db->escape(serialize($param)); } From ba42a7779fb7a27a2de5b6fc9019d31bf6278f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 14:34:26 +0100 Subject: [PATCH 031/138] FIX #3877 HTML encoded strings when searching for a supplier invoice Close #3877 --- htdocs/fourn/facture/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 4252e4a9ef6..a46c5e6ca38 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -273,7 +273,7 @@ if ($resql) if ($search_all) { foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); - print $langs->trans("FilterOnInto", $search_all, join(', ',$fieldstosearchall)); + print $langs->transnoentities("FilterOnInto", $search_all, join(', ',$fieldstosearchall)); } print '
'.$langs->trans("EstimatedStockValueShort").''.$langs->trans("SellPriceMin").''.$langs->trans("EstimatedStockValueSellShort").'
'.$langs->trans("batch_number").''.$entrepotstatic->getNomUrl(1).''.$obj->reel.($obj->reel<0?' '.img_warning():'').''.(price2num($product->pmp)?price2num($product->pmp,'MU'):'').''.(price2num($object->pmp)?price2num($object->pmp,'MU'):'').''.(price2num($product->pmp)?price(price2num($product->pmp*$obj->reel,'MT')):'').''.(price2num($object->pmp)?price(price2num($object->pmp*$obj->reel,'MT')):'').''; - if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($product->price,'MU'),1); + if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($object->price,'MU'),1); else print $langs->trans("Variable"); print ''; - if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($product->price*$obj->reel,'MT'),1).'
'; print img_picto($langs->trans("Tranfer"),'uparrow','class="hideonsmartphone"').' '; - print 'id.'">'.$langs->trans("StockMovement").''; + print 'id.'">'.$langs->trans("StockMovement").''; // Disabled, because edition of stock content must use the "Correct stock menu". // Do not use this, or data will be wrong (bad tracking of movement label, inventory code, ... //print 'id.'#'.$pdluo->id.'">'; diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php index dc102d8eb05..b1121731293 100644 --- a/htdocs/product/stock/tpl/stockcorrection.tpl.php +++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php @@ -21,7 +21,9 @@ load("productbatch"); + if (! is_object($product)) $product=$object; + + $langs->load("productbatch"); if (empty($id)) $id = $object->id; diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php index de947a75014..93c3135e5f1 100644 --- a/htdocs/product/stock/tpl/stocktransfer.tpl.php +++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php @@ -21,7 +21,11 @@ load("productbatch"); + + $pdluoid=GETPOST('pdluoid','int'); $pdluo = new Productbatch($db); diff --git a/htdocs/product/traduction.php b/htdocs/product/traduction.php index 413cb589dff..96187fad8dd 100644 --- a/htdocs/product/traduction.php +++ b/htdocs/product/traduction.php @@ -58,9 +58,9 @@ if ($cancel == $langs->trans("Cancel")) if ($action == 'delete' && GETPOST('langtodelete','alpha')) { - $product = new Product($db); - $product->fetch($id); - $product->delMultiLangs(GETPOST('langtodelete','alpha')); + $object = new Product($db); + $object->fetch($id); + $object->delMultiLangs(GETPOST('langtodelete','alpha')); } // Add translation @@ -68,33 +68,33 @@ if ($action == 'vadd' && $cancel != $langs->trans("Cancel") && ($user->rights->produit->creer || $user->rights->service->creer)) { - $product = new Product($db); - $product->fetch($id); + $object = new Product($db); + $object->fetch($id); $current_lang = $langs->getDefaultLang(); // update de l'objet if ( $_POST["forcelangprod"] == $current_lang ) { - $product->label = $_POST["libelle"]; - $product->description = dol_htmlcleanlastbr($_POST["desc"]); - $product->note = dol_htmlcleanlastbr($_POST["note"]); + $object->label = $_POST["libelle"]; + $object->description = dol_htmlcleanlastbr($_POST["desc"]); + $object->note = dol_htmlcleanlastbr($_POST["note"]); } else { - $product->multilangs[$_POST["forcelangprod"]]["label"] = $_POST["libelle"]; - $product->multilangs[$_POST["forcelangprod"]]["description"] = dol_htmlcleanlastbr($_POST["desc"]); - $product->multilangs[$_POST["forcelangprod"]]["note"] = dol_htmlcleanlastbr($_POST["note"]); + $object->multilangs[$_POST["forcelangprod"]]["label"] = $_POST["libelle"]; + $object->multilangs[$_POST["forcelangprod"]]["description"] = dol_htmlcleanlastbr($_POST["desc"]); + $object->multilangs[$_POST["forcelangprod"]]["note"] = dol_htmlcleanlastbr($_POST["note"]); } // sauvegarde en base - if ( $product->setMultiLangs() > 0 ) + if ( $object->setMultiLangs() > 0 ) { $action = ''; } else { $action = 'add'; - setEventMessage($product->error,'errors'); + setEventMessage($object->error,'errors'); } } @@ -103,34 +103,34 @@ if ($action == 'vedit' && $cancel != $langs->trans("Cancel") && ($user->rights->produit->creer || $user->rights->service->creer)) { - $product = new Product($db); - $product->fetch($id); + $object = new Product($db); + $object->fetch($id); $current_lang = $langs->getDefaultLang(); - foreach ( $product->multilangs as $key => $value ) // enregistrement des nouvelles valeurs dans l'objet + foreach ( $object->multilangs as $key => $value ) // enregistrement des nouvelles valeurs dans l'objet { if ( $key == $current_lang ) { - $product->label = $_POST["libelle-".$key]; - $product->description = dol_htmlcleanlastbr($_POST["desc-".$key]); - $product->note = dol_htmlcleanlastbr($_POST["note-".$key]); + $object->label = $_POST["libelle-".$key]; + $object->description = dol_htmlcleanlastbr($_POST["desc-".$key]); + $object->note = dol_htmlcleanlastbr($_POST["note-".$key]); } else { - $product->multilangs[$key]["label"] = $_POST["libelle-".$key]; - $product->multilangs[$key]["description"] = dol_htmlcleanlastbr($_POST["desc-".$key]); - $product->multilangs[$key]["note"] = dol_htmlcleanlastbr($_POST["note-".$key]); + $object->multilangs[$key]["label"] = $_POST["libelle-".$key]; + $object->multilangs[$key]["description"] = dol_htmlcleanlastbr($_POST["desc-".$key]); + $object->multilangs[$key]["note"] = dol_htmlcleanlastbr($_POST["note-".$key]); } } - if ( $product->setMultiLangs() > 0 ) + if ( $object->setMultiLangs() > 0 ) { $action = ''; } else { $action = 'edit'; - setEventMessage($product->error,'errors'); + setEventMessage($object->error,'errors'); } } @@ -139,24 +139,24 @@ if ($action == 'vdelete' && $cancel != $langs->trans("Cancel") && ($user->rights->produit->creer || $user->rights->service->creer)) { - $product = new Product($db); - $product->fetch($id); + $object = new Product($db); + $object->fetch($id); $langtodelete=GETPOST('langdel','alpha'); - if ( $product->delMultiLangs($langtodelete) > 0 ) + if ( $object->delMultiLangs($langtodelete) > 0 ) { $action = ''; } else { $action = 'edit'; - setEventMessage($product->error,'errors'); + setEventMessage($object->error,'errors'); } } -$product = new Product($db); -$result = $product->fetch($id,$ref); +$object = new Product($db); +$result = $object->fetch($id,$ref); /* @@ -168,20 +168,10 @@ llxHeader("","",$langs->trans("Translation")); $form = new Form($db); $formadmin=new FormAdmin($db); -$head=product_prepare_head($product); -$titre=$langs->trans("CardProduct".$product->type); -$picto=($product->type==Product::TYPE_SERVICE?'service':'product'); -dol_fiche_head($head, 'translation', $titre, 0, $picto); +$head=product_prepare_head($object); +$titre=$langs->trans("CardProduct".$object->type); +$picto=($object->type==Product::TYPE_SERVICE?'service':'product'); -print ''; - -// Reference -print ''; -print ''; -print ''; -print '
'.$langs->trans("Ref").''; -print $form->showrefnav($product,'ref','',1,'ref'); -print '
'; if ($action == 'edit') { @@ -191,33 +181,40 @@ if ($action == 'edit') print ''; print ''; print ''; - print ''; + print ''; - if (! empty($product->multilangs)) + dol_fiche_head($head, 'translation', $titre, 0, $picto); + + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + if (! empty($object->multilangs)) { - foreach ($product->multilangs as $key => $value) + foreach ($object->multilangs as $key => $value) { - print "
".$langs->trans('Language_'.$key)." :
"; + $s=picto_from_langcode($key); + print "
".($s?$s.' ':'')." ".$langs->trans('Language_'.$key).": ".'
'.img_delete('', '')."
"; + print ''; - print ''; + print ''; print ''; print ''; - print ''; print '
'.$langs->trans('Label').'
'.$langs->trans('Label').'
'.$langs->trans('Description').''; - $doleditor = new DolEditor("desc-$key", $product->multilangs[$key]["description"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80); + $doleditor = new DolEditor("desc-$key", $object->multilangs[$key]["description"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80); $doleditor->Create(); print '
'.$langs->trans('Note').''; - $doleditor = new DolEditor("note-$key", $product->multilangs[$key]["note"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80); + $doleditor = new DolEditor("note-$key", $object->multilangs[$key]["note"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80); $doleditor->Create(); print '
'.$langs->trans("Delete").'
'; } } - print '
'; + dol_fiche_end(); + + print '
'; print ''; print '     '; print ''; @@ -228,25 +225,30 @@ if ($action == 'edit') } else { - $cnt_trans = 0; - if (! empty($product->multilangs)) + dol_fiche_head($head, 'translation', $titre, 0, $picto); + + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + $cnt_trans = 0; + if (! empty($object->multilangs)) { - foreach ($product->multilangs as $key => $value) + foreach ($object->multilangs as $key => $value) { $cnt_trans++; $s=picto_from_langcode($key); - print "
".($s?$s.' ':'')." ".$langs->trans('Language_'.$key).": ".''.img_delete('', '')."
"; + print "
".($s?$s.' ':'')." ".$langs->trans('Language_'.$key).": ".''.img_delete('', '')."
"; print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; print '
'.$langs->trans('Label').''.$product->multilangs[$key]["label"].'
'.$langs->trans('Description').''.$product->multilangs[$key]["description"].'
'.$langs->trans('Note').''.$product->multilangs[$key]["note"].'
'.$langs->trans('Label').''.$object->multilangs[$key]["label"].'
'.$langs->trans('Description').''.$object->multilangs[$key]["description"].'
'.$langs->trans('Note').''.$object->multilangs[$key]["note"].'
'; } } if (! $cnt_trans) print '
'. $langs->trans('NoTranslation'); + + dol_fiche_end(); } -print "
\n"; /* ************************************************************************** */ @@ -260,8 +262,8 @@ print "\n
\n"; if ($action == '') if ($user->rights->produit->creer || $user->rights->service->creer) { - print ''.$langs->trans("Add").''; - print ''.$langs->trans("Update").''; + print ''.$langs->trans("Add").''; + print ''.$langs->trans("Update").''; } print "\n
\n"; @@ -284,7 +286,7 @@ if ($action == 'add' && ($user->rights->produit->creer || $user->rights->service print ''; print ''; print ''; print ''; + + if (! empty($conf->prelevement->enabled)) { + $colspan = 8; + } else { + $colspan = 7; + } + + print ''; } print '
'.$langs->trans('Language').''; - print $formadmin->select_language('','forcelangprod',0,$product->multilangs,1); + print $formadmin->select_language('','forcelangprod',0,$object->multilangs,1); print '
'.$langs->trans('Label').'
'.$langs->trans('Description').''; From 3bbedf1795c8b93527954af5fc814034b9b94800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 13:39:34 +0100 Subject: [PATCH 026/138] FIX #3707 Thirdparty bank account page table has a glitch --- htdocs/societe/rib.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/htdocs/societe/rib.php b/htdocs/societe/rib.php index 55f1a111a93..6505ea24f63 100644 --- a/htdocs/societe/rib.php +++ b/htdocs/societe/rib.php @@ -401,7 +401,14 @@ if ($socid && $action != 'edit' && $action != "create") } if (count($rib_list) == 0) { - print '
'.$langs->trans("NoBANRecord").'
'.$langs->trans("NoBANRecord").'
'; From 728f469c1e37e9cec1f22686461f8eedf48e8d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 13:43:59 +0100 Subject: [PATCH 027/138] FIX #3890 Expected transactions bank account page, shows negative numbers --- htdocs/compta/bank/treso.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/bank/treso.php b/htdocs/compta/bank/treso.php index b9274c34eb5..1b9925e761c 100644 --- a/htdocs/compta/bank/treso.php +++ b/htdocs/compta/bank/treso.php @@ -2,6 +2,7 @@ /* Copytight (C) 2005-2009 Regis Houssin * Copyright (C) 2008-2009 Laurent Destailleur (Eldy) * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2015 Marcos García "; print "
".$ref."".$refcomp."".price($total_ttc)." ".price(abs($total_ttc))."  ".price($total_ttc)."'.price($solde).'
'; From 75b4cb472785aea6152cbee70837b4d365e0a9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 14:37:47 +0100 Subject: [PATCH 032/138] NEW #3876 Renamed Product::isservice and Product::isproduct to match PSR-2 --- htdocs/core/lib/doc.lib.php | 2 +- htdocs/core/lib/pdf.lib.php | 2 +- htdocs/core/lib/product.lib.php | 2 +- htdocs/product/card.php | 8 ++++---- htdocs/product/class/product.class.php | 4 ++-- htdocs/product/composition/card.php | 4 ++-- htdocs/product/fournisseurs.php | 2 +- htdocs/public/paybox/newpayment.php | 2 +- htdocs/public/paypal/newpayment.php | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/htdocs/core/lib/doc.lib.php b/htdocs/core/lib/doc.lib.php index 330d3d2ba39..76337ec2763 100644 --- a/htdocs/core/lib/doc.lib.php +++ b/htdocs/core/lib/doc.lib.php @@ -106,7 +106,7 @@ function doc_getlinedesc($line,$outputlangs,$hideref=0,$hidedesc=0,$issupplierli $ref_prodserv = ""; if (! empty($conf->global->PRODUCT_ADD_TYPE_IN_DOCUMENTS)) // In standard mode, we do not show this { - if ($prodser->isservice()) + if ($prodser->isService()) { $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." "; } diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 8e0eef6d53b..881415555bc 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -1166,7 +1166,7 @@ function pdf_getlinedesc($object,$i,$outputlangs,$hideref=0,$hidedesc=0,$issuppl $ref_prodserv = ""; if (! empty($conf->global->PRODUCT_ADD_TYPE_IN_DOCUMENTS)) // In standard mode, we do not show this { - if ($prodser->isservice()) + if ($prodser->isService()) { $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." "; } diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index 69eb63717b2..d0bc74e77c3 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -98,7 +98,7 @@ function product_prepare_head($object) $head[$h][2] = 'referers'; $h++; - if ($object->isproduct() || ($object->isservice() && ! empty($conf->global->STOCK_SUPPORTS_SERVICES))) // If physical product we can stock (or service with option) + if ($object->isProduct() || ($object->isService() && ! empty($conf->global->STOCK_SUPPORTS_SERVICES))) // If physical product we can stock (or service with option) { if (! empty($conf->stock->enabled) && $user->rights->stock->lire) { diff --git a/htdocs/product/card.php b/htdocs/product/card.php index a7291cc1895..4c30691318f 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1038,7 +1038,7 @@ else require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $type = $langs->trans('Product'); - if ($object->isservice()) $type = $langs->trans('Service'); + if ($object->isService()) $type = $langs->trans('Service'); //print load_fiche_titre($langs->trans('Modify').' '.$type.' : '.(is_object($object->oldcopy)?$object->oldcopy->ref:$object->ref), ""); // Main official, simple, and not duplicated code @@ -1144,7 +1144,7 @@ else // Stock /* - if ($object->isproduct() && ! empty($conf->stock->enabled)) + if ($object->isProduct() && ! empty($conf->stock->enabled)) { print "".''; } - if ($object->isservice()) + if ($object->isService()) { // Duration print ''; } - if ($object->isservice()) + if ($object->isService()) { // Duration print '"; $nblignes=6; - if ($object->isproduct() && ! empty($conf->stock->enabled)) $nblignes++; - if ($object->isservice()) $nblignes++; + if ($object->isProduct() && ! empty($conf->stock->enabled)) $nblignes++; + if ($object->isService()) $nblignes++; // Reference print ''; - else print ''; + else print ''; } else { print ''; } - print ''; + print ''; print ''; print '
'.$langs->trans("StockLimit").''; print ''; @@ -1169,7 +1169,7 @@ else print '
'.$langs->trans("Duration").''; @@ -1435,7 +1435,7 @@ else print '
'.$langs->trans("Duration").''.$object->duration_value.' '; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index ba4dc432d36..0311d7cf281 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3789,7 +3789,7 @@ class Product extends CommonObject * * @return boolean True if it's a product */ - function isproduct() + function isProduct() { return ($this->type == Product::TYPE_PRODUCT ? true : false); } @@ -3799,7 +3799,7 @@ class Product extends CommonObject * * @return boolean True if it's a service */ - function isservice() + function isService() { return ($this->type == Product::TYPE_SERVICE ? true : false); } diff --git a/htdocs/product/composition/card.php b/htdocs/product/composition/card.php index 276356d8bca..86dfb8a8fd4 100644 --- a/htdocs/product/composition/card.php +++ b/htdocs/product/composition/card.php @@ -193,8 +193,8 @@ if ($id > 0 || ! empty($ref)) print "
'.$langs->trans("Ref").''; diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index dfbd5679ac4..96aa9aa6311 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -521,7 +521,7 @@ if ($id > 0 || $ref) { // Suppliers list title print ''; - if ($object->isproduct()) $nblignefour=4; + if ($object->isProduct()) $nblignefour=4; else $nblignefour=4; $param="&id=".$object->id; diff --git a/htdocs/public/paybox/newpayment.php b/htdocs/public/paybox/newpayment.php index 42ea013eade..481fd17f049 100644 --- a/htdocs/public/paybox/newpayment.php +++ b/htdocs/public/paybox/newpayment.php @@ -583,7 +583,7 @@ if (GETPOST("source") == 'contractline' && $valid) $duration=''; if ($contractline->fk_product) { - if ($product->isservice() && $product->duration_value > 0) + if ($product->isService() && $product->duration_value > 0) { $label=$langs->trans("Duration"); diff --git a/htdocs/public/paypal/newpayment.php b/htdocs/public/paypal/newpayment.php index 23f81c4295b..dcb43c07170 100644 --- a/htdocs/public/paypal/newpayment.php +++ b/htdocs/public/paypal/newpayment.php @@ -720,7 +720,7 @@ if (GETPOST("source") == 'contractline' && $valid) $duration=''; if ($contractline->fk_product) { - if ($product->isservice() && $product->duration_value > 0) + if ($product->isService() && $product->duration_value > 0) { $label=$langs->trans("Duration"); From 84a152dc2ec2c84350a7214071422ed9b3251712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 15:33:48 +0100 Subject: [PATCH 033/138] FIX #3836 Unable to upload a document to an invoice under some circunstances --- htdocs/core/lib/files.lib.php | 6 +++++- htdocs/core/tpl/document_actions_post_headers.tpl.php | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index c92d5ab4f25..b30e0494b39 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2,6 +2,7 @@ /* Copyright (C) 2008-2012 Laurent Destailleur * Copyright (C) 2012-2013 Regis Houssin * Copyright (C) 2012 Juanjo Menent + * Copyright (C) 2015 Marcos García * * 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 @@ -1041,10 +1042,13 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio // Define $destpath (path to file including filename) and $destfile (only filename) $destpath=$upload_dir . "/" . $_FILES[$varfiles]['name']; $destfile=$_FILES[$varfiles]['name']; + + $savingdocmask = dol_sanitizeFileName($savingdocmask); + if ($savingdocmask) { $destpath=$upload_dir . "/" . preg_replace('/__file__/',$_FILES[$varfiles]['name'],$savingdocmask); - $destfile=preg_replace('/__file__/',$_FILES[$varfiles]['name'],$savingdocmask); + $destfile=dol_osencode(preg_replace('/__file__/',$_FILES[$varfiles]['name'],$savingdocmask)); } $resupload = dol_move_uploaded_file($_FILES[$varfiles]['tmp_name'], $destpath, $allowoverwrite, 0, $_FILES[$varfiles]['error'], 0, $varfiles); diff --git a/htdocs/core/tpl/document_actions_post_headers.tpl.php b/htdocs/core/tpl/document_actions_post_headers.tpl.php index 75d18c2b1a5..0e91a3e182d 100644 --- a/htdocs/core/tpl/document_actions_post_headers.tpl.php +++ b/htdocs/core/tpl/document_actions_post_headers.tpl.php @@ -1,6 +1,7 @@ * Copyright (C) 2013-2014 Laurent Destailleur + * Copyright (C) 2015 Marcos García * * 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 @@ -48,7 +49,7 @@ if (empty($conf->global->MAIN_DISABLE_SUGGEST_REF_AS_PREFIX)) //var_dump($modulepart); if (in_array($modulepart,array('facture_fournisseur','commande_fournisseur','facture','commande','propal','ficheinter','contract','project','project_task'))) { - $savingdocmask=$object->ref.'-__file__'; + $savingdocmask=dol_sanitizeFileName($object->ref).'-__file__'; } /*if (in_array($modulepart,array('member'))) { From 4a52d3c1b1a2ca4df694e222df71b6591676e5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 15:35:00 +0100 Subject: [PATCH 034/138] Removed unwanted change --- htdocs/core/lib/files.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index b30e0494b39..7f6737afba2 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1048,7 +1048,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio if ($savingdocmask) { $destpath=$upload_dir . "/" . preg_replace('/__file__/',$_FILES[$varfiles]['name'],$savingdocmask); - $destfile=dol_osencode(preg_replace('/__file__/',$_FILES[$varfiles]['name'],$savingdocmask)); + $destfile=preg_replace('/__file__/',$_FILES[$varfiles]['name'],$savingdocmask); } $resupload = dol_move_uploaded_file($_FILES[$varfiles]['tmp_name'], $destpath, $allowoverwrite, 0, $_FILES[$varfiles]['error'], 0, $varfiles); From 57e162d7f87a250014c7ec6ae6e4a9094a3b6ee6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 15:13:51 +0100 Subject: [PATCH 035/138] The component selectAjaxArray can return javascript part into a global "delayed" variable so caller can output it at end of page. This reduce the Flash Over Unstyle Content effect. --- htdocs/core/class/html.form.class.php | 32 ++++++---- htdocs/main.inc.php | 31 +++++---- htdocs/margin/tabs/productMargins.php | 2 +- htdocs/product/class/product.class.php | 10 +-- htdocs/product/document.php | 2 +- htdocs/product/stats/card.php | 63 ++++++++----------- htdocs/product/stats/commande.php | 36 ++++------- htdocs/product/stats/commande_fournisseur.php | 43 +++++-------- htdocs/product/stats/contrat.php | 38 +++++------ htdocs/product/stats/facture.php | 37 ++++------- htdocs/product/stats/facture_fournisseur.php | 36 ++++------- htdocs/product/stats/propal.php | 36 ++++------- htdocs/product/stock/product.php | 7 ++- htdocs/public/test/test_forms.php | 1 - 14 files changed, 158 insertions(+), 216 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 822c43f3370..6c586ffe9b7 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4513,22 +4513,25 @@ class Form * @param string $morecss Add more class to css styles * @param int $callurlonselect If set to 1, some code is added so an url return by the ajax is called when value is selected. * @param string $placeholder String to use as placeholder - * @return string HTML select string. + * @param string $acceptdelayedhtml 1 if caller request to have html delayed content not returned but saved into global $delayedhtmlcontent (so caller can show it at end of page to avoid flash FOUC effect) + * @return string HTML select string */ - static function selectArrayAjax($htmlname, $url, $id='', $moreparam='', $moreparamtourl='', $disabled=0, $minimumInputLength=1, $morecss='', $callurlonselect=0, $placeholder='') + static function selectArrayAjax($htmlname, $url, $id='', $moreparam='', $moreparamtourl='', $disabled=0, $minimumInputLength=1, $morecss='', $callurlonselect=0, $placeholder='', $acceptdelayedhtml=0) { global $langs; + global $delayedhtmlcontent; - $out = ''; - $tmpplugin='select2'; - $out.=' + + $out=''; + + $outdelayed=' '; + }); + '; - - $out.=''; - + if ($acceptdelayedhtml) + { + $delayedhtmlcontent.=$outdelayed; + } + else + { + $out.=$outdelayed; + } return $out; } diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 8943ca95821..354ecb7b611 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -931,7 +931,7 @@ if (! function_exists("llxHeader")) } if (empty($conf->dol_hide_leftmenu)) { - left_menu('', $help_url, '', '', 1, $title); + left_menu('', $help_url, '', '', 1, $title, 1); } // main area @@ -1401,13 +1401,6 @@ function top_menu($head, $title='', $target='', $disablejs=0, $disablehead=0, $a ' . "\n"; } - // Wrapper to show tooltips - print '' . "\n"; - // Raven.js for client-side Sentry logging support if (array_key_exists('mod_syslog_sentry', $conf->loghandlers) && ! empty($conf->global->SYSLOG_SENTRY_DSN)) { @@ -1539,9 +1532,10 @@ function top_menu($head, $title='', $target='', $disablejs=0, $disablehead=0, $a * @param array $menu_array_after Table of menu entries to show after entries of menu handler * @param int $leftmenuwithoutmainarea Must be set to 1. 0 by default for backward compatibility with old modules. * @param string $title Title of web page + * @param string $acceptdelayedhtml 1 if caller request to have html delayed content not returned but saved into global $delayedhtmlcontent (so caller can show it at end of page to avoid flash FOUC effect) * @return void */ -function left_menu($menu_array_before, $helppagename='', $notused='', $menu_array_after='', $leftmenuwithoutmainarea=0, $title='') +function left_menu($menu_array_before, $helppagename='', $notused='', $menu_array_after='', $leftmenuwithoutmainarea=0, $title='', $acceptdelayedhtml=0) { global $user, $conf, $langs, $db, $form; global $hookmanager, $menumanager; @@ -1563,7 +1557,7 @@ function left_menu($menu_array_before, $helppagename='', $notused='', $menu_arra { if (! is_object($form)) $form=new Form($db); $selected=-1; - $searchform.=$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, '', '', 0, 1, 'vmenusearchselectcombo', 1, $langs->trans("Search")); + $searchform.=$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, '', '', 0, 1, 'vmenusearchselectcombo', 1, $langs->trans("Search"), 1); } else { @@ -1770,7 +1764,6 @@ function left_menu($menu_array_before, $helppagename='', $notused='', $menu_arra print "\n"; print ''."\n"; - if (empty($leftmenuwithoutmainarea)) main_area($title); } @@ -1892,6 +1885,7 @@ if (! function_exists("llxFooter")) /** * Show HTML footer * Close div /DIV data-role=page + /DIV class=fiche + /DIV /DIV main layout + /BODY + /HTML. + * If global var $delayedhtmlcontent was filled, we output it just before closing the body. * * @param string $comment A text to add as HTML comment into HTML generated page * @param string $zone 'private' (for private pages) or 'public' (for public pages) @@ -1900,7 +1894,8 @@ if (! function_exists("llxFooter")) function llxFooter($comment='',$zone='private') { global $conf, $langs; - + global $delayedhtmlcontent; + // Global html output events ($mesgs, $errors, $warnings) dol_htmloutput_events(); @@ -1937,6 +1932,18 @@ if (! function_exists("llxFooter")) //var_dump($langs); // Uncommment to see the property _tab_loaded to see which language file were loaded if (empty($conf->dol_hide_leftmenu) && empty($conf->dol_use_jmobile) && empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print ' '."\n"; // End div container + + if (! empty($delayedhtmlcontent)) print $delayedhtmlcontent; + + // Wrapper to show tooltips + print "\n\n"; + print '' . "\n"; + + print "\n"; print "\n"; } diff --git a/htdocs/margin/tabs/productMargins.php b/htdocs/margin/tabs/productMargins.php index 3b952b099ef..b409d0c752f 100644 --- a/htdocs/margin/tabs/productMargins.php +++ b/htdocs/margin/tabs/productMargins.php @@ -91,7 +91,7 @@ if ($id > 0 || ! empty($ref)) print '
'; // Total Margin - print ''; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index ba4dc432d36..3b653f9d919 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2207,7 +2207,7 @@ class Product extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."facturedet as d, ".MAIN_DB_PREFIX."facture as f, ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE f.rowid = d.fk_facture"; - $sql.= " AND d.fk_product =".$this->id; + if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; $sql.= " AND f.fk_soc = s.rowid"; $sql.= " AND f.entity IN (".getEntity('facture', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND f.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; @@ -2236,7 +2236,7 @@ class Product extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."facture_fourn_det as d, ".MAIN_DB_PREFIX."facture_fourn as f, ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE f.rowid = d.fk_facture_fourn"; - $sql.= " AND d.fk_product =".$this->id; + if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; $sql.= " AND f.fk_soc = s.rowid"; $sql.= " AND f.entity IN (".getEntity('facture_fourn', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND f.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; @@ -2265,7 +2265,7 @@ class Product extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."propaldet as d, ".MAIN_DB_PREFIX."propal as p, ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE p.rowid = d.fk_propal"; - $sql.= " AND d.fk_product =".$this->id; + if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; $sql.= " AND p.fk_soc = s.rowid"; $sql.= " AND p.entity IN (".getEntity('propal', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND p.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; @@ -2292,7 +2292,7 @@ class Product extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as d, ".MAIN_DB_PREFIX."commande as c, ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE c.rowid = d.fk_commande"; - $sql.= " AND d.fk_product =".$this->id; + if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; $sql.= " AND c.fk_soc = s.rowid"; $sql.= " AND c.entity IN (".getEntity('commande', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; @@ -2319,7 +2319,7 @@ class Product extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as d, ".MAIN_DB_PREFIX."commande_fournisseur as c, ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE c.rowid = d.fk_commande"; - $sql.= " AND d.fk_product =".$this->id; + if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; $sql.= " AND c.fk_soc = s.rowid"; $sql.= " AND c.entity IN (".getEntity('commande_fournisseur', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; diff --git a/htdocs/product/document.php b/htdocs/product/document.php index 93a5c21862d..ecb3d12bb52 100644 --- a/htdocs/product/document.php +++ b/htdocs/product/document.php @@ -202,7 +202,7 @@ if ($object->id) print '
'; print '
'.$langs->trans("TotalMargin").''; + print '
'.$langs->trans("TotalMargin").''; print ''; // set by jquery (see below) print '
'; - print ''; + print ''; print ''; print '
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; diff --git a/htdocs/product/stats/card.php b/htdocs/product/stats/card.php index 5fe6d5a4be3..4203705cfee 100644 --- a/htdocs/product/stats/card.php +++ b/htdocs/product/stats/card.php @@ -38,7 +38,7 @@ $langs->load("products"); $langs->load("bills"); $langs->load("other"); -$id = GETPOST('id','int'); +$id = GETPOST('id','int'); // For this page, id can also be 'all' $ref = GETPOST('ref'); $mode = (GETPOST('mode') ? GETPOST('mode') : 'byunit'); $error = 0; @@ -56,16 +56,24 @@ $result=restrictedArea($user,'produit|service',$fieldvalue,'product&product','', /* * View */ + $form = new Form($db); -if (! empty($id) || ! empty($ref)) +if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all') { $object = new Product($db); - $result = $object->fetch($id,$ref); - - llxHeader("","",$langs->trans("CardProduct".$object->type)); - - if ($result) + if (! empty($id) || ! empty($ref)) + { + $result = $object->fetch($id,$ref); + llxHeader("",$langs->trans("CardProduct".$object->type)); + } + else + { + llxHeader("",$langs->trans("ProductStatistics")); + } + + + if ($result && (! empty($id) || ! empty($ref))) { $head=product_prepare_head($object); $titre=$langs->trans("CardProduct".$object->type); @@ -73,37 +81,18 @@ if (! empty($id) || ! empty($ref)) dol_fiche_head($head, 'stats', $titre, 0, $picto); - print ''; - - // Reference - print ''; - print ''; - print ''; - - // Label - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; - - print '
'.$langs->trans("Ref").''; - print $form->showrefnav($object,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$object->label.'
'.$langs->trans("Status").' ('.$langs->trans("Sell").')'; - print $object->getLibStatut(2,0); - print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; - print $object->getLibStatut(2,1); - print '
'; - + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + dol_fiche_end(); - - + } + + + if ($result) + { // Choice of stats if (! empty($conf->dol_use_jmobile)) print "\n".'
'."\n"; - if ($mode == 'bynumber') print ''; + if ($mode == 'bynumber') print 'id).'&mode=byunit">'; else print img_picto('','tick').' '; print $langs->trans("StatsByNumberOfUnits"); if ($mode == 'bynumber') print ''; @@ -111,7 +100,7 @@ if (! empty($id) || ! empty($ref)) if (! empty($conf->dol_use_jmobile)) print '
'."\n".'
'."\n"; else print '   /   '; - if ($mode == 'byunit') print ''; + if ($mode == 'byunit') print 'id).'&mode=bynumber">'; else print img_picto('','tick').' '; print $langs->trans("StatsByNumberOfEntities"); if ($mode == 'byunit') print ''; @@ -237,13 +226,13 @@ if (! empty($id) || ! empty($ref)) if ($graphfiles[$key]['output'] && ! $px->isGraphKo()) { if (file_exists($dir."/".$graphfiles[$key]['file']) && filemtime($dir."/".$graphfiles[$key]['file'])) print '
'.$langs->trans("GeneratedOn",dol_print_date(filemtime($dir."/".$graphfiles[$key]['file']),"dayhour")).''.$langs->trans("GeneratedOn",dol_print_date(dol_now()),"dayhour").''.$langs->trans("GeneratedOn",dol_print_date(dol_now(),"dayhour")).''.($mesg?''.$mesg.'':$langs->trans("ChartNotGenerated")).''.img_picto($langs->trans("ReCalculate"),'refresh').'id).'&action=recalcul&mode='.$mode.'">'.img_picto($langs->trans("ReCalculate"),'refresh').'
'; diff --git a/htdocs/product/stats/commande.php b/htdocs/product/stats/commande.php index cdf571d7c75..69334976141 100644 --- a/htdocs/product/stats/commande.php +++ b/htdocs/product/stats/commande.php @@ -81,6 +81,8 @@ if ($id > 0 || ! empty($ref)) $product = new Product($db); $result = $product->fetch($id, $ref); + $object = $product; + $parameters=array('id'=>$id); $reshook=$hookmanager->executeHooks('doActions',$parameters,$product,$action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -97,34 +99,22 @@ if ($id > 0 || ! empty($ref)) $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$product,$action); // Note that $action and $object may have been modified by hook if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - print ''; - - // Reference - print ''; - print ''; - print ''; - - // Libelle - print ''; - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
'.$langs->trans("Ref").''; - print $form->showrefnav($product,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$product->label.'
'.$langs->trans("Status").' ('.$langs->trans("Sell").')'; - print $product->getLibStatut(2,0); - print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; - print $product->getLibStatut(2,1); - print '
'; show_stats_for_company($product,$socid); print "
"; - print ''; + print ''; + print '
'; + + dol_fiche_end(); + if ($user->rights->commande->lire) { diff --git a/htdocs/product/stats/commande_fournisseur.php b/htdocs/product/stats/commande_fournisseur.php index ef5352892c6..83f0912b3ee 100644 --- a/htdocs/product/stats/commande_fournisseur.php +++ b/htdocs/product/stats/commande_fournisseur.php @@ -86,16 +86,17 @@ if ($id > 0 || ! empty($ref)) { $product = new Product($db); $result = $product->fetch($id, $ref); - $parameters = array ( - 'id' => $id - ); + $object = $product; + + $parameters = array ('id' => $id); $reshook = $hookmanager->executeHooks('doActions', $parameters, $product, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); llxHeader("", "", $langs->trans("CardProduct" . $product->type)); - if ($result > 0) { + if ($result > 0) + { $head = product_prepare_head($product); $titre = $langs->trans("CardProduct" . $product->type); $picto = ($product->type == Product::TYPE_SERVICE ? 'service' : 'product'); @@ -105,34 +106,22 @@ if ($id > 0 || ! empty($ref)) { if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - print ''; - - // Reference - print ''; - print ''; - print ''; - - // Libelle - print ''; - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
' . $langs->trans("Ref") . ''; - print $form->showrefnav($product, 'ref', '', 1, 'ref'); - print '
' . $langs->trans("Label") . '' . $product->label . '
' . $langs->trans("Status") . ' (' . $langs->trans("Sell") . ')'; - print $product->getLibStatut(2, 0); - print '
' . $langs->trans("Status") . ' (' . $langs->trans("Buy") . ')'; - print $product->getLibStatut(2, 1); - print '
'; show_stats_for_company($product, $socid); print "
"; - print ''; + print ''; + print '
'; + + dol_fiche_end(); + if ($user->rights->fournisseur->commande->lire) { diff --git a/htdocs/product/stats/contrat.php b/htdocs/product/stats/contrat.php index 9d4d7d53abc..c2e6b25f7ab 100644 --- a/htdocs/product/stats/contrat.php +++ b/htdocs/product/stats/contrat.php @@ -71,6 +71,8 @@ if ($id > 0 || ! empty($ref)) $product = new Product($db); $result = $product->fetch($id, $ref); + $object = $product; + $parameters=array('id'=>$id); $reshook=$hookmanager->executeHooks('doActions',$parameters,$product,$action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -87,34 +89,22 @@ if ($id > 0 || ! empty($ref)) $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$product,$action); // Note that $action and $object may have been modified by hook if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
'; - // Reference - print ''; - print ''; - print ''; - - // Libelle - print ''; - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; - - show_stats_for_company($product,$socid); + show_stats_for_company($product,$socid); print "
'.$langs->trans("Ref").''; - print $form->showrefnav($product,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$product->label.'
'.$langs->trans("Status").' ('.$langs->trans("Sell").')'; - print $product->getLibStatut(2,0); - print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; - print $product->getLibStatut(2,1); - print '
"; - print ''; + print ''; + print '
'; + + dol_fiche_end(); + $now=dol_now(); diff --git a/htdocs/product/stats/facture.php b/htdocs/product/stats/facture.php index da39d5d67c1..590830702bb 100644 --- a/htdocs/product/stats/facture.php +++ b/htdocs/product/stats/facture.php @@ -81,7 +81,9 @@ if ($id > 0 || ! empty($ref)) { $product = new Product($db); $result = $product->fetch($id, $ref); - + + $object = $product; + $parameters=array('id'=>$id); $reshook=$hookmanager->executeHooks('doActions',$parameters,$product,$action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -98,34 +100,21 @@ if ($id > 0 || ! empty($ref)) $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$product,$action); // Note that $action and $object may have been modified by hook if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - print ''; - - // Reference - print ''; - print ''; - print ''; - - // Libelle - print ''; - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
'.$langs->trans("Ref").''; - print $form->showrefnav($product,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$product->label.'
'.$langs->trans("Status").' ('.$langs->trans("Sell").')'; - print $product->getLibStatut(2,0); - print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; - print $product->getLibStatut(2,1); - print '
'; show_stats_for_company($product,$socid); print "
"; - print ''; + print ''; + print '
'; + + dol_fiche_end(); if ($user->rights->facture->lire) diff --git a/htdocs/product/stats/facture_fournisseur.php b/htdocs/product/stats/facture_fournisseur.php index 3d5cbcbe455..27e5495a771 100644 --- a/htdocs/product/stats/facture_fournisseur.php +++ b/htdocs/product/stats/facture_fournisseur.php @@ -83,6 +83,8 @@ if ($id > 0 || ! empty($ref)) $product = new Product($db); $result = $product->fetch($id, $ref); + $object = $product; + $parameters = array('id' => $id); $reshook = $hookmanager->executeHooks('doActions', $parameters, $product, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -99,34 +101,22 @@ if ($id > 0 || ! empty($ref)) $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $product, $action); // Note that $action and $object may have been modified by hook if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - print ''; - - // Reference - print ''; - print ''; - print ''; - - // Libelle - print ''; - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
' . $langs->trans("Ref") . ''; - print $form->showrefnav($product, 'ref', '', 1, 'ref'); - print '
' . $langs->trans("Label") . '' . $product->label . '
' . $langs->trans("Status") . ' (' . $langs->trans("Sell") . ')'; - print $product->getLibStatut(2, 0); - print '
' . $langs->trans("Status") . ' (' . $langs->trans("Buy") . ')'; - print $product->getLibStatut(2, 1); - print '
'; show_stats_for_company($product, $socid); print "
"; - print ''; + print ''; + print '
'; + + dol_fiche_end(); + if ($user->rights->fournisseur->facture->lire) { diff --git a/htdocs/product/stats/propal.php b/htdocs/product/stats/propal.php index 44101d72e52..2fa69740e8b 100644 --- a/htdocs/product/stats/propal.php +++ b/htdocs/product/stats/propal.php @@ -81,6 +81,8 @@ if ($id > 0 || ! empty($ref)) $product = new Product($db); $result = $product->fetch($id, $ref); + $object = $product; + $parameters = array ('id' => $id); $reshook = $hookmanager->executeHooks('doActions', $parameters, $product, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -97,34 +99,22 @@ if ($id > 0 || ! empty($ref)) $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $product, $action); // Note that $action and $object may have been modified by hook if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - print ''; - - // Reference - print ''; - print ''; - print ''; - - // Libelle - print ''; - print ''; - - // Status (to sell) - print ''; - - // Status (to buy) - print ''; + dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); + + print '
'; + + print '
'; + print '
' . $langs->trans("Ref") . ''; - print $form->showrefnav($product, 'ref', '', 1, 'ref'); - print '
' . $langs->trans("Label") . '' . $product->label . '
' . $langs->trans("Status") . ' (' . $langs->trans("Sell") . ')'; - print $product->getLibStatut(2, 0); - print '
' . $langs->trans("Status") . ' (' . $langs->trans("Buy") . ')'; - print $product->getLibStatut(2, 1); - print '
'; show_stats_for_company($product, $socid); print "
"; - print ''; + print ''; + print '
'; + + dol_fiche_end(); + if ($user->rights->propale->lire) { diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index c37424e548b..093a364752c 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -399,14 +399,15 @@ if ($id > 0 || $ref) print '
'; print ''; - if ($conf->productbatch->enabled) { - print ''; } // PMP - print ''; + print ''; print ''; diff --git a/htdocs/public/test/test_forms.php b/htdocs/public/test/test_forms.php index f1c00f94acf..7fec8e895b6 100644 --- a/htdocs/public/test/test_forms.php +++ b/htdocs/public/test/test_forms.php @@ -68,7 +68,6 @@ print "Test 4d: a select with ajax refresh and with onchange call of url
\n"; $selected=-1; print $form->selectArrayAjax('testselectc', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, 'style="min-width: 250px;"', '', 0, 1, '', 1); - print '

'."\n"; // Test5a: form->select_thirdparty From 4e64230ac975ee04cef10080b38652923acee35f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 16:25:14 +0100 Subject: [PATCH 036/138] NEW Add chart of product statistics --- htdocs/core/menus/standard/eldy.lib.php | 4 +- htdocs/product/popuprop.php | 58 +++++++------ htdocs/product/stats/card.php | 107 +++++++++++++++++++++--- 3 files changed, 130 insertions(+), 39 deletions(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 099d65f7f95..6d31fbc52f6 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1088,7 +1088,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu } if (! empty($conf->propal->enabled)) { - $newmenu->add("/product/popuprop.php?leftmenu=stats&type=0", $langs->trans("Statistics"), 1, $user->rights->produit->lire && $user->rights->propale->lire); + $newmenu->add("/product/stats/card.php?id=all&leftmenu=stats&type=0", $langs->trans("Statistics"), 1, $user->rights->produit->lire && $user->rights->propale->lire); } } @@ -1100,7 +1100,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $newmenu->add("/product/list.php?leftmenu=service&type=1", $langs->trans("List"), 1, $user->rights->service->lire); if (! empty($conf->propal->enabled)) { - $newmenu->add("/product/popuprop.php?leftmenu=stats&type=1", $langs->trans("Statistics"), 1, $user->rights->service->lire && $user->rights->propale->lire); + $newmenu->add("/product/stats/card.php?id=all&leftmenu=stats&type=1", $langs->trans("Statistics"), 1, $user->rights->service->lire && $user->rights->propale->lire); } } diff --git a/htdocs/product/popuprop.php b/htdocs/product/popuprop.php index c8da665dd98..aad606627cb 100644 --- a/htdocs/product/popuprop.php +++ b/htdocs/product/popuprop.php @@ -38,18 +38,16 @@ $type=GETPOST("type","int"); if (! empty($user->societe_id)) $socid=$user->societe_id; $result=restrictedArea($user,'produit|service'); +$limit = GETPOST("limit")?GETPOST("limit","int"):$conf->liste_limit; $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); $page = GETPOST("page",'int'); -if ($page < 0) $page = 0; +if ($page == -1) { $page = 0; } if (! $sortfield) $sortfield="c"; if (! $sortorder) $sortorder="DESC"; - -$conf->liste_limit = 3; - -if ($page == -1) $page = 0; -$limit = $conf->liste_limit; $offset = $limit * $page ; +$pageprev = $page - 1; +$pagenext = $page + 1; $staticproduct=new Product($db); @@ -69,7 +67,13 @@ if ($type == '0') else if ($type == '1') { $helpurl='EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; - $title=$langs->trans("StatisticsOfServices"); + //$title=$langs->trans("StatisticsOfServices"); + $title=$langs->trans("Statistics"); +} +else +{ + $helpurl='EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; + //$title=$langs->trans("StatisticsOfProductsOrServices"); $title=$langs->trans("Statistics"); } @@ -80,24 +84,30 @@ print load_fiche_titre($title, $mesg,'title_products.png'); $param = ''; $title = $langs->trans("ListProductServiceByPopularity"); -if ($type != '') { - $param = '&type='.$type; - - if ($type == 1) { - $title = $langs->trans("ListServiceByPopularity"); - } else { - $title = $langs->trans("ListProductByPopularity"); - } +if ((string) $type == '1') { + $title = $langs->trans("ListServiceByPopularity"); } +if ((string) $type == '0') { + $title = $langs->trans("ListProductByPopularity"); +} + +if ($type != '') $param .= '&type='.$type; + $h=0; $head = array(); -$head[$h][0] = $_SERVER['PHP_SELF']; -$head[$h][1] = $title; -$head[$h][2] = 'product'; + +$head[$h][0] = DOL_URL_ROOT.'/product/stats/card.php?id=all'; +$head[$h][1] = $langs->trans("Chart"); +$head[$h][2] = 'chart'; $h++; -dol_fiche_head($head,'product',$langs->trans("Statistics")); +$head[$h][0] = $_SERVER['PHP_SELF']; +$head[$h][1] = $title; +$head[$h][2] = 'popularityprop'; +$h++; + +dol_fiche_head($head,'popularityprop',$langs->trans("Statistics")); @@ -127,15 +137,15 @@ if ($result) $num = $db->num_rows($result); $i = 0; - print_barre_liste($title, $page, $_SERVER["PHP_SELF"],$param,$sortfield,$sortorder,"",$num, $totalnboflines, ''); + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, "", $num, $totalnboflines, ''); print '
'.$langs->trans("ManageLotSerial").''; + if ($conf->productbatch->enabled) + { + print '
'.$langs->trans("ManageLotSerial").''; print $object->getLibStatut(0,2); print '
'.$langs->trans("AverageUnitPricePMP").'
'.$langs->trans("AverageUnitPricePMP").''; if ($object->pmp > 0) print price($object->pmp).' '.$langs->trans("HT"); print '
'; print ""; - print_liste_field_titre($langs->trans('Ref'), $_SERVER["PHP_SELF"], 'p.ref', '', '', '', $sortfield, $sortorder); - print_liste_field_titre($langs->trans('Type'), $_SERVER["PHP_SELF"], 'p.type', '', '', '', $sortfield, $sortorder); - print_liste_field_titre($langs->trans('Label'), $_SERVER["PHP_SELF"], 'p.label', '', '', '', $sortfield, $sortorder); - print_liste_field_titre($langs->trans('NbOfProposals'), $_SERVER["PHP_SELF"], 'c', '', '', 'align="right"', $sortfield, $sortorder); + print_liste_field_titre($langs->trans('Ref'), $_SERVER["PHP_SELF"], 'p.ref', '', $param, '', $sortfield, $sortorder); + print_liste_field_titre($langs->trans('Type'), $_SERVER["PHP_SELF"], 'p.fk_product_type', '', $param, '', $sortfield, $sortorder); + print_liste_field_titre($langs->trans('Label'), $_SERVER["PHP_SELF"], 'p.label', '', $param, '', $sortfield, $sortorder); + print_liste_field_titre($langs->trans('NbOfProposals'), $_SERVER["PHP_SELF"], 'c', '', $param, 'align="right"', $sortfield, $sortorder); print "\n"; diff --git a/htdocs/product/stats/card.php b/htdocs/product/stats/card.php index 4203705cfee..33390e51a70 100644 --- a/htdocs/product/stats/card.php +++ b/htdocs/product/stats/card.php @@ -62,14 +62,38 @@ $form = new Form($db); if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all') { $object = new Product($db); - if (! empty($id) || ! empty($ref)) + if (GETPOST('id') == 'all') { - $result = $object->fetch($id,$ref); - llxHeader("",$langs->trans("CardProduct".$object->type)); + llxHeader("",$langs->trans("ProductStatistics")); + + $type = GETPOST('type'); + + $helpurl=''; + if ($type == '0') + { + $helpurl='EN:Module_Products|FR:Module_Produits|ES:Módulo_Productos'; + //$title=$langs->trans("StatisticsOfProducts"); + $title=$langs->trans("Statistics"); + } + else if ($type == '1') + { + $helpurl='EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; + //$title=$langs->trans("StatisticsOfServices"); + $title=$langs->trans("Statistics"); + } + else + { + $helpurl='EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; + //$title=$langs->trans("StatisticsOfProductsOrServices"); + $title=$langs->trans("Statistics"); + } + + print load_fiche_titre($title, $mesg,'title_products.png'); } else { - llxHeader("",$langs->trans("ProductStatistics")); + $result = $object->fetch($id,$ref); + llxHeader("",$langs->trans("CardProduct".$object->type)); } @@ -85,14 +109,70 @@ if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all') dol_fiche_end(); } - - - if ($result) + if (GETPOST('id') == 'all') { + $h=0; + $head = array(); + + $head[$h][0] = DOL_URL_ROOT.'/product/stats/card.php?id=all'; + $head[$h][1] = $langs->trans("Chart"); + $head[$h][2] = 'chart'; + $h++; + + $title = $langs->trans("ListProductServiceByPopularity"); + if ((string) $type == '1') { + $title = $langs->trans("ListServiceByPopularity"); + } + if ((string) $type == '0') { + $title = $langs->trans("ListProductByPopularity"); + } + + $head[$h][0] = DOL_URL_ROOT.'/product/popuprop.php'.($type != ''?'?type='.$type:''); + $head[$h][1] = $title; + $head[$h][2] = 'popularityprop'; + $h++; + + dol_fiche_head($head,'chart',$langs->trans("Statistics")); + } + + + if ($result || GETPOST('id') == 'all') + { + if (GETPOST('id') == 'all') + { + // Choice of type of product + if (! empty($conf->dol_use_jmobile)) print "\n".'
'."\n"; + + if ((string) $type != '0') print 'id).'&type=0">'; + else print img_picto('','tick').' '; + print $langs->trans("Products"); + if ((string) $type != '0') print ''; + + if (! empty($conf->dol_use_jmobile)) print '
'."\n".'
'."\n"; + else print '   /   '; + + if ((string) $type != '1') print 'id).'&type=1">'; + else print img_picto('','tick').' '; + print $langs->trans("Services"); + if ((string) $type != '1') print ''; + + if (! empty($conf->dol_use_jmobile)) print '
'."\n".'
'."\n"; + else print '   /   '; + + if ((string) $type == '0' || (string) $type == '1') print 'id).'">'; + else print img_picto('','tick').' '; + print $langs->trans("ProductsAndServices"); + if ((string) $type == '0' || (string) $type == '1') print ''; + + if (! empty($conf->dol_use_jmobile)) print '
'; + else print '
'; + print '
'; + } + // Choice of stats if (! empty($conf->dol_use_jmobile)) print "\n".'
'."\n"; - if ($mode == 'bynumber') print 'id).'&mode=byunit">'; + if ($mode == 'bynumber') print 'id).($type != '' ? '&type='.$type:'').'&mode=byunit">'; else print img_picto('','tick').' '; print $langs->trans("StatsByNumberOfUnits"); if ($mode == 'bynumber') print ''; @@ -100,7 +180,7 @@ if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all') if (! empty($conf->dol_use_jmobile)) print '
'."\n".'
'."\n"; else print '   /   '; - if ($mode == 'byunit') print 'id).'&mode=bynumber">'; + if ($mode == 'byunit') print 'id).($type != '' ? '&type='.$type:'').'&mode=bynumber">'; else print img_picto('','tick').' '; print $langs->trans("StatsByNumberOfEntities"); if ($mode == 'byunit') print ''; @@ -255,10 +335,11 @@ if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all') print "\n".'
'; print '

'."\n"; } - - print '
'; - print '
'; - + } + + if (GETPOST('id') == 'all') + { + dol_fiche_end(); } } else From 198f8102fadbd61c3fe890860d08755506c3b542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sat, 7 Nov 2015 16:46:15 +0100 Subject: [PATCH 037/138] FIX #3941 Error installing Dolibarr develop --- htdocs/install/mysql/tables/llx_opensurvey_sondage.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql b/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql index 16e8a624e72..b728702db79 100644 --- a/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql +++ b/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql @@ -29,5 +29,5 @@ CREATE TABLE llx_opensurvey_sondage ( allow_comments tinyint NOT NULL DEFAULT 1, allow_spy tinyint NOT NULL DEFAULT 1, tms TIMESTAMP, - sujet TEXT, -- Not filled if format = 'F'. Question are into table llx_opensurvey_formquestions + sujet TEXT -- Not filled if format = 'F'. Question are into table llx_opensurvey_formquestions ) ENGINE=InnoDB; From a4fafae1096ec577ebb8e8246bad5a88c05664c5 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sat, 7 Nov 2015 17:19:13 +0100 Subject: [PATCH 038/138] FIX : Remove column creation for table llx_product_fournisseur_price, the column use un calss is fk_supplier_price_expression, and fk_price_expression does not exist into lx_product_fournisseur_price sql file declaration --- htdocs/install/mysql/migration/3.7.0-3.8.0.sql | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 965704f5309..2c0a788e446 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -148,8 +148,6 @@ CREATE TABLE llx_printing userid integer )ENGINE=innodb; -ALTER TABLE llx_product_fournisseur_price ADD COLUMN fk_price_expression integer DEFAULT NULL; - -- Add situation invoices ALTER TABLE llx_facture ADD COLUMN situation_cycle_ref smallint; ALTER TABLE llx_facture ADD COLUMN situation_counter smallint; From b34edeb751fe43e5bf3a9ba045e3e605436c8efb Mon Sep 17 00:00:00 2001 From: philippe grand Date: Sat, 7 Nov 2015 21:56:21 +0100 Subject: [PATCH 039/138] [Qual] Uniformize code --- htdocs/comm/address.php | 4 ++-- htdocs/comm/card.php | 10 +++++----- htdocs/comm/mailing/card.php | 2 +- htdocs/comm/propal.php | 36 +++++++++++++++++----------------- htdocs/comm/propal/contact.php | 16 +++++++-------- htdocs/comm/remx.php | 16 +++++++-------- 6 files changed, 42 insertions(+), 42 deletions(-) diff --git a/htdocs/comm/address.php b/htdocs/comm/address.php index eb3c51b1760..edb5042e358 100644 --- a/htdocs/comm/address.php +++ b/htdocs/comm/address.php @@ -106,7 +106,7 @@ if ($action == 'add' || $action == 'update') } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $action='create'; } } @@ -147,7 +147,7 @@ if ($action == 'add' || $action == 'update') else { $reload = 0; - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $action= "edit"; } } diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index b874eeefde5..3083ac9505c 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -105,7 +105,7 @@ if (empty($reshook)) $result=$object->fetch($id); $object->code_compta=$_POST["customeraccountancycode"]; $result=$object->update($object->id,$user,1,1,0); - if ($result < 0) setEventMessage($object->error,$object->errors,'errors'); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); } // conditions de reglement @@ -113,7 +113,7 @@ if (empty($reshook)) { $object->fetch($id); $result=$object->setPaymentTerms(GETPOST('cond_reglement_id','int')); - if ($result < 0) setEventMessage($object->error,$object->errors,'errors'); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); } // mode de reglement @@ -121,7 +121,7 @@ if (empty($reshook)) { $object->fetch($id); $result=$object->setPaymentMethods(GETPOST('mode_reglement_id','int')); - if ($result < 0) setEventMessage($object->error,$object->errors,'errors'); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); } // assujetissement a la TVA @@ -130,7 +130,7 @@ if (empty($reshook)) $object->fetch($id); $object->tva_assuj=$_POST['assujtva_value']; $result=$object->update($object->id); - if ($result < 0) setEventMessage($object->error,$object->errors,'errors'); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); } // set prospect level @@ -157,7 +157,7 @@ if (empty($reshook)) $object->fetch($id); $object->outstanding_limit=GETPOST('outstanding_limit'); $result=$object->set_OutstandingBill($user); - if ($result < 0) setEventMessage($object->error,$object->errors,'errors'); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); } } diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 2a892033865..e54aeb1c8a5 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -359,7 +359,7 @@ if (empty($reshook)) { $statut=2; // Status 'sent partially' (because at least one error) if ($nbok > 0) setEventMessages($langs->transnoentitiesnoconv("EMailSentToNRecipients",$nbok), null, 'mesgs'); - else setEventMessage($langs->transnoentitiesnoconv("EMailSentToNRecipients",$nbok), null, 'mesgs'); + else setEventMessages($langs->transnoentitiesnoconv("EMailSentToNRecipients",$nbok), null, 'mesgs'); } else { diff --git a/htdocs/comm/propal.php b/htdocs/comm/propal.php index 408d01d8eaa..1107e3b9b4d 100644 --- a/htdocs/comm/propal.php +++ b/htdocs/comm/propal.php @@ -6,7 +6,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2006 Andre Cianfarani * Copyright (C) 2010-2014 Juanjo Menent - * Copyright (C) 2010-2011 Philippe Grand + * Copyright (C) 2010-2015 Philippe Grand * Copyright (C) 2012-2013 Christophe Battarel * Copyright (C) 2012 Cedric Salvador * Copyright (C) 2013-2014 Florian Henry @@ -131,7 +131,7 @@ if (empty($reshook)) { if (! GETPOST('socid', 3)) { - setEventMessage($langs->trans("NoCloneOptionsSpecified"), 'errors'); + setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors'); } else { @@ -141,7 +141,7 @@ if (empty($reshook)) header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $result); exit(); } else { - if (count($object->errors) > 0) setEventMessage($object->errors, 'errors'); + if (count($object->errors) > 0) setEventMessages($object->error, $object->errors, 'errors'); $action = ''; } } @@ -157,7 +157,7 @@ if (empty($reshook)) exit(); } else { $langs->load("errors"); - setEventMessage($langs->trans($object->error), 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -211,8 +211,8 @@ if (empty($reshook)) } } else { $langs->load("errors"); - if (count($object->errors) > 0) setEventMessage($object->errors, 'errors'); - else setEventMessage($langs->trans($object->error), 'errors'); + if (count($object->errors) > 0) setEventMessages($object->error, $object->errors, 'errors'); + else setEventMessages($langs->trans($object->error), null, 'errors'); } } @@ -318,7 +318,7 @@ if (empty($reshook)) $id = $object->create_from($user); } else { - setEventMessage($langs->trans("ErrorFailedToCopyProposal", GETPOST('copie_propal')), 'errors'); + setEventMessages($langs->trans("ErrorFailedToCopyProposal", GETPOST('copie_propal')), null, 'errors'); } } else { $object->ref = GETPOST('ref'); @@ -507,7 +507,7 @@ if (empty($reshook)) if ($result < 0) { $error++; - setEventMessage($langs->trans("ErrorFailedToAddContact"), 'errors'); + setEventMessages($langs->trans("ErrorFailedToAddContact"), null, 'errors'); } } @@ -671,7 +671,7 @@ if (empty($reshook)) if ($object->id > 0) { $result = $object->insert_discount($_POST["remise_id"]); if ($result < 0) { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -875,7 +875,7 @@ if (empty($reshook)) if (! empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min))) { $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)); - setEventMessage($mesg, 'errors'); + setEventMessages($mesg, null, 'errors'); } else { // Insert line $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $pu_ttc, $info_bits, $type, - 1, 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $date_start, $date_end, $array_options, $fk_unit); @@ -929,13 +929,13 @@ if (empty($reshook)) } else { $db->rollback(); - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } } - // Mise a jour d'une ligne dans la propale + // Update a line within proposal else if ($action == 'updateligne' && $user->rights->propal->creer && GETPOST('save')) { // Define info_bits @@ -991,7 +991,7 @@ if (empty($reshook)) $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : ''); if ($price_min && (price2num($pu_ht) * (1 - price2num(GETPOST('remise_percent')) / 100) < price2num($price_min))) { - setEventMessage($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), 'errors'); + setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors'); $error ++; } } else { @@ -1040,7 +1040,7 @@ if (empty($reshook)) } else { $db->rollback(); - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -1137,9 +1137,9 @@ if (empty($reshook)) } else { if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { $langs->load("errors"); - setEventMessage($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), 'errors'); + setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors'); } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -1636,13 +1636,13 @@ if ($action == 'create') else if ($action == 'validate') { $error = 0; - // on verifie si l'objet est en numerotation provisoire + // We verifie whether the object is provisionally numbering $ref = substr($object->ref, 1, 4); if ($ref == 'PROV') { $numref = $object->getNextNumRef($soc); if (empty($numref)) { $error ++; - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } else { $numref = $object->ref; diff --git a/htdocs/comm/propal/contact.php b/htdocs/comm/propal/contact.php index 6a0a1076e62..544c5ab27e3 100644 --- a/htdocs/comm/propal/contact.php +++ b/htdocs/comm/propal/contact.php @@ -2,7 +2,7 @@ /* Copyright (C) 2005 Patrick Rouillon * Copyright (C) 2005-2009 Destailleur Laurent * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2011-2012 Philippe Grand + * Copyright (C) 2011-2015 Philippe Grand * * 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 @@ -54,12 +54,12 @@ if ($id > 0 || ! empty($ref)) if ($ret == 0) { $langs->load("errors"); - setEventMessage($langs->trans('ErrorRecordNotFound'), 'errors'); + setEventMessages($langs->trans('ErrorRecordNotFound'), null, 'errors'); $error++; } else if ($ret < 0) { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $error++; } } @@ -75,7 +75,7 @@ else /* - * Ajout d'un nouveau contact + * Add a new contact */ if ($action == 'addcontact' && $user->rights->propale->creer) @@ -96,16 +96,16 @@ if ($action == 'addcontact' && $user->rights->propale->creer) if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { $langs->load("errors"); - setEventMessage($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), 'errors'); + setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors'); } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } -// Bascule du statut d'un contact +// Toggle the status of a contact else if ($action == 'swapstatut' && $user->rights->propale->creer) { if ($object->id > 0) @@ -114,7 +114,7 @@ else if ($action == 'swapstatut' && $user->rights->propale->creer) } } -// Efface un contact +// Deletes a contact else if ($action == 'deletecontact' && $user->rights->propale->creer) { $result = $object->delete_contact($lineid); diff --git a/htdocs/comm/remx.php b/htdocs/comm/remx.php index e472c5fb848..ba85d593fce 100644 --- a/htdocs/comm/remx.php +++ b/htdocs/comm/remx.php @@ -65,17 +65,17 @@ if ($action == 'confirm_split' && GETPOST("confirm") == 'yes') if (! $res > 0) { $error++; - setEventMessage($langs->trans("ErrorFailedToLoadDiscount"), 'errors'); + setEventMessages($langs->trans("ErrorFailedToLoadDiscount"), null, 'errors'); } if (! $error && price2num($_POST["amount_ttc_1"]+$_POST["amount_ttc_2"]) != $discount->amount_ttc) { $error++; - setEventMessage($langs->trans("TotalOfTwoDiscountMustEqualsOriginal"), 'errors'); + setEventMessages($langs->trans("TotalOfTwoDiscountMustEqualsOriginal"), null, 'errors'); } if (! $error && $discount->fk_facture_line) { $error++; - setEventMessage($langs->trans("ErrorCantSplitAUsedDiscount"), 'errors'); + setEventMessages($langs->trans("ErrorCantSplitAUsedDiscount"), null, 'errors'); } if (! $error) { @@ -166,13 +166,13 @@ if ($action == 'setremise') else { $error++; - setEventMessage($soc->error, 'errors'); + setEventMessages($soc->error, $soc->errors, 'errors'); } } } else { - setEventMessage($langs->trans("ErrorFieldFormat",$langs->trans("NewGlobalDiscount")), 'errors'); + setEventMessages($langs->trans("ErrorFieldFormat",$langs->trans("NewGlobalDiscount")), null, 'errors'); } } @@ -194,7 +194,7 @@ if (GETPOST("action") == 'confirm_remove' && GETPOST("confirm")=='yes') } else { - setEventMessage($discount->error, 'errors'); + setEventMessages($discount->error, $discount->errors, 'errors'); $db->rollback(); } } @@ -216,7 +216,7 @@ if ($socid > 0) $object->fetch($socid); /* - * Affichage onglets + * Display tabs */ $head = societe_prepare_head($object); @@ -300,7 +300,7 @@ if ($socid > 0) } /* - * Liste remises fixes restant en cours (= liees a acune facture ni ligne de facture) + * Liste remises fixes restant en cours (= liees a aucune facture ni ligne de facture) */ $sql = "SELECT rc.rowid, rc.amount_ht, rc.amount_tva, rc.amount_ttc, rc.tva_tx,"; $sql.= " rc.datec as dc, rc.description,"; From 3906cb79c5bb49236721558c44d76ce48197bacf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 23:41:45 +0100 Subject: [PATCH 040/138] NEW: Add parameter to add a link to use "date of invoice" in one click when fille a payment card. --- htdocs/compta/facture/class/facture.class.php | 1 + htdocs/compta/paiement.php | 2 +- htdocs/core/class/html.form.class.php | 10 +++++++++- htdocs/fourn/facture/paiement.php | 8 ++++---- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index ede68b39324..ca7afeb7959 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -63,6 +63,7 @@ class Facture extends CommonInvoice var $author; var $fk_user_author; var $fk_user_valid; + var $date; // Date invoice var $date_creation; // Creation date var $date_validation; // Validation date var $datem; diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index 7466686239a..8c028b23aaa 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -415,7 +415,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie print ''; print ''; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 6c586ffe9b7..d64b9971a27 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4057,10 +4057,11 @@ class Form * @param int $disabled Disable input fields * @param int $fullday When a checkbox with this html name is on, hour and day are set with 00:00 or 23:59 * @param string $addplusone Add a link "+1 hour". Value must be name of another select_date field. + * @param datetime $adddateof Add a link "Date of invoice" using the following date. * @return mixed Nothing or string if nooutput is 1 * @see form_date */ - function select_date($set_time='', $prefix='re', $h=0, $m=0, $empty=0, $form_name="", $d=1, $addnowlink=0, $nooutput=0, $disabled=0, $fullday='', $addplusone='') + function select_date($set_time='', $prefix='re', $h=0, $m=0, $empty=0, $form_name="", $d=1, $addnowlink=0, $nooutput=0, $disabled=0, $fullday='', $addplusone='', $adddateof='') { global $conf,$langs; @@ -4318,6 +4319,13 @@ class Form } } + // Add a "Plus one hour" link + if ($conf->use_javascript_ajax && $adddateof) + { + $tmparray=dol_getdate($adddateof); + $retstring.=' - '; print ''; print ''; print ''; @@ -304,7 +304,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie if (! empty($conf->banque->enabled)) { print ''; } else From 031b33d582588aa44c4aac329715f25cba45a3da Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Nov 2015 23:54:11 +0100 Subject: [PATCH 041/138] FIX Checkbox reconciliated no correctly checked with some Chrome versions --- htdocs/compta/bank/ligne.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/bank/ligne.php b/htdocs/compta/bank/ligne.php index f1bb4eb9a62..d210e209b59 100644 --- a/htdocs/compta/bank/ligne.php +++ b/htdocs/compta/bank/ligne.php @@ -1,7 +1,7 @@ * Copyright (C) 2003 Xavier DUTOIT - * Copyright (C) 2004-2014 Laurent Destailleur + * Copyright (C) 2004-2015 Laurent Destailleur * Copyright (C) 2004 Christophe Combelles * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2015 Alexandre Spangaro @@ -587,7 +587,7 @@ if ($result) if ($user->rights->banque->consolidate) { print ''; } else From b5c9602da426b590429bb458780e180314a5c107 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 00:08:50 +0100 Subject: [PATCH 042/138] Fix Use new look for left-right arrow --- htdocs/compta/bank/releve.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/bank/releve.php b/htdocs/compta/bank/releve.php index 9620b00098b..cd8442114dc 100644 --- a/htdocs/compta/bank/releve.php +++ b/htdocs/compta/bank/releve.php @@ -282,9 +282,14 @@ else $found=true; } - $mesprevnext ="id\">".img_previous()."  "; - $mesprevnext.= $langs->trans("AccountStatement")." $num"; - $mesprevnext.="   id\">".img_next().""; + $mesprevnext=''; + $mesprevnext.=''; print load_fiche_titre($langs->trans("AccountStatement").' '.$num.', '.$langs->trans("BankAccount").' : '.$object->getNomUrl(0),$mesprevnext, 'title_bank.png'); print '
'; From 24dff1d8424dbbfcf0edee34ebc0ca9d261928ba Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 00:35:30 +0100 Subject: [PATCH 043/138] NEW Statistic graphs on products offer a filter on product type (product / service or both) --- htdocs/core/menus/init_menu_auguria.sql | 4 +- htdocs/product/class/product.class.php | 59 ++++++++++++++++--------- htdocs/product/stats/card.php | 35 +++++++++------ 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index df0b9e46488..a75be746ad1 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -98,12 +98,12 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->product->enabled', __HANDLER__, 'left', 2802__+MAX_llx_menu__, 'products', '', 2800__+MAX_llx_menu__, '/product/list.php?leftmenu=product&type=0', 'List', 1, 'products', '$user->rights->produit->lire', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->product->enabled', __HANDLER__, 'left', 2803__+MAX_llx_menu__, 'products', '', 2800__+MAX_llx_menu__, '/product/reassort.php?type=0', 'Stocks', 1, 'products', '$user->rights->produit->lire && $user->rights->stock->lire', '', 2, 4, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->productbatch->enabled', __HANDLER__, 'left', 2805__+MAX_llx_menu__, 'products', '', 2800__+MAX_llx_menu__, '/product/reassortlot.php?type=0', 'StocksByLotSerial', 1, 'products', '$user->rights->produit->lire && $user->rights->stock->lire', '', 2, 5, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->propal->enabled', __HANDLER__, 'left', 2804__+MAX_llx_menu__, 'products', '', 2800__+MAX_llx_menu__, '/product/popuprop.php?leftmenu=stats&type=0', 'Statistics', 1, 'main', '$user->rights->produit->lire', '', 2, 6, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->propal->enabled', __HANDLER__, 'left', 2804__+MAX_llx_menu__, 'products', '', 2800__+MAX_llx_menu__, '/product/stats/card.php?id=all&leftmenu=stats&type=0', 'Statistics', 1, 'main', '$user->rights->produit->lire', '', 2, 6, __ENTITY__); -- Product - Services insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->service->enabled', __HANDLER__, 'left', 2900__+MAX_llx_menu__, 'products', 'service', 3__+MAX_llx_menu__, '/product/index.php?leftmenu=service&type=1', 'Services', 0, 'products', '$user->rights->service->lire', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->service->enabled', __HANDLER__, 'left', 2901__+MAX_llx_menu__, 'products', '', 2900__+MAX_llx_menu__, '/product/card.php?leftmenu=service&action=create&type=1', 'NewService', 1, 'products', '$user->rights->service->creer', '', 2, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->service->enabled', __HANDLER__, 'left', 2902__+MAX_llx_menu__, 'products', '', 2900__+MAX_llx_menu__, '/product/list.php?leftmenu=service&type=1', 'List', 1, 'products', '$user->rights->service->lire', '', 2, 1, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->propal->enabled', __HANDLER__, 'left', 2903__+MAX_llx_menu__, 'products', '', 2900__+MAX_llx_menu__, '/product/popuprop.php?leftmenu=stats&type=1', 'Statistics', 1, 'main', '$user->rights->service->lire', '', 2, 5, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->propal->enabled', __HANDLER__, 'left', 2903__+MAX_llx_menu__, 'products', '', 2900__+MAX_llx_menu__, '/product/stats/card.php?id=all&leftmenu=stats&type=1', 'Statistics', 1, 'main', '$user->rights->service->lire', '', 2, 5, __ENTITY__); -- Product - Stocks insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3100__+MAX_llx_menu__, 'products', 'stock', 3__+MAX_llx_menu__, '/product/stock/index.php?leftmenu=stock', 'Stock', 0, 'stocks', '$user->rights->stock->lire', '', 2, 3, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3101__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/card.php?action=create', 'MenuNewWarehouse', 1, 'stocks', '$user->rights->stock->creer', '', 2, 0, __ENTITY__); diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 3b653f9d919..4594baab7a2 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2193,11 +2193,12 @@ class Product extends CommonObject /** * Return nb of units or customers invoices 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 - * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 + * @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 + * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 */ - function get_nb_vente($socid,$mode) + function get_nb_vente($socid, $mode, $filteronproducttype=-1) { global $conf; global $user; @@ -2205,9 +2206,11 @@ class Product extends CommonObject $sql = "SELECT sum(d.qty), date_format(f.datef, '%Y%m')"; if ($mode == 'bynumber') $sql.= ", count(DISTINCT f.rowid)"; $sql.= " FROM ".MAIN_DB_PREFIX."facturedet as d, ".MAIN_DB_PREFIX."facture as f, ".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 f.rowid = d.fk_facture"; if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; + if ($filteronproducttype >= 0) $sql.= " AND p.rowid = d.fk_product AND p.fk_product_type =".$filteronproducttype; $sql.= " AND f.fk_soc = s.rowid"; $sql.= " AND f.entity IN (".getEntity('facture', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND f.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; @@ -2222,11 +2225,12 @@ class Product extends CommonObject /** * Return nb of units or supplier invoices 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 - * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 + * @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 + * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 */ - function get_nb_achat($socid,$mode) + function get_nb_achat($socid, $mode, $filteronproducttype=-1) { global $conf; global $user; @@ -2234,9 +2238,11 @@ class Product extends CommonObject $sql = "SELECT sum(d.qty), date_format(f.datef, '%Y%m')"; if ($mode == 'bynumber') $sql.= ", count(DISTINCT f.rowid)"; $sql.= " FROM ".MAIN_DB_PREFIX."facture_fourn_det as d, ".MAIN_DB_PREFIX."facture_fourn as f, ".MAIN_DB_PREFIX."societe as s"; - if (!$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + 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 f.rowid = d.fk_facture_fourn"; if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; + if ($filteronproducttype >= 0) $sql.= " AND p.rowid = d.fk_product AND p.fk_product_type =".$filteronproducttype; $sql.= " AND f.fk_soc = s.rowid"; $sql.= " AND f.entity IN (".getEntity('facture_fourn', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND f.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; @@ -2251,11 +2257,12 @@ class Product extends CommonObject /** * Return nb of units or proposals 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 - * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 + * @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 + * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 */ - function get_nb_propal($socid,$mode) + function get_nb_propal($socid, $mode, $filteronproducttype=-1) { global $conf; global $user; @@ -2263,9 +2270,11 @@ class Product extends CommonObject $sql = "SELECT sum(d.qty), date_format(p.datep, '%Y%m')"; if ($mode == 'bynumber') $sql.= ", count(DISTINCT p.rowid)"; $sql.= " FROM ".MAIN_DB_PREFIX."propaldet as d, ".MAIN_DB_PREFIX."propal as p, ".MAIN_DB_PREFIX."societe as s"; + if ($filteronproducttype >= 0) $sql.=", ".MAIN_DB_PREFIX."product as prod"; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE p.rowid = d.fk_propal"; if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; + if ($filteronproducttype >= 0) $sql.= " AND prod.rowid = d.fk_product AND prod.fk_product_type =".$filteronproducttype; $sql.= " AND p.fk_soc = s.rowid"; $sql.= " AND p.entity IN (".getEntity('propal', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND p.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; @@ -2279,20 +2288,23 @@ class Product extends CommonObject /** * 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 - * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 + * @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 + * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 */ - function get_nb_order($socid,$mode) + function get_nb_order($socid, $mode, $filteronproducttype=-1) { global $conf, $user; $sql = "SELECT sum(d.qty), date_format(c.date_commande, '%Y%m')"; if ($mode == 'bynumber') $sql.= ", count(DISTINCT c.rowid)"; $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as d, ".MAIN_DB_PREFIX."commande as c, ".MAIN_DB_PREFIX."societe as s"; - if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + 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_commande"; if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; + 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('commande', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; @@ -2306,20 +2318,23 @@ class Product extends CommonObject /** * 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 - * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 + * @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 + * @return array <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11 */ - function get_nb_ordersupplier($socid,$mode) + function get_nb_ordersupplier($socid, $mode, $filteronproducttype=-1) { global $conf, $user; $sql = "SELECT sum(d.qty), date_format(c.date_commande, '%Y%m')"; if ($mode == 'bynumber') $sql.= ", count(DISTINCT c.rowid)"; $sql.= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as d, ".MAIN_DB_PREFIX."commande_fournisseur 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_commande"; if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; + 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('commande_fournisseur', 1).")"; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; diff --git a/htdocs/product/stats/card.php b/htdocs/product/stats/card.php index 33390e51a70..79d33b1d884 100644 --- a/htdocs/product/stats/card.php +++ b/htdocs/product/stats/card.php @@ -27,6 +27,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php'; @@ -204,19 +205,19 @@ if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all') $graphfiles=array( 'propal' =>array('modulepart'=>'productstats_proposals', - 'file' => $object->id.'/propal12m.png', + 'file' => $object->id.'/propal12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png', 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsProposals"):$langs->transnoentitiesnoconv("NumberOfProposals"))), 'orders' =>array('modulepart'=>'productstats_orders', - 'file' => $object->id.'/orders12m.png', + 'file' => $object->id.'/orders12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png', 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsCustomerOrders"):$langs->transnoentitiesnoconv("NumberOfCustomerOrders"))), 'invoices' =>array('modulepart'=>'productstats_invoices', - 'file' => $object->id.'/invoices12m.png', + 'file' => $object->id.'/invoices12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png', 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsCustomerInvoices"):$langs->transnoentitiesnoconv("NumberOfCustomerInvoices"))), 'orderssuppliers'=>array('modulepart'=>'productstats_orderssuppliers', - 'file' => $object->id.'/orderssuppliers12m.png', + 'file' => $object->id.'/orderssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png', 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierOrders"):$langs->transnoentitiesnoconv("NumberOfSupplierOrders"))), 'invoicessuppliers'=>array('modulepart'=>'productstats_invoicessuppliers', - 'file' => $object->id.'/invoicessuppliers12m.png', + 'file' => $object->id.'/invoicessuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png', 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierInvoices"):$langs->transnoentitiesnoconv("NumberOfSupplierInvoices"))), ); @@ -233,13 +234,21 @@ if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all') $graph_data = array(); - // TODO Test si deja existant et recent, on ne genere pas - if ($key == 'propal') $graph_data = $object->get_nb_propal($socid,$mode); - if ($key == 'orders') $graph_data = $object->get_nb_order($socid,$mode); - if ($key == 'invoices') $graph_data = $object->get_nb_vente($socid,$mode); - if ($key == 'invoicessuppliers') $graph_data = $object->get_nb_achat($socid,$mode); - if ($key == 'orderssuppliers') $graph_data = $object->get_nb_ordersupplier($socid,$mode); - + if (dol_is_file($dir . '/' . $graphfiles[$key]['file'])) + { + // TODO Load cachefile $graphfiles[$key]['file'] + } + else + { + if ($key == 'propal') $graph_data = $object->get_nb_propal($socid,$mode,((string) $type != '' ? $type : -1)); + if ($key == 'orders') $graph_data = $object->get_nb_order($socid,$mode,((string) $type != '' ? $type : -1)); + if ($key == 'invoices') $graph_data = $object->get_nb_vente($socid,$mode,((string) $type != '' ? $type : -1)); + if ($key == 'invoicessuppliers') $graph_data = $object->get_nb_achat($socid,$mode,((string) $type != '' ? $type : -1)); + if ($key == 'orderssuppliers') $graph_data = $object->get_nb_ordersupplier($socid,$mode,((string) $type != '' ? $type : -1)); + + // TODO Save cachefile $graphfiles[$key]['file'] + } + if (is_array($graph_data)) { $px->SetData($graph_data); @@ -312,7 +321,7 @@ if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all') { print '
'; } - print ''; + print ''; print ''; print '
'.$langs->trans('Date').''; $datepayment = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']); $datepayment= ($datepayment == '' ? (empty($conf->global->MAIN_AUTOFILL_DATE)?-1:'') : $datepayment); - $form->select_date($datepayment,'','','',0,"add_paiement",1,1); + $form->select_date($datepayment,'','','',0,"add_paiement",1,1,0,0,'','',$facture->date); print ''.$langs->trans('Comments').'
'.$langs->trans('Date').''; - $form->select_date($dateinvoice,'','','','',"addpaiement",1,1); + $form->select_date($dateinvoice,'','','','',"addpaiement",1,1,0,0,'','',$object->date); print ''.$langs->trans('Comments').'
'.$langs->trans('PaymentMode').''; - $form->select_types_paiements(empty($_POST['paiementid'])?'':$_POST['paiementid'],'paiementid'); + $form->select_types_paiements(empty($_POST['paiementid'])?$obj->fk_mode_reglement:$_POST['paiementid'],'paiementid'); print ''; print '
'.$langs->trans('Account').''; - $form->select_comptes(empty($accountid)?'':$accountid,'accountid',0,'',2); + $form->select_comptes(empty($accountid)?$obj->fk_account:$accountid,'accountid',0,'',2); print '
'; - print 'rappro?' checked':'')).'">'; + print 'rappro?' checked="checked"':'')).'">'; print ''.($mesg?''.$mesg.'':$langs->trans("ChartNotGenerated")).'id).'&action=recalcul&mode='.$mode.'">'.img_picto($langs->trans("ReCalculate"),'refresh').'id).((string) $type != ''?'&type='.$type:'').'&action=recalcul&mode='.$mode.'">'.img_picto($langs->trans("ReCalculate"),'refresh').'
'; From e350b759d3c420ad50f3d1d7ed29c66c9c68670e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 00:52:25 +0100 Subject: [PATCH 044/138] Increase number of last bank receits visible links --- htdocs/compta/bank/rappro.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/bank/rappro.php b/htdocs/compta/bank/rappro.php index 2bafa7e780e..a8791177954 100644 --- a/htdocs/compta/bank/rappro.php +++ b/htdocs/compta/bank/rappro.php @@ -186,7 +186,7 @@ if ($resql) print '
'; // Show last bank receipts - $nbmax=5; + $nbmax=15; // We accept to show last 15 receipts (so we can have more than one year) $liste=""; $sql = "SELECT DISTINCT num_releve FROM ".MAIN_DB_PREFIX."bank"; $sql.= " WHERE fk_account=".$acct->id." AND num_releve IS NOT NULL"; From fa8863d2eac449b2105419f610afae5c84ef9d66 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 01:38:03 +0100 Subject: [PATCH 045/138] Fix sql migration requests --- htdocs/install/mysql/migration/3.8.0-3.9.0.sql | 3 +-- htdocs/install/mysql/tables/llx_budget_lines.key.sql | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql index 0705512893e..a846eeff889 100755 --- a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql +++ b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql @@ -235,13 +235,12 @@ create table llx_budget_lines import_key integer )ENGINE=innodb; -ALTER TABLE llx_budget_lines ADD UNIQUE INDEX uk_budget_lines (fk_budget, fk_project); +ALTER TABLE llx_budget_lines ADD UNIQUE INDEX uk_budget_lines (fk_budget, fk_project_ids); -- Supprime orphelins pour permettre montee de la cle -- MYSQL V4 DELETE llx_budget_lines FROM llx_budget_lines LEFT JOIN llx_budget ON llx_budget.rowid = llx_budget_lines.fk_budget WHERE llx_budget_lines.rowid IS NULL; -- POSTGRESQL V8 DELETE FROM llx_budget_lines USING llx_budget WHERE llx_budget_lines.fk_budget NOT IN (SELECT llx_budget.rowid FROM llx_budget); -ALTER TABLE llx_budget_lines ADD INDEX idx_budget_lines (fk_project); ALTER TABLE llx_budget_lines ADD CONSTRAINT fk_budget_lines_budget FOREIGN KEY (fk_budget) REFERENCES llx_budget (rowid); diff --git a/htdocs/install/mysql/tables/llx_budget_lines.key.sql b/htdocs/install/mysql/tables/llx_budget_lines.key.sql index 9a9771570b1..b31e74b324d 100644 --- a/htdocs/install/mysql/tables/llx_budget_lines.key.sql +++ b/htdocs/install/mysql/tables/llx_budget_lines.key.sql @@ -17,11 +17,10 @@ -- =================================================================== -ALTER TABLE llx_budget_lines ADD UNIQUE INDEX uk_budget_lines (fk_budget, fk_project); +ALTER TABLE llx_budget_lines ADD UNIQUE INDEX uk_budget_lines (fk_budget, fk_project_ids); -- Supprime orphelins pour permettre montee de la cle -- MYSQL V4 DELETE llx_budget_lines FROM llx_budget_lines LEFT JOIN llx_budget ON llx_budget.rowid = llx_budget_lines.fk_budget WHERE llx_budget_lines.rowid IS NULL; -- POSTGRESQL V8 DELETE FROM llx_budget_lines USING llx_budget WHERE llx_budget_lines.fk_budget NOT IN (SELECT llx_budget.rowid FROM llx_budget); -ALTER TABLE llx_budget_lines ADD INDEX idx_budget_lines (fk_project); ALTER TABLE llx_budget_lines ADD CONSTRAINT fk_budget_lines_budget FOREIGN KEY (fk_budget) REFERENCES llx_budget (rowid); From 7a423c04d4e32deb5bf7d1437aa893649188b72f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 02:00:28 +0100 Subject: [PATCH 046/138] Fix The only default value is value we just entered --- htdocs/compta/bank/rappro.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/bank/rappro.php b/htdocs/compta/bank/rappro.php index a8791177954..332e7fffe60 100644 --- a/htdocs/compta/bank/rappro.php +++ b/htdocs/compta/bank/rappro.php @@ -226,7 +226,7 @@ if ($resql) print ''; print ''.$langs->trans("InputReceiptNumber").': '; - print ''; + print ''; // The only default value is value we just entered print '
'; if ($options) { From 333dd108747b65a8269e9fbb2087688f74c28ca1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 02:09:32 +0100 Subject: [PATCH 047/138] Add a way to lin on bank receipt tab directly --- htdocs/compta/bank/account.php | 27 +++++++++++----------- htdocs/compta/bank/class/account.class.php | 7 +++++- htdocs/compta/bank/releve.php | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/htdocs/compta/bank/account.php b/htdocs/compta/bank/account.php index e3bc2a3fc2c..b9c0d3821bc 100644 --- a/htdocs/compta/bank/account.php +++ b/htdocs/compta/bank/account.php @@ -378,19 +378,6 @@ if ($id > 0 || ! empty($ref)) { print '
'; - if ($object->type != 2 && $object->rappro) - { - // If not cash account and can be reconciliate - if ($user->rights->banque->consolidate) - { - print ''.$langs->trans("Conciliate").''; - } - else - { - print ''.$langs->trans("Conciliate").''; - } - } - if ($action != 'addline') { if (empty($conf->global->BANK_DISABLE_DIRECT_INPUT)) @@ -409,6 +396,20 @@ if ($id > 0 || ! empty($ref)) print ''.$langs->trans("AddBankRecord").''; } } + + if ($object->type != 2 && $object->rappro) + { + // If not cash account and can be reconciliate + if ($user->rights->banque->consolidate) + { + print ''.$langs->trans("Conciliate").''; + } + else + { + print ''.$langs->trans("Conciliate").''; + } + } + print '
'; } diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index e8978310ca3..65661b3cce8 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -998,7 +998,12 @@ class Account extends CommonObject $link = ''; + } + if ($withpicto) $result.=($link.img_object($label, 'account', 'class="classfortooltip"').$linkend.' '); $result.=$link.$this->label.$linkend; return $result; diff --git a/htdocs/compta/bank/releve.php b/htdocs/compta/bank/releve.php index cd8442114dc..88defbd8b04 100644 --- a/htdocs/compta/bank/releve.php +++ b/htdocs/compta/bank/releve.php @@ -290,7 +290,7 @@ else //$mesprevnext.='   '; $mesprevnext.=''; $mesprevnext.=''; - print load_fiche_titre($langs->trans("AccountStatement").' '.$num.', '.$langs->trans("BankAccount").' : '.$object->getNomUrl(0),$mesprevnext, 'title_bank.png'); + print load_fiche_titre($langs->trans("AccountStatement").' '.$num.', '.$langs->trans("BankAccount").' : '.$object->getNomUrl(0, 'receipts'), $mesprevnext, 'title_bank.png'); print '
'; print ""; From 1d2dab63a34a5eeefabb49b42324fa6ac019de96 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 02:32:22 +0100 Subject: [PATCH 048/138] More space --- htdocs/compta/bank/releve.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/compta/bank/releve.php b/htdocs/compta/bank/releve.php index 88defbd8b04..84c2edde0dd 100644 --- a/htdocs/compta/bank/releve.php +++ b/htdocs/compta/bank/releve.php @@ -157,6 +157,7 @@ if (empty($num)) } print ''; + print '

'; print_barre_liste('', $page, $_SERVER["PHP_SELF"], "&account=".$object->id, $sortfield, $sortorder,'',$numrows); From f0a3bca4c205b00d36336063b59ba389480494fe Mon Sep 17 00:00:00 2001 From: aspangaro Date: Sun, 8 Nov 2015 04:22:49 +0100 Subject: [PATCH 049/138] Fix: Accountancy compatibility with subtotal & jalon module --- htdocs/accountancy/customer/card.php | 12 ++++++++---- htdocs/accountancy/customer/list.php | 10 ++++++---- htdocs/accountancy/supplier/card.php | 7 ++++--- htdocs/accountancy/supplier/list.php | 11 ++++++----- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/htdocs/accountancy/customer/card.php b/htdocs/accountancy/customer/card.php index 9eb546ec89d..51190afdc98 100644 --- a/htdocs/accountancy/customer/card.php +++ b/htdocs/accountancy/customer/card.php @@ -1,7 +1,7 @@ - * Copyright (C) 2013-2014 Florian Henry - * Copyright (C) 2013-2014 Alexandre Spangaro + * Copyright (C) 2013-2015 Alexandre Spangaro * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ /** * \file htdocs/accountancy/customer/card.php - * \ingroup Accounting Expert + * \ingroup Accountancy * \brief Card customer ventilation */ @@ -84,7 +84,11 @@ if (! empty($id)) { $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accountingaccount as aa ON l.fk_code_ventilation = aa.rowid"; $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = l.fk_facture"; - $sql .= " WHERE f.fk_statut > 0 AND l.rowid = " . $id; + $sql .= " WHERE f.fk_statut > 0"; + $sql .= " AND l.rowid = " . $id; + if (! empty($conf->multicompany->enabled)) { + $sql .= " AND f.entity = '" . $conf->entity . "'"; + } if (! empty($conf->multicompany->enabled)) { $sql .= " AND f.entity = '" . $conf->entity . "'"; diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index 8ee5eb41eb5..dcf46fe4a44 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013-2014 Alexandre Spangaro + * Copyright (C) 2013-2015 Alexandre Spangaro * Copyright (C) 2014 Ari Elbaz (elarifr) * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2014 Juanjo Menent @@ -21,7 +21,7 @@ /** * \file htdocs/accountancy/customer/list.php - * \ingroup Accounting Expert + * \ingroup Accountancy * \brief Ventilation page from customers invoices */ @@ -121,7 +121,7 @@ if (! empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION)) { $offset = $limit * $page; -$sql = "SELECT f.facnumber, f.rowid as facid, l.fk_product, l.description, l.total_ht, l.rowid, l.fk_code_ventilation,"; +$sql = "SELECT f.facnumber, f.rowid as facid, l.fk_product, l.description, l.total_ht, l.rowid, l.fk_code_ventilation, l.product_type,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_sell as code_sell"; $sql .= " , aa.rowid as aarowid"; $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f"; @@ -129,7 +129,9 @@ $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "facturedet as l ON f.rowid = l.fk_fac $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accountingaccount as aa ON p.accountancy_code_sell = aa.account_number"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_system as accsys ON accsys.pcg_version = aa.fk_pcg_version"; -$sql .= " WHERE f.fk_statut > 0 AND fk_code_ventilation <= 0"; +$sql .= " WHERE f.fk_statut > 0"; +$sql. = " AND fk_code_ventilation <= 0"; +$sql. = " AND product_type <= 2"; $sql .= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR p.accountancy_code_sell IS NULL OR p.accountancy_code_sell ='')"; if (! empty($conf->multicompany->enabled)) { $sql .= " AND f.entity = '" . $conf->entity . "'"; diff --git a/htdocs/accountancy/supplier/card.php b/htdocs/accountancy/supplier/card.php index 1acd5829c45..8e5d2135965 100644 --- a/htdocs/accountancy/supplier/card.php +++ b/htdocs/accountancy/supplier/card.php @@ -1,7 +1,7 @@ * Copyright (C) 2005 Simon TOSSER - * Copyright (C) 2013-2014 Alexandre Spangaro + * Copyright (C) 2013-2015 Alexandre Spangaro * Copyright (C) 2013-2014 Olivier Geffroy * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2014 Juanjo Menent @@ -22,7 +22,7 @@ */ /** * \file htdocs/accountancy/supplier/card.php - * \ingroup Accounting Expert + * \ingroup Accountancy * \brief Card supplier ventilation */ @@ -85,7 +85,8 @@ if ($_GET["id"]) { $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accountingaccount as aa ON l.fk_code_ventilation = aa.rowid"; $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "facture_fourn as f ON f.rowid = l.fk_facture_fourn "; - $sql .= " WHERE f.fk_statut > 0 AND l.rowid = " . $id; + $sql .= " WHERE f.fk_statut > 0"; + $sql .= " AND l.rowid = " . $id; if (! empty($conf->multicompany->enabled)) { $sql .= " AND f.entity = '" . $conf->entity . "'"; } diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index 656afbd32cc..0ed1e1d6aa2 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013-2014 Alexandre Spangaro + * Copyright (C) 2013-2015 Alexandre Spangaro * Copyright (C) 2014 Ari Elbaz (elarifr) * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2014 Juanjo Menent s @@ -21,7 +21,7 @@ /** * \file htdocs/accountancy/supplier/list.php - * \ingroup Accounting Expert + * \ingroup Accountancy * \brief Ventilation page from suppliers invoices */ @@ -124,16 +124,17 @@ if (! empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION)) { $offset = $limit * $page; -$sql = "SELECT f.ref, f.rowid as facid, f.ref_supplier, l.fk_product, l.description, l.total_ht as price, l.rowid, l.fk_code_ventilation, "; +$sql = "SELECT f.ref, f.rowid as facid, f.ref_supplier, l.fk_product, l.description, l.total_ht as price, l.rowid, l.fk_code_ventilation, l.product_type,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_buy as code_buy"; $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f"; $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "facture_fourn_det as l ON f.rowid = l.fk_facture_fourn"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accountingaccount as aa ON p.accountancy_code_buy = aa.account_number"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_system as accsys ON accsys.pcg_version = aa.fk_pcg_version"; -$sql .= " WHERE f.fk_statut > 0 AND fk_code_ventilation <= 0"; +$sql .= " WHERE f.fk_statut > 0"; +$sql .= " AND fk_code_ventilation <= 0"; +$sql. = " AND product_type <= 2"; $sql .= " AND (accsys.rowid='".$conf->global->CHARTOFACCOUNTS."' OR p.accountancy_code_sell IS NULL OR p.accountancy_code_buy ='')"; - if (! empty($conf->multicompany->enabled)) { $sql .= " AND f.entity = '" . $conf->entity . "'"; } From 972c364c37f1011b454ae82866cc4d695edb780f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:12:28 +0100 Subject: [PATCH 050/138] FIX Add a protection to not make release if ChangeLog was not generated. Prepare package 3.8.2 --- ChangeLog | 56 ++++++++++++++++++++++++++++++++++++++ build/makepack-dolibarr.pl | 22 +++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/ChangeLog b/ChangeLog index b77f8a098a3..4cb0e1ef743 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,62 @@ Upgrading to any other version or any other database system is abolutely require make a Dolibarr upgrade. +***** ChangeLog for 3.8.2 compared to 3.8.1 ***** +FIX: 1/ update_extra() function must not be in "if(!empty(MAIN_DISABLE_CONTACTS_TAB)" test. 2/ Reindented code +FIX: #3240 +FIX: #3541 Bypass authentication when user was created using LDAP +FIX: #3605 deleting a shipping +FIX: #3661 Margin is not selected correctly when adding a product +FIX: #3689 Bug on workflow module +FIX: #3724 Bug: Blank page after cloning proposal if we changed client +FIX: #3726 Better support for PRODUCT_USE_OLD_PATH_FOR_PHOTO +FIX: #3726 Not showing images on product card +FIX: #3757 Can't set amount in a social contribution with some languages +FIX: #3786 Translation of select box. +FIX: #3841 creation of a task completed has not status set to finished by default +FIX: #3878 Storing and deleting files on emailing was done at wrong place +FIX: #3880 +FIX: #3882 +FIX: action not appear before an update because of a lack of line in action ressource +FIX: add tag myuser_job into ODT replacement +FIX: Avoid changing the state to a thirdparty who shouldn't be contacted anymore +FIX: bad calculation for stock value +FIX: Bad parameters +FIX: Bad picto for expense report +FIX: bad property so after creating an event from calendar, filter were lost. +FIX: bad stock valorisation +FIX: better fix to generate a PROV ref after clone +FIX: bug invoice classified in propale next update commonobject class in 3.8 +FIX: Can export a field into task time table with export project profile +FIX: change order date on clone (as everywhere else) +FIX: clone customer order create new order with validate ref and not with PROV +FIX: Contacts are not added to the list with the status "no contact" +FIX: Default thirdparty when cloning invoice was not set. +FIX: double db escape add too quote +FIX: event's data lost on user assign update +FIX: Filter in customer price per product of a thirdparty returned error +FIX: filters on supplier invoices list are not used, search_status instead +FIX: fix HTML into formconfirm box +FIX: IF autocomplete was set on thirdparty list, it was not possible to open list of extrafields. +FIX: If no end date is set on survey, we should be able to vote. +FIX: loss data also if update was cancel by error of ended state with no end date, try a generic patch +FIX: no need to remove file into mail form, the temp dir will be deleted after any sending +FIX: pmp calculation +FIX: Preview pages was not using correct style for ref +FIX: project was not retrieved on invoice creation form +FIX: Revert option WORKFLOW_PROPAL_CAN_CLASSIFIED_BILLED_WITHOUT_INVOICES into option WORKFLOW_PROPAL_NEED_INVOICE_TO_BE_CLASSIFIED_BILLED for better compatibility with old versions +FIX: Search status not saved into list +FIX: search_status not used in mergefusiontool +FIX: Show category selector if we have permission to view products or services +FIX: Show product image on getNomUrl() +FIX: skeleton class must use db->order rather than ORDER BY into fetchAll +FIX: Societe::set_parent() function needs societe object to be fetched to update parent +FIX: supplier rights for orderToInvoice +FIX: tag object_total_vat_x need x to be a string with unknown decimal lenght. Now use for x the real vat real with no more decimal (x = 20 or x = 8.5 or x = 5.99, ...) +FIX: The preview of PDF was never refreshed if PDF document was changed +FIX: The thumb of user into top menu was using the image in full size. This make a large download at each page call. We must use the mini thumbs. +FIX: Total in summary was not same than into detail on the referrer page. + ***** ChangeLog for 3.8.1 compared to 3.8.0 ***** FIX: #3521 postgresql migration error FIX: #3524 diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 99ec7b3543a..aafc21bf58a 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -351,6 +351,28 @@ if ($nboftargetok) { print "Go to directory $SOURCE\n"; $olddir=getcwd(); chdir("$SOURCE"); + + # Test that the ChangeLog is ok + $ret=`grep "ChangeLog for $MAJOR.$MINOR\.$BUILD" "$SOURCE/ChangeLog" 2>&1`; + if (! $ret) + { + print "Error: The ChangeLogFile was not updated. Run the following command first:\n"; + if (! $BUILD) + { + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log `git rev-list --boundary '.$MAJOR.'.'.$MINOR.'..origin/develop`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + } + else + { + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log '.$MAJOR.'.'.$MINOR.'.'.($BUILD-1).'.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + } + print "\n"; + exit; + } + else + { + print "ChangeLog for $MAJOR.$MINOR\.$BUILD was found into '$SOURCE/ChangeLog'\n"; + } + print 'Run git tag -a -m "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'" "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'"'."\n"; $ret=`git tag -a -m "$MAJOR.$MINOR.$BUILD" "$MAJOR.$MINOR.$BUILD" 2>&1`; if ($ret =~ /already exists/) From 6b98c50510009d35f6a025c07d3d4defa72d8bd3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:16:30 +0100 Subject: [PATCH 051/138] FIX Add a protection to not make release if ChangeLog was not generated. --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 4cb0e1ef743..ebdd392622d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ make a Dolibarr upgrade. ***** ChangeLog for 3.8.2 compared to 3.8.1 ***** +FIX: Add a protection to not make release if ChangeLog was not generated. FIX: 1/ update_extra() function must not be in "if(!empty(MAIN_DISABLE_CONTACTS_TAB)" test. 2/ Reindented code FIX: #3240 FIX: #3541 Bypass authentication when user was created using LDAP From 42ae4e10b3439cb879eac71a4845e790bf704bfa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:19:05 +0100 Subject: [PATCH 052/138] Abandon package APS. Was never used. --- build/makepack-dolibarr.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index aafc21bf58a..89e970c8b14 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -22,7 +22,8 @@ $PUBLISHSTABLE="eldy,dolibarr\@frs.sourceforge.net:/home/frs/project/dolibarr"; $PUBLISHBETARC="ldestailleur\@asso.dolibarr.org:/home/dolibarr/dolibarr.org/httpdocs/files"; -@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages +#@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages +@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","EXEDOLIWAMP","SNAPSHOT"); # Possible packages %REQUIREMENTPUBLISH=( "SF"=>"git ssh rsync", "ASSO"=>"git ssh rsync" From 98b887edaee094b6ebff2fa90fbd8f35d90b982f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:23:40 +0100 Subject: [PATCH 053/138] Update doc to generate ChangeLog --- build/makepack-dolibarr.pl | 2 +- build/makepack-howto.txt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 89e970c8b14..fbae52f9726 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -360,7 +360,7 @@ if ($nboftargetok) { print "Error: The ChangeLogFile was not updated. Run the following command first:\n"; if (! $BUILD) { - print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log `git rev-list --boundary '.$MAJOR.'.'.$MINOR.'..origin/develop`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log `git rev-list --boundary '.$MAJOR.'.'.$MINOR.'..origin/develop | grep ^- | cut -c2- | head -n`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; } else { diff --git a/build/makepack-howto.txt b/build/makepack-howto.txt index 953e207d28d..2bf516dfe88 100644 --- a/build/makepack-howto.txt +++ b/build/makepack-howto.txt @@ -9,8 +9,8 @@ beta version of Dolibarr, step by step. - Check all files are commited. - Update version/info in ChangeLog. -To generate a changelog of a major new version x.y.0, you can do "cd ~/git/dolibarr_x.y; git log `git merge-base x-1.y-1.0 origin/develop`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa" -To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dolibarr_x.y; git log `git merge-base x.y.z-1 origin/develop`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa" +To generate a changelog of a major new version x.y.0, you can do "cd ~/git/dolibarr_x.y; git log `git rev-list --boundary x.y..origin/develop | grep ^- | cut -c2- | head -n`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa" +To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dolibarr_x.y; git log x.y.z-1.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa" - Update version number with x.y.z-w in htdocs/filefunc.inc.php - Commit all changes. @@ -31,8 +31,8 @@ complete release of Dolibarr, step by step. - Check all files are commited. - Update version/info in ChangeLog. -To generate a changelog of a major new version x.y.0, you can do "cd ~/git/dolibarr_x.y; git log `git merge-base x-1.y-1.0 origin/develop`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa" -To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dolibarr_x.y; git log `git merge-base x.y.z-1 origin/develop`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa" +To generate a changelog of a major new version x.y.0, you can do "cd ~/git/dolibarr_x.y; git log `git rev-list --boundary x.y..origin/develop | grep ^- | cut -c2- | head -n`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa" +To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dolibarr_x.y; git log x.y.z-1.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa" - Update version number with x.y.z in htdocs/filefunc.inc.php - Commit all changes. From 7a0206adceb3760f867658bff3a0f78bbcdfb3db Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 14:37:50 +0100 Subject: [PATCH 054/138] FIX Missing to set context into workflow actions, so triggers can't know we are creating an invoice from order or an order from a proposal. --- htdocs/commande/class/commande.class.php | 4 ++-- .../interface_20_modWorkflow_WorkflowManager.class.php | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index f6f332d462b..5d2907041b2 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1043,7 +1043,7 @@ class Commande extends CommonOrder $this->ref_client = $object->ref_client; $this->note_private = $object->note_private; $this->note_public = $object->note_public; - + $this->origin = $object->element; $this->origin_id = $object->id; @@ -1133,7 +1133,7 @@ class Commande extends CommonOrder { global $mysoc, $conf, $langs; - dol_syslog(get_class($this)."::addline commandeid=$this->id, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, fk_product=$fk_product, remise_percent=$remise_percent, info_bits=$info_bits, fk_remise_except=$fk_remise_except, price_base_type=$price_base_type, pu_ttc=$pu_ttc, date_start=$date_start, date_end=$date_end, type=$type", LOG_DEBUG); + dol_syslog(get_class($this)."::addline commandeid=$this->id, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, fk_product=$fk_product, remise_percent=$remise_percent, info_bits=$info_bits, fk_remise_except=$fk_remise_except, price_base_type=$price_base_type, pu_ttc=$pu_ttc, date_start=$date_start, date_end=$date_end, type=$type special_code=$special_code", LOG_DEBUG); include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index d144f365533..4d3afeb8d92 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -61,6 +61,10 @@ class InterfaceWorkflowManager extends DolibarrTriggers include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; $newobject = new Commande($this->db); + $newobject->context['createfrompropal'] = 'createfrompropal'; + $newobject->context['origin'] = $object->element; + $newobject->context['origin_id'] = $object->id; + $ret=$newobject->createFromProposal($object); if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; } return $ret; @@ -76,6 +80,10 @@ class InterfaceWorkflowManager extends DolibarrTriggers include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $newobject = new Facture($this->db); + $newobject->context['createfromorder'] = 'createfromorder'; + $newobject->context['origin'] = $object->element; + $newobject->context['origin_id'] = $object->id; + $ret=$newobject->createFromOrder($object); if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; } return $ret; From c639e820621cfe675cea540f443fc007f3972009 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:16:30 +0100 Subject: [PATCH 055/138] FIX Add a protection to not make release if ChangeLog was not generated. Conflicts: ChangeLog --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 4d3b8252107..d5926b573ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ You may also experience troubles with Mysql 5.5.41 with error "Lost connection" Upgrading to any other version or database system is abolutely required BEFORE trying to make a Dolibarr upgrade. + ***** ChangeLog for 3.7.2 compared to 3.7.1 ***** FIX [ bug #2855 ] Wrong translation key in localtax report page FIX [ bug #1852 ] JS error when editing a customer order line From 04243510f3996d62957d64ea5ac82b101454d6d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sun, 8 Nov 2015 14:54:29 +0100 Subject: [PATCH 056/138] Little changes --- htdocs/product/class/product.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index be23fa6f06c..64068652ca9 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -4089,11 +4089,15 @@ class Product extends CommonObject return 1; } + /** + * Returns the rights used for this class + * @return stdClass + */ public function getRights() { global $user; - if ($this->isproduct()) { + if ($this->isProduct()) { return $user->rights->produit; } else { return $user->rights->service; From 9b8bb114cd1850ceaf198ed840c40beeb1c0ba6e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:12:28 +0100 Subject: [PATCH 057/138] FIX Add a protection to not make release if ChangeLog was not generated. Prepare package 3.7.2 Conflicts: ChangeLog --- ChangeLog | 102 ++++++++++++++++++++++++++++++------- build/makepack-dolibarr.pl | 22 ++++++++ 2 files changed, 107 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5926b573ce..1248b7b1988 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,24 +10,92 @@ make a Dolibarr upgrade. ***** ChangeLog for 3.7.2 compared to 3.7.1 ***** -FIX [ bug #2855 ] Wrong translation key in localtax report page -FIX [ bug #1852 ] JS error when editing a customer order line -FIX [ bug #2900 ] Courtesy title is not stored in create thirdparty form -FIX [ bug #3055 ] Product image thumbnails were not deleted after deleting the image -FIX [ bug 1634 ] Error deleting a project when it had many linked objects -FIX [ bug 1925 ] "Link to order" option in supplier invoices is not working properly -FIX [ bug #3198 ] Trigger LINECONTRACT_INSERT passes Contrat as $object instead of ContratLigne -FIX: Not showing delivery date on rouget pdf +FIX: #2957 : missing $langs object for trigger +FIX: #2983 Load gravatar avatar images securely over HTTPS +FIX: #3009: Better filtering to prevent SQL injection +FIX: #3091 TotalHT amount in supplier order is bold unlike the rest of Dolibarr +FIX: #3262 Webservice getProductsForCategory() +FIX: #3318 +FIX: [ #3460 ] Selected bank account was not saved when an error happened when trying to create a customer invoice +FIX: #3530 +FIX: #3630 - Wrong balance report when module salaries and donation disabled +FIX: #3679 Error when deleting a Localtax2 special payment +FIX: #3707 Thirdparty bank account page table has a glitch +FIX: #3724 Bug: Blank page after cloning proposal with changed client +FIX: #3836 Unable to upload a document to an invoice under some circunstances +FIX: #3841 creation of a task completed has not status set to finished by default +FIX: Add a protection to not make release if ChangeLog was not generated. +FIX: adjusted test for affecting supplier reference +FIX: Admin fiche inter page do not take good action +FIX: Avoid warning strict mode when hosting server do not have php5_curl installed +FIX: bad calculation for stock value +FIX: Bad condition into invoice export request making reporting too many rows. +FIX: bad stock valorisation +FIX: Bad visualization of suppliers name on Incomes-Expenses mode +FIX: Better management error into the color conversion functions +FIX: [ bug 1634 ] Error deleting a project when it had many linked objects +FIX: [ bug 1925 ] "Link to order" option in supplier invoices is not working properly +FIX: [ bug #2893 ] Dolibarr error when viewing an invoice after changing invoice mask +FIX: [ bug #3211 ] Error about sold to pay (Montant encours) +FIX: [ bug #3321 ] Users with certain permissions were shown a "forbidden access" page even if they had the rights +FIX: [ bug #3358 ] Tasks box does not work with PostgreSQL +FIX: [ bug #3383 ] Company name is overlapped with company direction in PDF models +FIX: [ bug #3426 ] Unable to create an invoice from a contract with extrafields +FIX: [ bug #3431 ] Invoice bank account is not respected +FIX: [ bug #3432 ] Spaces should be removed from IBAN when formatting it +FIX: Can create Proposal on close thridparty #3526 +FIX: change order date on clone (as everywhere else) +FIX: Close #2835 Customer prices of a product shows incorrect history order +FIX: Close #2837 Product list table column header does not match column body +FIX: Close bug #2855 Wrong translation key in localtax report page +FIX: Close bug #2861 Undefined variable $res when migrating from 3.6.2 to 3.7.0 +FIX: Close bug #2891 Category hooks do not work +FIX: Close bug #2900 Courtesy title is not stored in create thirdparty form +FIX: Close bug #2976: "Report" tab is the current tab but it is not marked as selected by the UI +FIX: contact country had wrong display if the country dont have translate +FIX: Display country name instead of country id (display country id makes no sense on vcard files) +FIX: display error on extrafields on ficheinter +FIX: double db escape add too quote +FIX: Email selector contact must not include inactive contact +FIX: End log must use same level then start log. +FIX: error in SQL due to a previous fix +FIX: event's data lost on user assign update +FIX: Export of tags for contact and member +FIX: facturestat bad sql when customer view is limited +FIX: if multicompany enabled, call to undifend method _setCookie instead of setCookie +FIX: If supplier invoice block linked element is display after other block total HT amount is not reset to 0 and sum other block (like customer orders values) +FIX: keep filter by category or by not enough stock if we switch page +FIX: Line break display as a block +FIX: load propal langs for availability traduction +FIX: loss data also if update was cancel by error of ended state with no end date, try a generic patch +FIX: Mass Mailing activity don't display all status +FIX: Missing to set context into workflow actions, so triggers can't know we are creating an invoice from order or an order from a proposal. +FIX: multientity warehouse management +FIX: New adherent from, always redirect on entity +FIX: No check warehouse is provided if module stock is not enabled. +FIX: no need to remove file into mail form, the temp dir will be deleted after any sending +FIX: no projet_task_time id from trigger TASK_TIMESPENT_CREATE FIX: Not showing task extrafields when creating from left menu -FIX [ bug #3288 ] Tasks box is not properly drawn -FIX [ bug #3211 ] Outstading bill amount of a client showed wrong amounts -FIX [ bug #3321 ] Users with certain permissions were shown a "forbidden access" page even if they had the rights -FIX [ bug #3426 ] Unable to create an invoice from a contract with extrafields -FIX [ bug #3431 ] Invoice bank account is not respected -FIX [ bug #3432 ] Spaces should be removed from IBAN when formatting it -FIX [ bug #3358 ] Tasks box does not work with PostgreSQL -FIX [ bug #3383 ] Company name is overlapped with company direction in PDF models -FIX [ bug #3460 ] Bank account is not saved when creating a customer invoice and facing an error message +FIX: only active customer should be return into new invoice creation select list +FIX: Payed invoices are showed as canceled FIX: Bad date filter on customer order +FIX: WAP calculation +FIX: Save of filters into export profiles failed. +FIX: supplier rights for orderToInvoice +FIX: Syntax error in Debian Apache configuration +FIX: The hours of date filter aren't correct +FIX: tool export handle the type "select" extrafields and return the value instead of id +FIX: total amount in tpl linked object are not reset +FIX: translate Jabberid on contact page with edit view +FIX: translation for 1 word do not work if product/service module are disabled because the translation search in products.lang +FIX: update2.php test res befre assign it +FIX: When delete actioncomm also delete actioncomm_resources +FIX: when fetch_optionnal_by_label in Extrafields with $this->db cannot work because this->db is never instanciated +FIX: when mailing is deleted, the targets list was kept in database +FIX: when multicompany was enabled, this function didn't check just on the good entity (problem when both company use same mask) +FIX: When we add an user on event in create mode, we lose linked object +FIX: When we automatically creta an order from a proposal with workflow module, if some extrafields of propal don't exist in order object, insertExtraFields() function tries to insert extrafields in unexistant column of commande_extrafields table. +FIX: When we clone a propal, if it has a project which is not assigned to a third, it was not on new propal because fk_project was always set to empty string if new propal is for another third. +FIX: XSS security using the onerror and missing escapement on type of member page. NEW: Created new ContratLigne::insert function diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 18e7092fc1b..d37c6b891aa 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -344,6 +344,28 @@ if ($nboftargetok) { print "Go to directory $SOURCE\n"; $olddir=getcwd(); chdir("$SOURCE"); + + # Test that the ChangeLog is ok + $ret=`grep "ChangeLog for $MAJOR.$MINOR\.$BUILD" "$SOURCE/ChangeLog" 2>&1`; + if (! $ret) + { + print "Error: The ChangeLogFile was not updated. Run the following command first:\n"; + if (! $BUILD) + { + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log `git rev-list --boundary '.$MAJOR.'.'.$MINOR.'..origin/develop`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + } + else + { + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log '.$MAJOR.'.'.$MINOR.'.'.($BUILD-1).'.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + } + print "\n"; + exit; + } + else + { + print "ChangeLog for $MAJOR.$MINOR\.$BUILD was found into '$SOURCE/ChangeLog'\n"; + } + print 'Run git tag -a -m "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'" "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'"'."\n"; $ret=`git tag -a -m "$MAJOR.$MINOR.$BUILD" "$MAJOR.$MINOR.$BUILD" 2>&1`; if ($ret =~ /already exists/) From 04aba8ce96807bf7856d263379fc911227e7660f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:19:05 +0100 Subject: [PATCH 058/138] Abandon package APS. Was never used. --- build/makepack-dolibarr.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index d37c6b891aa..a47fb76d35c 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -22,7 +22,8 @@ $PUBLISHSTABLE="eldy,dolibarr\@frs.sourceforge.net:/home/frs/project/dolibarr"; $PUBLISHBETARC="ldestailleur\@asso.dolibarr.org:/home/dolibarr/dolibarr.org/httpdocs/files"; -@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages +#@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages +@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","EXEDOLIWAMP","SNAPSHOT"); # Possible packages %REQUIREMENTPUBLISH=( "SF"=>"git ssh rsync", "ASSO"=>"git ssh rsync" From d4aeb8b3bcea0e212de82f2ade1070f56a262088 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:19:05 +0100 Subject: [PATCH 059/138] Abandon package APS. Was never used. --- build/makepack-dolibarr.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 9db6f3a4da3..c2359241ad0 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -22,7 +22,8 @@ $PUBLISHSTABLE="eldy,dolibarr\@frs.sourceforge.net:/home/frs/project/dolibarr"; $PUBLISHBETARC="ldestailleur\@asso.dolibarr.org:/home/dolibarr/dolibarr.org/httpdocs/files"; -@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages +#@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages +@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","EXEDOLIWAMP","SNAPSHOT"); # Possible packages %REQUIREMENTPUBLISH=( "SF"=>"git ssh rsync", "ASSO"=>"git ssh rsync" From 722a133b314807bd08b9a0d59c0614f6b0599d7f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 12:12:28 +0100 Subject: [PATCH 060/138] FIX Add a protection to not make release if ChangeLog was not generated. Prepare package 3.6.5 Conflicts: ChangeLog Conflicts: ChangeLog --- ChangeLog | 38 ++++++++++++++++++++++++++++++++++++-- build/makepack-dolibarr.pl | 22 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index a59cf9b7006..bd64723725a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,9 +2,43 @@ English Dolibarr ChangeLog -------------------------------------------------------------- + ***** ChangeLog for 3.6.5 compared to 3.6.4 ***** -- Fix: [ bug #1776 ] Undefined $deliverycompany variable in pdf_build_address -- Fix: [ bug #1794 ] Error when cloning Proposal gives error in a malformed page +FIX: #2957 : missing $langs object for trigger +FIX: #2983 Load gravatar avatar images securely over HTTPS +FIX: #3009: Better filtering to prevent SQL injection +FIX: #3841 creation of a task completed has not status set to finished by default +FIX: #3890 Expected transactions bank account page, shows negative numbers +FIX: #3928 Creating a Customer order and a Customer invoice from a project, does not inherit payment conditions and method of payment of customer card +FIX: bad calculation for stock value +FIX: bad stock valo +FIX: bad stock valorisation +FIX: [ bug #2893 ] Dolibarr error when viewing an invoice after changing invoice mask +FIX: button create payment hide if tax amount is less than 1 +FIX: change object statut on close shipping and remove erratic db commit +FIX: change order date on clone (as everywhere else) +FIX: Close #2835 Customer prices of a product shows incorrect history order +FIX: Close #2837 Product list table column header does not match column body +FIX: Close bug #2861 Undefined variable $res when migrating from 3.6.2 to 3.7.0 +FIX: Close bug #2891 Category hooks do not work +FIX: Close bug #2976: "Report" tab is the current tab but it is not marked as selected by the UI +FIX: contact country had wrong display if the country dont have translate +FIX: double db escape add too quote +FIX: End log must use same level then start log. +FIX: error in SQL due to a previous fix +FIX: event for restricted user was restricted if company null +FIX: facturestat bad sql when customer view is limited +FIX: If supplier invoice block linked element is display after other block total HT amount is not reset to 0 and sum other block (like customer orders values) +FIX: keep filter by category or by not enough stock if we switch page +FIX: no need to remove file into mail form, the temp dir will be deleted after any sending +FIX: no projet_task_time id from trigger TASK_TIMESPENT_CREATE +FIX: pmp +FIX: send mail, copy sendto don't read the list of contact +FIX: The hours of date filter aren't correct +FIX: tool export handle the type "select" extrafields and return the value instead of id +FIX: top links menu have target attribute with wrong value +FIX: total amount in tpl linked object are not reset +FIX: when multicompany was enabled, this function didn't check just on the good entity (problem when both company use same mask) ***** ChangeLog for 3.6.4 compared to 3.6.3 ***** - Fix: [ bug #2893 ] Dolibarr error when viewing an invoice after changing invoice mask diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index c2359241ad0..603fd0f2e7a 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -345,6 +345,28 @@ if ($nboftargetok) { print "Go to directory $SOURCE\n"; $olddir=getcwd(); chdir("$SOURCE"); + + # Test that the ChangeLog is ok + $ret=`grep "ChangeLog for $MAJOR.$MINOR\.$BUILD" "$SOURCE/ChangeLog" 2>&1`; + if (! $ret) + { + print "Error: The ChangeLogFile was not updated. Run the following command first:\n"; + if (! $BUILD) + { + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log `git rev-list --boundary '.$MAJOR.'.'.$MINOR.'..origin/develop`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + } + else + { + print 'cd ~/git/dolibarr_'.$MAJOR.'.'.$MINOR.'; git log '.$MAJOR.'.'.$MINOR.'.'.($BUILD-1).'.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e \'^FIX\|NEW\' | sort -u | sed \'s/FIXED:/FIX:/g\' | sed \'s/FIXED :/FIX:/g\' | sed \'s/FIX :/FIX:/g\' | sed \'s/FIX /FIX: /g\' | sed \'s/NEW :/NEW:/g\' | sed \'s/NEW /NEW: /g\' > /tmp/aaa'; + } + print "\n"; + exit; + } + else + { + print "ChangeLog for $MAJOR.$MINOR\.$BUILD was found into '$SOURCE/ChangeLog'\n"; + } + print 'Run git tag -a -m "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'" "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'"'."\n"; $ret=`git tag -a -m "$MAJOR.$MINOR.$BUILD" "$MAJOR.$MINOR.$BUILD" 2>&1`; if ($ret =~ /already exists/) From 7f0d81d255a58bdc0c7316b2eea21696c3c3cec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sun, 8 Nov 2015 15:12:31 +0100 Subject: [PATCH 061/138] Missing changes of PR #3927 --- htdocs/product/price.php | 159 +++++++++++++++++++++++---------------- 1 file changed, 95 insertions(+), 64 deletions(-) diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 497f676ae8c..114f6a8df53 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -431,13 +431,34 @@ $titre = $langs->trans("CardProduct" . $object->type); $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product'); dol_fiche_head($head, 'price', $titre, 0, $picto); -dol_banner_tab($object, 'ref', '', ($user->societe_id?0:1), 'ref'); +print ''; +// Ref +print ''; +print ''; +print ''; -print '
'; +// Label +print '
'; -print '
'; -print '
' . $langs->trans("Ref") . ''; +print $form->showrefnav($object, 'ref', '', 1, 'ref'); +print '
' . $langs->trans("Label") . '' . $object->label . '
'; +$isphoto = $object->is_photo_available($conf->product->multidir_output [$object->entity]); + +$nblignes = 5; +if ($isphoto) { + // Photo + print ''; +} + +print ''; + +// Status (to sell) +print ''; // MultiPrix if (! empty($conf->global->PRODUIT_MULTIPRICES)) @@ -450,7 +471,7 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) $soc->fetch($socid); // Selling price - print ''; + print '' . $langs->trans("SellingPrice") . ''; print ''; + print ''; } else { // TVA - print ''; + print ''; } print ''; @@ -613,7 +634,7 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) else { // TVA - print ''; + print ''; // Price print '
'; + print $object->show_photos($conf->product->multidir_output [$object->entity], 1, 1, 0, 0, 0, 80); + print '
' . $langs->trans("Status") . ' (' . $langs->trans("Sell") . ')'; +print $object->getLibStatut(2, 0); +print '
' . $langs->trans("SellingPrice") . '
'; if ($object->multiprices_base_type[$soc->price_level] == 'TTC') { print price($object->multiprices_ttc[$soc->price_level]); @@ -491,12 +512,12 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // using this option is a bug. kept for backward compatibility { // We show only vat for level 1 - print '
' . $langs->trans("VATRate") . '' . vatrate($object->multiprices_tva_tx [1], true) . '
' . $langs->trans("VATRate") . '' . vatrate($object->multiprices_tva_tx [1], true) . '
' . $langs->trans("VATRate") . '' . vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true) . '
' . $langs->trans("VATRate") . '' . vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true) . '
'.$langs->trans("PriceLevel").''.$langs->trans("SellingPrice").''.$langs->trans("MinPrice").'
' . $langs->trans("VATRate") . '' . vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true) . '
' . $langs->trans("VATRate") . '' . vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true) . '
' . $langs->trans("SellingPrice") . ''; @@ -711,10 +732,6 @@ else print "
\n"; -print ''; -print '
'; - - dol_fiche_end(); @@ -793,7 +810,7 @@ if ($action == 'edit_vat' && ($user->rights->produit->creer || $user->rights->se print '

'; } -if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights->service->creer)) +if ($action == 'edit_price' && $object->getRights()->creer) { print load_fiche_titre($langs->trans("NewPrice"), ''); @@ -809,7 +826,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> print ''; // VAT - print ''; @@ -817,7 +834,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> print ''; - print ''; print ''; @@ -825,7 +842,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> // Only show price mode and expression selector if module is enabled if (! empty($conf->dynamicprices->enabled)) { // Price mode selector - print ''; + // This code hides the numeric price input if is not selected, loads the editor page if editor button is pressed - print ''; + + rights->produit->creer || $user->rights-> print 'global->PRODUCT_MINIMUM_RECOMMENDED_PRICE)) { + print ' colspan="2"'; + } + print '>'; if ($object->price_base_type == 'TTC') { - print ''; + print ''; } - print ''; + print ''; print '
' . $langs->trans("VATRate") . ''; + print '
' . $langs->trans("VATRate") . ''; print $form->load_tva("tva_tx", $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr); print '
'; print $langs->trans('PriceBase'); print ''; + print ''; print $form->selectPriceBaseType($object->price_base_type, "price_base_type"); print '
'.$langs->trans("PriceMode").''; + print '
'.$langs->trans("PriceMode").''; $price_expression = new PriceExpression($db); $price_expression_list = array(0 => $langs->trans("PriceNumeric")); //Put the numeric mode as first option foreach ($price_expression->list_price_expression() as $entry) { @@ -835,17 +852,18 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> print $form->selectarray('eid', $price_expression_list, $price_expression_preselection); print ' 
'.$langs->trans("PriceExpressionEditor").'
'; print '
'; $text = $langs->trans('SellingPrice'); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); - print ''; + print ''; if ($object->price_base_type == 'TTC') { print ''; } else { @@ -874,16 +893,21 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> print '
'; $text = $langs->trans('MinPrice'); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); + print ''; + print ''; } else { - print ''; + print ''; } if ( !empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE)) { - print ''.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier,0,'',1,-1,-1,'auto')).' '.img_warning().''.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier,0,'',1,-1,-1,'auto')).' '.img_warning().'
'; @@ -927,65 +951,72 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights-> id . '" method="POST">'; + print ''; + print ''; + print ''; - for($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i ++) - { + if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($conf->global->PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL)) { + print $langs->trans('UseMultipriceRules'). ' price_autogen ? 'checked' : '').'>

'; + } - if ($i > 1) print '
'; - elseif (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($conf->global->PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL)) { - print $langs->trans('UseMultipriceRules'). ' price_autogen ? 'checked' : '').'>

'; - } - print ''; - print ''; - print ''; - if (empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) - { - print ''; - } - - print ''; + print '
'; + print ' + '; + if (!empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { + print ''; + } + print ' + '; + if (!empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE)) { + print ''; + } + print ''; + + for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i ++) { + $var = !$var; + + print ''; + print ''; // VAT - if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // This option is kept for backward compatibility but has no sense - { - print ''; + print ''; } - + // Selling price - print ''; + print ''; // Min price - print ''; } - print ''; - - print '
'.$langs->trans("PriceLevel").''.$langs->trans("VATRate").''.$langs->trans("SellingPrice").''.$langs->trans("MinPrice").'
'; + print $form->textwithpicto($langs->trans('SellingPrice') . ' ' . $i, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); + print '
' . $langs->trans("VATRate") . ''; + if (empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { + print ''; + } else { + // This option is kept for backward compatibility but has no sense + print ''; print $form->load_tva("tva_tx[" . $i.']', $object->multiprices_tva_tx[$i], $mysoc, '', $object->id); - print '
'; - $text = $langs->trans('SellingPrice') . ' ' . $i; - print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); - print ''; + print ''; if ($object->multiprices_base_type [$i] == 'TTC') { print ''; } else { print ''; } print ' '.$form->selectPriceBaseType($object->multiprices_base_type [$i], "multiprices_base_type[" . $i."]"); - print '
'; - $text = $langs->trans('MinPrice') . ' ' . $i; - print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1); + print ''; if ($object->multiprices_base_type [$i] == 'TTC') { - print ''; + print ''; } else { - print ''; + print ''; } if ( !empty($conf->global->PRODUCT_MINIMUM_RECOMMENDED_PRICE)) { print ''.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier,0,'',1,-1,-1,'auto')).' '.img_warning().'
'; + print '

'; print ''; print '   '; print '
'; From 350345eccaa70ac932f7ddaa94e6f217f01bef6e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 15:18:26 +0100 Subject: [PATCH 062/138] Prepare 3.6.5 --- build/debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/debian/changelog b/build/debian/changelog index 17fdd65230e..5d34808d3a6 100644 --- a/build/debian/changelog +++ b/build/debian/changelog @@ -1,4 +1,4 @@ -dolibarr (3.6.4-3) UNRELEASED; urgency=low +dolibarr (3.6.5-3) UNRELEASED; urgency=low [ Laurent Destailleur (eldy) ] * New upstream release. From bd56396394bb235e9b8303cd9d197ba8838ece3f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 8 Nov 2015 15:38:57 +0100 Subject: [PATCH 063/138] Fix migration error --- htdocs/core/class/html.form.class.php | 1 + htdocs/install/mysql/migration/3.8.0-3.9.0.sql | 2 +- htdocs/install/mysql/tables/llx_categorie_project.key.sql | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index d64b9971a27..393560b4640 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4533,6 +4533,7 @@ class Form $out=''; + // TODO Use an internal dolibarr component instead of select2 $outdelayed=' ' ); - -} - -/** - * The skin to load for all created instances, it may be the name of the skin - * folder inside the editor installation path, or the name and the path separated - * by a comma. - * - * **Note:** This is a global configuration that applies to all instances. - * - * CKEDITOR.skinName = 'moono'; - * - * CKEDITOR.skinName = 'myskin,/customstuff/myskin/'; - * - * @cfg {String} [skinName='moono'] - * @member CKEDITOR - */ -CKEDITOR.skinName = 'moono'; diff --git a/htdocs/includes/ckeditor/ckeditor/_source/config.js b/htdocs/includes/ckeditor/ckeditor/_source/config.js deleted file mode 100644 index e674a1054ac..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/config.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.html or http://ckeditor.com/license - */ - -CKEDITOR.editorConfig = function( config ) { - - // %REMOVE_START% - // The configuration options below are needed when running CKEditor from source files. - config.plugins = 'dialogui,dialog,about,a11yhelp,dialogadvtab,basicstyles,bidi,blockquote,clipboard,button,panelbutton,panel,floatpanel,colorbutton,colordialog,templates,menu,contextmenu,div,resize,toolbar,elementspath,enterkey,entities,popup,filebrowser,find,fakeobjects,flash,floatingspace,listblock,richcombo,font,forms,format,horizontalrule,htmlwriter,iframe,wysiwygarea,image,indent,indentblock,indentlist,smiley,justify,menubutton,language,link,list,liststyle,magicline,maximize,newpage,pagebreak,pastetext,pastefromword,preview,print,removeformat,save,selectall,showblocks,showborders,sourcearea,specialchar,scayt,stylescombo,tab,table,tabletools,undo,wsc'; - config.skin = 'moonocolor'; - // %REMOVE_END% - - // Define changes to default configuration here. For example: - // config.language = 'fr'; - // config.uiColor = '#AADC6E'; -}; diff --git a/htdocs/includes/ckeditor/ckeditor/_source/contents.css b/htdocs/includes/ckeditor/ckeditor/_source/contents.css deleted file mode 100644 index ac3e9af2b96..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/contents.css +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -body -{ - /* Font */ - font-family: sans-serif, Arial, Verdana, "Trebuchet MS"; - font-size: 12px; - - /* Text color */ - color: #333; - - /* Remove the background color to make it transparent */ - background-color: #fff; - - margin: 20px; -} - -.cke_editable -{ - font-size: 13px; - line-height: 1.6; -} - -blockquote -{ - font-style: italic; - font-family: Georgia, Times, "Times New Roman", serif; - padding: 2px 0; - border-style: solid; - border-color: #ccc; - border-width: 0; -} - -.cke_contents_ltr blockquote -{ - padding-left: 20px; - padding-right: 8px; - border-left-width: 5px; -} - -.cke_contents_rtl blockquote -{ - padding-left: 8px; - padding-right: 20px; - border-right-width: 5px; -} - -a -{ - color: #0782C1; -} - -ol,ul,dl -{ - /* IE7: reset rtl list margin. (#7334) */ - *margin-right: 0px; - /* preserved spaces for list items with text direction other than the list. (#6249,#8049)*/ - padding: 0 40px; -} - -h1,h2,h3,h4,h5,h6 -{ - font-weight: normal; - line-height: 1.2; -} - -hr -{ - border: 0px; - border-top: 1px solid #ccc; -} - -img.right -{ - border: 1px solid #ccc; - float: right; - margin-left: 15px; - padding: 5px; -} - -img.left -{ - border: 1px solid #ccc; - float: left; - margin-right: 15px; - padding: 5px; -} - -pre -{ - white-space: pre-wrap; /* CSS 2.1 */ - word-wrap: break-word; /* IE7 */ -} - -.marker -{ - background-color: Yellow; -} - -span[lang] -{ - font-style: italic; -} - -figure -{ - text-align: center; - border: solid 1px #ccc; - border-radius: 2px; - background: rgba(0,0,0,0.05); - padding: 10px; - margin: 10px 20px; - display: block; /* For IE8 */ -} - -figure figcaption -{ - text-align: center; - display: block; /* For IE8 */ -} \ No newline at end of file diff --git a/htdocs/includes/ckeditor/ckeditor/_source/core/_bootstrap.js b/htdocs/includes/ckeditor/ckeditor/_source/core/_bootstrap.js deleted file mode 100644 index d6802af54be..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/core/_bootstrap.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -/** - * @fileOverview API initialization code. - */ - -( function() { - // Disable HC detection in WebKit. (#5429) - if ( CKEDITOR.env.webkit ) - CKEDITOR.env.hc = false; - else { - // Check whether high contrast is active by creating a colored border. - var hcDetect = CKEDITOR.dom.element.createFromHtml( '
', CKEDITOR.document ); - - hcDetect.appendTo( CKEDITOR.document.getHead() ); - - // Update CKEDITOR.env. - // Catch exception needed sometimes for FF. (#4230) - try { - var top = hcDetect.getComputedStyle( 'border-top-color' ), - right = hcDetect.getComputedStyle( 'border-right-color' ); - - // We need to check if getComputedStyle returned any value, because on FF - // it returnes empty string if CKEditor is loaded in hidden iframe. (#11121) - CKEDITOR.env.hc = !!( top && top == right ); - } catch ( e ) { - CKEDITOR.env.hc = false; - } - - hcDetect.remove(); - } - - if ( CKEDITOR.env.hc ) - CKEDITOR.env.cssClass += ' cke_hc'; - - // Initially hide UI spaces when relevant skins are loading, later restored by skin css. - CKEDITOR.document.appendStyleText( '.cke{visibility:hidden;}' ); - - // Mark the editor as fully loaded. - CKEDITOR.status = 'loaded'; - CKEDITOR.fireOnce( 'loaded' ); - - // Process all instances created by the "basic" implementation. - var pending = CKEDITOR._.pending; - if ( pending ) { - delete CKEDITOR._.pending; - - for ( var i = 0; i < pending.length; i++ ) { - CKEDITOR.editor.prototype.constructor.apply( pending[ i ][ 0 ], pending[ i ][ 1 ] ); - CKEDITOR.add( pending[ i ][ 0 ] ); - } - } -} )(); - -/** - * Indicates that CKEditor is running on a High Contrast environment. - * - * if ( CKEDITOR.env.hc ) - * alert( 'You\'re running on High Contrast mode. The editor interface will get adapted to provide you a better experience.' ); - * - * @property {Boolean} hc - * @member CKEDITOR.env - */ - -/** - * Fired when a CKEDITOR core object is fully loaded and ready for interaction. - * - * @event loaded - * @member CKEDITOR - */ diff --git a/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor.js b/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor.js deleted file mode 100644 index aaa37d35212..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor.js +++ /dev/null @@ -1,204 +0,0 @@ -/** - * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -/** - * @fileOverview Contains the third and last part of the {@link CKEDITOR} object - * definition. - */ - -/** @class CKEDITOR */ - -// Remove the CKEDITOR.loadFullCore reference defined on ckeditor_basic. -delete CKEDITOR.loadFullCore; - -/** - * Stores references to all editor instances created. The name of the properties - * in this object correspond to instance names, and their values contain the - * {@link CKEDITOR.editor} object representing them. - * - * alert( CKEDITOR.instances.editor1.name ); // 'editor1' - * - * @property {Object} - */ -CKEDITOR.instances = {}; - -/** - * The document of the window storing the CKEDITOR object. - * - * alert( CKEDITOR.document.getBody().getName() ); // 'body' - * - * @property {CKEDITOR.dom.document} - */ -CKEDITOR.document = new CKEDITOR.dom.document( document ); - -/** - * Adds an editor instance to the global {@link CKEDITOR} object. This function - * is available for internal use mainly. - * - * @param {CKEDITOR.editor} editor The editor instance to be added. - */ -CKEDITOR.add = function( editor ) { - CKEDITOR.instances[ editor.name ] = editor; - - editor.on( 'focus', function() { - if ( CKEDITOR.currentInstance != editor ) { - CKEDITOR.currentInstance = editor; - CKEDITOR.fire( 'currentInstance' ); - } - } ); - - editor.on( 'blur', function() { - if ( CKEDITOR.currentInstance == editor ) { - CKEDITOR.currentInstance = null; - CKEDITOR.fire( 'currentInstance' ); - } - } ); - - CKEDITOR.fire( 'instance', null, editor ); -}; - -/** - * Removes an editor instance from the global {@link CKEDITOR} object. This function - * is available for internal use only. External code must use {@link CKEDITOR.editor#method-destroy}. - * - * @private - * @param {CKEDITOR.editor} editor The editor instance to be removed. - */ -CKEDITOR.remove = function( editor ) { - delete CKEDITOR.instances[ editor.name ]; -}; - -( function() { - var tpls = {}; - - /** - * Adds a named {@link CKEDITOR.template} instance to be reused among all editors. - * This will return the existing one if a template with same name is already - * defined. Additionally, it fires the "template" event to allow template source customization. - * - * @param {String} name The name which identifies a UI template. - * @param {String} source The source string for constructing this template. - * @returns {CKEDITOR.template} The created template instance. - */ - CKEDITOR.addTemplate = function( name, source ) { - var tpl = tpls[ name ]; - if ( tpl ) - return tpl; - - // Make it possible to customize the template through event. - var params = { name: name, source: source }; - CKEDITOR.fire( 'template', params ); - - return ( tpls[ name ] = new CKEDITOR.template( params.source ) ); - }; - - /** - * Retrieves a defined template created with {@link CKEDITOR#addTemplate}. - * - * @param {String} name The template name. - */ - CKEDITOR.getTemplate = function( name ) { - return tpls[ name ]; - }; -} )(); - -( function() { - var styles = []; - - /** - * Adds CSS rules to be appended to the editor document. - * This method is mostly used by plugins to add custom styles to the editor - * document. For basic content styling the `contents.css` file should be - * used instead. - * - * **Note:** This function should be called before the creation of editor instances. - * - * // Add styles for all headings inside editable contents. - * CKEDITOR.addCss( '.cke_editable h1,.cke_editable h2,.cke_editable h3 { border-bottom: 1px dotted red }' ); - * - * @param {String} css The style rules to be appended. - * @see CKEDITOR.config#contentsCss - */ - CKEDITOR.addCss = function( css ) { - styles.push( css ); - }; - - /** - * Returns a string will all CSS rules passed to the {@link CKEDITOR#addCss} method. - * - * @returns {String} A string containing CSS rules. - */ - CKEDITOR.getCss = function() { - return styles.join( '\n' ); - }; -} )(); - -// Perform global clean up to free as much memory as possible -// when there are no instances left -CKEDITOR.on( 'instanceDestroyed', function() { - if ( CKEDITOR.tools.isEmpty( this.instances ) ) - CKEDITOR.fire( 'reset' ); -} ); - -// Load the bootstrap script. -CKEDITOR.loader.load( '_bootstrap' ); // %REMOVE_LINE% - -// Tri-state constants. -/** - * Used to indicate the ON or ACTIVE state. - * - * @readonly - * @property {Number} [=1] - */ -CKEDITOR.TRISTATE_ON = 1; - -/** - * Used to indicate the OFF or INACTIVE state. - * - * @readonly - * @property {Number} [=2] - */ -CKEDITOR.TRISTATE_OFF = 2; - -/** - * Used to indicate the DISABLED state. - * - * @readonly - * @property {Number} [=0] - */ -CKEDITOR.TRISTATE_DISABLED = 0; - -/** - * The editor which is currently active (has user focus). - * - * function showCurrentEditorName() { - * if ( CKEDITOR.currentInstance ) - * alert( CKEDITOR.currentInstance.name ); - * else - * alert( 'Please focus an editor first.' ); - * } - * - * @property {CKEDITOR.editor} currentInstance - * @see CKEDITOR#event-currentInstance - */ - -/** - * Fired when the CKEDITOR.currentInstance object reference changes. This may - * happen when setting the focus on different editor instances in the page. - * - * var editor; // A variable to store a reference to the current editor. - * CKEDITOR.on( 'currentInstance', function() { - * editor = CKEDITOR.currentInstance; - * } ); - * - * @event currentInstance - */ - -/** - * Fired when the last instance has been destroyed. This event is used to perform - * global memory cleanup. - * - * @event reset - */ diff --git a/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor_base.js b/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor_base.js deleted file mode 100644 index 069793172a9..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor_base.js +++ /dev/null @@ -1,315 +0,0 @@ -/** - * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -/** - * @fileOverview Contains the first and essential part of the {@link CKEDITOR} - * object definition. - */ - -// #### Compressed Code -// Must be updated on changes in the script as well as updated in the ckeditor.js file. - -// window.CKEDITOR||(window.CKEDITOR=function(){var b={timestamp:"",version:"%VERSION%",revision:"%REV%",rnd:Math.floor(900*Math.random())+100,_:{pending:[]},status:"unloaded",basePath:function(){var a=window.CKEDITOR_BASEPATH||"";if(!a)for(var b=document.getElementsByTagName("script"),c=0;c tag. - var path = window.CKEDITOR_BASEPATH || ''; - - if ( !path ) { - var scripts = document.getElementsByTagName( 'script' ); - - for ( var i = 0; i < scripts.length; i++ ) { - var match = scripts[ i ].src.match( /(^|.*[\\\/])ckeditor(?:_basic)?(?:_source)?.js(?:\?.*)?$/i ); - - if ( match ) { - path = match[ 1 ]; - break; - } - } - } - - // In IE (only) the script.src string is the raw value entered in the - // HTML source. Other browsers return the full resolved URL instead. - if ( path.indexOf( ':/' ) == -1 && path.slice( 0, 2 ) != '//' ) { - // Absolute path. - if ( path.indexOf( '/' ) === 0 ) - path = location.href.match( /^.*?:\/\/[^\/]*/ )[ 0 ] + path; - // Relative path. - else - path = location.href.match( /^[^\?]*\/(?:)/ )[ 0 ] + path; - } - - if ( !path ) - throw 'The CKEditor installation path could not be automatically detected. Please set the global variable "CKEDITOR_BASEPATH" before creating editor instances.'; - - return path; - } )(), - - /** - * Gets the full URL for CKEditor resources. By default, URLs - * returned by this function contain a querystring parameter ("t") - * set to the {@link CKEDITOR#timestamp} value. - * - * It is possible to provide a custom implementation of this - * function by setting a global variable named `CKEDITOR_GETURL`. - * This global variable must be set **before** the editor script - * loading. If the custom implementation returns nothing (`==null`), the - * default implementation is used. - * - * // e.g. 'http://www.example.com/ckeditor/skins/default/editor.css?t=87dm' - * alert( CKEDITOR.getUrl( 'skins/default/editor.css' ) ); - * - * // e.g. 'http://www.example.com/skins/default/editor.css?t=87dm' - * alert( CKEDITOR.getUrl( '/skins/default/editor.css' ) ); - * - * // e.g. 'http://www.somesite.com/skins/default/editor.css?t=87dm' - * alert( CKEDITOR.getUrl( 'http://www.somesite.com/skins/default/editor.css' ) ); - * - * @param {String} resource The resource whose full URL we want to get. - * It may be a full, absolute, or relative URL. - * @returns {String} The full URL. - */ - getUrl: function( resource ) { - // If this is not a full or absolute path. - if ( resource.indexOf( ':/' ) == -1 && resource.indexOf( '/' ) !== 0 ) - resource = this.basePath + resource; - - // Add the timestamp, except for directories. - if ( this.timestamp && resource.charAt( resource.length - 1 ) != '/' && !( /[&?]t=/ ).test( resource ) ) - resource += ( resource.indexOf( '?' ) >= 0 ? '&' : '?' ) + 't=' + this.timestamp; - - return resource; - }, - - /** - * Specify a function to execute when the DOM is fully loaded. - * - * If called after the DOM has been initialized, the function passed in will - * be executed immediately. - * - * @method - * @todo - */ - domReady: ( function() { - // Based on the original jQuery code. - - var callbacks = []; - - function onReady() { - try { - // Cleanup functions for the document ready method - if ( document.addEventListener ) { - document.removeEventListener( 'DOMContentLoaded', onReady, false ); - executeCallbacks(); - } - // Make sure body exists, at least, in case IE gets a little overzealous. - else if ( document.attachEvent && document.readyState === 'complete' ) { - document.detachEvent( 'onreadystatechange', onReady ); - executeCallbacks(); - } - } catch ( er ) {} - } - - function executeCallbacks() { - var i; - while ( ( i = callbacks.shift() ) ) - i(); - } - - return function( fn ) { - callbacks.push( fn ); - - // Catch cases where this is called after the - // browser event has already occurred. - if ( document.readyState === 'complete' ) - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( onReady, 1 ); - - // Run below once on demand only. - if ( callbacks.length != 1 ) - return; - - // For IE>8, Firefox, Opera and Webkit. - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( 'DOMContentLoaded', onReady, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( 'load', onReady, false ); - - } - // If old IE event model is used - else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent( 'onreadystatechange', onReady ); - - // A fallback to window.onload, that will always work - window.attachEvent( 'onload', onReady ); - - // If IE and not a frame - // continually check to see if the document is ready - // use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - var toplevel = false; - - try { - toplevel = !window.frameElement; - } catch ( e ) {} - - if ( document.documentElement.doScroll && toplevel ) { - function scrollCheck() { - try { - document.documentElement.doScroll( 'left' ); - } catch ( e ) { - setTimeout( scrollCheck, 1 ); - return; - } - onReady(); - } - scrollCheck(); - } - } - }; - - } )() - }; - - // Make it possible to override the "url" function with a custom - // implementation pointing to a global named CKEDITOR_GETURL. - var newGetUrl = window.CKEDITOR_GETURL; - if ( newGetUrl ) { - var originalGetUrl = CKEDITOR.getUrl; - CKEDITOR.getUrl = function( resource ) { - return newGetUrl.call( CKEDITOR, resource ) || originalGetUrl.call( CKEDITOR, resource ); - }; - } - - return CKEDITOR; - } )(); -} - -/** - * Function called upon loading a custom configuration file that can - * modify the editor instance configuration ({@link CKEDITOR.editor#config}). - * It is usually defined inside the custom configuration files that can - * include developer defined settings. - * - * // This is supposed to be placed in the config.js file. - * CKEDITOR.editorConfig = function( config ) { - * // Define changes to default configuration here. For example: - * config.language = 'fr'; - * config.uiColor = '#AADC6E'; - * }; - * - * @method editorConfig - * @param {CKEDITOR.config} config A configuration object containing the - * settings defined for a {@link CKEDITOR.editor} instance up to this - * function call. Note that not all settings may still be available. See - * [Configuration Loading Order](http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Setting_Configurations#Configuration_Loading_Order) - * for details. - */ - -// PACKAGER_RENAME( CKEDITOR ) diff --git a/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor_basic.js b/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor_basic.js deleted file mode 100644 index efdb2456e6e..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/core/ckeditor_basic.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -/** - * @fileOverview Contains the second part of the {@link CKEDITOR} object - * definition, which defines the basic editor features to be available in - * the root ckeditor_basic.js file. - */ - -if ( CKEDITOR.status == 'unloaded' ) { - ( function() { - CKEDITOR.event.implementOn( CKEDITOR ); - - /** - * Forces the full CKEditor core code, in the case only the basic code has been - * loaded (`ckeditor_basic.js`). This method self-destroys (becomes undefined) in - * the first call or as soon as the full code is available. - * - * // Check if the full core code has been loaded and load it. - * if ( CKEDITOR.loadFullCore ) - * CKEDITOR.loadFullCore(); - * - * @member CKEDITOR - */ - CKEDITOR.loadFullCore = function() { - // If the basic code is not ready, just mark it to be loaded. - if ( CKEDITOR.status != 'basic_ready' ) { - CKEDITOR.loadFullCore._load = 1; - return; - } - - // Destroy this function. - delete CKEDITOR.loadFullCore; - - // Append the script to the head. - var script = document.createElement( 'script' ); - script.type = 'text/javascript'; - script.src = CKEDITOR.basePath + 'ckeditor.js'; - script.src = CKEDITOR.basePath + 'ckeditor_source.js'; // %REMOVE_LINE% - - document.getElementsByTagName( 'head' )[ 0 ].appendChild( script ); - }; - - /** - * The time to wait (in seconds) to load the full editor code after the - * page load, if the "ckeditor_basic" file is used. If set to zero, the - * editor is loaded on demand, as soon as an instance is created. - * - * This value must be set on the page before the page load completion. - * - * // Loads the full source after five seconds. - * CKEDITOR.loadFullCoreTimeout = 5; - * - * @property - * @member CKEDITOR - */ - CKEDITOR.loadFullCoreTimeout = 0; - - // Documented at ckeditor.js. - CKEDITOR.add = function( editor ) { - // For now, just put the editor in the pending list. It will be - // processed as soon as the full code gets loaded. - var pending = this._.pending || ( this._.pending = [] ); - pending.push( editor ); - }; - - ( function() { - var onload = function() { - var loadFullCore = CKEDITOR.loadFullCore, - loadFullCoreTimeout = CKEDITOR.loadFullCoreTimeout; - - if ( !loadFullCore ) - return; - - CKEDITOR.status = 'basic_ready'; - - if ( loadFullCore && loadFullCore._load ) - loadFullCore(); - else if ( loadFullCoreTimeout ) { - setTimeout( function() { - if ( CKEDITOR.loadFullCore ) - CKEDITOR.loadFullCore(); - }, loadFullCoreTimeout * 1000 ); - } - }; - - CKEDITOR.domReady( onload ); - } )(); - - CKEDITOR.status = 'basic_loaded'; - } )(); -} diff --git a/htdocs/includes/ckeditor/ckeditor/_source/core/command.js b/htdocs/includes/ckeditor/ckeditor/_source/core/command.js deleted file mode 100644 index e9c98863743..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/core/command.js +++ /dev/null @@ -1,271 +0,0 @@ -/** - * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -/** - * Represents a command that can be executed on an editor instance. - * - * var command = new CKEDITOR.command( editor, { - * exec: function( editor ) { - * alert( editor.document.getBody().getHtml() ); - * } - * } ); - * - * @class - * @mixins CKEDITOR.event - * @constructor Creates a command class instance. - * @param {CKEDITOR.editor} editor The editor instance this command will be - * related to. - * @param {CKEDITOR.commandDefinition} commandDefinition The command - * definition. - */ -CKEDITOR.command = function( editor, commandDefinition ) { - /** - * Lists UI items that are associated to this command. This list can be - * used to interact with the UI on command execution (by the execution code - * itself, for example). - * - * alert( 'Number of UI items associated to this command: ' + command.uiItems.length ); - */ - this.uiItems = []; - - /** - * Executes the command. - * - * command.exec(); // The command gets executed. - * - * @param {Object} [data] Any data to pass to the command. Depends on the - * command implementation and requirements. - * @returns {Boolean} A boolean indicating that the command has been successfully executed. - */ - this.exec = function( data ) { - if ( this.state == CKEDITOR.TRISTATE_DISABLED || !this.checkAllowed() ) - return false; - - if ( this.editorFocus ) // Give editor focus if necessary (#4355). - editor.focus(); - - if ( this.fire( 'exec' ) === false ) - return true; - - return ( commandDefinition.exec.call( this, editor, data ) !== false ); - }; - - /** - * Explicitly update the status of the command, by firing the {@link CKEDITOR.command#event-refresh} event, - * as well as invoke the {@link CKEDITOR.commandDefinition#refresh} method if defined, this method - * is to allow different parts of the editor code to contribute in command status resolution. - * - * @param {CKEDITOR.editor} editor The editor instance. - * @param {CKEDITOR.dom.elementPath} path - */ - this.refresh = function( editor, path ) { - // Do nothing is we're on read-only and this command doesn't support it. - // We don't need to disabled the command explicitely here, because this - // is already done by the "readOnly" event listener. - if ( !this.readOnly && editor.readOnly ) - return true; - - // Disable commands that are not allowed in the current selection path context. - if ( this.context && !path.isContextFor( this.context ) ) { - this.disable(); - return true; - } - - // Disable commands that are not allowed by the active filter. - if ( !this.checkAllowed( true ) ) { - this.disable(); - return true; - } - - // Make the "enabled" state a default for commands enabled from start. - if ( !this.startDisabled ) - this.enable(); - - // Disable commands which shouldn't be enabled in this mode. - if ( this.modes && !this.modes[ editor.mode ] ) - this.disable(); - - if ( this.fire( 'refresh', { editor: editor, path: path } ) === false ) - return true; - - return ( commandDefinition.refresh && commandDefinition.refresh.apply( this, arguments ) !== false ); - }; - - var allowed; - - /** - * Checks whether this command is allowed by the active allowed - * content filter ({@link CKEDITOR.editor#activeFilter}). This means - * that if command implements {@link CKEDITOR.feature} interface it will be tested - * by the {@link CKEDITOR.filter#checkFeature} method. - * - * @since 4.1 - * @param {Boolean} [noCache] Skip cache for example due to active filter change. Since CKEditor 4.2. - * @returns {Boolean} Whether this command is allowed. - */ - this.checkAllowed = function( noCache ) { - if ( !noCache && typeof allowed == 'boolean' ) - return allowed; - - return allowed = editor.activeFilter.checkFeature( this ); - }; - - CKEDITOR.tools.extend( this, commandDefinition, { - /** - * The editor modes within which the command can be executed. The - * execution will have no action if the current mode is not listed - * in this property. - * - * // Enable the command in both WYSIWYG and Source modes. - * command.modes = { wysiwyg:1,source:1 }; - * - * // Enable the command in Source mode only. - * command.modes = { source:1 }; - * - * @see CKEDITOR.editor#mode - */ - modes: { wysiwyg: 1 }, - - /** - * Indicates that the editor will get the focus before executing - * the command. - * - * // Do not force the editor to have focus when executing the command. - * command.editorFocus = false; - * - * @property {Boolean} [=true] - */ - editorFocus: 1, - - /** - * Indicates that this command is sensible to the selection context. - * If `true`, the {@link CKEDITOR.command#method-refresh} method will be - * called for this command on the {@link CKEDITOR.editor#event-selectionChange} event. - * - * @property {Boolean} [=false] - */ - contextSensitive: !!commandDefinition.context, - - /** - * Indicates the editor state. Possible values are: - * - * * {@link CKEDITOR#TRISTATE_DISABLED}: the command is - * disabled. It's execution will have no effect. Same as {@link #disable}. - * * {@link CKEDITOR#TRISTATE_ON}: the command is enabled - * and currently active in the editor (for context sensitive commands, for example). - * * {@link CKEDITOR#TRISTATE_OFF}: the command is enabled - * and currently inactive in the editor (for context sensitive commands, for example). - * - * Do not set this property directly, using the {@link #setState} method instead. - * - * if ( command.state == CKEDITOR.TRISTATE_DISABLED ) - * alert( 'This command is disabled' ); - * - * @property {Number} [=CKEDITOR.TRISTATE_DISABLED] - */ - state: CKEDITOR.TRISTATE_DISABLED - } ); - - // Call the CKEDITOR.event constructor to initialize this instance. - CKEDITOR.event.call( this ); -}; - -CKEDITOR.command.prototype = { - /** - * Enables the command for execution. The command state (see - * {@link CKEDITOR.command#property-state}) available before disabling it is restored. - * - * command.enable(); - * command.exec(); // Execute the command. - */ - enable: function() { - if ( this.state == CKEDITOR.TRISTATE_DISABLED && this.checkAllowed() ) - this.setState( ( !this.preserveState || ( typeof this.previousState == 'undefined' ) ) ? CKEDITOR.TRISTATE_OFF : this.previousState ); - }, - - /** - * Disables the command for execution. The command state (see - * {@link CKEDITOR.command#property-state}) will be set to {@link CKEDITOR#TRISTATE_DISABLED}. - * - * command.disable(); - * command.exec(); // "false" - Nothing happens. - */ - disable: function() { - this.setState( CKEDITOR.TRISTATE_DISABLED ); - }, - - /** - * Sets the command state. - * - * command.setState( CKEDITOR.TRISTATE_ON ); - * command.exec(); // Execute the command. - * command.setState( CKEDITOR.TRISTATE_DISABLED ); - * command.exec(); // 'false' - Nothing happens. - * command.setState( CKEDITOR.TRISTATE_OFF ); - * command.exec(); // Execute the command. - * - * @param {Number} newState The new state. See {@link #property-state}. - * @returns {Boolean} Returns `true` if the command state changed. - */ - setState: function( newState ) { - // Do nothing if there is no state change. - if ( this.state == newState ) - return false; - - if ( newState != CKEDITOR.TRISTATE_DISABLED && !this.checkAllowed() ) - return false; - - this.previousState = this.state; - - // Set the new state. - this.state = newState; - - // Fire the "state" event, so other parts of the code can react to the - // change. - this.fire( 'state' ); - - return true; - }, - - /** - * Toggles the on/off (active/inactive) state of the command. This is - * mainly used internally by context sensitive commands. - * - * command.toggleState(); - */ - toggleState: function() { - if ( this.state == CKEDITOR.TRISTATE_OFF ) - this.setState( CKEDITOR.TRISTATE_ON ); - else if ( this.state == CKEDITOR.TRISTATE_ON ) - this.setState( CKEDITOR.TRISTATE_OFF ); - } -}; - -CKEDITOR.event.implementOn( CKEDITOR.command.prototype ); - -/** - * Indicates the previous command state. - * - * alert( command.previousState ); - * - * @property {Number} previousState - * @see #state - */ - -/** - * Fired when the command state changes. - * - * command.on( 'state', function() { - * // Alerts the new state. - * alert( this.state ); - * } ); - * - * @event state - */ - - /** - * @event refresh - * @todo - */ diff --git a/htdocs/includes/ckeditor/ckeditor/_source/core/commanddefinition.js b/htdocs/includes/ckeditor/ckeditor/_source/core/commanddefinition.js deleted file mode 100644 index 18609bc0526..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/core/commanddefinition.js +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -/** - * @fileOverview Defines the "virtual" {@link CKEDITOR.commandDefinition} class, - * which contains the defintion of a command. This file is for - * documentation purposes only. - */ - -/** - * Virtual class that illustrates the features of command objects to be - * passed to the {@link CKEDITOR.editor#addCommand} function. - * - * @class CKEDITOR.commandDefinition - * @abstract - */ - -/** - * The function to be fired when the commend is executed. - * - * editorInstance.addCommand( 'sample', { - * exec: function( editor ) { - * alert( 'Executing a command for the editor name "' + editor.name + '"!' ); - * } - * } ); - * - * @method exec - * @param {CKEDITOR.editor} editor The editor within which run the command. - * @param {Object} [data] Additional data to be used to execute the command. - * @returns {Boolean} Whether the command has been successfully executed. - * Defaults to `true`, if nothing is returned. - */ - -/** - * Whether the command need to be hooked into the redo/undo system. - * - * editorInstance.addCommand( 'alertName', { - * exec: function( editor ) { - * alert( editor.name ); - * }, - * canUndo: false // No support for undo/redo. - * } ); - * - * @property {Boolean} [canUndo=true] - */ - -/** - * Whether the command is asynchronous, which means that the - * {@link CKEDITOR.editor#event-afterCommandExec} event will be fired by the - * command itself manually, and that the return value of this command is not to - * be returned by the {@link #exec} function. - * - * editorInstance.addCommand( 'loadOptions', { - * exec: function( editor ) { - * // Asynchronous operation below. - * CKEDITOR.ajax.loadXml( 'data.xml', function() { - * editor.fire( 'afterCommandExec' ); - * } ); - * }, - * async: true // The command need some time to complete after exec function returns. - * } ); - * - * @property {Boolean} [async=false] - */ - -/** - * Whether the command should give focus to the editor before execution. - * - * editorInstance.addCommand( 'maximize', { - * exec: function( editor ) { - * // ... - * }, - * editorFocus: false // The command doesn't require focusing the editing document. - * } ); - * - * @property {Boolean} [editorFocus=true] - * @see CKEDITOR.command#editorFocus - */ - - -/** - * Whether the command state should be set to {@link CKEDITOR#TRISTATE_DISABLED} on startup. - * - * editorInstance.addCommand( 'unlink', { - * exec: function( editor ) { - * // ... - * }, - * startDisabled: true // Command is unavailable until selection is inside a link. - * } ); - * - * @property {Boolean} [startDisabled=false] - */ - -/** - * Indicates that this command is sensible to the selection context. - * If `true`, the {@link CKEDITOR.command#method-refresh} method will be - * called for this command on selection changes, with a single parameter - * representing the current elements path. - * - * @property {Boolean} [contextSensitive=true] - */ - -/** - * Defined by command definition a function to determinate the command state, it will be invoked - * when editor has it's `states` or `selection` changed. - * - * **Note:** The function provided must be calling {@link CKEDITOR.command#setState} in all circumstance, - * if it is intended to update the command state. - * - * @method refresh - * @param {CKEDITOR.editor} editor - * @param {CKEDITOR.dom.elementPath} path - */ - -/** - * Sets the element name used to reflect the command state on selection changes. - * If the selection is in a place where the element is not allowed, the command - * will be disabled. - * Setting this property overrides {@link #contextSensitive} to `true`. - * - * @property {Boolean} [context=true] - */ - -/** - * The editor modes within which the command can be executed. The execution - * will have no action if the current mode is not listed in this property. - * - * editorInstance.addCommand( 'link', { - * exec: function( editor ) { - * // ... - * }, - * modes: { wysiwyg:1 } // Command is available in wysiwyg mode only. - * } ); - * - * @property {Object} [modes={ wysiwyg:1 }] - * @see CKEDITOR.command#modes - */ diff --git a/htdocs/includes/ckeditor/ckeditor/_source/core/config.js b/htdocs/includes/ckeditor/ckeditor/_source/core/config.js deleted file mode 100644 index dbdcaf1df08..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/core/config.js +++ /dev/null @@ -1,383 +0,0 @@ -/** - * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -/** - * @fileOverview Defines the {@link CKEDITOR.config} object that stores the - * default configuration settings. - */ - -/** - * Used in conjunction with {@link CKEDITOR.config#enterMode} - * and {@link CKEDITOR.config#shiftEnterMode} configuration - * settings to make the editor produce `

` tags when - * using the *Enter* key. - * - * @readonly - * @property {Number} [=1] - * @member CKEDITOR - */ -CKEDITOR.ENTER_P = 1; - -/** - * Used in conjunction with {@link CKEDITOR.config#enterMode} - * and {@link CKEDITOR.config#shiftEnterMode} configuration - * settings to make the editor produce `
` tags when - * using the *Enter* key. - * - * @readonly - * @property {Number} [=2] - * @member CKEDITOR - */ -CKEDITOR.ENTER_BR = 2; - -/** - * Used in conjunction with {@link CKEDITOR.config#enterMode} - * and {@link CKEDITOR.config#shiftEnterMode} configuration - * settings to make the editor produce `

` tags when - * using the *Enter* key. - * - * @readonly - * @property {Number} [=3] - * @member CKEDITOR - */ -CKEDITOR.ENTER_DIV = 3; - -/** - * Stores default configuration settings. Changes to this object are - * reflected in all editor instances, if not specified otherwise for a particular - * instance. - * - * @class - * @singleton - */ -CKEDITOR.config = { - /** - * The URL path for the custom configuration file to be loaded. If not - * overloaded with inline configuration, it defaults to the `config.js` - * file present in the root of the CKEditor installation directory. - * - * CKEditor will recursively load custom configuration files defined inside - * other custom configuration files. - * - * // Load a specific configuration file. - * CKEDITOR.replace( 'myfield', { customConfig: '/myconfig.js' } ); - * - * // Do not load any custom configuration file. - * CKEDITOR.replace( 'myfield', { customConfig: '' } ); - * - * @cfg {String} [="/config.js"] - */ - customConfig: 'config.js', - - /** - * Whether the replaced element (usually a ` - * ... - * CKEDITOR.replace( 'myfield' ); - * - * var textarea = document.body.appendChild( document.createElement( 'textarea' ) ); - * CKEDITOR.replace( textarea ); - * - * @param {Object/String} element The DOM element (textarea), its ID, or name. - * @param {Object} [config] The specific configuration to apply to this - * editor instance. Configuration set here will override the global CKEditor settings - * (see {@link CKEDITOR.config}). - * @returns {CKEDITOR.editor} The editor instance created. - */ - CKEDITOR.replace = function( element, config ) { - return createInstance( element, config, null, CKEDITOR.ELEMENT_MODE_REPLACE ); - }; - - /** - * Creates a new editor instance at the end of a specific DOM element. - * - *
- * ... - * CKEDITOR.appendTo( 'editorSpace' ); - * - * @param {Object/String} element The DOM element, its ID, or name. - * @param {Object} [config] The specific configuration to apply to this - * editor instance. Configuration set here will override the global CKEditor settings - * (see {@link CKEDITOR.config}). - * @param {String} [data] Since 3.3. Initial value for the instance. - * @returns {CKEDITOR.editor} The editor instance created. - */ - CKEDITOR.appendTo = function( element, config, data ) - { - return createInstance( element, config, data, CKEDITOR.ELEMENT_MODE_APPENDTO ); - }; - - /** - * Replaces all ` - data = protectElements( data, protectTextareaRegex ); - - // Before anything, we must protect the URL attributes as the - // browser may changing them when setting the innerHTML later in - // the code. - data = protectAttributes( data ); - - // Protect elements than can't be set inside a DIV. E.g. IE removes - // style tags from innerHTML. (#3710) - data = protectElements( data, protectElementsRegex ); - - // Certain elements has problem to go through DOM operation, protect - // them by prefixing 'cke' namespace. (#3591) - data = protectElementsNames( data ); - - // All none-IE browsers ignore self-closed custom elements, - // protecting them into open-close. (#3591) - data = protectSelfClosingElements( data ); - - // Compensate one leading line break after
 open as browsers
-			// eat it up. (#5789)
-			data = protectPreFormatted( data );
-
-			var fixBin = evtData.context || editor.editable().getName(),
-				isPre;
-
-			// Old IEs loose formats when load html into 
.
-			if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 && fixBin == 'pre' ) {
-				fixBin = 'div';
-				data = '
' + data + '
'; - isPre = 1; - } - - // Call the browser to help us fixing a possibly invalid HTML - // structure. - var el = editor.document.createElement( fixBin ); - // Add fake character to workaround IE comments bug. (#3801) - el.setHtml( 'a' + data ); - data = el.getHtml().substr( 1 ); - - // Restore shortly protected attribute names. - data = data.replace( new RegExp( ' data-cke-' + CKEDITOR.rnd + '-', 'ig' ), ' ' ); - - isPre && ( data = data.replace( /^
|<\/pre>$/gi, '' ) );
-
-			// Unprotect "some" of the protected elements at this point.
-			data = unprotectElementNames( data );
-
-			data = unprotectElements( data );
-
-			// Restore the comments that have been protected, in this way they
-			// can be properly filtered.
-			data = unprotectRealComments( data );
-
-			// Now use our parser to make further fixes to the structure, as
-			// well as apply the filter.
-			evtData.dataValue = CKEDITOR.htmlParser.fragment.fromHtml(
-				data, evtData.context, evtData.fixForBody === false ? false : getFixBodyTag( evtData.enterMode, editor.config.autoParagraph ) );
-		}, null, null, 5 );
-
-		// Filter incoming "data".
-		// Add element filter before htmlDataProcessor.dataFilter when purifying input data to correct html.
-		editor.on( 'toHtml', function( evt ) {
-			if ( evt.data.filter.applyTo( evt.data.dataValue, true, evt.data.dontFilter, evt.data.enterMode ) )
-				editor.fire( 'dataFiltered' );
-		}, null, null, 6 );
-
-		editor.on( 'toHtml', function( evt ) {
-			evt.data.dataValue.filterChildren( that.dataFilter, true );
-		}, null, null, 10 );
-
-		editor.on( 'toHtml', function( evt ) {
-			var evtData = evt.data,
-				data = evtData.dataValue,
-				writer = new CKEDITOR.htmlParser.basicWriter();
-
-			data.writeChildrenHtml( writer );
-			data = writer.getHtml( true );
-
-			// Protect the real comments again.
-			evtData.dataValue = protectRealComments( data );
-		}, null, null, 15 );
-
-
-		editor.on( 'toDataFormat', function( evt ) {
-			var data = evt.data.dataValue;
-
-			// #10854 - we need to strip leading blockless 
which FF adds - // automatically when editable contains only non-editable content. - // We do that for every browser (so it's a constant behavior) and - // not in BR mode, in which chance of valid leading blockless
is higher. - if ( evt.data.enterMode != CKEDITOR.ENTER_BR ) - data = data.replace( /^
/i, '' ); - - evt.data.dataValue = CKEDITOR.htmlParser.fragment.fromHtml( - data, evt.data.context, getFixBodyTag( evt.data.enterMode, editor.config.autoParagraph ) ); - }, null, null, 5 ); - - editor.on( 'toDataFormat', function( evt ) { - evt.data.dataValue.filterChildren( that.htmlFilter, true ); - }, null, null, 10 ); - - // Transform outcoming "data". - // Add element filter after htmlDataProcessor.htmlFilter when preparing output data HTML. - editor.on( 'toDataFormat', function( evt ) { - evt.data.filter.applyTo( evt.data.dataValue, false, true ); - }, null, null, 11 ); - - editor.on( 'toDataFormat', function( evt ) { - var data = evt.data.dataValue, - writer = that.writer; - - writer.reset(); - data.writeChildrenHtml( writer ); - data = writer.getHtml( true ); - - // Restore those non-HTML protected source. (#4475,#4880) - data = unprotectRealComments( data ); - data = unprotectSource( data, editor ); - - evt.data.dataValue = data; - }, null, null, 15 ); - }; - - CKEDITOR.htmlDataProcessor.prototype = { - /** - * Processes the input (potentially malformed) HTML to a purified form which - * is suitable for using in the WYSIWYG editable. - * - * This method fires the {@link CKEDITOR.editor#toHtml} event which makes it possible - * to hook into the process at various stages. - * - * **Note:** Since CKEditor 4.3 the signature of this method changed and all options - * are now grouped in one `options` object. Previously `context`, `fixForBody` and `dontFilter` - * were passed separately. - * - * @param {String} data The raw data. - * @param {Object} [options] The options object. - * @param {String} [options.context] The tag name of a context element within which - * the input is to be processed, default to be the editable element. - * If `null` is passed, then data will be parsed without context (as children of {@link CKEDITOR.htmlParser.fragment}). - * See {@link CKEDITOR.htmlParser.fragment#fromHtml} for more details. - * @param {Boolean} [options.fixForBody=true] Whether to trigger the auto paragraph for non-block contents. - * @param {CKEDITOR.filter} [options.filter] When specified, instead of using the {@link CKEDITOR.editor#filter main filter}, - * passed instance will be used to filter the content. - * @param {Boolean} [options.dontFilter] Do not filter data with {@link CKEDITOR.filter} (note: transformations - * will be still applied). - * @param {Number} [options.enterMode] When specified it will be used instead of the {@link CKEDITOR.editor#enterMode main enterMode}. - * @returns {String} - */ - toHtml: function( data, options, fixForBody, dontFilter ) { - var editor = this.editor, - context, filter, enterMode; - - // Typeof null == 'object', so check truthiness of options too. - if ( options && typeof options == 'object' ) { - context = options.context; - fixForBody = options.fixForBody; - dontFilter = options.dontFilter; - filter = options.filter; - enterMode = options.enterMode; - } - // Backward compatibility. Since CKEDITOR 4.3 every option was a separate argument. - else - context = options; - - // Fall back to the editable as context if not specified. - if ( !context && context !== null ) - context = editor.editable().getName(); - - return editor.fire( 'toHtml', { - dataValue: data, - context: context, - fixForBody: fixForBody, - dontFilter: dontFilter, - filter: filter || editor.filter, - enterMode: enterMode || editor.enterMode - } ).dataValue; - }, - - /** - * See {@link CKEDITOR.dataProcessor#toDataFormat}. - * - * This method fires the {@link CKEDITOR.editor#toDataFormat} event which makes it possible - * to hook into the process at various steps. - * - * @param {String} html - * @param {Object} [options] The options object. - * @param {String} [options.context] The tag name of a context element within which - * the input is to be processed, default to be the editable element. - * @param {CKEDITOR.filter} [options.filter] When specified, instead of using the {@link CKEDITOR.editor#filter main filter}, - * passed instance will be used to apply content transformations to the content. - * @param {Number} [options.enterMode] When specified it will be used instead of the {@link CKEDITOR.editor#enterMode main enterMode}. - * @returns {String} - */ - toDataFormat: function( html, options ) { - var context, filter, enterMode; - - // Do not shorten this to `options && options.xxx`, because - // falsy `options` will be passed instead of undefined. - if ( options ) { - context = options.context; - filter = options.filter; - enterMode = options.enterMode; - } - - // Fall back to the editable as context if not specified. - if ( !context && context !== null ) - context = this.editor.editable().getName(); - - return this.editor.fire( 'toDataFormat', { - dataValue: html, - filter: filter || this.editor.filter, - context: context, - enterMode: enterMode || this.editor.enterMode - } ).dataValue; - } - }; - - // Produce a set of filtering rules that handles bogus and filler node at the - // end of block/pseudo block, in the following consequence: - // 1. elements: - this filter removes any bogus node, then check - // if it's an empty block that requires a filler. - // 2. elements:
- After cleaned with bogus, this filter checks the real - // line-break BR to compensate a filler after it. - // - // Terms definitions: - // filler: An element that's either
or &NBSP; at the end of block that established line height. - // bogus: Whenever a filler is proceeded with inline content, it becomes a bogus which is subjected to be removed. - // - // Various forms of the filler: - // In output HTML: Filler should be consistently &NBSP;
at the end of block is always considered as bogus. - // In Wysiwyg HTML: Browser dependent - see env.needsBrFiller. Either BR for when needsBrFiller is true, or &NBSP; otherwise. - //
is NEVER considered as bogus when needsBrFiller is true. - function createBogusAndFillerRules( editor, type ) { - function createFiller( isOutput ) { - return isOutput || CKEDITOR.env.needsNbspFiller ? - new CKEDITOR.htmlParser.text( '\xa0' ) : - new CKEDITOR.htmlParser.element( 'br', { 'data-cke-bogus': 1 } ); - } - - // This text block filter, remove any bogus and create the filler on demand. - function blockFilter( isOutput, fillEmptyBlock ) { - - return function( block ) { - - // DO NOT apply the filer if it's a fragment node. - if ( block.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT ) - return; - - cleanBogus( block ); - - // [Opera] it's mandatory for the filler to present inside of empty block when in WYSIWYG. - if ( ( ( CKEDITOR.env.opera && !isOutput ) || - ( typeof fillEmptyBlock == 'function' ? fillEmptyBlock( block ) !== false : fillEmptyBlock ) ) && - isEmptyBlockNeedFiller( block ) ) - { - block.add( createFiller( isOutput ) ); - } - }; - } - - // Append a filler right after the last line-break BR, found at the end of block. - function brFilter( isOutput ) { - return function( br ) { - - // DO NOT apply the filer if parent's a fragment node. - if ( br.parent.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT ) - return; - - var attrs = br.attributes; - // Dismiss BRs that are either bogus or eol marker. - if ( 'data-cke-bogus' in attrs || - 'data-cke-eol' in attrs ) { - delete attrs [ 'data-cke-bogus' ]; - return; - } - - // Judge the tail line-break BR, and to insert bogus after it. - var next = getNext( br ), previous = getPrevious( br ); - - if ( !next && isBlockBoundary( br.parent ) ) - append( br.parent, createFiller( isOutput ) ); - else if ( isBlockBoundary( next ) && previous && !isBlockBoundary( previous ) ) - createFiller( isOutput ).insertBefore( next ); - }; - } - - // Determinate whether this node is potentially a bogus node. - function maybeBogus( node, atBlockEnd ) { - - // BR that's not from IE<11 DOM, except for a EOL marker. - if ( !( isOutput && !CKEDITOR.env.needsBrFiller ) && - node.type == CKEDITOR.NODE_ELEMENT && node.name == 'br' && - !node.attributes[ 'data-cke-eol' ] ) - return true; - - var match; - // NBSP, possibly. - if ( node.type == CKEDITOR.NODE_TEXT && - ( match = node.value.match( tailNbspRegex ) ) ) - { - // We need to separate tail NBSP out of a text node, for later removal. - if ( match.index ) { - ( new CKEDITOR.htmlParser.text( node.value.substring( 0, match.index ) ) ).insertBefore( node ); - node.value = match[ 0 ]; - } - - // From IE<11 DOM, at the end of a text block, or before block boundary. - if ( !CKEDITOR.env.needsBrFiller && isOutput && ( !atBlockEnd || node.parent.name in textBlockTags ) ) - return true; - - // From the output. - if ( !isOutput ) { - var previous = node.previous; - - // Following a line-break at the end of block. - if ( previous && previous.name == 'br' ) - return true; - - // Or a single NBSP between two blocks. - if ( !previous || isBlockBoundary( previous ) ) - return true; - } - } - - return false; - } - - // Removes all bogus inside of this block, and to convert fillers into the proper form. - function cleanBogus( block ) { - var bogus = []; - var last = getLast( block ), node, previous; - if ( last ) { - - // Check for bogus at the end of this block. - // e.g.

foo

- maybeBogus( last, 1 ) && bogus.push( last ); - - while ( last ) { - - // Check for bogus at the end of any pseudo block contained. - if ( isBlockBoundary( last ) && - ( node = getPrevious( last ) ) && - maybeBogus( node ) ) - { - // Bogus must have inline proceeding, instead single BR between two blocks, - // is considered as filler, e.g.


- if ( ( previous = getPrevious( node ) ) && !isBlockBoundary( previous ) ) - bogus.push( node ); - // Convert the filler into appropriate form. - else { - createFiller( isOutput ).insertAfter( node ); - node.remove(); - } - } - - last = last.previous; - } - } - - // Now remove all bogus collected from above. - for ( var i = 0 ; i < bogus.length ; i++ ) - bogus[ i ].remove(); - } - - // Judge whether it's an empty block that requires a filler node. - function isEmptyBlockNeedFiller( block ) { - - // DO NOT fill empty editable in IE<11. - if ( !isOutput && !CKEDITOR.env.needsBrFiller && block.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT ) - return false; - - // 1. For IE version >=8, empty blocks are displayed correctly themself in wysiwiyg; - // 2. For the rest, at least table cell and list item need no filler space. (#6248) - if ( !isOutput && !CKEDITOR.env.needsBrFiller && - ( document.documentMode > 7 || - block.name in CKEDITOR.dtd.tr || - block.name in CKEDITOR.dtd.$listItem ) ) { - return false; - } - - var last = getLast( block ); - return !last || block.name == 'form' && last.name == 'input' ; - } - - var rules = { elements: {} }; - var isOutput = type == 'html'; - - // Build the list of text blocks. - var textBlockTags = CKEDITOR.tools.extend( {}, blockLikeTags ); - for ( var i in textBlockTags ) { - if ( !( '#' in dtd[ i ] ) ) - delete textBlockTags[ i ]; - } - - for ( i in textBlockTags ) - rules.elements[ i ] = blockFilter( isOutput, editor.config.fillEmptyBlocks !== false ); - - // Editable element is to be checked separately. - rules.root = blockFilter( isOutput ); - rules.elements.br = brFilter( isOutput ); - return rules; - } - - function getFixBodyTag( enterMode, autoParagraph ) { - return ( enterMode != CKEDITOR.ENTER_BR && autoParagraph !== false ) ? enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p' : false; - } - - // Regex to scan for   at the end of blocks, which are actually placeholders. - // Safari transforms the   to \xa0. (#4172) - var tailNbspRegex = /(?: |\xa0)$/; - - var protectedSourceMarker = '{cke_protected}'; - - function getLast( node ) { - var last = node.children[ node.children.length - 1 ]; - while ( last && isEmpty( last ) ) - last = last.previous; - return last; - } - - function getNext( node ) { - var next = node.next; - while ( next && isEmpty( next ) ) - next = next.next; - return next; - } - - function getPrevious( node ) { - var previous = node.previous; - while ( previous && isEmpty( previous ) ) - previous = previous.previous; - return previous; - } - - // Judge whether the node is an ghost node to be ignored, when traversing. - function isEmpty( node ) { - return node.type == CKEDITOR.NODE_TEXT && - !CKEDITOR.tools.trim( node.value ) || - node.type == CKEDITOR.NODE_ELEMENT && - node.attributes[ 'data-cke-bookmark' ]; - } - - // Judge whether the node is a block-like element. - function isBlockBoundary( node ) { - return node && - ( node.type == CKEDITOR.NODE_ELEMENT && node.name in blockLikeTags || - node.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT ); - } - - function append( parent, node ) { - var last = parent.children[ parent.children.length -1 ]; - parent.children.push( node ); - node.parent = parent; - if ( last ) { - last.next = node; - node.previous = last; - } - } - - function getNodeIndex( node ) { - return node.parent ? node.getIndex() : -1; - } - - var dtd = CKEDITOR.dtd, - // Define orders of table elements. - tableOrder = [ 'caption', 'colgroup', 'col', 'thead', 'tfoot', 'tbody' ], - // List of all block elements. - blockLikeTags = CKEDITOR.tools.extend( {}, dtd.$blockLimit, dtd.$block ); - - // - // DATA filter rules ------------------------------------------------------ - // - - var defaultDataFilterRulesEditableOnly = { - elements: { - input: protectReadOnly, - textarea: protectReadOnly - } - }; - - // These rules will also be applied to non-editable content. - var defaultDataFilterRulesForAll = { - attributeNames: [ - // Event attributes (onXYZ) must not be directly set. They can become - // active in the editing area (IE|WebKit). - [ ( /^on/ ), 'data-cke-pa-on' ], - - // Don't let some old expando enter editor. Concerns only IE8, - // but for consistency remove on all browsers. - [ ( /^data-cke-expando$/ ), '' ] - ] - }; - - // Disable form elements editing mode provided by some browsers. (#5746) - function protectReadOnly( element ) { - var attrs = element.attributes; - - // We should flag that the element was locked by our code so - // it'll be editable by the editor functions (#6046). - if ( attrs.contenteditable != 'false' ) - attrs[ 'data-cke-editable' ] = attrs.contenteditable ? 'true' : 1; - - attrs.contenteditable = 'false'; - } - - // - // HTML filter rules ------------------------------------------------------ - // - - var defaultHtmlFilterRulesEditableOnly = { - elements: { - embed: function( element ) { - var parent = element.parent; - - // If the is child of a , copy the width - // and height attributes from it. - if ( parent && parent.name == 'object' ) { - var parentWidth = parent.attributes.width, - parentHeight = parent.attributes.height; - if ( parentWidth ) - element.attributes.width = parentWidth; - if ( parentHeight ) - element.attributes.height = parentHeight; - } - }, - - // Remove empty link but not empty anchor. (#3829) - a: function( element ) { - if ( !( element.children.length || element.attributes.name || element.attributes[ 'data-cke-saved-name' ] ) ) - return false; - } - } - }; - - // These rules will also be applied to non-editable content. - var defaultHtmlFilterRulesForAll = { - elementNames: [ - // Remove the "cke:" namespace prefix. - [ ( /^cke:/ ), '' ], - - // Ignore tags. - [ ( /^\?xml:namespace$/ ), '' ] - ], - - attributeNames: [ - // Attributes saved for changes and protected attributes. - [ ( /^data-cke-(saved|pa)-/ ), '' ], - - // All "data-cke-" attributes are to be ignored. - [ ( /^data-cke-.*/ ), '' ], - - [ 'hidefocus', '' ] - ], - - elements: { - $: function( element ) { - var attribs = element.attributes; - - if ( attribs ) { - // Elements marked as temporary are to be ignored. - if ( attribs[ 'data-cke-temp' ] ) - return false; - - // Remove duplicated attributes - #3789. - var attributeNames = [ 'name', 'href', 'src' ], - savedAttributeName; - for ( var i = 0; i < attributeNames.length; i++ ) { - savedAttributeName = 'data-cke-saved-' + attributeNames[ i ]; - savedAttributeName in attribs && ( delete attribs[ attributeNames[ i ] ] ); - } - } - - return element; - }, - - // The contents of table should be in correct order (#4809). - table: function( element ) { - // Clone the array as it would become empty during the sort call. - var children = element.children.slice( 0 ); - children.sort( function( node1, node2 ) { - var index1, index2; - - // Compare in the predefined order. - if ( node1.type == CKEDITOR.NODE_ELEMENT && - node2.type == node1.type ) { - index1 = CKEDITOR.tools.indexOf( tableOrder, node1.name ); - index2 = CKEDITOR.tools.indexOf( tableOrder, node2.name ); - } - - // Make sure the sort is stable, if no order can be established above. - if ( !( index1 > -1 && index2 > -1 && index1 != index2 ) ) { - index1 = getNodeIndex( node1 ); - index2 = getNodeIndex( node2 ); - } - - return index1 > index2 ? 1 : -1; - } ); - }, - - // Restore param elements into self-closing. - param: function( param ) { - param.children = []; - param.isEmpty = true; - return param; - }, - - // Remove dummy span in webkit. - span: function( element ) { - if ( element.attributes[ 'class' ] == 'Apple-style-span' ) - delete element.name; - }, - - html: function( element ) { - delete element.attributes.contenteditable; - delete element.attributes[ 'class' ]; - }, - - body: function( element ) { - delete element.attributes.spellcheck; - delete element.attributes.contenteditable; - }, - - style: function( element ) { - var child = element.children[ 0 ]; - if ( child && child.value ) - child.value = CKEDITOR.tools.trim( child.value ); - - if ( !element.attributes.type ) - element.attributes.type = 'text/css'; - }, - - title: function( element ) { - var titleText = element.children[ 0 ]; - - // Append text-node to title tag if not present (i.e. non-IEs) (#9882). - !titleText && append( element, titleText = new CKEDITOR.htmlParser.text() ); - - // Transfer data-saved title to title tag. - titleText.value = element.attributes[ 'data-cke-title' ] || ''; - }, - - input: unprotectReadyOnly, - textarea: unprotectReadyOnly - }, - - attributes: { - 'class': function( value, element ) { - // Remove all class names starting with "cke_". - return CKEDITOR.tools.ltrim( value.replace( /(?:^|\s+)cke_[^\s]*/g, '' ) ) || false; - } - } - }; - - if ( CKEDITOR.env.ie ) { - // IE outputs style attribute in capital letters. We should convert - // them back to lower case, while not hurting the values (#5930) - defaultHtmlFilterRulesForAll.attributes.style = function( value, element ) { - return value.replace( /(^|;)([^\:]+)/g, function( match ) { - return match.toLowerCase(); - } ); - }; - } - - // Disable form elements editing mode provided by some browsers. (#5746) - function unprotectReadyOnly( element ) { - var attrs = element.attributes; - switch ( attrs[ 'data-cke-editable' ] ) { - case 'true': - attrs.contenteditable = 'true'; - break; - case '1': - delete attrs.contenteditable; - break; - } - } - - // - // Preprocessor filters --------------------------------------------------- - // - - var protectElementRegex = /<(a|area|img|input|source)\b([^>]*)>/gi, - // Be greedy while looking for protected attributes. This will let us avoid an unfortunate - // situation when "nested attributes", which may appear valid, are also protected. - // I.e. if we consider the following HTML: - // - // - // - // then the "non-greedy match" returns: - // - // 'href' => '"X"' // It's wrong! Href is not an attribute of . - // - // while greedy match returns: - // - // 'data-x' => '<a href="X"' - // - // which, can be easily filtered out (#11508). - protectAttributeRegex = /([\w-]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi, - protectAttributeNameRegex = /^(href|src|name)$/i; - - // Note: we use lazy star '*?' to prevent eating everything up to the last occurrence of or . - var protectElementsRegex = /(?:])[^>]*>[\s\S]*?<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi, - protectTextareaRegex = /(])[^>]*>)([\s\S]*?)(?:<\/textarea>)/gi, - encodedElementsRegex = /([^<]*)<\/cke:encoded>/gi; - - var protectElementNamesRegex = /(<\/?)((?:object|embed|param|html|body|head|title)[^>]*>)/gi, - unprotectElementNamesRegex = /(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi; - - var protectSelfClosingRegex = /]*?)\/?>(?!\s*<\/cke:\1)/gi; - - function protectAttributes( html ) { - return html.replace( protectElementRegex, function( element, tag, attributes ) { - return '<' + tag + attributes.replace( protectAttributeRegex, function( fullAttr, attrName ) { - // Avoid corrupting the inline event attributes (#7243). - // We should not rewrite the existed protected attributes, e.g. clipboard content from editor. (#5218) - if ( protectAttributeNameRegex.test( attrName ) && attributes.indexOf( 'data-cke-saved-' + attrName ) == -1 ) - return ' data-cke-saved-' + fullAttr + ' data-cke-' + CKEDITOR.rnd + '-' + fullAttr; - - return fullAttr; - } ) + '>'; - } ); - } - - function protectElements( html, regex ) { - return html.replace( regex, function( match, tag, content ) { - // Encode < and > in textarea because this won't be done by a browser, since - // textarea will be protected during passing data through fix bin. - if ( match.indexOf( '/g, '>' ) + ''; - - return '' + encodeURIComponent( match ) + ''; - } ); - } - - function unprotectElements( html ) { - return html.replace( encodedElementsRegex, function( match, encoded ) { - return decodeURIComponent( encoded ); - } ); - } - - function protectElementsNames( html ) { - return html.replace( protectElementNamesRegex, '$1cke:$2' ); - } - - function unprotectElementNames( html ) { - return html.replace( unprotectElementNamesRegex, '$1$2' ); - } - - function protectSelfClosingElements( html ) { - return html.replace( protectSelfClosingRegex, '' ); - } - - function protectPreFormatted( html ) { - return CKEDITOR.env.opera ? html : html.replace( /(]*>)(\r\n|\n)/g, '$1$2$2' ); - } - - function protectRealComments( html ) { - return html.replace( //g, function( match ) { - return ''; - } ); - } - - function unprotectRealComments( html ) { - return html.replace( //g, function( match, data ) { - return decodeURIComponent( data ); - } ); - } - - function unprotectSource( html, editor ) { - var store = editor._.dataStore; - - return html.replace( //g, function( match, data ) { - return decodeURIComponent( data ); - } ).replace( /\{cke_protected_(\d+)\}/g, function( match, id ) { - return store && store[ id ] || ''; - } ); - } - - function protectSource( data, editor ) { - var protectedHtml = [], - protectRegexes = editor.config.protectedSource, - store = editor._.dataStore || ( editor._.dataStore = { id: 1 } ), - tempRegex = /<\!--\{cke_temp(comment)?\}(\d*?)-->/g; - - var regexes = [ - // Script tags will also be forced to be protected, otherwise - // IE will execute them. - ( //gi ), - - //